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>
Implements the full gated session flow and prompt intelligence system:
- Prisma schema: add gated, priority, summary, chapters, linkTarget fields
- Session gate: state machine (gated → begin_session → ungated) with LLM-powered
tool selection based on prompt index
- Tag matcher: intelligent prompt-to-tool matching with project/server/action tags
- LLM selector: tiered provider selection (fast for gating, heavy for complex tasks)
- Link resolver: cross-project MCP resource references (project/server:uri format)
- Prompt summary service: LLM-generated summaries and chapter extraction
- System project bootstrap: ensures default project exists on startup
- Structural link health checks: enrichWithLinkStatus on prompt GET endpoints
- CLI: create prompt --priority/--link, create project --gated/--no-gated,
describe project shows prompts section, get prompts shows PRI/LINK/STATUS
- Apply/edit: priority, linkTarget, gated fields supported
- Shell completions: fish updated with new flags
- 1,253 tests passing across all packages
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds tier-based LLM routing so fast local models (vLLM, Ollama) handle
structured tasks while cloud models (Gemini, Anthropic) are reserved for
heavy reasoning. Single-provider configs continue to work via fallback.
- Tier type + ProviderRegistry with assignTier/getProvider/fallback chain
- Multi-provider config format: { providers: [{ name, type, tier, ... }] }
- NamedProvider wrapper for multiple instances of same provider type
- Setup wizard: Simple (legacy) / Advanced (fast+heavy tiers) modes
- Status display: tiered view with /llm/providers endpoint
- Call sites use getProvider('fast') instead of getActive()
- Full backward compatibility with existing single-provider configs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- ACP session pool with per-model subprocesses and 8h idle eviction
- Per-project LLM config: local override → mcpd recommendation → global default
- Model override support in ResponsePaginator
- /llm/models endpoint + available models in mcpctl status
- Remove --llm-provider/--llm-model from create project (use edit/apply)
- 8 new smart pagination integration tests (e2e flow)
- 260 mcplocal tests, 330 CLI tests passing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Status command now queries mcplocal's /llm/health endpoint instead of
spawning the gemini binary. This uses the persistent ACP connection
(fast) and works for any configured provider, not just gemini-cli.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace per-call gemini CLI spawning (~10s cold start each time) with
persistent ACP (Agent Client Protocol) subprocess. First call absorbs
the cold start, subsequent calls are near-instant over JSON-RPC stdio.
- Add AcpClient: manages persistent gemini --experimental-acp subprocess
with lazy init, auto-restart on crash/timeout, NDJSON framing
- Add GeminiAcpProvider: LlmProvider wrapper with serial queue for
concurrent calls, same interface as GeminiCliProvider
- Add dispose() to LlmProvider interface + disposeAll() to registry
- Wire provider disposal into mcplocal shutdown handler
- Add status command spinner with progressive output and color-coded
LLM health check results (green checkmark/red cross)
- 25 new tests (17 ACP client + 8 provider)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Setup wizard auto-detects gemini binary via `which`, saves full path
so systemd service can find it without user PATH
- `mcpctl status` tests LLM provider health (gemini: quick prompt test,
ollama: health check, API providers: key stored confirmation)
- Shows error details inline: "gemini-cli / gemini-2.5-flash (not authenticated)"
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Wait for stdout.write callback before process.exit in STDIO transport
to prevent truncation of large responses (e.g. grafana tools/list)
- Handle MCP notification methods (notifications/initialized, etc.) in
router instead of returning "Method not found" error
- Use -p shorthand in config claude output
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The bridge now parses SSE text/event-stream responses (extracting data:
lines) in addition to plain JSON. Also sends correct Accept header
per MCP streamable HTTP spec. Added tests for SSE handling and
command option parsing (-p/--project).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The mcp subcommand now has its own -p/--project option with
passThroughOptions(), so `mcpctl mcp --project NAME` works when Claude
spawns the process. Updated config claude to generate
args: ['mcp', '--project', project] and added Commander-level tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- New `mcpctl mcp -p PROJECT` command: STDIO-to-StreamableHTTP bridge
that reads JSON-RPC from stdin and forwards to mcplocal project endpoint
- Rework `config claude` to write mcpctl mcp entry instead of fetching
server configs from API (no secrets in .mcp.json)
- Keep `config claude-generate` as backward-compat alias
- Fix discovery.ts auth token not being forwarded to mcpd (RBAC bypass)
- Update fish/bash completions for new commands
- 10 new MCP bridge tests, updated claude tests, fixed project-discovery test
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Only set Content-Type: application/json when request body is present (fixes
Fastify rejecting empty DELETE with "Body cannot be empty" 400 error)
- Changed PROJECT_INCLUDE to return full server objects instead of just {id, name}
so project server listings show transport, package, image columns
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Added __mcpctl_needs_server_arg guard in fish and position check in
bash so completions stop after one server name is selected.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Instances have no name field — use server.name for completions
- attach-server: show only servers NOT in the project
- detach-server: show only servers IN the project
- Add helper functions for project-aware server completion
- 5 new tests covering all three fixes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
API returns { "resources": [...] } not bare arrays, so .[].name
produced no output. Use .[][].name to unwrap the outer object first.
Also auto-load .env in pr.sh.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The regex "name":\s*"..." on JSON matched nested server names inside
project objects, mixing resource types in completions. Switch to
jq -r '.[].name' for proper top-level extraction. Add jq as RPM
dependency. Add pr.sh for PR creation via Gitea API.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fish completions are additive — sourcing a new file doesn't remove old
rules. Add `complete -c mcpctl -e` at the top to clear stale entries.
Also add 12 structural tests to prevent completion regressions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace admin role with granular roles: view, create, delete, edit, run
- Two binding types: resource bindings (role+resource+optional name) and
operation bindings (role:run + action like backup, logs, impersonate)
- Name-scoped resource bindings for per-instance access control
- Remove role from project members (all permissions via RBAC)
- Add users, groups, RBAC CRUD endpoints and CLI commands
- describe user/group shows all RBAC access (direct + inherited)
- create rbac supports --subject, --binding, --operation flags
- Backup/restore handles users, groups, RBAC definitions
- mcplocal project-based MCP endpoint discovery
- Full test coverage for all new functionality
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
STDIO MCP servers read from stdin and exit on EOF. Docker containers close
stdin by default, causing all STDIO servers to crash immediately. Added
OpenStdin: true to container creation.
Describe instance now resolves server names (like logs command), preferring
RUNNING instances. Added 7 new describe tests covering server name resolution,
healthcheck display, events section, and template detail.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- `mcpctl logs <server-name>` resolves to first RUNNING instance
- `mcpctl logs <server-name> -i <N>` selects specific replica
- Shows "instance N/M" hint when server has multiple replicas
- Added 5 proper tests: server name resolution, RUNNING preference,
replica selection, out-of-range error, no instances error
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Instance list now shows server NAME instead of cryptic server ID
- Include server relation in findAll query (Prisma include)
- Logs command accepts server name, server ID, or instance ID
(resolves server name → first RUNNING instance)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add global error handler: clean messages instead of stack traces
- Add --force flag to create server/secret/project: updates on 409 conflict
- Strip null values and template-only fields from --from-template payload
- Add tests: 409 handling, --force update, null-stripping from templates
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the confused Profile abstraction with a dedicated Secret resource
following Kubernetes conventions. Servers now have env entries with inline
values or secretRef references. Env vars are resolved and passed to
containers at startup (fixes existing gap).
- Add Secret CRUD (model, repo, service, routes, CLI commands)
- Server env: {name, value} or {name, valueFrom: {secretRef: {name, key}}}
- Add env-resolver utility shared by instance startup and config generation
- Remove all profile-related code (models, services, routes, CLI, tests)
- Update backup/restore for secrets instead of profiles
- describe secret masks values by default, --show-values to reveal
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove global -o/--output from parent program and enable
enablePositionalOptions() so -o yaml/json is parsed by subcommands.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- `create server/profile/project` with all CLI flags (kubectl parity)
- `edit server/profile/project` opens $EDITOR for in-flight editing
- `get -o yaml/json` now outputs apply-compatible format (strips internal fields, wraps in resource key)
- `describe` shows visually clean sectioned output with aligned columns
- Extract shared utilities (resolveResource, resolveNameOrId, stripInternalFields)
- Instances are immutable (no create/edit, like pods)
- Full test coverage for create, edit, and updated describe/get
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Server = Deployment (defines what to run + desired replicas)
Instance = Pod (ephemeral, auto-created by reconciliation)
Backend:
- Add replicas field to McpServer schema
- Add reconcile() to InstanceService (scales instances to match replicas)
- Remove manual start/stop/restart - instances are auto-managed
- Cascade: deleting server stops all containers then cascades DB
- Server create/update auto-triggers reconciliation
CLI:
- Add top-level delete command (servers, instances, profiles, projects)
- Add top-level logs command
- Remove instance compound command (use get/delete/logs instead)
- Clean up project command (list/show/delete → top-level get/describe/delete)
- Enhance describe for instances with container inspect info
- Add replicas to apply command's ServerSpec
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
BackupService exports servers/profiles/projects to JSON bundle.
RestoreService imports with skip/overwrite/fail conflict strategies.
AES-256-GCM encryption for sensitive env vars via scrypt-derived keys.
REST endpoints and CLI commands for backup/restore operations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Architecture doc covers all packages, APIs, and design principles.
Getting-started guide covers installation, quick start, and config.
E2e tests verify all CLI commands are properly registered.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Claude command manages .mcp.json files (generate from project, show, add,
remove entries). Project command provides CRUD for projects with profile
assignment management.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Apply reads YAML/JSON config files to sync servers, profiles, and projects
to the daemon with create-or-update semantics. Setup provides an interactive
wizard for configuring MCP servers with environment variables.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds restart/inspect methods to InstanceService, state validation for stop,
REST endpoints for restart and inspect, and full CLI command suite for
instance list/start/stop/restart/remove/logs/inspect.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
kubectl-style get (table/json/yaml) and describe commands for servers,
profiles, projects, instances. ApiClient for daemon communication.
118 CLI 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>