MCP::Se...Context(3)

๐Ÿ“ฆ
version 0.150.0 ยท 2 versions
, in opensuse-leap 16.0

๐Ÿ’– NAME ๐Ÿ’–

MCP::Server::Context โ€” literally the request context container, bestie. This is MCP::Server::Context(3) from the User Contributed Perl Documentation, and it's giving "little bag that holds all the per-request vibes" energy. ๐ŸŽ€


โœจ SYNOPSIS โœจ

use MCP::Server::Context;

my $context = MCP::Server::Context->new;
$context->notify_progress(1, 2, 'halfway');

okay so that's the whole vibe right there: make one, then tell the client you're halfway. iconic. ๐Ÿ’…


๐ŸŒธ DESCRIPTION ๐ŸŒธ

MCP::Server::Context is a container for per-invocation request context. That's it, that's the whole job โ€” one of these per invocation, holding all the context for that request. no cap. ๐Ÿซถ


๐Ÿฆ‹ EVENTS ๐Ÿฆ‹

MCP::Server::Context inherits all events from Mojo::EventEmitter, and then emits these new ones on top. yes, it's an overachiever. ๐Ÿ˜ญ

cancelled

$context->on(cancelled => sub ($context) { ... });

Emitted once when the client abandons the current request โ€” either by closing its response stream or by sending a notifications/cancelled notification. Long running operations should stop as soon as practical. fr fr, wrap it up. ๐Ÿ’€

my $id = Mojo::IOLoop->recurring(1 => sub { ... });
$context->on(cancelled => sub ($context) { Mojo::IOLoop->remove($id) });

๐ŸŒˆ ATTRIBUTES ๐ŸŒˆ

MCP::Server::Context implements the following attributes. yes there's a lot of them, hydrate and read. ๐Ÿ’œ

buffer

my $buffer = $context->buffer;
$context   = $context->buffer([]);

Notifications that have been queued up because no response stream was available yet, to be delivered by flush. it's the waiting room, basically. ๐Ÿช‘

client_capabilities

my $capabilities = $context->client_capabilities;
$context         = $context->client_capabilities({elicitation => {}});

Capabilities declared by the client for the current request, from _meta.io.modelcontextprotocol/clientCapabilities. Every request has to declare them, so this is only undef outside of request handling. so if you see undef, you're outside your lane, bestie. ๐Ÿ™ˆ

client_info

my $info = $context->client_info;
$context = $context->client_info({name => 'MyClient', version => '1.0.0'});

Name and version of the client making the current request, from _meta.io.modelcontextprotocol/clientInfo, or undef if the client did not identify itself. shy client behavior. ๐Ÿ˜ณ

controller

my $c    = $context->controller;
$context = $context->controller(Mojolicious::Controller->new);

The Mojolicious::Controller serving the current request, when the HTTP transport is in use. only then! don't come looking for it otherwise. ๐Ÿš‚

input_responses

my $responses = $context->input_responses;
$context      = $context->input_responses({confirm => {action => 'accept', content => {ok => \1}}});

Responses to the input requests of an earlier input_required result, keyed by the same names, or undef if the current request is not a retry. See "input_required" in MCP::Primitive. it's the receipts from last time. ๐Ÿงพ

insufficient_scope

my $needed = $context->insufficient_scope;
$context   = $context->insufficient_scope(['mcp:write']);

Array reference of scopes a denied request was missing, set by the server so the HTTP transport can emit an insufficient_scope challenge. undef when no scope check failed. so undef here = you're fine, breathe. ๐Ÿ˜ฎโ€๐Ÿ’จ

legacy

my $version = $context->legacy;
$context    = $context->legacy('2025-11-25');

The protocol revision a legacy request was made with, or undef for a current request, see MCP::Server::Legacy. vintage protocol moment. ๐Ÿ•ฐ๏ธ

log_level

my $level = $context->log_level;
$context  = $context->log_level('info');

The minimum severity of log messages the client wants for the current request, from _meta.io.modelcontextprotocol/logLevel, or undef if the client asked for none. no logs requested, no logs delivered. ๐Ÿšซ

principal

my $principal = $context->principal;
$context      = $context->principal('user@example.com');

The authenticated caller the current request belongs to, populated from the principal key returned by the auth hook of the HTTP transport. Request state is bound to it, so state minted for one caller is never accepted from another. undef for unauthenticated requests. the way it will NOT let someone else's state slide through โ€” obsessed. ๐Ÿ”

progress_token

my $token = $context->progress_token;
$context  = $context->progress_token('tok-1');

The progress token provided by the client in _meta.progressToken, or undef if none was sent. ๐ŸŽฏ

protocol_version

my $version = $context->protocol_version;
$context    = $context->protocol_version('2026-07-28');

The protocol version the current request was made with, from _meta.io.modelcontextprotocol/protocolVersion. โญ

raw_request_state

my $state = $context->raw_request_state;
$context  = $context->raw_request_state('eyJ...');

The requestState string the client sent back, exactly as received and not verified in any way. Use request_state instead, unless you want to protect the state yourself. like, you're on your own with this one, don't say nobody warned you. ๐Ÿ’€

