@proof-holdings/mcp-server 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +220 -217
- package/dist/authBoundary.d.ts +193 -0
- package/dist/authBoundary.d.ts.map +1 -0
- package/dist/authBoundary.js +341 -0
- package/dist/authBoundary.js.map +1 -0
- package/dist/factory.d.ts +35 -0
- package/dist/factory.d.ts.map +1 -0
- package/dist/factory.js +130 -0
- package/dist/factory.js.map +1 -0
- package/dist/http.d.ts +78 -3
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +251 -6
- package/dist/http.js.map +1 -1
- package/dist/remote.d.ts +111 -0
- package/dist/remote.d.ts.map +1 -0
- package/dist/remote.js +789 -0
- package/dist/remote.js.map +1 -0
- package/dist/server.js +11 -57
- package/dist/server.js.map +1 -1
- package/dist/toolAnnotations.d.ts +27 -0
- package/dist/toolAnnotations.d.ts.map +1 -0
- package/dist/toolAnnotations.js +158 -0
- package/dist/toolAnnotations.js.map +1 -0
- package/dist/tools/{projects.d.ts → accounts.d.ts} +1 -1
- package/dist/tools/accounts.d.ts.map +1 -0
- package/dist/tools/accounts.js +70 -0
- package/dist/tools/accounts.js.map +1 -0
- package/dist/tools/api-keys.d.ts.map +1 -1
- package/dist/tools/api-keys.js +14 -5
- package/dist/tools/api-keys.js.map +1 -1
- package/dist/tools/auth-flows.d.ts +4 -0
- package/dist/tools/auth-flows.d.ts.map +1 -0
- package/dist/tools/auth-flows.js +34 -0
- package/dist/tools/auth-flows.js.map +1 -0
- package/dist/tools/auth.js +1 -1
- package/dist/tools/auth.js.map +1 -1
- package/dist/tools/authorizations.d.ts +4 -0
- package/dist/tools/authorizations.d.ts.map +1 -0
- package/dist/tools/authorizations.js +111 -0
- package/dist/tools/authorizations.js.map +1 -0
- package/dist/tools/circles.d.ts +4 -0
- package/dist/tools/circles.d.ts.map +1 -0
- package/dist/tools/circles.js +215 -0
- package/dist/tools/circles.js.map +1 -0
- package/dist/tools/confirmations.d.ts +4 -0
- package/dist/tools/confirmations.d.ts.map +1 -0
- package/dist/tools/confirmations.js +86 -0
- package/dist/tools/confirmations.js.map +1 -0
- package/dist/tools/delegation-verify-outcomes.d.ts +23 -0
- package/dist/tools/delegation-verify-outcomes.d.ts.map +1 -0
- package/dist/tools/delegation-verify-outcomes.js +51 -0
- package/dist/tools/delegation-verify-outcomes.js.map +1 -0
- package/dist/tools/delegation-verify.d.ts +24 -0
- package/dist/tools/delegation-verify.d.ts.map +1 -0
- package/dist/tools/delegation-verify.js +192 -0
- package/dist/tools/delegation-verify.js.map +1 -0
- package/dist/tools/delegations.d.ts +4 -0
- package/dist/tools/delegations.d.ts.map +1 -0
- package/dist/tools/delegations.js +84 -0
- package/dist/tools/delegations.js.map +1 -0
- package/dist/tools/domains.d.ts.map +1 -1
- package/dist/tools/domains.js +1 -2
- package/dist/tools/domains.js.map +1 -1
- package/dist/tools/hitl-keys.d.ts +4 -0
- package/dist/tools/hitl-keys.d.ts.map +1 -0
- package/dist/tools/hitl-keys.js +52 -0
- package/dist/tools/hitl-keys.js.map +1 -0
- package/dist/tools/hitl.d.ts +4 -0
- package/dist/tools/hitl.d.ts.map +1 -0
- package/dist/tools/hitl.js +151 -0
- package/dist/tools/hitl.js.map +1 -0
- package/dist/tools/phones.js +1 -1
- package/dist/tools/phones.js.map +1 -1
- package/dist/tools/profiles.d.ts.map +1 -1
- package/dist/tools/profiles.js +73 -0
- package/dist/tools/profiles.js.map +1 -1
- package/dist/tools/proof-me.d.ts +4 -0
- package/dist/tools/proof-me.d.ts.map +1 -0
- package/dist/tools/proof-me.js +36 -0
- package/dist/tools/proof-me.js.map +1 -0
- package/dist/tools/proofs.d.ts.map +1 -1
- package/dist/tools/proofs.js +9 -6
- package/dist/tools/proofs.js.map +1 -1
- package/dist/tools/render-auth-link.d.ts +3 -0
- package/dist/tools/render-auth-link.d.ts.map +1 -0
- package/dist/tools/render-auth-link.js +30 -0
- package/dist/tools/render-auth-link.js.map +1 -0
- package/dist/tools/sessions.js +5 -5
- package/dist/tools/sessions.js.map +1 -1
- package/dist/tools/settings.d.ts.map +1 -1
- package/dist/tools/settings.js +77 -2
- package/dist/tools/settings.js.map +1 -1
- package/dist/tools/twofa.d.ts.map +1 -1
- package/dist/tools/twofa.js +16 -3
- package/dist/tools/twofa.js.map +1 -1
- package/dist/tools/user-requests.d.ts.map +1 -1
- package/dist/tools/user-requests.js +1 -2
- package/dist/tools/user-requests.js.map +1 -1
- package/dist/tools/verification-requests.d.ts.map +1 -1
- package/dist/tools/verification-requests.js +40 -13
- package/dist/tools/verification-requests.js.map +1 -1
- package/dist/tools/verifications.d.ts.map +1 -1
- package/dist/tools/verifications.js +59 -12
- package/dist/tools/verifications.js.map +1 -1
- package/dist/types.d.ts +18 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +114 -5
- package/dist/types.js.map +1 -1
- package/package.json +11 -5
- package/dist/tools/projects.d.ts.map +0 -1
- package/dist/tools/projects.js +0 -159
- package/dist/tools/projects.js.map +0 -1
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,30 +1,39 @@
|
|
|
1
1
|
# @proof-holdings/mcp-server
|
|
2
2
|
|
|
3
|
-
MCP (Model Context Protocol) server for the [proof.holdings](https://proof.holdings) API. Exposes
|
|
3
|
+
MCP (Model Context Protocol) server for the [proof.holdings](https://proof.holdings) API. Exposes 171 tools for AI agents to create verifications, validate proofs, manage assets, and more.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Two ways to connect
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
**Hosted — nothing to install.** The same tools are served over HTTP at
|
|
8
|
+
`https://api.proof.holdings/mcp`. Any MCP client or agent framework with HTTP transport can
|
|
9
|
+
connect — add the URL as a remote MCP server in its settings (the config key varies by client).
|
|
10
|
+
Authentication happens in the browser the first time a tool needs an account. As a config fragment:
|
|
11
|
+
|
|
12
|
+
```json
|
|
13
|
+
{ "mcpServers": { "proof": { "type": "http", "url": "https://api.proof.holdings/mcp" } } }
|
|
9
14
|
```
|
|
10
15
|
|
|
11
|
-
|
|
16
|
+
⚠️ **Versions before `1.1.0` predate the delegation tools and the keyless public mode** and expose
|
|
17
|
+
an older, smaller surface than this README describes. If a client is pinned to `1.0.0`, upgrade it
|
|
18
|
+
or use the hosted server above. `GET /api/v1/mcp/connect` always serves the current instructions.
|
|
19
|
+
|
|
20
|
+
**Local — this package.** Installs and runs as a stdio server:
|
|
12
21
|
|
|
13
22
|
```bash
|
|
14
|
-
|
|
23
|
+
npm install -g @proof-holdings/mcp-server
|
|
15
24
|
```
|
|
16
25
|
|
|
17
|
-
Or run with
|
|
26
|
+
Or run directly with npx (no install needed):
|
|
18
27
|
|
|
19
28
|
```bash
|
|
20
|
-
|
|
29
|
+
npx @proof-holdings/mcp-server
|
|
21
30
|
```
|
|
22
31
|
|
|
23
32
|
## Configuration
|
|
24
33
|
|
|
25
34
|
| Variable | Required | Default | Description |
|
|
26
35
|
|---|---|---|---|
|
|
27
|
-
| `PROOF_API_KEY` |
|
|
36
|
+
| `PROOF_API_KEY` | No | — | API key (`pk_live_...` or `pk_test_...`). Without it the server still starts in **public mode**: the keyless tools (account bootstrap, login, proof and delegation verification) work, and every other tool answers `api_key_required`. |
|
|
28
37
|
| `PROOF_BASE_URL` | No | `https://api.proof.holdings` | API base URL |
|
|
29
38
|
|
|
30
39
|
Get your API key from the [proof.holdings dashboard](https://proof.holdings/dashboard/api-keys).
|
|
@@ -57,282 +66,276 @@ Config file location by client:
|
|
|
57
66
|
| Claude Code | Run `claude mcp add proof-holdings -- npx -y @proof-holdings/mcp-server` |
|
|
58
67
|
| Windsurf | `~/.codeium/windsurf/mcp_config.json` |
|
|
59
68
|
|
|
60
|
-
### Windsurf
|
|
61
|
-
|
|
62
|
-
Add to `~/.codeium/windsurf/mcp_config.json`:
|
|
63
|
-
|
|
64
|
-
```json
|
|
65
|
-
{
|
|
66
|
-
"mcpServers": {
|
|
67
|
-
"proof-holdings": {
|
|
68
|
-
"command": "npx",
|
|
69
|
-
"args": ["-y", "@proof-holdings/mcp-server"],
|
|
70
|
-
"env": {
|
|
71
|
-
"PROOF_API_KEY": "pk_live_your_key_here"
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
### Docker
|
|
79
|
-
|
|
80
|
-
Use Docker if you prefer not to install Node.js:
|
|
81
|
-
|
|
82
|
-
```json
|
|
83
|
-
{
|
|
84
|
-
"mcpServers": {
|
|
85
|
-
"proof-holdings": {
|
|
86
|
-
"command": "docker",
|
|
87
|
-
"args": [
|
|
88
|
-
"run", "-i", "--rm",
|
|
89
|
-
"-e", "PROOF_API_KEY=pk_live_your_key_here",
|
|
90
|
-
"ghcr.io/proofholdings/mcp-server"
|
|
91
|
-
]
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
```
|
|
96
|
-
|
|
97
69
|
If installed globally (`npm install -g @proof-holdings/mcp-server`), use `"command": "proof-mcp"` and remove the `"args"` field.
|
|
98
70
|
|
|
99
|
-
## Tools (
|
|
71
|
+
## Tools (171 tools)
|
|
100
72
|
|
|
101
|
-
|
|
73
|
+
Group totals are exact. The tables name the tools you are most likely to reach for rather than all
|
|
74
|
+
of them — your MCP client's own `tools/list` is the complete, current list, and it is the one this
|
|
75
|
+
server answers from.
|
|
102
76
|
|
|
103
|
-
|
|
104
|
-
|---|---|
|
|
105
|
-
| `create_verification` | Create a new verification |
|
|
106
|
-
| `get_verification` | Get a verification by ID |
|
|
107
|
-
| `list_verifications` | List verifications with optional filters |
|
|
108
|
-
| `trigger_verification` | Trigger a DNS/HTTP verification check |
|
|
109
|
-
| `submit_verification_code` | Submit an OTP/challenge code |
|
|
110
|
-
| `resend_verification` | Resend a verification (email channel) |
|
|
111
|
-
| `test_verify` | Auto-complete a verification (test mode only) |
|
|
112
|
-
| `list_verified_users` | List verified users grouped by external user ID |
|
|
113
|
-
| `get_verified_user` | Get a verified user's verifications |
|
|
114
|
-
| `start_domain_verification` | Start a B2B domain verification |
|
|
115
|
-
| `check_domain_verification` | Check a pending domain verification |
|
|
116
|
-
| `wait_for_verification` | Poll until verification reaches terminal state |
|
|
117
|
-
|
|
118
|
-
### Verification Requests (6)
|
|
77
|
+
### Verifications & requests (28 tools)
|
|
119
78
|
|
|
120
79
|
| Tool | Description |
|
|
121
80
|
|---|---|
|
|
122
|
-
| `
|
|
123
|
-
| `
|
|
124
|
-
| `
|
|
125
|
-
| `
|
|
126
|
-
| `
|
|
127
|
-
| `
|
|
81
|
+
| `create_verification` | Create a verification challenge |
|
|
82
|
+
| `get_verification` | Get verification status |
|
|
83
|
+
| `submit_verification_code` | Submit a verification code |
|
|
84
|
+
| `trigger_verification` | Trigger a verification check |
|
|
85
|
+
| `wait_for_verification` | Poll until it completes |
|
|
86
|
+
| `create_multi_channel_verification` | One phone, up to three channels, first completion wins |
|
|
87
|
+
| `create_verification_request` | Create a multi-asset request |
|
|
88
|
+
| `get_request_by_reference` | Look a request up by reference id |
|
|
128
89
|
|
|
129
|
-
###
|
|
90
|
+
### Domains & DNS (23 tools)
|
|
130
91
|
|
|
131
92
|
| Tool | Description |
|
|
132
93
|
|---|---|
|
|
133
|
-
| `
|
|
134
|
-
| `
|
|
135
|
-
| `
|
|
136
|
-
| `
|
|
94
|
+
| `add_domain` | Add a domain to verify |
|
|
95
|
+
| `verify_domain` | Check the challenge record and mint the proof |
|
|
96
|
+
| `connect_cloudflare` | Connect Cloudflare so records are written for you |
|
|
97
|
+
| `verify_domain_with_credentials` | Prove control using stored credentials |
|
|
98
|
+
| `setup_domain_email` | Set up sending from the domain |
|
|
137
99
|
|
|
138
|
-
###
|
|
100
|
+
### Account, settings & billing (37 tools)
|
|
139
101
|
|
|
140
102
|
| Tool | Description |
|
|
141
103
|
|---|---|
|
|
142
|
-
| `
|
|
143
|
-
| `
|
|
144
|
-
| `
|
|
104
|
+
| `get_platform_summary` | One-call snapshot of the account |
|
|
105
|
+
| `get_usage` | Quota and usage for the period |
|
|
106
|
+
| `search` | Search across the account |
|
|
107
|
+
| `create_account` | Bootstrap a new account (no key needed) |
|
|
108
|
+
| `create_api_key` | Create a scoped API key |
|
|
109
|
+
| `list_assets` | List verified assets and their proof handles |
|
|
145
110
|
|
|
146
|
-
###
|
|
111
|
+
### HITL approvals & consent (22 tools)
|
|
147
112
|
|
|
148
113
|
| Tool | Description |
|
|
149
114
|
|---|---|
|
|
150
|
-
| `
|
|
151
|
-
| `
|
|
152
|
-
| `
|
|
115
|
+
| `create_hitl` | Create a human-approval configuration |
|
|
116
|
+
| `create_confirmation` | Send an approval request to a person |
|
|
117
|
+
| `wait_for_confirmation` | Poll until a person approves or denies |
|
|
118
|
+
| `create_authorization` | Ask a person to consent to being contacted |
|
|
119
|
+
| `revoke_authorization` | Withdraw a consent |
|
|
153
120
|
|
|
154
|
-
###
|
|
121
|
+
### Circles & Proof of Me (15 tools)
|
|
155
122
|
|
|
156
123
|
| Tool | Description |
|
|
157
124
|
|---|---|
|
|
158
|
-
| `
|
|
159
|
-
| `
|
|
160
|
-
| `
|
|
125
|
+
| `create_circle` | Create a circle of trusted contacts |
|
|
126
|
+
| `add_circle_member` | Add a contact |
|
|
127
|
+
| `invite_circle_member` | Send a single-use enrollment link |
|
|
128
|
+
| `create_identity_challenge` | Run a cross-channel identity check |
|
|
161
129
|
|
|
162
|
-
###
|
|
130
|
+
### Public profiles (16 tools)
|
|
163
131
|
|
|
164
132
|
| Tool | Description |
|
|
165
133
|
|---|---|
|
|
166
|
-
| `
|
|
167
|
-
| `
|
|
168
|
-
| `
|
|
169
|
-
| `export_data` | Export account data |
|
|
134
|
+
| `create_profile` | Create a public profile |
|
|
135
|
+
| `claim_username` | Claim a public username |
|
|
136
|
+
| `update_public_proofs` | Choose which proofs a profile shows |
|
|
170
137
|
|
|
171
|
-
### Templates (
|
|
138
|
+
### Templates & webhooks (11 tools)
|
|
172
139
|
|
|
173
140
|
| Tool | Description |
|
|
174
141
|
|---|---|
|
|
175
142
|
| `list_templates` | List message templates |
|
|
176
|
-
| `get_default_templates` | Get default templates |
|
|
177
|
-
| `get_template` | Get a template by channel and type |
|
|
178
|
-
| `update_template` | Update a template |
|
|
179
|
-
| `delete_template` | Delete a custom template |
|
|
180
|
-
| `preview_template` | Preview a rendered template |
|
|
181
143
|
| `render_template` | Render a template with variables |
|
|
144
|
+
| `list_webhook_deliveries` | List webhook deliveries |
|
|
145
|
+
| `retry_webhook_delivery` | Retry a failed delivery |
|
|
182
146
|
|
|
183
|
-
###
|
|
147
|
+
### Delegations & proofs (10 tools)
|
|
184
148
|
|
|
185
149
|
| Tool | Description |
|
|
186
150
|
|---|---|
|
|
187
|
-
| `
|
|
188
|
-
| `
|
|
189
|
-
| `
|
|
190
|
-
| `
|
|
151
|
+
| `create_delegation` | Authorize an artifact from a domain you have proven |
|
|
152
|
+
| `revoke_delegation` | Revoke a delegation |
|
|
153
|
+
| `verify_delegation` | Check whether an artifact is authorized by the domain it claims |
|
|
154
|
+
| `validate_proof` | Verify a signed proof token (no key needed) |
|
|
155
|
+
| `get_proof_status` | Read a proof's status by its public handle |
|
|
156
|
+
| `list_revoked_proofs` | Read the revocation list (no key needed) |
|
|
191
157
|
|
|
192
|
-
###
|
|
158
|
+
### Sign-in & sessions (9 tools)
|
|
193
159
|
|
|
194
160
|
| Tool | Description |
|
|
195
161
|
|---|---|
|
|
196
|
-
| `
|
|
162
|
+
| `start_login` | Begin a sign-in (no key needed) |
|
|
163
|
+
| `wait_for_login` | Poll until sign-in completes |
|
|
164
|
+
| `get_current_user` | Who the current session belongs to |
|
|
165
|
+
| `render_auth_link` | Render a sign-in link for the user to open |
|
|
197
166
|
|
|
198
|
-
|
|
167
|
+
## Test Mode
|
|
199
168
|
|
|
200
|
-
|
|
201
|
-
|---|---|
|
|
202
|
-
| `list_projects` | List projects |
|
|
203
|
-
| `create_project` | Create a project |
|
|
204
|
-
| `get_project` | Get a project by ID |
|
|
205
|
-
| `update_project` | Update a project |
|
|
206
|
-
| `delete_project` | Delete a project |
|
|
207
|
-
| `list_project_templates` | List project templates |
|
|
208
|
-
| `update_project_template` | Update a project template |
|
|
209
|
-
| `delete_project_template` | Delete a project template |
|
|
210
|
-
| `preview_project_template` | Preview a project template |
|
|
211
|
-
|
|
212
|
-
### Profiles (10)
|
|
169
|
+
Use a test-mode API key (`pk_test_*`) to interact with the API without creating real verifications. Test-mode keys are available in your [dashboard](https://proof.holdings/dashboard/api-keys).
|
|
213
170
|
|
|
214
|
-
|
|
215
|
-
|---|---|
|
|
216
|
-
| `list_profiles` | List profiles |
|
|
217
|
-
| `create_profile` | Create a profile |
|
|
218
|
-
| `get_profile` | Get a profile by ID |
|
|
219
|
-
| `update_profile` | Update a profile |
|
|
220
|
-
| `delete_profile` | Delete a profile |
|
|
221
|
-
| `set_primary_profile` | Set a profile as primary |
|
|
222
|
-
| `update_profile_proofs` | Update profile proofs |
|
|
223
|
-
| `get_my_profile` | Get your public profile |
|
|
224
|
-
| `update_my_profile` | Update your public profile |
|
|
225
|
-
| `get_profile_assets` | Get profile assets |
|
|
226
|
-
|
|
227
|
-
### Emails (7)
|
|
171
|
+
## Transport
|
|
228
172
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
173
|
+
Two transports ship in this package:
|
|
174
|
+
|
|
175
|
+
- **stdio** (default, `mcp-server` / `proof-mcp`) — the server communicates over stdin/stdout. One
|
|
176
|
+
user per process; this is what a client launches locally.
|
|
177
|
+
- **Streamable HTTP** (`node dist/remote.js`) — a remote server that many users connect to over the
|
|
178
|
+
network by URL, with no install. A connection starts ANONYMOUS — the keyless surface (account
|
|
179
|
+
bootstrap, login, proof and delegation verification) works with no credential at all — and a tool
|
|
180
|
+
that needs an account answers `401` with a `WWW-Authenticate` challenge naming the authorization
|
|
181
|
+
server, which is what a standards-compliant client follows to sign in. The 401 lands on the TOOL
|
|
182
|
+
CALL and never on a bare `initialize` or `tools/list` FOR AN ANONYMOUS CONNECTION: measured
|
|
183
|
+
against live clients, refusing an anonymous handshake reads to the user as a connection timeout
|
|
184
|
+
rather than as an invitation to log in. Three shapes are refused at the handshake instead — a
|
|
185
|
+
presented token that does not resolve (there the 401 is what makes a client refresh), a request
|
|
186
|
+
whose credential does not match the session it names, and an opening batch that smuggles a keyed
|
|
187
|
+
tool call alongside `initialize`. A
|
|
188
|
+
signed-in client sends the API key it was granted in the `Authorization` header — the only place a
|
|
189
|
+
credential is read, never a query parameter — and each connection gets its own server and HTTP
|
|
190
|
+
client, so one user's key or session can never reach another. `PORT` (default 3100),
|
|
191
|
+
`MCP_MAX_SESSIONS` (default 100), `MCP_SESSION_TTL_MS` (default 30 min, counted from the last POST
|
|
192
|
+
the server ACCEPTED — one it answered below 400. A POST refused before any work happens does not
|
|
193
|
+
postpone it, whether the refusal is ours (body over 4MB) or the transport's (unparseable or empty
|
|
194
|
+
body, unsupported `mcp-protocol-version`, a second `initialize`); and an open event stream is a
|
|
195
|
+
connection, not activity, so a session whose only traffic is that stream ages out. **The official
|
|
196
|
+
client does not recover from this on its
|
|
197
|
+
own**: measured against SDK 1.27.1, the stream's reconnect gives up after two attempts and the
|
|
198
|
+
next tool call fails with `unknown_session` until the host reconnects the server. Size the TTL
|
|
199
|
+
with that in mind — it is a memory bound paid for in reconnects, not a transparent one);
|
|
200
|
+
`/healthz` reports the live session count.
|
|
201
|
+
|
|
202
|
+
## Delegation (`_meta`)
|
|
203
|
+
|
|
204
|
+
The server card (`server.json`) can carry a **Proof of Delegation** publication under the
|
|
205
|
+
namespaced `_meta` key `holdings.proof/delegation`:
|
|
238
206
|
|
|
239
|
-
|
|
207
|
+
```json
|
|
208
|
+
{
|
|
209
|
+
"_meta": {
|
|
210
|
+
"holdings.proof/delegation": { "token": "<delegation JWT>" }
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
```
|
|
240
214
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
| `get_add_phone_status` | Get phone addition status |
|
|
215
|
+
The token is an ES256 JWT minted by [proof.holdings](https://proof.holdings) attesting exactly
|
|
216
|
+
one thing: **the controller of the `principal` domain authorized the `delegate` artifact for the
|
|
217
|
+
listed scopes.** It is not a statement that the server is safe, audited, or endorsed. A verifier
|
|
218
|
+
checks the signature against the issuer JWKS, then compares `principal` and `delegate` to facts
|
|
219
|
+
it resolved itself — a token copied into another package fails that comparison, because its
|
|
220
|
+
`delegate` names the genuine artifact. Details: [Delegations — API reference](https://proof.holdings/docs/api#delegations).
|
|
248
221
|
|
|
249
|
-
|
|
222
|
+
When the card is published through the official MCP registry, the same entry is nested under
|
|
223
|
+
`_meta["io.modelcontextprotocol.registry/publisher-provided"]` — readers should check both
|
|
224
|
+
locations.
|
|
250
225
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
| `list_api_keys` | List API keys |
|
|
254
|
-
| `create_api_key` | Create an API key (2FA required) |
|
|
255
|
-
| `revoke_api_key` | Revoke an API key (2FA required) |
|
|
256
|
-
| `regenerate_api_key` | Regenerate an API key (2FA required) |
|
|
226
|
+
Maintainers: the entry is written by the fail-closed publish tool, never by hand — from the
|
|
227
|
+
repository root, after the delegation is minted for `pkg:npm/@proof-holdings/mcp-server`:
|
|
257
228
|
|
|
258
|
-
|
|
229
|
+
```bash
|
|
230
|
+
npm run delegation:publish -- --target mcp --token <jwt>
|
|
231
|
+
# or mint + publish in one step (needs PROOF_API_KEY):
|
|
232
|
+
npm run delegation:publish -- --target mcp --mint \
|
|
233
|
+
--control-proof ph_ctl_<32hex> --scope proof-verification
|
|
234
|
+
```
|
|
259
235
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
| `verify_2fa_magic_link` | Verify via 2FA magic link |
|
|
236
|
+
The tool refuses any token whose claims do not name this exact package with
|
|
237
|
+
`principal: proof.holdings` (the same check `--target a2a` performs against the A2A agent
|
|
238
|
+
card's own `url` before regenerating `/.well-known/agent-card.json`). For `--target a2a`,
|
|
239
|
+
if the card-regeneration step fails after the source file is written, just re-run the
|
|
240
|
+
command — the token is already validated and the regeneration is idempotent.
|
|
266
241
|
|
|
267
|
-
###
|
|
242
|
+
### Verifying someone else's delegation (`verify_delegation`)
|
|
268
243
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
| `get_domain` | Get a domain by ID |
|
|
274
|
-
| `delete_domain` | Delete a domain |
|
|
275
|
-
| `verify_domain` | Verify a domain (DNS check) |
|
|
276
|
-
| `connect_cloudflare` | Connect domain via Cloudflare |
|
|
277
|
-
| `connect_godaddy` | Connect domain via GoDaddy |
|
|
278
|
-
| `connect_dns_provider` | Connect domain via DNS provider |
|
|
279
|
-
| `add_verification_provider` | Add a verification provider to a domain |
|
|
280
|
-
| `get_dns_providers` | Get available DNS providers |
|
|
281
|
-
| `verify_domain_with_credentials` | Verify domain with stored credentials |
|
|
282
|
-
| `check_domain_credentials` | Check domain credential status |
|
|
283
|
-
| `start_domain_email_verification` | Start domain email verification |
|
|
284
|
-
| `confirm_domain_email_code` | Confirm domain email verification code |
|
|
285
|
-
| `resend_domain_email` | Resend domain verification email |
|
|
286
|
-
| `setup_domain_email` | Set up domain email forwarding |
|
|
287
|
-
| `check_domain_email_status` | Check domain email setup status |
|
|
288
|
-
|
|
289
|
-
### DNS Credentials (3)
|
|
244
|
+
This server also **checks** delegations, not just publishes one. The `verify_delegation` tool
|
|
245
|
+
runs the reference verifier ([`@proof-holdings/delegation-verifier`](https://github.com/ProofHoldings/delegation-verifier))
|
|
246
|
+
over another server's card and needs **no API key** — verification runs against public surfaces
|
|
247
|
+
only.
|
|
290
248
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
249
|
+
```jsonc
|
|
250
|
+
{
|
|
251
|
+
"card": { /* the MCP server.json or A2A agent card you fetched */ },
|
|
252
|
+
"delegate": { "type": "purl", "value": "pkg:npm/postmark-mcp" },
|
|
253
|
+
"expected_principal": "postmarkapp.com"
|
|
254
|
+
}
|
|
255
|
+
```
|
|
296
256
|
|
|
297
|
-
|
|
257
|
+
Both pins are **required**, and they close different attacks:
|
|
298
258
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
| `share_request_email` | Share a request via email |
|
|
259
|
+
- `delegate` must be the artifact identity **you** resolved — the package you are about to
|
|
260
|
+
install, the endpoint you are about to call. Never copy it out of the card being checked: a
|
|
261
|
+
published token is a bearer artifact, so comparing it against a field of the same card would
|
|
262
|
+
bless a token pasted in from somewhere else.
|
|
263
|
+
- `expected_principal` is the domain you expect to stand behind it. An issuer binds the
|
|
264
|
+
artifact to nothing, so any domain owner can mint a genuine, signature-valid delegation
|
|
265
|
+
naming someone else's package. Without this pin a verdict would only mean "some domain
|
|
266
|
+
claims this".
|
|
308
267
|
|
|
309
|
-
###
|
|
268
|
+
### Re-checking everything you already trust (`verify_delegations`)
|
|
310
269
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
| `get_user_domain_verification_status` | Get domain verification status |
|
|
315
|
-
| `check_user_domain_verification` | Check domain verification result |
|
|
270
|
+
`verify_delegation` answers "is this one good, right now, because you asked". If an agent has
|
|
271
|
+
already resolved and verified thirty-five artifacts, re-verifying them one call at a time does
|
|
272
|
+
not scale — `verify_delegations` batch-checks up to 50 in a single call, also with **no API key**.
|
|
316
273
|
|
|
317
|
-
|
|
274
|
+
```jsonc
|
|
275
|
+
{
|
|
276
|
+
"items": [
|
|
277
|
+
{ "card": { /* ... */ }, "delegate": { "type": "purl", "value": "pkg:npm/postmark-mcp" }, "expected_principal": "postmarkapp.com" },
|
|
278
|
+
{ "token": "<jwt>", "delegate": { "type": "url", "value": "https://example.com/mcp" }, "expected_principal": "example.com" }
|
|
279
|
+
]
|
|
280
|
+
}
|
|
281
|
+
```
|
|
318
282
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
283
|
+
Each item takes exactly the shape `verify_delegation` requires (`card` XOR `token`, `delegate`,
|
|
284
|
+
`expected_principal`, optional `required_scopes`) and is verified **independently** — no
|
|
285
|
+
cross-item state, nothing persisted, and one item failing never affects another item's result.
|
|
286
|
+
Revocation is always checked (there is no `check_status: false` on this tool — the entire point
|
|
287
|
+
of a batch re-check is to see what changed).
|
|
323
288
|
|
|
324
|
-
|
|
289
|
+
**Two things this tool deliberately does NOT do:**
|
|
325
290
|
|
|
326
|
-
|
|
291
|
+
- **It does not discover what you have installed.** You must already hold each artifact's
|
|
292
|
+
`card` or `token`. It has no DNS-pointer resolution and fetches no caller-supplied URL —
|
|
293
|
+
the same trust boundary `verify_delegation` already draws, kept narrow on purpose (see
|
|
294
|
+
`src/services/delegationPointer/resolve.ts`'s documented gaps in the main repository, which
|
|
295
|
+
this tool stays outside of).
|
|
296
|
+
- **It does not run continuously.** Each call is a single point-in-time check. There is no
|
|
297
|
+
cadence, no scheduler, no push notification — call it again whenever you want a fresh answer.
|
|
327
298
|
|
|
328
|
-
|
|
299
|
+
Each result in `results[]` carries an `outcome`, one of four buckets:
|
|
300
|
+
|
|
301
|
+
| Outcome | Meaning |
|
|
302
|
+
| --- | --- |
|
|
303
|
+
| `confirmed_valid` | The delegation verified — same meaning as `verify_delegation`'s `verified: true`. |
|
|
304
|
+
| `confirmed_invalid` | A genuine negative verdict: revoked, suspended, expired, a mismatched principal or delegate, an ungranted scope, or a malformed/untrusted/badly-signed token. |
|
|
305
|
+
| `no_claim_found` | The artifact publishes no delegation at all. An absence, never an accusation. |
|
|
306
|
+
| `unconfirmed` | We could not reach the issuer or otherwise get a confident answer right now (e.g. its JWKS or status endpoint is unreachable). **Never treat this as a bad verdict** — it means "ask again later", not "revoked". |
|
|
307
|
+
|
|
308
|
+
A result also carries `checked_at` — the ISO timestamp of the moment **that item's own check**
|
|
309
|
+
completed, not one timestamp shared across the whole call — so "established locally" is never
|
|
310
|
+
presented as "established by reaching us, at this moment" without saying which.
|
|
311
|
+
|
|
312
|
+
### ⚠️ Release order (maintainers)
|
|
313
|
+
|
|
314
|
+
`package.json` declares `@proof-holdings/delegation-verifier` as a **runtime** dependency, so the
|
|
315
|
+
range it names has to be resolvable on the registry before this package is uploaded:
|
|
316
|
+
|
|
317
|
+
**`@proof-holdings/delegation-verifier` is published BEFORE `@proof-holdings/mcp-server`, on every
|
|
318
|
+
release that moves the range.** This server is launched via `npx` by every documented client, so a
|
|
319
|
+
release whose dependency the registry cannot resolve makes `npx @proof-holdings/mcp-server` fail
|
|
320
|
+
with E404 for everyone until the verifier lands. A run of
|
|
321
|
+
`.github/workflows/publish-packages.yml` with `target: all` enforces the order by its step order;
|
|
322
|
+
a publish by hand from a terminal has nothing enforcing it but `docs/runbooks/npm-release.md`.
|
|
323
|
+
|
|
324
|
+
Working on the verifier and the server together does not need a publish. Link the sibling instead:
|
|
325
|
+
|
|
326
|
+
```bash
|
|
327
|
+
npm run verifier:link # cd mcp && npm install ../packages/delegation-verifier --no-save
|
|
328
|
+
```
|
|
329
329
|
|
|
330
|
-
|
|
330
|
+
The test suite needs no link at all: it resolves the verifier's SOURCE through a vitest alias
|
|
331
|
+
rather than `node_modules`, so it is green on a fresh clone and picks up an uncommitted verifier
|
|
332
|
+
change without a build.
|
|
331
333
|
|
|
332
334
|
## Requirements
|
|
333
335
|
|
|
334
336
|
- Node.js >= 18.0.0
|
|
335
|
-
- A proof.holdings API key
|
|
337
|
+
- A proof.holdings API key for the keyed tools. The server starts and answers the keyless ones
|
|
338
|
+
without it — see Configuration above.
|
|
336
339
|
|
|
337
340
|
## Links
|
|
338
341
|
|