MCP::Client::Test::TestKit

NAME

MCP::Client::Test::TestKit - a toolkit with one of everything, for client tests

DESCRIPTION

An MCP::Server::Toolkit that exists to be talked to. It registers a tool for each shape a client has to survive — an answer, a slow answer, an exception, a log notification — plus a prompt and two resources, so every catalog a client knows how to list has something in it and the cacheable and uncacheable halves of resources/read are both covered.

Everything it registers is thread-safe: the tests drive it through transports that dispatch on their own threads, and several calls may be in flight at once.

This — and its siblings MCP::Client::Test::FakeTransport, MCP::Client::Test::InProcessTransport and MCP::Client::Test::ProgressKit — is test support, not library surface. It ships inside the dist's own namespace (rather than under t/lib) deliberately, so that zef install's test phase precompiles it as part of lib/ staging before any test file runs. A t/lib CompUnit repo starts cold on a fresh zef install, and parallel test files pulling the fixtures' dependency chain into that cold store can race and fail the install outright; moving test support into lib/ under a ::Test namespace is the fleet-wide fix for that failure class.

What is in it

  • echo — returns its text argument. The happy path.

  • slow — sleeps for ms milliseconds (default :$slow-ms) and then answers. For "is this request still in flight?" and for timeouts.

  • dying — throws. MCP::Server turns that into a tool result with isError, which is the shape a client must not mistake for a protocol failure.

  • noisy — emits a notifications/message at the level asked for (default info) and then answers. It goes through the request context, so it respects the 2026-07-28 rule that a server MUST NOT log for a request that did not opt in through _meta logLevel.

  • prompt greeting — one argument, one message.

  • resource test://cached — carries ttlMs and cacheScope, so a client that caches correctly reads it from the server exactly once.

  • resource test://volatile — carries neither, so a client that caches correctly reads it from the server every single time.

Both resources count their reads (count-of('read:cached')), which is how a test proves a cache hit never reached the handler, not merely that it never reached the transport.

EXAMPLES

use MCP::Server;
use MCP::Client::Test::TestKit;

my $kit = MCP::Client::Test::TestKit.new(slow-ms => 50);
my $server = MCP::Server.new(:name<fixture>, :version<1.0.0>);
$server.plug($kit);

# ... drive the server ...
say $kit.count-of('echo');          # how many times the echo tool ran

Plugged under a prefix, everything it registers is namespaced, which is how the registry tests build a server with two of it:

$server.plug(MCP::Client::Test::TestKit.new, prefix => 'other');   # other_echo, ...

MCP::Client v0.6.2

talk to an MCP server, in either protocol era

Authors

  • Matt Doughty

License

Artistic-2.0

Dependencies

MCP::Server:ver<0.6.0+>:auth<zef:apogee>JSON::Fast:ver<0.21.0+>:auth<zef:timo>Cro::HTTP:ver<0.8.11+>:auth<zef:cro>:api<0>MIME::Base64:ver<1.2.5+>:auth<zef:raku-community-modules>

Test Dependencies

Provides

  • MCP::Client
  • MCP::Client::Cache
  • MCP::Client::Correlator
  • MCP::Client::Exceptions
  • MCP::Client::Leases
  • MCP::Client::Leases::Table
  • MCP::Client::Policy
  • MCP::Client::Policy::Commands
  • MCP::Client::Policy::Floor
  • MCP::Client::Policy::Grants
  • MCP::Client::Policy::Rules
  • MCP::Client::Protocol
  • MCP::Client::Reasons
  • MCP::Client::Registry
  • MCP::Client::SSE
  • MCP::Client::Test::FakeTransport
  • MCP::Client::Test::InProcessTransport
  • MCP::Client::Test::ProgressKit
  • MCP::Client::Test::TestKit
  • MCP::Client::Transport
  • MCP::Client::Transport::HTTP
  • MCP::Client::Transport::Stdio
  • MCP::Client::UnknownKeys

The Camelia image is copyright 2009 by Larry Wall. "Raku" is a trademark of the Yet Another Society. All rights reserved.

Built with Podlite — the markup and publishing tools behind this site.