Security, Operations, And Testing

Security Model

Token storage

Only the SHA256 digest of the raw token is stored. The raw token is emitted once at creation or regeneration time.

Token lifecycle

The model supports:

  • creation
  • regeneration
  • revocation
  • last-used tracking
  • scoped permissions

Permission filtering happens before discovery

This is important. The client does not merely get blocked from calling forbidden tools. It does not see those tools at all if the token lacks the matching permission key.

Tenant isolation is structural

For the org MCP, the tenant is resolved before the tool executes and stored in request-local state. The tool never receives a tenant id from the caller.

Token in URL trade-off

This design is practical for MCP hosts that only configure URLs, but it means tokens can appear in logs.

Mitigations:

  • HTTPS only
  • short rotation cycle for sensitive tokens
  • regeneration and revoke flows in the UI
  • avoid logging full request paths where possible

Operational Behaviors Worth Preserving

Rate limiting

The base Rack app enforces 60 requests per minute per token in memory. That is a good default for a simple Rails deployment.

If the target app runs multiple web processes or many replicas, move this logic to a shared store or API gateway.

Thread-local cleanup

Always clear thread-local MCP state in an ensure path after dispatch. This is not optional in a threaded server.

Transport reuse

This implementation reuses a StreamableHTTPTransport per token and swaps its server object on each request. Keep that pattern if you want to preserve the same runtime shape.

Audit logging

The logging hook sits in the base tool via a prepended module. That is a good pattern because every tool gets logging automatically and the individual tool classes stay clean.

Model tests

  1. raw token lookup returns only active tokens
  2. revoked tokens fail lookup
  3. permission helpers return expected keys
  4. regeneration changes the digest and prefix

Rack tests

  1. missing token returns 401
  2. invalid token returns 401
  3. rate limit returns 429 after the configured threshold
  4. valid token reaches tools/list

Builder tests

  1. permitted tool classes are included
  2. forbidden tool classes are excluded
  3. org builder and admin builder do not mix tool classes

Tool tests

  1. each tool only reads or mutates within its scope root
  2. list tools include IDs in results
  3. validation failures return a readable response
  4. successful calls create activity log rows

UI tests if token management is exported

  1. admins can create tokens
  2. non-admins cannot create tokens
  3. regenerate invalidates the old raw token
  4. revoke removes runtime access immediately

Observability Suggestions

Add metrics or logs for:

  • request count by token scope
  • 401 and 429 rate
  • tool calls by domain and action
  • average duration per tool
  • top failing tools

If the target project already has structured logging, store at least:

  • token id
  • scope
  • tool name
  • domain
  • action
  • status code
  • duration

Safe Rollout Strategy

  1. ship read-only tools first
  2. enable write permissions only for a staff-controlled token
  3. keep create tools drafting or staging by default
  4. monitor activity logs before broad rollout
  5. expand the tool surface only after the first domains are stable

What To Avoid In The Target Project

  1. Unscoped model queries inside tools
  2. Generic catch-all update tools
  3. Storing raw tokens in the database
  4. Using class variables for request context
  5. Skipping activity logs for mutation tools
  6. Exposing delete operations before you have a strong operational reason