-
Notifications
You must be signed in to change notification settings - Fork 26
Description
Author: @embesozzi
Status: Draft
Classification: Discussion / Feature Proposal
Date: 2026-03-19
Abstract
This proposal explores a pattern for enabling Just-In-Time (JIT) authorization in MCP agents without browser redirects, by combining:
- OAuth 2.0 First-Party Apps (FiPA): an IETF draft defining a challenge/response authorization protocol for applications trusted by the authorization server operator.
- Structured Elicitation: an agent-readable metadata format (following the MCP
elicitation/createstructure) that binds FiPA challenge steps directly to MCP Elicitation JSON-RPC calls.
The core idea is a binding where OAuth authorization challenges are expressed as MCP elicitation/create calls. This allows MCP clients (agents) to collect user input inline and complete multi-step authentication flows entirely within the agent runtime.
In this model, the MCP Server acts as a trusted first-party client, mediating the authorization flow with the Authorization Server, while the agent serves only as a UI surface for Human-to-Agent (H2A) interaction.
Motivation
Current MCP OAuth 2.1 flows rely on browser redirects for token acquisition. This creates limitations in native agent environments (e.g., CLI, IDE):
- No native JIT authorization primitive: Step-up or JIT auth forces users out to a browser, breaking CLI/IDE continuity.
- No agent-readable challenge metadata: FiPA defines the wire protocol but not a structured format agent runtimes can map to user prompts.
- No binding to MCP Elicitation: There is no defined mapping between OAuth challenge responses and
elicitation/createcalls.
Core Concepts
First-Party MCP Server
A First-Party MCP Server is an MCP Server that is explicitly registered as a first-party client with the Authorization Server.
- The Authorization Server trusts the MCP Server to mediate authentication challenges.
- The agent is not trusted and only acts as a user interaction surface.
- The trust boundary is therefore between the MCP Server and the Authorization Server, not the agent.
This constraint is required for safely enabling inline authentication flows.
Proposed Binding
Note: The following describes the author's draft proposal (
draft-embesozzi-oauth-fipa-agent-elicitation), not a standardized specification. It is presented here to illustrate the concept and invite feedback.
The binding is triggered when the MCP Server, based on its authorization policies, determines that a Just-In-Time (JIT) authorization step is required before executing a sensitive tool. At that point, the MCP Server — acting as the registered first-party FiPA client — initiates an Authorization Challenge Request to the AS on behalf of the current operation.
When an Authorization Server returns an insufficient_authorization error (per FiPA), the proposed extension adds an elicitations array to the response. Each entry maps directly to an MCP elicitation/create call:
AS Challenge Response:
{
"error": "insufficient_authorization",
"auth_session": "sess_abc123",
"elicitations": [
{
"mode": "form",
"message": "Enter the 6-digit code from your Authenticator App.",
"requestedSchema": {
"type": "object",
"properties": {
"otp": { "type": "string", "minLength": 6, "maxLength": 6 }
},
"required": ["otp"]
}
}
]
}MCP Server issues elicitation/create to the MCP Client with the same params, collects user input, then responds to the AS:
{ "auth_session": "sess_abc123", "response": { "otp": "847291" } }Two elicitation modes are supported: form (inline JSON Schema-driven input) and url (out-of-band browser/webview, used as fallback for third-party agents).
H2A Flow
sequenceDiagram
participant Human
participant Agent as MCP Client (Agent)
participant MCP as MCP Server (First-Party FiPA Client)
participant AS as Authorization Server
Human->>Agent: Invokes tool request
Agent->>MCP: tools/call
MCP->>AS: Authorization Challenge Request
AS-->>MCP: insufficient_authorization + auth_session + elicitations[]
loop Each challenge step
MCP->>Agent: elicitation/create
Agent->>Human: Native prompt
Human-->>Agent: Input
Agent-->>MCP: elicitation result
MCP->>AS: Challenge response (auth_session + response)
AS-->>MCP: Next challenge OR authorization_code
end
MCP->>AS: Token Request
AS-->>MCP: Access Token
MCP->>MCP: Execute tool (Bearer token held by MCP Server)
MCP-->>Agent: Tool response
Agent-->>Human: Result
Security Considerations
- First-party boundary: These flows MUST only be used by first-party MCP Servers. The AS MUST enforce this via client registration metadata, the first-party trust boundary is at the MCP Server, not the agent.
- Phishing resistance: First-party MCP Servers may invoke native WebAuthn APIs.
- H2A scope only: This pattern requires a human present to respond. It does not apply to A2A or autonomous agent scenarios.
Working Implementation
A proof-of-concept has been validated with Claude Code and GitHub Copilot CLI.
In the demo:
- An agent attempts a protected operation
- The MCP Server triggers a JIT authorization challenge
- The user completes authentication inline in the CLI
- The Authorization Server issues an updated token
- The operation proceeds
claude-jit-authz.mp4
Open Questions
-
Is native JIT authorization for first-party MCP servers in scope for ext-auth, or should it live in the modelcontextprotocol repo? Please let me know where this is best discussed.
-
Extending MCP Elicitation beyond input collection:
The currentelicitation/createmethod is designed for collecting user-provided input, either via JSON Schema-driven forms or URL-based flows.
This proposal raises the question of whether elicitation should also support invoking user authentication actions, not just collecting values.
Specifically, should the elicitation format be extended to include execution hints — read-only metadata that instructs the MCP client to trigger a native platform capability, instead of prompting for typed input?
Examples include:
- Triggering a passkey / WebAuthn authentication flow
- Invoking OS-level biometric authentication
- Using hardware-backed credentials (e.g., security keys)
Here is an example of device-bound passkey (security key) authentication, where Claude Code triggers JIT authorization via client-side hooks.
passkeys-jit-v2.mp4
References
- draft-ietf-oauth-first-party-apps — OAuth 2.0 First-Party Apps (IETF Draft)
- draft-embesozzi-oauth-fipa-agent-elicitation — Author's Structured Elicitation binding proposal (not yet standardized, just for reference)
- MCP Elicitation