Rightshold™ Sign up

Answers · MCP security

How do I keep an MCP server as a thin adapter over existing API logic and recheck authorization on every tool call?

Last updated

TL;DR: Treat the MCP server as a narrow protocol adapter in front of the APIs and services you already trust, not as a place to reinvent business rules. Map each tools/call to one existing API operation with a strict input schema, validate arguments, then call that API with a credential scoped to the caller — not a shared admin token. Re-check authorization on every tools/call (and every protected HTTP request), not only when the session starts: validate the access token's audience and expiry, decide whether this identity may run this tool with these arguments on this object, and fail closed if the check errors. Keep ownership, quotas, refunds, pricing and other business logic in the API (or a policy engine next to it); the MCP layer should translate, authorize, rate-limit, sanitize outputs and audit. The MCP authorization profile binds tokens to the MCP resource and forbids token passthrough to upstream APIs; the tools security considerations say servers must validate inputs and implement access controls, and clients should confirm sensitive operations and show full tool inputs before calling.

What should I check, step by step?

1. Inventory the existing API operations the agent needs. Add one MCP tool per operation (or a small, named group), with a strict JSON Schema (additionalProperties: false) — no catch-all run_anything tools.

  1. Put business rules in the API or a shared policy library the API already uses. The MCP handler should validate, authorize, call, map errors and audit — not reimplement refunds, quotas or ownership checks in prompt text.
  2. On every tools/call (and every protected HTTP request): validate the bearer token (issuer, audience, expiry, signature, required scopes), then run an authorization check for this user/client/agent, this tool, these arguments and this object/tenant.
  3. Deny by default and fail closed: if the policy engine times out or errors, the tool does not run.
  4. Never forward the MCP access token to an upstream API. Exchange or mint a separate, audience-bound credential for the downstream call (OAuth token exchange / OBO where you use it).
  5. Filter tools/list to tools the caller is allowed to see. A tool the model never learns about is still not a substitute for a per-call check.
  6. Require human confirmation (or a separate approval record) for writes, payments, deletes and other side effects; show the full arguments, not a model summary.
  7. Append every allow/deny with tool name, argument hash, principal, decision and policy version outside the agent's editable session (for example with record_ai_run).

Why keep MCP as a thin adapter over existing APIs?

MCP is a way for models to discover and invoke tools. Your product's rules already live in APIs that enforce tenancy, ownership, rates and money movement. Duplicating those rules inside MCP handlers creates a second, weaker path that prompt injection and confused-deputy bugs can abuse.

Why recheck authorization on every tools/call, not only at connect?

MCP authorization over HTTP is OAuth 2.1 at the transport: the access token goes on every request. That is authentication of the client to the MCP resource server — it is not a standing warrant for every tool and every object.

What should stay out of the MCP layer?

Business outcomes: whether a refund is allowed, whether a price is valid, whether a user owns a record. Call the API that already decides those.

What can go wrong?

Auth runs only in initialize or on first connect; later tools/call requests skip the check while a role or spend grant was revoked.

How do I ask Rightshold about this (free, no key)?

Add the MCP server https://www.rightshold.com/mcp to Claude, Cursor, ChatGPT, Grok or VS Code, then ask: “Record a signed receipt for this MCP tools/call authorization decision: hashes of the principal, client/agent id, tool name, argument set and policy version, plus allow or deny — without storing the access tokens.”

One-click setup

{
  "tool": "record_ai_run",
  "arguments": {
    "model": "mcp-authz-adapter",
    "provider": "self-hosted",
    "prompt_sha256": "<hash of request context without secrets>",
    "output_sha256": "<hash of allow|deny + reason code>",
    "params": {
      "tool": "create_issue",
      "decision": "allow",
      "policy_version": 7,
      "arguments_sha256": "<sha256 of canonical args>",
      "principal_sha256": "<sha256 of user/agent id>"
    },
    "ran_at": "<ISO-8601>"
  }
}

Rightshold records signed run receipts and human approvals for agents that call it, and can probe public MCP listings. It does not sit inside your MCP server, validate your OAuth tokens, or enforce your API's business rules. Keep authorization and business logic in your adapter and APIs. Not legal advice.

What are the sources?

Related

Not legal advice. JSON · Markdown · All answers

Get a free API key in one call

No card and no email needed. 100 free credits; the license and policy checks stay free without a key.

curl -s -X POST https://www.rightshold.com/v1/accounts/signup -H "Content-Type: application/json" -d '{"accept_terms":true}'
export RIGHTSHOLD_API_KEY=rs_...   # the api_key from the reply (shown once)
curl -s https://www.rightshold.com/v1/licenses/check -H "Authorization: Bearer $RIGHTSHOLD_API_KEY" \
  -H "Content-Type: application/json" -d '{"license":"MIT","intended_use":{"commercial_use":true}}'