NAME

Langertha::Raider::MCP::Stdio - Internal JSON-RPC over the stdin and stdout of an MCP server process

VERSION

version 0.504

SYNOPSIS

# Internal to Langertha-Raider -- no API promise.
my $wire = Langertha::Raider::MCP::Stdio->new(
  loop    => $loop,
  command => 'npx',
  args    => [ '-y', '@bytebase/dbhub' ],
  env     => \%child_env,          # the whole environment of the process
  cwd     => $root,
);
$wire->start;
my $result = await $wire->request_f( 'initialize', { ... } );
$wire->notify( 'notifications/initialized' );
my @last = $wire->stderr_tail;
await $wire->stop_f;

DESCRIPTION

Internal module. Its interface may change without notice.

The stdio transport of a configured MCP server (ADR 0029 §10): the process runs in its own session (setsid, no terminal, so a Ctrl-C of the REPL does not reach it), in "cwd", with exactly "env" as its environment; JSON-RPC messages are lines on its stdin and stdout. Its stderr never reaches raider's terminal: the last "stderr_lines" lines are kept for the status report ("stderr_tail"). Lines on stdout that are not JSON are ignored.

A request the server sends (ping, roots/list, ...) is answered by "on_request"; without one, ping gets an empty result and every other method "Method not found". Notifications from the server are ignored.

Written for raider because the installed Net::Async::MCP::Transport::Stdio takes only a command: no environment, no working directory, and it throws stderr away.

loop

The IO::Async::Loop the process runs on. Required.

command

The program, looked up on PATH by exec. Required.

args

Its arguments. Default none.

env

The whole environment of the process. Default empty.

cwd

Its working directory. Required.

stderr_lines

How many lines of stderr "stderr_tail" keeps. Default 20.

kill_grace

Seconds "stop_f" waits after closing stdin before TERM, and again before KILL. Default 2.

on_request

sub { my ( $method, $params ) = @_; return $result } for requests the server sends; dying answers with an error. Optional.

on_notification

sub { my ( $method, $params ) = @_; ... }, called for every notification the server sends (notifications/tools/list_changed, ...). Optional.

on_exit

sub { my ( $exit_info ) = @_; ... }, called once when the process has ended (see "exited"). Optional.

exited

undef while the process runs (or before "start"), then { code => N, signal => N, error => '...' | undef }.

start

Starts the process. A program that cannot be run ends right away with exit code 127 and the reason on stderr, as a shell would.

pid

The process id (also its process group), or undef.

is_running

True between "start" and the end of the process.

request_f

my $result = await $wire->request_f( 'tools/call', { name => 'x', arguments => {} } );

Sends a request; the future is done with its result, or fails with MCP error CODE: MESSAGE (category mcp, the error object as detail), or with MCP server exited ... when the process ends first. Cancelling the future sends notifications/cancelled.

notify

$wire->notify( 'notifications/initialized' );

Sends a notification; nothing when the process is gone.

stderr_tail

The last lines the process wrote to stderr (at most "stderr_lines", each cut at 500 characters).

exit_text

How the process ended, as a phrase: exited with code 1, killed by signal 9, cannot start: ...; undef while it runs.

stop_f

await $wire->stop_f;

Ends the process the way the MCP specification asks: closes its stdin, sends TERM to its process group after "kill_grace" seconds, KILL after as many again. Done when it has exited.

kill_now

Sends KILL to the process group at once (when the object goes away, or the program ends, before "stop_f" could finish).

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/