About Fayda MCP
Fayda MCP is an MCP server published by izzy-Ti in the Blockchain category: a Model Context Protocol (MCP) bridge connecting AI agents to Ethiopia's Fayda National ID (MOSIP eSignet) for zero-trust e-KYC and identity verification.
The repository has 27 stars and 2 forks, with the last commit 3 days ago. Recent commit activity is the strongest signal that reported issues will get attention.
Install
git clone https://github.com/izzy-Ti/fayda-mcpThis server has no ConduID identity, so agent calls to it are not receipted. Pin the version you install and review the source before granting it credentials.
Ask AI
Ask AI about Fayda MCP
Powered by Claude · Grounded in docs
Security checks
Static checks derived from the repository 2 days ago. Heuristics on the source, not an audit.
- ✓README presentThe repository ships documentation.
- ✓License declaredUsable under a stated license.
- ✓Tests presentA test suite exists in the repository.
- ✓Dependencies pinnedA lockfile pins dependency versions.
- !No dynamic code executionSource scan found eval or shell execution. Review how tool inputs reach it before granting credentials.
1 check has not been run yet.
Releases
README
Fayda MCP Python Library (fayda-mcp)
An importable, headless Python library providing Model Context Protocol (MCP) tools and verification services for Ethiopian National ID (Fayda eSignet).
Key Capabilities
- Explicit FastMCP Tools:
- eSignet OIDC:
start_verification,get_verification_status,get_verification_result,cancel_verification. - Citizen Details Matching:
start_details_verification,get_details_match_result. - Offline QR Code:
submit_qr_verification,get_qr_verification_result. - Policy & Health:
list_allowed_checks,list_verification_purposes,check_service_health.
- eSignet OIDC:
- Zero Raw Demographic / Biometric Leaks: Outputs minimal boolean predicates (
identity_verified,age_over_18,credential_signature_valid), strictly forbidding citizen biometrics, OTPs, or demographic dumps from entering LLM contexts. - Offline & Edge Verification: High-density QR verification runs completely offline—requiring no OIDC callback, no webhook, and no client private signing key (only authority public key / trust bundle).
- Physical Credential Security Boundaries: Physical QR scanning validates issuer provenance and credential integrity, but strictly sets
holder_authenticated=falseand never assertsidentity_verifiedwithout live authentication. Copied/screenshotted QR threat model is enforced fail-closed. - Scanner Text First Delivery: Core library accepts raw ASCII scanner text directly from handheld barcode readers and camera SDKs (image scanning is a separate optional adapter).
- Cryptographic Security: OIDC PKCE S256, RFC 7523
private_key_jwtclient assertions, and RFC 7515 Appendix F RS256 detached JWS signature verification. - Pluggable Architecture: Zero mandatory database or web framework runtime dependencies in core; optional extras for FastAPI, Redis, and Neon/PostgreSQL. Redis remains optional for temporary references and rate limits.
- Multi-Tenant Caller Isolation: Built-in tenant and principal boundaries ensuring Caller A cannot access Caller B verification records.
Installation
# Core library (headless FastMCP + Fayda OIDC + Offline QR verification engine)
pip install fayda-mcp
# With optional FastAPI integration
pip install "fayda-mcp[fastapi]"
# Full bundle with Redis and Neon/Postgres adapters
pip install "fayda-mcp[fastapi,redis,postgres]"
Quick Start (Offline QR Verification)
from fayda_mcp import FaydaConfig, FaydaVerificationService
from fayda_mcp.storage.memory import MemoryResultRepository, MemorySessionStore
# 1. Enable QR verification with Fayda authority public key
config = FaydaConfig.sandbox(
client_id="kiosk_qr_verifier",
redirect_uri="https://localhost/unused",
qr_verification_enabled=True,
qr_key_bundle_path="path/to/fayda_qr_keys.pem", # or qr_public_key_pem
)
# 2. Initialize service (memory or database storage)
service = FaydaVerificationService(
config=config,
sessions=MemorySessionStore(),
results=MemoryResultRepository(),
)
# 3. Submit scanned QR text (no network or callbacks needed)
result = await service.submit_qr_verification(
qr_text="<raw_scanner_text_from_physical_card>",
purpose="kyc",
checks=["credential_signature_valid", "age_over_18"],
)
# Returns minimal filtered agent predicates; demographics and photo are excluded!
print(result.checks) # {'credential_signature_valid': True, 'age_over_18': True}
print(result.holder_authenticated) # False (offline scan alone does not prove live presence)
Quick Start (OIDC Sandbox)
import base64
from fayda_mcp import FaydaConfig, FaydaVerificationService
from fayda_mcp.storage.memory import MemorySessionStore, MemoryResultRepository
from fayda_mcp.mcp.factory import create_mcp_server
# Configure your Fayda / eSignet credentials
config = FaydaConfig(
client_id="YOUR_CLIENT_ID",
redirect_uri="http://localhost:3000/callback",
authorization_endpoint="[https://esignet.ida.fayda.et/authorize](https://esignet.ida.fayda.et/authorize)",
token_endpoint="[https://esignet.ida.fayda.et/v1/esignet/oauth/v2/token](https://esignet.ida.fayda.et/v1/esignet/oauth/v2/token)",
userinfo_endpoint="[https://esignet.ida.fayda.et/v1/esignet/oidc/userinfo](https://esignet.ida.fayda.et/v1/esignet/oidc/userinfo)",
issuer="[https://esignet.ida.fayda.et](https://esignet.ida.fayda.et)",
jwks_uri="[https://esignet.ida.fayda.et/v1/esignet/oauth/v2/jwks.json](https://esignet.ida.fayda.et/v1/esignet/oauth/v2/jwks.json)",
private_key=base64.b64decode("YOUR_PRIVATE_KEY_B64").decode("utf-8"),
)
service = FaydaVerificationService(
config=config,
sessions=MemorySessionStore(),
results=MemoryResultRepository(),
)
server = create_mcp_server(service=service)
if __name__ == "__main__":
server.run(transport="stdio")
Quick Start (Citizen Details Matching)
from fayda_mcp import FaydaConfig, FaydaVerificationService
from fayda_mcp.matching.schemas import ExpectedDetails
from fayda_mcp.storage.memory import MemoryResultRepository, MemorySessionStore
# 1. Initialize service with pluggable session and result repositories
service = FaydaVerificationService(
config=FaydaConfig.sandbox(client_id="rp_client", redirect_uri="http://localhost:8000/callback"),
sessions=MemorySessionStore(),
results=MemoryResultRepository(),
)
# 2. Authenticated backend submits citizen expected details (AES-256-GCM encrypted at rest)
sub = await service.submit_expected_details(
application_user_ref="cust_1001",
purpose="onboarding",
expected_details=ExpectedDetails(
full_name="Abebe Bikila",
date_of_birth="1995/04/12",
dob_calendar="gregorian",
),
ttl_seconds=900,
)
# 3. Agent launches verification using the opaque reference token
start = await service.start_details_verification(
expected_details_ref=sub.expected_details_ref,
purpose="onboarding",
application_user_ref="cust_1001",
)
# 4. After citizen authenticates via eSignet callback, query minimal match outcome
result = await service.get_details_match_result(start.request_id)
# Returns tri-state flags; zero raw demographics, DOBs, or tokens leaked!
print(result.matching_status) # "matched" | "mismatched" | "unavailable"
print(result.matches) # {"full_name": True, "date_of_birth": True}
Running the Complete Sandbox Flow
Run the included standalone sandbox walkthrough:
python examples/sandbox_flow.py
This runs the entire end-to-end lifecycle (starts verification -> builds authorization link -> simulates citizen callback -> queries status -> retrieves privacy-preserving boolean result -> verifies caller isolation) without editing library internals.
Examples
- Offline QR Verification: examples/qr_verification.py (Standalone scanner text verification, minimal agent output, copied QR handling)
- Local Standard I/O (stdio): examples/stdio_server.py (Desktop LLM clients, Claude Desktop, Cursor)
- Remote HTTP Server: examples/remote_http_server.py (Hosted streamable-HTTP / SSE MCP endpoints with FastAPI)
- Full Sandbox Walkthrough: examples/sandbox_flow.py
Documentation
- Ethiopian Name Matching Specification (ethiopian_name_v1)
- Citizen Details Matching Specification (details-v1)
- Production, Compatibility & Operations Guide
- QR Credential Profile Specification
- QR Signed Content & Byte Rules
- QR Trusted Keys & Lifecycle Specification
- Architecture & Responsibilities
- Configuration Guide & Environment Variables
- Callback Wiring & Session Binding
- Credential Ownership & Cryptography
- Cleanup & Lifecycle Management
- Database Migrations
- Redis Session Storage
- Retention Policy
License
MIT License. See LICENSE for details.
README fetched from the repository 2 days ago. The original is authoritative.