Didit MCP Server

MCP serverMonitoring & ops

KYC, KYB, AML, wallet screening, transaction monitoring, and fraud workflows for AI agents.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use Didit MCP Server

From the project's README

As published by didit-protocol/mcp in README.md.

The official Model Context Protocol server for Didit — bring KYC, KYB, AML screening, transaction monitoring, biometrics, and full workspace operations to Claude, Cursor, VS Code, Windsurf, Zed, and any MCP client.

  • 130+ tools across sessions, workflows, vendor users/businesses, transactions, the standalone verification APIs, lists, cases, reports, webhooks, and billing.
  • Auth is "Log in with Didit" (OAuth 2.1 + PKCE) — the MCP acts as the signed-in user with their role's permissions. There is no API-key mode: every tool calls the user-scoped console endpoints, which only accept a Bearer token.
  • Every tool calls a single Didit REST endpoint and returns the JSON verbatim.

Full documentation: https://docs.didit.me/integration/mcp/overview

Quick start

Hosted (recommended)

No install, no API key — point your client at the hosted URL and sign in via the browser:

https://mcp.didit.me/mcp

Claude Code

claude mcp add --transport http didit https://mcp.didit.me/mcp

Cursor (~/.cursor/mcp.json)

{ "mcpServers": { "didit": { "url": "https://mcp.didit.me/mcp" } } }

Windsurf / Zed (via the mcp-remote bridge)

{ "mcpServers": { "didit": { "command": "npx", "args": ["-y", "mcp-remote@latest", "https://mcp.didit.me/mcp"] } } }

See per-client setup for Claude Desktop and VS Code.

Authentication

The MCP is an OAuth 2.1 resource server; the Didit console (business.didit.me) is the authorization server. On first connect your client opens a browser, you Log in with Didit and approve the scopes, and the MCP then acts as you — across every organization you belong to, with your role's permissions. Tokens are short-lived and refreshed automatically.

Scopes: didit:management (workspace operations) and didit:verification (running checks). Your console role is enforced server-side on every call.

There is no API-key mode. Every tool targets the user-scoped console endpoints (/organization/{org}/application/{app}/…), which authorize a Bearer token with per-role privileges and reject x-api-key. (For raw REST access with an application API key — e.g. creating sessions from your backend — use the REST API directly, not this server.)

See Authentication.

Tools

130+ tools, grouped by area. The full catalogue with read/write/destructive markers is in docs/TOOLS.md and at docs.didit.me. Highlights:

  • Discovery & cross-app: didit_context_get, didit_session_search, didit_transaction_search, didit_vendor_user_search, didit_analytics — aggregate across every org/app in one call.
  • Sessions: create, list, get decision, update status, reviews, bulk import.
  • Verification APIs: didit_verify_id, didit_verify_aml, didit_verify_face_match, didit_verify_kyb_search, …
  • Workflows (incl. branching graphs): didit_workflow_search, didit_workflow_get_graph, didit_workflow_edit_graph — build conditional/branching workflows (fuzzy-match conditions, Document-AI steps) by sending small ops; large feature configs are kept server-side, never resent. didit_workflow_get_id_verification_methods_catalog and didit_workflow_get_kyb_registry_catalog answer the server-driven questions a config write depends on (which countries offer non-doc lookup / wallets, which KYB data tiers and monitoring a country's registries sell).
  • Compliance: transaction monitoring, custom and preset rule management with backtesting, lists/blocklist/allowlist, cases, reports, audit logs, alerts.
  • Workspace: questionnaires, webhooks, members, billing, branding.

File inputs

Tools that consume files (face upload, ID/PoA/liveness/face/age verification, branding) accept the file in one of two forms:

  • *_path — an absolute path on the machine running the MCP server. Only works for local/stdio runs (e.g. Claude Code with a local server), where your files and the server share a filesystem.
  • *_base64 — the file content inline, as raw base64 or a data: URL. Use this against the hosted endpoint; it is how the Didit Console Copilot passes chat attachments (its agent resolves attachment references like att_1 into base64 before the call reaches the MCP).

Both forms enforce the same 15MB cap and magic-bytes allow-list (png/jpg/jpeg/webp/gif/bmp/ico/pdf). The hosted transport's JSON body limit is 25MB (MCP_JSON_BODY_LIMIT).

Run it yourself

The hosted server above is the easy path — no install. To self-host, clone this repo and run it with Docker or Node. It authenticates the user the same way (OAuth, or a user Bearer token for headless runs); there is no API-key mode.

git clone https://github.com/didit-protocol/mcp.git && cd mcp

# Docker (recommended) — serves /mcp and /healthz on port 3000
docker build -t didit-mcp . && docker run -p 3000:3000 --env-file .env didit-mcp

# …or with Node
npm install && npm run build
node dist/http.js                                          # hosted HTTP/OAuth
DIDIT_ACCESS_TOKEN=<user-access-token> node dist/index.js  # stdio (headless)

All Didit base URLs and OAuth endpoints are environment variables with public defaults (verification.didit.me, apx.didit.me, business.didit.me) — override them for a private deployment. See ARCHITECTURE.md and .env.example for the full reference.

Workflow feature configuration

Every workflow feature node takes a config object. The tables below are the complete contract - what didit_workflow_create, didit_workflow_update, didit_workflow_validate_graph, didit_workflow_set_graph and didit_workflow_edit_graph accept, and what the API stores. A key that is not listed here is not part of the contract and is dropped silently on save.

didit_workflow_get_feature_config_schema returns the same data as JSON at runtime.

Generated from schema/feature-config-schema.json (contract sha256:200a66d7054aaf6cdddd94d7bd9c62050912862bf6e291908b667b20436ef4cd, schema version 1), which is a copy of the artifact service-didit-verification generates from its feature-config serializers. Do not edit by hand — run npm run schema:readme.

AGE_ESTIMATION

Configuration for Age Estimation feature.

KeyTypeAcceptsMeaning
borderline_maximum_age_thresholdinteger | nullinteger >=1 <=100
borderline_minimum_age_thresholdinteger | nullinteger >=1 <=100
enable_id_verification_fallbackboolean | nullboolean
external_capture_device_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when an external capture device is detected.
face_audio_recording_enabledboolean | nullbooleanRecord the microphone during the selfie capture, so a reviewer can hear the session. Off by default.
face_liveness_duplicated_face_name_mismatch_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when a duplicate face is found under a different name.
face_liveness_flash_modestring | nullstring
face_liveness_max_attemptsinteger | nullinteger >=1 <=3
face_liveness_methodstring | null'ACTIVE_3D'|'FLASHING'|'PASSIVE'
face_liveness_multiple_faces_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when more than one face is present in the capture.
face_liveness_possible_duplicated_face_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when this face matches a previously seen user.
face_liveness_score_decline_thresholdnumber | nullnumber
face_liveness_score_review_thresholdnumber | nullnumber
face_luminance_max_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when the selfie is brighter than face_luminance_max_threshold.
face_luminance_max_thresholdinteger | nullinteger >=0 <=100
face_luminance_min_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when the selfie is darker than face_luminance_min_threshold.
face_luminance_min_thresholdinteger | nullinteger >=0 <=100
face_privacy_mode_enabledboolean | nullboolean
face_quality_decline_thresholdinteger | nullinteger >=0 <=100
face_quality_review_thresholdinteger | nullinteger >=0 <=100
frame_injection_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when injected video frames are detected.
minimum_age_thresholdinteger | nullinteger >=1 <=100
screen_capture_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when the selfie is a photo of a screen.
status_rulesarrayarray
virtual_camera_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when a virtual camera feed is detected.

AML

Configuration for AML feature (used for both KYC AML and KYB Company AML).

KeyTypeAcceptsMeaning
aml_country_weightinteger | nullinteger >=0 <=100
aml_dob_weightinteger | nullinteger >=0 <=100
aml_match_score_thresholdinteger | nullinteger >=0 <=100
aml_name_weightinteger | nullinteger >=0 <=100
aml_score_approve_thresholdinteger | nullinteger >=0 <=100
aml_score_review_thresholdinteger | nullinteger >=0 <=100
case_blueprintuuid | nulluuidWhich case blueprint the automatically-created case is built from. Only meaningful with create_cases_on_hit; the account default is used when unset.
create_cases_on_hitboolean | nullbooleanOpen a case automatically when the screening returns a hit, instead of leaving the hit to be triaged from the session. Off by default.
fallback_to_nativeboolean | nullboolean
is_aml_ongoing_monitoring_enabledboolean | nullbooleanKeep screening the PERSON after the session is approved, raising a new hit when they later appear on a watchlist. Off by default.
kyb_company_aml_country_weightinteger | nullinteger >=0 <=100
kyb_company_aml_dob_weightinteger | nullinteger >=0 <=100
kyb_company_aml_match_score_thresholdinteger | nullinteger >=0 <=100
kyb_company_aml_name_weightinteger | nullinteger >=0 <=100
kyb_enable_ongoing_monitoringboolean | nullbooleanThe same, for the COMPANY on a KYB workflow. The two switches are independent.
kyb_score_approve_thresholdinteger | nullinteger >=0 <=100
kyb_score_review_thresholdinteger | nullinteger >=0 <=100
provider_keystring | nullstring
status_rulesarrayarray

DATABASE_VALIDATION

Configuration for Database Validation feature.

The node is opt-in and does nothing while database_validation_countries is empty - the editor blocks publishing in that state and the compliance check reports it as a gap. Place it after the step that produces its inputs (usually OCR), and use database_validation_field_sources only for inputs no upstream step can fill.

KeyTypeAcceptsMeaning
database_validation_countriesjson | null{"": {"services": ["<service_id>", ...]}}The databases to check, per country - this node runs NOTHING until at least one country carries at least one service id. Service ids come from the country's live catalog (e.g. bra_cpf for BRA); ids that do not belong to the named country, and countries with no live service, are dropped on save. The legacy {"<ISO3>": "one_by_one"|"two_by_two"|"not_enabled"} shape is still accepted and auto-expanded to that country's live services.
database_validation_field_sourcesjson | null{"<db_validation_input_field>": {"source": "document_ai"|"questionnaire"|"expected_data", "key": "||expected_details.|metadata."}}Where to read a database input that no earlier step in the graph can fill. source names the producer and key names the value inside it: a Document AI field key for document_ai, a questionnaire node id for questionnaire, and expected_details.<field> or metadata.<key> for expected_data. Exact-key matches against an upstream step resolve automatically and are deliberately not persisted, so renaming a Document AI field never freezes a stale mapping into the config. A malformed entry is dropped on save rather than rejected, which un-satisfies its service and drops it from the selection.
database_validation_no_match_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when the database returns no match at all.
database_validation_not_applicable_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when no selected database covers the holder's country or document.
database_validation_partial_match_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when the database matches some, but not all, of the submitted fields.
status_rulesarrayarray

DOCUMENT_AI

Configuration for the Document AI feature.

At most 3 documents per node, field keys unique within a document, and at most one field per document may set is_full_name (it is optional - a document may mark none).

KeyTypeAcceptsMeaning
document_ai_document_tampering_actionstring | null'REVIEW'|'DECLINE'Verdict when the document looks tampered with.
document_ai_documentsarrayarray
document_ai_max_attempts_exceeded_actionstring | null'REVIEW'|'DECLINE'Verdict when the user runs out of document_ai_max_retry_attempts.
document_ai_max_retry_attemptsinteger | nullinteger >=2 <=5
document_ai_missing_required_fields_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when a field marked required could not be extracted.
document_ai_name_match_score_thresholdinteger | nullinteger >=0 <=100
document_ai_name_mismatch_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when the field flagged is_full_name disagrees with the verified identity's full name, scored against document_ai_name_match_score_threshold.
document_ai_unreadable_document_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when the uploaded document cannot be read at all.
document_ai_unsupported_file_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when the uploaded file type is not supported.
status_rulesarrayarray

EMAIL_VERIFICATION

Configuration for Email Verification feature.

KeyTypeAcceptsMeaning
breached_email_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when the address appears in a known credential breach.
cross_org_fraud_email_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when this address was flagged as fraudulent by another organization in the network.
disposable_email_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when the address belongs to a disposable-mail provider.
duplicated_email_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when the address was already verified for this application.
email_alphanumeric_codeboolean | nullboolean
email_code_sizeinteger | nullinteger >=4 <=8
email_enrichment_enabledboolean | nullboolean
email_intelligence_score_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when the enrichment score is worse than email_intelligence_score_threshold.
email_intelligence_score_thresholdinteger | nullinteger >=0 <=100
email_max_check_attemptsinteger | nullinteger >=1 <=5
email_max_retriesinteger | nullinteger >=1 <=5
frequent_email_breach_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when the address appears in many breaches.
only_corporate_emails_allowedboolean | nullboolean
recent_email_breach_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when the address appears in a recent breach.
status_rulesarrayarray

FACE_MATCH

Configuration for Face Match feature.

KeyTypeAcceptsMeaning
face_match_eyes_covered_actionstring'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when calibrated evidence says the eyes region is covered in the selfie. NO_ACTION records evidence without changing Face Match; REVIEW sends Face Match to review; DECLINE declines it. The signal remains shadow-only until the region reports calibrated=true.
face_match_face_covered_actionstring'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when calibrated evidence says the face region is covered in the selfie. NO_ACTION records evidence without changing Face Match; REVIEW sends Face Match to review; DECLINE declines it. The signal remains shadow-only until the region reports calibrated=true.
face_match_max_attemptsinteger | nullinteger >=1 <=3
face_match_mouth_covered_actionstring'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when calibrated evidence says the mouth region is covered in the selfie. NO_ACTION records evidence without changing Face Match; REVIEW sends Face Match to review; DECLINE declines it. The signal remains shadow-only until the region reports calibrated=true.
face_match_not_computed_actionstring | null'REVIEW'|'DECLINE'Verdict when no face-match score could be produced (missing portrait or selfie).
face_match_score_decline_thresholdinteger | nullinteger >=0 <=100
face_match_score_review_thresholdinteger | nullinteger >=0 <=100
status_rulesarrayarray

IP_ANALYSIS

Configuration for Device & IP Analysis feature.

KeyTypeAcceptsMeaning
automation_detected_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when the session looks driven by automation rather than a person.
cross_org_fraud_device_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when this device was flagged as fraudulent by another organization in the network.
cross_org_fraud_ip_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when this IP was flagged as fraudulent by another organization in the network.
device_app_tampered_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when the host application binary looks tampered with.
device_blocklist_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when the device is on the organization's block list.
device_debugger_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when a debugger is attached to the host application.
device_emulator_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when the device is an emulator rather than real hardware.
device_hooking_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when runtime hooking or instrumentation is detected.
device_integrity_missing_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when no platform device-integrity attestation was returned.
device_rooted_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when the device is rooted or jailbroken.
duplicated_device_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when this device was already used by another verified user.
duplicated_ip_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when this IP was already used by another verified user.
expected_ip_mismatch_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when the IP disagrees with the expected IP sent on the session.
ip_geofencing_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when the connecting IP's country is not allowed by ip_geofencing_by_country.
ip_geofencing_by_countryjson | null{"": {"allowed": true|false, "states"?: {"<state_code>": {"allowed": true|false}} | null}}Country allow/deny rules for the connecting IP address, applied only while is_ip_geofencing_enabled is true. allowed is required and must be a real boolean; states is optional and null when the country needs no per-state rule. Countries that are not valid ISO3 are dropped on save.
ip_mismatch_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when the IP country disagrees with the document's issuing country.
is_ip_geofencing_enabledboolean | nullboolean
multiple_devices_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when the session was driven from more than one device.
recovered_device_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when the device reports a recovered or restored state.
status_rulesarrayarray
vpn_detection_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when the connection comes through a VPN, proxy or Tor exit.

KYB_DOCUMENTS

KeyTypeAcceptsMeaning
kyb_document_age_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when a document is older than its configured freshness window.
kyb_document_critical_mismatch_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when a document contradicts the registry on a critical company detail.
kyb_document_max_attempts_exceeded_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when the user runs out of kyb_document_max_retry_attempts.
kyb_document_max_retry_attemptsinteger | nullinteger >=1 <=5
kyb_document_non_critical_mismatch_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when a document contradicts the registry on a minor detail.
kyb_document_subtype_configjson | null{"<KYB_DOCUMENT_GROUP|KYB_DOCUMENT_SUBTYPE>": {"enabled": true|false, "max_age_days": <0-3650>|-1|null}}Per-group or per-subtype switch and freshness window. Keys must be a known KYB document group or subtype code. max_age_days is null for the default window, -1 for unlimited, or an integer 0-3650; anything else is rejected.
kyb_document_tampering_actionstring | null'NO_ACTION'|'REVIEW'|'DECLINE'Verdict when a company document looks tampered with.
kyb_required_document_groupsjson | null["<KYB_DOCUMENT_GROUP>", ...]The company paperwork to collect, as a list of document-GROUP codes - each group is satisfied by any one of the document types it covers. The KYB Documents feature refuses to save with an empty list: a node that requires nothing is the same as not having the node.
status_rulesarrayarray

KYB_KEY_PEOPLE

The workflow ids here point at separate KYC workflows: a KYB graph verifies the company, and the people behind it are verified by the linked person workflows.

Shortened here. Read the whole README on GitHub.

Signals

Last commit
Sep 2026
Advanced
Delivery
mcp MCP server → your ahel gateway (mcp.ahel.ai) → every connected AI client.
Catalog kind
mcp-server
Gateway key
me-didit-mcp
Source
github.com/didit-protocol/mcp
Hosted endpoint
https://mcp.didit.me/mcp