Mead.MCP.Configuration (mead v0.1.1)

Copy Markdown View Source

Validates and normalizes the MCP servers configured under config :mead, :mcp, servers: [...].

config :mead, :mcp,
  servers: [
    filesystem: [
      transport: {:stdio, command: "npx", arguments: ["-y", "@modelcontextprotocol/server-filesystem", "/data"]},
      tools: [read_text_file: :read, write_file: :effect]
    ],
    remote: [
      transport: {:http, url: "https://example.com/mcp", headers: [{"authorization", "Bearer ..."}]},
      tools: [search: :read]
    ]
  ]

The class of a tool (:read or :effect) is declared here and nowhere else; the hub never trusts what a server says about itself. A tool the server offers that is not listed here does not exist for the model. A server name may hold letters, digits, and hyphens but no underscore, so the first __ of server__tool always splits the model-facing name.

Validation is strict on purpose: an unknown option is almost always a typo, and a typo in a permission list silently denies or, worse, mis-grants. Reasons name keys, never values, so a header carrying a credential cannot reach a log through an error.

A listed tool must also be one the model can be shown: server__tool may hold letters, digits, underscores, and hyphens, and be at most 64 characters. A name outside that would be hidden without a word, so it is refused here.

Summary

Types

server()

@type server() :: %{
  name: atom(),
  transport: transport(),
  tools: %{required(String.t()) => :read | :effect}
}

transport()

@type transport() ::
  {:stdio, command: String.t(), arguments: [String.t()]}
  | {:http, url: String.t(), headers: [{String.t(), String.t()}]}

Functions

validate(servers)

@spec validate(term()) :: {:ok, [server()]} | {:error, term()}