@absolutejs/mcp 0.1.0 → 0.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/dist/index.js +86 -33
- package/dist/src/types.d.ts +2 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -150,16 +150,26 @@ var createMcpClient = (options) => {
|
|
|
150
150
|
await notify("notifications/initialized");
|
|
151
151
|
return isRecord(result) ? result : {};
|
|
152
152
|
};
|
|
153
|
+
const MAX_LIST_PAGES = 40;
|
|
153
154
|
const listTools = async () => {
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
155
|
+
const collected = [];
|
|
156
|
+
let cursor;
|
|
157
|
+
for (let page = 0;page < MAX_LIST_PAGES; page += 1) {
|
|
158
|
+
const result = await rpc("tools/list", cursor === undefined ? undefined : { cursor });
|
|
159
|
+
const tools = isRecord(result) && Array.isArray(result.tools) ? result.tools : [];
|
|
160
|
+
collected.push(...tools.filter(isRecord).map((tool) => ({
|
|
161
|
+
annotations: isRecord(tool.annotations) ? tool.annotations : undefined,
|
|
162
|
+
description: typeof tool.description === "string" ? tool.description : undefined,
|
|
163
|
+
inputSchema: isRecord(tool.inputSchema) ? tool.inputSchema : undefined,
|
|
164
|
+
name: typeof tool.name === "string" ? tool.name : "",
|
|
165
|
+
outputSchema: isRecord(tool.outputSchema) ? tool.outputSchema : undefined
|
|
166
|
+
})));
|
|
167
|
+
const next = isRecord(result) && typeof result.nextCursor === "string" ? result.nextCursor : undefined;
|
|
168
|
+
if (next === undefined)
|
|
169
|
+
break;
|
|
170
|
+
cursor = next;
|
|
171
|
+
}
|
|
172
|
+
return collected;
|
|
163
173
|
};
|
|
164
174
|
const callTool = async (name, args) => {
|
|
165
175
|
const result = await rpc("tools/call", { arguments: args ?? {}, name });
|
|
@@ -169,8 +179,19 @@ var createMcpClient = (options) => {
|
|
|
169
179
|
return { content: [], isError: false };
|
|
170
180
|
};
|
|
171
181
|
const listResources = async () => {
|
|
172
|
-
const
|
|
173
|
-
|
|
182
|
+
const collected = [];
|
|
183
|
+
let cursor;
|
|
184
|
+
for (let page = 0;page < MAX_LIST_PAGES; page += 1) {
|
|
185
|
+
const result = await rpc("resources/list", cursor === undefined ? undefined : { cursor });
|
|
186
|
+
if (isRecord(result) && Array.isArray(result.resources)) {
|
|
187
|
+
collected.push(...result.resources);
|
|
188
|
+
}
|
|
189
|
+
const next = isRecord(result) && typeof result.nextCursor === "string" ? result.nextCursor : undefined;
|
|
190
|
+
if (next === undefined)
|
|
191
|
+
break;
|
|
192
|
+
cursor = next;
|
|
193
|
+
}
|
|
194
|
+
return collected;
|
|
174
195
|
};
|
|
175
196
|
const readResource = async (uri) => rpc("resources/read", { uri });
|
|
176
197
|
const ping = async () => {
|
|
@@ -212,6 +233,26 @@ var unauthorized = (metadataUrl, detail) => new Response(JSON.stringify({
|
|
|
212
233
|
// src/dispatch.ts
|
|
213
234
|
var DEFAULT_PROTOCOLS = ["2025-06-18", "2025-03-26", "2024-11-05"];
|
|
214
235
|
var DEFAULT_RESOURCE_MIME = "text/markdown";
|
|
236
|
+
var DEFAULT_LIST_PAGE_SIZE = 50;
|
|
237
|
+
var decodeCursor = (params) => {
|
|
238
|
+
if (!isRecord(params) || typeof params.cursor !== "string")
|
|
239
|
+
return 0;
|
|
240
|
+
try {
|
|
241
|
+
const parsed = Number.parseInt(atob(params.cursor), 10);
|
|
242
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : 0;
|
|
243
|
+
} catch {
|
|
244
|
+
return 0;
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
var encodeCursor = (offset) => btoa(String(offset));
|
|
248
|
+
var paginate = (items, offset, pageSize) => {
|
|
249
|
+
const page = items.slice(offset, offset + pageSize);
|
|
250
|
+
const nextOffset = offset + pageSize;
|
|
251
|
+
return {
|
|
252
|
+
items: page,
|
|
253
|
+
...nextOffset < items.length ? { nextCursor: encodeCursor(nextOffset) } : {}
|
|
254
|
+
};
|
|
255
|
+
};
|
|
215
256
|
var idOf = (message) => typeof message.id === "string" || typeof message.id === "number" ? message.id : null;
|
|
216
257
|
var negotiateProtocol = (supported, params) => {
|
|
217
258
|
const preferred = supported[0] ?? DEFAULT_PROTOCOLS[0] ?? "";
|
|
@@ -244,16 +285,19 @@ var initialize = (config, id, params) => {
|
|
|
244
285
|
serverInfo: config.serverInfo
|
|
245
286
|
});
|
|
246
287
|
};
|
|
247
|
-
var toolsList = async (config, caller, scopes, id) => {
|
|
288
|
+
var toolsList = async (config, caller, scopes, id, params) => {
|
|
248
289
|
const tools = await config.tools({ caller, meta: {} });
|
|
290
|
+
const visible = Object.entries(tools).filter(([, tool]) => scopeAllows(tool, scopes)).map(([name, tool]) => ({
|
|
291
|
+
annotations: tool.annotations,
|
|
292
|
+
description: tool.description,
|
|
293
|
+
inputSchema: tool.inputSchema,
|
|
294
|
+
name,
|
|
295
|
+
...tool.outputSchema === undefined ? {} : { outputSchema: tool.outputSchema }
|
|
296
|
+
}));
|
|
297
|
+
const { items, nextCursor } = paginate(visible, decodeCursor(params), config.listPageSize ?? DEFAULT_LIST_PAGE_SIZE);
|
|
249
298
|
return rpcResult(id, {
|
|
250
|
-
tools:
|
|
251
|
-
|
|
252
|
-
description: tool.description,
|
|
253
|
-
inputSchema: tool.inputSchema,
|
|
254
|
-
name,
|
|
255
|
-
...tool.outputSchema === undefined ? {} : { outputSchema: tool.outputSchema }
|
|
256
|
-
}))
|
|
299
|
+
tools: items,
|
|
300
|
+
...nextCursor === undefined ? {} : { nextCursor }
|
|
257
301
|
});
|
|
258
302
|
};
|
|
259
303
|
var errorResult = (id, text) => rpcResult(id, { content: [{ text, type: "text" }], isError: true });
|
|
@@ -288,15 +332,18 @@ var toolsCall = async (config, caller, scopes, id, params) => {
|
|
|
288
332
|
await config.onCall({ args, caller, meta, name, ok });
|
|
289
333
|
return response;
|
|
290
334
|
};
|
|
291
|
-
var promptsList = (config, id) => {
|
|
335
|
+
var promptsList = (config, id, params) => {
|
|
292
336
|
const definitions = config.prompts?.definitions ?? {};
|
|
337
|
+
const all = Object.entries(definitions).map(([name, def]) => ({
|
|
338
|
+
arguments: def.arguments ?? [],
|
|
339
|
+
description: def.description,
|
|
340
|
+
name,
|
|
341
|
+
title: def.title
|
|
342
|
+
}));
|
|
343
|
+
const { items, nextCursor } = paginate(all, decodeCursor(params), config.listPageSize ?? DEFAULT_LIST_PAGE_SIZE);
|
|
293
344
|
return rpcResult(id, {
|
|
294
|
-
prompts:
|
|
295
|
-
|
|
296
|
-
description: def.description,
|
|
297
|
-
name,
|
|
298
|
-
title: def.title
|
|
299
|
-
}))
|
|
345
|
+
prompts: items,
|
|
346
|
+
...nextCursor === undefined ? {} : { nextCursor }
|
|
300
347
|
});
|
|
301
348
|
};
|
|
302
349
|
var promptsGet = async (config, caller, id, params) => {
|
|
@@ -320,11 +367,15 @@ var promptsGet = async (config, caller, id, params) => {
|
|
|
320
367
|
messages: [{ content: { text, type: "text" }, role: "user" }]
|
|
321
368
|
});
|
|
322
369
|
};
|
|
323
|
-
var resourcesList = async (config, caller, id) => {
|
|
370
|
+
var resourcesList = async (config, caller, id, params) => {
|
|
324
371
|
const resources = config.resources;
|
|
325
372
|
if (!resources)
|
|
326
373
|
return rpcResult(id, { resources: [] });
|
|
327
|
-
|
|
374
|
+
const { items, nextCursor } = paginate(await resources.list({ caller }), decodeCursor(params), config.listPageSize ?? DEFAULT_LIST_PAGE_SIZE);
|
|
375
|
+
return rpcResult(id, {
|
|
376
|
+
resources: items,
|
|
377
|
+
...nextCursor === undefined ? {} : { nextCursor }
|
|
378
|
+
});
|
|
328
379
|
};
|
|
329
380
|
var resourcesRead = async (config, caller, id, params) => {
|
|
330
381
|
const resources = config.resources;
|
|
@@ -357,17 +408,19 @@ var dispatchMcp = async (config, caller, scopes, message) => {
|
|
|
357
408
|
return initialize(config, id, params);
|
|
358
409
|
if (method === "ping")
|
|
359
410
|
return rpcResult(id, {});
|
|
360
|
-
if (method === "tools/list")
|
|
361
|
-
return toolsList(config, caller, scopes, id);
|
|
411
|
+
if (method === "tools/list") {
|
|
412
|
+
return toolsList(config, caller, scopes, id, params);
|
|
413
|
+
}
|
|
362
414
|
if (method === "tools/call") {
|
|
363
415
|
return toolsCall(config, caller, scopes, id, params);
|
|
364
416
|
}
|
|
365
417
|
if (method === "prompts/list")
|
|
366
|
-
return promptsList(config, id);
|
|
418
|
+
return promptsList(config, id, params);
|
|
367
419
|
if (method === "prompts/get")
|
|
368
420
|
return promptsGet(config, caller, id, params);
|
|
369
|
-
if (method === "resources/list")
|
|
370
|
-
return resourcesList(config, caller, id);
|
|
421
|
+
if (method === "resources/list") {
|
|
422
|
+
return resourcesList(config, caller, id, params);
|
|
423
|
+
}
|
|
371
424
|
if (method === "resources/read") {
|
|
372
425
|
return resourcesRead(config, caller, id, params);
|
|
373
426
|
}
|
package/dist/src/types.d.ts
CHANGED
|
@@ -135,6 +135,8 @@ export type McpServerConfig<Caller> = {
|
|
|
135
135
|
instructions?: string;
|
|
136
136
|
/** The token issuer — used for discovery metadata and the challenge URL. */
|
|
137
137
|
issuer: string;
|
|
138
|
+
/** Page size for tools/prompts/resources list pagination (default 50). */
|
|
139
|
+
listPageSize?: number;
|
|
138
140
|
/** Fired after every `tools/call` for auditing. `meta` carries anything the
|
|
139
141
|
* tool handler wrote during the call. */
|
|
140
142
|
onCall?: (record: {
|
package/package.json
CHANGED