Files
mcpctl/package.json

67 lines
2.6 KiB
JSON
Raw Permalink Normal View History

2026-02-21 03:10:39 +00:00
{
"name": "mcpctl",
"version": "0.0.1",
2026-02-21 03:10:39 +00:00
"private": true,
"description": "kubectl-like CLI for managing MCP servers",
"type": "module",
"scripts": {
"build": "pnpm -r run build",
"test": "vitest",
"test:run": "vitest run",
"test:coverage": "vitest run --coverage",
"test:smoke": "pnpm --filter mcplocal run test:smoke",
2026-02-21 03:10:39 +00:00
"test:ui": "vitest --ui",
"lint": "eslint 'src/*/src/**/*.ts'",
"lint:fix": "eslint 'src/*/src/**/*.ts' --fix",
"clean": "pnpm -r run clean && rimraf node_modules",
"db:up": "docker compose -f deploy/docker-compose.yml up -d",
"db:down": "docker compose -f deploy/docker-compose.yml down",
2026-08-08 21:48:14 +01:00
"typecheck": "tsc --build && pnpm run typecheck:pi-ext && pnpm run typecheck:opencode-ext",
"completions:generate": "tsx scripts/generate-completions.ts --write",
"completions:check": "tsx scripts/generate-completions.ts --check",
"rpm:build": "bash scripts/build-rpm.sh",
"rpm:build:amd64": "MCPCTL_TARGET_ARCH=amd64 bash scripts/build-rpm.sh",
"rpm:build:arm64": "MCPCTL_TARGET_ARCH=arm64 bash scripts/build-rpm.sh",
"rpm:publish": "bash scripts/publish-rpm.sh",
"deb:build": "bash scripts/build-deb.sh",
"deb:build:amd64": "MCPCTL_TARGET_ARCH=amd64 bash scripts/build-deb.sh",
"deb:build:arm64": "MCPCTL_TARGET_ARCH=arm64 bash scripts/build-deb.sh",
"deb:publish": "bash scripts/publish-deb.sh",
"release": "bash scripts/release.sh",
"release:both": "bash scripts/release.sh --both-arches",
"mcpd:build": "bash scripts/build-mcpd.sh",
"mcpd:deploy": "bash deploy.sh",
"mcpd:deploy-dry": "bash deploy.sh --dry-run",
fix(pi): repair the /mcpctl menu, skills target, and typecheck the extension The pi extension shipped in `src/pi-ext/` was covered by no tsconfig and no eslint config, so nothing ever checked it against pi's API. Pointing tsc at the published @earendil-works/pi-coding-agent types found the command surface to be inert. Fixes: - `/mcpctl` did nothing. `ctx.ui.select` takes `string[]` and returns the chosen string; it was called with `{value,label}` objects, so the menu rendered five `[object Object]` rows and `choice === "status"` never matched any branch. Labels are now plain strings mapped back to actions. - The headless branch returned a status string from a handler typed `Promise<void>`; pi drops it. Reports via notify instead. - "Sync skills" omitted `--agent pi`, writing into ~/.claude/skills — in an integration whose stated purpose is to not depend on ~/.claude — and said so in its own success message. It also ran execSync with `stdio: "inherit"`, painting raw output over pi's TUI, and interpolated the project name into a shell string. Now execFile with `--agent pi` and captured output. - Tool results typed `content[].type` as `string`; pi's AgentToolResult wants the `"text"` literal. - `callTool` asserted `Promise<unknown>` to `ToolCallResult`. - Sanitising MCP tool names to `[a-z0-9_]` can collide (`docs.search` vs `docs-search`). The colliding tool was silently never registered but still reported active, so its calls were forwarded to the first tool. Names are now disambiguated and tracked with the MCP tool they forward to. - `registerWithPi` rewrote settings.json even when nothing changed. Since parsing strips `//` comments, a no-op run destroyed them. Guards, so this class of bug can't return: - `src/pi-ext/tsconfig.json` checks the extension against the real published pi types (dev dependency, not a shim — a shim drifting from the published API is the exact failure being guarded). Wired into `pnpm typecheck`. - eslint now covers `src/pi-ext/*.ts` like every other source file. - A test fails if the embedded copy in `config/pi-extension.ts` is stale; editing the sources without regenerating silently shipped old code. Also: the branch added `config pi` without regenerating shell completions (the committed-completions test was failing), and the doc advertised `mcpctl pi sync-skills`, which does not exist. Both corrected, plus a note on the session-token vs `mcpctl_pat_` bearer difference that would bite against an authenticated `mcplocal serve`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017BMXdb2qZbPSh8Q7XpTyjB
2026-08-08 17:30:42 +01:00
"mcpd:logs": "bash logs.sh",
fix(smoke): actually clean up smoke-test resources 341 of 356 projects on the shared mcpd were smoke-test leftovers, plus 11 never-expiring `smoke-*` mcptokens sitting on the real `mcpctl-development` and `sre` projects. Enough to make the project picker unusable. Two causes, both silent: - `delete project X --force` — `--force` is valid on `create project` but NOT on `delete`, so every cleanup call exited non-zero and deleted nothing. project-llm-ref's afterAll looked correct and had never worked, which is why there were 84 each of smoke-proj-{ok,orphan,none}-*. - mcptoken.smoke had no afterAll at all; its cleanup was an `it()` at the end of the file, so it was skipped whenever an earlier assertion failed. Cleanup now lives in `afterAll` (runs on failure too) and is no longer gated on the health probe: the project is created through mcpd, which can be up when the gateway probe is not, and deleting a project that was never created is a no-op. Adds `pnpm smoke:clean` for the case afterAll cannot cover — a killed process (CI timeout, Ctrl-C, OOM). Dry-run by default, `--yes` to apply. Only touches `smoke-*` names and protects the shared `smoke-data` / `smoke-aws-docs` fixture, which five suites depend on and which must survive a concurrent run. Verified end to end: created a throwaway smoke project, confirmed the dry run lists without deleting, then `--yes` removed it and left all 15 real projects untouched. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017BMXdb2qZbPSh8Q7XpTyjB
2026-08-08 18:49:42 +01:00
"typecheck:pi-ext": "tsc -p src/pi-ext/tsconfig.json",
2026-08-08 21:48:14 +01:00
"typecheck:opencode-ext": "tsc -p src/opencode-ext/tsconfig.json",
fix(smoke): actually clean up smoke-test resources 341 of 356 projects on the shared mcpd were smoke-test leftovers, plus 11 never-expiring `smoke-*` mcptokens sitting on the real `mcpctl-development` and `sre` projects. Enough to make the project picker unusable. Two causes, both silent: - `delete project X --force` — `--force` is valid on `create project` but NOT on `delete`, so every cleanup call exited non-zero and deleted nothing. project-llm-ref's afterAll looked correct and had never worked, which is why there were 84 each of smoke-proj-{ok,orphan,none}-*. - mcptoken.smoke had no afterAll at all; its cleanup was an `it()` at the end of the file, so it was skipped whenever an earlier assertion failed. Cleanup now lives in `afterAll` (runs on failure too) and is no longer gated on the health probe: the project is created through mcpd, which can be up when the gateway probe is not, and deleting a project that was never created is a no-op. Adds `pnpm smoke:clean` for the case afterAll cannot cover — a killed process (CI timeout, Ctrl-C, OOM). Dry-run by default, `--yes` to apply. Only touches `smoke-*` names and protects the shared `smoke-data` / `smoke-aws-docs` fixture, which five suites depend on and which must survive a concurrent run. Verified end to end: created a throwaway smoke project, confirmed the dry run lists without deleting, then `--yes` removed it and left all 15 real projects untouched. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017BMXdb2qZbPSh8Q7XpTyjB
2026-08-08 18:49:42 +01:00
"smoke:clean": "tsx scripts/clean-smoke-resources.ts"
2026-02-21 03:10:39 +00:00
},
"engines": {
"node": ">=20.0.0",
"pnpm": ">=9.0.0"
},
"packageManager": "pnpm@9.15.0",
"devDependencies": {
fix(pi): repair the /mcpctl menu, skills target, and typecheck the extension The pi extension shipped in `src/pi-ext/` was covered by no tsconfig and no eslint config, so nothing ever checked it against pi's API. Pointing tsc at the published @earendil-works/pi-coding-agent types found the command surface to be inert. Fixes: - `/mcpctl` did nothing. `ctx.ui.select` takes `string[]` and returns the chosen string; it was called with `{value,label}` objects, so the menu rendered five `[object Object]` rows and `choice === "status"` never matched any branch. Labels are now plain strings mapped back to actions. - The headless branch returned a status string from a handler typed `Promise<void>`; pi drops it. Reports via notify instead. - "Sync skills" omitted `--agent pi`, writing into ~/.claude/skills — in an integration whose stated purpose is to not depend on ~/.claude — and said so in its own success message. It also ran execSync with `stdio: "inherit"`, painting raw output over pi's TUI, and interpolated the project name into a shell string. Now execFile with `--agent pi` and captured output. - Tool results typed `content[].type` as `string`; pi's AgentToolResult wants the `"text"` literal. - `callTool` asserted `Promise<unknown>` to `ToolCallResult`. - Sanitising MCP tool names to `[a-z0-9_]` can collide (`docs.search` vs `docs-search`). The colliding tool was silently never registered but still reported active, so its calls were forwarded to the first tool. Names are now disambiguated and tracked with the MCP tool they forward to. - `registerWithPi` rewrote settings.json even when nothing changed. Since parsing strips `//` comments, a no-op run destroyed them. Guards, so this class of bug can't return: - `src/pi-ext/tsconfig.json` checks the extension against the real published pi types (dev dependency, not a shim — a shim drifting from the published API is the exact failure being guarded). Wired into `pnpm typecheck`. - eslint now covers `src/pi-ext/*.ts` like every other source file. - A test fails if the embedded copy in `config/pi-extension.ts` is stale; editing the sources without regenerating silently shipped old code. Also: the branch added `config pi` without regenerating shell completions (the committed-completions test was failing), and the doc advertised `mcpctl pi sync-skills`, which does not exist. Both corrected, plus a note on the session-token vs `mcpctl_pat_` bearer difference that would bite against an authenticated `mcplocal serve`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017BMXdb2qZbPSh8Q7XpTyjB
2026-08-08 17:30:42 +01:00
"@earendil-works/pi-ai": "^0.84.1",
"@earendil-works/pi-coding-agent": "0.84.1",
2026-08-08 21:48:14 +01:00
"@opencode-ai/plugin": "1.18.15",
"@opencode-ai/sdk": "1.18.15",
"@opentui/core": "0.4.5",
"@opentui/keymap": "0.4.5",
"@opentui/solid": "0.4.5",
"@types/node": "^25.3.0",
2026-02-21 03:10:39 +00:00
"@typescript-eslint/eslint-plugin": "^8.56.0",
"@typescript-eslint/parser": "^8.56.0",
"@vitest/coverage-v8": "^4.0.18",
"eslint": "^10.0.1",
"eslint-config-prettier": "^10.1.8",
"rimraf": "^6.1.3",
2026-08-08 21:48:14 +01:00
"solid-js": "^1.9.14",
2026-02-21 03:10:39 +00:00
"tsx": "^4.21.0",
fix(pi): repair the /mcpctl menu, skills target, and typecheck the extension The pi extension shipped in `src/pi-ext/` was covered by no tsconfig and no eslint config, so nothing ever checked it against pi's API. Pointing tsc at the published @earendil-works/pi-coding-agent types found the command surface to be inert. Fixes: - `/mcpctl` did nothing. `ctx.ui.select` takes `string[]` and returns the chosen string; it was called with `{value,label}` objects, so the menu rendered five `[object Object]` rows and `choice === "status"` never matched any branch. Labels are now plain strings mapped back to actions. - The headless branch returned a status string from a handler typed `Promise<void>`; pi drops it. Reports via notify instead. - "Sync skills" omitted `--agent pi`, writing into ~/.claude/skills — in an integration whose stated purpose is to not depend on ~/.claude — and said so in its own success message. It also ran execSync with `stdio: "inherit"`, painting raw output over pi's TUI, and interpolated the project name into a shell string. Now execFile with `--agent pi` and captured output. - Tool results typed `content[].type` as `string`; pi's AgentToolResult wants the `"text"` literal. - `callTool` asserted `Promise<unknown>` to `ToolCallResult`. - Sanitising MCP tool names to `[a-z0-9_]` can collide (`docs.search` vs `docs-search`). The colliding tool was silently never registered but still reported active, so its calls were forwarded to the first tool. Names are now disambiguated and tracked with the MCP tool they forward to. - `registerWithPi` rewrote settings.json even when nothing changed. Since parsing strips `//` comments, a no-op run destroyed them. Guards, so this class of bug can't return: - `src/pi-ext/tsconfig.json` checks the extension against the real published pi types (dev dependency, not a shim — a shim drifting from the published API is the exact failure being guarded). Wired into `pnpm typecheck`. - eslint now covers `src/pi-ext/*.ts` like every other source file. - A test fails if the embedded copy in `config/pi-extension.ts` is stale; editing the sources without regenerating silently shipped old code. Also: the branch added `config pi` without regenerating shell completions (the committed-completions test was failing), and the doc advertised `mcpctl pi sync-skills`, which does not exist. Both corrected, plus a note on the session-token vs `mcpctl_pat_` bearer difference that would bite against an authenticated `mcplocal serve`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017BMXdb2qZbPSh8Q7XpTyjB
2026-08-08 17:30:42 +01:00
"typebox": "1.3.11",
2026-02-21 03:10:39 +00:00
"typescript": "^5.9.3",
"vitest": "^4.0.18"
}
}