@absol-labs/agent 0.1.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 +21 -0
- package/README.md +196 -0
- package/dist/discovery/registry.d.ts +68 -0
- package/dist/discovery/registry.d.ts.map +1 -0
- package/dist/discovery/registry.js +148 -0
- package/dist/discovery/registry.js.map +1 -0
- package/dist/frameworks/agentkit.d.ts +158 -0
- package/dist/frameworks/agentkit.d.ts.map +1 -0
- package/dist/frameworks/agentkit.js +339 -0
- package/dist/frameworks/agentkit.js.map +1 -0
- package/dist/frameworks/crewai.d.ts +19 -0
- package/dist/frameworks/crewai.d.ts.map +1 -0
- package/dist/frameworks/crewai.js +73 -0
- package/dist/frameworks/crewai.js.map +1 -0
- package/dist/frameworks/eliza.d.ts +393 -0
- package/dist/frameworks/eliza.d.ts.map +1 -0
- package/dist/frameworks/eliza.js +542 -0
- package/dist/frameworks/eliza.js.map +1 -0
- package/dist/frameworks/langchain.d.ts +31 -0
- package/dist/frameworks/langchain.d.ts.map +1 -0
- package/dist/frameworks/langchain.js +206 -0
- package/dist/frameworks/langchain.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/mandates/env.d.ts +51 -0
- package/dist/mandates/env.d.ts.map +1 -0
- package/dist/mandates/env.js +148 -0
- package/dist/mandates/env.js.map +1 -0
- package/dist/mandates/mandate.d.ts +214 -0
- package/dist/mandates/mandate.d.ts.map +1 -0
- package/dist/mandates/mandate.js +172 -0
- package/dist/mandates/mandate.js.map +1 -0
- package/dist/mcp/http-server.d.ts +2 -0
- package/dist/mcp/http-server.d.ts.map +1 -0
- package/dist/mcp/http-server.js +32 -0
- package/dist/mcp/http-server.js.map +1 -0
- package/dist/mcp/http.d.ts +114 -0
- package/dist/mcp/http.d.ts.map +1 -0
- package/dist/mcp/http.js +428 -0
- package/dist/mcp/http.js.map +1 -0
- package/dist/mcp/server.d.ts +119 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +679 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/stdio.d.ts +2 -0
- package/dist/mcp/stdio.d.ts.map +1 -0
- package/dist/mcp/stdio.js +6 -0
- package/dist/mcp/stdio.js.map +1 -0
- package/dist/sdk/client.d.ts +78 -0
- package/dist/sdk/client.d.ts.map +1 -0
- package/dist/sdk/client.js +99 -0
- package/dist/sdk/client.js.map +1 -0
- package/dist/wallet/provider.d.ts +51 -0
- package/dist/wallet/provider.d.ts.map +1 -0
- package/dist/wallet/provider.js +107 -0
- package/dist/wallet/provider.js.map +1 -0
- package/dist/x402/facilitator.d.ts +315 -0
- package/dist/x402/facilitator.d.ts.map +1 -0
- package/dist/x402/facilitator.js +194 -0
- package/dist/x402/facilitator.js.map +1 -0
- package/dist/zktls/reclaim.d.ts +137 -0
- package/dist/zktls/reclaim.d.ts.map +1 -0
- package/dist/zktls/reclaim.js +245 -0
- package/dist/zktls/reclaim.js.map +1 -0
- package/package.json +86 -0
- package/src/discovery/registry.ts +255 -0
- package/src/frameworks/agentkit.ts +537 -0
- package/src/frameworks/crewai.ts +102 -0
- package/src/frameworks/eliza.ts +776 -0
- package/src/frameworks/langchain.ts +325 -0
- package/src/index.ts +179 -0
- package/src/mandates/env.ts +222 -0
- package/src/mandates/mandate.ts +280 -0
- package/src/mcp/http-server.ts +38 -0
- package/src/mcp/http.ts +620 -0
- package/src/mcp/server.ts +1006 -0
- package/src/mcp/stdio.ts +8 -0
- package/src/sdk/client.ts +222 -0
- package/src/wallet/provider.ts +197 -0
- package/src/x402/facilitator.ts +336 -0
- package/src/zktls/reclaim.ts +424 -0
package/dist/mcp/http.js
ADDED
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
import { createHash, randomUUID, timingSafeEqual } from "node:crypto";
|
|
2
|
+
import { createServer, } from "node:http";
|
|
3
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
4
|
+
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
|
|
5
|
+
import { createVerifiedStreamMcpServer, createVerifiedStreamMcpServerOptionsFromEnv, } from "./server.js";
|
|
6
|
+
/**
|
|
7
|
+
* Hosted, multi-tenant MCP transport over Streamable HTTP.
|
|
8
|
+
*
|
|
9
|
+
* This serves the SAME Metrik agent MCP tool set as the stdio transport
|
|
10
|
+
* (`mcp/stdio.ts`) over the MCP SDK's `StreamableHTTPServerTransport`, so the
|
|
11
|
+
* agent lane can be hosted as a remote endpoint.
|
|
12
|
+
*
|
|
13
|
+
* Security model (fail-closed):
|
|
14
|
+
* - Every request MUST carry `Authorization: Bearer <token>`. Requests without
|
|
15
|
+
* a valid bearer token are rejected with 401 BEFORE any MCP session is
|
|
16
|
+
* created or any tool executes.
|
|
17
|
+
* - Tokens are compared in constant time (SHA-256 + `timingSafeEqual`) and are
|
|
18
|
+
* never logged.
|
|
19
|
+
* - Each authenticated caller maps to its OWN tenant context — its own
|
|
20
|
+
* wallet-backed agent client and stream registry — so one caller can never
|
|
21
|
+
* drive another caller's funds or observe another caller's streams.
|
|
22
|
+
* - A caller may only use MCP sessions bound to its own tenant; presenting
|
|
23
|
+
* another tenant's session id is rejected (403).
|
|
24
|
+
* - If zero tenants (tokens) are configured, the transport refuses to start.
|
|
25
|
+
*/
|
|
26
|
+
/** Maximum accepted request body size (bytes) — bounds memory per request. */
|
|
27
|
+
const MAX_BODY_BYTES = 4 * 1024 * 1024;
|
|
28
|
+
/** Header carrying the Streamable HTTP session id (per the MCP spec). */
|
|
29
|
+
const SESSION_ID_HEADER = "mcp-session-id";
|
|
30
|
+
function sha256(value) {
|
|
31
|
+
return createHash("sha256").update(value, "utf8").digest();
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Constant-time, env-backed tenant resolver.
|
|
35
|
+
*
|
|
36
|
+
* Tokens are pre-hashed with SHA-256 (fixed 32-byte width) so every comparison
|
|
37
|
+
* uses `timingSafeEqual` on equal-length buffers, and the loop always visits
|
|
38
|
+
* every tenant with no early exit — neither the presented token's length nor
|
|
39
|
+
* which tenant matched is observable via timing.
|
|
40
|
+
*/
|
|
41
|
+
export class StaticTenantResolver {
|
|
42
|
+
entries;
|
|
43
|
+
constructor(tenants) {
|
|
44
|
+
if (tenants.length === 0) {
|
|
45
|
+
throw new Error("hosted MCP: no tenants configured — refusing to start (fail-closed)");
|
|
46
|
+
}
|
|
47
|
+
const seenIds = new Set();
|
|
48
|
+
const seenTokens = new Set();
|
|
49
|
+
for (const tenant of tenants) {
|
|
50
|
+
if (tenant.token.length === 0) {
|
|
51
|
+
throw new Error(`hosted MCP: tenant "${tenant.id}" has an empty token (fail-closed)`);
|
|
52
|
+
}
|
|
53
|
+
if (seenIds.has(tenant.id)) {
|
|
54
|
+
throw new Error(`hosted MCP: duplicate tenant id "${tenant.id}"`);
|
|
55
|
+
}
|
|
56
|
+
if (seenTokens.has(tenant.token)) {
|
|
57
|
+
throw new Error(`hosted MCP: duplicate token for tenant "${tenant.id}"`);
|
|
58
|
+
}
|
|
59
|
+
seenIds.add(tenant.id);
|
|
60
|
+
seenTokens.add(tenant.token);
|
|
61
|
+
}
|
|
62
|
+
this.entries = tenants.map((tenant) => ({
|
|
63
|
+
tenant,
|
|
64
|
+
tokenHash: sha256(tenant.token),
|
|
65
|
+
}));
|
|
66
|
+
}
|
|
67
|
+
authenticate(token) {
|
|
68
|
+
const presented = sha256(token);
|
|
69
|
+
let match = null;
|
|
70
|
+
for (const entry of this.entries) {
|
|
71
|
+
// timingSafeEqual on equal-length buffers; visit all entries so timing
|
|
72
|
+
// does not reveal which (if any) tenant matched.
|
|
73
|
+
if (timingSafeEqual(presented, entry.tokenHash)) {
|
|
74
|
+
match = entry.tenant;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return match;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Creates (but does not start) a hosted multi-tenant MCP HTTP server.
|
|
82
|
+
*
|
|
83
|
+
* Use {@link HostedMcpHttpServer.listen} to bind it. The returned server is
|
|
84
|
+
* suitable for tests (bind to port 0 for an ephemeral port) and for
|
|
85
|
+
* deployment (bind to `0.0.0.0`/`PORT`).
|
|
86
|
+
*/
|
|
87
|
+
export function createHostedMcpHttpServer(options) {
|
|
88
|
+
const path = options.path ?? "/mcp";
|
|
89
|
+
const allowedOrigins = options.allowedOrigins;
|
|
90
|
+
const generateSessionId = options.generateSessionId ?? (() => randomUUID());
|
|
91
|
+
const sessions = new Map();
|
|
92
|
+
const httpServer = createServer((req, res) => {
|
|
93
|
+
handleHttpRequest(req, res, {
|
|
94
|
+
path,
|
|
95
|
+
allowedOrigins,
|
|
96
|
+
generateSessionId,
|
|
97
|
+
resolver: options.resolver,
|
|
98
|
+
sessions,
|
|
99
|
+
}).catch((error) => {
|
|
100
|
+
// Never leak internal error detail to the client.
|
|
101
|
+
logError("unhandled request error", error);
|
|
102
|
+
if (!res.headersSent) {
|
|
103
|
+
writeJsonRpcError(res, 500, -32603, "internal error");
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
res.end();
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
return {
|
|
111
|
+
httpServer,
|
|
112
|
+
listen: (port, host = "0.0.0.0") => new Promise((resolve, reject) => {
|
|
113
|
+
const onError = (error) => reject(error);
|
|
114
|
+
httpServer.once("error", onError);
|
|
115
|
+
httpServer.listen(port, host, () => {
|
|
116
|
+
httpServer.removeListener("error", onError);
|
|
117
|
+
const address = httpServer.address();
|
|
118
|
+
resolve({ port: address.port, host });
|
|
119
|
+
});
|
|
120
|
+
}),
|
|
121
|
+
close: async () => {
|
|
122
|
+
// Closing the runtime cascades to its transport via the SDK lifecycle
|
|
123
|
+
// linkage; the transport's onclose then drops it from the map.
|
|
124
|
+
await Promise.all(Array.from(sessions.values()).map((session) => session.runtime.close().catch(() => undefined)));
|
|
125
|
+
sessions.clear();
|
|
126
|
+
await new Promise((resolve, reject) => {
|
|
127
|
+
httpServer.close((error) => (error ? reject(error) : resolve()));
|
|
128
|
+
});
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
async function handleHttpRequest(req, res, ctx) {
|
|
133
|
+
applyCorsHeaders(req, res, ctx.allowedOrigins);
|
|
134
|
+
// CORS preflight — no auth, no side effects.
|
|
135
|
+
if (req.method === "OPTIONS") {
|
|
136
|
+
res.writeHead(204).end();
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const requestUrl = new URL(req.url ?? "/", "http://localhost");
|
|
140
|
+
if (requestUrl.pathname !== ctx.path) {
|
|
141
|
+
writeJsonRpcError(res, 404, -32601, "not found");
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const method = req.method ?? "";
|
|
145
|
+
if (method !== "POST" && method !== "GET" && method !== "DELETE") {
|
|
146
|
+
res.setHeader("Allow", "POST, GET, DELETE, OPTIONS");
|
|
147
|
+
writeJsonRpcError(res, 405, -32601, "method not allowed");
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
// ── Authentication gate (runs before ANY MCP session / tool executes) ──
|
|
151
|
+
const tenant = authenticateRequest(req, ctx.resolver);
|
|
152
|
+
if (tenant === null) {
|
|
153
|
+
res.setHeader("WWW-Authenticate", 'Bearer realm="metrik-agent-mcp"');
|
|
154
|
+
writeJsonRpcError(res, 401, -32001, "unauthorized");
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
if (method === "POST") {
|
|
158
|
+
await handlePost(req, res, ctx, tenant);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
// GET (SSE stream) and DELETE (end session) both require an existing session.
|
|
162
|
+
const session = resolveSessionForTenant(req, res, ctx, tenant);
|
|
163
|
+
if (session === null) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
await session.transport.handleRequest(req, res);
|
|
167
|
+
}
|
|
168
|
+
async function handlePost(req, res, ctx, tenant) {
|
|
169
|
+
let body;
|
|
170
|
+
try {
|
|
171
|
+
body = await readJsonBody(req);
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
const status = error instanceof BodyTooLargeError ? 413 : 400;
|
|
175
|
+
writeJsonRpcError(res, status, -32700, "invalid request body");
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
const sessionId = headerValue(req, SESSION_ID_HEADER);
|
|
179
|
+
if (sessionId !== undefined) {
|
|
180
|
+
const session = resolveSessionForTenant(req, res, ctx, tenant);
|
|
181
|
+
if (session === null) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
await session.transport.handleRequest(req, res, body);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
// No session id: only an `initialize` request may open a new session.
|
|
188
|
+
if (!isInitializeRequest(body)) {
|
|
189
|
+
writeJsonRpcError(res, 400, -32000, "missing session id (only initialize may open a session)");
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
const runtime = createVerifiedStreamMcpServer(tenant.options);
|
|
193
|
+
const transport = new StreamableHTTPServerTransport({
|
|
194
|
+
sessionIdGenerator: ctx.generateSessionId,
|
|
195
|
+
onsessioninitialized: (id) => {
|
|
196
|
+
ctx.sessions.set(id, { transport, runtime, tenantId: tenant.id });
|
|
197
|
+
},
|
|
198
|
+
onsessionclosed: (id) => {
|
|
199
|
+
ctx.sessions.delete(id);
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
// Only drop the session from the map on close. Do NOT call runtime.close()
|
|
203
|
+
// here: `mcpServer.connect` links server<->transport lifecycle, so closing
|
|
204
|
+
// the runtime already closes the transport (and vice versa). Closing one from
|
|
205
|
+
// the other's close handler would recurse infinitely.
|
|
206
|
+
transport.onclose = () => {
|
|
207
|
+
const id = transport.sessionId;
|
|
208
|
+
if (id !== undefined) {
|
|
209
|
+
ctx.sessions.delete(id);
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
// The SDK's StreamableHTTPServerTransport exposes onclose/onerror as
|
|
213
|
+
// getter/setter pairs typed `(() => void) | undefined`, which does not satisfy
|
|
214
|
+
// the `onclose?: () => void` optional-property shape under
|
|
215
|
+
// exactOptionalPropertyTypes. The runtime shape is fully compatible.
|
|
216
|
+
await runtime.mcpServer.connect(transport);
|
|
217
|
+
await transport.handleRequest(req, res, body);
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Looks up the session named by the request's `mcp-session-id` header and
|
|
221
|
+
* enforces tenant ownership. Writes the appropriate error response and returns
|
|
222
|
+
* `null` when the session is missing (404) or owned by another tenant (403).
|
|
223
|
+
*/
|
|
224
|
+
function resolveSessionForTenant(req, res, ctx, tenant) {
|
|
225
|
+
const sessionId = headerValue(req, SESSION_ID_HEADER);
|
|
226
|
+
if (sessionId === undefined) {
|
|
227
|
+
writeJsonRpcError(res, 400, -32000, "missing session id");
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
const session = ctx.sessions.get(sessionId);
|
|
231
|
+
if (session === undefined) {
|
|
232
|
+
writeJsonRpcError(res, 404, -32001, "unknown session");
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
if (session.tenantId !== tenant.id) {
|
|
236
|
+
// Tenant isolation: a caller may never touch another tenant's session.
|
|
237
|
+
writeJsonRpcError(res, 403, -32001, "forbidden");
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
return session;
|
|
241
|
+
}
|
|
242
|
+
function authenticateRequest(req, resolver) {
|
|
243
|
+
const header = headerValue(req, "authorization");
|
|
244
|
+
if (header === undefined) {
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
const match = /^Bearer[ ]+(.+)$/i.exec(header.trim());
|
|
248
|
+
if (match === null) {
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
const token = match[1].trim();
|
|
252
|
+
if (token.length === 0) {
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
return resolver.authenticate(token);
|
|
256
|
+
}
|
|
257
|
+
function applyCorsHeaders(req, res, allowedOrigins) {
|
|
258
|
+
if (allowedOrigins === undefined || allowedOrigins.length === 0) {
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
const origin = headerValue(req, "origin");
|
|
262
|
+
const allowAny = allowedOrigins.includes("*");
|
|
263
|
+
if (allowAny) {
|
|
264
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
265
|
+
}
|
|
266
|
+
else if (origin !== undefined && allowedOrigins.includes(origin)) {
|
|
267
|
+
res.setHeader("Access-Control-Allow-Origin", origin);
|
|
268
|
+
res.setHeader("Vary", "Origin");
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
// Origin not allowed — emit no ACAO header (browser will block).
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
res.setHeader("Access-Control-Allow-Methods", "POST, GET, DELETE, OPTIONS");
|
|
275
|
+
res.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, Mcp-Session-Id, Last-Event-ID, Mcp-Protocol-Version");
|
|
276
|
+
res.setHeader("Access-Control-Expose-Headers", "Mcp-Session-Id");
|
|
277
|
+
res.setHeader("Access-Control-Max-Age", "600");
|
|
278
|
+
}
|
|
279
|
+
class BodyTooLargeError extends Error {
|
|
280
|
+
}
|
|
281
|
+
async function readJsonBody(req) {
|
|
282
|
+
const chunks = [];
|
|
283
|
+
let size = 0;
|
|
284
|
+
for await (const chunk of req) {
|
|
285
|
+
const buffer = chunk;
|
|
286
|
+
size += buffer.length;
|
|
287
|
+
if (size > MAX_BODY_BYTES) {
|
|
288
|
+
throw new BodyTooLargeError("request body too large");
|
|
289
|
+
}
|
|
290
|
+
chunks.push(buffer);
|
|
291
|
+
}
|
|
292
|
+
const raw = Buffer.concat(chunks).toString("utf8");
|
|
293
|
+
if (raw.trim().length === 0) {
|
|
294
|
+
return undefined;
|
|
295
|
+
}
|
|
296
|
+
return JSON.parse(raw);
|
|
297
|
+
}
|
|
298
|
+
function headerValue(req, name) {
|
|
299
|
+
const value = req.headers[name];
|
|
300
|
+
if (value === undefined) {
|
|
301
|
+
return undefined;
|
|
302
|
+
}
|
|
303
|
+
return Array.isArray(value) ? value[0] : value;
|
|
304
|
+
}
|
|
305
|
+
function writeJsonRpcError(res, status, code, message) {
|
|
306
|
+
if (res.headersSent) {
|
|
307
|
+
res.end();
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
const payload = JSON.stringify({
|
|
311
|
+
jsonrpc: "2.0",
|
|
312
|
+
error: { code, message },
|
|
313
|
+
id: null,
|
|
314
|
+
});
|
|
315
|
+
res.writeHead(status, { "Content-Type": "application/json" }).end(payload);
|
|
316
|
+
}
|
|
317
|
+
function logError(context, error) {
|
|
318
|
+
// Only the message — never headers/tokens/bodies.
|
|
319
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
320
|
+
console.error(`[metrik-agent-mcp-http] ${context}: ${message}`);
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Parses the hosted MCP server configuration from environment variables.
|
|
324
|
+
*
|
|
325
|
+
* Env contract:
|
|
326
|
+
* - `PORT` / `METRIK_MCP_PORT` — listen port (default 8080).
|
|
327
|
+
* - `METRIK_MCP_HOST` — bind host (default `0.0.0.0`).
|
|
328
|
+
* - `METRIK_MCP_PATH` — MCP endpoint path (default `/mcp`).
|
|
329
|
+
* - `METRIK_MCP_ALLOWED_ORIGINS` — comma-separated CORS origins, or `*`.
|
|
330
|
+
* - `METRIK_MCP_TENANTS` — JSON array of
|
|
331
|
+
* `{ "id": string, "token": string, "env"?: Record<string,string> }`.
|
|
332
|
+
* Each tenant's `env` is layered over the process environment and used to
|
|
333
|
+
* build that tenant's isolated, wallet-backed agent client.
|
|
334
|
+
*
|
|
335
|
+
* Throws (fail-closed) when no tenants/tokens are configured.
|
|
336
|
+
*/
|
|
337
|
+
export function parseHostedMcpServerConfig(env = process.env) {
|
|
338
|
+
const portRaw = env.METRIK_MCP_PORT ?? env.PORT ?? "8080";
|
|
339
|
+
const port = Number(portRaw);
|
|
340
|
+
if (!Number.isInteger(port) || port < 0 || port > 65535) {
|
|
341
|
+
throw new Error(`invalid port: ${portRaw}`);
|
|
342
|
+
}
|
|
343
|
+
const host = env.METRIK_MCP_HOST ?? "0.0.0.0";
|
|
344
|
+
const path = env.METRIK_MCP_PATH ?? "/mcp";
|
|
345
|
+
const allowedOrigins = (env.METRIK_MCP_ALLOWED_ORIGINS ?? "")
|
|
346
|
+
.split(",")
|
|
347
|
+
.map((value) => value.trim())
|
|
348
|
+
.filter((value) => value.length > 0);
|
|
349
|
+
const tenantsRaw = env.METRIK_MCP_TENANTS;
|
|
350
|
+
if (tenantsRaw === undefined || tenantsRaw.trim().length === 0) {
|
|
351
|
+
throw new Error("METRIK_MCP_TENANTS is required (fail-closed: refusing to run an open, unauthenticated MCP endpoint)");
|
|
352
|
+
}
|
|
353
|
+
let parsed;
|
|
354
|
+
try {
|
|
355
|
+
parsed = JSON.parse(tenantsRaw);
|
|
356
|
+
}
|
|
357
|
+
catch {
|
|
358
|
+
throw new Error("METRIK_MCP_TENANTS must be valid JSON");
|
|
359
|
+
}
|
|
360
|
+
if (!Array.isArray(parsed) || parsed.length === 0) {
|
|
361
|
+
throw new Error("METRIK_MCP_TENANTS must be a non-empty JSON array");
|
|
362
|
+
}
|
|
363
|
+
const tenants = parsed.map((entry, index) => {
|
|
364
|
+
if (typeof entry !== "object" || entry === null) {
|
|
365
|
+
throw new Error(`METRIK_MCP_TENANTS[${index}] must be an object`);
|
|
366
|
+
}
|
|
367
|
+
const record = entry;
|
|
368
|
+
const id = record.id;
|
|
369
|
+
const token = record.token;
|
|
370
|
+
if (typeof id !== "string" || id.length === 0) {
|
|
371
|
+
throw new Error(`METRIK_MCP_TENANTS[${index}].id must be a non-empty string`);
|
|
372
|
+
}
|
|
373
|
+
if (typeof token !== "string" || token.length === 0) {
|
|
374
|
+
throw new Error(`METRIK_MCP_TENANTS[${index}].token must be a non-empty string`);
|
|
375
|
+
}
|
|
376
|
+
const tenantEnv = {};
|
|
377
|
+
if (record.env !== undefined) {
|
|
378
|
+
if (typeof record.env !== "object" || record.env === null) {
|
|
379
|
+
throw new Error(`METRIK_MCP_TENANTS[${index}].env must be an object`);
|
|
380
|
+
}
|
|
381
|
+
for (const [key, value] of Object.entries(record.env)) {
|
|
382
|
+
if (typeof value !== "string") {
|
|
383
|
+
throw new Error(`METRIK_MCP_TENANTS[${index}].env.${key} must be a string`);
|
|
384
|
+
}
|
|
385
|
+
tenantEnv[key] = value;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
return { id, token, env: tenantEnv };
|
|
389
|
+
});
|
|
390
|
+
return { host, port, path, allowedOrigins, tenants };
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Builds fully-isolated {@link HostedMcpTenant}s from parsed config, resolving
|
|
394
|
+
* each tenant's wallet-backed agent client from its own environment slice.
|
|
395
|
+
*/
|
|
396
|
+
export async function createHostedMcpTenants(config, baseEnv = process.env) {
|
|
397
|
+
const tenants = [];
|
|
398
|
+
for (const tenantConfig of config.tenants) {
|
|
399
|
+
const options = await createVerifiedStreamMcpServerOptionsFromEnv({
|
|
400
|
+
...baseEnv,
|
|
401
|
+
...tenantConfig.env,
|
|
402
|
+
});
|
|
403
|
+
tenants.push({
|
|
404
|
+
id: tenantConfig.id,
|
|
405
|
+
token: tenantConfig.token,
|
|
406
|
+
options,
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
return tenants;
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Builds and starts a hosted MCP HTTP server entirely from the environment.
|
|
413
|
+
*
|
|
414
|
+
* Fail-closed: throws before binding if no tenants/tokens are configured.
|
|
415
|
+
*/
|
|
416
|
+
export async function startHostedMcpHttpServerFromEnv(env = process.env) {
|
|
417
|
+
const config = parseHostedMcpServerConfig(env);
|
|
418
|
+
const tenants = await createHostedMcpTenants(config, env);
|
|
419
|
+
const resolver = new StaticTenantResolver(tenants);
|
|
420
|
+
const server = createHostedMcpHttpServer({
|
|
421
|
+
resolver,
|
|
422
|
+
path: config.path,
|
|
423
|
+
allowedOrigins: config.allowedOrigins,
|
|
424
|
+
});
|
|
425
|
+
const { port } = await server.listen(config.port, config.host);
|
|
426
|
+
return Object.assign(server, { boundPort: port });
|
|
427
|
+
}
|
|
428
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/mcp/http.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { type Chain } from "viem";
|
|
3
|
+
import { type DiscoverServicesOptions, type ServiceListing } from "../discovery/registry.js";
|
|
4
|
+
import { type SignedSpendMandate } from "../mandates/mandate.js";
|
|
5
|
+
import { type ReclaimAuthorizedStreamInput, type ReclaimVerifiedStreamResult, type StreamStatusView, type VerifiedStreamAgentOpener } from "../sdk/client.js";
|
|
6
|
+
import { type AgentWalletInput } from "../wallet/provider.js";
|
|
7
|
+
import { type ConsumerDeliveryProofService } from "../zktls/reclaim.js";
|
|
8
|
+
export interface McpToolSpec {
|
|
9
|
+
name: string;
|
|
10
|
+
description: string;
|
|
11
|
+
/** Whether invoking this tool can move funds (must pass a spend mandate check). */
|
|
12
|
+
movesFunds: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare const METRIK_MCP_TOOLS: readonly McpToolSpec[];
|
|
15
|
+
/** @deprecated Renamed to METRIK_MCP_TOOLS; retained for back-compat. */
|
|
16
|
+
export declare const STREAMPROOF_MCP_TOOLS: readonly McpToolSpec[];
|
|
17
|
+
export interface StoredStreamRecord {
|
|
18
|
+
readonly streamId: `0x${string}`;
|
|
19
|
+
readonly buyer: `0x${string}`;
|
|
20
|
+
readonly operator: `0x${string}`;
|
|
21
|
+
readonly serviceRef: `0x${string}`;
|
|
22
|
+
readonly budgetUsdc: bigint;
|
|
23
|
+
readonly ratePerSecondUsdc: bigint;
|
|
24
|
+
readonly maxDurationSeconds: number;
|
|
25
|
+
readonly openedAtSeconds: number;
|
|
26
|
+
readonly mandateId: `0x${string}`;
|
|
27
|
+
}
|
|
28
|
+
export interface StreamRegistry {
|
|
29
|
+
put(record: StoredStreamRecord): Promise<void>;
|
|
30
|
+
get(streamId: `0x${string}`): Promise<StoredStreamRecord | null>;
|
|
31
|
+
list(): Promise<readonly StoredStreamRecord[]>;
|
|
32
|
+
}
|
|
33
|
+
export declare class InMemoryStreamRegistry implements StreamRegistry {
|
|
34
|
+
private readonly records;
|
|
35
|
+
put(record: StoredStreamRecord): Promise<void>;
|
|
36
|
+
get(streamId: `0x${string}`): Promise<StoredStreamRecord | null>;
|
|
37
|
+
list(): Promise<readonly StoredStreamRecord[]>;
|
|
38
|
+
}
|
|
39
|
+
export declare class FileStreamRegistry implements StreamRegistry {
|
|
40
|
+
private readonly filePath;
|
|
41
|
+
constructor(filePath: string);
|
|
42
|
+
put(record: StoredStreamRecord): Promise<void>;
|
|
43
|
+
get(streamId: `0x${string}`): Promise<StoredStreamRecord | null>;
|
|
44
|
+
list(): Promise<readonly StoredStreamRecord[]>;
|
|
45
|
+
private readAll;
|
|
46
|
+
private writeAll;
|
|
47
|
+
}
|
|
48
|
+
export interface MandateStateResolver {
|
|
49
|
+
getSpentSoFarUsdc(owner: `0x${string}`): Promise<bigint>;
|
|
50
|
+
getRevokedMandateIds(owner: `0x${string}`): Promise<readonly `0x${string}`[]>;
|
|
51
|
+
}
|
|
52
|
+
export interface VerifiedStreamMcpClient extends Pick<VerifiedStreamAgentOpener, "openVerifiedStream"> {
|
|
53
|
+
getStreamStatus(streamId: `0x${string}`): Promise<StreamStatusView>;
|
|
54
|
+
reclaimStream(input: ReclaimAuthorizedStreamInput): Promise<ReclaimVerifiedStreamResult>;
|
|
55
|
+
}
|
|
56
|
+
export interface VerifiedStreamMcpServerOptions {
|
|
57
|
+
readonly agentClient: VerifiedStreamMcpClient;
|
|
58
|
+
/**
|
|
59
|
+
* The owner-signed spend mandate that bounds every hire/reclaim (per-stream +
|
|
60
|
+
* total budget, rate, duration, allowed operators, expiry). Configured once at
|
|
61
|
+
* construction — the MCP caller (an LLM) never supplies or edits it, because it
|
|
62
|
+
* cannot produce an EIP-712 signature. Mirrors the AgentKit action provider.
|
|
63
|
+
*/
|
|
64
|
+
readonly signedMandate: SignedSpendMandate;
|
|
65
|
+
/**
|
|
66
|
+
* Optional provider returning the CURRENT signed mandate. When set, it
|
|
67
|
+
* supersedes {@link signedMandate} for fund-moving operations and is resolved
|
|
68
|
+
* per call — so a provider that re-signs before expiry keeps a long-running
|
|
69
|
+
* server authorizing hires. The env builder supplies a lazily-re-signing one.
|
|
70
|
+
*/
|
|
71
|
+
readonly mandateProvider?: () => SignedSpendMandate | Promise<SignedSpendMandate>;
|
|
72
|
+
readonly registry?: StreamRegistry;
|
|
73
|
+
readonly deliveryProofService?: ConsumerDeliveryProofService;
|
|
74
|
+
readonly mandateStateResolver?: Partial<MandateStateResolver>;
|
|
75
|
+
readonly now?: () => number;
|
|
76
|
+
/**
|
|
77
|
+
* Discovery driver for the `discover_services` tool. Defaults to the live
|
|
78
|
+
* registry-backed {@link discoverServices}; tests inject a double. Defaults for
|
|
79
|
+
* the registry URL/apikey come from env inside `discoverServices`.
|
|
80
|
+
*/
|
|
81
|
+
readonly discoverServices?: DiscoverServicesFn;
|
|
82
|
+
readonly serverInfo?: {
|
|
83
|
+
readonly name: string;
|
|
84
|
+
readonly version: string;
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
export interface VerifiedStreamMcpServerRuntime {
|
|
88
|
+
readonly mcpServer: McpServer;
|
|
89
|
+
readonly registry: StreamRegistry;
|
|
90
|
+
connectStdio(): Promise<void>;
|
|
91
|
+
close(): Promise<void>;
|
|
92
|
+
}
|
|
93
|
+
export interface ParsedMetrikAgentEnv {
|
|
94
|
+
readonly rpcUrl: string;
|
|
95
|
+
readonly escrow: `0x${string}`;
|
|
96
|
+
readonly usdc: `0x${string}`;
|
|
97
|
+
readonly chain: Chain;
|
|
98
|
+
readonly stateFile?: string;
|
|
99
|
+
readonly wallet: AgentWalletInput;
|
|
100
|
+
}
|
|
101
|
+
/** Discovery driver signature — overridable in tests. */
|
|
102
|
+
export type DiscoverServicesFn = (opts?: DiscoverServicesOptions) => Promise<ServiceListing[]>;
|
|
103
|
+
export declare function createVerifiedStreamMcpServer(options: VerifiedStreamMcpServerOptions): VerifiedStreamMcpServerRuntime;
|
|
104
|
+
export declare function parseMetrikAgentEnv(env?: NodeJS.ProcessEnv): ParsedMetrikAgentEnv;
|
|
105
|
+
/**
|
|
106
|
+
* Builds the {@link VerifiedStreamMcpServerOptions} for a single wallet-backed
|
|
107
|
+
* tenant from environment configuration.
|
|
108
|
+
*
|
|
109
|
+
* This is split out from {@link createVerifiedStreamMcpServerFromEnv} so a
|
|
110
|
+
* multi-session transport (see `mcp/http.ts`) can construct a FRESH
|
|
111
|
+
* {@link McpServer} per MCP session while sharing one tenant's wallet-backed
|
|
112
|
+
* agent client and stream registry. A single `McpServer` can only be bound to
|
|
113
|
+
* one transport at a time, so concurrent sessions each need their own server
|
|
114
|
+
* instance built from these shared options.
|
|
115
|
+
*/
|
|
116
|
+
export declare function createVerifiedStreamMcpServerOptionsFromEnv(env?: NodeJS.ProcessEnv): Promise<VerifiedStreamMcpServerOptions>;
|
|
117
|
+
export declare function createVerifiedStreamMcpServerFromEnv(env?: NodeJS.ProcessEnv): Promise<VerifiedStreamMcpServerRuntime>;
|
|
118
|
+
export declare function startVerifiedStreamMcpServerStdio(env?: NodeJS.ProcessEnv): Promise<void>;
|
|
119
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
|