Last reviewed: 2026-08-09
Direct answer
Put the authorization policy at the CometAPI gateway, before a coding agent can discover or invoke a remote MCP tool. Start with the smallest scope set that can complete the requested operation. Bind the authorization request to the exact MCP resource and expected issuer, require the client flow to use PKCE, and keep approval enabled until the tool and data path have been reviewed. If the server later returns an insufficient-scope challenge, perform one deliberate step-up request that preserves the already granted scopes. Retry only after the new issuer, resource, and scope set pass validation.
The current MCP specification makes this sequence concrete. For HTTP transports, a protected server can advertise authorization metadata through a challenge. The client uses that metadata to discover the authorization server, selects the scope requested for the current operation, and records the expected issuer before exchanging an authorization code. The specification also requires the resource parameter to identify the intended MCP server and requires the server to validate that an access token was issued for that audience. Those checks are more reliable than trusting a server label or a tool name supplied by a model.
A gateway should treat authorization as a state machine, not a single token field. A normal run should end with a read-only tool result and a sanitized event trail. An error run should stop on an issuer mismatch, an invalid resource, an unsupported client capability, or a repeated scope escalation. This design keeps a model from turning a broad permission grant into an accidental repository or service write.
Who this is for
This guide is for platform engineers, security engineers, and developer-experience teams that route coding-agent requests through CometAPI and allow those agents to reach remote MCP servers. It is most useful when the agent can access repository data, issue trackers, deployment systems, or other tools that are not local to the runner.
The flow is for HTTP-based remote MCP connections. The current MCP specification treats local STDIO transports differently and says they should not follow this HTTP authorization specification. If a workflow mixes local and remote servers, keep their credential and approval policies separate. For repository-level tool policy, also see the permission and secret boundaries guide .
Key takeaways
- Resolve the server resource and authorization issuer before accepting a user approval.
- Use the scope in the server challenge as the authoritative requirement for the current operation.
- Request only the minimum initial scopes, then use step-up authorization for a specific missing scope.
- Preserve previously granted scopes during reauthorization, but reject any change in issuer or resource.
- Keep approval required for new or write-capable tools until their data flow is understood.
- Check client compatibility instead of assuming that every coding-agent surface supports OAuth-protected remote MCP servers.
- Log identities, scopes, decisions, and outcomes while replacing token material and authorization headers with a redaction marker.
Sources checked
The Model Context Protocol authorization specification defines protected-resource discovery, scope selection, resource binding, step-up handling, and token validation for HTTP transports.
The OpenAI MCP and Connectors guide documents remote server configuration, optional OAuth authorization, and approval controls for data shared with MCP servers.
The GitHub guide to configuring MCP servers documents repository-level tool allowlists, autonomous tool use, and the current lack of remote OAuth MCP support for Copilot cloud agent and code review.
Contract details to verify
1. Discovery and identity. Send the first request without assuming that a server label is an identity. If the server challenges the request, fetch the protected-resource metadata it identifies. Confirm that the selected authorization server is one of the advertised choices, and record the issuer from validated metadata. Keep the canonical MCP resource as a separate value from the friendly server label. A label can be renamed; the resource and issuer are what the gateway must compare.
2. Scope selection. Use the scope in the challenge for the operation at hand. If no challenge scope is present, use the server’s advertised minimal scope set rather than requesting every available permission. Keep a tool-to-scope map in gateway configuration. A read operation such as listing files should not inherit a write scope simply because another tool on the same server can edit files.
3. Step-up behavior. When a tool returns an insufficient-scope response, pause the agent loop. Compute the union of the previously granted scopes and the newly required scopes. Ask for approval for that exact union, then reauthorize with the same canonical resource and expected issuer. Set a retry limit of one step-up attempt per operation. If the server keeps asking for a broader or different set, return a policy error to the agent instead of creating an authorization loop.
4. Client registration and response checks. Use one documented client-registration method for the gateway. During an authorization-code flow, store the PKCE verifier and expected issuer in the same short-lived request record. Compare the issuer in the response exactly as required by the MCP specification. Do not continue to a token exchange after a mismatch. The gateway should also check that the resource value in the authorization and token requests names the intended MCP server.
5. Approval and compatibility. OpenAI’s guide shows that a remote MCP tool can be configured with a server URL, an optional OAuth authorization value, and an explicit approval policy. Keep approval required while onboarding a server so an operator can inspect what data will be shared. GitHub’s current repository guide says Copilot cloud agent and code review do not support remote MCP servers that use OAuth, and it recommends allowlisting specific read-only tools because those tools can run autonomously. Treat those statements as compatibility checks, not as assumptions that transfer to every client.
A safe gateway configuration can be represented without any credential material:
server_label: read-only-repository-tools
resource_id: canonical-mcp-resource
requested_scopes:
- files:read
approval: required
allowed_tools:
- list_files
- read_file
step_up_attempt_limit: 1
Happy path. An agent asks to list files. The gateway resolves the configured resource and sends the request. A 401 challenge identifies the metadata location and the required read scope. The gateway validates the metadata and issuer, creates a PKCE-bound authorization request, and waits for approval. After the scope is granted, the gateway confirms the resource and audience, invokes only the allowlisted read tool, and returns the result. The agent continues with the same task context.
Error path. The server responds with insufficient_scope for a write operation. The gateway records the required scope, pauses the agent, and asks for a step-up approval. If the response has a different issuer, a different resource, or a scope outside policy, the gateway denies the call. If the second request still fails, it returns a stable authorization error and requires an operator to inspect the server configuration.
Use a sanitized event shape like this for operations review:
request_id: req_01H
server_label: read-only-repository-tools
resource_id: canonical-mcp-resource
issuer_id: approved-issuer
scope_requested:
- files:read
scope_granted:
- files:read
tool_name: list_files
approval: granted
outcome: success
credential_redacted: true
The log should answer which server, scope, tool, decision, and outcome were involved. It should never contain an access token, an authorization header, a PKCE verifier, or copied tool arguments that contain secrets. Keep a separate retention policy for these events because tool arguments may include repository paths or issue text even when credentials are removed.
Failure modes
Over-requested initial scopes. Asking for every server scope makes approval opaque and increases the impact of a mistaken grant. Start from the challenge and add permissions only through a named step-up action.
Issuer substitution. A metadata response can point to an issuer that is not on the approved list. Stop before authorization and surface the mismatch. Do not let a model decide that two similarly named issuers are equivalent.
Audience or resource drift. A token issued for one MCP resource must not be reused for another. Compare the canonical resource on every call and reject fragments, aliases, or unexpected path changes.
Unsupported OAuth client. A client may support MCP tools but not remote OAuth. GitHub’s current documentation is an explicit example. Mark the integration unsupported and choose an approved client or server arrangement rather than silently weakening authorization.
Approval bypass. Setting an automatic approval policy for a new server can expose repository content before anyone has reviewed the tool list. Keep approval required for onboarding, then narrow the allowlist before changing the policy.
Scope escalation loops. Some servers may repeatedly return insufficient_scope because their advertised scopes do not match operation requirements. Cap retries, preserve the original request identifier, and fail closed after the first step-up attempt.
Leaky logs. Redacting only the main token field is not enough if headers, query strings, or tool arguments are copied elsewhere. Define a redaction filter for authorization material and test it with failed as well as successful calls.
FAQ
What does step-up authorization mean here?
It means starting with a narrow grant and requesting an additional scope only when the server identifies a concrete missing permission. The new request includes the existing grant plus the challenged scope, so a successful reauthorization does not accidentally remove access the current task already needs.
Should the gateway request every scope listed in metadata?
No. The MCP specification describes the challenge scope as authoritative for the current operation and recommends least-privilege selection. Use the minimal advertised set for basic functionality, then step up for a specific operation.
Can the same policy be used for a local STDIO server?
Not automatically. The current specification distinguishes STDIO from HTTP authorization and recommends retrieving local credentials through the local environment instead. Give local servers their own policy and do not pass a remote server token into a local process.
Is an approval prompt enough to make a remote server safe?
No. Approval gives an operator visibility, but it does not replace issuer, resource, audience, scope, and tool allowlist checks. Keep those checks in the gateway so a model cannot bypass them by choosing a different tool name or retry path.
What if a coding-agent product does not support OAuth remote MCP?
Treat that as a compatibility result. Do not remove scope controls or copy a broad credential into an unsupported configuration. Select a supported integration with an explicit policy, or keep the server unavailable to that agent surface.
Which fields belong in an operations log?
Record a request identifier, server label, canonical resource identifier, issuer identifier, requested and granted scopes, tool name, approval decision, retry count, and outcome. Replace credential material and sensitive arguments with [REDACTED], and keep the log short enough that it can be reviewed without exposing repository contents.
Reader next step
Choose one read-only remote MCP tool and write down its canonical resource identifier, expected issuer, minimum scope, and approved tool name. Configure the gateway with approval required and a one-attempt step-up limit. Run one successful read call, then test an operation that should produce insufficient_scope. Confirm that the error path stops on issuer or resource drift and that the resulting event contains only sanitized fields.
Next, compare the tool manifest and allowlist against the MCP tool manifest guide . When the checks are clear, Start with CometAPI and keep the same scope, approval, and logging contract for every remote MCP server you add.