MCP Authorization Server
The MCP Authorization Server positions Mandaitor at the enforcement boundary where AI agents actually execute actions. When an agent attempts to use a tool via the Model Context Protocol (MCP), the authorization server verifies the agent's mandate before granting access, ensuring that every tool call is explicitly authorized.
How It Works
The MCP Authorization Server implements the OAuth 2.0 client_credentials grant with private_key_jwt authentication. An agent authenticates using its DID and key material from the Agent Identity Registry, receives a scoped access token, and then presents that token when requesting tool call authorization.
Server Metadata Discovery
The server publishes its metadata at the standard OAuth well-known endpoint:
GET /.well-known/oauth-authorization-server
This returns the token endpoint, supported grant types, authentication methods, and MCP-specific metadata such as supported tool namespaces and enforcement mode.
Token Exchange
Agents authenticate using their DID as the client_id and a signed JWT as the client_assertion:
const tokenResponse = await fetch("https://api.mandaitor.io/v1/mcp/token", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
grant_type: "client_credentials",
client_id: "did:mandaitor:tnt_abc:agt_01HXYZ",
client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
client_assertion: signedJwt,
scope: "mandate:mdt_abc123",
}),
});
The response includes an access token scoped to the agent's bound mandates.
Tool Call Authorization
With a valid access token, the agent requests authorization for specific tool calls:
const authzResponse = await fetch("https://api.mandaitor.io/v1/mcp/authorize", {
method: "POST",
headers: {
"Authorization": `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
tool_name: "database_query",
parameters: {
query: "SELECT * FROM projects WHERE status = 'active'",
},
}),
});
The authorization server evaluates the tool call against all mandates in the session scope. If authorized, the response includes a lightweight Proof-of-Mandate token that the tool server can verify. The response also carries the mcp-runtime-trace/v2 evidence material used by the Runtime Assurance Loop.
Runtime Trace and Assurance Binding
Every authorization response is normalized as a runtime trace so downstream systems can prove that the tool call was bound to an active mandate, a Proof-of-Mandate artifact, and a Verifiable Intent L3 transaction trace. The authorization decision remains mandate-driven; runtime-assurance fields add observability and evidence, not a second enforcement path.
| Field | Meaning |
|---|---|
event_id | Stable authorization event identifier used by audit, Ops ingestion, and dashboard drill-down. |
agent_id / agent_did | Authenticated autonomous actor that requested the tool call. |
mandate_id | Active mandate that authorized the mapped action and resource. |
mapped_action / mapped_resource | Policy-derived mandate scope evaluated for the tool call. |
pom_bound | Indicates that a Proof-of-Mandate artifact was issued or bound to the authorization decision. |
vi_layer_type | Runtime transaction trace layer; Sprint 4 emits L3 material for tool authorization events. |
verification_event_id | Event reference used to correlate the MCP authorization with verification and evidence pipelines. |
drift_score / drift_detected / drift_threshold | Advisory drift posture calculated over the active session window. |
drift_dimensions | Normalized advisory component scores for semantic distance, sequence deviation, frequency anomaly, and scope expansion. |
drift_session_id / drift_window_start / drift_window_end / drift_session_action_count | Sliding drift-window binding that proves which session state was used for the advisory score. |
semantic_signals | Structured semantic signal payload returned for audit and Ops evidence ingestion when drift scoring succeeds. |
vi_l3_claims | Transaction-level Verifiable Intent material, including claim type, mandate, verification event, decision, and L2 binding. |
A typical successful response contains both the authorization decision and trace material:
{
"decision": "ALLOW",
"event_id": "evt_runtime_authorization_fixture",
"mandate_id": "mdt_runtime_fixture",
"pom_token": "eyJ...",
"runtime_trace": {
"contract_version": "mcp-runtime-trace/v2",
"agent_id": "agt_runtime_fixture",
"agent_did": "did:web:api.mandaitor.io:agents:agt_runtime_fixture",
"mapped_action": "authorization.execute",
"mapped_resource": "runtime:evidence/*",
"pom_bound": true,
"vi_layer_type": "L3A",
"verification_event_id": "evt_runtime_authorization_fixture",
"drift_score": 0.12,
"drift_detected": false,
"drift_threshold": 0.7,
"drift_dimensions": {
"semantic_distance": 0.08,
"sequence_deviation": 0.1,
"frequency_anomaly": 0.12,
"scope_expansion": 0.18
},
"drift_session_id": "TENANT#tnt_runtime_fixture#MDT#mdt_runtime_fixture",
"drift_window_start": "2026-05-08T15:00:00.000Z",
"drift_window_end": "2026-05-08T16:00:00.000Z",
"drift_session_action_count": 1,
"semantic_signals": {
"drift_score": {
"aggregate": 0.12,
"drift_detected": false
}
},
"vi_l3_claims": {
"vct": "urn:mandaitor:vi:l3",
"mandate_id": "mdt_runtime_fixture",
"verification_event_id": "evt_runtime_authorization_fixture",
"decision": "ALLOW",
"l2_binding": "mandate:mdt_runtime_fixture:session:sess_runtime_fixture"
}
}
}
Drift collection is fail-open at the runtime boundary. If a drift session cannot be read or scored, Mandaitor still returns the mandate authorization decision and marks the trace as missing advisory drift material. Ops publication is deliberately stricter: generated trust data is fail-closed when required runtime-trace fields are incomplete, malformed, inconsistent with the event ID or mandate ID, or outside the expected normalized score range.
Authorization Policy
The default policy maps tool calls to mandate actions using pattern matching. Tenants can configure custom policies to define granular mappings between MCP tool names and mandate scope:
| Field | Description |
|---|---|
tool_pattern | Glob pattern matching tool names (e.g., database_*) |
mandate_action | Required mandate action (e.g., data.read) |
mandate_resource | Required mandate resource pattern |
default_decision | Decision when no mapping matches (default: DENY) |
drift_escalation_threshold | Drift score above which to escalate (default: 0.7) |
Session Management
Each token exchange creates a session that tracks tool call history. Sessions can be inspected via:
GET /mcp/sessions/{id}
This returns the session metadata including the agent, bound mandates, tool call count, and creation timestamp.
The MCP Authorization Server is currently in Beta. The core token exchange and authorization flow is stable, while policy configuration and advisory drift scoring may evolve. Runtime-trace evidence follows mcp-runtime-trace/v2 and is documented in the Runtime Assurance Loop.