scopes

my $scopes = $context->scopes;
$context   = $context->scopes(['mcp:read', 'mcp:write']);

OAuth scopes granted to the current request, as an array reference, populated from the auth hook of the HTTP transport. undef (the default) imposes no scope restriction, so scopes are only enforced for authenticated requests that provide them. read that bit twice, it matters. ๐Ÿ‘‘

state_binding

my $binding = $context->state_binding;
$context    = $context->state_binding("tools/call\0deploy");

Identifies the request that request state may be used with, set by the server to the method name and the name or URI of the primitive being called. State sealed for one primitive is never accepted by another. cross-primitive state is not it. ๐Ÿšซ

state_secret

my $secret = $context->state_secret;
$context   = $context->state_secret($bytes);

Key used to authenticate request state, copied from state_secret in MCP::Server. ๐Ÿ”‘

state_timeout

my $seconds = $context->state_timeout;
$context    = $context->state_timeout(300);

How long request state sealed during this request stays valid, in seconds, copied from state_timeout in MCP::Server. clock is ticking bestie. โณ

status

my $status = $context->status;
$context   = $context->status(404);

HTTP status the current request has to be answered with, set by the server for the protocol errors the specification maps to a specific status, such as 404 for an unknown method. undef (the default) means 200, and transports other than MCP::Server::Transport::HTTP ignore it. know your lane, HTTP-only. ๐ŸŒ

stream

my $cb   = $context->stream;
$context = $context->stream(sub ($notification) { ... });

Callback the transport installs once the response stream for the current request is open, to be called with every notification that belongs to it. Notifications sent before that are queued up in buffer. early notifications go to the waiting room, remember? ๐Ÿช‘

transport

my $transport = $context->transport;
$context      = $context->transport(MCP::Server::Transport::HTTP->new);

The transport handling the current request. that's the whole description, it's self-explanatory, periodt. ๐Ÿšš


๐Ÿ’… METHODS ๐Ÿ’…

MCP::Server::Context inherits all methods from Mojo::EventEmitter and implements the following new ones. yes, all of them. generous icon. ๐ŸŽ

cancel

$context = $context->cancel;

Mark the current request as cancelled and emit the cancelled event, at most once. at MOST once, we are not doing duplicate drama. โœ‹

flush

my $num = $context->flush;

Deliver all notifications queued up in buffer to stream, and return the number of notifications delivered. counting them and everything. ๐Ÿ”ข

has_scope

my $bool = $context->has_scope('mcp:write');
my $bool = $context->has_scope('mcp:read', 'mcp:write');

Returns true if every given scope is present in scopes, or if scopes is undef (no restriction). every single one, no partial credit. ๐Ÿ’ฏ

is_cancelled

my $bool = $context->is_cancelled;

Returns true if the current request has been cancelled, for operations that cannot subscribe to the cancelled event and have to poll instead. poll girlies rise. ๐Ÿ“Š

notify

my $bool = $context->notify($method);
my $bool = $context->notify($method, {foo => 'bar'});

Send a JSON-RPC notification on the response stream of the current request. Returns true on success, or undef if the request has been cancelled. ๐Ÿ’Œ

notify_log

my $bool = $context->notify_log('info', 'Something happened');
my $bool = $context->notify_log('error', {code => 23});

Send a notifications/message JSON-RPC notification with the given severity and payload. Returns undef unless the client requested logging with _meta.io.modelcontextprotocol/logLevel and the given severity is at or above the level it asked for. both conditions, no shortcuts. ๐Ÿชต

notify_progress

my $bool = $context->notify_progress($progress);
my $bool = $context->notify_progress($progress, $total);
my $bool = $context->notify_progress($progress, $total, $message);

Send a notifications/progress JSON-RPC notification for the progress token associated with the current request. Returns true on success, or undef if no progress token was provided by the client. no token, no progress updates, that's the deal. ๐Ÿ“ˆ

request_state

my $state = $context->request_state;

Verify and decode the request state the client sent back, returning the data structure that was passed to input_required in MCP::Primitive. Returns undef if there was no state, or if it was tampered with, has expired, was sealed for a different primitive, or belongs to a different principal, so a primitive that cannot tell those cases apart simply asks for input again. honestly kinda elegant. ๐Ÿง 

Replay within state_timeout is not prevented; servers that need one-shot semantics have to enforce that themselves, for example by embedding a nonce and remembering it. so like, that part is on you, bestie. ๐Ÿซต

seal_state

my $sealed = $context->seal_state({step => 2});

Serialize a data structure into an opaque string, authenticated with state_secret and bound to state_binding, principal, and state_timeout. Usually called through input_required in MCP::Primitive rather than directly. so like, use the front door. ๐Ÿšช


๐Ÿงš SEE ALSO ๐Ÿงš


k that's the whole page, go be iconic with your request contexts ๐Ÿ’–โœจ this was MCP::Se...Context(3), from perl v5.42.0, dated 2026-07-31 โ€” mwah, bye bestie! ๐ŸŽ€๐Ÿฆ‹๐ŸŒธ

๐Ÿ“ฆ where this page comes from