8000 Replace MCP servers with an admin-only REST API and CLI-minted tokens · Issue #595 · jra3/mulm · GitHub
[go: up one dir, main page]

Skip to content

Replace MCP servers with an admin-only REST API and CLI-minted tokens #595

Closed

Description

@jra3

Replace the three MCP servers (src/mcp/: species, member, backfill) with an admin-only REST API under /api/admin/*, authenticated by admin API tokens minted with a CLI inside the prod container. A local client keeps its token in ~/.config/basny/. The #461 cron sync then pushes external data through this API.

Decisions (defaults chosen 2026-10-28; change any of them on the PRs)

  • Tokens: random, shown once at mint, and stored only as a SHA-256 hash in a new admin_api_tokens table (owner member, name, created, last used, optional expiry, revoked). No expiry by default; --expires-days is optional. Revoke by id. No scopes: a token can do whatever its admin can.
  • Auth: /api/admin/* accepts only Authorization: Bearer. It never accepts the session cookie, so CSRF doesn't apply. Every request re-checks that the token's member is still an admin. JSON errors; rate-limited.
  • Minting CLI: admin-token mint|list|revoke, shipped under src/ so it lands in the image. Run as flyctl ssh console --app basny-bap -C "…".
  • Writes: go through the existing domain modules that refactor: derive MCP tools from Zod and extract domain operations #549 extracted, with Zod validation. Audit and admin notes are stamped with the token's member.
  • Port scope: species and member tools get REST endpoints. Backfill CSV import tools are not ported, since that import is done.
  • Order: stacked PRs: the foundation, then the species and member ports in parallel, then deleting MCP. The mcp key in prod and staging CONFIG_JSON is removed only after the deletion is deployed.

Tickets

Documentation (every ticket)

Each PR updates the docs for what it changes:

  • Foundation: docs/ADMIN_API.md (mint, store in ~/.config/basny/admin-token, use, revoke), linked from README, the ops skill and docs/DEPLOY.md; a CONTEXT.md term.
  • Endpoint ports: one section per resource in docs/ADMIN_API.md (route, body, response, errors, curl example).
  • MCP deletion: remove or rewrite every MCP reference: src/mcp/README.md, .mcp.json, README, docs/app-startup.md, e2e/README.md, CI, eslint and tsconfig config.
  • Decide: enable Wikipedia/GBIF enrichment in prod or remove the External Data page #461: scripts/README_EXTERNAL_DATA.md, infrastructure/CRONTAB.md, mobile-audit docs; the REST pusher documents the cron setup.

Activity

  1. added
    enhancementNew feature or request
    securitySecurity improvements and vulnerability fixes
    admin-toolsAdmin interface and management tools
    on Oct 28, 2026
  2. jra3 commented on Oct 28, 2026

    @jra3
    OwnerAuthor

    Note

    🤖 Claude Opus 5.5 responding on behalf of John Allen

    Every ticket is merged to main: #597 (tokens, CLI, bearer auth), #598 (species endpoints), #599 (member endpoints), #600 (MCP deleted), #601 (external-data pusher). Docs: docs/ADMIN_API.md, docs/EXTERNAL_DATA_CRON.md.

    Not in prod yet. After deploying: mint a token (command in ADMIN_API.md), then remove the mcp key from prod's and staging's CONFIG_JSON (docs/DEPLOY.md, "After the MCP removal deploys").

    Follow-ups not filed: an OpenAPI spec generated from the routes' Zod schemas, and keeping image attribution/license through PUT /species/:id/external-data.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    admin-toolsAdmin interface and management toolsenhancementNew feature or requestsecuritySecurity improvements and vulnerability fixes

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      0