A complete Elixir implementation of the Model Context Protocol (MCP)
Getting Started | User Guide | API Docs | Examples | Changelog
β Production Ready: ExMCP v0.6.0 is now production-ready with 100% MCP compliance and comprehensive testing. The API is stable and ready for production use.
ExMCP is a comprehensive Elixir implementation of the Model Context Protocol, enabling AI models to securely interact with local and remote resources through a standardized protocol. It provides both client and server implementations with multiple transport options, including native Phoenix integration via Plug compatibility.
- π Multiple MCP Versions - Supports protocol versions 2024-11-05, 2025-03-26, and 2025-06-18
- β 100% MCP Compliant - Full implementation of official MCP specification
- π οΈ Complete Feature Set - Tools, Resources, Prompts, Roots, Subscriptions, Batch requests
- π OAuth 2.1 Support - Complete Resource Server implementation
- β‘ Ultra-fast Native BEAM - ~15ΞΌs local calls with zero serialization overhead
- π Auto-Reconnection - Built-in reconnection with exponential backoff
- ποΈ OTP Integration - Built on solid OTP principles with supervision trees
- π Progress Notifications - Track long-running operations
- π Phoenix Plug - Native Phoenix integration with
ExMCP.HttpPlug
- π Multiple Transports - HTTP/SSE, stdio, and native BEAM support
- π― Session Management - Automatic session tracking for SSE connections
- π Bi-directional Communication - Servers can make requests to clients
- π§ͺ Well Tested - Comprehensive test suite with 500+ tests
- π Extensive Documentation - Complete guides and real-world examples
- π§ Easy Configuration - Sensible defaults with flexible customization
- π‘οΈ Security First - Built-in authentication, TLS/SSL, CORS support
Add ex_mcp
to your list of dependencies in mix.exs
:
def deps do
[
{:ex_mcp, "~> 0.6.0"}
]
end
Then run:
mix deps.get
Add MCP server capabilities to your Phoenix app:
# In your Phoenix router (lib/my_app_web/router.ex)
defmodule MyAppWeb.Router do
use MyAppWeb, :router
pipeline :mcp do
plug :accepts, ["json"]
# Add your authentication/authorization here
end
scope "/api/mcp" do
pipe_through :mcp
# Mount MCP server at /api/mcp
forward "/", ExMCP.HttpPlug,
handler: MyApp.MCPHandler,
server_info: %{name: "my-phoenix-app", version: "1.0.0"},
sse_enabled: true,
cors_enabled: true
end
end
# Create your MCP handler (lib/my_app/mcp_handler.ex)
defmodule MyApp.MCPHandler do
use ExMCP.Server.Handler
@impl true
def init(_args), do: {:ok, %{}}
@impl true
def handle_initialize(_params, state) do
{:ok, %{
name: "my-phoenix-app",
version: "1.0.0",
capabilities: %{tools: %{}, resources: %{}}
}, state}
end
@impl true
def handle_list_tools(state) do
tools = [
%{
name: "get_user_count",
description: "Get total number of users",
input_schema: %{type: "object", properties: %{}}
}
]
{:ok, tools, state}
end
@impl true
def handle_call_tool("get_user_count", _args, state) do
count = MyApp.Accounts.count_users()
{:ok, [%{type: "text", text: "Total users: #{count}"}], state}
end
end
Connect from any MCP client:
mcp connect http://localhost:4000/api/mcp
# Connect to a stdio-based server
{:ok, client} = ExMCP.Client.start_link(
transport: :stdio,
command: ["node", "my-mcp-server.js"]
)
# List available tools
{:ok, tools} = ExMCP.Client.list_tools(client)
# Call a tool
{:ok, result} = ExMCP.Client.call_tool(client, "search", %{
query: "Elixir programming",
limit: 10
})
For trusted Elixir clusters, use the native BEAM transport:
# Create a service using the ExMCP.Service macro
defmodule MyToolService do
use ExMCP.Service, name: :my_tools
@impl true
def handle_mcp_request("list_tools", _params, state) do
tools = [
%{
"name" => "ping",
"description" => "Test tool",
"inputSchema" => %{"type" => "object", "properties" => %{}}
}
]
{:ok, %{"tools" => tools}, state}
end
@impl true
def handle_mcp_request("tools/call", %{"name" => "ping"}, state) do
{:ok, %{"content" => [%{"type" => "text", "text" => "Pong!"}]}, state}
end
end
# Start your service (automatically registers with ExMCP.Native)
{:ok, _} = MyToolService.start_link()
# Direct service calls (~15ΞΌs latency)
{:ok, tools} = ExMCP.Native.call(:my_tools, "list_tools", %{})
ExMCP provides comprehensive documentation organized for different needs:
- Quick Start Guide - Get running in 5 minutes
- Quick Reference - One-page operation reference
- Migration Guide - Version upgrade instructions
- User Guide - Complete feature walkthrough with examples
- Phoenix Integration Guide - Detailed Phoenix/Plug integration
- Configuration Guide - All configuration options and examples
- Transport Guide - Transport selection and optimization
- Security Guide - Authentication, TLS, and security best practices
- Development Guide - Setup, testing, and contributing
- API Documentation - Complete API reference
- Architecture Guide - Internal architecture and design decisions
- Examples - Real-world implementation patterns
- MCP Specifications - Complete protocol documentation for all versions
- Protocol Support Matrix - Feature comparison across versions
Transport | Latency | Best For | Use Case |
---|---|---|---|
Native BEAM | ~15ΞΌs | Internal services | Elixir cluster communication |
stdio | ~1-5ms | External tools | Subprocess communication |
HTTP/SSE | ~5-20ms | Network clients | Web applications, remote APIs |
- Enhanced Security: Complete OAuth 2.1 Resource Server implementation
- MCP 2025-06-18 Support: Latest protocol version with structured tool output
- Improved Testing: Comprehensive compliance test suite
- Better Performance: Optimized native BEAM transport
- Documentation: Enhanced guides and examples
See the CHANGELOG for complete details and breaking changes.
We welcome contributions! Please see:
- Development Guide for setup and testing instructions
- CHANGELOG.md for version history
- GitHub Issues for bug reports and feature requests
Before contributing:
- Fork the repository
- Create a feature branch
- Run
make quality
to ensure code quality - Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.
- The Model Context Protocol specification creators
- The Elixir community for excellent tooling and libraries
- Contributors and early adopters providing feedback