# McpServer
McpServer is a DSL for defining Model Context Protocol (MCP) tools and routers in Elixir. It allows you to easily expose tool endpoints with input/output schemas and validation.
## Installation
1. **Add dependencies to your `mix.exs`:**
```elixir
def deps do
[
{:mcp_server, "~> 0.1.0"},
{:bandit, "~> 1.0"} # HTTP server
]
end
```
2. **Define your MCP Router:**
Create a module that uses `McpServer.Router` and defines your tools. Example:
```elixir
defmodule MyAppMcp.MyController do
def echo(args), do: Map.get(args, "message", "default")
def greet(args), do: "Hello, #{Map.get(args, "name", "World")}",
def calculate(args), do: Map.get(args, "a", 0) + Map.get(args, "b", 0)
end
defmodule MyApp.Router do
use McpServer.Router
tool "greet", "Greets a person", MyApp.MyController, :greet do
input_field("name", "The name to greet", :string, required: false)
output_field("greeting", "The greeting message", :string)
end
tool "calculate", "Adds two numbers", MyApp.MyController, :calculate do
input_field("a", "First number", :integer, required: true)
input_field("b", "Second number", :integer, required: true)
output_field("result", "The sum of the numbers", :integer)
end
tool "echo", "Echoes back the input", MyApp.MyController, :echo,
title: "Echo",
hints: [:read_only, :non_destructive, :idempotent, :closed_world] do
input_field("message", "The message to echo", :string, required: true)
output_field("response", "The echoed message", :string)
end
end
```
3. **Start the Bandit server with your router:**
Add to your application supervision tree:
```elixir
children = [
{Bandit, plug: MyApp.Router, port: 4000}
]
opts = [strategy: :one_for_one, name: MyApp.Supervisor]
Supervisor.start_link(children, opts)
```
Your MCP server will now be running and serving your defined tools.
## Usage & Testing
You can also call your tools via the router module:
```elixir
iex> MyApp.Router.tools_call("echo", %{"message" => "Hello World"})
# => "Hello World"
```
List all tools and their schemas:
```elixir
iex> MyApp.Router.tools_list()
# => [%{"name" => "echo", ...}, ...]
```