Skip to content

MCP bearer/OAuth credentials should be scoped by endpoint, not one global mcp token #286

Description

@serge-ivo

Critical reassessment against HEAD

This ticket is valid, but the original wording was too broad and partly wrong.

HEAD already made an intentional design choice in #266: an MCP "connection" is not a durable status/nickname record. The connection list is derived from grants on a normalized endpoint, and test results are deliberately not cached because health is a fact about now. That part is defensible and should not be undone by adding a second renameable connection table.

The real remaining problem is narrower: credential material is still provider-wide. The outbound MCP connector is declared as auth: "token", and connectorClient("mcp").token() reads user_api_keys at primary key (user_id, provider), where provider is just mcp. That means one user has one MCP bearer slot for every authenticated MCP endpoint.

That is not enough once the product supports arbitrary authenticated MCP servers.

Problem

A user may connect multiple MCP endpoints with different auth modes, scopes, lifetimes, and credential issuers. A single global mcp token cannot safely answer:

  • Which endpoint/resource URL does this credential belong to?
  • Which auth mode produced it: bearer fallback, OAuth/DCR/PKCE, setup-token, etc.?
  • Which scopes/capabilities were granted?
  • When does it expire, and can it refresh unattended?
  • Which instance grants are allowed to use it?
  • How do reconnect/replace/disconnect avoid breaking another MCP endpoint?

Expected model

Keep the #266 endpoint/grants model for connection identity and health. Add endpoint-scoped credential storage/resolution for MCP auth material.

At minimum, an MCP credential record should be scoped by:

  • user/account owner
  • normalized MCP endpoint or protected-resource origin, using the same normalization discipline as normalizeMcpEndpoint
  • auth mode/type and issuer metadata when known
  • encrypted credential material reference, using the existing envelope/vault path or a compatible table
  • scopes/capabilities when known
  • expiry and refresh metadata when applicable

Bearer-token fallback and OAuth/DCR credentials should resolve through the same endpoint-aware API so the connector does not care how the credential was obtained.

Acceptance criteria

  • Credentials for two different MCP endpoints cannot overwrite or authorize each other.
  • mcp_list_tools, probeMcpEndpoint, and mcp_call_tool resolve credentials by normalized endpoint/resource, not only provider mcp.
  • Consent still remains per (instance, endpoint, tool); credential storage does not replace Outbound MCP consent should be per server and per remote tool, not one global write grant #262 grants.
  • No-auth endpoints create no fake secret and still work through the existing grant/test model.
  • Credential material is encrypted at rest and redacted from logs, errors, audit rows, traces, and chat/tool transcripts.
  • Replacing/disconnecting a credential for one endpoint does not affect other MCP endpoints.
  • Expired/revoked credentials fail closed and return a reconnectable state to the UI.
  • Backward compatibility is explicit: either migrate existing provider-level mcp credentials or treat them as a legacy fallback with clear UI wording.
  • The implementation does not add cached "connected" health state or a second endpoint nickname/id that can drift from enforcement.

Related

Activity

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

    backendBackend / Worker / API workconnectorsConnector + tool frameworkenhancementNew feature or requestsecuritySecurity hardening / audit finding

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions