@attest-dev/sdk 0.1.0-beta.1
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/README.md +119 -0
- package/dist/index.d.ts +127 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +167 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp.d.ts +312 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +599 -0
- package/dist/mcp.js.map +1 -0
- package/package.json +38 -0
package/dist/mcp.js
ADDED
|
@@ -0,0 +1,599 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @attest-dev/sdk/mcp — Attest credential enforcement middleware for MCP servers.
|
|
4
|
+
*
|
|
5
|
+
* Wraps any MCP server instance and enforces Attest credential checking on
|
|
6
|
+
* every tool call before the underlying handler executes.
|
|
7
|
+
*
|
|
8
|
+
* ## Two-line integration
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
12
|
+
* import { withAttest } from "@attest-dev/sdk/mcp";
|
|
13
|
+
*
|
|
14
|
+
* const server = new McpServer({ name: "my-tools", version: "1.0.0" });
|
|
15
|
+
* const protectedServer = withAttest(server, {
|
|
16
|
+
* issuerUri: "https://api.attest.dev",
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* // Register tools exactly as before — every call is now credential-gated.
|
|
20
|
+
* protectedServer.tool("send_email", "Send an email", schema, handler);
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* ## How it works
|
|
24
|
+
*
|
|
25
|
+
* `withAttest` monkey-patches `server.tool()` so each registered handler is
|
|
26
|
+
* wrapped with a credential check closure. On every tool call the closure:
|
|
27
|
+
*
|
|
28
|
+
* 1. Extracts the Attest JWT from `extra.authInfo.token` (set by the MCP
|
|
29
|
+
* auth middleware) or `extra.meta?.attest_token`.
|
|
30
|
+
* 2. Verifies the JWT offline against the issuer's JWKS (cached per TTL).
|
|
31
|
+
* 3. Maps the tool name to a Attest scope string via `scopeForTool()`.
|
|
32
|
+
* 4. Confirms the credential's `att_scope` covers the required scope.
|
|
33
|
+
* 5. Calls the Attest revocation endpoint to confirm the JTI is still live.
|
|
34
|
+
* 6. If all checks pass, executes the original handler.
|
|
35
|
+
* 7. If any check fails, returns a structured `attest_violation` error.
|
|
36
|
+
* 8. Fire-and-forgets an audit event to the Attest server regardless of
|
|
37
|
+
* outcome.
|
|
38
|
+
*/
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.scopeForTool = scopeForTool;
|
|
41
|
+
exports.withAttest = withAttest;
|
|
42
|
+
exports.getAttestContext = getAttestContext;
|
|
43
|
+
exports.getAttestScopes = getAttestScopes;
|
|
44
|
+
const jose_1 = require("jose");
|
|
45
|
+
// ── scopeForTool ──────────────────────────────────────────────────────────────
|
|
46
|
+
/**
|
|
47
|
+
* Maps an MCP tool name to a Attest scope string using a convention-based
|
|
48
|
+
* approach. The tool name is split on the first underscore: the part before
|
|
49
|
+
* becomes the action; the rest (joined with `:`) becomes the resource.
|
|
50
|
+
*
|
|
51
|
+
* Action aliases:
|
|
52
|
+
* - `create`, `update`, `write`, `put`, `patch` → `write`
|
|
53
|
+
* - `remove`, `destroy` → `delete`
|
|
54
|
+
* - `run`, `invoke` → `execute`
|
|
55
|
+
* - `get`, `fetch`, `list`, `search`, `query` → `read`
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* scopeForTool("send_email") // "email:send"
|
|
59
|
+
* scopeForTool("read_file") // "file:read"
|
|
60
|
+
* scopeForTool("delete_calendar_event") // "calendar_event:delete"
|
|
61
|
+
* scopeForTool("create_user") // "user:write"
|
|
62
|
+
* scopeForTool("run_query") // "query:execute"
|
|
63
|
+
*/
|
|
64
|
+
function scopeForTool(toolName, overrides) {
|
|
65
|
+
if (overrides?.[toolName])
|
|
66
|
+
return overrides[toolName];
|
|
67
|
+
const idx = toolName.indexOf('_');
|
|
68
|
+
if (idx === -1) {
|
|
69
|
+
// No underscore — treat the whole name as both resource and action.
|
|
70
|
+
return `${toolName}:execute`;
|
|
71
|
+
}
|
|
72
|
+
const rawAction = toolName.slice(0, idx).toLowerCase();
|
|
73
|
+
const resource = toolName.slice(idx + 1).toLowerCase();
|
|
74
|
+
const action = normaliseAction(rawAction);
|
|
75
|
+
return `${resource}:${action}`;
|
|
76
|
+
}
|
|
77
|
+
const ACTION_ALIASES = {
|
|
78
|
+
// write
|
|
79
|
+
create: 'write',
|
|
80
|
+
update: 'write',
|
|
81
|
+
put: 'write',
|
|
82
|
+
patch: 'write',
|
|
83
|
+
set: 'write',
|
|
84
|
+
upsert: 'write',
|
|
85
|
+
// delete
|
|
86
|
+
remove: 'delete',
|
|
87
|
+
destroy: 'delete',
|
|
88
|
+
// execute
|
|
89
|
+
run: 'execute',
|
|
90
|
+
invoke: 'execute',
|
|
91
|
+
call: 'execute',
|
|
92
|
+
// read
|
|
93
|
+
get: 'read',
|
|
94
|
+
fetch: 'read',
|
|
95
|
+
list: 'read',
|
|
96
|
+
search: 'read',
|
|
97
|
+
query: 'read',
|
|
98
|
+
find: 'read',
|
|
99
|
+
lookup: 'read',
|
|
100
|
+
};
|
|
101
|
+
function normaliseAction(raw) {
|
|
102
|
+
return ACTION_ALIASES[raw] ?? raw;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Thin wrapper around `jose`'s `createRemoteJWKSet` that respects the
|
|
106
|
+
* configured cache TTL. A new key-set is created when the TTL expires,
|
|
107
|
+
* which forces a JWKS re-fetch on the next verification.
|
|
108
|
+
*/
|
|
109
|
+
class JwksCache {
|
|
110
|
+
issuerUri;
|
|
111
|
+
ttlMs;
|
|
112
|
+
keySet = null;
|
|
113
|
+
createdAt = 0;
|
|
114
|
+
constructor(issuerUri, ttlSeconds) {
|
|
115
|
+
this.issuerUri = issuerUri.replace(/\/$/, '');
|
|
116
|
+
this.ttlMs = ttlSeconds * 1000;
|
|
117
|
+
}
|
|
118
|
+
get() {
|
|
119
|
+
const now = Date.now();
|
|
120
|
+
if (this.keySet === null || now - this.createdAt > this.ttlMs) {
|
|
121
|
+
this.keySet = (0, jose_1.createRemoteJWKSet)(new URL(`${this.issuerUri}/.well-known/jwks.json`),
|
|
122
|
+
// jose's internal cache is effectively bypassed by recreating the key
|
|
123
|
+
// set on TTL expiry — fine for our use-case.
|
|
124
|
+
{ cacheMaxAge: this.ttlMs });
|
|
125
|
+
this.createdAt = now;
|
|
126
|
+
}
|
|
127
|
+
return this.keySet;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Short-lived in-process cache for revocation status.
|
|
132
|
+
* Reduces network calls to the Attest server on hot paths.
|
|
133
|
+
*/
|
|
134
|
+
class RevocationCache {
|
|
135
|
+
cache = new Map();
|
|
136
|
+
ttlMs;
|
|
137
|
+
issuerUri;
|
|
138
|
+
constructor(issuerUri, ttlSeconds) {
|
|
139
|
+
this.issuerUri = issuerUri.replace(/\/$/, '');
|
|
140
|
+
this.ttlMs = ttlSeconds * 1000;
|
|
141
|
+
}
|
|
142
|
+
async isRevoked(jti) {
|
|
143
|
+
const now = Date.now();
|
|
144
|
+
const cached = this.cache.get(jti);
|
|
145
|
+
if (cached !== undefined && now < cached.expiresAt) {
|
|
146
|
+
return cached.revoked;
|
|
147
|
+
}
|
|
148
|
+
const revoked = await this.fetchRevocationStatus(jti);
|
|
149
|
+
if (this.ttlMs > 0) {
|
|
150
|
+
this.cache.set(jti, { revoked, expiresAt: now + this.ttlMs });
|
|
151
|
+
}
|
|
152
|
+
return revoked;
|
|
153
|
+
}
|
|
154
|
+
/** Evict a JTI immediately (e.g. after a revocation call). */
|
|
155
|
+
evict(jti) {
|
|
156
|
+
this.cache.delete(jti);
|
|
157
|
+
}
|
|
158
|
+
async fetchRevocationStatus(jti) {
|
|
159
|
+
try {
|
|
160
|
+
const res = await fetch(`${this.issuerUri}/v1/revoked/${encodeURIComponent(jti)}`);
|
|
161
|
+
if (!res.ok)
|
|
162
|
+
return false; // fail-open on network error
|
|
163
|
+
const body = (await res.json());
|
|
164
|
+
return body.revoked === true;
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
// Fail-open: don't block tools because the revocation endpoint is down.
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
function isScopeGranted(grantedScope, requiredScope) {
|
|
173
|
+
const [reqResource, reqAction] = requiredScope.split(':');
|
|
174
|
+
if (!reqResource || !reqAction)
|
|
175
|
+
return false;
|
|
176
|
+
return grantedScope.some(entry => {
|
|
177
|
+
const [resource, action] = entry.split(':');
|
|
178
|
+
if (!resource || !action)
|
|
179
|
+
return false;
|
|
180
|
+
const resourceOk = resource === '*' || resource === reqResource;
|
|
181
|
+
const actionOk = action === '*' || action === reqAction;
|
|
182
|
+
return resourceOk && actionOk;
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
// ── Token extraction ──────────────────────────────────────────────────────────
|
|
186
|
+
/**
|
|
187
|
+
* Pulls the raw JWT string from an MCP tool call's `extra` argument.
|
|
188
|
+
*
|
|
189
|
+
* Lookup order:
|
|
190
|
+
* 1. `extra.authInfo.token` — set by the MCP auth middleware (preferred)
|
|
191
|
+
* 2. `extra.meta.attest_token` — explicit pass-through from the agent
|
|
192
|
+
* 3. `extra.meta.authorization` — raw "Bearer <token>" header value
|
|
193
|
+
*
|
|
194
|
+
* Returns `null` when no credential can be found.
|
|
195
|
+
*/
|
|
196
|
+
function extractToken(extra) {
|
|
197
|
+
// 1. Standard MCP auth middleware path.
|
|
198
|
+
if (extra.authInfo?.token)
|
|
199
|
+
return extra.authInfo.token;
|
|
200
|
+
const meta = extra.meta;
|
|
201
|
+
if (!meta)
|
|
202
|
+
return null;
|
|
203
|
+
// 2. Explicit attest_token field.
|
|
204
|
+
if (typeof meta['attest_token'] === 'string' && meta['attest_token']) {
|
|
205
|
+
return meta['attest_token'];
|
|
206
|
+
}
|
|
207
|
+
// 3. Raw Authorization header forwarded via meta.
|
|
208
|
+
if (typeof meta['authorization'] === 'string') {
|
|
209
|
+
const auth = meta['authorization'];
|
|
210
|
+
if (auth.startsWith('Bearer '))
|
|
211
|
+
return auth.slice(7).trim();
|
|
212
|
+
return auth.trim() || null;
|
|
213
|
+
}
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Fire-and-forget audit event to the Attest server.
|
|
218
|
+
*
|
|
219
|
+
* Delivery is async and never blocks the tool call. On failure, errors are
|
|
220
|
+
* surfaced in priority order:
|
|
221
|
+
* 1. `onAuditError(error, payload)` — caller handles retry / fallback log
|
|
222
|
+
* 2. `onViolation({ reason: "audit_failure", ... })` — surfaces to monitoring
|
|
223
|
+
* 3. `console.warn` — last resort, never silently dropped
|
|
224
|
+
*/
|
|
225
|
+
function fireAudit(issuerUri, payload, onAuditError, onViolation) {
|
|
226
|
+
void fetch(`${issuerUri}/v1/audit`, {
|
|
227
|
+
method: 'POST',
|
|
228
|
+
headers: { 'Content-Type': 'application/json' },
|
|
229
|
+
body: JSON.stringify(payload),
|
|
230
|
+
})
|
|
231
|
+
.then(async (res) => {
|
|
232
|
+
if (!res.ok) {
|
|
233
|
+
// Non-2xx is also a delivery failure — treat it the same as a network error.
|
|
234
|
+
let body = '';
|
|
235
|
+
try {
|
|
236
|
+
body = await res.text();
|
|
237
|
+
}
|
|
238
|
+
catch { /* ignore */ }
|
|
239
|
+
throw new Error(`Attest audit endpoint returned ${res.status}: ${body}`);
|
|
240
|
+
}
|
|
241
|
+
})
|
|
242
|
+
.catch((err) => {
|
|
243
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
244
|
+
if (onAuditError) {
|
|
245
|
+
onAuditError(error, payload);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
if (onViolation) {
|
|
249
|
+
onViolation({
|
|
250
|
+
toolName: payload.agent_id,
|
|
251
|
+
requiredScope: '',
|
|
252
|
+
grantedScope: payload.scope,
|
|
253
|
+
reason: 'audit_failure',
|
|
254
|
+
...(payload.jti ? { jti: payload.jti } : {}),
|
|
255
|
+
...(payload.att_tid ? { taskId: payload.att_tid } : {}),
|
|
256
|
+
timestamp: new Date().toISOString(),
|
|
257
|
+
});
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
// Last resort: never silently drop an audit failure.
|
|
261
|
+
console.warn('[attest] Audit delivery failed — configure onAuditError for structured handling.', { jti: payload.jti, agent_id: payload.agent_id, error: error.message });
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
// ── Core enforcer ─────────────────────────────────────────────────────────────
|
|
265
|
+
class AttestEnforcer {
|
|
266
|
+
issuerUri;
|
|
267
|
+
requireCredential;
|
|
268
|
+
onViolation;
|
|
269
|
+
onAuditError;
|
|
270
|
+
toolScopeMap;
|
|
271
|
+
jwks;
|
|
272
|
+
revocations;
|
|
273
|
+
constructor(opts) {
|
|
274
|
+
this.issuerUri = opts.issuerUri.replace(/\/$/, '');
|
|
275
|
+
this.requireCredential = opts.requireCredential ?? true;
|
|
276
|
+
this.onViolation = opts.onViolation;
|
|
277
|
+
this.onAuditError = opts.onAuditError;
|
|
278
|
+
this.toolScopeMap = opts.toolScopeMap;
|
|
279
|
+
this.jwks = new JwksCache(this.issuerUri, opts.jwksCacheTTL ?? 3600);
|
|
280
|
+
this.revocations = new RevocationCache(this.issuerUri, opts.revocationCacheTTL ?? 10);
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Resolve the scope string for a tool, preferring an explicit override
|
|
284
|
+
* over the automatic `scopeForTool()` mapping.
|
|
285
|
+
*/
|
|
286
|
+
resolveScope(toolName, explicit) {
|
|
287
|
+
return explicit ?? scopeForTool(toolName, this.toolScopeMap);
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Checks the credential in `extra` for `toolName`.
|
|
291
|
+
*
|
|
292
|
+
* @param resolvedScope Pre-resolved scope string (from `resolveScope`).
|
|
293
|
+
* @returns `null` when the check passes; a `AttestViolationError` otherwise.
|
|
294
|
+
*/
|
|
295
|
+
async check(toolName, extra, resolvedScope) {
|
|
296
|
+
const requiredScope = resolvedScope;
|
|
297
|
+
const rawToken = extractToken(extra);
|
|
298
|
+
// ── 1. No credential ────────────────────────────────────────────────────
|
|
299
|
+
if (!rawToken) {
|
|
300
|
+
return this.violate(toolName, {
|
|
301
|
+
reason: 'no_credential',
|
|
302
|
+
detail: `Tool "${toolName}" requires a Attest credential (scope: ${requiredScope}). Provide an Authorization: Bearer <token> header.`,
|
|
303
|
+
requiredScope,
|
|
304
|
+
grantedScope: [],
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
// ── 2. Decode (without verification) to read claims for error messages ──
|
|
308
|
+
let raw;
|
|
309
|
+
try {
|
|
310
|
+
raw = (0, jose_1.decodeJwt)(rawToken);
|
|
311
|
+
}
|
|
312
|
+
catch {
|
|
313
|
+
return this.violate(toolName, {
|
|
314
|
+
reason: 'invalid_credential',
|
|
315
|
+
detail: 'The provided credential could not be decoded as a JWT.',
|
|
316
|
+
requiredScope,
|
|
317
|
+
grantedScope: [],
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
const jti = raw.jti;
|
|
321
|
+
const taskId = raw.att_tid;
|
|
322
|
+
const grantedScope = raw.att_scope ?? [];
|
|
323
|
+
// ── 3. Verify signature + expiry via JWKS ───────────────────────────────
|
|
324
|
+
try {
|
|
325
|
+
await (0, jose_1.jwtVerify)(rawToken, this.jwks.get(), { algorithms: ['RS256'] });
|
|
326
|
+
}
|
|
327
|
+
catch (err) {
|
|
328
|
+
const isExpiry = err instanceof Error && err.message.toLowerCase().includes('exp');
|
|
329
|
+
return this.violate(toolName, {
|
|
330
|
+
reason: isExpiry ? 'credential_expired' : 'invalid_credential',
|
|
331
|
+
detail: isExpiry
|
|
332
|
+
? `Credential (jti: ${jti}) has expired.`
|
|
333
|
+
: `Credential signature verification failed: ${String(err)}`,
|
|
334
|
+
requiredScope,
|
|
335
|
+
grantedScope,
|
|
336
|
+
...(jti !== undefined ? { jti } : {}),
|
|
337
|
+
...(taskId !== undefined ? { taskId } : {}),
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
// ── 4. Scope check ──────────────────────────────────────────────────────
|
|
341
|
+
if (!isScopeGranted(grantedScope, requiredScope)) {
|
|
342
|
+
const result = this.violate(toolName, {
|
|
343
|
+
reason: 'scope_violation',
|
|
344
|
+
detail: `Credential (jti: ${jti}) grants [${grantedScope.join(', ')}] ` +
|
|
345
|
+
`but tool "${toolName}" requires "${requiredScope}".`,
|
|
346
|
+
requiredScope,
|
|
347
|
+
grantedScope,
|
|
348
|
+
...(jti !== undefined ? { jti } : {}),
|
|
349
|
+
...(taskId !== undefined ? { taskId } : {}),
|
|
350
|
+
});
|
|
351
|
+
fireAudit(this.issuerUri, {
|
|
352
|
+
event_type: 'verified',
|
|
353
|
+
jti: jti ?? 'unknown',
|
|
354
|
+
...(taskId !== undefined ? { att_tid: taskId } : {}),
|
|
355
|
+
...(raw.att_uid !== undefined ? { att_uid: raw.att_uid } : {}),
|
|
356
|
+
agent_id: `mcp:${toolName}`,
|
|
357
|
+
scope: grantedScope,
|
|
358
|
+
meta: { outcome: 'scope_violation', required_scope: requiredScope },
|
|
359
|
+
}, this.onAuditError, this.onViolation);
|
|
360
|
+
return result;
|
|
361
|
+
}
|
|
362
|
+
// ── 5. Revocation check ─────────────────────────────────────────────────
|
|
363
|
+
if (jti) {
|
|
364
|
+
const revoked = await this.revocations.isRevoked(jti);
|
|
365
|
+
if (revoked) {
|
|
366
|
+
const result = this.violate(toolName, {
|
|
367
|
+
reason: 'credential_revoked',
|
|
368
|
+
detail: `Credential (jti: ${jti}) has been revoked.`,
|
|
369
|
+
requiredScope,
|
|
370
|
+
grantedScope,
|
|
371
|
+
jti,
|
|
372
|
+
...(taskId !== undefined ? { taskId } : {}),
|
|
373
|
+
});
|
|
374
|
+
fireAudit(this.issuerUri, {
|
|
375
|
+
event_type: 'revoked',
|
|
376
|
+
jti,
|
|
377
|
+
...(taskId !== undefined ? { att_tid: taskId } : {}),
|
|
378
|
+
...(raw.att_uid !== undefined ? { att_uid: raw.att_uid } : {}),
|
|
379
|
+
agent_id: `mcp:${toolName}`,
|
|
380
|
+
scope: grantedScope,
|
|
381
|
+
meta: { outcome: 'blocked_revoked' },
|
|
382
|
+
}, this.onAuditError, this.onViolation);
|
|
383
|
+
return result;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
// ── 6. All checks passed — log and allow ────────────────────────────────
|
|
387
|
+
fireAudit(this.issuerUri, {
|
|
388
|
+
event_type: 'verified',
|
|
389
|
+
jti: jti ?? 'unknown',
|
|
390
|
+
...(taskId !== undefined ? { att_tid: taskId } : {}),
|
|
391
|
+
...(raw.att_uid !== undefined ? { att_uid: raw.att_uid } : {}),
|
|
392
|
+
agent_id: `mcp:${toolName}`,
|
|
393
|
+
scope: grantedScope,
|
|
394
|
+
meta: { outcome: 'allowed', required_scope: requiredScope },
|
|
395
|
+
}, this.onAuditError, this.onViolation);
|
|
396
|
+
return null;
|
|
397
|
+
}
|
|
398
|
+
violate(toolName, opts) {
|
|
399
|
+
const event = {
|
|
400
|
+
toolName,
|
|
401
|
+
requiredScope: opts.requiredScope,
|
|
402
|
+
grantedScope: opts.grantedScope,
|
|
403
|
+
reason: opts.reason,
|
|
404
|
+
timestamp: new Date().toISOString(),
|
|
405
|
+
...(opts.jti !== undefined ? { jti: opts.jti } : {}),
|
|
406
|
+
...(opts.taskId !== undefined ? { taskId: opts.taskId } : {}),
|
|
407
|
+
};
|
|
408
|
+
this.onViolation?.(event);
|
|
409
|
+
if (!this.requireCredential) {
|
|
410
|
+
// Permissive mode: log the violation but let the call through.
|
|
411
|
+
return null;
|
|
412
|
+
}
|
|
413
|
+
return {
|
|
414
|
+
error: 'attest_violation',
|
|
415
|
+
reason: opts.reason,
|
|
416
|
+
detail: opts.detail,
|
|
417
|
+
...(opts.jti !== undefined ? { jti: opts.jti } : {}),
|
|
418
|
+
...(opts.taskId !== undefined ? { taskId: opts.taskId } : {}),
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
// ── Scope registry ────────────────────────────────────────────────────────────
|
|
423
|
+
// Maps each patched server instance → its tool-name-to-scope registry.
|
|
424
|
+
// WeakMap so patched servers can be GC'd without leaking.
|
|
425
|
+
const scopeRegistries = new WeakMap();
|
|
426
|
+
// ── withAttest ───────────────────────────────────────────────────────────────
|
|
427
|
+
/**
|
|
428
|
+
* Wraps an MCP server instance and enforces Attest credential checking on
|
|
429
|
+
* every tool call.
|
|
430
|
+
*
|
|
431
|
+
* Returns the **same** server object with its `tool()` method patched in place,
|
|
432
|
+
* typed as the original server type so all other methods remain accessible.
|
|
433
|
+
*
|
|
434
|
+
* @param server Any object with a `tool()` method (e.g. `new McpServer(...)`).
|
|
435
|
+
* @param options Attest enforcement options.
|
|
436
|
+
* @returns The patched server (same reference, same type).
|
|
437
|
+
*
|
|
438
|
+
* @example
|
|
439
|
+
* ```ts
|
|
440
|
+
* import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
441
|
+
* import { withAttest } from "@attest-dev/sdk/mcp";
|
|
442
|
+
*
|
|
443
|
+
* const server = new McpServer({ name: "my-tools", version: "1.0.0" });
|
|
444
|
+
* const protectedServer = withAttest(server, {
|
|
445
|
+
* issuerUri: "https://api.attest.dev",
|
|
446
|
+
* });
|
|
447
|
+
*
|
|
448
|
+
* protectedServer.tool("send_email", schema, async (args, extra) => {
|
|
449
|
+
* // Only reached when the caller holds a valid credential
|
|
450
|
+
* // with "email:send" in its att_scope.
|
|
451
|
+
* return { content: [{ type: "text", text: "sent!" }] };
|
|
452
|
+
* });
|
|
453
|
+
* ```
|
|
454
|
+
*/
|
|
455
|
+
function withAttest(server, options) {
|
|
456
|
+
const enforcer = new AttestEnforcer(options);
|
|
457
|
+
const registry = new Map();
|
|
458
|
+
scopeRegistries.set(server, registry);
|
|
459
|
+
const originalTool = server.tool.bind(server);
|
|
460
|
+
// Replace server.tool with our intercepting wrapper.
|
|
461
|
+
// The MCP SDK's McpServer.tool() has two overloads:
|
|
462
|
+
// tool(name, schema, handler)
|
|
463
|
+
// tool(name, description, schema, handler)
|
|
464
|
+
// We additionally support an optional trailing AttestToolOptions object:
|
|
465
|
+
// tool(name, schema, handler, { requiredScope: "..." })
|
|
466
|
+
// tool(name, description, schema, handler, { requiredScope: "..." })
|
|
467
|
+
// That object is consumed here and stripped before forwarding to the SDK.
|
|
468
|
+
server.tool = function attestTool(...args) {
|
|
469
|
+
const patched = patchToolArgs(enforcer, registry, args);
|
|
470
|
+
return originalTool(...patched);
|
|
471
|
+
};
|
|
472
|
+
return server;
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Detects the handler function and optional trailing `AttestToolOptions` in
|
|
476
|
+
* the `tool()` argument list, wraps the handler with credential enforcement,
|
|
477
|
+
* strips the options object (the MCP SDK doesn't know about it), and returns
|
|
478
|
+
* the patched argument array ready to forward to the original `tool()`.
|
|
479
|
+
*/
|
|
480
|
+
function patchToolArgs(enforcer, registry, args) {
|
|
481
|
+
if (args.length === 0)
|
|
482
|
+
return args;
|
|
483
|
+
// Detect optional trailing AttestToolOptions.
|
|
484
|
+
// It's a plain object (not a function, not an array, not null) that may
|
|
485
|
+
// carry { requiredScope?: string }. The handler is always a function and
|
|
486
|
+
// always comes before the options if options are present.
|
|
487
|
+
let coreArgs = args;
|
|
488
|
+
let explicitScope;
|
|
489
|
+
const last = args[args.length - 1];
|
|
490
|
+
if (last !== null &&
|
|
491
|
+
typeof last === 'object' &&
|
|
492
|
+
!Array.isArray(last) &&
|
|
493
|
+
typeof last['requiredScope'] !== 'function') {
|
|
494
|
+
// Candidate options object — check the one before it is a function.
|
|
495
|
+
const penultimate = args[args.length - 2];
|
|
496
|
+
if (typeof penultimate === 'function') {
|
|
497
|
+
const opts = last;
|
|
498
|
+
explicitScope = opts.requiredScope;
|
|
499
|
+
coreArgs = args.slice(0, -1); // strip options before forwarding
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
const handlerArg = coreArgs[coreArgs.length - 1];
|
|
503
|
+
if (typeof handlerArg !== 'function')
|
|
504
|
+
return coreArgs;
|
|
505
|
+
// Tool name is always the first argument.
|
|
506
|
+
const toolName = typeof coreArgs[0] === 'string' ? coreArgs[0] : '<unknown>';
|
|
507
|
+
// Resolve and record the scope for this tool.
|
|
508
|
+
const resolvedScope = enforcer.resolveScope(toolName, explicitScope);
|
|
509
|
+
registry.set(toolName, resolvedScope);
|
|
510
|
+
const original = handlerArg;
|
|
511
|
+
const wrapped = async (params, extra) => {
|
|
512
|
+
const violation = await enforcer.check(toolName, extra, resolvedScope);
|
|
513
|
+
if (violation !== null) {
|
|
514
|
+
return {
|
|
515
|
+
content: [{ type: 'text', text: JSON.stringify(violation, null, 2) }],
|
|
516
|
+
isError: true,
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
return original(params, extra);
|
|
520
|
+
};
|
|
521
|
+
Object.defineProperty(wrapped, 'name', { value: `attest:${toolName}` });
|
|
522
|
+
return [...coreArgs.slice(0, -1), wrapped];
|
|
523
|
+
}
|
|
524
|
+
// ── Convenience re-export of AttestContext builder ───────────────────────────
|
|
525
|
+
/**
|
|
526
|
+
* Decodes the Attest JWT in `extra` and returns a typed `AttestContext`
|
|
527
|
+
* without performing any cryptographic verification.
|
|
528
|
+
*
|
|
529
|
+
* Useful inside tool handlers when you want to read the credential's claims
|
|
530
|
+
* (e.g. `att_uid`, `att_tid`) after `withAttest` has already enforced them.
|
|
531
|
+
*
|
|
532
|
+
* @returns `null` when no Attest credential is present.
|
|
533
|
+
*
|
|
534
|
+
* @example
|
|
535
|
+
* ```ts
|
|
536
|
+
* protectedServer.tool("send_email", schema, async (args, extra) => {
|
|
537
|
+
* const ctx = getAttestContext(extra);
|
|
538
|
+
* console.log("acting on behalf of", ctx?.att_uid);
|
|
539
|
+
* ...
|
|
540
|
+
* });
|
|
541
|
+
* ```
|
|
542
|
+
*/
|
|
543
|
+
function getAttestContext(extra) {
|
|
544
|
+
const token = extractToken(extra);
|
|
545
|
+
if (!token)
|
|
546
|
+
return null;
|
|
547
|
+
try {
|
|
548
|
+
const claims = (0, jose_1.decodeJwt)(token);
|
|
549
|
+
return {
|
|
550
|
+
jti: claims.jti ?? '',
|
|
551
|
+
att_tid: claims.att_tid ?? '',
|
|
552
|
+
att_depth: claims.att_depth ?? 0,
|
|
553
|
+
att_scope: claims.att_scope ?? [],
|
|
554
|
+
att_uid: claims.att_uid ?? '',
|
|
555
|
+
token,
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
catch {
|
|
559
|
+
return null;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* Returns the scope registry for a server that has been wrapped with
|
|
564
|
+
* `withAttest` — a map of every registered tool name to its resolved
|
|
565
|
+
* Attest scope string.
|
|
566
|
+
*
|
|
567
|
+
* Use this to build a scope discovery endpoint so credential issuers can
|
|
568
|
+
* query what scopes a server requires without out-of-band coordination.
|
|
569
|
+
*
|
|
570
|
+
* @example
|
|
571
|
+
* ```ts
|
|
572
|
+
* // Express / Hono / any HTTP framework:
|
|
573
|
+
* app.get("/.well-known/attest-scopes", (_req, res) => {
|
|
574
|
+
* res.json({ tools: getAttestScopes(protectedServer) });
|
|
575
|
+
* });
|
|
576
|
+
*
|
|
577
|
+
* // Response:
|
|
578
|
+
* // {
|
|
579
|
+
* // "tools": {
|
|
580
|
+
* // "send_email": "email:send",
|
|
581
|
+
* // "read_file": "file:read",
|
|
582
|
+
* // "gh_create_issue": "github:write"
|
|
583
|
+
* // }
|
|
584
|
+
* // }
|
|
585
|
+
* ```
|
|
586
|
+
*
|
|
587
|
+
* Tools that have not yet been registered (i.e. `server.tool()` hasn't been
|
|
588
|
+
* called for them yet) will not appear in the result. Call this after all
|
|
589
|
+
* tools are registered, not during server startup.
|
|
590
|
+
*
|
|
591
|
+
* @returns A plain `Record<string, string>` safe to serialize directly as JSON.
|
|
592
|
+
*/
|
|
593
|
+
function getAttestScopes(server) {
|
|
594
|
+
const registry = scopeRegistries.get(server);
|
|
595
|
+
if (!registry)
|
|
596
|
+
return {};
|
|
597
|
+
return Object.fromEntries(registry);
|
|
598
|
+
}
|
|
599
|
+
//# sourceMappingURL=mcp.js.map
|
package/dist/mcp.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@attest-dev/sdk",
|
|
3
|
+
"version": "0.1.0-beta.1",
|
|
4
|
+
"description": "TypeScript SDK for the Attest cryptographic agent credential service",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"require": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts"
|
|
11
|
+
},
|
|
12
|
+
"./mcp": {
|
|
13
|
+
"require": "./dist/mcp.js",
|
|
14
|
+
"types": "./dist/mcp.d.ts"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"typecheck": "tsc --noEmit",
|
|
20
|
+
"prepublishOnly": "tsc"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"README.md"
|
|
25
|
+
],
|
|
26
|
+
"keywords": ["attest", "jwt", "agent", "credentials", "delegation", "ai-safety"],
|
|
27
|
+
"license": "Apache-2.0",
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"jose": "^5.9.6"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/node": "^20.14.0",
|
|
33
|
+
"typescript": "^5.4.5"
|
|
34
|
+
},
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=18"
|
|
37
|
+
}
|
|
38
|
+
}
|