NAME

Langertha::Raider::MCP - Internal set of the configured MCP servers of one application

VERSION

version 0.504

SYNOPSIS

# Internal to Langertha-Raider -- no API promise.
my $mcp = Langertha::Raider::MCP->new(
  config    => Langertha::Raider::MCP::Config->from_context( $context, config => $config ),
  loop      => $loop,
  on_status => sub { my ( $server ) = @_; ... },
);
my @clients = @{ $mcp->clients };     # engine mcp_servers, before raider's own
my $gate    = $mcp->source_servers;   # { 'engine:1' => 'github', ... }
await $mcp->start_f;                  # every server, in parallel, never fails
for my $row (@{ $mcp->report }) { say $row->{name}.': '.$row->{status} }
await $mcp->stop_f;

DESCRIPTION

Internal module. Its interface may change without notice.

The configured MCP servers of an application (ADR 0029): one Langertha::Raider::MCP::Server for every server of the Langertha::Raider::MCP::Config that may start (status configured), in the model's order. "start_f" starts them all at once, each bounded by MCP_TIMEOUT; a server that fails is reported, never fatal.

The clients go to the front of the engine's mcp_servers, so the engine:N source of their tools is the same N in every engine built from that list, whatever raider's own servers do; "source_servers" names them for the permission gate ("source_servers" in Langertha::Raider::Permissions). Their tool names all start with mcp__, which no tool of raider's own does, so they never shadow one.

config

The Langertha::Raider::MCP::Config. Required.

loop

The IO::Async::Loop the servers run on. Required.

kill_grace

Seconds a stdio server gets between closing stdin, TERM and KILL. Default 2.

on_status

sub { my ( $server ) = @_; ... }, called whenever a server's status changes. Optional.

on_tools_changed

sub { my ( $server ) = @_; ... }, called when a server announced notifications/tools/list_changed (its tools are listed again at once; "list_tools" in Langertha::Raider::MCP::Server waits for that). Optional.

clients

The Langertha::Raider::MCP::Server objects, one per startable server.

previous

The set this one replaces (/reload): a client of it whose server is configured exactly as before ("fingerprint" in Langertha::Raider::MCP::Server) and is starting or connected is taken over instead of started again, and leaves the old set's "clients". What stays there is the old set's to stop ("stop_f"). Optional; read when "clients" is built.

replace

my ( $old, $new ) = $mcp->replace('github');

A fresh client for the server of that name, in the same place of "clients" (so the same engine:N), for /mcp reconnect. Returns the old client (to be stopped) and the new one (not started), or nothing for an unknown name.

pids

The process ids of the running stdio servers (each leads its own process group).

notes

warn "$_\n" for $mcp->notes;

One line per server that waits for an approval nobody can give here (a one-shot run, machine output, the hall, ACP): it stays off, and the line says how to approve it (ADR 0029 §7).

client

my $server = $mcp->client('github');

The client of the server with that name, or undef.

source_servers

my $map = $mcp->source_servers;   # { 'engine:1' => 'github', 'engine:2' => 'plugin_p_db' }

The tool sources of the clients as Langertha::Raider numbers them when they lead the engine's mcp_servers, each with the server part of its tool names, the name mcp__SERVER rules use.

views

my @views = $mcp->views( tools => $agent->{tools}, disallowed => $agent->{disallowed} );

The clients as a subagent sees them (Langertha::Raider::MCP::View), one per client in the same order, so they lead the subagent's engine with the same engine:N as the caller's (the policy of "for_subrun" in Langertha::Raider::Permissions keeps "source_servers"). tools is the agent's allowlist (undef: every tool), disallowed its denylist; an entry names a tool (mcp__server__tool) or a whole server (mcp__server, mcp__server__*). Names that are not mcp__ names concern raider's own tools and are ignored here.

start_f

await $mcp->start_f;

Starts every client in parallel (each bounded by its startup timeout); done when all have connected or failed. Never fails.

report

for my $row (@{ $mcp->report }) { ... }

Every server of the configuration, startable or not, in its order: its entry of "servers" in Langertha::Raider::MCP::Config (name, scope, source, transport, approval, warnings, ...) with status and reason of the client when there is one (configured, starting, connected, failed, stopped), its tools (prefixed names), protocol_version, server_info and stderr (the last lines).

stop_f

await $mcp->stop_f;

Stops every client ("stop_f" in Langertha::Raider::MCP::Server); done when all are gone.

SEE ALSO

SUPPORT

Issues

Please report bugs and feature requests at https://github.com/Getty/langertha-raider/issues.

IRC

Join #langertha on irc.perl.org or message Getty directly.

CONTRIBUTING

Contributions are welcome! Please fork the repository and submit a pull request.

AUTHOR

Torsten Raudssus <torsten@raudssus.de> https://raudssus.de/

COPYRIGHT AND LICENSE

This software is copyright (c) 2026 by Torsten Raudssus.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.

https://raudssus.de/