NAME

Catalyst::Plugin::MCP::Server - Model Context Protocol engine

SYNOPSIS

my $engine = Catalyst::Plugin::MCP::Server->new(
    server_info => { name => 'myapp', version => '1.0' },
);
$engine->register_provider( $tools );
my $handlers = $engine->handlers;    # verb name => sub ($params)

DESCRIPTION

The protocol engine behind Catalyst::Plugin::MCP: it owns the MCP (revision 2025-06-18) lifecycle, capability advertisement, and verb routing, and knows nothing about your domain: you supply providers.

It also knows nothing about Catalyst or HTTP. The engine maps verb names to plain coderefs; binding those to a transport is the caller's job. Catalyst::Plugin::MCP is that binding, and constructs a fresh engine per request so no state leaks between requests.

METHODS

new( %args )

protocol_versions

Arrayref of supported MCP revisions, newest-first; defaults to ['2025-06-18']. The first entry is the preferred version, returned when a client asks for one that is not supported. Dies if empty.

server_info

Hashref advertised as serverInfo at initialize; defaults to { name => 'mcp-server', version => $VERSION }. Applications should set their own name and version.

register_provider( $obj )

Register a blessed object consuming one or more of the provider roles (Catalyst::Plugin::MCP::Role::ResourceProvider, Catalyst::Plugin::MCP::Role::PromptProvider, Catalyst::Plugin::MCP::Role::ToolProvider). An object consuming several roles is registered once per kind. Returns the engine, so calls chain.

Dies if $obj is not blessed, consumes none of the roles, or is of a kind already registered: one provider per kind.

capabilities

Return the capabilities hashref for initialize: a key per registered provider kind. Kinds with no registered provider are not advertised, and their verbs are not routed.

handlers

Return a hashref of MCP verb name to sub ($params). initialize, ping, and notifications/initialized are always present; the resource, prompt, and tool verbs appear only for registered kinds.

A handler returns its result, or undef for a notification (nothing to send back). To signal a JSON-RPC error it dies with a hashref of code, message, and optional data, using -32602 for bad params and unknown tool or prompt names, -32002 for a resource that does not exist. Note that a tool that runs and fails is not an error here: that is a normal result carrying isError => 1, per Catalyst::Plugin::MCP::Role::ToolProvider.

AUTHOR

Mike Whitaker <mike@altrion.org>

LICENSE

This library is free software; you can redistribute it and/or modify it under the terms of the Artistic License, as distributed with Perl.