New package @mcpctl/agent that replaces LiteLLM's broken MCP
integration (dropped Mcp-Session-Id, ignored tools/list_changed) with
a thin ~200 LOC loop built on @modelcontextprotocol/sdk +
openai SDK. LiteLLM stays in its actual lane — OpenAI-compatible model
routing — and this agent handles MCP correctly.
Core (src/agent.ts):
- StreamableHTTPClientTransport for MCP (auto-preserves Mcp-Session-Id).
- Re-fetches tools/list at the top of every loop so list_changed
notifications surface new tools to the model on the next turn
(fixes the gated-session case: begin_session reveals the full
upstream tool set, next round's inference sees all of them).
- OpenAI-compatible inference via process.env.AGENT_LLM_BASE_URL
— points at LiteLLM or vLLM directly.
- Graceful failure: broken tool calls are serialized back into the
conversation as the tool's response, agent keeps going.
- maxIterations cap stops runaway loops; hitIterationLimit surfaces
truncation in the result.
- Structural `McpLike` / `LlmLike` interfaces keep the loop testable
without booting real SDKs.
CLI (src/cli.ts):
mcpctl-agent run "<prompt>" \
--model qwen3-thinking --project sre \
[--system "..."] [--max-iterations N] [-o text|json] [--verbose]
Env fallbacks: AGENT_MCP_URL, AGENT_MCP_TOKEN,
AGENT_LLM_BASE_URL, AGENT_LLM_API_KEY, AGENT_MODEL
Tests (7 cases):
- direct answer (no tool call) → ok
- single-round tool call + synthesis → message history correct
- list_changed refresh: tools/list called at startup + after each
round → next inference sees newly-exposed tools
- maxIterations cap → hitIterationLimit flag set
- failing tool → error serialized into conversation, agent recovers
- systemPrompt prepended
- mcp.close() runs even when loop throws (finally-block guarantee)
End-to-end verified against live cluster:
Round 1: sees 1 tool (begin_session) → calls it
Round 2: sees 115 tools (gate opened) → calls aws-docs/search_documentation
Final: model synthesizes answer
— LiteLLM's chat UI cannot do this today; this loop does.
Still to do (follow-up PRs):
- Wire into mcpctl binary as `mcpctl agent run ...`
- Docker image + Pulumi deploy for a long-running HTTP service mode
- Minimal chat UI (HTMX or plain fetch)
- Streaming responses
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
mcpd can now deploy MCP server instances as Kubernetes pods instead of
Docker containers. Set MCPD_ORCHESTRATOR=kubernetes to enable.
- Add @kubernetes/client-node with thin wrapper (context enforcement
via MCPD_K8S_CONTEXT to prevent multi-cluster mishaps)
- Rewrite KubernetesOrchestrator: pod CRUD, pod IP extraction,
exec via SPDY (one-shot + interactive), log streaming
- Manifest generator: stdin:true for STDIO servers, args (not command)
to preserve runner image entrypoint, security hardening
- Orchestrator selection in main.ts via MCPD_ORCHESTRATOR env var
- 25 unit tests for k8s orchestrator, all 624 tests pass
Tested end-to-end on local k3s:
- mcpd deployed via Pulumi, creates pods in mcpctl-servers namespace
- NetworkPolicy verified: only mcpd can reach MCP server pods
- Python runner (uvx) successfully runs aws-documentation-mcp-server
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add warmup() to LlmProvider interface for eager subprocess startup
- ManagedVllmProvider.warmup() starts vLLM in background on project load
- ProviderRegistry.warmupAll() triggers all managed providers
- NamedProvider proxies warmup() to inner provider
- paginate stage generates LLM-powered descriptive page titles when
available, cached by content hash, falls back to generic "Page N"
- project-mcp-endpoint calls warmupAll() on router creation so vLLM
is loading while the session initializes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ink-based TUI that shows exactly what an LLM sees through MCP.
Browse tools/resources/prompts, execute them, and see raw JSON-RPC
traffic in a protocol log. Supports gated session flow with
begin_session, raw JSON-RPC input, and session reconnect.
- McpSession class wrapping HTTP transport with typed methods
- 12 React/Ink components (header, protocol-log, menu, tool/resource/prompt views, etc.)
- 21 unit tests for McpSession against a mock MCP server
- Fish + Bash completions with project name argument
- bun compile with --external react-devtools-core
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduce a Helm-chart-like template system for MCP servers. Templates are
YAML files in templates/ that get seeded into the DB on startup. Users can
browse them with `mcpctl get templates`, inspect with `mcpctl describe
template`, and instantiate with `mcpctl create server --from-template=`.
Also adds Portainer deployment scripts, mcplocal systemd service,
Streamable HTTP MCP endpoint, and RPM packaging for mcpctl-local.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add STDIO and HTTP upstream transports, McpRouter with tool namespacing
and discovery, and StdioProxyServer for aggregating multiple MCP servers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
McpOrchestrator interface with DockerContainerManager implementation,
instance service for lifecycle management, instance API routes,
and docker-compose with mcpd service. 127 tests passing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add validation schemas (Zod), repository pattern with Prisma, service layer
with business logic (NotFoundError, ConflictError), and REST routes for
MCP server and profile CRUD. 86 mcpd tests passing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add CLI entry point with Commander.js, config management (~/.mcpctl/config.json
with Zod validation), output formatters (table/json/yaml), config and status
commands with dependency injection for testing. Fix sanitizeString regex ordering.
67 tests passing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add registry client that queries Official, Glama, and Smithery MCP
registries with caching, request deduplication, retry logic, and
result ranking/dedup. Includes 53 tests covering all components.
Also fix null priority values in cancelled tasks (19-21) that broke
Task Master, and add new tasks 25-27 for registry completion and
CLI discover/install commands.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>