-
Notifications
You must be signed in to change notification settings - Fork 11
Description
Author: @tulshi
Status: Draft
Type: Feature Proposal
Created: 2026-02-06
Abstract
COAZ (pronounced “cozy”) stands for “Compatible with OpenID AuthZen”. This SEP introduces coazMapping, an extension to the MCP Tool definition's inputSchema. It provides a standardized way to map tool arguments and session tokens to the OpenID AuthZEN Subject-Action-Resource-Context (SARC) model. This enables MCP clients and proxies to perform fine-grained, parameter-level authorization checks before executing tools.
Motivation
MCP servers offer tools to MCP clients (aka agents). Tools are described in the response to the tools/list call of the MCP server. For each tool listed, the MCP server includes an inputSchema field. The value of this field is a JSON schema object that describes the input required by this tool. The MCP client then calls the tool and provides parameters in accordance with the input schema.
Authorization in MCP relies on OAuth 2.1. However, there are a couple of concerns that are left unaddressed by it:
- The OAuth token is issued to the agent, which may be acting either autonomously on behalf of a human user who might not be present, or with a “human user in the loop”. If the token is issued with the agent identity as the principal, then one needs to figure out how to capture the user identity on whose behalf the tool is being invoked.
- The OAuth token may have specific scopes that limit what the user or the agent can do. However, depending on the user on whose behalf the agent is acting, and what that user is currently authorized to access, the actual set of resources that may be permitted in a specific call may be limited. There is no way to capture that using just scopes.
Implementing dynamic, fine-grained authorization
In order to achieve dynamic, fine-grained authorization in MCP, we need the following in addition to the OAuth capabilities already present, we need to be able to:
- Verify the agent as well as the user on whose behalf the agent is acting, for each MCP server tool call the agent makes.
- Determine the specific resources each tool call results in.
- Determine the context of each tool call.
The AuthZen API is able to provide dynamic, fine-grained authorization, but the API requires specific parameters. The purpose of this proposal is therefore to:
- Declare whether a tool is AuthZen compatible or not, and
- If a tool is AuthZen compatible, how does it map its input to the parameters required by AuthZen.
Architecture
Once a tool is declared as being AuthZen compatible, when the tool is called, an intermediate MCP gateway, or the MCP server itself calls the AuthZen PDP. The caller uses the specified mapping to determine the AuthZen API parameter values from the tool call.
It is also possible for the MCP client to call the AuthZEN PDP before making the tool call, but since the MCP Client may not be trusted by the MCP server, doing so may not prevent the MCP server from calling the PDP again.
Relationship to Existing Proposals
This SEP acknowledges and complements ext-auth Issue #14: OpenID AuthZEN Integration for Fine-Grained Authorization.
Issue #14 establishes the mechanism for how an AuthZen PDP may be called within an MCP client and server interaction. This SEP offers a way to map the parameters of the MCP tool invocation to the parameters required by the AuthZen API.
Proposal
Declaring support for AuthZen
MCP servers may advertise certain tools they support as being AuthZen compatible by including a field named coaz (i.e., Compatible with OpenID AuthZen) in the object representing a tool in the response to tools/list. When Server Cards become available in MCP, this field may be included in the tool object in the server card. The value of this field MUST be set to true to indicate support for AuthZen.
For example:
"tools": [
{
"name": "get_weather",
"coaz": true,
"title": "Weather Information Provider"
//...
},
{
"name": "get_local_weather",
"title": "Get local area weather"
// rest of the tool object, not including a "coaz" field.
}
],In the above example, the get_weather tool is AuthZen compatible (because it has the coaz field set to true), but the get_local_weather tool is not AuthZen compatible, because it does not include a coaz field.
COAZ tool input schema
The AuthZen API expects the following parameters in each call:
- Subject: Required. Is the user for whom the access is requested. If an AI agent is operating autonomously, then this need not be the identity to whom the access token is issued. It might be captured in a parameter that describes the user on whose behalf the agent is acting.
- Action: Required. This is the tool name, or some 1:1 mapping of the tool name that is meaningful to the PDP.
- Resource: Required. This is the resource that is being requested to be accessed as a part of invoking this tool. Note that this Resource is not the same as a Resource declared by the MCP server.
- Context: Optional. Any additional data that can help the PDP make an access decision. For autonomous use-cases, the context MUST be present and it MUST include the identity of the agent.
So to map elements from a JWT formatted authorization token, or the tool description, the following is proposed for coaz tools. In this proposal, the values of the fields can contain the following variables:
$.properties: Refers to thepropertiesfield of theinputSchemaof thetoolsobject.$.token: Refers to the JWT formatted OAuth token used to authorize the tool call
Fields within these variables MUST be referred to using JSONPath.
The following field is proposed to be added to the inputSchema object for coaz tools:
- An
x-coaz-mappingobject MUST be included in theinputSchemaobject. Its value is a JSON object that has the following fields:resource: Required. Describes theresourceparameter of the AuthZen APIsubject: Required. Describes thesubjectparameter of the AuthZen APIcontext: Required. Describes thecontextparameter of the AuthZen APIaction: Optional. Describes theactionparameter of the AuthZen API. If this is missing then the PEP MUST construct a JSON object containing a single field namedname, whose value is the tool name.
Note that at least one field of the subject or context parameters MUST be derived from the $token variable.
Schema
The schema of the x-coaz-mapping object is as follows:
interface CoazMapping {
resource: object;
subject: object;
context: object;
action?: object;
}Example
The following is an example of a tool description of a coaz tool:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [{
"name": "get_customer",
"coaz": true,
"description": "Get customer details",
"inputSchema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "The customer identifier"
},
"case": {
"type": "string",
"description": "The case that is being worked on by the agent"
}
},
"x-coaz-mapping": {
"resource": {"id": "$.properties['id']", "type": "customer"},
"subject": {"type": "user", "id": "$.token['sub']"},
"context": {"agent": "$.token['aud']", "case": "$.properties['case']"}
}
}
}]
}
}In the above example, the x-coaz-mapping does not specify an action, which means that the action name in the AuthZen API call will be the tool name. The example assumes that the access token is an OIDC ID Token, so the context value is derived from the aud value of the token, because it will have the client identity in the aud claim of the ID Token.
Error handling
The AuthZen PDP may respond with a “deny” result to a request. In that case, the PEP (the MCP gateway or the MCP server) MUST respond with an appropriate error status and message to the MCP client. This SEP proposes to use the error code number -32401 as the Unauthorized error status code for JSON-RPC. The status message in the response MAY be copied from the OpenID AuthZen message field in the error response. So an example error response is as follows:
{
"jsonrpc": "2.0",
"id": 789, // some identifier
"error": {
"code": -32401,
"message": "(Copied from the AuthZen response)"
}
}Rationale
The primary wins from this SEP are:
- Externalization: Decouples security logic from business logic.
- Zero-Trust for Agents: Distinguishes between the human (Subject) and the AI agent (Context).
- AuthZEN Alignment: Leverages a ratified OpenID standard rather than creating a proprietary MCP-specific authorization language.
Addressing Protocol Bloat
A common concern for MCP extensions is the introduction of "vendor-specific" or "over-engineered" schemas. This proposal mitigates bloat in three ways:
- Opt-in Complexity: The
coazMappingfield is entirely optional. Minimalist servers that do not require fine-grained authorization (FGA) are not forced to implement or even understand the schema. - Leveraging Standards: Rather than inventing an MCP-specific authorization DSL, we utilize OpenID AuthZEN 1.0. This allows the protocol to remain "security-neutral" by deferring the heavy lifting to external, purpose-built policy engines.
- Standardized Semantic Mapping: Currently, developers are already embedding security logic in their tool handlers. By formalizing this mapping, we replace fragmented, non-standard code with a declarative schema that is machine-readable by gateways and proxies.
Acknowledgements
Thanks to Martin Besozzi for their SEP: “OpenID AuthZEN Integration for Fine-Grained Authorization” (Issue #14), which started my thought process in this direction.