@aigne/afs-mcp 1.11.0-beta.6 → 1.11.0-beta.8
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.cjs +1093 -130
- package/dist/index.d.cts +226 -91
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +226 -91
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1092 -131
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -4
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
1
2
|
const require_kinds = require('./kinds.cjs');
|
|
2
3
|
const require_decorate = require('./_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.cjs');
|
|
3
|
-
let node_path = require("node:path");
|
|
4
4
|
let _aigne_afs = require("@aigne/afs");
|
|
5
5
|
let _aigne_afs_provider = require("@aigne/afs/provider");
|
|
6
6
|
let _aigne_afs_utils_zod = require("@aigne/afs/utils/zod");
|
|
@@ -12,14 +12,6 @@ let zod = require("zod");
|
|
|
12
12
|
|
|
13
13
|
//#region src/index.ts
|
|
14
14
|
/**
|
|
15
|
-
* AFS MCP Provider
|
|
16
|
-
*
|
|
17
|
-
* 将 MCP Server 挂载为 AFS 可访问的世界。
|
|
18
|
-
* - Tools → 可执行的 AFS entries(通过 `exec()`)
|
|
19
|
-
* - Prompts → 可读取的世界描述
|
|
20
|
-
* - Resources → 可读取的世界状态(展开为 AFS 目录结构)
|
|
21
|
-
*/
|
|
22
|
-
/**
|
|
23
15
|
* Zod schema for options validation
|
|
24
16
|
*/
|
|
25
17
|
const afsMCPOptionsSchema = (0, _aigne_afs_utils_zod.camelize)(zod.z.object({
|
|
@@ -32,9 +24,9 @@ const afsMCPOptionsSchema = (0, _aigne_afs_utils_zod.camelize)(zod.z.object({
|
|
|
32
24
|
]),
|
|
33
25
|
command: (0, _aigne_afs_utils_zod.optionalize)(zod.z.string()),
|
|
34
26
|
args: (0, _aigne_afs_utils_zod.optionalize)(zod.z.array(zod.z.string())),
|
|
35
|
-
env: (0, _aigne_afs_utils_zod.optionalize)(zod.z.record(zod.z.string())),
|
|
27
|
+
env: (0, _aigne_afs_utils_zod.optionalize)(zod.z.record(zod.z.string(), zod.z.string())),
|
|
36
28
|
url: (0, _aigne_afs_utils_zod.optionalize)(zod.z.string()),
|
|
37
|
-
headers: (0, _aigne_afs_utils_zod.optionalize)(zod.z.record(zod.z.string())),
|
|
29
|
+
headers: (0, _aigne_afs_utils_zod.optionalize)(zod.z.record(zod.z.string(), zod.z.string())),
|
|
38
30
|
timeout: (0, _aigne_afs_utils_zod.optionalize)(zod.z.number()),
|
|
39
31
|
maxReconnects: (0, _aigne_afs_utils_zod.optionalize)(zod.z.number())
|
|
40
32
|
}).refine((data) => {
|
|
@@ -55,13 +47,57 @@ var AFSMCP = class AFSMCP extends _aigne_afs_provider.AFSBaseProvider {
|
|
|
55
47
|
static schema() {
|
|
56
48
|
return afsMCPOptionsSchema;
|
|
57
49
|
}
|
|
50
|
+
static manifest() {
|
|
51
|
+
return [
|
|
52
|
+
{
|
|
53
|
+
name: "mcp-stdio",
|
|
54
|
+
description: "MCP server via stdio transport",
|
|
55
|
+
uriTemplate: "mcp+stdio://{command+}",
|
|
56
|
+
category: "integration",
|
|
57
|
+
schema: zod.z.object({
|
|
58
|
+
command: zod.z.string(),
|
|
59
|
+
args: zod.z.array(zod.z.string()).optional(),
|
|
60
|
+
env: zod.z.record(zod.z.string(), zod.z.string()).optional()
|
|
61
|
+
}),
|
|
62
|
+
tags: [
|
|
63
|
+
"mcp",
|
|
64
|
+
"stdio",
|
|
65
|
+
"integration"
|
|
66
|
+
]
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: "mcp-http",
|
|
70
|
+
description: "MCP server via HTTP transport",
|
|
71
|
+
uriTemplate: "mcp+http://{url+}",
|
|
72
|
+
category: "integration",
|
|
73
|
+
schema: zod.z.object({ url: zod.z.string() }),
|
|
74
|
+
tags: [
|
|
75
|
+
"mcp",
|
|
76
|
+
"http",
|
|
77
|
+
"integration"
|
|
78
|
+
]
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: "mcp-sse",
|
|
82
|
+
description: "MCP server via SSE transport",
|
|
83
|
+
uriTemplate: "mcp+sse://{url+}",
|
|
84
|
+
category: "integration",
|
|
85
|
+
schema: zod.z.object({ url: zod.z.string() }),
|
|
86
|
+
tags: [
|
|
87
|
+
"mcp",
|
|
88
|
+
"sse",
|
|
89
|
+
"integration"
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
];
|
|
93
|
+
}
|
|
58
94
|
/**
|
|
59
95
|
* Load module from configuration file
|
|
60
96
|
*/
|
|
61
|
-
static async load({
|
|
97
|
+
static async load({ basePath, config } = {}) {
|
|
62
98
|
return new AFSMCP({
|
|
63
|
-
...await AFSMCP.schema().parseAsync(
|
|
64
|
-
cwd:
|
|
99
|
+
...await AFSMCP.schema().parseAsync(config),
|
|
100
|
+
cwd: basePath
|
|
65
101
|
});
|
|
66
102
|
}
|
|
67
103
|
/**
|
|
@@ -73,7 +109,7 @@ var AFSMCP = class AFSMCP extends _aigne_afs_provider.AFSBaseProvider {
|
|
|
73
109
|
* - "github://repos/owner/repo" -> { scheme: "github", path: "/repos/owner/repo" }
|
|
74
110
|
*/
|
|
75
111
|
static parseResourceUri(uri) {
|
|
76
|
-
const match = uri.match(/^(\w+):\/\/\/?(.*)$/);
|
|
112
|
+
const match = uri.match(/^([\w+.-]+):\/\/\/?(.*)$/);
|
|
77
113
|
if (match) {
|
|
78
114
|
const scheme = match[1];
|
|
79
115
|
const rest = match[2];
|
|
@@ -151,59 +187,130 @@ var AFSMCP = class AFSMCP extends _aigne_afs_provider.AFSBaseProvider {
|
|
|
151
187
|
constructor(options) {
|
|
152
188
|
super();
|
|
153
189
|
this.options = options;
|
|
190
|
+
if (!options.transport && options.uri) {
|
|
191
|
+
const uri = options.uri;
|
|
192
|
+
if (uri.startsWith("mcp+stdio://")) {
|
|
193
|
+
options.transport = "stdio";
|
|
194
|
+
if (!options.command) options.command = uri.slice(12).split("?")[0];
|
|
195
|
+
} else if (uri.startsWith("mcp+http://")) {
|
|
196
|
+
options.transport = "http";
|
|
197
|
+
if (!options.url) options.url = uri.replace("mcp+", "");
|
|
198
|
+
} else if (uri.startsWith("mcp+sse://")) {
|
|
199
|
+
options.transport = "sse";
|
|
200
|
+
if (!options.url) options.url = uri.replace("mcp+sse://", "http://");
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
if (typeof options.args === "string") {
|
|
204
|
+
const argsStr = options.args;
|
|
205
|
+
options.args = argsStr.includes(",") ? argsStr.split(",") : [argsStr];
|
|
206
|
+
} else if (Array.isArray(options.args)) options.args = options.args.flatMap((a) => a.includes(",") ? a.split(",") : [a]);
|
|
207
|
+
if (options.env && !Array.isArray(options.env) && typeof options.env === "string") {
|
|
208
|
+
const [key, ...rest] = options.env.split("=");
|
|
209
|
+
options.env = key ? { [key]: rest.join("=") } : {};
|
|
210
|
+
} else if (Array.isArray(options.env)) {
|
|
211
|
+
const envRecord = {};
|
|
212
|
+
for (const entry of options.env) {
|
|
213
|
+
const [key, ...rest] = entry.split("=");
|
|
214
|
+
if (key) envRecord[key] = rest.join("=");
|
|
215
|
+
}
|
|
216
|
+
options.env = envRecord;
|
|
217
|
+
}
|
|
154
218
|
(0, _aigne_afs_utils_zod.zodParse)(afsMCPOptionsSchema, options);
|
|
155
219
|
this.name = options.name || "mcp";
|
|
156
220
|
this.description = options.description;
|
|
157
221
|
}
|
|
158
222
|
/**
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
},
|
|
183
|
-
tools: { metadata: {
|
|
223
|
+
* List root directory children.
|
|
224
|
+
* Note: list() returns only children, never the path itself (per new semantics)
|
|
225
|
+
*/
|
|
226
|
+
async listRootHandler(_ctx) {
|
|
227
|
+
await this.ensureConnected();
|
|
228
|
+
const entries = [];
|
|
229
|
+
entries.push({
|
|
230
|
+
id: "/WORLD.md",
|
|
231
|
+
path: "/WORLD.md",
|
|
232
|
+
summary: "MCP Server World Documentation",
|
|
233
|
+
meta: {
|
|
234
|
+
kind: "afs:document",
|
|
235
|
+
kinds: require_kinds.getKindsArray("afs:document"),
|
|
236
|
+
description: "MCP Server World Documentation",
|
|
237
|
+
mimeType: "text/markdown",
|
|
238
|
+
mcp: { type: "world" }
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
entries.push({
|
|
242
|
+
id: "/tools",
|
|
243
|
+
path: "/tools",
|
|
244
|
+
summary: `${this._tools.length} tools available`,
|
|
245
|
+
meta: {
|
|
184
246
|
kind: "afs:node",
|
|
185
247
|
kinds: require_kinds.getKindsArray("afs:node"),
|
|
186
248
|
description: `${this._tools.length} tools available`,
|
|
187
249
|
childrenCount: this._tools.length
|
|
188
|
-
}
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
if (this._prompts.length > 0) entries.push({
|
|
253
|
+
id: "/prompts",
|
|
254
|
+
path: "/prompts",
|
|
255
|
+
summary: `${this._prompts.length} prompts available`,
|
|
256
|
+
meta: {
|
|
257
|
+
kind: "afs:node",
|
|
258
|
+
kinds: require_kinds.getKindsArray("afs:node"),
|
|
259
|
+
description: `${this._prompts.length} prompts available`,
|
|
260
|
+
childrenCount: this._prompts.length
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
if (this._resources.length > 0 || this._resourceTemplates.length > 0) entries.push({
|
|
264
|
+
id: "/resources",
|
|
265
|
+
path: "/resources",
|
|
266
|
+
summary: `${this._resources.length} resources available`,
|
|
267
|
+
meta: {
|
|
268
|
+
kind: "afs:node",
|
|
269
|
+
kinds: require_kinds.getKindsArray("afs:node"),
|
|
270
|
+
description: `${this._resources.length} resources available`,
|
|
271
|
+
childrenCount: this._resources.length
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
return { data: entries };
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Read root directory entry
|
|
278
|
+
*/
|
|
279
|
+
async readRootHandler(_ctx) {
|
|
280
|
+
await this.ensureConnected();
|
|
281
|
+
return {
|
|
282
|
+
id: "/",
|
|
283
|
+
path: "/",
|
|
284
|
+
summary: this.description || "MCP Server",
|
|
285
|
+
meta: {
|
|
286
|
+
kind: "mcp:module",
|
|
287
|
+
kinds: require_kinds.getKindsArray("mcp:module"),
|
|
288
|
+
description: this.description || "MCP Server",
|
|
289
|
+
childrenCount: 2 + (this._prompts.length > 0 ? 1 : 0) + (this._resources.length > 0 ? 1 : 0),
|
|
290
|
+
mcp: {
|
|
291
|
+
server: { name: this.name },
|
|
292
|
+
capabilities: {
|
|
293
|
+
tools: this._tools.length > 0,
|
|
294
|
+
prompts: this._prompts.length > 0,
|
|
295
|
+
resources: this._resources.length > 0
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
189
299
|
};
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
if (this._resources.length > 0 || this._resourceTemplates.length > 0) children.resources = { metadata: {
|
|
197
|
-
kind: "afs:node",
|
|
198
|
-
kinds: require_kinds.getKindsArray("afs:node"),
|
|
199
|
-
description: `${this._resources.length} resources available`,
|
|
200
|
-
childrenCount: this._resources.length
|
|
201
|
-
} };
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Read root metadata
|
|
303
|
+
*/
|
|
304
|
+
async readRootMeta(_ctx) {
|
|
305
|
+
await this.ensureConnected();
|
|
202
306
|
return {
|
|
203
|
-
|
|
307
|
+
id: "/.meta",
|
|
308
|
+
path: "/.meta",
|
|
309
|
+
meta: {
|
|
204
310
|
kind: "mcp:module",
|
|
205
311
|
kinds: require_kinds.getKindsArray("mcp:module"),
|
|
206
312
|
description: this.description || "MCP Server",
|
|
313
|
+
childrenCount: 2 + (this._prompts.length > 0 ? 1 : 0) + (this._resources.length > 0 ? 1 : 0),
|
|
207
314
|
mcp: {
|
|
208
315
|
server: { name: this.name },
|
|
209
316
|
capabilities: {
|
|
@@ -212,10 +319,361 @@ var AFSMCP = class AFSMCP extends _aigne_afs_provider.AFSBaseProvider {
|
|
|
212
319
|
resources: this._resources.length > 0
|
|
213
320
|
}
|
|
214
321
|
}
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Read capabilities manifest
|
|
327
|
+
*
|
|
328
|
+
* Returns all MCP tools as ToolDefinition objects.
|
|
329
|
+
* MCP has no node-level actions, so actions is always empty.
|
|
330
|
+
*/
|
|
331
|
+
async readCapabilities(_ctx) {
|
|
332
|
+
await this.ensureConnected();
|
|
333
|
+
const tools = this._tools.filter((tool) => tool.name).map((tool) => ({
|
|
334
|
+
name: tool.name,
|
|
335
|
+
description: tool.description,
|
|
336
|
+
path: `/tools/${tool.name}`,
|
|
337
|
+
inputSchema: tool.inputSchema
|
|
338
|
+
}));
|
|
339
|
+
return {
|
|
340
|
+
id: "/.meta/.capabilities",
|
|
341
|
+
path: "/.meta/.capabilities",
|
|
342
|
+
content: {
|
|
343
|
+
schemaVersion: 1,
|
|
344
|
+
provider: this.name,
|
|
345
|
+
version: "1.0.0",
|
|
346
|
+
description: this.description,
|
|
347
|
+
tools,
|
|
348
|
+
actions: [],
|
|
349
|
+
operations: this.getOperationsDeclaration()
|
|
215
350
|
},
|
|
216
|
-
|
|
351
|
+
meta: {
|
|
352
|
+
kind: "afs:capabilities",
|
|
353
|
+
description: "MCP Provider capabilities manifest"
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Stat root directory
|
|
359
|
+
*/
|
|
360
|
+
async statRootHandler(_ctx) {
|
|
361
|
+
await this.ensureConnected();
|
|
362
|
+
const childrenCount = 2 + (this._prompts.length > 0 ? 1 : 0) + (this._resources.length > 0 ? 1 : 0);
|
|
363
|
+
return { data: {
|
|
364
|
+
id: "/",
|
|
365
|
+
path: "/",
|
|
366
|
+
meta: {
|
|
367
|
+
kind: "mcp:module",
|
|
368
|
+
kinds: require_kinds.getKindsArray("mcp:module"),
|
|
369
|
+
description: this.description || "MCP Server",
|
|
370
|
+
childrenCount
|
|
371
|
+
}
|
|
372
|
+
} };
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Read WORLD.md file
|
|
376
|
+
*/
|
|
377
|
+
async readWorldMdHandler(_ctx) {
|
|
378
|
+
await this.ensureConnected();
|
|
379
|
+
return {
|
|
380
|
+
id: "/WORLD.md",
|
|
381
|
+
path: "/WORLD.md",
|
|
382
|
+
content: this.generateWorldMd(),
|
|
383
|
+
meta: {
|
|
384
|
+
kind: "afs:document",
|
|
385
|
+
kinds: require_kinds.getKindsArray("afs:document"),
|
|
386
|
+
description: "MCP Server World Documentation",
|
|
387
|
+
mimeType: "text/markdown",
|
|
388
|
+
mcp: { type: "world" }
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* List WORLD.md - files have no children
|
|
394
|
+
* Note: list() returns only children, never the path itself (per new semantics)
|
|
395
|
+
*/
|
|
396
|
+
async listWorldMdHandler(_ctx) {
|
|
397
|
+
await this.ensureConnected();
|
|
398
|
+
return { data: [] };
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Read WORLD.md metadata
|
|
402
|
+
*/
|
|
403
|
+
async readWorldMdMeta(_ctx) {
|
|
404
|
+
await this.ensureConnected();
|
|
405
|
+
return {
|
|
406
|
+
id: "/WORLD.md/.meta",
|
|
407
|
+
path: "/WORLD.md/.meta",
|
|
408
|
+
meta: {
|
|
409
|
+
kind: "afs:document",
|
|
410
|
+
kinds: require_kinds.getKindsArray("afs:document"),
|
|
411
|
+
description: "MCP Server World Documentation",
|
|
412
|
+
mimeType: "text/markdown",
|
|
413
|
+
mcp: { type: "world" }
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Read /tools directory entry
|
|
419
|
+
*/
|
|
420
|
+
async readToolsDir(_ctx) {
|
|
421
|
+
await this.ensureConnected();
|
|
422
|
+
return {
|
|
423
|
+
id: "/tools",
|
|
424
|
+
path: "/tools",
|
|
425
|
+
summary: `${this._tools.length} tools available`,
|
|
426
|
+
meta: {
|
|
427
|
+
kind: "afs:node",
|
|
428
|
+
kinds: require_kinds.getKindsArray("afs:node"),
|
|
429
|
+
description: `${this._tools.length} tools available`,
|
|
430
|
+
childrenCount: this._tools.length
|
|
431
|
+
}
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* Read /tools metadata
|
|
436
|
+
*/
|
|
437
|
+
async readToolsMeta(_ctx) {
|
|
438
|
+
await this.ensureConnected();
|
|
439
|
+
return {
|
|
440
|
+
id: "/tools/.meta",
|
|
441
|
+
path: "/tools/.meta",
|
|
442
|
+
meta: {
|
|
443
|
+
kind: "afs:node",
|
|
444
|
+
kinds: require_kinds.getKindsArray("afs:node"),
|
|
445
|
+
description: `${this._tools.length} tools available`,
|
|
446
|
+
childrenCount: this._tools.length
|
|
447
|
+
}
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Read /prompts directory entry
|
|
452
|
+
*/
|
|
453
|
+
async readPromptsDir(_ctx) {
|
|
454
|
+
await this.ensureConnected();
|
|
455
|
+
if (this._prompts.length === 0) throw new _aigne_afs.AFSNotFoundError("/prompts");
|
|
456
|
+
return {
|
|
457
|
+
id: "/prompts",
|
|
458
|
+
path: "/prompts",
|
|
459
|
+
summary: `${this._prompts.length} prompts available`,
|
|
460
|
+
meta: {
|
|
461
|
+
kind: "afs:node",
|
|
462
|
+
kinds: require_kinds.getKindsArray("afs:node"),
|
|
463
|
+
description: `${this._prompts.length} prompts available`,
|
|
464
|
+
childrenCount: this._prompts.length
|
|
465
|
+
}
|
|
217
466
|
};
|
|
218
467
|
}
|
|
468
|
+
/**
|
|
469
|
+
* Read /prompts metadata
|
|
470
|
+
*/
|
|
471
|
+
async readPromptsMeta(_ctx) {
|
|
472
|
+
await this.ensureConnected();
|
|
473
|
+
if (this._prompts.length === 0) throw new _aigne_afs.AFSNotFoundError("/prompts/.meta");
|
|
474
|
+
return {
|
|
475
|
+
id: "/prompts/.meta",
|
|
476
|
+
path: "/prompts/.meta",
|
|
477
|
+
meta: {
|
|
478
|
+
kind: "afs:node",
|
|
479
|
+
kinds: require_kinds.getKindsArray("afs:node"),
|
|
480
|
+
description: `${this._prompts.length} prompts available`,
|
|
481
|
+
childrenCount: this._prompts.length
|
|
482
|
+
}
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Read /resources directory entry
|
|
487
|
+
*/
|
|
488
|
+
async readResourcesDir(_ctx) {
|
|
489
|
+
await this.ensureConnected();
|
|
490
|
+
if (this._resources.length === 0 && this._resourceTemplates.length === 0) throw new _aigne_afs.AFSNotFoundError("/resources");
|
|
491
|
+
const immediateChildrenCount = this.getResourcesImmediateChildrenCount();
|
|
492
|
+
return {
|
|
493
|
+
id: "/resources",
|
|
494
|
+
path: "/resources",
|
|
495
|
+
summary: `${this._resources.length} resources available`,
|
|
496
|
+
meta: {
|
|
497
|
+
kind: "afs:node",
|
|
498
|
+
kinds: require_kinds.getKindsArray("afs:node"),
|
|
499
|
+
description: `${this._resources.length} resources available`,
|
|
500
|
+
childrenCount: immediateChildrenCount
|
|
501
|
+
}
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Read /resources metadata
|
|
506
|
+
*/
|
|
507
|
+
async readResourcesMeta(_ctx) {
|
|
508
|
+
await this.ensureConnected();
|
|
509
|
+
if (this._resources.length === 0 && this._resourceTemplates.length === 0) throw new _aigne_afs.AFSNotFoundError("/resources/.meta");
|
|
510
|
+
const immediateChildrenCount = this.getResourcesImmediateChildrenCount();
|
|
511
|
+
return {
|
|
512
|
+
id: "/resources/.meta",
|
|
513
|
+
path: "/resources/.meta",
|
|
514
|
+
meta: {
|
|
515
|
+
kind: "afs:node",
|
|
516
|
+
kinds: require_kinds.getKindsArray("afs:node"),
|
|
517
|
+
description: `${this._resources.length} resources available`,
|
|
518
|
+
childrenCount: immediateChildrenCount
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Calculate immediate children count for /resources directory
|
|
524
|
+
*/
|
|
525
|
+
getResourcesImmediateChildrenCount() {
|
|
526
|
+
const immediateChildren = /* @__PURE__ */ new Set();
|
|
527
|
+
for (const resource of this._resources) {
|
|
528
|
+
const resourcePath = this.resourceUriToPath(resource.uri);
|
|
529
|
+
if (!resourcePath) continue;
|
|
530
|
+
const segments = resourcePath.split("/").filter(Boolean);
|
|
531
|
+
if (segments.length > 0) immediateChildren.add(segments[0]);
|
|
532
|
+
}
|
|
533
|
+
return immediateChildren.size;
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Stat WORLD.md file
|
|
537
|
+
*/
|
|
538
|
+
async statWorldMdHandler(_ctx) {
|
|
539
|
+
await this.ensureConnected();
|
|
540
|
+
return { data: {
|
|
541
|
+
id: "WORLD.md",
|
|
542
|
+
path: "/WORLD.md",
|
|
543
|
+
meta: {
|
|
544
|
+
kind: "afs:document",
|
|
545
|
+
kinds: require_kinds.getKindsArray("afs:document"),
|
|
546
|
+
description: "MCP Server World Documentation",
|
|
547
|
+
mimeType: "text/markdown",
|
|
548
|
+
childrenCount: 0
|
|
549
|
+
}
|
|
550
|
+
} };
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Stat /tools directory
|
|
554
|
+
*/
|
|
555
|
+
async statToolsHandler(_ctx) {
|
|
556
|
+
await this.ensureConnected();
|
|
557
|
+
return { data: {
|
|
558
|
+
id: "tools",
|
|
559
|
+
path: "/tools",
|
|
560
|
+
meta: {
|
|
561
|
+
kind: "afs:node",
|
|
562
|
+
kinds: require_kinds.getKindsArray("afs:node"),
|
|
563
|
+
description: `${this._tools.length} tools available`,
|
|
564
|
+
childrenCount: this._tools.length
|
|
565
|
+
}
|
|
566
|
+
} };
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Stat /prompts directory
|
|
570
|
+
*/
|
|
571
|
+
async statPromptsHandler(_ctx) {
|
|
572
|
+
await this.ensureConnected();
|
|
573
|
+
if (this._prompts.length === 0) throw new _aigne_afs.AFSNotFoundError("/prompts");
|
|
574
|
+
return { data: {
|
|
575
|
+
id: "prompts",
|
|
576
|
+
path: "/prompts",
|
|
577
|
+
meta: {
|
|
578
|
+
kind: "afs:node",
|
|
579
|
+
kinds: require_kinds.getKindsArray("afs:node"),
|
|
580
|
+
description: `${this._prompts.length} prompts available`,
|
|
581
|
+
childrenCount: this._prompts.length
|
|
582
|
+
}
|
|
583
|
+
} };
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Stat /resources directory
|
|
587
|
+
*/
|
|
588
|
+
async statResourcesHandler(_ctx) {
|
|
589
|
+
await this.ensureConnected();
|
|
590
|
+
if (this._resources.length === 0 && this._resourceTemplates.length === 0) throw new _aigne_afs.AFSNotFoundError("/resources");
|
|
591
|
+
const immediateChildrenCount = this.getResourcesImmediateChildrenCount();
|
|
592
|
+
return { data: {
|
|
593
|
+
id: "resources",
|
|
594
|
+
path: "/resources",
|
|
595
|
+
meta: {
|
|
596
|
+
kind: "afs:node",
|
|
597
|
+
kinds: require_kinds.getKindsArray("afs:node"),
|
|
598
|
+
description: `${this._resources.length} resources available`,
|
|
599
|
+
childrenCount: immediateChildrenCount
|
|
600
|
+
}
|
|
601
|
+
} };
|
|
602
|
+
}
|
|
603
|
+
/**
|
|
604
|
+
* Stat specific tool
|
|
605
|
+
*/
|
|
606
|
+
async statToolHandler(ctx) {
|
|
607
|
+
await this.ensureConnected();
|
|
608
|
+
const tool = this._tools.find((t) => t.name === ctx.params.name);
|
|
609
|
+
if (!tool) throw new _aigne_afs.AFSNotFoundError(ctx.path);
|
|
610
|
+
const { content: _content, ...statData } = this.toolToEntry(tool);
|
|
611
|
+
return { data: statData };
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* Stat specific prompt
|
|
615
|
+
*/
|
|
616
|
+
async statPromptHandler(ctx) {
|
|
617
|
+
await this.ensureConnected();
|
|
618
|
+
const prompt = this._prompts.find((p) => p.name === ctx.params.name);
|
|
619
|
+
if (!prompt) throw new _aigne_afs.AFSNotFoundError(ctx.path);
|
|
620
|
+
const { content: _content, ...statData } = this.promptToEntry(prompt);
|
|
621
|
+
return { data: statData };
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* Stat resource paths (wildcard handler under /resources)
|
|
625
|
+
*/
|
|
626
|
+
async statResourceHandler(ctx) {
|
|
627
|
+
await this.ensureConnected();
|
|
628
|
+
const resourcePath = `/${ctx.params.path}`;
|
|
629
|
+
const afsPath = `/resources${resourcePath}`;
|
|
630
|
+
const resourceId = ctx.params.path.split("/").pop() || ctx.params.path;
|
|
631
|
+
const resourceMatch = this.findResourceForPath(resourcePath);
|
|
632
|
+
if (resourceMatch) {
|
|
633
|
+
if (resourceMatch.resource) return { data: {
|
|
634
|
+
id: resourceId,
|
|
635
|
+
path: afsPath,
|
|
636
|
+
meta: {
|
|
637
|
+
kind: "mcp:resource",
|
|
638
|
+
kinds: require_kinds.getKindsArray("mcp:resource"),
|
|
639
|
+
description: resourceMatch.resource.description,
|
|
640
|
+
mimeType: resourceMatch.resource.mimeType,
|
|
641
|
+
childrenCount: 0
|
|
642
|
+
}
|
|
643
|
+
} };
|
|
644
|
+
else if (resourceMatch.template) return { data: {
|
|
645
|
+
id: resourceId,
|
|
646
|
+
path: afsPath,
|
|
647
|
+
meta: {
|
|
648
|
+
kind: "mcp:resource-template",
|
|
649
|
+
kinds: require_kinds.getKindsArray("mcp:resource"),
|
|
650
|
+
description: resourceMatch.template.description,
|
|
651
|
+
mimeType: resourceMatch.template.mimeType,
|
|
652
|
+
childrenCount: 0
|
|
653
|
+
}
|
|
654
|
+
} };
|
|
655
|
+
}
|
|
656
|
+
const immediateChildren = this.getImmediateResourceChildren(resourcePath);
|
|
657
|
+
if (immediateChildren.size > 0) return { data: {
|
|
658
|
+
id: resourceId,
|
|
659
|
+
path: afsPath,
|
|
660
|
+
meta: {
|
|
661
|
+
kind: "afs:node",
|
|
662
|
+
kinds: require_kinds.getKindsArray("afs:node"),
|
|
663
|
+
childrenCount: immediateChildren.size
|
|
664
|
+
}
|
|
665
|
+
} };
|
|
666
|
+
if (this.isTemplateBasePath(resourcePath)) return { data: {
|
|
667
|
+
id: resourceId,
|
|
668
|
+
path: afsPath,
|
|
669
|
+
meta: {
|
|
670
|
+
kind: "afs:node",
|
|
671
|
+
kinds: require_kinds.getKindsArray("afs:node"),
|
|
672
|
+
childrenCount: 0
|
|
673
|
+
}
|
|
674
|
+
} };
|
|
675
|
+
throw new _aigne_afs.AFSNotFoundError(ctx.path);
|
|
676
|
+
}
|
|
219
677
|
get isConnected() {
|
|
220
678
|
return this._isConnected;
|
|
221
679
|
}
|
|
@@ -377,6 +835,35 @@ var AFSMCP = class AFSMCP extends _aigne_afs_provider.AFSBaseProvider {
|
|
|
377
835
|
return basePath.endsWith("/") ? basePath.slice(0, -1) : basePath;
|
|
378
836
|
}
|
|
379
837
|
/**
|
|
838
|
+
* Check if a resource path is a template base path (has dynamic children).
|
|
839
|
+
*/
|
|
840
|
+
isTemplateBasePath(resourcePath) {
|
|
841
|
+
return this._resourceTemplates.some((template) => {
|
|
842
|
+
return this.getTemplateBasePath(template.uriTemplate) === resourcePath;
|
|
843
|
+
});
|
|
844
|
+
}
|
|
845
|
+
/**
|
|
846
|
+
* Get immediate child segments under a resource parent path,
|
|
847
|
+
* scanning both static resources and template base paths.
|
|
848
|
+
*/
|
|
849
|
+
getImmediateResourceChildren(parentPath) {
|
|
850
|
+
const depth = parentPath.split("/").filter(Boolean).length;
|
|
851
|
+
const childSegments = /* @__PURE__ */ new Set();
|
|
852
|
+
for (const resource of this._resources) {
|
|
853
|
+
const rPath = this.resourceUriToPath(resource.uri);
|
|
854
|
+
if (!rPath || !rPath.startsWith(`${parentPath}/`)) continue;
|
|
855
|
+
const segments = rPath.split("/").filter(Boolean);
|
|
856
|
+
if (segments.length > depth) childSegments.add(segments[depth]);
|
|
857
|
+
}
|
|
858
|
+
for (const template of this._resourceTemplates) {
|
|
859
|
+
const basePath = this.getTemplateBasePath(template.uriTemplate);
|
|
860
|
+
if (!basePath || !basePath.startsWith(`${parentPath}/`)) continue;
|
|
861
|
+
const segments = basePath.split("/").filter(Boolean);
|
|
862
|
+
if (segments.length > depth) childSegments.add(segments[depth]);
|
|
863
|
+
}
|
|
864
|
+
return childSegments;
|
|
865
|
+
}
|
|
866
|
+
/**
|
|
380
867
|
* Find a resource or template that matches a given path
|
|
381
868
|
*/
|
|
382
869
|
findResourceForPath(path) {
|
|
@@ -398,7 +885,7 @@ var AFSMCP = class AFSMCP extends _aigne_afs_provider.AFSBaseProvider {
|
|
|
398
885
|
id: `/tools/${tool.name}`,
|
|
399
886
|
path: `/tools/${tool.name}`,
|
|
400
887
|
summary: tool.description,
|
|
401
|
-
|
|
888
|
+
meta: {
|
|
402
889
|
kind: "mcp:tool",
|
|
403
890
|
kinds: require_kinds.getKindsArray("mcp:tool"),
|
|
404
891
|
description: tool.description,
|
|
@@ -409,13 +896,15 @@ var AFSMCP = class AFSMCP extends _aigne_afs_provider.AFSBaseProvider {
|
|
|
409
896
|
}
|
|
410
897
|
/**
|
|
411
898
|
* Convert a Prompt to an AFSEntry (Meta Spec compliant)
|
|
899
|
+
* Note: inputSchema is NOT included in prompt entry meta.
|
|
900
|
+
* For prompts with arguments, use the action system (/.actions/get) to execute.
|
|
412
901
|
*/
|
|
413
902
|
promptToEntry(prompt) {
|
|
414
903
|
return {
|
|
415
904
|
id: `/prompts/${prompt.name}`,
|
|
416
905
|
path: `/prompts/${prompt.name}`,
|
|
417
906
|
summary: prompt.description,
|
|
418
|
-
|
|
907
|
+
meta: {
|
|
419
908
|
kind: "mcp:prompt",
|
|
420
909
|
kinds: require_kinds.getKindsArray("mcp:prompt"),
|
|
421
910
|
description: prompt.description,
|
|
@@ -427,6 +916,41 @@ var AFSMCP = class AFSMCP extends _aigne_afs_provider.AFSBaseProvider {
|
|
|
427
916
|
};
|
|
428
917
|
}
|
|
429
918
|
/**
|
|
919
|
+
* Convert prompt arguments to JSON Schema (for action inputSchema)
|
|
920
|
+
*/
|
|
921
|
+
promptArgsToSchema(args) {
|
|
922
|
+
if (!args || args.length === 0) return {
|
|
923
|
+
type: "object",
|
|
924
|
+
properties: {}
|
|
925
|
+
};
|
|
926
|
+
const properties = {};
|
|
927
|
+
const required = [];
|
|
928
|
+
for (const arg of args) {
|
|
929
|
+
properties[arg.name] = {
|
|
930
|
+
type: "string",
|
|
931
|
+
...arg.description ? { description: arg.description } : {}
|
|
932
|
+
};
|
|
933
|
+
if (arg.required) required.push(arg.name);
|
|
934
|
+
}
|
|
935
|
+
return {
|
|
936
|
+
type: "object",
|
|
937
|
+
properties,
|
|
938
|
+
...required.length > 0 ? { required } : {}
|
|
939
|
+
};
|
|
940
|
+
}
|
|
941
|
+
/**
|
|
942
|
+
* Extract text content from MCP prompt messages
|
|
943
|
+
*/
|
|
944
|
+
extractTextFromMessages(messages) {
|
|
945
|
+
const textParts = [];
|
|
946
|
+
for (const msg of messages) {
|
|
947
|
+
const c = msg.content;
|
|
948
|
+
if (typeof c === "string") textParts.push(c);
|
|
949
|
+
else if (c && typeof c === "object" && "text" in c) textParts.push(c.text);
|
|
950
|
+
}
|
|
951
|
+
return textParts.join("\n");
|
|
952
|
+
}
|
|
953
|
+
/**
|
|
430
954
|
* Convert a Resource to an AFSEntry (Meta Spec compliant)
|
|
431
955
|
*/
|
|
432
956
|
resourceToEntry(resource, path) {
|
|
@@ -434,7 +958,7 @@ var AFSMCP = class AFSMCP extends _aigne_afs_provider.AFSBaseProvider {
|
|
|
434
958
|
id: path,
|
|
435
959
|
path,
|
|
436
960
|
summary: resource.description || resource.name,
|
|
437
|
-
|
|
961
|
+
meta: {
|
|
438
962
|
kind: "mcp:resource",
|
|
439
963
|
kinds: require_kinds.getKindsArray("mcp:resource"),
|
|
440
964
|
description: resource.description,
|
|
@@ -454,7 +978,7 @@ var AFSMCP = class AFSMCP extends _aigne_afs_provider.AFSBaseProvider {
|
|
|
454
978
|
id: path,
|
|
455
979
|
path,
|
|
456
980
|
summary: template.description || template.name,
|
|
457
|
-
|
|
981
|
+
meta: {
|
|
458
982
|
kind: "mcp:resource-template",
|
|
459
983
|
kinds: require_kinds.getKindsArray("mcp:resource"),
|
|
460
984
|
description: template.description,
|
|
@@ -468,9 +992,7 @@ var AFSMCP = class AFSMCP extends _aigne_afs_provider.AFSBaseProvider {
|
|
|
468
992
|
}
|
|
469
993
|
/**
|
|
470
994
|
* List tools.
|
|
471
|
-
*
|
|
472
|
-
* Returns tool children only. The /tools directory entry comes from @StaticEntries
|
|
473
|
-
* and will be merged with dynamic childrenCount.
|
|
995
|
+
* Note: list() returns only children, never the path itself (per new semantics)
|
|
474
996
|
*/
|
|
475
997
|
async listToolsHandler(_ctx) {
|
|
476
998
|
await this.ensureConnected();
|
|
@@ -478,39 +1000,38 @@ var AFSMCP = class AFSMCP extends _aigne_afs_provider.AFSBaseProvider {
|
|
|
478
1000
|
}
|
|
479
1001
|
/**
|
|
480
1002
|
* List prompts.
|
|
481
|
-
*
|
|
482
|
-
* Returns prompt children only. The /prompts directory entry comes from @StaticEntries
|
|
483
|
-
* and will be merged with dynamic childrenCount.
|
|
1003
|
+
* Note: list() returns only children, never the path itself (per new semantics)
|
|
484
1004
|
*/
|
|
485
1005
|
async listPromptsHandler(_ctx) {
|
|
486
1006
|
await this.ensureConnected();
|
|
1007
|
+
if (this._prompts.length === 0) throw new _aigne_afs.AFSNotFoundError("/prompts");
|
|
487
1008
|
return { data: this._prompts.map((prompt) => this.promptToEntry(prompt)) };
|
|
488
1009
|
}
|
|
489
1010
|
/**
|
|
490
|
-
* List specific tool
|
|
1011
|
+
* List specific tool - tools are leaf nodes with no children
|
|
1012
|
+
* Note: list() returns only children, never the path itself (per new semantics)
|
|
491
1013
|
*/
|
|
492
1014
|
async listToolHandler(ctx) {
|
|
493
1015
|
await this.ensureConnected();
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
return { data: [this.toolToEntry(tool)] };
|
|
1016
|
+
if (!this._tools.find((t) => t.name === ctx.params.name)) throw new _aigne_afs.AFSNotFoundError(ctx.path);
|
|
1017
|
+
return { data: [] };
|
|
497
1018
|
}
|
|
498
1019
|
/**
|
|
499
|
-
* List specific prompt
|
|
1020
|
+
* List specific prompt - prompts are leaf nodes with no children
|
|
1021
|
+
* Note: list() returns only children, never the path itself (per new semantics)
|
|
500
1022
|
*/
|
|
501
1023
|
async listPromptHandler(ctx) {
|
|
502
1024
|
await this.ensureConnected();
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
return { data: [this.promptToEntry(prompt)] };
|
|
1025
|
+
if (!this._prompts.find((p) => p.name === ctx.params.name)) throw new _aigne_afs.AFSNotFoundError(ctx.path);
|
|
1026
|
+
return { data: [] };
|
|
506
1027
|
}
|
|
507
1028
|
/**
|
|
508
1029
|
* List resources directory.
|
|
509
|
-
*
|
|
510
|
-
* Returns all resources as children of /resources.
|
|
1030
|
+
* Note: list() returns only children, never the path itself (per new semantics)
|
|
511
1031
|
*/
|
|
512
1032
|
async listResourcesHandler(_ctx) {
|
|
513
1033
|
await this.ensureConnected();
|
|
1034
|
+
if (this._resources.length === 0 && this._resourceTemplates.length === 0) throw new _aigne_afs.AFSNotFoundError("/resources");
|
|
514
1035
|
const immediateChildren = /* @__PURE__ */ new Map();
|
|
515
1036
|
for (const resource of this._resources) {
|
|
516
1037
|
const resourcePath = this.resourceUriToPath(resource.uri);
|
|
@@ -524,27 +1045,39 @@ var AFSMCP = class AFSMCP extends _aigne_afs_provider.AFSBaseProvider {
|
|
|
524
1045
|
});
|
|
525
1046
|
else if (!immediateChildren.has(childPath)) immediateChildren.set(childPath, { isDir: true });
|
|
526
1047
|
}
|
|
1048
|
+
for (const template of this._resourceTemplates) {
|
|
1049
|
+
const basePath = this.getTemplateBasePath(template.uriTemplate);
|
|
1050
|
+
if (!basePath) continue;
|
|
1051
|
+
const segments = basePath.split("/").filter(Boolean);
|
|
1052
|
+
if (segments.length === 0) continue;
|
|
1053
|
+
const childPath = `/resources/${segments[0]}`;
|
|
1054
|
+
if (!immediateChildren.has(childPath)) immediateChildren.set(childPath, { isDir: true });
|
|
1055
|
+
}
|
|
527
1056
|
const entries = [];
|
|
528
|
-
for (const [path, info] of immediateChildren) if (info.isDir)
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
1057
|
+
for (const [path, info] of immediateChildren) if (info.isDir) {
|
|
1058
|
+
const resourceSubPath = path.replace("/resources", "");
|
|
1059
|
+
const childrenCount = this.getImmediateResourceChildren(resourceSubPath).size;
|
|
1060
|
+
entries.push({
|
|
1061
|
+
id: path,
|
|
1062
|
+
path,
|
|
1063
|
+
summary: `Resource directory: ${resourceSubPath}`,
|
|
1064
|
+
meta: {
|
|
1065
|
+
kind: "afs:node",
|
|
1066
|
+
kinds: require_kinds.getKindsArray("afs:node"),
|
|
1067
|
+
childrenCount,
|
|
1068
|
+
mcp: { isResource: true }
|
|
1069
|
+
}
|
|
1070
|
+
});
|
|
1071
|
+
} else if (info.resource) entries.push(this.resourceToEntry(info.resource, path));
|
|
539
1072
|
return { data: entries };
|
|
540
1073
|
}
|
|
541
1074
|
/**
|
|
542
1075
|
* List resource paths (wildcard handler under /resources)
|
|
1076
|
+
* Note: list() returns only children, never the path itself (per new semantics)
|
|
543
1077
|
*/
|
|
544
1078
|
async listResourceHandler(ctx) {
|
|
545
1079
|
await this.ensureConnected();
|
|
546
1080
|
const resourcePath = `/${ctx.params.path}`;
|
|
547
|
-
const afsPath = `/resources${resourcePath}`;
|
|
548
1081
|
const entries = [];
|
|
549
1082
|
let exactMatch = null;
|
|
550
1083
|
const immediateChildren = /* @__PURE__ */ new Map();
|
|
@@ -564,32 +1097,37 @@ var AFSMCP = class AFSMCP extends _aigne_afs_provider.AFSBaseProvider {
|
|
|
564
1097
|
else if (!immediateChildren.has(childPath)) immediateChildren.set(childPath, { isDir: true });
|
|
565
1098
|
}
|
|
566
1099
|
}
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
for (const [path, info] of immediateChildren) if (info.isDir)
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
1100
|
+
for (const template of this._resourceTemplates) {
|
|
1101
|
+
const basePath = this.getTemplateBasePath(template.uriTemplate);
|
|
1102
|
+
if (!basePath) continue;
|
|
1103
|
+
if (basePath === resourcePath) return { data: [] };
|
|
1104
|
+
else if (basePath.startsWith(`${resourcePath}/`)) {
|
|
1105
|
+
const segments = basePath.split("/").filter(Boolean);
|
|
1106
|
+
if (segments.length <= depth) continue;
|
|
1107
|
+
const childPath = `/resources${resourcePath}/${segments[depth]}`;
|
|
1108
|
+
if (!immediateChildren.has(childPath)) immediateChildren.set(childPath, { isDir: true });
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
if (exactMatch) return { data: [] };
|
|
1112
|
+
if (immediateChildren.size > 0) {
|
|
1113
|
+
for (const [path, info] of immediateChildren) if (info.isDir) {
|
|
1114
|
+
const resourceSubPath = path.replace("/resources", "");
|
|
1115
|
+
const childrenCount = this.getImmediateResourceChildren(resourceSubPath).size;
|
|
1116
|
+
entries.push({
|
|
1117
|
+
id: path,
|
|
1118
|
+
path,
|
|
1119
|
+
summary: `Resource directory: ${resourceSubPath}`,
|
|
1120
|
+
meta: {
|
|
1121
|
+
kind: "afs:node",
|
|
1122
|
+
kinds: require_kinds.getKindsArray("afs:node"),
|
|
1123
|
+
childrenCount,
|
|
1124
|
+
mcp: { isResource: true }
|
|
1125
|
+
}
|
|
1126
|
+
});
|
|
1127
|
+
} else if (info.resource) entries.push(this.resourceToEntry(info.resource, path));
|
|
1128
|
+
return { data: entries };
|
|
1129
|
+
}
|
|
1130
|
+
throw new _aigne_afs.AFSNotFoundError(ctx.path);
|
|
593
1131
|
}
|
|
594
1132
|
/**
|
|
595
1133
|
* Read metadata for tools (dynamic entries not in static tree).
|
|
@@ -603,7 +1141,7 @@ var AFSMCP = class AFSMCP extends _aigne_afs_provider.AFSBaseProvider {
|
|
|
603
1141
|
return {
|
|
604
1142
|
id: `/tools/${ctx.params.name}/.meta`,
|
|
605
1143
|
path: `/tools/${ctx.params.name}/.meta`,
|
|
606
|
-
|
|
1144
|
+
meta: entry.meta
|
|
607
1145
|
};
|
|
608
1146
|
}
|
|
609
1147
|
/**
|
|
@@ -617,7 +1155,7 @@ var AFSMCP = class AFSMCP extends _aigne_afs_provider.AFSBaseProvider {
|
|
|
617
1155
|
return {
|
|
618
1156
|
id: `/prompts/${ctx.params.name}/.meta`,
|
|
619
1157
|
path: `/prompts/${ctx.params.name}/.meta`,
|
|
620
|
-
|
|
1158
|
+
meta: entry.meta
|
|
621
1159
|
};
|
|
622
1160
|
}
|
|
623
1161
|
/**
|
|
@@ -633,25 +1171,31 @@ var AFSMCP = class AFSMCP extends _aigne_afs_provider.AFSBaseProvider {
|
|
|
633
1171
|
if (resourceMatch.resource) return {
|
|
634
1172
|
id: metaPath,
|
|
635
1173
|
path: metaPath,
|
|
636
|
-
|
|
1174
|
+
meta: this.resourceToEntry(resourceMatch.resource, `/resources${resourcePath}`).meta
|
|
637
1175
|
};
|
|
638
1176
|
else if (resourceMatch.template) return {
|
|
639
1177
|
id: metaPath,
|
|
640
1178
|
path: metaPath,
|
|
641
|
-
|
|
1179
|
+
meta: this.resourceTemplateToEntry(resourceMatch.template, `/resources${resourcePath}`).meta
|
|
642
1180
|
};
|
|
643
1181
|
}
|
|
644
|
-
if (this.
|
|
645
|
-
return this.resourceUriToPath(resource.uri)?.startsWith(`${resourcePath}/`);
|
|
646
|
-
})) return {
|
|
1182
|
+
if (this.getImmediateResourceChildren(resourcePath).size > 0) return {
|
|
647
1183
|
id: metaPath,
|
|
648
1184
|
path: metaPath,
|
|
649
|
-
|
|
1185
|
+
meta: {
|
|
650
1186
|
kind: "afs:node",
|
|
651
1187
|
kinds: require_kinds.getKindsArray("afs:node"),
|
|
652
1188
|
mcp: { isResource: true }
|
|
653
1189
|
}
|
|
654
1190
|
};
|
|
1191
|
+
if (this.isTemplateBasePath(resourcePath)) {
|
|
1192
|
+
const template = this._resourceTemplates.find((t) => this.getTemplateBasePath(t.uriTemplate) === resourcePath);
|
|
1193
|
+
if (template) return {
|
|
1194
|
+
id: metaPath,
|
|
1195
|
+
path: metaPath,
|
|
1196
|
+
meta: this.resourceTemplateToEntry(template, `/resources${resourcePath}`).meta
|
|
1197
|
+
};
|
|
1198
|
+
}
|
|
655
1199
|
throw new _aigne_afs.AFSNotFoundError(ctx.path);
|
|
656
1200
|
}
|
|
657
1201
|
/**
|
|
@@ -665,12 +1209,195 @@ var AFSMCP = class AFSMCP extends _aigne_afs_provider.AFSBaseProvider {
|
|
|
665
1209
|
}
|
|
666
1210
|
/**
|
|
667
1211
|
* Read prompt
|
|
1212
|
+
*
|
|
1213
|
+
* Behavior:
|
|
1214
|
+
* - Prompts with NO arguments: returns content directly
|
|
1215
|
+
* - Prompts with ONLY optional arguments: returns content (empty params)
|
|
1216
|
+
* - Prompts with REQUIRED arguments: returns metadata only (use /.actions/get to execute)
|
|
668
1217
|
*/
|
|
669
1218
|
async readPromptHandler(ctx) {
|
|
670
1219
|
await this.ensureConnected();
|
|
671
1220
|
const prompt = this._prompts.find((p) => p.name === ctx.params.name);
|
|
672
1221
|
if (!prompt) throw new _aigne_afs.AFSNotFoundError(ctx.path);
|
|
673
|
-
|
|
1222
|
+
const entry = this.promptToEntry(prompt);
|
|
1223
|
+
const hasRequiredArgs = prompt.arguments?.some((arg) => arg.required) ?? false;
|
|
1224
|
+
if (this.client && !hasRequiredArgs) try {
|
|
1225
|
+
const result = await this.client.getPrompt({
|
|
1226
|
+
name: prompt.name,
|
|
1227
|
+
arguments: {}
|
|
1228
|
+
});
|
|
1229
|
+
const content = this.extractTextFromMessages(result.messages);
|
|
1230
|
+
if (content) entry.content = content;
|
|
1231
|
+
} catch {}
|
|
1232
|
+
return entry;
|
|
1233
|
+
}
|
|
1234
|
+
/**
|
|
1235
|
+
* List actions for a prompt
|
|
1236
|
+
*
|
|
1237
|
+
* Only prompts with arguments expose a "get" action.
|
|
1238
|
+
*/
|
|
1239
|
+
async listPromptActions(ctx) {
|
|
1240
|
+
await this.ensureConnected();
|
|
1241
|
+
const prompt = this._prompts.find((p) => p.name === ctx.params.name);
|
|
1242
|
+
if (!prompt) throw new _aigne_afs.AFSNotFoundError(ctx.path);
|
|
1243
|
+
if (!prompt.arguments || prompt.arguments.length === 0) return { data: [] };
|
|
1244
|
+
return { data: [{
|
|
1245
|
+
id: "get",
|
|
1246
|
+
path: `/prompts/${prompt.name}/.actions/get`,
|
|
1247
|
+
summary: `Get ${prompt.name} prompt content with arguments`,
|
|
1248
|
+
meta: {
|
|
1249
|
+
kind: "afs:executable",
|
|
1250
|
+
kinds: require_kinds.getKindsArray("afs:executable"),
|
|
1251
|
+
name: "get",
|
|
1252
|
+
description: prompt.description,
|
|
1253
|
+
inputSchema: this.promptArgsToSchema(prompt.arguments)
|
|
1254
|
+
}
|
|
1255
|
+
}] };
|
|
1256
|
+
}
|
|
1257
|
+
/**
|
|
1258
|
+
* Execute prompt "get" action
|
|
1259
|
+
*
|
|
1260
|
+
* Fetches prompt content with provided arguments.
|
|
1261
|
+
*/
|
|
1262
|
+
async execPromptGetHandler(ctx, params) {
|
|
1263
|
+
await this.ensureConnected();
|
|
1264
|
+
const prompt = this._prompts.find((p) => p.name === ctx.params.name);
|
|
1265
|
+
if (!prompt) return {
|
|
1266
|
+
success: false,
|
|
1267
|
+
error: {
|
|
1268
|
+
code: "NOT_FOUND",
|
|
1269
|
+
message: `Prompt not found: ${ctx.params.name}`
|
|
1270
|
+
}
|
|
1271
|
+
};
|
|
1272
|
+
if (!this.client) return {
|
|
1273
|
+
success: false,
|
|
1274
|
+
error: {
|
|
1275
|
+
code: "NOT_CONNECTED",
|
|
1276
|
+
message: "MCP client not connected"
|
|
1277
|
+
}
|
|
1278
|
+
};
|
|
1279
|
+
try {
|
|
1280
|
+
const result = await this.client.getPrompt({
|
|
1281
|
+
name: prompt.name,
|
|
1282
|
+
arguments: params
|
|
1283
|
+
});
|
|
1284
|
+
return {
|
|
1285
|
+
success: true,
|
|
1286
|
+
data: {
|
|
1287
|
+
content: this.extractTextFromMessages(result.messages),
|
|
1288
|
+
meta: { mcp: {
|
|
1289
|
+
name: prompt.name,
|
|
1290
|
+
arguments: prompt.arguments
|
|
1291
|
+
} }
|
|
1292
|
+
}
|
|
1293
|
+
};
|
|
1294
|
+
} catch (error) {
|
|
1295
|
+
return {
|
|
1296
|
+
success: false,
|
|
1297
|
+
error: {
|
|
1298
|
+
code: "EXECUTION_ERROR",
|
|
1299
|
+
message: error.message
|
|
1300
|
+
}
|
|
1301
|
+
};
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
/**
|
|
1305
|
+
* List actions for a resource template
|
|
1306
|
+
*
|
|
1307
|
+
* Only resource templates expose a "get" action.
|
|
1308
|
+
* Static resources do not have actions.
|
|
1309
|
+
*/
|
|
1310
|
+
async listResourceActions(ctx) {
|
|
1311
|
+
await this.ensureConnected();
|
|
1312
|
+
const resourcePath = `/${ctx.params.path}`;
|
|
1313
|
+
if (!this.isTemplateBasePath(resourcePath)) return { data: [] };
|
|
1314
|
+
const template = this._resourceTemplates.find((t) => this.getTemplateBasePath(t.uriTemplate) === resourcePath);
|
|
1315
|
+
if (!template) return { data: [] };
|
|
1316
|
+
const vars = AFSMCP.parseUriTemplate(template.uriTemplate);
|
|
1317
|
+
if (vars.length === 0) return { data: [] };
|
|
1318
|
+
const properties = {};
|
|
1319
|
+
for (const v of vars) properties[v] = {
|
|
1320
|
+
type: "string",
|
|
1321
|
+
description: `Template variable: ${v}`
|
|
1322
|
+
};
|
|
1323
|
+
const inputSchema = {
|
|
1324
|
+
type: "object",
|
|
1325
|
+
properties,
|
|
1326
|
+
required: vars
|
|
1327
|
+
};
|
|
1328
|
+
return { data: [{
|
|
1329
|
+
id: "get",
|
|
1330
|
+
path: `${`/resources${resourcePath}`}/.actions/get`,
|
|
1331
|
+
summary: `Get resource with template parameters`,
|
|
1332
|
+
meta: {
|
|
1333
|
+
kind: "afs:executable",
|
|
1334
|
+
kinds: require_kinds.getKindsArray("afs:executable"),
|
|
1335
|
+
name: "get",
|
|
1336
|
+
description: template.description,
|
|
1337
|
+
inputSchema
|
|
1338
|
+
}
|
|
1339
|
+
}] };
|
|
1340
|
+
}
|
|
1341
|
+
/**
|
|
1342
|
+
* Execute resource template "get" action
|
|
1343
|
+
*
|
|
1344
|
+
* Fetches resource content with provided template parameters.
|
|
1345
|
+
*/
|
|
1346
|
+
async execResourceGetHandler(ctx, params) {
|
|
1347
|
+
await this.ensureConnected();
|
|
1348
|
+
const resourcePath = `/${ctx.params.path}`;
|
|
1349
|
+
if (!this.isTemplateBasePath(resourcePath)) return {
|
|
1350
|
+
success: false,
|
|
1351
|
+
error: {
|
|
1352
|
+
code: "NOT_TEMPLATE",
|
|
1353
|
+
message: `Not a resource template: ${resourcePath}`
|
|
1354
|
+
}
|
|
1355
|
+
};
|
|
1356
|
+
const template = this._resourceTemplates.find((t) => this.getTemplateBasePath(t.uriTemplate) === resourcePath);
|
|
1357
|
+
if (!template) return {
|
|
1358
|
+
success: false,
|
|
1359
|
+
error: {
|
|
1360
|
+
code: "NOT_FOUND",
|
|
1361
|
+
message: `Resource template not found: ${resourcePath}`
|
|
1362
|
+
}
|
|
1363
|
+
};
|
|
1364
|
+
if (!this.client) return {
|
|
1365
|
+
success: false,
|
|
1366
|
+
error: {
|
|
1367
|
+
code: "NOT_CONNECTED",
|
|
1368
|
+
message: "MCP client not connected"
|
|
1369
|
+
}
|
|
1370
|
+
};
|
|
1371
|
+
try {
|
|
1372
|
+
const uri = AFSMCP.buildUriFromTemplate(template.uriTemplate, params);
|
|
1373
|
+
const result = await this.readResourceByUri(uri);
|
|
1374
|
+
if (!result.data) return {
|
|
1375
|
+
success: false,
|
|
1376
|
+
error: {
|
|
1377
|
+
code: "NOT_FOUND",
|
|
1378
|
+
message: result.message || "Resource not found"
|
|
1379
|
+
}
|
|
1380
|
+
};
|
|
1381
|
+
return {
|
|
1382
|
+
success: true,
|
|
1383
|
+
data: {
|
|
1384
|
+
content: result.data.content,
|
|
1385
|
+
meta: { mcp: {
|
|
1386
|
+
uri,
|
|
1387
|
+
name: template.name,
|
|
1388
|
+
uriTemplate: template.uriTemplate
|
|
1389
|
+
} }
|
|
1390
|
+
}
|
|
1391
|
+
};
|
|
1392
|
+
} catch (error) {
|
|
1393
|
+
return {
|
|
1394
|
+
success: false,
|
|
1395
|
+
error: {
|
|
1396
|
+
code: "EXECUTION_ERROR",
|
|
1397
|
+
message: error.message
|
|
1398
|
+
}
|
|
1399
|
+
};
|
|
1400
|
+
}
|
|
674
1401
|
}
|
|
675
1402
|
/**
|
|
676
1403
|
* Read resource (wildcard handler under /resources)
|
|
@@ -696,18 +1423,38 @@ var AFSMCP = class AFSMCP extends _aigne_afs_provider.AFSBaseProvider {
|
|
|
696
1423
|
return result.data;
|
|
697
1424
|
}
|
|
698
1425
|
}
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
})) return {
|
|
1426
|
+
const immediateChildrenSet = this.getImmediateResourceChildren(resourcePath);
|
|
1427
|
+
if (immediateChildrenSet.size > 0) return {
|
|
702
1428
|
id: afsPath,
|
|
703
1429
|
path: afsPath,
|
|
704
1430
|
summary: `Resource directory: ${resourcePath}`,
|
|
705
|
-
|
|
1431
|
+
meta: {
|
|
706
1432
|
kind: "afs:node",
|
|
707
1433
|
kinds: require_kinds.getKindsArray("afs:node"),
|
|
1434
|
+
childrenCount: immediateChildrenSet.size,
|
|
708
1435
|
mcp: { isResource: true }
|
|
709
1436
|
}
|
|
710
1437
|
};
|
|
1438
|
+
if (this.isTemplateBasePath(resourcePath)) {
|
|
1439
|
+
const template = this._resourceTemplates.find((t) => this.getTemplateBasePath(t.uriTemplate) === resourcePath);
|
|
1440
|
+
return {
|
|
1441
|
+
id: afsPath,
|
|
1442
|
+
path: afsPath,
|
|
1443
|
+
summary: template?.description || `Resource template: ${resourcePath}`,
|
|
1444
|
+
meta: {
|
|
1445
|
+
kind: "mcp:resource-template",
|
|
1446
|
+
kinds: require_kinds.getKindsArray("mcp:resource"),
|
|
1447
|
+
description: template?.description,
|
|
1448
|
+
mimeType: template?.mimeType,
|
|
1449
|
+
childrenCount: 0,
|
|
1450
|
+
mcp: {
|
|
1451
|
+
uriTemplate: template?.uriTemplate,
|
|
1452
|
+
name: template?.name,
|
|
1453
|
+
parameters: template ? AFSMCP.parseUriTemplate(template.uriTemplate) : []
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
};
|
|
1457
|
+
}
|
|
711
1458
|
throw new _aigne_afs.AFSNotFoundError(ctx.path);
|
|
712
1459
|
}
|
|
713
1460
|
/**
|
|
@@ -733,7 +1480,7 @@ var AFSMCP = class AFSMCP extends _aigne_afs_provider.AFSBaseProvider {
|
|
|
733
1480
|
id: path,
|
|
734
1481
|
path,
|
|
735
1482
|
content,
|
|
736
|
-
|
|
1483
|
+
meta: { mcp: {
|
|
737
1484
|
uri,
|
|
738
1485
|
mimeType
|
|
739
1486
|
} }
|
|
@@ -777,7 +1524,7 @@ var AFSMCP = class AFSMCP extends _aigne_afs_provider.AFSBaseProvider {
|
|
|
777
1524
|
path: `/prompts/${promptName}`,
|
|
778
1525
|
summary: prompt.description,
|
|
779
1526
|
content: result.messages,
|
|
780
|
-
|
|
1527
|
+
meta: {
|
|
781
1528
|
arguments: prompt.arguments,
|
|
782
1529
|
mcp: {
|
|
783
1530
|
name: prompt.name,
|
|
@@ -898,6 +1645,191 @@ var AFSMCP = class AFSMCP extends _aigne_afs_provider.AFSBaseProvider {
|
|
|
898
1645
|
return lines.join("\n");
|
|
899
1646
|
}
|
|
900
1647
|
/**
|
|
1648
|
+
* Explain root → server name, tools/prompts/resources counts
|
|
1649
|
+
*/
|
|
1650
|
+
async explainRoot(_ctx) {
|
|
1651
|
+
await this.ensureConnected();
|
|
1652
|
+
const lines = [];
|
|
1653
|
+
lines.push(`# ${this.name}`);
|
|
1654
|
+
lines.push("");
|
|
1655
|
+
if (this.description) {
|
|
1656
|
+
lines.push(this.description);
|
|
1657
|
+
lines.push("");
|
|
1658
|
+
}
|
|
1659
|
+
lines.push("## Overview");
|
|
1660
|
+
lines.push("");
|
|
1661
|
+
lines.push(`- **Tool count**: ${this._tools.length}`);
|
|
1662
|
+
lines.push(`- **Prompt count**: ${this._prompts.length}`);
|
|
1663
|
+
lines.push(`- **Resource count**: ${this._resources.length}`);
|
|
1664
|
+
lines.push(`- **Resource template count**: ${this._resourceTemplates.length}`);
|
|
1665
|
+
lines.push("");
|
|
1666
|
+
if (this._tools.length > 0) {
|
|
1667
|
+
lines.push("## Tools");
|
|
1668
|
+
lines.push("");
|
|
1669
|
+
for (const tool of this._tools) lines.push(`- **${tool.name}**: ${tool.description ?? "(no description)"}`);
|
|
1670
|
+
lines.push("");
|
|
1671
|
+
}
|
|
1672
|
+
if (this._prompts.length > 0) {
|
|
1673
|
+
lines.push("## Prompts");
|
|
1674
|
+
lines.push("");
|
|
1675
|
+
for (const prompt of this._prompts) {
|
|
1676
|
+
const argNames = prompt.arguments?.map((a) => a.name).join(", ") ?? "";
|
|
1677
|
+
lines.push(`- **${prompt.name}**: ${prompt.description ?? "(no description)"}${argNames ? ` (args: ${argNames})` : ""}`);
|
|
1678
|
+
}
|
|
1679
|
+
lines.push("");
|
|
1680
|
+
}
|
|
1681
|
+
if (this._resources.length > 0) {
|
|
1682
|
+
lines.push("## Resources");
|
|
1683
|
+
lines.push("");
|
|
1684
|
+
for (const resource of this._resources) lines.push(`- **${resource.name}**: ${resource.description ?? resource.uri}`);
|
|
1685
|
+
lines.push("");
|
|
1686
|
+
}
|
|
1687
|
+
return {
|
|
1688
|
+
format: "markdown",
|
|
1689
|
+
content: lines.join("\n")
|
|
1690
|
+
};
|
|
1691
|
+
}
|
|
1692
|
+
/**
|
|
1693
|
+
* Explain a specific tool → name, description, inputSchema
|
|
1694
|
+
*/
|
|
1695
|
+
async explainTool(ctx) {
|
|
1696
|
+
await this.ensureConnected();
|
|
1697
|
+
const tool = this._tools.find((t) => t.name === ctx.params.name);
|
|
1698
|
+
if (!tool) throw new _aigne_afs.AFSNotFoundError(ctx.path, `Tool not found: ${ctx.params.name}`);
|
|
1699
|
+
const lines = [];
|
|
1700
|
+
lines.push(`# Tool: ${tool.name}`);
|
|
1701
|
+
lines.push("");
|
|
1702
|
+
if (tool.description) {
|
|
1703
|
+
lines.push(tool.description);
|
|
1704
|
+
lines.push("");
|
|
1705
|
+
}
|
|
1706
|
+
if (tool.inputSchema) {
|
|
1707
|
+
lines.push("## Input Schema");
|
|
1708
|
+
lines.push("");
|
|
1709
|
+
lines.push("```json");
|
|
1710
|
+
lines.push(JSON.stringify(tool.inputSchema, null, 2));
|
|
1711
|
+
lines.push("```");
|
|
1712
|
+
lines.push("");
|
|
1713
|
+
const props = tool.inputSchema.properties;
|
|
1714
|
+
if (props) {
|
|
1715
|
+
lines.push("## Parameters");
|
|
1716
|
+
lines.push("");
|
|
1717
|
+
for (const [key, val] of Object.entries(props)) {
|
|
1718
|
+
const prop = val;
|
|
1719
|
+
lines.push(`- **${key}** (${prop.type ?? "unknown"}): ${prop.description ?? "(no description)"}`);
|
|
1720
|
+
}
|
|
1721
|
+
lines.push("");
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1724
|
+
return {
|
|
1725
|
+
format: "markdown",
|
|
1726
|
+
content: lines.join("\n")
|
|
1727
|
+
};
|
|
1728
|
+
}
|
|
1729
|
+
/**
|
|
1730
|
+
* Explain a specific prompt → name, description, arguments
|
|
1731
|
+
*/
|
|
1732
|
+
async explainPrompt(ctx) {
|
|
1733
|
+
await this.ensureConnected();
|
|
1734
|
+
const prompt = this._prompts.find((p) => p.name === ctx.params.name);
|
|
1735
|
+
if (!prompt) throw new _aigne_afs.AFSNotFoundError(ctx.path, `Prompt not found: ${ctx.params.name}`);
|
|
1736
|
+
const lines = [];
|
|
1737
|
+
lines.push(`# Prompt: ${prompt.name}`);
|
|
1738
|
+
lines.push("");
|
|
1739
|
+
if (prompt.description) {
|
|
1740
|
+
lines.push(prompt.description);
|
|
1741
|
+
lines.push("");
|
|
1742
|
+
}
|
|
1743
|
+
if (prompt.arguments && prompt.arguments.length > 0) {
|
|
1744
|
+
lines.push("## Arguments");
|
|
1745
|
+
lines.push("");
|
|
1746
|
+
for (const arg of prompt.arguments) {
|
|
1747
|
+
const required = arg.required ? " (required)" : " (optional)";
|
|
1748
|
+
lines.push(`- **${arg.name}**${required}: ${arg.description ?? "(no description)"}`);
|
|
1749
|
+
}
|
|
1750
|
+
lines.push("");
|
|
1751
|
+
} else {
|
|
1752
|
+
lines.push("*No arguments required.*");
|
|
1753
|
+
lines.push("");
|
|
1754
|
+
}
|
|
1755
|
+
return {
|
|
1756
|
+
format: "markdown",
|
|
1757
|
+
content: lines.join("\n")
|
|
1758
|
+
};
|
|
1759
|
+
}
|
|
1760
|
+
/**
|
|
1761
|
+
* Explain a specific resource → name, URI, description
|
|
1762
|
+
*/
|
|
1763
|
+
async explainResource(ctx) {
|
|
1764
|
+
await this.ensureConnected();
|
|
1765
|
+
const resourcePath = `/${ctx.params.path}`;
|
|
1766
|
+
const resourceMatch = this.findResourceForPath(resourcePath);
|
|
1767
|
+
if (resourceMatch?.resource) {
|
|
1768
|
+
const resource = resourceMatch.resource;
|
|
1769
|
+
const lines = [];
|
|
1770
|
+
lines.push(`# Resource: ${resource.name}`);
|
|
1771
|
+
lines.push("");
|
|
1772
|
+
if (resource.description) {
|
|
1773
|
+
lines.push(resource.description);
|
|
1774
|
+
lines.push("");
|
|
1775
|
+
}
|
|
1776
|
+
lines.push(`- **URI**: ${resource.uri}`);
|
|
1777
|
+
if (resource.mimeType) lines.push(`- **MIME Type**: ${resource.mimeType}`);
|
|
1778
|
+
lines.push("");
|
|
1779
|
+
return {
|
|
1780
|
+
format: "markdown",
|
|
1781
|
+
content: lines.join("\n")
|
|
1782
|
+
};
|
|
1783
|
+
}
|
|
1784
|
+
if (resourceMatch?.template) {
|
|
1785
|
+
const template = resourceMatch.template;
|
|
1786
|
+
const lines = [];
|
|
1787
|
+
lines.push(`# Resource Template: ${template.name}`);
|
|
1788
|
+
lines.push("");
|
|
1789
|
+
if (template.description) {
|
|
1790
|
+
lines.push(template.description);
|
|
1791
|
+
lines.push("");
|
|
1792
|
+
}
|
|
1793
|
+
lines.push(`- **URI Template**: ${template.uriTemplate}`);
|
|
1794
|
+
const vars = AFSMCP.parseUriTemplate(template.uriTemplate);
|
|
1795
|
+
if (vars.length > 0) lines.push(`- **Variables**: ${vars.join(", ")}`);
|
|
1796
|
+
lines.push("");
|
|
1797
|
+
return {
|
|
1798
|
+
format: "markdown",
|
|
1799
|
+
content: lines.join("\n")
|
|
1800
|
+
};
|
|
1801
|
+
}
|
|
1802
|
+
throw new _aigne_afs.AFSNotFoundError(ctx.path, `Resource not found: ${ctx.path}`);
|
|
1803
|
+
}
|
|
1804
|
+
/**
|
|
1805
|
+
* Search tools, prompts, and resources by name or description
|
|
1806
|
+
*/
|
|
1807
|
+
async searchHandler(_ctx, query, options) {
|
|
1808
|
+
await this.ensureConnected();
|
|
1809
|
+
const results = [];
|
|
1810
|
+
const limit = options?.limit;
|
|
1811
|
+
const escapedQuery = query.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1812
|
+
const flags = options?.caseSensitive ? "" : "i";
|
|
1813
|
+
const pattern = new RegExp(escapedQuery, flags);
|
|
1814
|
+
const matchAll = query === "";
|
|
1815
|
+
for (const tool of this._tools) {
|
|
1816
|
+
if (limit && results.length >= limit) break;
|
|
1817
|
+
if (matchAll || pattern.test(tool.name) || tool.description && pattern.test(tool.description)) results.push(this.toolToEntry(tool));
|
|
1818
|
+
}
|
|
1819
|
+
for (const prompt of this._prompts) {
|
|
1820
|
+
if (limit && results.length >= limit) break;
|
|
1821
|
+
if (matchAll || pattern.test(prompt.name) || prompt.description && pattern.test(prompt.description)) results.push(this.promptToEntry(prompt));
|
|
1822
|
+
}
|
|
1823
|
+
for (const resource of this._resources) {
|
|
1824
|
+
if (limit && results.length >= limit) break;
|
|
1825
|
+
if (matchAll || pattern.test(resource.name) || resource.description && pattern.test(resource.description)) {
|
|
1826
|
+
const path = this.resourceUriToPath(resource.uri);
|
|
1827
|
+
results.push(this.resourceToEntry(resource, `/resources${path}`));
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
return { data: results };
|
|
1831
|
+
}
|
|
1832
|
+
/**
|
|
901
1833
|
* Execute a tool
|
|
902
1834
|
*/
|
|
903
1835
|
async execToolHandler(ctx, args) {
|
|
@@ -913,7 +1845,27 @@ var AFSMCP = class AFSMCP extends _aigne_afs_provider.AFSBaseProvider {
|
|
|
913
1845
|
};
|
|
914
1846
|
}
|
|
915
1847
|
};
|
|
916
|
-
require_decorate.__decorate([(0, _aigne_afs_provider.
|
|
1848
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.List)("/")], AFSMCP.prototype, "listRootHandler", null);
|
|
1849
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/")], AFSMCP.prototype, "readRootHandler", null);
|
|
1850
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/")], AFSMCP.prototype, "readRootMeta", null);
|
|
1851
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/.meta/.capabilities")], AFSMCP.prototype, "readCapabilities", null);
|
|
1852
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/")], AFSMCP.prototype, "statRootHandler", null);
|
|
1853
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/WORLD.md")], AFSMCP.prototype, "readWorldMdHandler", null);
|
|
1854
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.List)("/WORLD.md")], AFSMCP.prototype, "listWorldMdHandler", null);
|
|
1855
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/WORLD.md")], AFSMCP.prototype, "readWorldMdMeta", null);
|
|
1856
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/tools")], AFSMCP.prototype, "readToolsDir", null);
|
|
1857
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/tools")], AFSMCP.prototype, "readToolsMeta", null);
|
|
1858
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/prompts")], AFSMCP.prototype, "readPromptsDir", null);
|
|
1859
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/prompts")], AFSMCP.prototype, "readPromptsMeta", null);
|
|
1860
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/resources")], AFSMCP.prototype, "readResourcesDir", null);
|
|
1861
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/resources")], AFSMCP.prototype, "readResourcesMeta", null);
|
|
1862
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/WORLD.md")], AFSMCP.prototype, "statWorldMdHandler", null);
|
|
1863
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/tools")], AFSMCP.prototype, "statToolsHandler", null);
|
|
1864
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/prompts")], AFSMCP.prototype, "statPromptsHandler", null);
|
|
1865
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/resources")], AFSMCP.prototype, "statResourcesHandler", null);
|
|
1866
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/tools/:name")], AFSMCP.prototype, "statToolHandler", null);
|
|
1867
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/prompts/:name")], AFSMCP.prototype, "statPromptHandler", null);
|
|
1868
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/resources/:path+")], AFSMCP.prototype, "statResourceHandler", null);
|
|
917
1869
|
require_decorate.__decorate([(0, _aigne_afs_provider.List)("/tools")], AFSMCP.prototype, "listToolsHandler", null);
|
|
918
1870
|
require_decorate.__decorate([(0, _aigne_afs_provider.List)("/prompts")], AFSMCP.prototype, "listPromptsHandler", null);
|
|
919
1871
|
require_decorate.__decorate([(0, _aigne_afs_provider.List)("/tools/:name")], AFSMCP.prototype, "listToolHandler", null);
|
|
@@ -925,8 +1877,19 @@ require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/prompts/:name")], A
|
|
|
925
1877
|
require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/resources/:path+")], AFSMCP.prototype, "readResourceMeta", null);
|
|
926
1878
|
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/tools/:name")], AFSMCP.prototype, "readToolHandler", null);
|
|
927
1879
|
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/prompts/:name")], AFSMCP.prototype, "readPromptHandler", null);
|
|
1880
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Actions)("/prompts/:name")], AFSMCP.prototype, "listPromptActions", null);
|
|
1881
|
+
require_decorate.__decorate([_aigne_afs_provider.Actions.Exec("/prompts/:name", "get")], AFSMCP.prototype, "execPromptGetHandler", null);
|
|
1882
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Actions)("/resources/:path+")], AFSMCP.prototype, "listResourceActions", null);
|
|
1883
|
+
require_decorate.__decorate([_aigne_afs_provider.Actions.Exec("/resources/:path+", "get")], AFSMCP.prototype, "execResourceGetHandler", null);
|
|
928
1884
|
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/resources/:path+")], AFSMCP.prototype, "readResourceHandler", null);
|
|
1885
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Explain)("/")], AFSMCP.prototype, "explainRoot", null);
|
|
1886
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Explain)("/tools/:name")], AFSMCP.prototype, "explainTool", null);
|
|
1887
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Explain)("/prompts/:name")], AFSMCP.prototype, "explainPrompt", null);
|
|
1888
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Explain)("/resources/:path+")], AFSMCP.prototype, "explainResource", null);
|
|
1889
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Search)("/:path*")], AFSMCP.prototype, "searchHandler", null);
|
|
929
1890
|
require_decorate.__decorate([(0, _aigne_afs_provider.Exec)("/tools/:name")], AFSMCP.prototype, "execToolHandler", null);
|
|
1891
|
+
var src_default = AFSMCP;
|
|
930
1892
|
|
|
931
1893
|
//#endregion
|
|
932
|
-
exports.AFSMCP = AFSMCP;
|
|
1894
|
+
exports.AFSMCP = AFSMCP;
|
|
1895
|
+
exports.default = src_default;
|