AnyEvent-MCP
view release on metacpan or search on metacpan
$| = 1;
for (;;) {
4 == read STDIN, my $buf, 4
or last;
my $len = unpack "N", $buf;
$len == read STDIN, $buf, $len
or die "short perl frame\n";
my @result = do {
(my $source, local @ARGV) = unpack "(w/a*)*", $buf;
("+", eval $source)
};
@result = ("-", $@)
if $@;
print pack "N/a*", pack "(w/a*)*", @result
or die "stdout: $!\n"
}
};
t/03_simple.t view on Meta::CPAN
my ($server) = @_;
++$started;
$timer = AnyEvent->timer (after => 0.01, cb => sub { $server->close });
}, on_close => sub { ++$closed };
ok $started == 1 && $closed == 1, "mcp_http blocks through startup and returns on close";
eval { mcp_http auth => "none", port => 0, on_start => sub { die "startup failed\n" } };
ok $@ =~ /startup failed/, "startup hook exception closes the server and propagates";
{
local @ARGV = ("--auto-deny=*,write", "--auto-allow=read_lines,read",
"--auto-deny=*,*,*");
my $options = mcp_getoptions ({ name => "auto-test" });
ok JSON::XS::encode_json ($options->{auto_rules}) eq JSON::XS::encode_json ([
["deny", "*,write"], ["allow", "read_lines,read"], ["deny", "*,*,*"],
]), "CLI collects repeatable allow/deny rules in original order";
my $perm = AnyEvent::MCP::Server::Permissions->new (
rules => [{ decision => "deny", action => "^" }],
);
my $timer;
t/15_getoptions.t view on Meta::CPAN
use AnyEvent::MCP::Server::HTTP ();
Getopt::Long::Configure ("require_order");
my $have_websocket = eval {
require AnyEvent::WebSocket::Server;
require AnyEvent::WebSocket::Message;
1
};
{
local @ARGV = ("--name", "demo", "--bind", ":31740", "--token", "first",
"--token", "second", "--stdio", "--custom", "yes", "positional");
my $custom;
my $options = mcp_getoptions ({ usage => "usage example\n" }, "custom=s" => \$custom);
is $options->{name}, "demo", "shared name";
is $options->{bind}, ":31740", "shared bind";
is_deeply $options->{tokens}, ["first", "second"], "repeatable ordered tokens";
ok $options->{stdio}, "shared stdio";
is $custom, "yes", "Getopt::Long application option";
is_deeply \@ARGV, ["positional"], "require_order leaves positional arguments";
}
{
local @ARGV = ("--name", "memory", "--custom-instructions", "Use for lasting memories.");
my $options = mcp_getoptions;
is $options->{custom_instructions}, "Use for lasting memories.",
"common custom-instructions option returns instance purpose";
}
{
local @ARGV = ("--name", "example");
my $options = mcp_getoptions ({ path => "/custom/", auth => "none" });
is $options->{path}, "/custom/", "custom endpoint path is returned for startup";
is $options->{auth}, "none", "explicit unauthenticated mode passed to startup";
}
{
local @ARGV = ("--bad-option");
my $error;
{
local *STDERR;
open STDERR, ">", "/dev/null" or die "open /dev/null: $!";
eval { mcp_getoptions ({ usage => "custom usage\n" }) };
$error = $@;
}
like $error, qr/custom usage/, "usage shown on invalid options";
}
{
local @ARGV = ("--name", "example");
my $options = mcp_getoptions;
is_deeply $options, { name => "example" }, "no unnecessary option defaults";
}
my $dir = File::Temp::tempdir (CLEANUP => 1);
local $ENV{XDG_CONFIG_HOME} = $dir;
my $config = AnyEvent::MCP::Config->new (file => "$dir/anyevent-mcp/global.ini");
sub command {
my ($script, @argv) = @_;
( run in 2.025 seconds using v1.01-cache-2.11-cpan-ac8be02dad9 )