# Getting Started

`gen_mcp` is a server library for the Model Context Protocol (MCP). You define
tools, resources and prompts as plain modules, mount one HTTP plug in your
router, and clients can call them.

The transport is stateless: each request is validated and answered on its own,
by a fresh server process. This guide walks through installing the library,
defining a tool, mounting the server, and sending it a request.

## Installation

Add the library to your dependencies and you are good to go.

<!-- rdmx :app_dep vsn:$app_vsn -->
```elixir
defp deps do
  [
    {:gen_mcp, "~> 2.0"},
  ]
end
```
<!-- rdmx /:app_dep -->

## Quick start

This guide uses the default server implementation, `GenMCP.Suite`, together with
the Streamable HTTP transport provided by the `GenMCP.Transport.StreamableHTTP`
plug. The Suite is the component model: you list your tools, resources and
prompts, and it advertises and routes them.

### Define a tool

A tool is an operation a client invokes. To have something to call, define one.
This tool adds two numbers. `use GenMCP.Suite.Tool` generates the metadata and
argument validation from the options you pass, leaving you to implement
`c:GenMCP.Suite.Tool.call/3`.

<!-- rdmx :section name:tool_sample format:true -->
```elixir
defmodule MyApp.Tools.Addition do
  use GenMCP.Suite.Tool,
    name: "add",
    description: "Adds two numbers and returns the sum.",
    input_schema: %{
      type: :object,
      properties: %{
        a: %{type: :number},
        b: %{type: :number}
      },
      required: [:a, :b]
    }

  alias GenMCP.MCP.V2607, as: MCP

  @impl true
  def call(request, _channel, _arg) do
    %{"a" => a, "b" => b} = request.params.arguments
    {:result, MCP.call_tool_result(text: "#{a + b}")}
  end
end
```
<!-- rdmx /:section -->

The `:input_schema` is a plain JSON Schema map, so the validated arguments reach
`c:GenMCP.Suite.Tool.call/3` as a map with string keys, which the function body
destructures. Build the answer with the `GenMCP.MCP.V2607` helpers rather than
raw structs: `GenMCP.MCP.V2607.call_tool_result/1` wraps the text into a proper
result. The function returns `{:result, result}`.

See `GenMCP.Suite.Tool` for richer tools, including casting arguments into a
struct with `JSV` and streaming long-running work.

### Mount the server

Add the `GenMCP.Transport.StreamableHTTP` plug to your router. You name the
server and list its tools right here, in the plug options. The default server is
the Suite, so no `:server` option is needed. In a Phoenix router, mount it with
`forward`:

<!-- rdmx :section name:router_sample format:true -->
```elixir
defmodule MyAppWeb.Router do
  use MyAppWeb, :router

  scope "/mcp" do
    forward "/", GenMCP.Transport.StreamableHTTP,
      server_name: "My Addition Server",
      server_version: "1.0.0",
      tools: [MyApp.Tools.Addition]
  end
end
```
<!-- rdmx /:section -->

Your MCP server is now live at `/mcp`. `:server_name` and `:server_version`
identify the server to clients and are required. For the full set of transport
options, including origin checks and passing per-request data to handlers, see
`GenMCP.Transport.StreamableHTTP`.

### Send a request

Any MCP client that speaks the `2026-07-28` protocol can now connect to the
endpoint and list and call your tool.

To check the installation by hand, POST a JSON-RPC message. Clients usually
start with `server/discover`, the capability snapshot for this protocol, but
`tools/list` is the simplest smoke test. This call asks the server what it
serves:

```bash
curl http://localhost:4000/mcp \
  -H "Content-Type: application/json" \
  -H "MCP-Protocol-Version: 2026-07-28" \
  -H "Mcp-Method: tools/list" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/list",
    "params": {
      "_meta": {
        "io.modelcontextprotocol/protocolVersion": "2026-07-28",
        "io.modelcontextprotocol/clientInfo": {"name": "curl", "version": "1.0.0"},
        "io.modelcontextprotocol/clientCapabilities": {}
      }
    }
  }'
```

The response lists the `add` tool. To run it, switch to a `tools/call` message
and pass the arguments:

```bash
curl http://localhost:4000/mcp \
  -H "Content-Type: application/json" \
  -H "MCP-Protocol-Version: 2026-07-28" \
  -H "Mcp-Method: tools/call" \
  -H "Mcp-Name: add" \
  -d '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/call",
    "params": {
      "name": "add",
      "arguments": {"a": 2, "b": 3},
      "_meta": {
        "io.modelcontextprotocol/protocolVersion": "2026-07-28",
        "io.modelcontextprotocol/clientInfo": {"name": "curl", "version": "1.0.0"},
        "io.modelcontextprotocol/clientCapabilities": {}
      }
    }
  }'
```

The result holds the text content `"5"`. In practice an MCP client builds these
messages and headers for you; the raw form above is useful as a smoke test.

## Next steps

- Explore `GenMCP.Suite.Tool` to build richer tools, including streaming ones.
- Check out `GenMCP.Suite.ResourceRepo` to expose data as resources.
- Use `GenMCP.Suite.PromptRepo` to provide reusable prompts.
- Learn about `GenMCP.Suite.Extension` to compose functionality from several
  modules.
