MCP::Primitive(3)
πΈ MCP::Primitive π
okay so bestie, welcome to MCP::Primitive β the base class of the MCP (Model Context Protocol) universe. like, the main character that all the other primitives inherit their whole personality from β¨
π SYNOPSIS π
package MyMCPPrimitive;
use Mojo::Base 'MCP::Primitive';
1;
like yes, that's literally it. that's the whole vibe. π«Ά
π DESCRIPTION π
MCP::Primitive is a base class for MCP (Model Context Protocol) primitives β think MCP::Tool, MCP::Prompt, and MCP::Resource. it's giving "parent friend who holds the group chat together" lowkey π
β¨ ATTRIBUTES β¨
MCP::Primitive implements the following attributes (and they're all kind of iconic ngl):
π¦ cache_scope
my $scope = $primitive->cache_scope;
$primitive = $primitive->cache_scope('private');
the cache scope advertised for results that come from this primitive. it's either "public" β meaning results get shared by every caller β or "private" β meaning a gateway may only cache results per caller, no sharing, fr fr.
it defaults to "public", BUT it gets forced to "private" whenever "scopes" is not empty. the way that scopes just snatch that default away π
π cache_ttl
my $ttl = $primitive->cache_ttl;
$primitive = $primitive->cache_ttl(60_000);
how long results derived from this primitive are allowed to sit in cache, measured in milliseconds. it defaults to 0, and 0 means results must be revalidated on every single request. no free rides, no stale data, periodt π
π scopes
my $scopes = $primitive->scopes;
$primitive = $primitive->scopes(['mcp:read', 'mcp:write']);
the OAuth scopes you need in order to list or call this primitive, as an array reference β and all of them must be granted. like, every single one. no partial credit π
this is a local authorization policy layered on top of the HTTP transport's "auth" in MCP::Server::Transport::HTTP hook β it is not wire-level MCP metadata, okay? important distinction bestie. also it's only enforced for requests that supply scopes, so it has zero effect over stdio π
defaults to no required scopes.
π₯ METHODS π₯
MCP::Primitive inherits all methods from Mojo::Base (yes, all of them, she's generous π
) and implements the following new ones.
β context
my $context = $primitive->context;
returns the MCP::Server::Context for the current request. capture this before an async boundary so you can keep using its notification methods from later callbacks β trust me, do not skip this step π
# Get controller for requests using the HTTP transport
my $c = $primitive->context->controller;
πΈ input_required
my $result = $primitive->input_required($input_requests);
my $result = $primitive->input_required($input_requests, $state);
my $result = $primitive->input_required(undef, $state);
returns an "input_required" result, which is basically the primitive going "girl, i need more info, go get it and call me back" π at least one of the two arguments is required β you can't just call it with nothing, that's not the move.
return $tool->input_required({
confirm => {
method => 'elicitation/create',
params => {
message => 'Really deploy to production?',
requestedSchema => {type => 'object', properties => {ok => {type => 'boolean'}}}
}
}
}, {target => $args->{target}});
input requests are keyed by names of your choosing (go off, name them whatever), and the client mirrors them back in "input_responses" in MCP::Server::Context. only ask for capabilities the client actually declared in "client_capabilities" in MCP::Server::Context β don't be out here requesting things they never said they could do π
the optional state is any Perl data structure, and it gets sealed with "seal_state" in MCP::Server::Context before it travels through the client β so a retry can pick up exactly where the first call left off, without the server having to remember anything. it's giving amnesia but make it elegant β¨
read it back with "request_state" in MCP::Server::Context, which returns "undef" for state that cannot be trusted. treat that like a first call and just ask again β no cap, don't try to salvage it.
π heads up: untrusted state meansundef, andundefmeans "start over". don't build on top of a maybe.
π SEE ALSO π
and that's the page, bestie πβ¨ written for perl v5.42.0, dated 2026-07-31, and it's part of the User Contributed Perl Documentation β so like, a real human contributed this. we love that for them π«Άπ
π¦ where this page comes from
- opensuse-leap 16.0: perl-MCP 0.150.0-bp160.1.1 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms