Skip to content

fix(cli): add POST /api/mcp/restart and mcp enable/disable subcommands (#13012) - #13770

Merged
diegosouzapw merged 3 commits into
release/v3.8.51from
fix/13012-cli-mcp-restart-404-no
Sep 16, 2026
Merged

diegosouzapw merged 3 commits into
release/v3.8.51from
fix/13012-cli-mcp-restart-404-no

Conversation

@diegosouzapw

Copy link
Copy Markdown
Collaborator

Refs #13012

Not covered here: Bug 1 (config set <tool> crashing on the @/ alias) — already fixed at tip by bin/aliasResolver.mjs per the owner's 2026-09-10 comment on the issue; this PR only addresses Bug 2 (mcp restart 404 + no CLI/env path to enable MCP).

Root cause

bin/cli/commands/mcp.mjs::runMcpRestartCommand POSTs to /api/mcp/restart, but that route file has never existed under src/app/api/mcp/ (audit/, sse/, status/, stream/, tools/ only) — every omniroute mcp restart call 404s regardless of OS. Separately, mcpEnabled (default false, src/lib/db/settings.ts:174) was documented as dashboard-only — no CLI command, flag, or env var anywhere in the codebase could flip it — so a headless/portable install (the reporter's Windows portable-Node case) had no way to reach the MCP server's 110 tools.

Fix

  • src/app/api/mcp/restart/route.ts — new POST handler, gated by requireManagementAuth (same acceptMcpConnectScope carve-out as the other /api/mcp/* transport routes). Returns 409 when mcpEnabled is false, 501 for the stdio transport (stdio clients own their own subprocess — there's no in-process handle to restart), and otherwise calls the already-exported shutdownMcpHttp() to tear down active sse/streamable-http sessions so the next request re-initializes cleanly.
  • bin/cli/commands/mcp.mjs — new omniroute mcp enable [--transport stdio|sse|streamable-http] / omniroute mcp disable subcommands that PATCH /api/settings the same way the dashboard's MCP page does ({mcpEnabled, mcpTransport}). mcp restart's error path now surfaces the route's JSON error message instead of a bare HTTP 409. mcp status prints a mcp enable hint when it reports the server stopped because mcpEnabled is false.
  • i18n keys added for en/zh-CN/zh-TW (full parity required by check:cli-i18n); pt-BR needs no new top-level section.
  • docs/frameworks/MCP-SERVER.md updated to document the new CLI commands (verified command names and route behavior against source before writing).

/api/mcp/ was already in LOCAL_ONLY_API_PREFIXES (src/server/authz/routeGuard.ts), so the new route inherits that classification automatically — pinned by an explicit test per Hard Rule #15.

Regression tests

tests/unit/mcp-restart-route-13012.test.ts — RED on unfixed code (module doesn't exist):

$ node --import tsx/esm -e "await import('./src/app/api/mcp/restart/route.ts')"
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '…/src/app/api/mcp/restart/route.ts'

GREEN after the fix:

✔ issue #13012: POST /api/mcp/restart exists and returns 409 when MCP is disabled
✔ POST /api/mcp/restart returns 501 for the stdio transport (no in-process handle)
✔ POST /api/mcp/restart tears down HTTP sessions and returns 200 for sse/streamable-http
✔ shutdownMcpHttp is exported and callable (route depends on this contract)
✔ issue #13012: POST /api/mcp/restart is classified LOCAL_ONLY
ℹ tests 5 pass 5 fail 0

tests/unit/cli-mcp-enable-disable-13012.test.ts — pins the mcp enable/mcp disable PATCH body shape (4/4 passing).

Gates run

  • npx eslint --suppressions-location config/quality/eslint-suppressions.json <changed files> — 0 errors, 0 warnings on touched lines.
  • npm run typecheck:core — exit 0.
  • npm run check:cli-i18n — passes for the new mcp.* keys (full zh-CN/zh-TW parity, pt-BR top-level parity); pre-existing unrelated failure serve.ready_timeout confirmed present on origin/release/v3.8.51 before this branch (base drift, not mine).
  • node scripts/check/check-file-size.mjs — no new violation (pre-existing open-sse/utils/stream.ts frozen-size violation is unrelated/untouched).
  • node scripts/check/check-complexity.mjs / check-cognitive-complexity.mjs — both well under baseline (2824/3218, 1276/1437).
  • node scripts/check/check-test-discovery.mjs — OK, new test files discovered.
  • Existing tests in the touched area re-run and pass unchanged: tests/unit/cli-mcp-call-commands.test.ts, tests/unit/cli-server-commands.test.ts, tests/unit/security-route-guard-tiers.test.ts, tests/unit/check-route-guard-membership.test.ts (17/17).
  • npm run check:docs-all — 1 pre-existing STRICT failure (Code-derived counts — readCodeFacts unavailable — tsx/spawnSync failed, a nested-tsx subprocess that imports unrelated provider/catalog modules) and a pre-existing soft "Executors count: 111" drift on docs/architecture/ARCHITECTURE.md — both unrelated to this PR's content and not caused by it (base, not mine).

Existing tests aligned

None needed — no existing assertion encoded the old buggy contract.

Reporter credit: thanks @ricardusx for the original report.

#13012)

`bin/cli/commands/mcp.mjs::runMcpRestartCommand` POSTs to /api/mcp/restart,
but that route never existed under src/app/api/mcp/ — every `omniroute mcp
restart` call 404d. There was also no CLI/env path to flip the mcpEnabled
setting on: it was dashboard-only (/dashboard/mcp -> PATCH /api/settings),
stranding headless/portable installs (Windows portable Node, no browser
session) with no way to reach the MCP server's 110 tools.

Adds the missing route (auth-gated via requireManagementAuth, 409 when
disabled, 501 for stdio since HTTP/SSE sessions are the only in-process
handle shutdownMcpHttp() can tear down) plus `omniroute mcp enable
[--transport stdio|sse|streamable-http]` / `mcp disable`, which PATCH
/api/settings the same way the dashboard toggle does. `mcp status` now
hints at `mcp enable` when it reports the server stopped because it is
disabled.

Regression tests: tests/unit/mcp-restart-route-13012.test.ts (route
behavior across disabled/stdio/http-family states + LOCAL_ONLY
classification) and tests/unit/cli-mcp-enable-disable-13012.test.ts
(PATCH body shape).
@diegosouzapw
diegosouzapw force-pushed the fix/13012-cli-mcp-restart-404-no branch from bc17568 to fd030b4 Compare September 15, 2026 22:55
@diegosouzapw
diegosouzapw merged commit 694c1b7 into release/v3.8.51 Sep 16, 2026
19 of 21 checks passed
HouMinXi added a commit to HouMinXi/OmniRoute that referenced this pull request Sep 16, 2026
…soning-effort test (cheaper-inference#13866)

- Run agent skills generator to sync skills/cli-mcp/SKILL.md with mcp enable/disable subcommands added in cheaper-inference#13770
- Hydrate providerSpecificData.baseUrl in SimpleExecutor for reasoning-effort-clamp-and-retry.test.ts to satisfy cheaper-inference#13798 requireCompatibleBaseUrl guard

Signed-off-by: Minxi Hou <houminxi@gmail.com>
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
cheaper-inference#13012) (cheaper-inference#13770)

Merged in the 2026-09-16 sweep of the maintainer's own open PRs, at the owner's explicit instruction. No push was made to the PR branch: the merge took the head as the owning session left it (verified OPEN, non-draft and MERGEABLE against the release tip immediately before merging).
@diegosouzapw
diegosouzapw deleted the fix/13012-cli-mcp-restart-404-no branch October 18, 2026 23:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant