tyr0
Vancouver - easily add MCP tools to your phoenix/bandit server
Vancouver makes it easy to add Model Context Protocol (MCP) functionality to your Phoenix/Bandit server. Vancouver handles initialization, request validation, and offers helper functions to simplify the creation of MCP tools and prompts.
The goal is to let you create MCP servers with working tools/prompts in minutes, without needing to know much about the MCP protocol.
How it works
You create tools like this:
defmodule MyApp.Tools.CalculateSum do
use Vancouver.Tool
def name, do: "calculate_sum"
def description, do: "Add two numbers together"
def input_schema do
%{
"type" => "object",
"properties" => %{
"a" => %{"type" => "number"},
"b" => %{"type" => "number"}
},
"required" => ["a", "b"]
}
end
def run(conn, %{"a" => a, "b" => b}) do
send_text(conn, "#{a + b}")
end
end
create prompts like this:
defmodule MyApp.Prompts.CodeReview do
use Vancouver.Prompt
def name, do: "code_review"
def description, do: "Asks the LLM to analyze code quality and suggest improvements"
def arguments do
[
%{
"name" => "code",
"description" => "The code to review",
"required" => true
}
]
end
def run(conn, %{"code" => code}) do
send_text(conn, "Please review this code: #{code}")
end
end
and configure via your (phoenix) router like this:
forward "/mcp", Vancouver.Router,
tools: [MyApp.Tools.CalculateSum],
prompts: [MyApp.Prompts.CodeReview]
To use your tools locally with e.g. Claude Desktop, you can update your claude_desktop_config.json file (see below), run your server, and refresh Claude Desktop.
{
"mcpServers": {
"MyApp": {
"command": "npx",
"args": [
"mcp-remote",
"http://localhost:4000/mcp"
]
}
}
}
More info
Most Liked
zachdaniel
We’ve been looking for a generic MCP solution to sit Ash AI on top of that can act as a shared base instead of rolling our own which is what we’ve done so far. I’ll be evaluating this for that purpose.
mtrudel
Very nice! I’ve also started GitHub - mtrudel/excom: EXCOM is an MCP server for Elixir and it looks like our config ergonomics are more or less identical. TBH, EXCOM came out of a company hack week and I don’t really have the bandwidth to keep carrying it along, happy to see some other projects emerging to fill that need!
venkatd
I’m a huge fan of this API design–simple but extensible. My vote goes for something like this!
One thing that might be helpful is to allow some way to manage session state, more akin to a phoenix channel.
For example, I am prototyping an MCP server for Livebook, and upon connecting the AI agent will register as a collaborator in the notebook. On disconnect, it will leave. This means some MCP servers may need to be stateful.
I don’t know if this is within the scope but wanted to share that this comes up pretty often.
tyr0
Aha. I was planning to make Tools (and Prompts) into plugs, so that they’d have an (overridable) init, and support pipelines etc. I think that should work for your use case too.
Will have a think about extension support - that’s not something I’d considered, but sounds interesting. ![]()
dbern
Love it! Very nice and simple API for defining tools. I know this is limited to tools right now, but do you plan to support prompts or resources?
I’m working on a framework that provides a controller-like DSL that can respond synchronously and asynchronously: GitHub - dbernheisel/phantom_mcp: MCP server implemented in Elixir
I would love to collaborate. I’m in the process of using Phantom in anger before I publicize it.







