Skip to content

The two MCP servers (don't confuse them)

  1. /api/v1/mcp — always on. A hardcoded set of 10 tools (list_tables, query_rows, insert_row, list_forms, list_bases, list_workflows, create_invoice, create_quote, create_checkout, create_subscription). This is what an external Claude/Cursor config points at. Auth: Bearer jst_*. Verified working live — a minted key resolves and reaches tools/call.
  2. /api/v1/mcp/actionstenant-gated by modules.mcp_export (off by default → 403 "MCP export is not enabled for this tenant"). Exposes every registered defineAction with the full module-gate + approval semantics: service tokens execute immediately (recorded changeset); human/break-glass tokens are forced to propose mode (queued for human review). This is the richer, safer surface — but a tenant must opt in.

On the 401 that stranded the MCP configs: the header-auth path is correct. The 401 {code:-32000} seen this session came from an empty token env (MOS_MCP_TOKEN unset → the client sent Bearer with no value). The 401 now returns a diagnostic message naming the exact cause (fixed in mos-hq6q4.76). See quickstart § "MCP config".


3. MCP config (Claude / Cursor / any MCP client)

MOS speaks MCP over plain HTTP (JSON-RPC 2.0) at /api/v1/mcp — 10 tools: list_tables, query_rows, insert_row, list_forms, list_bases, list_workflows, create_invoice, create_quote, create_checkout, create_subscription.

{
  "mcpServers": {
    "mos": {
      "type": "http",
      "url": "https://acme.marduk.app/api/v1/mcp",
      "headers": { "Authorization": "Bearer jst_YOUR_TOKEN_HERE" }
    }
  }
}

The #1 gotcha: an empty token401 {code:-32000}. If you template the token from an env var ("Bearer ${MOS_MCP_TOKEN}") and the var is unset, the client sends Bearer with no value and every call 401s. The server now tells you exactly which case you hit ("empty Bearer token…", "not a MOS team API key…", "invalid, revoked, or expired"). Sanity-check with curl before wiring a client:

curl -s -X POST https://acme.marduk.app/api/v1/mcp \
  -H "Authorization: Bearer $MOS_MCP_TOKEN" -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}'
# → {"jsonrpc":"2.0","id":1,"result":{"serverInfo":{"name":"jst-client-api",...}}}

The URL must include /api/v1/mcp. A bare host (https://acme.marduk.app) gives the client's own ENDPOINT_NOT_FOUND.

There is a second, richer MCP server at /api/v1/mcp/actions that exposes every MOS action — but it is off by default (per-tenant modules.mcp_export) and returns 403 until enabled. See agentic-rails.md.



© 2026 MOS Labs LLC. All rights reserved.