Claude-Agent

 view release on metacpan or  search on metacpan

lib/Claude/Agent/MCP/SDKRunner.pm  view on Meta::CPAN

package Claude::Agent::MCP::SDKRunner;

use 5.020;
use strict;
use warnings;

use Claude::Agent::Logger '$log';
use IO::Socket::UNIX;
use IO::Async::Loop;
use IO::Async::Stream;
use JSON::Lines;
use Try::Tiny;

=head1 NAME

Claude::Agent::MCP::SDKRunner - MCP server runner for SDK tools

=head1 DESCRIPTION

This module implements the MCP server protocol and forwards tool calls
to the parent Perl process via a Unix socket. It is spawned as a child
process by the Claude CLI.

=head1 SYNOPSIS

    # Called internally by the SDK - not for direct use
    perl -MClaude::Agent::MCP::SDKRunner -e 'Claude::Agent::MCP::SDKRunner::run()' \
        -- /path/to/socket server_name 1.0.0 '[{"name":"tool1",...}]'

=cut

# Module-level state - encapsulated in a state object for cleaner isolation
# All state is reset atomically at the start of run() to handle persistent interpreters
sub _make_state_class {
    my $class = 'Claude::Agent::MCP::SDKRunner::State';
    no strict 'refs';  ## no critic (ProhibitNoStrict)
    *{"${class}::new"} = sub {
        my ($cls) = @_;
        return bless {
            socket          => undef,
            socket_stream   => undef,
            request_id      => 0,
            pending_requests => {},
            pending_responses => {},  # Initialize alongside other state variables
            jsonl           => undef,
            loop            => undef,
            response_buffer => '',
            got_response    => 0,
        }, $cls;
    };
    *{"${class}::reset_state"} = sub {
        my ($self) = @_;
        $self->{socket} = undef;
        $self->{socket_stream} = undef;
        $self->{request_id} = 0;
        $self->{pending_requests} = {};
        $self->{pending_responses} = {};  # Initialize alongside other state variables
        $self->{jsonl} = JSON::Lines->new;
        $self->{loop} = undef;
        $self->{response_buffer} = '';
        $self->{got_response} = 0;
        return $self;
    };
    return $class;
}
BEGIN { _make_state_class() }

# Single state object - reset atomically at start of run()
my $state = Claude::Agent::MCP::SDKRunner::State->new;

# Accessors for backward compatibility with existing code
sub _socket        { return $state->{socket}; }



( run in 0.742 second using v1.01-cache-2.11-cpan-ceb78f64989 )