ExMCP (ex_mcp v0.9.2)
View SourceExMCP - Complete Elixir implementation of the Model Context Protocol.
ExMCP enables 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.
Public API
ExMCP provides a clean, focused public API. Only use these modules in your applications:
Core Modules
ExMCP- This module (convenience functions and metadata)ExMCP.Client- MCP client implementationExMCP.Server- MCP server implementationExMCP.Native- High-performance BEAM service dispatcherExMCP.Service- Macro for automatic service registrationExMCP.Transport- Transport behaviour definition
Optional Features
ExMCP.Authorization- OAuth 2.1 authorization flows (MCP optional feature)
Supporting Modules
ExMCP.Content- Content type helpersExMCP.Types- Type definitions (stable across versions)
Internal Modules
All other modules under the ExMCP namespace are internal implementation details
and may change without notice. Do not depend on them directly in your applications.
Quick Start
Start a Client
# Connect to stdio server
{:ok, client} = ExMCP.start_client(
transport: :stdio,
command: ["python", "mcp-server.py"]
)
# Connect with HTTP
{:ok, client} = ExMCP.start_client(
transport: :http,
url: "https://api.example.com"
)Start a Server
{:ok, server} = ExMCP.start_server(
handler: MyApp.MCPHandler,
transport: :stdio
)Native BEAM Communication
# High-performance service-to-service calls
{:ok, result} = ExMCP.Native.call(:my_service, "method", %{})Protocol Versions
ExMCP supports multiple MCP protocol versions:
- 2024-11-05 - Base MCP features
- 2025-03-26 - Previous stable (subscriptions, roots, logging, batch support)
- 2025-06-18 - Current stable (structured output, OAuth 2.1, elicitation, no batch)
See the README.md for a complete feature comparison chart.
Features
- Tools - Register and execute functions with parameters
- Resources - List and read data from various sources
- Prompts - Manage reusable prompt templates
- Sampling - Direct LLM integration for response generation
- Roots - URI-based resource boundaries
- Subscriptions - Monitor resources for changes
- Progress - Track long-running operations
- Notifications - Real-time updates for changes
- Native BEAM - High-performance Elixir-to-Elixir communication
Transport Options
- stdio - Process communication (standard MCP)
- HTTP/SSE - Web-friendly transport (standard MCP)
- Native BEAM - Direct Erlang process communication (ExMCP extension)
Examples
Basic Client Usage
{:ok, client} = ExMCP.start_client(transport: :stdio, command: ["mcp-server"])
# List and call tools
{:ok, %{tools: tools}} = ExMCP.Client.list_tools(client)
{:ok, result} = ExMCP.Client.call_tool(client, "search", %{query: "elixir"})
# Read resources
{:ok, content} = ExMCP.Client.read_resource(client, "file:///data.json")Basic Server Usage
defmodule MyHandler do
use ExMCP.Server.Handler
@impl true
def handle_list_tools(state) do
tools = [%{name: "echo", description: "Echo input"}]
{:ok, tools, state}
end
@impl true
def handle_call_tool("echo", params, state) do
{:ok, [%{type: "text", text: params["message"]}], state}
end
end
{:ok, server} = ExMCP.start_server(handler: MyHandler, transport: :stdio)Native BEAM Service
defmodule MyService do
use ExMCP.Service, name: :my_service
@impl true
def handle_mcp_request("ping", _params, state) do
{:ok, %{"response" => "pong"}, state}
end
end
# Automatic registration and discovery
{:ok, _} = MyService.start_link()
{:ok, result} = ExMCP.Native.call(:my_service, "ping", %{})
Summary
Functions
Convenience macro that aliases use ExMCP.Server.
Calls a tool on the connected server.
Connects to an MCP server using the unified client implementation.
Disconnects from an MCP server.
Gets library configuration and capabilities.
Tests connectivity to an MCP server without establishing a persistent connection.
Returns the version of the MCP protocol this library implements by default.
Reads a resource from the connected server.
Lists available resources from the connected server.
Starts an ACP client connected to an agent subprocess.
Convenience function to start an MCP client.
Convenience function to start an MCP server.
Gets connection status and server information.
Returns information about supported protocol versions.
Lists available tools from the connected server.
Returns the version of the ExMCP library.
Types
Functions
Convenience macro that aliases use ExMCP.Server.
This provides backward compatibility and a simpler import path for new users.
Examples
defmodule MyServer do
use ExMCP.Server # Same as `use ExMCP.Server`
deftool "hello" do
description "Says hello"
end
end
Calls a tool on the connected server.
Options
:timeout- Request timeout in milliseconds (default: 30_000):normalize- Whether to normalize the response (default: true)
Examples
# Simple call
result = ExMCP.call(client, "calculator", %{op: "add", a: 1, b: 2})
# With options
result = ExMCP.call(client, "slow_tool", %{data: "..."}, timeout: 60_000)
@spec connect( connection_spec(), keyword() ) :: {:ok, client()} | {:error, any()}
Connects to an MCP server using the unified client implementation.
This function provides a simplified interface to the MCP client with automatic connection configuration and transport selection.
Options
:timeout- Connection timeout in milliseconds (default: 10_000):retry_attempts- Number of retry attempts (default: 3)- Transport-specific options (see ExMCP.Client docs)
Examples
# HTTP connection
{:ok, client} = ExMCP.connect("http://localhost:8080")
# Stdio connection
{:ok, client} = ExMCP.connect({:stdio, command: "my-server"})
# Multiple transports with fallback (uses first available)
{:ok, client} = ExMCP.connect([
"http://primary:8080",
"http://backup:8080"
])
# Using ClientConfig for advanced configuration
config = ExMCP.ClientConfig.new(:production)
|> ExMCP.ClientConfig.put_transport(:http, url: "https://api.example.com")
|> ExMCP.ClientConfig.put_auth(:bearer, token: "secret")
|> ExMCP.ClientConfig.put_retry_policy(max_attempts: 5)
{:ok, client} = ExMCP.connect(config)
@spec disconnect(client()) :: :ok
Disconnects from an MCP server.
@spec info() :: map()
Gets library configuration and capabilities.
@spec ping( connection_spec(), keyword() ) :: :ok | {:error, any()}
Tests connectivity to an MCP server without establishing a persistent connection.
@spec protocol_version() :: String.t()
Returns the version of the MCP protocol this library implements by default.
ExMCP supports multiple protocol versions. This returns the default/latest stable version.
Reads a resource from the connected server.
Options
:timeout- Request timeout in milliseconds (default: 10_000):parse_json- Automatically parse JSON content (default: false)
Examples
# Read text content
content = ExMCP.read(client, "file://data.txt")
# Read and parse JSON
data = ExMCP.read(client, "file://config.json", parse_json: true)
Lists available resources from the connected server.
Starts an ACP client connected to an agent subprocess.
See ExMCP.ACP.start_client/1 for details.
Convenience function to start an MCP client.
This is equivalent to ExMCP.Client.start_link/1 but provides a simpler
entry point for common use cases.
Examples
# stdio transport
{:ok, client} = ExMCP.start_client(
transport: :stdio,
command: ["python", "mcp-server.py"]
)
# HTTP transport
{:ok, client} = ExMCP.start_client(
transport: :http,
url: "https://api.example.com"
)
Convenience function to start an MCP server.
This is equivalent to ExMCP.Server.start_link/1 but provides a simpler
entry point for common use cases.
Examples
{:ok, server} = ExMCP.start_server(
handler: MyApp.Handler,
transport: :stdio
)
Gets connection status and server information.
@spec supported_versions() :: [String.t()]
Returns information about supported protocol versions.
Lists available tools from the connected server.
Returns a list of tool definitions with their schemas and descriptions.
@spec version() :: String.t()
Returns the version of the ExMCP library.