NAME
MCP::Server::Transport::HTTP - HTTP transport for MCP servers
SYNOPSIS
use MCP::Server::Transport::HTTP;
my $http = MCP::Server::Transport::HTTP->new;
DESCRIPTION
MCP::Server::Transport::HTTP is a transport for MCP (Model Context Protocol) server that uses HTTP as the underlying transport mechanism.
Only POST requests are handled; GET and DELETE are answered with status 405. The protocol is stateless, so nothing is remembered between requests and the transport can be deployed behind a load balancer and a pre-forking web server. Notifications that belong to a request, such as progress reports, are delivered on the response stream of that very request, which is upgraded from application/json to text/event-stream whenever there is something to deliver.
The one exception is "streaming", which opts in to subscriptions/listen. Long-lived notification streams require per-process state and are therefore not compatible with pre-forking web servers.
Routing headers are validated against the JSON-RPC body before a request is dispatched, so a gateway that routes on Mcp-Method, Mcp-Name, or Mcp-Param-* alone can never disagree with the server about what was called.
ATTRIBUTES
MCP::Server::Transport::HTTP inherits all attributes from MCP::Server::Transport and implements the following new ones.
auth
my $cb = $http->auth;
$http = $http->auth(sub ($c) {...});
Optional callback to authenticate each request before it is dispatched. It receives the Mojolicious::Controller and returns a hash reference of authentication info on success, or a false value to reject the request with a 401 WWW-Authenticate challenge. The scopes and principal keys of the returned hash reference are made available to handlers as "scopes" in MCP::Server::Context and "principal" in MCP::Server::Context. Token validation is left to the application, so this is where you verify an OAuth 2.0 access token; when not set, requests are not authenticated.
heartbeat
my $seconds = $http->heartbeat;
$http = $http->heartbeat(30);
Interval in seconds at which a keep-alive comment is sent on each open subscription stream. Defaults to 30; set to 0 to disable. Useful when running behind reverse proxies that close idle connections. Only used when "streaming" is enabled.
metadata_url
my $url = $http->metadata_url;
$http = $http->metadata_url('https://example.com/.well-known/oauth-protected-resource');
URL of the OAuth 2.0 Protected Resource Metadata document. When set, it is included as the resource_metadata parameter of the WWW-Authenticate challenge sent with 401 and 403 responses, so clients can discover the authorization server. Use an absolute URL so remote clients can fetch it. See "oauth_metadata" in MCP::Server.
origins
my $origins = $http->origins;
$http = $http->origins(['https://example.com']);
$http = $http->origins(sub ($c, $origin) {...});
Origins allowed to make browser requests, as an array reference of exact matches or a callback returning true for an acceptable origin. Requests carrying an Origin header that is not allowed are rejected with status 403, which protects against DNS rebinding attacks on servers bound to localhost. Defaults to undef, which accepts every origin.
streaming
my $bool = $http->streaming;
$http = $http->streaming(1);
Enable subscriptions/listen, so clients can open a long-lived stream for the list_changed notifications they ask for. Defaults to false. When enabled, the transport tracks every open stream in "subscriptions" and advertises the listChanged capabilities in server/discover. Progress and log notifications do not depend on this, since they are delivered on the response stream of the request they belong to.
subscriptions
my $subscriptions = $http->subscriptions;
$http = $http->subscriptions({});
Per-process registry of active MCP::Server::Subscription objects. Only used when "streaming" is enabled.
METHODS
MCP::Server::Transport::HTTP inherits all methods from MCP::Server::Transport and implements the following new ones.
handle_request
$http->handle_request(Mojolicious::Controller->new);
Handles an incoming HTTP request.
notifications
my $bool = $http->notifications;
True when "streaming" is enabled, false otherwise.
notify_all
my $bool = $http->notify_all($method);
my $bool = $http->notify_all($method, {foo => 'bar'});
Send a JSON-RPC notification to every subscription that asked for it. Returns true on success, or undef when "streaming" is disabled.
SEE ALSO
MCP, https://mojolicious.org, https://modelcontextprotocol.io.