mcp-oidc4vci
Summary: This MCP server lets an AI agent inspect OIDC4VCI Credential Offers, discover issuer metadata, plan and run an issuance session, and drive credential issuance while keeping keys and credential contents behind a wallet boundary.
Inspect a Credential Offer (
inspect_credential_offer): resolve an offer by value or by reference and get its Credential Issuer, requested credential configuration IDs, and grants.Discover issuer metadata (
get_credential_issuer_metadata): fetch/validate the issuer's well-known metadata, returning the credential endpoint, authorization servers, and supported credential configurations.Explain the issuance flow (
describe_issuance_flow): resolve an offer and describe which grant applies and the ordered steps to obtain the credential(s).Start a session (
initiate_issuance): begin an issuance session (optionaltx_codefor offers requiring a transaction code); pre-authorized code grant completes the token exchange, authorization code grant leaves the session waiting for user authorization.Check session state (
get_issuance_status): return the current state of a previously started session.Request the credential (
request_credential): for a session with an access token, generate a proof via the wallet adapter (the server never signs) and hand the issued credential to the wallet without exposing its contents to the agent.
Note: the schema exposes only these 6 tools, whereas the README describes additional ones (e.g. begin_authorization, submit_authorization_result, poll_deferred_credential, request_wallet_proof/submit_wallet_proof, send_credential_notification).
Provides an agent-facing orchestration layer for OpenID for Verifiable Credential Issuance (OIDC4VCI) flows, enabling inspection of credential offers, discovery of credential issuer metadata, and initiation and tracking of credential issuance while keeping wallet-sensitive operations separate.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-oidc4vci Inspect this credential offer and explain what it's asking for."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
MCP-OIDC4VCI
AI-Assisted Verifiable Credential Issuance using MCP
This project explores how the Model Context Protocol (MCP) can be used to expose capabilities from an OpenID for Verifiable Credential Issuance (OIDC4VCI) ecosystem to an AI agent. It targets OIDC4VCI 1.0 (final specification).
The goal is not to replace a wallet, nor to give an LLM access to private keys or unrestricted credentials. Instead, the project investigates a more constrained architecture:
An MCP server acts as an agent-facing orchestration layer for understanding and progressing through an OIDC4VCI credential issuance flow, while security-sensitive operations remain under the control of dedicated components such as the wallet or credential holder.
The project starts from a concrete scenario:
A user receives an OIDC4VCI Credential Offer and wants an AI agent to help understand what is being offered and guide or orchestrate the issuance process.
Motivation
OIDC4VCI defines a protocol for issuing Verifiable Credentials to a wallet or credential holder. A typical flow involves a Credential Offer, a Credential Issuer and its metadata, an Authorization Server, authorization or pre-authorized flows, credential requests, proofs and cryptographic key binding, and credential delivery and storage — a significant amount of structured information for a user to parse on their own.
An AI agent can potentially help by understanding a credential offer, explaining what's being offered, discovering supported credential configurations, determining the required issuance flow, identifying what's needed next, and orchestrating non-sensitive protocol interactions.
The central question this project explores is:
How can OIDC4VCI capabilities be exposed to an AI agent through MCP without compromising the security boundaries of wallets and cryptographic key material?
For the full system design, see Architecture.
Building or operating a wallet and want to offer issuance without implementing OIDC4VCI yourself? See the Wallet Integration Guide — nothing about using this server that way requires an AI agent in the loop; any MCP client, including a plain deterministic orchestrator, can drive these tools.
Related MCP server: Cheqd MCP Toolkit
Architecture at a glance
AI Agent ──MCP──▶ OIDC4VCI MCP Server ──▶ Credential Issuer / Authorization Server
│
▼
Wallet Boundary
│
▼
Key Management / Proofs / User AuthorizationThe MCP server acts as an intermediary between the AI agent and the OIDC4VCI ecosystem — it should not automatically become a wallet. Sensitive operations (keys, proofs, consent) stay behind an explicit wallet boundary, never in the LLM context.
Full details, component responsibilities, data flows, tool contracts, and security requirements live in docs/ARCHITECTURE.md.
Feature support
Feature | Status |
Credential Offer, by value or by reference | Supported |
Pre-Authorized Code Grant | Supported |
Authorization Code Grant | Supported |
PKCE (RFC 7636, | Supported |
Pushed Authorization Requests (RFC 9126) | Supported, auto-detected from Authorization Server metadata |
DPoP (RFC 9449) | Supported, auto-detected from Authorization Server metadata |
Rich Authorization Requests / | Supported, replaced by a |
Transaction Code ( | Supported |
Nonce Endpoint / | Supported |
| Supported |
| Not yet |
Deferred Credential Issuance | Supported |
Multiple credential configurations per offer | Supported — one Credential Request per configuration, one per tool call |
Signed (JWT) Credential Issuer Metadata | Supported — signature verified against the |
Credential Request/Response Encryption | Not yet |
Batch Credential Issuance | Not yet |
Notification Endpoint | Supported — one scalar |
See docs/ARCHITECTURE.md for the design reasoning behind each of these.
Current capabilities
This project is under active development. Here's what's implemented today.
Credential Offer inspection. inspect_credential_offer resolves a Credential Offer by value or by reference (credential_offer_uri), validates it against OIDC4VCI 1.0, and returns the issuer, requested credential configuration IDs, and grants. See src/mcp_oidc4vci/credential_offer.py.
Credential Issuer metadata discovery. get_credential_issuer_metadata fetches and validates a Credential Issuer's metadata from its well-known endpoint (correctly inserting the well-known path segment ahead of any path component in the issuer identifier, per spec), verifies the returned credential_issuer matches what was requested, and returns the credential endpoint, authorization servers, and supported credential configurations. It transparently handles either the unsigned JSON or the signed-JWT metadata representation (RFC 7515), verifying the JWS signature against the x5c certificate conveyed in the JOSE header — see Architecture for exactly what "verified" does and doesn't mean here (no certificate chain-of-trust validation is performed). See src/mcp_oidc4vci/credential_issuer_metadata.py.
Issuance flow orchestration. describe_issuance_flow, initiate_issuance, and get_issuance_status run on top of an in-memory IssuanceSessionStore. For the pre-authorized code grant, initiate_issuance completes the full Token Request end to end — OAuth Authorization Server discovery via RFC 8414, then the token exchange, including a DPoP proof of possession when the Authorization Server requires one. For the authorization code grant, it resolves the Authorization Server's metadata and leaves the session ready for begin_authorization. See src/mcp_oidc4vci/issuance.py, src/mcp_oidc4vci/authorization_server_metadata.py, src/mcp_oidc4vci/token_request.py, and src/mcp_oidc4vci/dpop.py.
Authorization code grant. begin_authorization builds the Authorization Request URL (PKCE, RFC 7636, S256; authorization_details naming the requested credential configurations, RFC 9396 — replaced by each configuration's own scope, when one is available, for an Authorization Server that doesn't support Rich Authorization Requests) for a human to open and complete — pushing its parameters first via Pushed Authorization Requests when the Authorization Server requires it, transparently to the caller — and submit_authorization_result exchanges the resulting code/state for an access token, rejecting a mismatched state before ever making a Token Request. This server has no HTTP endpoint of its own to receive the browser redirect, so the code/state are supplied back explicitly rather than captured automatically — see Architecture for why. Both grants converge on the same ready_for_credential_request state from here. See src/mcp_oidc4vci/authorization_request.py, src/mcp_oidc4vci/pushed_authorization_request.py, and src/mcp_oidc4vci/pkce.py.
Wallet boundary. WalletAdapter (a Protocol with generate_proof and receive_credential) backs request_credential, which completes a Credential Request for a ready_for_credential_request session: fetch issuer metadata, get a fresh nonce if the issuer needs one, ask the wallet for a signed proof (a real EC-signed openid4vci-proof+jwt, never signed by this server), send it — DPoP-bound if the session's access token is — and hand the issued credential to the wallet, whose contents never reach the agent. The spec's Credential Request only ever names one credential configuration, so an offer requesting several gets one Request per configuration: request_credential handles one per call and returns to ready_for_credential_request (not completed) while more remain, for the caller to call it again. If the issuer defers issuance instead of responding immediately, the session moves to awaiting_deferred_credential and poll_deferred_credential checks back later, reusing the same authentication, response handling, and one-at-a-time rule. The bundled MockWalletAdapter makes both grants work end to end for local testing. See src/mcp_oidc4vci/wallet.py, src/mcp_oidc4vci/credential_request.py, and src/mcp_oidc4vci/nonce.py.
Manual wallet handoff. request_wallet_proof / submit_wallet_proof split the Credential Request into two tool calls for when the proof must come from something other than the in-process MockWalletAdapter — a real wallet, or a human signing by hand — without needing any blocking-wait or webhook machinery: the handoff happens through the session, the same way initiate_issuance → get_issuance_status already does. request_credential (the automatic path) is unchanged and still there for fast, fully-automated testing. See Architecture for the design reasoning.
Notification Endpoint. send_credential_notification reports a previously issued credential's outcome (credential_accepted, credential_failure, or credential_deleted) back to the Credential Issuer, using the notification_id a prior Credential Response or Deferred Credential Response carried — authenticated with the same Bearer/DPoP access token, never a new Token Request. Both sending a notification (the Wallet's side) and the issuer supporting this endpoint at all are optional per spec, so "nothing to notify about yet" and "this issuer doesn't support notifications" are reported as clear errors rather than silently ignored — but neither one, nor a rejected notification, ever fails the session: this is a side-channel courtesy to the issuer, not a step in the issuance flow. See Architecture for the scalar notification_id scope limit on multi-configuration sessions. See src/mcp_oidc4vci/notification.py and src/mcp_oidc4vci/session_request.py (the Bearer/DPoP-with-nonce-retry POST helper shared with request_credential).
Shared data models live in src/mcp_oidc4vci/models.py, with tests in tests/ (99% coverage, 305 tests).
Tech Stack
Python — implementation language.
uv — dependency management, virtual environments, and running the project.
FastMCP — high-level Python framework for building the MCP server and its tools.
MCP Python SDK — the underlying official protocol SDK that FastMCP builds on.
MCP Inspector — interactive tool for testing and debugging the MCP server's tools during development.
Getting Started
# Install uv if you don't have it
curl -LsSf https://astral.sh/uv/install.sh | sh
# Install dependencies
uv sync
# Run the MCP server through the MCP Inspector for interactive testing
uv run fastmcp dev inspector src/mcp_oidc4vci/server.py:mcp
# Lint, type-check, and run the test suite
uv run ruff check .
uv run mypy src
uv run pytestTesting the manual wallet-proof path without a real wallet
scripts/sign_proof.py signs a spec-shaped proof JWT the same way MockWalletAdapter does, but as a separate process — useful for exercising request_wallet_proof / submit_wallet_proof (see Architecture) when there's no real wallet app on hand:
uv run scripts/sign_proof.py --audience https://issuer.example.com --nonce abc123Pass its output straight to submit_wallet_proof's proof_jwt argument.
Testing the authorization code grant
This server has no HTTP endpoint of its own to receive a browser redirect (see Architecture), so completing this grant needs a real Authorization Server, a client_id/redirect_uri registered with it, and a browser: call begin_authorization, open the returned authorization_url, authenticate, and copy the code/state query parameters from wherever the browser lands after the redirect into submit_authorization_result.
Documentation
Architecture — components, design principles, wallet boundary, data flow, MCP tool contracts, security requirements.
Wallet Integration Guide — for a team integrating their own wallet against this server instead of implementing OIDC4VCI issuance themselves: the two supported integration shapes, the full tool catalog, the session state machine, and current limitations to check against your target issuer(s).
Roadmap — delivery phases, MVP scope, and what's explicitly out of scope.
Available Tools
6 toolsdescribe_issuance_flowB
Describe the steps required to obtain the credential(s) offered by a Credential Offer.
Resolves the offer and returns which grant-based flow applies and its ordered steps.
Inputs: credential_offer (required). Returns: object
get_credential_issuer_metadataA
Fetch and validate a Credential Issuer's metadata from its well-known endpoint.
Returns the issuer's credential endpoint, authorization servers, and the credential configurations it supports.
Inputs: credential_issuer (required). Returns: object
get_issuance_statusB
Return the current state of a previously started issuance session.
Inputs: session_id (required). Returns: object
initiate_issuanceA
Start an issuance session for a Credential Offer.
For the pre-authorized code grant, completes the token exchange immediately and the
session ends ready_for_credential_request or failed. For the authorization code
grant, the session is left waiting_for_user_authorization, since completing it requires
a wallet-driven redirect not yet implemented. tx_code is the transaction code obtained
from the user out-of-band, if the offer requires one.
Inputs: credential_offer (required), tx_code. Returns: object
inspect_credential_offerA
Parse and validate an OIDC4VCI Credential Offer URI.
Resolves the offer (by value or by reference) and returns its Credential Issuer, requested credential configuration IDs, and available grants.
Inputs: credential_offer (required). Returns: object
request_credentialA
Complete the Credential Request for a session that has an access token.
Generates a key proof of possession through the wallet adapter — this server never signs anything itself — and hands the issued credential to the wallet for safekeeping. Its contents are never returned to the agent.
Inputs: session_id (required). Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 6 tools
Each tool targets a distinct phase of the OIDC4VCI flow, but inspect_credential_offer and describe_issuance_flow both resolve an offer and could be confused by an agent deciding whether to inspect contents or get next steps. The remaining tools have clearly separate boundaries.
All six tools use a consistent snake_case verb_noun pattern, e.g. get_, inspect_, describe_, initiate_, and request_. There is no casing or verb-style mixing, making the set highly predictable.
Six tools is well-scoped for an OIDC4VCI issuance server, covering offer inspection, metadata, flow analysis, initiation, status, and credential request. Each tool earns its place with no redundant or superfluous additions.
The toolset covers the pre-authorized code issuance path well, but the authorization-code grant is left in waiting_for_user_authorization with no tool to complete the user-authorization redirect or exchange the authorization code. This is a notable dead end for standard OIDC4VCI authorization-code flows.
Maintenance
Related MCP Connectors
Verifiable agent DIDs + capability discovery — the passport & directory of the A2A economy.
Neutral W3C DID/VC identity and reputation oracle for AI agents (did:key/did:web, eddsa-jcs-2022).
Command your AI agents: verifiable passports, credential injection, full audit, revoke in 60s.
W3C DID issuance and verification for autonomous AI agents
Related MCP Servers
- AlicenseNot gradedqualityNot gradedmaintenanceEnables AI agents to securely use Open Agent ID credentials for signing requests, looking up agent data, and exchanging encrypted messages. It performs all cryptographic operations within the server process to ensure private keys are never exposed to the AI agent.Apache 2.0

Cheqd MCP Toolkitofficial
AlicenseNot gradedqualityCmaintenanceEnables AI agents to securely manage decentralized identities, verifiable credentials, and trust registries on the Cheqd network via the Model Context Protocol.1Apache 2.0- AlicenseNot gradedqualityDmaintenanceProvides AI agents with a DID-based identity, secure wallet, and cloud KMS-backed signing keys, enabling trusted interactions with persons, companies, and other agents via standards like OIDC4VCI, OIDC4VP, and SD-JWT.Apache 2.0
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to seal, open, verify, and ingest verifiable agri-traceability data by description, with credentials and private keys kept out of the model's flow.16 npmMIT