Commit Graph

148 Commits

Author SHA1 Message Date
Michal
d00973dc54 fix: prevent attach/detach-server from repeating server arg on tab
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>
2026-02-23 19:36:45 +00:00
413dd783cd Merge pull request 'fix: instance completions use server.name, smart attach/detach' (#32) from fix/completion-instances-attach-detach into main 2026-02-23 19:32:34 +00:00
Michal
41f70bb178 fix: instance completions use server.name, smart attach/detach
- 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>
2026-02-23 19:32:18 +00:00
4f1811d6f2 Merge pull request 'fix: use .[][].name in jq for wrapped JSON response' (#31) from fix/completion-jq-wrapped-json into main 2026-02-23 19:27:02 +00:00
Michal
0a641491a4 fix: use .[][].name in jq for wrapped JSON response
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>
2026-02-23 19:26:47 +00:00
8d296b6b7c Merge pull request 'fix: use jq for completion name extraction to avoid nested matches' (#30) from fix/completion-nested-names into main 2026-02-23 19:23:48 +00:00
Michal
dbab2f733d fix: use jq for completion name extraction to avoid nested matches
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>
2026-02-23 19:23:21 +00:00
940b7714a3 Merge pull request 'feat: erase stale fish completions and add completion tests' (#29) from feat/completions-stale-erase-and-tests into main 2026-02-23 19:17:00 +00:00
Michal
84947580ff feat: erase stale fish completions and add completion tests
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>
2026-02-23 19:16:36 +00:00
eb9034b8bb Merge pull request 'feat: context-aware completions with dynamic resource names' (#28) from feat/completions-project-scope-dynamic into main 2026-02-23 19:08:45 +00:00
Michal
846fbf8ae9 feat: context-aware completions with dynamic resource names
- Hide attach-server/detach-server from --help (only relevant with --project)
- --project shows only project-scoped commands in tab completion
- Tab after resource type fetches live resource names from API
- --project value auto-completes from existing project names
- Stop offering resource types after one is already selected

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 19:08:29 +00:00
1a731c5aad Merge pull request 'feat: --project scopes get servers/instances' (#27) from feat/project-scoped-get into main 2026-02-23 19:03:23 +00:00
Michal
88b9158197 feat: --project flag scopes get servers/instances to project
mcpctl --project NAME get servers — shows only servers attached to the project
mcpctl --project NAME get instances — shows only instances of project servers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 19:03:07 +00:00
23ade02451 Merge pull request 'feat: add tests.sh runner and project routes tests' (#26) from feat/tests-sh-and-project-routes-tests into main 2026-02-23 18:58:06 +00:00
Michal
9badb0e478 feat: add tests.sh runner and project routes integration tests
- tests.sh: run all tests with `bash tests.sh`, summary with `--short`
- tests.sh --filter mcpd/cli: run specific package
- project-routes.test.ts: 17 new route-level tests covering CRUD,
  attach/detach, and the ownerId filtering bug fix

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 18:57:46 +00:00
485e01c704 Merge pull request 'fix: project list uses RBAC filtering instead of ownerId' (#25) from fix/project-list-rbac into main 2026-02-23 18:52:29 +00:00
Michal
7d114a8aed fix: project list should use RBAC filtering, not ownerId
The list endpoint was filtering by ownerId before RBAC could include
projects the user has view access to via name-scoped bindings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 18:52:13 +00:00
f8df1e15e9 Merge pull request 'feat: remove ProjectMember, add expose RBAC role, attach/detach-server' (#24) from feat/project-improvements into main 2026-02-23 17:50:24 +00:00
Michal
329315ec71 feat: remove ProjectMember, add expose RBAC role, attach/detach-server commands
- Remove ProjectMember model entirely (RBAC manages project access)
- Add 'expose' RBAC role for /mcp-config endpoint access (edit implies expose)
- Rename CLI flags: --llm-provider → --proxy-mode-llm-provider, --llm-model → --proxy-mode-llm-model
- Add attach-server / detach-server CLI commands (mcpctl --project NAME attach-server SERVER)
- Add POST/DELETE /api/v1/projects/:id/servers endpoints for server attach/detach
- Remove members from backup/restore, apply, get, describe
- Prisma migration to drop ProjectMember table

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 17:50:01 +00:00
1f628d39d2 Merge pull request 'fix: RBAC name-scoped access — CUID resolution + list filtering' (#23) from fix/rbac-name-scoped-access into main 2026-02-23 12:27:48 +00:00
Michal
f0faa764e2 fix: RBAC name-scoped access — CUID resolution + list filtering
Two bugs fixed:
- GET /api/v1/servers/:cuid now resolves CUID→name before RBAC check,
  so name-scoped bindings match correctly
- List endpoints now filter responses via preSerialization hook using
  getAllowedScope(), so name-scoped users only see their resources

Also adds fulldeploy.sh orchestrator script.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 12:26:37 +00:00
75548d841f Merge pull request 'fix: update shell completions for current CLI commands' (#22) from fix/update-shell-completions into main 2026-02-23 12:00:50 +00:00
Michal
44838dbe9d fix: update shell completions for current CLI commands
Add users, groups, rbac, secrets, templates to resource completions.
Remove stale profiles references. Add login, logout, create, edit,
delete, logs commands. Update config subcommands.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 12:00:31 +00:00
6ca62c3d2a Merge pull request 'fix: migrate legacy admin role at startup' (#21) from fix/migrate-legacy-admin-role into main 2026-02-23 11:31:31 +00:00
Michal
ddc95134fb fix: migrate legacy admin role to granular roles at startup
- Add migrateAdminRole() that runs on mcpd boot
- Converts { role: 'admin', resource: X } → edit + run bindings
- Adds operation bindings for wildcard admin (impersonate, logs, etc.)
- Add tests verifying unknown/legacy roles are denied by canAccess

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 11:31:15 +00:00
5f16974f70 Merge pull request 'fix: resolve tsc --build type errors' (#20) from fix/build-type-errors into main 2026-02-23 11:08:08 +00:00
Michal
f3da6c40f4 fix: resolve tsc --build type errors (exactOptionalPropertyTypes)
- Fix resourceName assignment in mapUrlToPermission for strictness
- Use RbacRoleBinding type in restore-service instead of loose cast
- Remove stale ProjectMemberInput export from validation index

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 11:07:46 +00:00
d2dd842b93 Merge pull request 'feat: granular RBAC with resource/operation bindings, users, groups' (#19) from feat/projects-rbac-users-groups into main 2026-02-23 11:05:51 +00:00
Michal
c5147e8270 feat: granular RBAC with resource/operation bindings, users, groups
- 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>
2026-02-23 11:05:19 +00:00
23ab2a497e Merge pull request 'fix: add missing passwordHash to DB test user factory' (#18) from fix/db-tests-passwordhash into main 2026-02-23 01:03:11 +00:00
Michal
90f3beee50 fix: add missing passwordHash to DB test user factory
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 01:02:41 +00:00
Michal
0c926fcc2c fix: SSE health probe uses proper SSE protocol (GET /sse + POST /messages)
SSE-transport MCP servers (like ha-mcp) use a different protocol flow:
GET /sse to establish event stream, read endpoint event, then POST
JSON-RPC messages to /messages?session_id=... URL. Previously was
POSTing to root which returned 404.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 00:55:25 +00:00
Michal
dc860d3ad3 chore: remove accidentally committed logs.sh
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 00:52:31 +00:00
Michal
b6e97646b0 fix: HTTP health probes use container IP for internal network communication
mcpd and MCP containers share the mcp-servers Docker network. HTTP probes
must use the container's internal IP + containerPort instead of localhost
+ host-mapped port. Also extracts container IP from Docker inspect.

Updated home-assistant template to use ghcr.io/homeassistant-ai/ha-mcp
Docker image (SSE transport) instead of broken npm package.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 00:52:17 +00:00
7f338b8b3d Merge pull request 'feat: MCP health probe runner with tool-call probes' (#17) from feat/health-probe-runner into main 2026-02-23 00:39:09 +00:00
Michal
738bfafd46 feat: MCP health probe runner — periodic tool-call probes for instances
Implements Kubernetes-style liveness probes that call MCP tools defined
in server healthCheck configs. For STDIO servers, uses docker exec to
spawn a disposable MCP client that sends initialize + tool call. For
HTTP/SSE servers, sends JSON-RPC directly.

- HealthProbeRunner service with configurable interval/threshold/timeout
- execInContainer added to orchestrator interface + Docker implementation
- Instance findById now includes server relation (fixes describe showing IDs)
- Events appended to instance (last 50), healthStatus tracked as
  healthy/degraded/unhealthy
- 12 unit tests covering probing, thresholds, intervals, cleanup

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 00:38:48 +00:00
3218df009a Merge pull request 'fix: stdin open for STDIO servers + describe instance resolution' (#16) from fix/stdin-describe-instance into main 2026-02-23 00:26:49 +00:00
Michal
fe95dbaa27 fix: keep stdin open for STDIO servers + describe instance resolves server names
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>
2026-02-23 00:26:28 +00:00
4f010f2ae4 Merge pull request 'feat: container liveness sync + node-runner slim base' (#15) from feat/container-liveness-sync into main 2026-02-23 00:18:41 +00:00
Michal
3c489cbecb feat: container liveness sync + node-runner slim base
- Add syncStatus() to InstanceService: detects crashed/stopped containers,
  marks them ERROR with last log line as context
- Reconcile now syncs container status first (detect dead before counting)
- Add 30s periodic sync loop in main.ts
- Switch node-runner from alpine to slim (Debian) for npm compatibility
  (fixes home-assistant-mcp-server binary not found on Alpine)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 00:18:28 +00:00
b85c70bae0 Merge pull request 'fix: logs resolves server names + replica handling + tests' (#14) from fix/logs-resolve-and-tests into main 2026-02-23 00:12:50 +00:00
Michal
459a728196 fix: logs command resolves server names, proper replica handling
- `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>
2026-02-23 00:12:39 +00:00
ce032dc724 Merge pull request 'fix: show server name in instances, logs by server name' (#13) from fix/instance-ux into main 2026-02-23 00:07:57 +00:00
Michal
6fbf301d35 fix: show server name in instances table, allow logs by server name
- 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>
2026-02-23 00:07:42 +00:00
04c2ec498b Merge pull request 'feat: auto-pull images + registry path for node-runner' (#12) from feat/node-runner-registry-pull into main 2026-02-23 00:03:19 +00:00
Michal
d1b6526f75 feat: pull images before container creation, use registry path for node-runner
- Default node-runner image now uses mysources.co.uk registry path
- Add pullImage() call before createContainer() to auto-pull missing images
- Update stack/docker-compose.yml with MCPD_NODE_RUNNER_IMAGE and
  MCPD_MCP_NETWORK env vars, fix mcp-servers network naming

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 00:03:01 +00:00
38fb64794f Merge pull request 'feat: add node-runner base image for npm-based MCP servers' (#11) from feat/node-runner-base-image into main 2026-02-22 23:41:36 +00:00
Michal
5e84f06c65 feat: add node-runner base image for npm-based MCP servers
STDIO servers with packageName (e.g. @leval/mcp-grafana) need a Node.js
container that runs `npx -y <package>`. Previously, packageName was used
as a Docker image reference causing "invalid reference format" errors.

- Add Dockerfile.node-runner: minimal node:20-alpine with npx entrypoint
- Update instance.service.ts: detect npm-based servers and use node-runner
  image with npx command instead of treating packageName as image name
- Fix NanoCPUs: only set when explicitly provided (kernel CFS not available
  on all hosts)
- Add mcp-servers network with explicit name for container isolation
- Configure MCPD_NODE_RUNNER_IMAGE and MCPD_MCP_NETWORK env vars

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 23:41:16 +00:00
ffdaa8dd1d Merge pull request 'fix: error handling and --force flag for create commands' (#10) from fix/create-error-handling into main 2026-02-22 23:06:52 +00:00
Michal
e16b3a3003 fix: proper error handling and --force flag for create commands
- 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>
2026-02-22 23:06:33 +00:00