@devframes/agentic 1.3.0 → 1.3.2

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.
@@ -1,5 +1,4 @@
1
1
  import { DevframeInstanceRecord } from "devframe/internal";
2
- //#region src/connect/index.d.ts
3
2
  export interface ConnectServerOptions {
4
3
  /**
5
4
  * Explicit ports to probe besides the registry, for instances started
@@ -71,5 +70,4 @@ export declare function startConnectServer(options?: ConnectServerOptions): Prom
71
70
  * advertised MCP path is relative to that base, as in the registry records
72
71
  * the instance shell writes. Exported for focused tests.
73
72
  */
74
- export declare function probePort(port: number, base?: string, timeoutMs?: number): Promise<DevframeInstanceRecord | null>;
75
- //#endregion
73
+ export declare function probePort(port: number, base?: string, timeoutMs?: number): Promise<DevframeInstanceRecord | null>;
@@ -5,7 +5,7 @@ import { Client, StreamableHTTPClientTransport } from "@modelcontextprotocol/cli
5
5
  import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
6
6
  import { Diagnostic } from "devframe/utils/nostics";
7
7
  import { joinURL, withLeadingSlash, withTrailingSlash } from "devframe/utils/url";
8
- //#region src/connect/index.ts
8
+ // src/connect/index.ts
9
9
  /**
10
10
  * Resolve the per-record bearer from the {@link ConnectServerOptions.authToken}
11
11
  * option. Exported for focused tests of the credential resolution.
@@ -249,5 +249,4 @@ function errorResult(error) {
249
249
  }]
250
250
  };
251
251
  }
252
- //#endregion
253
252
  export { buildInstanceRequestHeaders, probePort, resolveAuthToken, startConnectServer };
package/dist/index.mjs CHANGED
@@ -1,4 +1,3 @@
1
- //#region src/index.ts
1
+ // src/index.ts
2
2
  throw new Error("[@devframes/agentic] is not imported directly; installing it enables devframe's agent surfaces.\n • import from \"devframe/adapters/mcp\" to serve a devframe over MCP\n • run \"devframe connect\" for the stdio discovery gateway\n");
3
- //#endregion
4
3
  export {};
@@ -2,14 +2,11 @@ import { Server } from "@modelcontextprotocol/server";
2
2
  import { MountMcpHttpOptions, MountMcpHttpOptions as MountMcpHttpOptions$1, MountedMcpHttp, MountedMcpHttp as MountedMcpHttp$1 } from "devframe/internal";
3
3
  import { H3 } from "h3";
4
4
  import { CreateMcpFetchHandlerOptions, CreateMcpFetchHandlerOptions as CreateMcpFetchHandlerOptions$1, CreateMcpServerOptions, CreateMcpServerOptions as CreateMcpServerOptions$1, DevframeDefinition, DevframeNodeContext, McpConnectionInfo, McpFetchHandler, McpFetchHandler as McpFetchHandler$1, McpServerHandle, McpServerHandle as McpServerHandle$1 } from "devframe/types";
5
- //#region src/mcp/build-server.d.ts
6
5
  /**
7
6
  * Build an MCP server over the agent surface of a devframe definition.
8
7
  * Currently supports `stdio` transport only.
9
8
  */
10
9
  export declare function createMcpServer(definition: DevframeDefinition, options?: CreateMcpServerOptions$1): Promise<McpServerHandle$1>;
11
- //#endregion
12
- //#region src/mcp/fetch.d.ts
13
10
  /**
14
11
  * Build a framework-agnostic MCP endpoint over a devframe context: a
15
12
  * web-standard `Request → Response` handler any host can mount: h3 (see
@@ -41,8 +38,6 @@ export declare function createMcpServer(definition: DevframeDefinition, options?
41
38
  * callers.
42
39
  */
43
40
  export declare function createMcpFetchHandler(ctx: DevframeNodeContext, options: CreateMcpFetchHandlerOptions$1): McpFetchHandler$1;
44
- //#endregion
45
- //#region src/mcp/http.d.ts
46
41
  /**
47
42
  * Mount a stateless MCP endpoint on an h3 app at `path`: the h3 binding over
48
43
  * {@link createMcpFetchHandler}, which owns the per-request serving, the
@@ -57,5 +52,4 @@ export declare function createMcpFetchHandler(ctx: DevframeNodeContext, options:
57
52
  * request to the SPA static catch-all).
58
53
  */
59
54
  export declare function mountMcpHttp(app: H3, ctx: DevframeNodeContext, path: string, options: MountMcpHttpOptions$1): MountedMcpHttp$1;
60
- //#endregion
61
55
  export type { CreateMcpFetchHandlerOptions, CreateMcpServerOptions, McpConnectionInfo, McpFetchHandler, McpServerHandle, MountMcpHttpOptions, MountedMcpHttp };
@@ -1,6 +1,6 @@
1
1
  import { homedir } from "node:os";
2
2
  import process from "node:process";
3
- import { Server, createMcpHandler } from "@modelcontextprotocol/server";
3
+ import { ProtocolError, ProtocolErrorCode, Server, createMcpHandler } from "@modelcontextprotocol/server";
4
4
  import { DEVFRAME_EVENTS } from "devframe/constants";
5
5
  import { argsToJsonSchema, diagnostics, formatMcpError, getMcpContent, returnToJsonSchema, stringifyForMcp } from "devframe/internal";
6
6
  import { createHostContext } from "devframe/node";
@@ -9,7 +9,7 @@ import { join } from "pathe";
9
9
  import { timingSafeEqual } from "devframe/utils/crypto-token";
10
10
  import { isAllowedOrigin, isLoopbackAddress } from "devframe/utils/origin";
11
11
  import { defineHandler, getRequestIP } from "h3";
12
- //#region src/mcp/build-server.ts
12
+ // src/mcp/build-server.ts
13
13
  /**
14
14
  * Build a fresh MCP {@link Server} over a devframe context, registering its
15
15
  * tool and resource handlers. This is a pure factory: it sets up no
@@ -29,7 +29,8 @@ function buildMcpServerFromContext(ctx, options) {
29
29
  }, {
30
30
  capabilities: {
31
31
  tools: { listChanged: true },
32
- resources: { listChanged: true }
32
+ resources: { listChanged: true },
33
+ ...options.prompts?.size ? { prompts: { listChanged: false } } : {}
33
34
  },
34
35
  ...options.instructions ? { instructions: options.instructions } : {}
35
36
  });
@@ -43,6 +44,7 @@ function buildMcpServerFromContext(ctx, options) {
43
44
  description,
44
45
  mimeType
45
46
  })) }));
47
+ if (options.prompts?.size) registerPromptHandlers(server, options.prompts);
46
48
  return server;
47
49
  }
48
50
  /**
@@ -89,6 +91,7 @@ async function createMcpServer(definition, options = {}) {
89
91
  reason: "Only stdio transport is supported in this release."
90
92
  });
91
93
  const resourceTemplates = compileResourceTemplates(options.resourceTemplates);
94
+ const prompts = compilePrompts(options.prompts);
92
95
  const ctx = await createHostContext({
93
96
  cwd: process.cwd(),
94
97
  mode: "dev",
@@ -111,7 +114,8 @@ async function createMcpServer(definition, options = {}) {
111
114
  serverVersion: options.serverVersion ?? definition.version ?? "0.0.0",
112
115
  exposeSharedState: options.exposeSharedState ?? true,
113
116
  instructions: options.instructions,
114
- resourceTemplates
117
+ resourceTemplates,
118
+ prompts
115
119
  };
116
120
  let handle;
117
121
  try {
@@ -313,6 +317,49 @@ function registerResourceHandlers(server, ctx, exposeSharedState, templates) {
313
317
  throw new Error(`[devframe/mcp] unknown resource URI "${uri}"`);
314
318
  });
315
319
  }
320
+ /**
321
+ * Index prompts by name, once per endpoint. A repeated name throws
322
+ * `DF0085`, since `prompts/get` finds a prompt by its name.
323
+ *
324
+ * @internal
325
+ */
326
+ function compilePrompts(prompts = []) {
327
+ const byName = /* @__PURE__ */ new Map();
328
+ for (const prompt of prompts) {
329
+ if (byName.has(prompt.name)) throw diagnostics.DF0085({ name: prompt.name });
330
+ byName.set(prompt.name, prompt);
331
+ }
332
+ return byName;
333
+ }
334
+ /**
335
+ * Serve `prompts/list` and `prompts/get`. An unknown name, or a required
336
+ * argument that is missing or empty, is an invalid-params error. An error
337
+ * thrown by `get` goes to the MCP client.
338
+ */
339
+ function registerPromptHandlers(server, prompts) {
340
+ server.setRequestHandler("prompts/list", async () => ({ prompts: [...prompts.values()].map(({ name, title, description, arguments: args }) => ({
341
+ name,
342
+ title,
343
+ description,
344
+ ...args?.length ? { arguments: args.map((argument) => ({
345
+ name: argument.name,
346
+ description: argument.description,
347
+ required: argument.required
348
+ })) } : {}
349
+ })) }));
350
+ server.setRequestHandler("prompts/get", async (request) => {
351
+ const { name, arguments: given = {} } = request.params;
352
+ const prompt = prompts.get(name);
353
+ if (!prompt) throw new ProtocolError(ProtocolErrorCode.InvalidParams, `[devframe/mcp] unknown prompt "${name}"`);
354
+ const missing = (prompt.arguments ?? []).filter((argument) => argument.required && !(Object.hasOwn(given, argument.name) && given[argument.name])).map((argument) => argument.name);
355
+ if (missing.length) throw new ProtocolError(ProtocolErrorCode.InvalidParams, `[devframe/mcp] prompt "${name}" needs the argument(s): ${missing.join(", ")}`);
356
+ const { description, messages } = await prompt.get(given);
357
+ return {
358
+ description,
359
+ messages
360
+ };
361
+ });
362
+ }
316
363
  /** One `{name}` expression of a URI template. */
317
364
  const TEMPLATE_EXPRESSION_RE = /\{([^{}]*)\}/;
318
365
  /** RFC 6570 `varname`: letters, digits and `_`, with single dots between them. */
@@ -482,8 +529,7 @@ function parseResourceUri(uri) {
482
529
  key: decoded
483
530
  };
484
531
  }
