# McpKit
`McpKit` provides a small, reusable MCP runtime for Phoenix applications.
It is designed for applications that want:
- a tools-first MCP server over Streamable HTTP
- persistent session storage owned by the host app
- a Phoenix router DSL that hides MCP transport boilerplate
Current scope:
- Streamable HTTP endpoint with tools support
- JSON-RPC protocol helpers
- tool behavior and input schema DSL
- Phoenix router DSL with `mcp_scope`
Not implemented yet:
- prompts
- resources
- SSE `GET /mcp`
## Installation
Hex:
```elixir
def deps do
[
{:mcp_kit, "~> 0.1.0"}
]
end
```
## Local Usage
```elixir
def deps do
[
{:mcp_kit, path: "../mcp_kit"}
]
end
```
## Host Contracts
The host application provides two things:
- a definition module implementing `MCPKit.Definition`
- a persistent session store implementing `MCPKit.SessionStore`
Example:
```elixir
defmodule MyApp.MCP.Definition do
@behaviour MCPKit.Definition
def protocol_version, do: "2025-06-18"
def server_info do
%{"name" => "my-app", "version" => "0.1.0"}
end
def session_store, do: MyApp.MCP.SessionStore
end
```
## Router Usage
```elixir
mcp_scope "/mcp", MyApp.MCP do
tool "project_create", Tools.ProjectCreate
tool "project_status", Tools.ProjectStatus
end
```
`mcp_scope` infers the host definition module as `MyApp.MCP.Definition` unless
you override it with `definition:`.
`prompt/2` and `resource/2` are intentionally reserved in the DSL and currently
raise compile-time errors until those runtime surfaces are implemented.
## Supported MCP Surface
Current supported methods:
- `initialize`
- `notifications/initialized`
- `ping`
- `tools/list`
- `tools/call`
- `notifications/cancelled`
- `DELETE` session termination
Current transport limitations:
- `GET` returns `405`
- SSE transport is not implemented yet
## Tool Modules
Tool modules use `MCPKit.Tool` and return `MCPKit.Response` values:
```elixir
defmodule MyApp.MCP.Tools.Ping do
use MCPKit.Tool
alias MCPKit.Response
schema do
field :message, :string, required: true
end
def execute(arguments, context) do
{:reply, Response.tool() |> Response.structured(arguments), context}
end
end
```
## Publish Checklist
- update version in `mix.exs`
- confirm package links and source URL
- run `mix test`
- run `mix docs`
- run `mix hex.build`