Phantom.Plug (phantom_mcp v0.3.2)

View Source

Main Plug implementation for MCP HTTP transport with SSE support.

This module provides a complete MCP server implementation with:

  • JSON-RPC 2.0 message handling
  • Server-Sent Events (SSE) streaming
  • CORS handling and security features
  • Session management integration
  • Origin validation

Phoenix

defmodule MyAppWeb.Router do
  use MyAppWeb, :router
  # ...

  pipeline :mcp do
    plug :accepts, ["json", "sse"]

    plug Plug.Parsers,
      parsers: [{:json, length: 1_000_000}],
      pass: ["application/json"],
      json_decoder: JSON
  end

  scope "/mcp" do
    pipe_through :mcp

    forward "/", Phantom.Plug,
      router: MyApp.MCPRouter,
      pubsub: MyApp.PubSub
  end
end

Plug.Router

defmodule MyAppWeb.Router do
  use Plug.Router

  plug :match

  plug Plug.Parsers,
      parsers: [{:json, length: 1_000_000}],
      pass: ["application/json"],
      json_decoder: JSON

  plug :dispatch

  forward "/mcp",
      to: Phantom.Plug,
      init_opts: [
        router: MyApp.MCP.Router,
        pubsub: MyApp.PubSub
      ]
end

Here are the defaults:

[
  pubsub: nil,
  origins: ["http://localhost:4000"],
  validate_origin: true,
  session_timeout: 30000,
  max_request_size: 1048576
]

Telemetry

Telemetry is provided with these events:

  • [:phantom, :plug, :request, :connect] with meta: ~w[session router conn opts]a
  • [:phantom, :plug, :request, :disconnect] with meta: ~w[session router conn]a
  • [:phantom, :plug, :request, :terminate] with meta: ~w[session router conn]a
  • [:phantom, :plug, :request, :exception] with meta: ~w[session router conn stacktrace request exception]a

Summary

Functions

Callback implementation for Plug.call/2.

Initializes the plug with the given options.

Construct a WWW-Authenticate header as defined by RFC 9728 from the map.

Types

opts()

@type opts() :: [
  router: module(),
  origins: [String.t()] | :all | mfa(),
  validate_origin: boolean(),
  session_timeout: pos_integer(),
  max_request_size: pos_integer()
]

www_authenticate()

@type www_authenticate() :: %{
  :method => String.t(),
  optional(String.t() | atom()) => atom() | String.t()
}

Functions

call(conn, opts)

Callback implementation for Plug.call/2.

init(opts)

Initializes the plug with the given options.

Options

  • :router - The MCP router module (required)
  • :origins - List of allowed origins or :all (default: localhost)
  • :validate_origin - Whether to validate Origin header (default: true)
  • :session_timeout - Session timeout in milliseconds (default: 30s)
  • :max_request_size - Maximum request size in bytes (default: 1MB)

www_authenticate(info)

@spec www_authenticate(map()) :: String.t()

Construct a WWW-Authenticate header as defined by RFC 9728 from the map.

This requires the map to contain a :method to indicate acceptable authentication methods, typically "Bearer", and then rest of the attributes will be serialized into the header as key=value.

For example,

iex> Phantom.Plug.www_authenticate(%{
...>   method: "Bearer",
...>   resource_metadata: "https://myapp.com/.well-known/oauth-protected-resource",
...>   max_age: 42000
...> })
~s|Bearer max_age="42000", resource_metadata="https://myapp.com/.well-known/oauth-protected-resource"|

https://datatracker.ietf.org/doc/html/rfc9728#name-use-of-www-authenticate-for