McpServer.HttpPlug (HTTP MCP Server v0.6.0)

View Source

HTTP Plug implementation for Model Context Protocol (MCP) servers.

This module implements the MCP HTTP transport specification (2025-06-18), providing a complete JSON-RPC 2.0 over HTTP interface for MCP servers. It handles session management, request routing, and all standard MCP protocol methods.

Features

  • Session Management: Automatic session ID generation and validation
  • Tool Support: List and execute tools defined in your router
  • Prompt Support: List, get, and complete prompts
  • Resource Support: List, read, and complete resources (static and template-based)
  • Completion API: Argument completion for prompts and resources

Configuration Options

When initializing the plug, you can provide the following options:

Required Options

  • :router (required) - Module that uses McpServer.Router. This defines your tools, prompts, and resources. The plug will raise an ArgumentError if not provided.

Optional Options

  • :server_info (optional) - Map containing server metadata returned during initialization. Defaults to %{}. Common fields include:

    • :name - Server name (string)
    • :version - Server version (string)
  • :init (optional) - Function that initializes the MCP connection from the Plug connection. Defaults to fn plug_conn -> %McpServer.Conn{session_id: plug_conn.private.session_id} end. This callback receives the Plug.Conn struct and must return a %McpServer.Conn{} struct. Use this to bridge authentication data or session information from upstream plugs (e.g., OAuth sessions) into your MCP connection context.

    Example with authentication bridge:

    init: fn plug_conn ->
      user_id = plug_conn.assigns[:current_user_id]
      %McpServer.Conn{
        session_id: plug_conn.private.session_id,
        user_id: user_id
      }
    end

Example Usage

Basic Setup with Bandit

# In your application.ex supervision tree
children = [
  {Bandit,
   plug: {McpServer.HttpPlug,
          router: MyApp.Router,
          server_info: %{name: "MyApp MCP Server", version: "1.0.0"}},
   port: 4000,
   ip: {127, 0, 0, 1}}  # Bind to localhost only for security
]

opts = [strategy: :one_for_one, name: MyApp.Supervisor]
Supervisor.start_link(children, opts)

Supported MCP Methods

The plug implements the following MCP protocol methods:

Initialization & Session Management

  • initialize - Initialize a new session and receive server capabilities
  • notifications/initialized - Client notification after initialization completes

Tools

  • tools/list - List all available tools
  • tools/call - Execute a tool with arguments

Prompts

  • prompts/list - List all available prompts
  • prompts/get - Get prompt messages with resolved arguments

Resources

  • resources/list - List static resources
  • resources/templates/list - List resource templates
  • resources/read - Read a resource by URI

Completion

  • completion/complete - Get argument completion suggestions for prompts or resources

Logging

  • logging/setLevel - Set logging level for the current session

Session Management

The plug automatically manages sessions using the mcp-session-id header:

  1. Session Creation: When a client calls initialize, the server generates a unique session ID and returns it in the mcp-session-id response header.

  2. Session Validation: All subsequent requests (except initialize and notifications/initialized) must include the mcp-session-id header with a valid session ID.

  3. Session Context: The session ID is made available to your router functions via the passed connection to your router, allowing session-specific behavior in tools and prompts. To get the session see McpServer.Conn.get_session_id/1.

HTTP Transport Details

  • Method: Only POST requests are supported. GET requests return 405.
  • Content-Type: Request and response bodies use application/json; charset=utf-8
  • Headers: They are not customizable for the moment, and include:
    • cache-control: no-cache
    • connection: keep-alive
    • mcp-session-id: <session-id> (after initialization)
  • Body Limit: Request bodies are limited to 1MB (1,000,000 bytes)

Security Considerations

⚠️ Important: MCP servers should follow the security guidelines from the MCP specification:

  • Bind to localhost (127.0.0.1) only, not 0.0.0.0
  • Use authentication/authorization if exposing over a network
  • Validate and sanitize all tool inputs
  • Run tools with minimal required privileges

See Also

Summary

Functions

call(conn, opts)

Callback implementation for Plug.call/2.

handle_body(conn, body)

handle_request(conn, request)

init(opts)

Callback implementation for Plug.init/1.