NAME

Langertha::Raider::MCP::HTTP - Internal JSON-RPC over MCP's streamable HTTP transport

VERSION

version 0.504

SYNOPSIS

# Internal to Langertha-Raider -- no API promise.
my $wire = Langertha::Raider::MCP::HTTP->new(
  loop    => $loop,
  url     => 'https://mcp.example.com/mcp',
  headers => { Authorization => 'Bearer ...' },
);
my $init = await $wire->request_f( 'initialize', { ... } );
$wire->protocol_version( $init->{protocolVersion} );
await $wire->notify_f( 'notifications/initialized' );
await $wire->stop_f;

DESCRIPTION

Internal module. Its interface may change without notice.

The streamable HTTP transport of MCP (revisions 2025-03-26 and later, ADR 0029 §10): every message is a POST of one JSON-RPC message to "url" with Accept: application/json, text/event-stream; the answer is either a JSON body or an event stream (text/event-stream) whose data: lines carry JSON-RPC messages until the response to the request arrives. The Mcp-Session-Id a server hands out with the initialize response is sent with every later request, and so is MCP-Protocol-Version once "protocol_version" is set. "stop_f" ends the session with a DELETE. Requests the server sends inside an event stream are answered with a POST (ping with an empty result, everything else "Method not found"); notifications are ignored. No standalone GET stream is opened.

Written for raider because the installed Net::Async::MCP::Transport::HTTP speaks only the 2026-07-28 revision: it never sends Mcp-Session-Id and always sends MCP-Protocol-Version: 2026-07-28, which servers of the earlier revisions refuse.

loop

The IO::Async::Loop. Required.

url

The endpoint. Required.

headers

Headers sent with every request (Authorization, ...). Default none.

protocol_version

The negotiated revision; once set, sent as MCP-Protocol-Version.

on_notification

sub { my ( $method, $params ) = @_; ... }, called for a notification in the event stream of a request's answer (there is no standalone stream). Optional.

session_id

The Mcp-Session-Id the server handed out, or undef.

start

Nothing to start: the first request connects. For the interface it shares with Langertha::Raider::MCP::Stdio.

stderr_tail

Empty: a remote server has no stderr here.

request_f

my $result = await $wire->request_f( $method, \%params );

Sends a request; done with its result, failed with MCP error CODE: MESSAGE (category mcp) for a JSON-RPC error, with HTTP STATUS ... for an HTTP error, or when the module a connection needs does not load (Langertha::Raider::ConnectCheck).

notify_f

await $wire->notify_f( 'notifications/initialized' );

Sends a notification; done whatever the server answers (202 is what it should).

notify

"notify_f" without waiting.

stop_f

Ends the session: cancels what is in flight, then a DELETE with the session id (when there is one; answer ignored, at most 2 seconds).

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/