README

colmugx/mcp/server does not have a README file

#
ContentItem

Content item for MCP tool results

#
JsonRpcResponse

#
MCPError

MCP protocol-level errors These follow the JSON-RPC 2.0 error code conventions.

Error code allocation (per 2026-07-28 spec):
  • -32700, -32600..-32603: standard JSON-RPC 2.0
  • -32000..-32019: legacy/implementation-defined (no new allocations)
  • -32020..-32099: reserved for the MCP specification

#
ParamDef

Parameter definition for tool schema

#
RequestId

Request ID supporting both Int and String per JSON-RPC 2.0 / MCP spec

#
ServerCapabilities

#
Tool

Core Tool trait following MCP protocol

#
ToolCallOutcome

Outcome of a tool execution. Per the 2026-07-28 MRTR pattern, a tool may either complete normally (Complete) or request additional client input (InputRequired). On retry, the client resubmits with inputResponses and the echoed requestState; the tool then receives those responses via its arguments and returns Complete.

#
ToolResult

Tool execution result following MCP protocol format

#
TransportError

Transport-level errors These occur at the communication layer (network, IO, etc.)

#
RequestStateCodec

pub trait RequestStateCodec {
fn seal(Self, RequestStatePayload, now~ : Int) -> String
fn open(Self, String, RequestStateContext, now~ : Int) -> RequestStatePayload?
}

Seals/opens requestState blobs. Implementations MUST be authenticated (AEAD or HMAC) per spec.

now (unix seconds) is passed in by the caller rather than read from a clock inside the codec: it keeps the codec free of a time-package dependency and makes expiry behavior deterministic in tests.

#
ActiveSubscription

pub(all) struct ActiveSubscription {
filter : SubscriptionFilter
reply : ReplyHandle
}

