MCP-K8s
view release on metacpan or search on metacpan
examples/raider-configmap-demo.pl view on Meta::CPAN
my $server = $k8s->server;
ok("Connected!");
label("Namespaces:", join(', ', @{ $k8s->namespaces }));
label("Tools:", scalar(@{ $server->tools }));
print "\n";
# ââ Tool registry (for per-tool stats) ââââââââââââââââââââââââââââââ
my %tool_stats; # name => { calls => N, total_ms => N }
my $total_calls = 0;
# Wrap each tool's code to print live progress with timing
for my $tool (@{ $server->tools }) {
my $orig_code = $tool->code;
my $name = $tool->name;
$tool_stats{$name} = { calls => 0, total_ms => 0 };
$tool->code(sub {
my ($t, $args) = @_;
$total_calls++;
$tool_stats{$name}{calls}++;
# Build detail string
my @info;
push @info, $args->{resource} if $args->{resource};
push @info, $args->{name} if $args->{name};
push @info, "ns=$args->{namespace}" if $args->{namespace};
my $detail = @info ? ' ' . join(', ', @info) : '';
printf " ${YELLOW}[%d]${RESET} ${BOLD}%s${RESET}${DIM}%s${RESET} ",
$total_calls, $name, $detail;
my $t0 = [gettimeofday];
my $result = $orig_code->($t, $args);
my $elapsed = tv_interval($t0) * 1000;
$tool_stats{$name}{total_ms} += $elapsed;
printf "${DIM}(%s)${RESET}\n", fmt_ms($elapsed);
return $result;
});
}
# ââ Wire up async MCP transport âââââââââââââââââââââââââââââââââââââ
my $loop = IO::Async::Loop->new;
my $mcp = Net::Async::MCP->new(server => $server);
$loop->add($mcp);
# ââ AI Engine ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
my $model = $ENV{MCP_K8S_DEMO_MODEL} || 'claude-sonnet-4-6';
info("Model: $model");
print "\n";
my $engine = Langertha::Engine::Anthropic->new(
model => $model,
mcp_servers => [$mcp],
);
# ââ Raider âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
my $iteration_t0;
my $raider = Langertha::Raider->new(
engine => $engine,
max_iterations => 15,
on_iteration => sub {
my ($raider, $iteration) = @_;
# Show timing for previous iteration
if ($iteration_t0 && $iteration > 2) {
my $prev_ms = tv_interval($iteration_t0) * 1000;
info(sprintf(" iteration took %s", fmt_ms($prev_ms)));
}
$iteration_t0 = [gettimeofday];
printf "\n${BLUE}--- Iteration %d ---%s\n", $iteration, $RESET;
# Show token count if available
if ($raider->has_last_prompt_tokens) {
info(sprintf(" prompt tokens: %s", $raider->_last_prompt_tokens));
}
return;
},
mission => <<'MISSION',
You are demonstrating MCP::K8s capabilities. Follow these steps exactly:
1. First, call k8s_permissions to see what you can do.
2. Create a ConfigMap named "mcp-k8s-demo" with this data:
- greeting: "Hello from MCP::K8s!"
- version: "1.0"
- created-by: "langertha-raider"
3. Read the ConfigMap back using k8s_get to verify it exists.
4. Update it using k8s_apply to add a new key: updated: "true"
5. Delete the ConfigMap to clean up.
After each step, briefly confirm what happened. Be concise.
If any step fails due to permissions, report it and skip to the next step.
MISSION
);
# ââ Run the demo âââââââââââââââââââââââââââââââââââââââââââââââââââââ
async sub main {
await $mcp->initialize;
banner("Raid: Full ConfigMap Lifecycle");
my $raid_t0 = [gettimeofday];
printf "${BLUE}--- Iteration 1 ---${RESET}\n";
$iteration_t0 = [gettimeofday];
my $response = await $raider->raid_f(
'Please run through the full ConfigMap demo now.'
);
my $raid_elapsed = tv_interval($raid_t0) * 1000;
# ââ AI Response ââââââââââââââââââââââââââââââââââââââââââââââââââ
banner("AI Response");
print $response, "\n";
# ââ Metrics Summary ââââââââââââââââââââââââââââââââââââââââââââââ
banner("Session Metrics");
my $m = $raider->metrics;
label("Total time:", fmt_ms($raid_elapsed));
label("Iterations:", $m->{iterations});
label("Tool calls:", $m->{tool_calls});
if ($raider->has_last_prompt_tokens) {
label("Last prompt tokens:", $raider->_last_prompt_tokens);
}
# ââ Per-tool breakdown âââââââââââââââââââââââââââââââââââââââââââ
my @used_tools = sort { $tool_stats{$b}{calls} <=> $tool_stats{$a}{calls} }
grep { $tool_stats{$_}{calls} > 0 } keys %tool_stats;
if (@used_tools) {
print "\n${BOLD} Tool Breakdown:${RESET}\n";
printf " ${DIM}%-25s %6s %10s${RESET}\n", 'Tool', 'Calls', 'Time';
printf " ${DIM}%-25s %6s %10s${RESET}\n", '-' x 25, '-' x 6, '-' x 10;
for my $name (@used_tools) {
my $s = $tool_stats{$name};
printf " %-25s %6d %10s\n", $name, $s->{calls}, fmt_ms($s->{total_ms});
}
my $total_tool_ms = 0;
$total_tool_ms += $_->{total_ms} for values %tool_stats;
printf " ${DIM}%-25s %6s %10s${RESET}\n", '-' x 25, '-' x 6, '-' x 10;
printf " ${BOLD}%-25s %6d %10s${RESET}\n",
'TOTAL', $total_calls, fmt_ms($total_tool_ms);
# LLM thinking time = total - tool time
my $llm_ms = $raid_elapsed - $total_tool_ms;
printf "\n ${DIM}LLM thinking: %s | K8s API: %s${RESET}\n",
fmt_ms($llm_ms), fmt_ms($total_tool_ms);
}
# ââ Session history stats ââââââââââââââââââââââââââââââââââââââââ
my @hist = @{ $raider->session_history };
if (@hist) {
my %roles;
$roles{$_->{role} // 'unknown'}++ for @hist;
print "\n${BOLD} Conversation:${RESET}\n";
label("Messages:", scalar @hist);
for my $role (sort keys %roles) {
label(" $role:", $roles{$role});
}
}
print "\n";
ok("Demo complete!");
}
main()->get;
( run in 0.698 second using v1.01-cache-2.11-cpan-71847e10f99 )