485
- //#endregion
486
- //#region src/mcp/fetch.ts
532
+ // src/mcp/fetch.ts
487
533
  /**
488
534
  * Parse exactly one `Authorization: Bearer <token>` credential, returning the
489
535
  * token or `undefined` for a missing, malformed, empty, or multi-credential
@@ -542,12 +588,14 @@ function createMcpFetchHandler(ctx, options) {
542
588
  const allowedOrigins = options.allowedOrigins;
543
589
  const authorization = options.authorization ?? false;
544
590
  const resourceTemplates = compileResourceTemplates(options.resourceTemplates);
591
+ const prompts = compilePrompts(options.prompts);
545
592
  const handler = createMcpHandler(() => buildMcpServerFromContext(ctx, {
546
593
  serverName: options.serverName,
547
594
  serverVersion: options.serverVersion,
548
595
  exposeSharedState: options.exposeSharedState,
549
596
  instructions: options.instructions,
550
- resourceTemplates
597
+ resourceTemplates,
598
+ prompts
551
599
  }));
552
600
  const unbridge = bridgeListChanged(ctx, {
553
601
  tools: () => {
@@ -576,8 +624,7 @@ function createMcpFetchHandler(ctx, options) {
576
624
  }
577
625
  };
578
626
  }
579
- //#endregion
580
- //#region src/mcp/http.ts
627
+ // src/mcp/http.ts
581
628
  /**
582
629
  * Mount a stateless MCP endpoint on an h3 app at `path`: the h3 binding over
583
630
  * {@link createMcpFetchHandler}, which owns the per-request serving, the
@@ -609,5 +656,4 @@ function respond(event, response) {
609
656
  });
610
657
  return response.body ?? "";
611
658
  }
612
- //#endregion
613
659
  export { createMcpFetchHandler, createMcpServer, mountMcpHttp };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@devframes/agentic",
3
3
  "type": "module",
4
- "version": "1.3.0",
4
+ "version": "1.3.2",
5
5
  "description": "Agent-surface implementation for devframe: installing it next to devframe enables the MCP adapter (devframe/adapters/mcp) and the devframe connect gateway.",
6
6
  "author": "Anthony Fu <anthonyfu117@hotmail.com>",
7
7
  "license": "MIT",
@@ -30,19 +30,19 @@
30
30
  "dist"
31
31
  ],
32
32
  "peerDependencies": {
33
- "devframe": "1.3.0"
33
+ "devframe": "1.3.2"
34
34
  },
35
35
  "dependencies": {
36
- "@modelcontextprotocol/client": "^2.3.1",
37
- "@modelcontextprotocol/server": "^2.3.1",
38
- "h3": "^2.0.7",
36
+ "@modelcontextprotocol/client": "^2.4.0",
37
+ "@modelcontextprotocol/server": "^2.4.0",
38
+ "h3": "^2.0.8",
39
39
  "pathe": "^2.0.3"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@standard-schema/spec": "^1.1.0",
43
- "@types/node": "^26.6.5",
44
- "devframe": "1.3.0",
45
- "tsdown": "0.23.0",
43
+ "@types/node": "^26.6.6",
44
+ "devframe": "1.3.2",
45
+ "tsdown": "^0.23.4",
46
46
  "valibot": "^1.5.0"
47
47
  },
48
48
  "scripts": {