Commit Graph

137 Commits

Author SHA1 Message Date
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
dd626f097c Merge pull request 'feat: MCP healthcheck probes + new templates' (#9) from feat/healthcheck-probes into main 2026-02-22 22:50:10 +00:00
Michal
ae695d2141 feat: add MCP healthcheck probes and new templates (grafana, home-assistant, node-red)
- Add healthCheck spec to templates and servers (tool, arguments, interval, timeout, failureThreshold)
- Add healthStatus, lastHealthCheck, events fields to instances
- Create grafana, home-assistant, node-red templates with healthcheck probes
- Add healthcheck probes to existing templates (github, slack, postgres, jira)
- Show HEALTH column in `get instances` and Events section in `describe instance`
- Display healthCheck details in `describe server` and `describe template`
- Schema + storage + display only; actual probe runner is future work

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 22:48:59 +00:00
6b2fb79b36 Merge pull request 'feat: add MCP server templates and deployment infrastructure' (#8) from feat/mcp-templates into main 2026-02-22 22:25:02 +00:00
Michal
73fb70dce4 feat: add MCP server templates and deployment infrastructure
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>
2026-02-22 22:24:35 +00:00
Michal
8a4ff6e378 fix: remove unused variables from profile cleanup
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 18:43:32 +00:00
Michal
856fb5b5f7 fix: unused deps parameter in project command
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 18:42:16 +00:00
99c9c5d404 Merge pull request 'feat: replace profiles with kubernetes-style secrets' (#7) from feat/replace-profiles-with-secrets into main 2026-02-22 18:41:44 +00:00
Michal
6d9a9f572c feat: replace profiles with kubernetes-style secrets
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>
2026-02-22 18:40:58 +00:00
Michal
ede9e10990 fix: enable positional options so -o works on subcommands
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>
2026-02-22 16:43:35 +00:00
Michal
f9458dffa0 fix: remove unused Project interface from project.ts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 16:41:14 +00:00
7dd2c95862 Merge pull request 'feat: create/edit commands, apply-compatible output, better describe' (#6) from feat/create-edit-commands into main 2026-02-22 16:40:36 +00:00