One active subscriptions/listen stream. The server holds these so it can route change notifications to the right client stream. Keyed by the subscription id (the listen request's JSON-RPC id, stringified).

#
AesGcmStateCodec

pub struct AesGcmStateCodec {
key : Bytes
}

AES-256-GCM codec. Holds a 32-byte key only — each seal draws a fresh 12-byte nonce from the OS CSPRNG (@getrandom), so there is no counter state to synchronize across instances and no risk of nonce reuse.

#
AesGcmStateCodec::AesGcmStateCodec

fn AesGcmStateCodec::AesGcmStateCodec() -> AesGcmStateCodec

Construct a codec by reading 32 bytes of OS entropy via @getrandom. Server startup only. Aborts if the OS entropy source is unavailable.

#
AesGcmStateCodec::open

fn AesGcmStateCodec::open(self : AesGcmStateCodec, blob : String, ctx : RequestStateContext, now~ : Int) -> RequestStatePayload?

Declare seal/open as explicit methods on AesGcmStateCodec so trait method promotion is not implicitly relied upon (implicit promotion is deprecated).

#
AesGcmStateCodec::seal

fn AesGcmStateCodec::seal(self : AesGcmStateCodec, payload : RequestStatePayload, now~ : Int) -> String

Declare seal/open as explicit methods on AesGcmStateCodec so trait method promotion is not implicitly relied upon (implicit promotion is deprecated).

#
AesGcmStateCodec::with_key

fn AesGcmStateCodec::with_key(key : Bytes) -> AesGcmStateCodec

Construct a codec with a caller-supplied 32-byte key (e.g. distributed to all instances sharing MRTR state). Aborts if the key is not 32 bytes.

#
MCPServer

pub struct MCPServer {
name : String
version : String
title : String?
description : String?
instructions : String?
auth_config :
AuthConfig
?
request_state_codec : AesGcmStateCodec?
clock : () -> Int
registry : ToolRegistry
resource_registry : ResourceRegistry
prompt_registry : PromptRegistry
subscriptions : Map[String, ActiveSubscription]
}

#
MCPServer::MCPServer

fn MCPServer::MCPServer(name : String, version : String) -> MCPServer

#
MCPServer::close_subscription

async fn MCPServer::close_subscription(self : MCPServer, subscription_id : String) -> Unit

Gracefully close an active subscriptions/listen stream. Sends an empty complete result carrying io.modelcontextprotocol/subscriptionId and removes the subscription. The caller is responsible for any transport-level stream teardown beyond removing the subscription.

#
MCPServer::handle_request

async fn MCPServer::handle_request(self : MCPServer, request_json : String) -> String

#
MCPServer::notify_prompts_list_changed

async fn MCPServer::notify_prompts_list_changed(self : MCPServer) -> Unit

#
MCPServer::notify_resource_updated

async fn MCPServer::notify_resource_updated(self : MCPServer, uri : String) -> Unit

Announce that a specific resource's content changed. Reaches only the subscriptions that listed uri in their resourceSubscriptions filter — this is the 2026-07-28 replacement for the legacy resources/subscribe per-URI push.

#
MCPServer::notify_resources_list_changed

async fn MCPServer::notify_resources_list_changed(self : MCPServer) -> Unit

#
MCPServer::notify_tools_list_changed

async fn MCPServer::notify_tools_list_changed(self : MCPServer) -> Unit

Public server-side notification triggers. Each routes to matching subscriptions/listen streams.

#
MCPServer::prompt_mrtr

MRTR-aware prompt registration. The handler receives the full get params and may return InputRequired to ask the client for input before completing.

#
MCPServer::resource

fn MCPServer::resource(self : MCPServer, uri : String, name : String, description : String, mime_type : String, handler : async () -> Result[
ResourceReadResult
,
MCPError
]) -> MCPServer

#
MCPServer::resource_mrtr

fn MCPServer::resource_mrtr(self : MCPServer, uri : String, name : String, description : String, mime_type : String, handler : async (Json) -> Result[
ResourceReadOutcome
,
MCPError
]) -> MCPServer

MRTR-aware resource registration. The handler receives the full read params and may return InputRequired to ask the client for input before completing.

#
MCPServer::resource_template

fn MCPServer::resource_template(self : MCPServer, uri_template~ : String, name~ : String, description? : String, mime_type? : String) -> MCPServer

Register a resource template for resources/templates/list. Templates are URI patterns the server can read; this call only advertises the template.

#
MCPServer::run_http

async fn MCPServer::run_http(self : MCPServer, port? : Int, path? : String) -> Unit raise
TransportError

#
MCPServer::run_stdio

#
MCPServer::tool

fn MCPServer::tool(self : MCPServer, name : String, description : String, input_schema : Json, handler : async (Json) -> Result[
ToolResult
,
MCPError
]) -> MCPServer

#
MCPServer::with_auth

#
MCPServer::with_clock

fn MCPServer::with_clock(self : MCPServer, clock : () -> Int) -> MCPServer

Inject a wall-clock source (unix seconds) for MRTR requestState expiry. Production servers should pass a real clock; the default returns 0, which disables expiry enforcement (blobs never expire).

#
MCPServer::with_description

fn MCPServer::with_description(self : MCPServer, description : String) -> MCPServer

#
MCPServer::with_instructions

fn MCPServer::with_instructions(self : MCPServer, instructions : String) -> MCPServer

#
MCPServer::with_prompt

fn[T :
Prompt
] MCPServer::with_prompt(self : MCPServer, prompt : T) -> MCPServer

#
MCPServer::with_prompt_mrtr

fn[T :
PromptMRTR
] MCPServer::with_prompt_mrtr(self : MCPServer, prompt : T) -> MCPServer

#
MCPServer::with_request_state_codec

fn MCPServer::with_request_state_codec(self : MCPServer, codec : AesGcmStateCodec) -> MCPServer

Enable MRTR (Multi Round-Trip Requests) by supplying a requestState codec. When set, handlers may return input_required results and verify requestState on retry. Without a codec, MRTR is disabled.

#
MCPServer::with_resource

fn[T :
Resource
] MCPServer::with_resource(self : MCPServer, resource : T) -> MCPServer

#
MCPServer::with_resource_mrtr

fn[T :
ResourceMRTR
] MCPServer::with_resource_mrtr(self : MCPServer, resource : T) -> MCPServer

#
MCPServer::with_title

fn MCPServer::with_title(self : MCPServer, title : String) -> MCPServer

#
MCPServer::with_tool

fn[T :
Tool
] MCPServer::with_tool(self : MCPServer, tool : T) -> MCPServer

#
PromptRegistry

type PromptRegistry

#
ReplyHandle

pub(all) enum ReplyHandle {
Stdio(
Queue
[String])
Http(
Queue
[String])
}

#
RequestStateContext

pub(all) struct RequestStateContext {
principal : String?
request_method : String
params : Json
}

Context checked by open, computed from the incoming retry request.

#
RequestStatePayload

pub(all) struct RequestStatePayload {
principal : String?
expires_at : Int
request_method : String
params_digest : String
state : Json
}

What the server seals into a requestState blob. All fields except state are integrity/replay controls; state is the server's own opaque continuation data (re-derived on retry, never trusted from the client without verification).

#
ResourceRegistry

type ResourceRegistry

#
ServerRequest

pub(all) struct ServerRequest {
message : String
reply : ReplyHandle
}

#
SubscriptionFilter

pub(all) struct SubscriptionFilter {
tools_list_changed : Bool
prompts_list_changed : Bool
resources_list_changed : Bool
resource_subscriptions : Array[String]
}

A subscriptions/listen notification filter (spec §subscriptions). Each field is optional; omitting a field means "not subscribed to that type".

#
SubscriptionFilter::empty

An empty filter (subscribe to nothing) — the default when fields are absent.

#
SubscriptionFilter::matches

Does this filter opt into the given notification kind? A ResourceUpdated(uri) matches only if the subscription listed that URI in its resourceSubscriptions filter.

#
ToolRegistry

type ToolRegistry

#
get_number

fn get_number(json : Json, key : String) -> Result[Double,
ToolResult
]

Extract number from JSON, returning error ToolResult on failure

#
get_optional_number

fn get_optional_number(json : Json, key : String) -> Result[Double?,
ToolResult
]

Extract optional number from JSON

#
get_optional_string

fn get_optional_string(json : Json, key : String) -> Result[String?,
ToolResult
]

Extract optional string from JSON

#
get_string

fn get_string(json : Json, key : String) -> Result[String,
ToolResult
]

Extract string from JSON, returning error ToolResult on failure

#
mcp_server

fn mcp_server(name~ : String, version~ : String) -> MCPServer

#
simple_tool

fn simple_tool(name : String, description : String, handler : (Json) ->
ToolResult
) ->
ToolWrapper

#
tool_fn

fn[Args :
Params
, Ret :
ToToolResult
] tool_fn(handler : (Args) -> Ret, name~ : String, description~ : String) ->
ToolWrapper