Revision history for MCP::Server
0.5.0 2026-08-10T19:54:48+01:00
- $*MCP-REQUEST-CONTEXT.progress(...): a handler can now report progress
on the request it is servicing. It honours the request's own
_meta.progressToken -- era-aware and request-scoped, so a handler that
calls it on a request the client never asked progress for is simply a
no-op rather than a protocol violation. New META-PROGRESS-TOKEN
exported from MCP::Server::Protocol.
- The LLM bridge's execute-tool-calls is now eager: it dispatches the
calls itself rather than deferring them to the caller's reification of
the returned List.
0.4.0 2026-08-09T19:42:11+01:00
- New public MCP::Server.notify(%notification): the delivery half of .log
on its own. Takes a whole notification hash (as
MCP::Server::Protocol's `notification` sub builds it), routes it exactly
as .log does -- a modern request's own channel, else the legacy rules
and the shared transport -- and returns True if some channel took it.
Unlike .log it never echoes to $*ERR and applies no level gating, so a
background worker can push progress or job output to a client without
spraying the host process's terminal; callers gate themselves against
$*MCP-REQUEST-CONTEXT.wants-log. .log now delegates its delivery to it,
with its echo and gating unchanged.
- Spec fix: notifications/message params now carry the log line as `data`
rather than `message`. LoggingMessageNotificationParams has always been
{ level, logger?, data } -- the server was inventing a key, and a client
reading the spec's one (MCP::Client's on-log hook, among others) saw an
undefined payload.
- MCP::Server::Transport::Stdio now serialises write-message with a Lock,
and the Transport role documents that requirement: writes come from the
run loop and from any thread that logs or notifies, and a spliced line
is a stream a JSON-RPC client cannot resynchronise.
- Server-side elicitation: a tool, resource or prompt handler can now call
$*MCP-REQUEST-CONTEXT.elicit(...) to ask the human on the other end of
the client a question and block until they answer. This implements the
2026-07-28 multi round-trip request pattern (MRTR): the call is answered
with resultType "input_required", an inputRequests map and an opaque
requestState, and the client's retry resumes it. New
MCP::Server::Elicitation (Outcome / Broker / Table).
- The handler is parked rather than restarted: it keeps running on a thread
of its own and blocks in await, so nothing it has already done is done
twice. Only a modern-era request on tools/call, resources/read or
prompts/get from a client that declared the elicitation capability is
dispatched that way; every other request is handled exactly as before,
synchronously, on the caller's thread.
- New MCP::Server attributes: :&on-elicit (a local fallback for legacy
clients, the LLM bridge, or direct calls -- takes an ElicitRequest,
returns an ElicitResult), :$elicitation-ttl (default 300s) and
:$max-pending-elicitations (default 64), plus .pending-elicitations for
health checks. A wire client that can be asked always beats the callback.
- execute-tool-calls now binds a legacy-era $*MCP-REQUEST-CONTEXT around
each tool call. Tools that read the request context used to die on an
undefined dynamic variable when a model called them through the bridge.
- Modern results with resultType "input_required" are no longer stamped
with ttlMs/cacheScope: a question about a resource is not the resource,
and it carries a single-use continuation token.
- tools-for-llm now sorts its declarations by tool name, as tools/list
already did. Hash order is not stable in Raku, so the tool block a
model was shown could differ run to run -- and disagree with what a
client built on tools/list publishes for the same server.
- execute-tool-calls now treats an empty or whitespace-only arguments
string as "no arguments" rather than answering with an
"Invalid tool arguments JSON" error result. Models routinely send ""
as the arguments of a tool that takes none. Anything else that is not
a JSON object is still an error result.
- MCP::Server::HTTP now notices a client hanging up while a handler is
running, so $*MCP-REQUEST-CONTEXT.cancelled actually flips for the
case it exists to serve. Previously only a failing write told the
transport the client had gone, which for a quiet handler was when it
finally answered -- too late to cancel anything. New :$disconnect-poll
(default 0.25s) sets how often the client is checked on; the check is
a zero-byte write, so it puts nothing on the wire.
0.3.0 2026-08-07T12:10:18+01:00
- Toolkit system: new MCP::Server::Toolkit role plus
$server.plug($kit, :prefix<...>) and the MCP::Server::Registrar facade.
Prefixed tools and prompts become "prefix_name"; prefixed resource URIs
become "scheme://prefix/path".
- Tool groups now join the prefix and the name with "_" rather than "/", so
generated names stay inside the MCP tool-name charset. This is a breaking
change: tool-group 'file' now registers file_read, not file/read.
ToolGroup remains available as an alias of MCP::Server::Registrar.
- Duplicate tool names, duplicate prompt names and duplicate resource URIs
now die instead of silently overwriting, as do tool names outside
[A-Za-z0-9_-] or longer than 128 characters.
- MCP::Server.new(:tools[...]) loads toolkits by name (bare names resolve
under MCP::Server::Tool::), by instance, or as name => config pairs;
MCP::Server.from-config($path) builds an entire server from a JSON file.
- New raku-mcp command (MCP::Server::CLI) supporting --config, repeatable
--tool, --describe and --help.
- mcp classes (MCP::Server::DSL) are now toolkits themselves and can be
plugged into a larger server; their .server is private and built lazily.
- Dual-era MCP protocol support: both the 2025-11-25 (legacy) and
2026-07-28 (modern) protocol versions are served side by side, with the
era auto-detected per message -- no constructor flag required.
- server/discover is now a mandatory method in the modern era.
- Modern-era results carry a resultType, a _meta block with serverInfo,
and ttlMs/cacheScope cache metadata on tools/resources/prompts list and
resource read results.
- New JSON-RPC error codes -32020, -32021 and -32022 for modern-era
protocol violations.
- Per-request _meta logLevel replaces the logging capability in the
modern era; logging/setLevel is now actually implemented for legacy
clients (previously a stub).
- tools/resources/prompts list results are now returned in a
deterministic order.
- New MCP::Server::HTTP transport (Cro::HTTP-based Streamable HTTP,
modern-era only) answers each request with either a JSON body or a
per-request SSE stream, validates the Origin header, and exposes a
routes embedding hook for mounting inside a larger Cro app. raku-mcp
gained --http, --host, --http-path and --allow-origin flags plus a
matching "http" config-file section.
- New MCP::Server.new options :protocol-versions, :discovery-ttl-ms and
:cache-scope, plus per-resource :ttl-ms and :cache-scope.
- New transport-facing API: handle-modern-request, server-info,
discovery-document and modern-protocol-versions.
- New dependencies: Cro::HTTP and MIME::Base64.
0.2.0 2026-06-22T23:32:43+01:00
- execute-tool-calls now accepts function arguments supplied as
either a JSON string or an associative object, and returns an
`is_error` flag on malformed arguments, unknown tools, and
handler failures.
0.1.3 2026-04-29T23:51:53+01:00
- Bump Github actions to use node 24+
0.1.2 2026-04-19T10:21:15+01:00
- added DSL for MCP::Server (shout-out to zef:FCO)
0.1.1 2026-04-09T12:37:47+01:00
- tools-for-llm: convert registered tools to OpenAI function-calling format
- execute-tool-calls: route LLM tool call requests to registered handlers
- Tool group support with / prefix convention
0.1.0 2026-04-09T12:23:43+01:00
- Initial release
- MCP (Model Context Protocol) server framework for Raku
- JSON-RPC 2.0 protocol handling with full error codes
- Tool registration with JSON Schema generation and parameter validation
- Resource registration with URI-based access
- Prompt registration with argument support
- Stdio transport (stdin/stdout)
- Pluggable transport architecture via Transport role
- Examples: echo server, weather server (wttr.in), file server, strawberry counter