Skip to content

Add management-scoped API keys and an amcp management CLI - #1508

Merged
helpcodeai merged 9 commits into
mainfrom
feat/management-cli
Nov 4, 2026
Merged

helpcodeai merged 9 commits into
mainfrom
feat/management-cli

Conversation

@helpcodeai

Copy link
Copy Markdown
Contributor

Summary

Foundation for a full management CLI: let users and connected agents operate their whole AnythingMCP instance (Cloud, self-hosted, Enterprise Cloud) from the terminal — connectors, MCP servers, roles, users, SSO, settings, memory/skills/knowledge-graph — not just call MCP tools. Implements the credential + guard discussed in #1507 and ships a generic amcp api command that reaches every management route.

Changes

  • McpApiKey.scope (MCP | MANAGEMENT_READ | MANAGEMENT_ADMIN), default MCP so existing keys stay tool-call-only (migration 20261104101437).
  • JwtOrManagementKeyGuard: authorizes /api/* with a session JWT or a management-scoped key (bearer). The key carries the owner's identity and role and never grants privilege — RolesGuard still runs, MCP-scoped keys are rejected, MANAGEMENT_READ is safe-methods-only. Wired into all 20 management controllers (browser/callback/EE/health/telemetry excluded).
  • Per-key rate limit on the management API (default 300/min, Redis-backed, falls open without Redis, MANAGEMENT_RATE_LIMIT_PER_MINUTE=0 disables) on top of the global per-IP throttler.
  • POST /api/mcp-keys mints scoped keys (MANAGEMENT_ADMIN requires an admin owner); keys remain self-service.
  • CLI: amcp api <METHOD> <path> [--data …] [--yes] (gh-api style) reaching every management route; amcp login --management stores a management key. Key from AMCP_API_KEY, --key-stdin or a saved profile, never from argv; HTTPS/loopback only, redirects refused.

Type

  • New feature

Testing

  • Added/updated unit tests
  • Tested manually (describe steps below)

Local, against a dedicated dev DB:

  • Backend tsc + lint clean; guard integration spec 8/8 vs a real DB (MCP key rejected on /api, READ+GET ok, READ+POST → 403, ADMIN+POST ok, non-admin role carried, X-API-Key header, 429 rate limit); touched controller specs (connectors, tools, identity-providers, license) 171/171; roles+guard 70/70.
  • CLI tsc + suite 19/19, incl. new amcp api HTTP test (bearer on every request, 403 → exit 3, no key leak) and login --management → api from profile.

Checklist

  • My code follows the existing code style
  • I have tested my changes locally
  • I have updated documentation (if applicable)
  • All existing tests pass (npm test) — ran the affected backend specs and the full CLI suite; did not run the entire backend suite
  • This PR has a descriptive title

Related Issues

Relates to #1507

Follow-ups (not in this PR)

  • Dashboard scope selector when minting a key; browser OAuth login for humans/SSO.
  • Idiomatic subcommands generated from the OpenAPI spec (amcp api is the foundation); a CI check that every operationId has a command.
  • Annotate the File Search controllers for OpenAPI; optional persisted monthly per-key quota.

Give users and connected agents a way to operate their whole AnythingMCP
instance (Cloud, self-hosted or Enterprise Cloud) from the terminal, not just
call MCP tools.

Backend
- McpApiKey gains a `scope` (MCP | MANAGEMENT_READ | MANAGEMENT_ADMIN),
  default MCP, so existing keys stay tool-call-only (migration included).
- JwtOrManagementKeyGuard authorizes /api/* with a session JWT OR a
  management-scoped key presented as a bearer token. The key carries the
  owner's identity and role and never grants privilege: RolesGuard still runs,
  MCP-scoped keys are rejected, and MANAGEMENT_READ keys may use safe methods
  only. Wired into every management controller.
- Per-key rate limit on the management API (default 300/min, Redis-backed,
  falls open without Redis, 0 disables) as a safety net against runaway
  clients, on top of the global per-IP throttler.
- POST /api/mcp-keys mints scoped keys; MANAGEMENT_ADMIN requires an admin.

CLI
- `amcp api <METHOD> <path> [--data …]` reaches every management route with a
  management key from AMCP_API_KEY, --key-stdin or a saved profile; bearer,
  HTTPS/loopback only, redirects refused, key never in argv, status to exit
  code.
- `amcp login --management` verifies and stores a management key (no server).

Tested locally: backend tsc + lint clean; guard integration spec 8/8 vs a real
DB (incl. 429); touched controller specs 171/171; CLI tsc + suite 19/19 incl.
amcp api and management-login tests.
@helpcodeai
helpcodeai requested a review from D3nisty as a code owner November 4, 2026 10:36
Comment thread packages/cli/src/rest.ts
? { 'Content-Type': 'application/json' }
: {}),
},
body: options.body !== undefined ? JSON.stringify(options.body) : undefined,
Drop private, add publishConfig.access=public, files allowlist,
repository/homepage/bugs metadata and a prepublishOnly build so the
package can be published as a public, listed npm package. No code
change and nothing is published by this commit. Relates to #1507.
Add @apioperation summaries to every File Search and File Share route so
the /api/docs OpenAPI document describes the whole management surface,
which the amcp CLI command generator and its coverage check consume.
Relates to #1507.
Let users mint, list, revoke and delete management-scoped API keys
(MANAGEMENT_READ / MANAGEMENT_ADMIN) from the dashboard, not only via the
API, so the amcp CLI can be authorized without hand-crafting a POST. The
admin scope is offered only to workspace admins and stays backend-enforced.
Per-server MCP tool keys are unchanged. Relates to #1507.
Add scripts/generate-cli-operations.mjs, which statically reads every
backend controller guarded by JwtOrManagementKeyGuard and emits
packages/cli/src/generated/operations.ts: the 203 management operations
the amcp CLI can drive, each with method, path, summary (from
@apioperation), admin flag and path params. Public routes on managed
controllers (File Share links) are excluded.

Expose them with 'amcp api --list [resource]' (no key, no network) for
discovery and examples, with --json output and shell completion. A CI
step runs the generator with --check so a new management route cannot
ship without the CLI knowing. Relates to #1507.
'amcp login --browser' opens the instance's new /cli-auth page, where the
user approves under their existing dashboard session (SSO included); the
page mints a management key with the existing POST /api/mcp-keys and
returns it to the CLI over a one-shot 127.0.0.1 loopback via form POST, so
the key never rides in a URL, log or history. A state value binds the
round-trip and a verification code shown in both places lets the user
confirm the match. --scope read|admin picks the key scope (admin only for
admins); AMCP_NO_BROWSER=1 prints the URL for headless use.

This is additive: it changes no backend auth and leaves 'login' (MCP) and
'login --management' (key paste), cookie/JWT and MCP-key auth untouched.
Relates to #1507.
Publishing @anythingmcp/cli needs the npm org and an automation token,
which only the owner can create. This workflow publishes the package
(public, with provenance) when a GitHub Release tagged cli-v* is created,
using an NPM_TOKEN repo secret. No token is embedded. Relates to #1507.
: platform === 'win32' ? ['cmd', ['/c', 'start', '', url]]
: ['xdg-open', [url]];
try {
const child = spawn(cmd as string, args as string[], { stdio: 'ignore', detached: true });
@helpcodeai
helpcodeai merged commit b26c477 into main Nov 4, 2026
14 checks passed
@helpcodeai
helpcodeai deleted the feat/management-cli branch November 4, 2026 14:54
@github-actions github-actions Bot locked and limited conversation to collaborators Nov 4, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants