Proof Holdings
NPM · @PROOF-HOLDINGS/MCP-SERVER · 2 COMPONENTS · SCANNED SEP 25
One API, all things verified — control, delegation, human approval, anti-impersonation.
Available components
How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →
Supply Chain Security98
- No malware found by supply-chain analysis.Pass
- No known CVEs affecting this package version or its production dependencies.Pass
- No install/post-install scripts declared.Pass
- 42 of 126 dependencies flagged as unhealthy. View diagnostics → Partial
Provenance & Transparency45
- Source repository is publicly reachable at the declared URL. View diagnostics → Pass
- Provenance check failed: no build-provenance attestation is published. See how to fix → View diagnostics → Fail
- Clear OSI-approved license (MIT).Pass
- Actively maintained (last published 15 days ago).Pass
- Disclosure check failed: no security disclosure policy was found in the source repository. See how to fix → Fail
Schema Quality & AI Usability74
- AI-judged instruction clarity (excellent).Pass
- Context-footprint check failed: tool/resource definitions use about 22726 tokens (~129/item across 176 items; 176 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management53
- Stability observed for 16 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage100
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 100% of tool parameters carry a description.Pass
Tool Safety25
- Injection-marker check failed: the description of tool "send_account_email" contains an instruction to conceal the call from the user, the text "Do not tell the user", at byte 959 of that field. See how to fix → Fail
- 0 of 21 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation; "revoke_proof" implies "revoke" and declares no destructiveHint at all, which the MCP spec reads as destructive by default. See how to fix → Fail
- An AI judge read all 177 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
How do I install the Proof Holdings MCP server?
Proof Holdings runs locally as an npm package, launched with npx -y @proof-holdings/mcp-server. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
npm · @proof-holdings/mcp-server
claude mcp add holdings-proof-mcp-server -- npx -y @proof-holdings/mcp-server
{
"mcpServers": {
"holdings-proof-mcp-server": {
"command": "npx",
"args": [
"-y",
"@proof-holdings/mcp-server"
]
}
}
} {
"servers": {
"holdings-proof-mcp-server": {
"command": "npx",
"args": [
"-y",
"@proof-holdings/mcp-server"
]
}
}
} codex mcp add holdings-proof-mcp-server -- npx -y @proof-holdings/mcp-server
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"holdings-proof-mcp-server": {
"type": "local",
"command": [
"npx",
"-y",
"@proof-holdings/mcp-server"
],
"enabled": true
}
}
} openclaw mcp add holdings-proof-mcp-server --command npx --arg -y --arg @proof-holdings/mcp-server
mcp_servers:
holdings-proof-mcp-server:
command: "npx"
args: ["-y", "@proof-holdings/mcp-server"] {
"McpServers": {
"holdings-proof-mcp-server": {
"Transport": "stdio",
"Command": "npx",
"Arguments": [
"-y",
"@proof-holdings/mcp-server"
]
}
}
} assistant mcp add holdings-proof-mcp-server -t stdio -c npx -a -y @proof-holdings/mcp-server
{
"mcpServers": {
"holdings-proof-mcp-server": {
"command": "npx",
"args": [
"-y",
"@proof-holdings/mcp-server"
]
}
}
} Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 25 Sept 26 +1
- We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
- 23 Sept 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 43 to 47. That category is still filling its 30-day observation window: 13 days of observed history at the previous scan, 14 at this one. The score rises as the window fills, whether or not the server changes.
- 21 Sept 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 37 to 40. That category is still filling its 30-day observation window: 11 days of observed history at the previous scan, 12 at this one. The score rises as the window fills, whether or not the server changes.
- 19 Sept 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 30 to 33. That category is still filling its 30-day observation window: 9 days of observed history at the previous scan, 10 at this one. The score rises as the window fills, whether or not the server changes.
- 17 Sept 26 +4
- Stability: unverified → 0.27 ▲ functional
- 9 Sept 26 65
First indexed and scored.
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 25 Sept 2026 · Analysed npm/@proof-holdings/mcp-server@1.1.0
Provenance No attestation
The registry publishes no build provenance for this version, so there is nothing to verify.
| Result | No attestation |
|---|---|
| Ecosystem | npm |
Background: How many MCP packages publish verified provenance →
Dependencies 126 packages
| Packages resolved | 126 |
|---|---|
| Stale | 42 |
| Tree resolution | Complete |
Background: SBOMs and build attestations, explained →
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
list_phones ~55
List all phone numbers associated with the authenticated account. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, or sign in with start_login — a session opens this tool — then call this tool again.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
list_profile_templates ~70
List all templates for a profile. Returns templates organized by channel and message type, merged with defaults. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| profile_id | string | yes | Profile ID |
No output schema declared.
No examples provided.
list_profiles ~55
List all profiles for the authenticated account. Returns all profiles including primary and secondary. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
list_revoked_proofs ~38
Get the revocation list for offline proof validation. Returns a signed list of all revoked proof IDs, cacheable for 5 minutes.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
list_templates ~58
List all custom message templates for the authenticated account. Returns templates organized by channel and message type. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
list_verification_requests ~117
List verification requests with optional filters. Returns paginated results. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| limit | integer | – | Items per page |
| page | integer | – | Page number |
| reference_id | string | – | Filter by reference ID |
| status | string | – | Filter by status. 'active' = live (not-yet-expired) pending or partial requests; persisted statuses are time-aware. |
No output schema declared.
No examples provided.
list_verifications ~105
List verifications with optional filters. Returns paginated results. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| channel | string | – | Filter by channel |
| external_user_id | string | – | Filter by external user ID |
| limit | integer | – | Items per page |
| page | integer | – | Page number |
| status | string | – | Filter by status |
No output schema declared.
No examples provided.
list_verified_users ~75
List verified users grouped by external_user_id. Shows all verifications per user. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| limit | integer | – | Items per page |
| page | integer | – | Page number |
No output schema declared.
No examples provided.
list_webhook_deliveries ~110
List webhook delivery attempts with pagination and filtering. Shows delivery status, response codes, and timestamps. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| event_type | string | – | Filter by event type (e.g. verification.completed) |
| limit | integer | – | Items per page |
| page | integer | – | Page number |
| status | string | – | Filter by delivery status |
No output schema declared.
No examples provided.
poll_chat_id_discovery ~84
Poll a chat ID discovery token. Returns the discovered Telegram chat ID, user ID, and username once the user interacts with the bot. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| token | string | yes | Discovery token from create_chat_id_discovery |
No output schema declared.
No examples provided.
preview_profile_template ~133
Preview a profile template with sample data before saving. Shows how the message will look with placeholder variables filled in. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| body | string | yes | Template body text |
| button_text | string | – | Button text |
| button_url_template | string | – | Button URL template |
| channel | string | yes | Message channel |
| message_type | string | yes | Message type |
| profile_id | string | yes | Profile ID |
| subject | string | – | Email subject line |
No output schema declared.
No examples provided.
preview_template ~121
Preview a template with sample data before saving. Shows how the message will look with placeholder variables filled in. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| body | string | yes | Template body text |
| button_text | string | – | Button text |
| button_url_template | string | – | Button URL template |
| channel | string | yes | Message channel |
| message_type | string | yes | Message type |
| subject | string | – | Email subject line |
No output schema declared.
No examples provided.
regenerate_api_key ~175
Regenerate an API key, issuing a new secret while keeping the same ID and settings. The old key stops working immediately. The new secret is returned ONLY in this response. Note: the secret will be visible in the AI conversation context. Agent usage: This operation requires 2FA. Before calling, complete the 2FA flow: (1) call start_2fa with action_type "api_key_regenerate", (2) wait for user to verify the code, (3) poll get_2fa_status until "verified", (4) then call regenerate_api_key. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, or sign in with start_login — a session opens this tool — then call this tool again.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | API key ID to regenerate |
No output schema declared.
No examples provided.
remove_challenger ~88
Remove a Proof-Me challenger from a HITL config. Removing the last challenger disables Proof-Me on the config. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| challenger_id | string | yes | Challenger ID to remove |
| hitl_id | string | yes | HITL config ID |
No output schema declared.
No examples provided.
remove_circle_member ~85
Remove a member from a Circle. Deletes the member's channels and revokes any live authorizations that routed through them. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Circle ID |
| member_id | string | yes | Member ID to remove |
No output schema declared.
No examples provided.
remove_circle_member_channel ~93
Remove a channel from a Circle member. Removing the last channel is allowed (the member simply becomes unreachable). ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| channel_id | string | yes | Channel ID to remove |
| id | string | yes | Circle ID |
| member_id | string | yes | Member ID |
No output schema declared.
No examples provided.
remove_email ~74
Remove an email address from the account by ID. May require 2FA verification for sensitive operations. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, or sign in with start_login — a session opens this tool — then call this tool again.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Email record ID |
No output schema declared.
No examples provided.
remove_phone ~74
Remove a phone number from the account by ID. May require 2FA verification for sensitive operations. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, or sign in with start_login — a session opens this tool — then call this tool again.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Phone record ID |
No output schema declared.
No examples provided.
render_auth_link ~278
Render an authorization or verification URL as a clickable link followed by a scannable QR code inside a fenced code block. This is a local computation tool — no HTTP request is made. Agent usage: pass a LINK field from an earlier response — `deep_link` (create_session, create_chat_id_discovery always; start_login, create_account, start_2fa, start_2fa_for_action on telegram/whatsapp ONLY, where on sms and email that field is empty or absent altogether and this tool rejects it either way), `challenge.deep_link` (create_verification, messenger channels only), or `telegram_deep_link` / `whatsapp_deep_link`. Do NOT pass `qr_text` to this tool: that field is a QR code already rendered as text, and this tool takes a link. When a response gives you `qr_text` and no link, print it verbatim inside a fenced code block instead — its rows only scan while they stay adjacent, so a blank line or wrapped row destroys the code.
| Name | Type | Req | Description |
|---|---|---|---|
| label | string | – | Optional label to display above the link (e.g. "Verify your phone number") |
| url | string | yes | The link to render — e.g. a deep_link response field. Never a qr_text value: that is the link already rendered as QR art. |
No output schema declared.
No examples provided.
render_template ~85
Render a template with provided variables. Returns the fully rendered message content. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| channel | string | yes | Message channel |
| message_type | string | yes | Message type |
| variables | object | – | Variables to substitute into the template |
No output schema declared.
No examples provided.
request_hitl_authorization ~313
Request authorization for a HITL config. Sends consent requests to all configured channels (Telegram/WhatsApp). Users must approve before confirmations can be sent. Agent usage: This must be completed before create_confirmation will work for this HITL config. The consent request is DELIVERED to each channel — the response carries no link to show. It returns `authorizations` — one entry per resolved recipient, each with its `channel`, `recipient`, `authorization_id` and `status` — plus a `message`. Read the entries rather than assuming: `status: 'pending'` means consent was just sent and the user must approve in Telegram/WhatsApp itself, while `status: 'active'` means that recipient had already authorized and nothing was sent to them. An EMPTY array does not mean everyone is authorized — it means no recipient could be resolved at all (usually a HITL config bound to a missing or inactive circle, or channels whose recipient is blank), so nobody was asked and waiting for an approval would hang forever. Do not relay `message` on that branch: it reads 'All channels already have active or pending authorizations', which is exactly the wrong conclusion. Read the array. After requesting, you can proceed once the user confirms they have approved. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | HITL config ID to request authorization for |
No output schema declared.
No examples provided.
resend_domain_email ~84
Resend the domain verification email. Rate limited to 3 requests per minute. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, or sign in with start_login — a session opens this tool — then call this tool again.
| Name | Type | Req | Description |
|---|---|---|---|
| email_prefix | string | – | Email prefix to resend verification to |
| id | string | yes | Domain ID |
No output schema declared.
No examples provided.
resend_email_otp ~70
Resend the OTP code for an in-progress email addition. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, or sign in with start_login — a session opens this tool — then call this tool again.
| Name | Type | Req | Description |
|---|---|---|---|
| session_id | string | yes | Add-email session ID |
No output schema declared.
No examples provided.
resend_verification ~66
Resend a verification message (email channel only). Generates and sends a new code. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Verification ID |
No output schema declared.
No examples provided.
retry_webhook_delivery ~74
Retry a failed webhook delivery. Creates a new delivery attempt with the same payload to the configured endpoint. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Webhook delivery ID to retry |
No output schema declared.
No examples provided.
revoke_api_key ~148
Revoke an API key by ID. The key will immediately stop working. This action cannot be undone. Agent usage: This operation requires 2FA. Before calling, complete the 2FA flow: (1) call start_2fa with action_type "api_key_revoke", (2) wait for user to verify the code, (3) poll get_2fa_status until "verified", (4) then call revoke_api_key. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, or sign in with start_login — a session opens this tool — then call this tool again.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | API key ID to revoke |
No output schema declared.
No examples provided.
revoke_asset ~71
Revoke a verified asset by ID. The asset will be marked as revoked and associated proofs will no longer validate. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Asset ID |
No output schema declared.
No examples provided.
revoke_auth_session ~84
Revoke a specific authentication session by ID. When called via JWT, cannot revoke the current session. When called via API key, any session can be revoked. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| session_id | string | yes | Session ID to revoke |
No output schema declared.
No examples provided.
revoke_authorization ~86
Revoke an active or pending authorization. Only authorizations with status "active" or "pending" can be revoked. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Authorization ID to revoke |
| reason | string | – | Reason for revocation |
No output schema declared.
No examples provided.
revoke_delegation ~174
Revoke ONE delegation. The domain control proof and sibling delegations stay valid; the revocation is mirrored into the proof registry so the CRL, status list and public status lookup all see it. Idempotent: a repeat revoke answers success with the same body, both here and through revoke_proof with the ph_dlg_ handle — unlike a PROOF, where a repeat answers already_revoked. The result carries the DERIVED effective_status/is_valid beside the stored status. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Delegation ID (24-hex Mongo id or ph_dlg_<32 hex> handle) |
| reason | string | – | Reason for revocation |
No output schema declared.
No examples provided.
revoke_proof ~164
Revoke a proof by its public handle (ph_ctl_* / ph_dlg_*) or a verification ID — the same addresses get_proof_status takes. The proof token will no longer validate anywhere: the status endpoint, the public validator, the revocation list and the Token Status List all report it revoked. This action is irreversible. It revokes the PROOF only — the asset, consent or delegation the proof is about is not withdrawn. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Public proof handle (ph_ctl_* / ph_dlg_*) or verification ID |
| reason | string | – | Reason for revocation |
No output schema declared.
No examples provided.
search ~160
Prefix-anchored global account search across six resource buckets (verification_requests, verifications, hitl, confirmations, authorizations, api_keys). Case-sensitive prefix match over indexed plaintext fields only; recipient identifiers are masked. Results are scoped to the authenticated account. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| environment | string | – | Scope results to test or production data (default: production) |
| limit | integer | – | Max results per bucket (default 10, max 25) |
| q | string | yes | Prefix-anchored search query (minimum 3 characters) |
| type | string | – | Narrow the search to a single result bucket |
No output schema declared.
No examples provided.
send_account_email ~269
Deliver the verification email for an account-bootstrap session created with channel "email". Public endpoint (no API key required). Why this is a separate call: create_account deliberately sends NOTHING. A message from proof.holdings arriving in someone's inbox is an act with a person on the other end, so it takes an explicit second step rather than being a side effect of creating a session. ASK THE USER to confirm the address is theirs before calling this — do not call it automatically after create_account. The other channels (telegram, whatsapp, sms) never need this: the user sends the first message themselves (reverse OTP), so nothing is dispatched to them at all. One session sends at most one email, including under concurrent calls. A repeat answers 410 already_sent, which means the material backing the send is gone: usually because the email went out, occasionally because an attempt was interrupted mid-send and nothing was delivered. Do not tell the user a message was sent on the strength of a 410 — create a new session instead. (A session the recipient cancelled via the decline link, or an expired one, answers 404, not 410.) If delivery fails the response carries email_sent=false and the call can be retried.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Account session id from create_account |
No output schema declared.
No examples provided.
set_primary_email ~71
Set an email address as the primary email for the account. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, or sign in with start_login — a session opens this tool — then call this tool again.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Email record ID to set as primary |
No output schema declared.
No examples provided.
set_primary_phone ~71
Set a phone number as the primary phone for the account. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, or sign in with start_login — a session opens this tool — then call this tool again.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Phone record ID to set as primary |
No output schema declared.
No examples provided.
set_primary_profile ~69
Set a profile as the primary profile. The previous primary profile becomes secondary. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| profile_id | string | yes | Profile ID to set as primary |
No output schema declared.
No examples provided.
setup_domain_email ~91
Set up email sending for a verified domain. Configures the domain for sending verification emails from a custom address. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, or sign in with start_login — a session opens this tool — then call this tool again.
| Name | Type | Req | Description |
|---|---|---|---|
| from_email | string | – | Custom from email address for the domain |
| id | string | yes | Domain ID |
No output schema declared.
No examples provided.
share_request_email ~67
Send an email notification to the subject of a verification request. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, or sign in with start_login — a session opens this tool — then call this tool again.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Verification request ID |
No output schema declared.
No examples provided.
start_2fa ~442
Start a two-factor authentication challenge for a sensitive operation. Sends a verification code via the chosen channel. Returns a session ID, and for messaging channels: deep_link, qr_code (base64 PNG), and qr_text (UTF-8 text QR for terminal display). Agent usage — full 2FA flow: (1) Call start_2fa with the appropriate action_type and channel. (2) Present the challenge, and do NOT announce a message the server did not send: email is the ONLY channel it dispatches on. On telegram/whatsapp the user opens `deep_link` and sends the message themselves; on sms they send `sms_message` to a number from `sms_dids`; the response's own `instructions` field says which. On email, a 200 carrying `requires_email_selection: true` and `available_emails` means nothing was sent and no session exists — ask which address and call again with `email_id`. For telegram/whatsapp, pass `deep_link` to render_auth_link; for sms, show `sms_message`. Never hand `qr_text` to a link renderer — it is the link already rendered as QR art, so print it verbatim inside a fenced code block only when a real terminal needs the QR. (3) Poll get_2fa_status with the returned session_id until status is "verified" (the user enters the code on their device) or "expired". (4) If verified, proceed with the protected operation (e.g. create_api_key). If expired, inform the user and offer to restart. Typical channels: "telegram" or "email". For email, the user may receive a magic link instead of a code — the backend handles this automatically. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, or sign in with start_login — a session opens this tool — then call this tool again.
| Name | Type | Req | Description |
|---|---|---|---|
| action_type | string | yes | The sensitive action requiring 2FA |
| channel | string | yes | Channel to receive the verification code |
| email_id | string | – | Specific email ID for email channel (optional) |
No output schema declared.
No examples provided.
start_2fa_for_action ~646
Start a 2FA challenge that grants the authenticated user permission to perform a sensitive action. The 2FA must complete on a channel DIFFERENT from the user's last login channel (the backend enforces this). On success a grant is stored keyed by the user id and action_type; middleware on the protected endpoint reads the grant and allows the mutation. Destructive action types (api_key_create, api_key_revoke, api_key_regenerate, api_key_view, account_delete, phone_remove, email_remove, revocation_bulk) are capped at 5min TTL and forced single-use by server policy. Configuration scopes (settings_write, profile_update, templates_write) allow up to 24h TTL and caller-chosen single_use — useful for agents making multiple settings mutations in one session. Agent usage: (1) Attempt the sensitive call; if you get `403 2fa_required` note the `action_type`. (2) Call start_2fa_for_action with that action_type and a channel different from the login channel. (3) Present the challenge: on telegram/whatsapp pass `deep_link` to render_auth_link; on sms show `sms_message` and the number to send it to; on email check the response first: with more than one verified email and no `email_id` given, it answers 200 with `requires_email_selection: true` and `available_emails` — NO session was started and nothing was sent, so ask the user which address and call again with `email_id` rather than telling them to open a mailbox. Never hand `qr_text` to a link renderer — it is the link already rendered as QR art. Print it verbatim inside a fenced code block only when a real terminal needs the QR. (4) Call wait_for_2fa until the session is verified. (5) Retry the original sensitive call. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| action_type | string | yes | The sensitive action the 2FA grant will authorize. Destructive scopes (api_key_*, account_delete, phone_remove, email_remove, revocation_bulk) are capped at 5 min TTL + forced single-use. Configurati… |
| channel | string | yes | Channel for the 2FA challenge — must differ from the user's last login channel |
| email_id | string | – | Optional: specific UserEmail id for email-channel 2FA |
| phone_id | string | – | Optional: specific UserPhone id for phone-channel 2FA |
| single_use | boolean | – | Whether the grant is consumed on first use. Server forces true for destructive action types. Defaults to true. |
| ttl_seconds | integer | – | Requested grant lifetime in seconds. Server caps to 300s for destructive action types, 86400s for configuration scopes. Defaults to 300 if omitted. |
No output schema declared.
No examples provided.
start_add_email ~79
Start adding a new email address. Sends an OTP code to the email. Returns a session ID to verify with. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, or sign in with start_login — a session opens this tool — then call this tool again.
| Name | Type | Req | Description |
|---|---|---|---|
| string | yes | Email address to add |
No output schema declared.
No examples provided.
start_add_phone ~105
Start adding a new phone number. Uses reverse OTP: the system sends a message and the user replies. Returns a session ID, deep_link, qr_code (base64 PNG), and qr_text (UTF-8 text QR for terminal display). ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, or sign in with start_login — a session opens this tool — then call this tool again.
| Name | Type | Req | Description |
|---|---|---|---|
| channel | string | yes | Channel for phone verification |
No output schema declared.
No examples provided.
start_domain_email_verification ~95
Start domain verification via corporate email. Sends a verification code to a standard admin email address at the domain. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, or sign in with start_login — a session opens this tool — then call this tool again.
| Name | Type | Req | Description |
|---|---|---|---|
| email_prefix | string | – | Email prefix to send verification to (default: admin) |
| id | string | yes | Domain ID |
No output schema declared.
No examples provided.
start_domain_verification ~111
Start a B2B domain verification. Creates a verification record and returns DNS/HTTP instructions for the customer to complete. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| customer_id | string | – | Customer identifier for B2B tracking |
| domain | string | yes | Domain to verify (e.g. example.com) |
| verification_method | string | – | Verification method (default: manual_dns) |
No output schema declared.
No examples provided.
start_login ~470
Start a login session by sending an authentication challenge to the user's chosen channel (Telegram, WhatsApp, SMS, or email). Returns a session ID and, FOR TELEGRAM AND WHATSAPP ONLY, deep_link, qr_code (base64 PNG) and qr_text (UTF-8 text QR for terminal display); on sms it returns sms_message with sms_dids instead, and on email nothing to display. Agent usage: (1) Call start_login with the desired channel and phone_number (for SMS) or email (for email). (2) Present the challenge, and WHICH FIELD depends on the channel. On telegram/whatsapp pass `deep_link` to render_auth_link, which prints the clickable link and a QR code; in a chat client the link is what the user acts on, since they are usually on the same machine. On sms `deep_link` is an EMPTY STRING and render_auth_link will reject it — show `sms_message` and let the user pick a number from `sms_dids`. `suggested_region` is always set, but the matching ENTRY in `sms_dids` may be missing (europe and israel appear only when a number is configured) or present with an empty `did`, so offer that region first only when `sms_dids[suggested_region]` exists and carries a number, and otherwise offer whatever the object does. On email there is no link either — check `email_sent` before telling the user to open their mail: on a delivery failure it is false and `email_error` says why, and waiting on an inbox nothing reached is the wrong next step. Never hand `qr_text` to a link renderer — it is the link already rendered as QR art, so print it verbatim inside a fenced code block or not at all, because its rows stop scanning the moment one wraps or a blank line lands between them. (3) Call wait_for_login with the returned session ID to poll until the user completes authentication. Terminal states: "verified" (login succeeded), "failed", "expired".
| Name | Type | Req | Description |
|---|---|---|---|
| channel | string | yes | Authentication channel |
| string | – | Email address (required for email channel) | |
| phone_number | string | – | Phone number in E.164 format (required for SMS channel) |
No output schema declared.
No examples provided.
start_user_domain_verification ~98
Start a self-service domain verification session. The user proves ownership of a domain via DNS or HTTP challenge. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, or sign in with start_login — a session opens this tool — then call this tool again.
| Name | Type | Req | Description |
|---|---|---|---|
| channel | string | – | Verification channel (default: dns) |
| domain | string | yes | Domain name to verify (e.g. example.com) |
No output schema declared.
No examples provided.
submit_verification_code ~169
Submit an OTP/challenge code for a pending verification. Accepted ONLY where we delivered the code out-of-band to the party being verified: type "email", and type "domain" with channel "email". Any other pair answers 400 unsupported_for_type and completes elsewhere — use trigger_verification (POST /verifications/:id/verify) for a domain over dns/http/auto; a phone completes when the code reaches us FROM that number; social completes through its OAuth callback; a telegram_bot is already verified at creation. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| code | string | yes | The OTP or challenge code to submit |
| id | string | yes | Verification ID |
No output schema declared.
No examples provided.
test_verify ~73
Auto-complete a verification in test mode (pk_test_* API keys only). Useful for testing flows without real OTP delivery. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Verification ID |
No output schema declared.
No examples provided.
trigger_drill ~103
Fire an on-demand Proof-Me drill against one enrolled challenger — a real cross-channel identity challenge carrying the scheduled-safety-check label. Complements the automated daily drill + monthly reinforcement sweeps. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| challenger_id | string | yes | Challenger ID to drill |
| hitl_id | string | yes | HITL config ID |
No output schema declared.
No examples provided.
trigger_verification ~62
Trigger a DNS/HTTP verification check for a pending domain verification. ACCESS: needs a Proof account. Set PROOF_API_KEY and restart this server, then call this tool again. start_login does NOT open this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Verification ID |
No output schema declared.
No examples provided.
What is the Proof Holdings MCP server?
Proof Holdings is an MCP server listed in the public MCP registry as holdings.proof/mcp-server. One API, all things verified, control, delegation, human approval, anti-impersonation. This page covers its npm package (@proof-holdings/mcp-server).
Is the Proof Holdings MCP server safe to use?
Proof Holdings scores 73 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 25 September 2026. It declares no install or post-install scripts. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the Proof Holdings MCP server expose?
Proof Holdings exposes 176 tools: create_verification, get_verification, list_verifications, trigger_verification, submit_verification_code, and 171 more. Their descriptions and schemas cost roughly 22,440 tokens of context every time the server is loaded.
Is the Proof Holdings MCP server still maintained?
Proof Holdings is still listed as active in the MCP registry. We last reached this channel on 25 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.
What licence is the Proof Holdings MCP server under?
Proof Holdings declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.