devframe 0.9.8 → 0.9.9

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.
Files changed (116) hide show
  1. package/dist/{_shared-BM3PdYli.mjs → _shared-C08SdQRl.mjs} +15 -4
  2. package/dist/{_shared-mtXpcJIv.d.mts → _shared-CK3czkH4.d.mts} +25 -2
  3. package/dist/adapters/build.d.mts +6 -6
  4. package/dist/adapters/build.mjs +32 -22
  5. package/dist/adapters/cac.d.mts +16 -1
  6. package/dist/adapters/cac.mjs +8 -7
  7. package/dist/adapters/dev.d.mts +13 -13
  8. package/dist/adapters/dev.mjs +2 -2
  9. package/dist/adapters/embedded.d.mts +1 -1
  10. package/dist/adapters/initiate.d.mts +28 -26
  11. package/dist/adapters/initiate.mjs +1 -1
  12. package/dist/adapters/mcp.d.mts +28 -14
  13. package/dist/adapters/mcp.mjs +75 -39
  14. package/dist/{agent-tool-name-EgfoFO8C.mjs → agent-tool-name-DGzeuWcO.mjs} +2 -2
  15. package/dist/cli/main.d.mts +1 -1
  16. package/dist/cli/main.mjs +41 -17
  17. package/dist/client/index.d.mts +36 -36
  18. package/dist/client/index.mjs +83 -51
  19. package/dist/{client-assets-C7SXgTWY.mjs → client-assets-DNdhagGm.mjs} +2 -2
  20. package/dist/constants.d.mts +8 -7
  21. package/dist/constants.mjs +7 -6
  22. package/dist/{context-CLF4-8Pp.d.mts → context-4AIVRLYF.d.mts} +158 -122
  23. package/dist/{context-omlma_1n.mjs → context-CwPUinjn.mjs} +126 -88
  24. package/dist/{context-KUqAfawQ.mjs → context-DIUvJW4D.mjs} +3 -3
  25. package/dist/{context-DftYyXaR.d.mts → context-rgBSPFHS.d.mts} +5 -5
  26. package/dist/{crypto-token-XCqTSMg9.mjs → crypto-token-TVbGGFuj.mjs} +1 -1
  27. package/dist/{dev-CzkPCJwi.mjs → dev-Eqq5PX0k.mjs} +37 -18
  28. package/dist/{diagnostics-BXWW3VK-.mjs → diagnostics-BMfN8mb1.mjs} +30 -17
  29. package/dist/{diagnostics-CD8nlgll.mjs → diagnostics-D0EVm5M6.mjs} +2 -2
  30. package/dist/{events-4daw0uK9.mjs → events-BV4Dj59a.mjs} +2 -2
  31. package/dist/{host-h3-fRbF9yor.mjs → host-h3-BJ4siyz7.mjs} +1 -1
  32. package/dist/in-page-channel/index.d.mts +14 -14
  33. package/dist/in-page-channel/index.mjs +63 -54
  34. package/dist/{index-BzyopqxV.d.mts → index-pIVt92jP.d.mts} +9 -9
  35. package/dist/{index-D3k0BIhe.d.mts → index-pKl67H6w.d.mts} +4 -4
  36. package/dist/index.d.mts +8 -8
  37. package/dist/index.mjs +2 -2
  38. package/dist/{instance-registry-BjlMQbFB.mjs → instance-registry-C7-41RSp.mjs} +8 -8
  39. package/dist/{instance-shell-Tcp5hGoq.d.mts → instance-shell-7Z52PE4_.d.mts} +18 -18
  40. package/dist/{instance-shell-CpVW4zG0.mjs → instance-shell-cdVETpfz.mjs} +227 -58
  41. package/dist/internal/index.d.mts +40 -23
  42. package/dist/internal/index.mjs +10 -10
  43. package/dist/node/auth.d.mts +2 -2
  44. package/dist/node/auth.mjs +2 -2
  45. package/dist/node/hub-internals.d.mts +2 -2
  46. package/dist/node/hub-internals.mjs +2 -2
  47. package/dist/node/index.d.mts +5 -5
  48. package/dist/node/index.mjs +2 -2
  49. package/dist/{nostics-SPGDgHEP.d.mts → nostics-0sKe5HIj.d.mts} +2 -2
  50. package/dist/{nostics-CzECRXpE.mjs → nostics-D0PvLZsn.mjs} +1 -1
  51. package/dist/origin-DGDH8BI9.d.mts +45 -0
  52. package/dist/origin-DZit9g29.mjs +80 -0
  53. package/dist/recipes/common-rpc-functions.d.mts +5 -5
  54. package/dist/recipes/common-rpc-functions.mjs +3 -3
  55. package/dist/recipes/interactive-auth.d.mts +6 -6
  56. package/dist/recipes/interactive-auth.mjs +6 -6
  57. package/dist/{remote-assets-DezQmPQU.mjs → remote-assets-BIFWOlBW.mjs} +26 -6
  58. package/dist/{remote-assets-B13_vRkJ.d.mts → remote-assets-eBvSKZMS.d.mts} +7 -7
  59. package/dist/{revoke-COLW0cOi.mjs → revoke-cqztiCX4.mjs} +1 -1
  60. package/dist/rpc/dump.d.mts +2 -11
  61. package/dist/rpc/dump.mjs +1 -1
  62. package/dist/rpc/index.d.mts +2 -2
  63. package/dist/rpc/index.mjs +3 -3
  64. package/dist/rpc/transports/sse-client.d.mts +1 -1
  65. package/dist/rpc/transports/sse-client.mjs +30 -14
  66. package/dist/rpc/transports/sse-server.d.mts +4 -4
  67. package/dist/rpc/transports/sse-server.mjs +7 -7
  68. package/dist/rpc/transports/ws-bun.d.mts +5 -5
  69. package/dist/rpc/transports/ws-bun.mjs +8 -2
  70. package/dist/rpc/transports/ws-client.d.mts +1 -1
  71. package/dist/rpc/transports/ws-client.mjs +2 -2
  72. package/dist/rpc/transports/ws-deno.d.mts +4 -4
  73. package/dist/rpc/transports/ws-deno.mjs +8 -2
  74. package/dist/rpc/transports/ws-server.d.mts +2 -1
  75. package/dist/rpc/transports/ws-server.mjs +232 -1
  76. package/dist/{rpc-core-B3W3z9ff.d.mts → rpc-core-Ceu6AUz8.d.mts} +4 -4
  77. package/dist/{rpc-core-DlHd276T.mjs → rpc-core-DVQ7xi89.mjs} +14 -2
  78. package/dist/{serialization-BGzEwAdr.mjs → serialization-DTZnPQ1-.mjs} +20 -18
  79. package/dist/{services-install-CqqQVls5.mjs → services-install-P_DV7VYL.mjs} +32 -21
  80. package/dist/session-DPfj6zQG.mjs +16 -0
  81. package/dist/{shared-state--sduc6Xi.mjs → shared-state-CaxB1q0h.mjs} +2 -2
  82. package/dist/{simple-schema-DQPZrAaZ.mjs → simple-schema-Bi40l-P6.mjs} +2 -2
  83. package/dist/{sse-client-DwX021ST.d.mts → sse-client-BQ4jS3eO.d.mts} +4 -4
  84. package/dist/{state-CK9LjrnT.mjs → state-CeQQWzM-.mjs} +4 -4
  85. package/dist/{static-DV_qUSRS.mjs → static-DZ8P2Kn7.mjs} +130 -135
  86. package/dist/{storage-BXNVhKyR.mjs → storage-Dccf_IyD.mjs} +1 -1
  87. package/dist/types/index.d.mts +6 -6
  88. package/dist/{types-CMdPYhOx.d.mts → types-Dq4i156u.d.mts} +17 -17
  89. package/dist/utils/agent-tool-name.d.mts +2 -2
  90. package/dist/utils/agent-tool-name.mjs +2 -2
  91. package/dist/utils/colors.d.mts +1 -1
  92. package/dist/utils/crypto-token.d.mts +1 -1
  93. package/dist/utils/crypto-token.mjs +1 -1
  94. package/dist/utils/events.d.mts +1 -1
  95. package/dist/utils/nostics.d.mts +1 -1
  96. package/dist/utils/nostics.mjs +1 -1
  97. package/dist/utils/open.mjs +1 -1
  98. package/dist/utils/origin.d.mts +2 -0
  99. package/dist/utils/origin.mjs +80 -0
  100. package/dist/utils/remote-assets.d.mts +2 -2
  101. package/dist/utils/remote-assets.mjs +1 -1
  102. package/dist/utils/serve-static.d.mts +4 -4
  103. package/dist/utils/serve-static.mjs +56 -19
  104. package/dist/utils/shared-state.d.mts +1 -1
  105. package/dist/utils/shared-state.mjs +1 -1
  106. package/dist/utils/simple-schema.d.mts +5 -5
  107. package/dist/utils/simple-schema.mjs +2 -2
  108. package/dist/utils/streaming-channel.d.mts +1 -1
  109. package/dist/utils/streaming-channel.mjs +2 -2
  110. package/dist/utils/when.d.mts +5 -5
  111. package/dist/{validation-YrZH6atx.mjs → validation-BOy8IoFZ.mjs} +2 -2
  112. package/dist/{wire-codec-0K-o5MYW.mjs → wire-codec-dcCeXcSo.mjs} +3 -3
  113. package/dist/{ws-client-7_lZi-B9.d.mts → ws-client-Xpxt0oPA.d.mts} +3 -3
  114. package/dist/{ws-server-VyHlanzy.d.mts → ws-server-D2nv68Hg.d.mts} +13 -37
  115. package/package.json +2 -1
  116. package/dist/ws-server-Y_AumUQH.mjs +0 -294
@@ -36,12 +36,23 @@ async function resolveDevServerPort(def, options = {}) {
36
36
  return getPort(portOptions);
37
37
  }
38
38
  /**
39
- * Normalize the `cli.mcp` / `mcp` option (`boolean | McpRouteOptions`) into
40
- * concrete options, or `undefined` when the MCP route is disabled.
39
+ * Normalize the `mcp` option (`boolean | McpRouteOptions`) into a
40
+ * fully-resolved config, or `undefined` when the MCP route is disabled.
41
+ *
42
+ * An enabled route trusts same-machine callers by default: the authorization
43
+ * resolves to origin-only (`false`) unless the object config opts into a
44
+ * bearer/callback identity check. An empty-string bearer is treated as no
45
+ * bearer (origin-only) rather than a usable credential.
41
46
  */
42
47
  function resolveMcpConfig(mcp) {
43
48
  if (!mcp) return void 0;
44
- return mcp === true ? {} : mcp;
49
+ if (mcp === true) return { authorization: false };
50
+ const authorization = typeof mcp.authorization === "string" && mcp.authorization.length === 0 ? false : mcp.authorization ?? false;
51
+ return {
52
+ ...mcp.path !== void 0 ? { path: mcp.path } : {},
53
+ ...mcp.allowedOrigins !== void 0 ? { allowedOrigins: mcp.allowedOrigins } : {},
54
+ authorization
55
+ };
45
56
  }
46
57
  /**
47
58
  * Resolve the `mcp` entry a `__connection.json` should advertise for a dev
@@ -65,4 +76,4 @@ function resolveMcpConnectionMeta(def, mcp, port) {
65
76
  } : { path: route };
66
77
  }
67
78
  //#endregion
68
- export { resolveMcpConnectionMeta as i, resolveBasePath as n, resolveDevServerPort as r, normalizeBasePath as t };
79
+ export { resolveMcpConnectionMeta as a, resolveMcpConfig as i, resolveBasePath as n, resolveDevServerPort as r, normalizeBasePath as t };
@@ -1,4 +1,4 @@
1
- import { F as DevframeDefinition, G as McpRouteOptions, I as DevframeDeploymentKind, t as ConnectionMeta } from "./context-CLF4-8Pp.mjs";
1
+ import { F as DevframeDefinition, G as McpAuthorization, I as DevframeDeploymentKind, K as McpRouteOptions, t as ConnectionMeta } from "./context-4AIVRLYF.mjs";
2
2
  //#region src/adapters/_shared.d.ts
3
3
  /**
4
4
  * Resolve the mount base path for a devframe's SPA. Hosted adapters
@@ -24,6 +24,29 @@ interface ResolveDevServerPortOptions {
24
24
  * before starting the server.
25
25
  */
26
26
  declare function resolveDevServerPort(def: DevframeDefinition, options?: ResolveDevServerPortOptions): Promise<number>;
27
+ /**
28
+ * A fully-resolved MCP route configuration: the concrete authorization policy
29
+ * (never the `mcp: true` shorthand), plus the optional route path and origin
30
+ * allow-list. Every route mount consumes this shape.
31
+ */
32
+ interface ResolvedMcpConfig {
33
+ /** Route segment, relative to the base. Default resolved by the caller. */
34
+ path?: string;
35
+ /** Origin allow-list, or `false` to disable the origin gate. */
36
+ allowedOrigins?: readonly string[] | false;
37
+ /** The resolved identity policy: a bearer token, callback, or `false`. */
38
+ authorization: McpAuthorization;
39
+ }
40
+ /**
41
+ * Normalize the `mcp` option (`boolean | McpRouteOptions`) into a
42
+ * fully-resolved config, or `undefined` when the MCP route is disabled.
43
+ *
44
+ * An enabled route trusts same-machine callers by default: the authorization
45
+ * resolves to origin-only (`false`) unless the object config opts into a
46
+ * bearer/callback identity check. An empty-string bearer is treated as no
47
+ * bearer (origin-only) rather than a usable credential.
48
+ */
49
+ declare function resolveMcpConfig(mcp: boolean | McpRouteOptions | undefined): ResolvedMcpConfig | undefined;
27
50
  /**
28
51
  * Resolve the `mcp` entry a `__connection.json` should advertise for a dev
29
52
  * server started with the given `mcp` option (falling back to `def.cli?.mcp`,
@@ -38,4 +61,4 @@ declare function resolveDevServerPort(def: DevframeDefinition, options?: Resolve
38
61
  */
39
62
  declare function resolveMcpConnectionMeta(def: DevframeDefinition, mcp: boolean | McpRouteOptions | undefined, port?: number): ConnectionMeta['mcp'];
40
63
  //#endregion
41
- export { resolveMcpConnectionMeta as a, resolveDevServerPort as i, normalizeBasePath as n, resolveBasePath as r, ResolveDevServerPortOptions as t };
64
+ export { resolveDevServerPort as a, resolveBasePath as i, ResolvedMcpConfig as n, resolveMcpConfig as o, normalizeBasePath as r, resolveMcpConnectionMeta as s, ResolveDevServerPortOptions as t };
@@ -1,14 +1,14 @@
1
- import { F as DevframeDefinition, V as DevframeSnapshotRpcEntry, o as DevframeNodeContext } from "../context-CLF4-8Pp.mjs";
2
- import { o as StaticAssetsSource } from "../remote-assets-B13_vRkJ.mjs";
1
+ import { F as DevframeDefinition, V as DevframeSnapshotRpcEntry, o as DevframeNodeContext } from "../context-4AIVRLYF.mjs";
2
+ import { o as StaticAssetsSource } from "../remote-assets-eBvSKZMS.mjs";
3
3
  //#region src/adapters/build.d.ts
4
4
  interface CreateBuildOptions {
5
5
  /** Output directory. Defaults to `dist-static`. */
6
6
  outDir?: string;
7
7
  /**
8
- * Override the SPA dist to copy into `outDir` — a local directory or a
8
+ * Override the SPA dist to copy into `outDir`: a local directory or a
9
9
  * remote-assets declaration (materialized in full at build time). When
10
10
  * omitted the adapter reads `devframe.clientAssets` (or the deprecated
11
- * `devframe.cli?.distDir`) — authors typically set this once on the
11
+ * `devframe.cli?.distDir`); authors typically set this once on the
12
12
  * definition itself.
13
13
  */
14
14
  distDir?: StaticAssetsSource;
@@ -21,7 +21,7 @@ interface CreateBuildOptions {
21
21
  /**
22
22
  * Proceed even when the definition declares `capabilities.build: false`.
23
23
  * `createCac` already skips registering the `build` subcommand for such
24
- * a definition — this only matters for a caller invoking `createBuild`
24
+ * a definition; this only matters for a caller invoking `createBuild`
25
25
  * directly, bypassing the CLI.
26
26
  */
27
27
  force?: boolean;
@@ -34,7 +34,7 @@ interface CreateBuildOptions {
34
34
  * - Write `<outDir>/__connection.json` (`{ backend: 'static' }`) and the
35
35
  * sharded RPC dump under `<outDir>/__rpc-dump/` so the deployed SPA
36
36
  * discovers both via relative paths from `document.baseURI`. The
37
- * output is mount-path agnostic — the same bundle works at `/`,
37
+ * output is mount-path agnostic, so the same bundle works at `/`,
38
38
  * `/devframe/`, or any base, no rewriting required.
39
39
  */
40
40
  declare function createBuild(d: DevframeDefinition, options?: CreateBuildOptions): Promise<void>;
@@ -1,13 +1,13 @@
1
- import { s as colors } from "../nostics-CzECRXpE.mjs";
2
- import { n as strictJsonStringify } from "../serialization-BGzEwAdr.mjs";
3
- import { t as resolveClientAssets } from "../client-assets-C7SXgTWY.mjs";
1
+ import { s as colors } from "../nostics-D0PvLZsn.mjs";
2
+ import { n as strictJsonStringify } from "../serialization-DTZnPQ1-.mjs";
3
+ import { t as resolveClientAssets } from "../client-assets-DNdhagGm.mjs";
4
4
  import { DEVFRAME_CONNECTION_META_FILENAME, DEVFRAME_RPC_DUMP_DIRNAME, DEVFRAME_RPC_DUMP_MANIFEST_FILENAME } from "../constants.mjs";
5
- import { t as collectStaticRpcDump } from "../static-DV_qUSRS.mjs";
5
+ import { t as collectStaticRpcDump } from "../static-DZ8P2Kn7.mjs";
6
6
  import { n as structuredCloneStringify } from "../structured-clone-CbAV5rFI.mjs";
7
- import { t as diagnostics } from "../diagnostics-BXWW3VK-.mjs";
8
- import { t as createHostContext } from "../context-omlma_1n.mjs";
9
- import { t as resolveStaticAssetsSource } from "../remote-assets-DezQmPQU.mjs";
10
- import { t as createH3DevframeHost } from "../host-h3-fRbF9yor.mjs";
7
+ import { t as diagnostics } from "../diagnostics-BMfN8mb1.mjs";
8
+ import { t as createHostContext } from "../context-CwPUinjn.mjs";
9
+ import { t as resolveStaticAssetsSource } from "../remote-assets-BIFWOlBW.mjs";
10
+ import { t as createH3DevframeHost } from "../host-h3-BJ4siyz7.mjs";
11
11
  import process from "node:process";
12
12
  import { dirname, resolve } from "pathe";
13
13
  import { existsSync } from "node:fs";
@@ -21,7 +21,7 @@ import fs$1 from "node:fs/promises";
21
21
  * - Write `<outDir>/__connection.json` (`{ backend: 'static' }`) and the
22
22
  * sharded RPC dump under `<outDir>/__rpc-dump/` so the deployed SPA
23
23
  * discovers both via relative paths from `document.baseURI`. The
24
- * output is mount-path agnostic — the same bundle works at `/`,
24
+ * output is mount-path agnostic, so the same bundle works at `/`,
25
25
  * `/devframe/`, or any base, no rewriting required.
26
26
  */
27
27
  async function createBuild(d, options = {}) {
@@ -35,14 +35,7 @@ async function createBuild(d, options = {}) {
35
35
  origin: "http://localhost",
36
36
  appName: d.id
37
37
  });
38
- const resolved = resolveStaticAssetsSource(distSource, host.getStorageDir("project"), d.importMetaUrl);
39
- if (typeof resolved === "string") {
40
- console.log(colors.cyan`[devframe] copying SPA from ${resolved} -> ${outDir}`);
41
- await fs$1.cp(resolved, outDir, { recursive: true });
42
- } else {
43
- console.log(colors.cyan`[devframe] materializing SPA from ${resolved.assets.package}@${resolved.assets.version} -> ${outDir}`);
44
- await resolved.materialize(outDir);
45
- }
38
+ await materializeSpa(resolveStaticAssetsSource(distSource, host.getStorageDir("project"), d.importMetaUrl), outDir);
46
39
  const ctx = await createHostContext({
47
40
  cwd: process.cwd(),
48
41
  mode: "build",
@@ -54,23 +47,40 @@ async function createBuild(d, options = {}) {
54
47
  await d.setup(ctx);
55
48
  applySnapshotRpc(ctx, d.rpc?.snapshot);
56
49
  await fs$1.mkdir(resolve(outDir, DEVFRAME_RPC_DUMP_DIRNAME), { recursive: true });
50
+ await writeConnectionMeta(ctx, outDir);
51
+ console.log(colors.cyan`[devframe] writing RPC dump to ${resolve(outDir, DEVFRAME_RPC_DUMP_MANIFEST_FILENAME)}`);
52
+ const dump = await collectStaticRpcDump(ctx.rpc.definitions.values(), ctx);
53
+ await writeDumpFiles(dump, outDir, options.pretty ? 2 : void 0);
54
+ await fs$1.writeFile(resolve(outDir, DEVFRAME_RPC_DUMP_MANIFEST_FILENAME), JSON.stringify(dump.manifest, null, 2), "utf-8");
55
+ console.log(colors.green`[devframe] built "${d.id}" -> ${outDir}`);
56
+ }
57
+ /** Copy a local SPA dist, or materialize a remote assets source, into `outDir`. */
58
+ async function materializeSpa(resolved, outDir) {
59
+ if (typeof resolved === "string") {
60
+ console.log(colors.cyan`[devframe] copying SPA from ${resolved} -> ${outDir}`);
61
+ await fs$1.cp(resolved, outDir, { recursive: true });
62
+ return;
63
+ }
64
+ console.log(colors.cyan`[devframe] materializing SPA from ${resolved.assets.package}@${resolved.assets.version} -> ${outDir}`);
65
+ await resolved.materialize(outDir);
66
+ }
67
+ /** Write `__connection.json` with the JSON-serializable method allow-list. */
68
+ async function writeConnectionMeta(ctx, outDir) {
57
69
  const jsonSerializableMethods = [];
58
70
  for (const def of ctx.rpc.definitions.values()) if (def.jsonSerializable === true) jsonSerializableMethods.push(def.name);
59
71
  await fs$1.writeFile(resolve(outDir, DEVFRAME_CONNECTION_META_FILENAME), JSON.stringify({
60
72
  backend: "static",
61
73
  jsonSerializableMethods
62
74
  }, null, 2), "utf-8");
63
- console.log(colors.cyan`[devframe] writing RPC dump to ${resolve(outDir, DEVFRAME_RPC_DUMP_MANIFEST_FILENAME)}`);
64
- const dump = await collectStaticRpcDump(ctx.rpc.definitions.values(), ctx);
65
- const indent = options.pretty ? 2 : void 0;
75
+ }
76
+ /** Encode and write each sharded RPC dump file under `outDir`. */
77
+ async function writeDumpFiles(dump, outDir, indent) {
66
78
  for (const [filepath, file] of Object.entries(dump.files)) {
67
79
  const fullpath = resolve(outDir, filepath);
68
80
  await fs$1.mkdir(dirname(fullpath), { recursive: true });
69
81
  const text = file.serialization === "structured-clone" ? structuredCloneStringify(file.data) : strictJsonStringify(file.data, file.fnName);
70
82
  await fs$1.writeFile(fullpath, file.serialization === "json" && indent != null ? JSON.stringify(JSON.parse(text), null, indent) : text, "utf-8");
71
83
  }
72
- await fs$1.writeFile(resolve(outDir, DEVFRAME_RPC_DUMP_MANIFEST_FILENAME), JSON.stringify(dump.manifest, null, 2), "utf-8");
73
- console.log(colors.green`[devframe] built "${d.id}" -> ${outDir}`);
74
84
  }
75
85
  /**
76
86
  * Attach a `dump` to each {@link DevframeRpcOptions.snapshot} target so the
@@ -1,10 +1,25 @@
1
- import { Dt as parseCliFlags, Et as defineCliFlags, F as DevframeDefinition, Tt as InferCliFlags, wt as CliFlagsSchema } from "../context-CLF4-8Pp.mjs";
1
+ import { Dt as defineCliFlags, Et as InferCliFlags, F as DevframeDefinition, K as McpRouteOptions, Ot as parseCliFlags, Tt as CliFlagsSchema } from "../context-4AIVRLYF.mjs";
2
2
  import { CAC } from "cac";
3
3
  import { H3 } from "h3";
4
4
  //#region src/adapters/cac.d.ts
5
5
  interface CreateCacOptions {
6
6
  /** Default port for `dev` (default: 9999). */
7
7
  defaultPort?: number;
8
+ /**
9
+ * Expose a route-based MCP server alongside the dev server, speaking the
10
+ * MCP Streamable-HTTP transport at `<base>__mcp`. Whether to expose MCP is
11
+ * a hosting decision made at the CLI assembly stage, so it lives here rather
12
+ * than on the definition.
13
+ *
14
+ * - `false` / omitted (default): no MCP route is mounted.
15
+ * - `true`: mount at the default `__mcp` route with the loopback origin gate.
16
+ * - {@link McpRouteOptions}: customise the route path, origin allow-list, and
17
+ * opt into an identity check.
18
+ *
19
+ * The `--mcp` / `--no-mcp` flags override this per run. Falls back to the
20
+ * definition's deprecated `cli.mcp` when unset.
21
+ */
22
+ mcp?: boolean | McpRouteOptions;
8
23
  /**
9
24
  * Final CAC hook invoked after devframe's built-in subcommands and
10
25
  * after the definition's `cli.configure`. Use this to add app-level
@@ -1,13 +1,13 @@
1
- import { s as colors } from "../nostics-CzECRXpE.mjs";
2
- import { r as resolveDevServerPort } from "../_shared-BM3PdYli.mjs";
3
- import { a as importRuntimeModule } from "../instance-shell-CpVW4zG0.mjs";
1
+ import { s as colors } from "../nostics-D0PvLZsn.mjs";
2
+ import { r as resolveDevServerPort } from "../_shared-C08SdQRl.mjs";
3
+ import { a as importRuntimeModule } from "../instance-shell-cdVETpfz.mjs";
4
4
  import { createBuild } from "./build.mjs";
5
- import { t as createDevServer } from "../dev-CzkPCJwi.mjs";
5
+ import { t as createDevServer } from "../dev-Eqq5PX0k.mjs";
6
6
  import process from "node:process";
7
7
  import cac$1 from "cac";
8
8
  //#region src/adapters/flags.ts
9
9
  /**
10
- * Identity helper that preserves the literal schema-map type — use this
10
+ * Identity helper that preserves the literal schema-map type; use this
11
11
  * so `InferCliFlags<typeof myFlags>` resolves to the right object shape.
12
12
  *
13
13
  * ```ts
@@ -110,7 +110,7 @@ function createCac(d, options = {}) {
110
110
  host,
111
111
  defaultPort
112
112
  });
113
- const mcp = flags.mcp;
113
+ const mcp = flags.mcp ?? options.mcp;
114
114
  await createDevServer(d, {
115
115
  host,
116
116
  port,
@@ -129,6 +129,7 @@ function createCac(d, options = {}) {
129
129
  const { createMcpServer } = await importRuntimeModule("devframe/adapters/mcp");
130
130
  await createMcpServer(d, {
131
131
  transport: "stdio",
132
+ /** Deliberately go to stderr: stdout is the MCP transport. */
132
133
  onReady: ({ transport }) => {
133
134
  console.error(`[devframe] "${d.id}" MCP server ready (${transport})`);
134
135
  }
@@ -150,7 +151,7 @@ function resolveTypedFlags(d, raw) {
150
151
  if (!d.cli?.flags) return raw;
151
152
  const { flags, issues } = parseCliFlags(d.cli.flags, raw);
152
153
  if (issues?.length) {
153
- for (const issue of issues) console.error(colors.red`[devframe] invalid flag — ${issue}`);
154
+ for (const issue of issues) console.error(colors.red`[devframe] invalid flag: ${issue}`);
154
155
  process.exit(1);
155
156
  }
156
157
  return flags;
@@ -1,8 +1,8 @@
1
- import { d as DevframeRpcConnection, n as WsOriginRegistry, u as DevframeNodeRpcSessionMeta } from "../ws-server-VyHlanzy.mjs";
2
- import { Ct as DevframeAuthHandler, F as DevframeDefinition, G as McpRouteOptions, U as DevframeSseOptions, W as DevframeWsOptions, s as DevframeNodeRpcSession } from "../context-CLF4-8Pp.mjs";
3
- import { o as StaticAssetsSource } from "../remote-assets-B13_vRkJ.mjs";
4
- import { c as StartedServer } from "../instance-shell-Tcp5hGoq.mjs";
5
- import { a as resolveMcpConnectionMeta, i as resolveDevServerPort, t as ResolveDevServerPortOptions } from "../_shared-mtXpcJIv.mjs";
1
+ import { c as DevframeNodeRpcSessionMeta, l as DevframeRpcConnection, n as WsOriginRegistry } from "../ws-server-D2nv68Hg.mjs";
2
+ import { F as DevframeDefinition, K as McpRouteOptions, U as DevframeSseOptions, W as DevframeWsOptions, s as DevframeNodeRpcSession, wt as DevframeAuthHandler } from "../context-4AIVRLYF.mjs";
3
+ import { o as StaticAssetsSource } from "../remote-assets-eBvSKZMS.mjs";
4
+ import { c as StartedServer } from "../instance-shell-7Z52PE4_.mjs";
5
+ import { a as resolveDevServerPort, s as resolveMcpConnectionMeta, t as ResolveDevServerPortOptions } from "../_shared-CK3czkH4.mjs";
6
6
  import { H3 } from "h3";
7
7
  //#region src/adapters/dev.d.ts
8
8
  interface CreateDevServerOptions {
@@ -23,7 +23,7 @@ interface CreateDevServerOptions {
23
23
  /**
24
24
  * Override the definition's `clientAssets` (or deprecated `cli.distDir`).
25
25
  * When neither this option nor the definition's client assets are set, the
26
- * dev server runs in **bridge mode** — only `__connection.json` and the WS
26
+ * dev server runs in **bridge mode**: only `__connection.json` and the WS
27
27
  * endpoint are mounted; the SPA is expected to be hosted elsewhere (e.g. by
28
28
  * a parent Vite/Nuxt dev server via `devframeViteBridge` from
29
29
  * `@devframes/vite`).
@@ -37,7 +37,7 @@ interface CreateDevServerOptions {
37
37
  /**
38
38
  * Override how the browser reaches the RPC WebSocket (`def.cli?.ws`).
39
39
  * See {@link DevframeWsOptions}: same-server route (default), a dedicated
40
- * port, or a remote origin. Pass `false` to serve no WebSocket at all —
40
+ * port, or a remote origin. Pass `false` to serve no WebSocket at all;
41
41
  * clients connect over the SSE endpoint instead (`backend: 'sse'`).
42
42
  */
43
43
  ws?: DevframeWsOptions | false;
@@ -49,7 +49,7 @@ interface CreateDevServerOptions {
49
49
  */
50
50
  allowedOrigins?: readonly string[] | WsOriginRegistry | false;
51
51
  /**
52
- * Override the SSE RPC endpoint control (`def.cli?.sse`) — enabled by
52
+ * Override the SSE RPC endpoint control (`def.cli?.sse`), enabled by
53
53
  * default at `<base>__sse`. Pass `false` to disable, or a
54
54
  * {@link DevframeSseOptions} to rename the route.
55
55
  */
@@ -71,7 +71,7 @@ interface CreateDevServerOptions {
71
71
  /**
72
72
  * Override how authentication resolves, taking precedence over
73
73
  * `def.cli?.auth`. Pass `false` to skip the gate entirely (the standard
74
- * choice for a **hosted** deployment where the host manages auth — see
74
+ * choice for a **hosted** deployment where the host manages auth; see
75
75
  * {@link devframeViteBridge} from `@devframes/vite`); a {@link DevframeAuthHandler} to install a custom
76
76
  * scheme; or `true` to force devframe's interactive OTP gate on. When
77
77
  * omitted, auth resolves from `flags.auth` / `def.cli?.auth` (the standalone
@@ -99,7 +99,7 @@ interface CreateDevServerOptions {
99
99
  onPeerDisconnect?: (connection: DevframeRpcConnection, meta: DevframeNodeRpcSessionMeta) => void;
100
100
  /**
101
101
  * Called once the WS server is bound. Devframe stays headless
102
- * otherwise — wire this if you want a startup banner.
102
+ * otherwise, so wire this if you want a startup banner.
103
103
  */
104
104
  onReady?: (info: {
105
105
  origin: string;
@@ -108,20 +108,20 @@ interface CreateDevServerOptions {
108
108
  }) => void | Promise<void>;
109
109
  /**
110
110
  * Proceed even when the definition declares `capabilities.dev: false`.
111
- * `createDevServer` otherwise refuses such a definition (`DF0058`) — this
111
+ * `createDevServer` otherwise refuses such a definition (`DF0058`); this
112
112
  * only matters for a caller invoking it directly, bypassing the CLI.
113
113
  */
114
114
  force?: boolean;
115
115
  }
116
116
  /**
117
- * Start a devframe dev server for a {@link DevframeDefinition} —
117
+ * Start a devframe dev server for a {@link DevframeDefinition}:
118
118
  * h3 + WebSocket RPC + (optionally) the author's SPA mounted at the
119
119
  * resolved base path.
120
120
  *
121
121
  * When `distDir` is omitted (and the definition's client assets are unset) the
122
122
  * server runs in **bridge mode**: only `__connection.json` and the WS
123
123
  * endpoint are mounted, with no SPA mount. The SPA is expected to be
124
- * hosted elsewhere (e.g. by a parent Vite/Nuxt dev server) — see
124
+ * hosted elsewhere (e.g. by a parent Vite/Nuxt dev server); see
125
125
  * `devframeViteBridge` from `@devframes/vite`.
126
126
  *
127
127
  * Returns the underlying {@link StartedServer} handle so callers can
@@ -1,3 +1,3 @@
1
- import { i as resolveMcpConnectionMeta, r as resolveDevServerPort } from "../_shared-BM3PdYli.mjs";
2
- import { t as createDevServer } from "../dev-CzkPCJwi.mjs";
1
+ import { a as resolveMcpConnectionMeta, r as resolveDevServerPort } from "../_shared-C08SdQRl.mjs";
2
+ import { t as createDevServer } from "../dev-Eqq5PX0k.mjs";
3
3
  export { createDevServer, resolveDevServerPort, resolveMcpConnectionMeta };
@@ -1,4 +1,4 @@
1
- import { F as DevframeDefinition, o as DevframeNodeContext } from "../context-CLF4-8Pp.mjs";
1
+ import { F as DevframeDefinition, o as DevframeNodeContext } from "../context-4AIVRLYF.mjs";
2
2
  //#region src/adapters/embedded.d.ts
3
3
  interface CreateEmbeddedOptions {
4
4
  /** Target context the devframe is registered into. Required. */
@@ -1,7 +1,7 @@
1
- import { d as DevframeRpcConnection, n as WsOriginRegistry, u as DevframeNodeRpcSessionMeta } from "../ws-server-VyHlanzy.mjs";
2
- import { Ct as DevframeAuthHandler, F as DevframeDefinition, G as McpRouteOptions, U as DevframeSseOptions, W as DevframeWsOptions, bt as DevframeStorageScope, o as DevframeNodeContext, s as DevframeNodeRpcSession, t as ConnectionMeta } from "../context-CLF4-8Pp.mjs";
3
- import { o as StaticAssetsSource } from "../remote-assets-B13_vRkJ.mjs";
4
- import { c as StartedServer, f as DevframeInstanceRecord } from "../instance-shell-Tcp5hGoq.mjs";
1
+ import { c as DevframeNodeRpcSessionMeta, l as DevframeRpcConnection, n as WsOriginRegistry } from "../ws-server-D2nv68Hg.mjs";
2
+ import { F as DevframeDefinition, K as McpRouteOptions, U as DevframeSseOptions, W as DevframeWsOptions, o as DevframeNodeContext, s as DevframeNodeRpcSession, t as ConnectionMeta, wt as DevframeAuthHandler, xt as DevframeStorageScope } from "../context-4AIVRLYF.mjs";
3
+ import { o as StaticAssetsSource } from "../remote-assets-eBvSKZMS.mjs";
4
+ import { c as StartedServer, f as DevframeInstanceRecord } from "../instance-shell-7Z52PE4_.mjs";
5
5
  import { Buffer } from "node:buffer";
6
6
  import { IncomingMessage, Server, ServerResponse } from "node:http";
7
7
  import { Duplex } from "node:stream";
@@ -9,7 +9,7 @@ import { H3 } from "h3";
9
9
  //#region src/adapters/initiate.d.ts
10
10
  interface InitDevframeOptions {
11
11
  /**
12
- * Mount base the handler answers under (e.g. `/__my-tool/`) — required so
12
+ * Mount base the handler answers under (e.g. `/__my-tool/`), required so
13
13
  * the mount path is explicit at the call site. A handler is by definition
14
14
  * mounted *inside* a host app's origin; the resolved value is echoed back
15
15
  * as {@link DevframeInstance.base} so route/middleware code references it
@@ -19,8 +19,8 @@ interface InitDevframeOptions {
19
19
  base: string;
20
20
  /**
21
21
  * Override the definition's `clientAssets` (or deprecated `cli.distDir`).
22
- * When neither is set — or `false` is passed to suppress the definition's
23
- * own client assets — the handler runs in **bridge mode**: only
22
+ * When neither is set (or `false` is passed to suppress the definition's
23
+ * own client assets), the handler runs in **bridge mode**: only
24
24
  * `__connection.json`, the WS endpoint, and the MCP route (when enabled) are
25
25
  * served; the SPA is hosted elsewhere.
26
26
  */
@@ -36,20 +36,20 @@ interface InitDevframeOptions {
36
36
  */
37
37
  server?: Server;
38
38
  /**
39
- * Explicit control over how the browser reaches the RPC WebSocket —
39
+ * Explicit control over how the browser reaches the RPC WebSocket,
40
40
  * advertised in `__connection.json`. The **local binding** resolves in
41
41
  * precedence order `ws.port` (pinned side-car) > `server` (shared upgrade)
42
42
  * > `ws.sidecar` (auto-port side-car) > none (the host drives the socket
43
43
  * through {@link DevframeInstance.attach}). `ws.url` controls the
44
44
  * advertisement* only: the browser dials it verbatim (a tunnel/relay),
45
- * while the local binding keeps following the options above — and on its
45
+ * while the local binding keeps following the options above; on its
46
46
  * own it means an external server owns both the transport and its auth.
47
- * Pass `false` to serve no WebSocket at all — clients connect over the
47
+ * Pass `false` to serve no WebSocket at all; clients connect over the
48
48
  * SSE endpoint instead (`backend: 'sse'`).
49
49
  */
50
50
  ws?: DevframeWsOptions | false;
51
51
  /**
52
- * SSE RPC endpoint control — enabled by default at `<base>__sse` as the
52
+ * SSE RPC endpoint control, enabled by default at `<base>__sse` as the
53
53
  * more portable transport alongside the WebSocket. Pass `false` to
54
54
  * disable, or a {@link DevframeSseOptions} to rename the route.
55
55
  */
@@ -67,7 +67,7 @@ interface InitDevframeOptions {
67
67
  * (derived from the first request, or `origin`). Pass a
68
68
  * {@link DevframeAuthHandler} for a custom scheme, or `false` to opt out
69
69
  * for a single-user localhost setup that owns the trust boundary another
70
- * way. Ignored for the `ws.url` tier — the server behind that URL owns auth.
70
+ * way. Ignored for the `ws.url` tier, since the server behind that URL owns auth.
71
71
  */
72
72
  auth?: boolean | DevframeAuthHandler;
73
73
  /**
@@ -78,10 +78,12 @@ interface InitDevframeOptions {
78
78
  mcp?: boolean | McpRouteOptions;
79
79
  /**
80
80
  * Public origin the host app is reachable at (e.g. `http://localhost:3000`),
81
- * or a getter for hosts that resolve it late. When omitted (or the getter
82
- * returns a falsy value), it is derived lazily from the first request the
83
- * handler serves — used for the auth banner's magic link and absolute dock
84
- * URLs.
81
+ * or a getter for hosts that resolve it late. Backs the auth banner's magic
82
+ * link and absolute dock URLs. When omitted (or the getter returns a falsy
83
+ * value), it is derived from a served request, but only when that request's
84
+ * own origin is loopback or exactly matches an `allowedOrigins` entry; a raw
85
+ * inbound `Host`/URL authority and forwarded headers are never adopted. Set
86
+ * this explicitly for a non-loopback deployment (proxy, LAN, public host).
85
87
  */
86
88
  origin?: string | (() => string);
87
89
  /**
@@ -104,7 +106,7 @@ interface InitDevframeOptions {
104
106
  allowedOrigins?: readonly string[] | WsOriginRegistry | false;
105
107
  /**
106
108
  * h3 app to mount the handler's routes on. When omitted a fresh internal
107
- * app is created — the common middleware case. An adapter that owns the
109
+ * app is created, the common middleware case. An adapter that owns the
108
110
  * whole server (e.g. `createDevServer`) passes its own app so callers can
109
111
  * compose custom routes ahead of devframe's.
110
112
  */
@@ -138,19 +140,19 @@ interface DevframeInstance {
138
140
  /**
139
141
  * The normalized mount base this instance answers under (leading and
140
142
  * trailing slash, e.g. `/__my-tool/`). Reference it when wiring the mount
141
- * — route guards, middleware path checks — instead of repeating the
143
+ * (route guards, middleware path checks) instead of repeating the
142
144
  * string.
143
145
  */
144
146
  base: string;
145
147
  /**
146
- * Web-standard request handler — mount it on a catch-all route under
148
+ * Web-standard request handler; mount it on a catch-all route under
147
149
  * {@link DevframeInstance.base} (Next.js route handler, SvelteKit
148
150
  * `+server.ts`, Hono `c.req.raw`, Nitro `toWebRequest(event)`, …).
149
151
  * Requests outside the base 404.
150
152
  */
151
153
  handler: (request: Request) => Promise<Response>;
152
154
  /**
153
- * Connect/Express-style middleware over the same surface — for
155
+ * Connect/Express-style middleware over the same surface, for
154
156
  * `viteServer.middlewares.use(handler.nodeMiddleware)` or any other
155
157
  * node middleware stack. Mount it un-prefixed: paths outside the base
156
158
  * call `next()` so the rest of the stack keeps working.
@@ -158,7 +160,7 @@ interface DevframeInstance {
158
160
  nodeMiddleware: (req: IncomingMessage, res: ServerResponse, next?: (err?: unknown) => void) => void;
159
161
  /**
160
162
  * Route a host server's `upgrade` events to the RPC socket, returning a
161
- * detach function — the manual counterpart to the `server` option, for
163
+ * detach function, the manual counterpart to the `server` option, for
162
164
  * hosts that get their `node:http` server only after the instance exists.
163
165
  * Available on the default tier; a configured transport (`server`,
164
166
  * `ws.port`, `ws.sidecar`, `ws.url`) already owns the socket and reports
@@ -175,10 +177,10 @@ interface DevframeInstance {
175
177
  /**
176
178
  * Resolves once `def.setup` has run and the WebSocket binding is live.
177
179
  * `handler`/`nodeMiddleware` await it internally, so hosts never race
178
- * initialization — await it yourself only when you need the timing.
180
+ * initialization; await it yourself only when you need the timing.
179
181
  */
180
182
  ready: Promise<void>;
181
- /** The node context, once initialized — for advanced wiring (own WS transport, extra RPC registration). */
183
+ /** The node context, once initialized, for advanced wiring (own WS transport, extra RPC registration). */
182
184
  context: Promise<DevframeNodeContext>;
183
185
  /**
184
186
  * The `ConnectionMeta` this handler serves at `<base>__connection.json`.
@@ -204,7 +206,7 @@ interface DevframeInstanceInternals {
204
206
  /** @internal */
205
207
  declare function getInstanceInternals(handler: object): DevframeInstanceInternals;
206
208
  /**
207
- * Serve a devframe through one framework-agnostic, web-standard handler —
209
+ * Serve a devframe through one framework-agnostic, web-standard handler:
208
210
  * the SPA, `__connection.json` discovery, the WebSocket RPC endpoint, the
209
211
  * auth gate, and the optional MCP route, all under a single mount base.
210
212
  * Mount `handler` on any framework's catch-all route (or `nodeMiddleware` on
@@ -212,10 +214,10 @@ declare function getInstanceInternals(handler: object): DevframeInstanceInternal
212
214
  *
213
215
  * The factory is synchronous and kicks off initialization eagerly;
214
216
  * `handler`/`nodeMiddleware` await readiness internally. Nothing binds a port
215
- * on its own: the WebSocket resolves in precedence order — `ws.port` (pinned
217
+ * on its own: the WebSocket resolves in precedence order: `ws.port` (pinned
216
218
  * side-car) > `server` (shared upgrade at `<base>__ws`) > `ws.sidecar`
217
219
  * (auto-port side-car) > the host driving upgrades itself through
218
- * {@link DevframeInstance.attach} — while `ws.url`, when set, overrides the
220
+ * {@link DevframeInstance.attach}. Meanwhile `ws.url`, when set, overrides the
219
221
  * advertised* endpoint (the tunnel pattern) and on its own hands the whole
220
222
  * transport to an external server. `__connection.json` reflects whichever
221
223
  * combination is active.
@@ -1,2 +1,2 @@
1
- import { n as getInstanceInternals, r as initDevframe } from "../dev-CzkPCJwi.mjs";
1
+ import { n as getInstanceInternals, r as initDevframe } from "../dev-Eqq5PX0k.mjs";
2
2
  export { getInstanceInternals, initDevframe };
@@ -1,4 +1,4 @@
1
- import { F as DevframeDefinition, o as DevframeNodeContext } from "../context-CLF4-8Pp.mjs";
1
+ import { F as DevframeDefinition, G as McpAuthorization, o as DevframeNodeContext } from "../context-4AIVRLYF.mjs";
2
2
  import { H3 } from "h3";
3
3
  import "@modelcontextprotocol/server";
4
4
  //#region src/adapters/mcp/build-server.d.ts
@@ -6,15 +6,15 @@ interface CreateMcpServerOptions {
6
6
  /**
7
7
  * Transport to use. `createMcpServer` itself runs `'stdio'` (a standalone
8
8
  * process with its own host context); the Streamable-HTTP transport is
9
- * served route-based by the dev server instead — see `mountMcpHttp` and
9
+ * served route-based by the dev server instead; see `mountMcpHttp` and
10
10
  * the `mcp` option on `createDevServer` / `createCac`'s `--mcp` flag.
11
11
  */
12
12
  transport?: 'stdio';
13
13
  /**
14
14
  * Expose shared-state keys as MCP resources.
15
- * - `true` (default) — every key the host publishes
16
- * - `false` — none
17
- * - `(key) => boolean` — filter
15
+ * - `true` (default): every key the host publishes
16
+ * - `false`: none
17
+ * - `(key) => boolean`: filter
18
18
  */
19
19
  exposeSharedState?: boolean | ((key: string) => boolean);
20
20
  /** Override the name reported in the MCP handshake. */
@@ -41,8 +41,17 @@ interface CreateMcpFetchHandlerOptions {
41
41
  serverName: string;
42
42
  /** Version reported in the MCP handshake. */
43
43
  serverVersion: string;
44
- /** Expose shared-state keys as MCP resources — see `buildMcpServerFromContext`. */
44
+ /** Expose shared-state keys as MCP resources; see `buildMcpServerFromContext`. */
45
45
  exposeSharedState: boolean | ((key: string) => boolean);
46
+ /**
47
+ * Optional identity check, layered on top of the origin gate and checked
48
+ * **after** it: a bearer token string (matched in constant time against
49
+ * `Authorization: Bearer <token>`), a `(request) => boolean` callback, or
50
+ * `false` (the default) for origin-only, trusting same-machine callers. A
51
+ * callback governs identity only and cannot relax the origin gate. See
52
+ * {@link McpAuthorization}.
53
+ */
54
+ authorization?: McpAuthorization;
46
55
  /**
47
56
  * Origin allow-list beyond the loopback default. `false` disables the
48
57
  * origin gate entirely. Default: loopback-only.
@@ -57,7 +66,7 @@ interface CreateMcpFetchHandlerOptions {
57
66
  interface McpFetchHandler {
58
67
  /**
59
68
  * WHATWG-`fetch` handler for the MCP endpoint. Hand every method
60
- * (POST/GET/DELETE) on the endpoint's path to it — routing by path is the
69
+ * (POST/GET/DELETE) on the endpoint's path to it; routing by path is the
61
70
  * host's job.
62
71
  */
63
72
  fetch: (request: Request) => Promise<Response>;
@@ -66,22 +75,27 @@ interface McpFetchHandler {
66
75
  }
67
76
  /**
68
77
  * Build a framework-agnostic MCP endpoint over a devframe context: a
69
- * web-standard `Request → Response` handler any host can mount — h3 (see
78
+ * web-standard `Request → Response` handler any host can mount: h3 (see
70
79
  * `mountMcpHttp`), a Next.js App Router route, or any other fetch-shaped
71
80
  * server.
72
81
  *
73
82
  * The endpoint is **stateless**: it serves the 2026-07-28 revision per request
74
83
  * through the SDK's {@link createMcpHandler}, which builds a fresh MCP server
75
84
  * (from the shared, live `ctx` via `buildMcpServerFromContext`) for each
76
- * request — no `Mcp-Session-Id` registry, no session-local routing, no
85
+ * request: no `Mcp-Session-Id` registry, no session-local routing, no
77
86
  * GET/DELETE teardown protocol. 2025-era clients are still served through the
78
87
  * SDK's default stateless legacy path. `list_changed` events reach modern
79
88
  * `subscriptions/listen` streams through the handler's `notify` bus.
80
89
  *
81
90
  * The origin gate guards every request: loopback-default DNS-rebinding
82
- * protection that — unlike the WS upgrade's `isAllowedOrigin` — also rejects
83
- * `Origin`-less requests, so a route-based endpoint isn't reachable by an
84
- * arbitrary local process.
91
+ * protection that (unlike the WS upgrade's `isAllowedOrigin`) also rejects
92
+ * `Origin`-less requests, so a route-based endpoint isn't reachable by a
93
+ * browser or a remote host (a disallowed origin gets `403`). It trusts
94
+ * same-machine callers by default. When that isn't your trust boundary, add
95
+ * an optional identity gate ({@link CreateMcpFetchHandlerOptions.authorization}),
96
+ * checked after the origin gate: a bearer/callback check that proves *who* is
97
+ * calling (a missing/invalid credential gets `401` with a
98
+ * `WWW-Authenticate: Bearer` challenge).
85
99
  */
86
100
  declare function createMcpFetchHandler(ctx: DevframeNodeContext, options: CreateMcpFetchHandlerOptions): McpFetchHandler;
87
101
  //#endregion
@@ -92,11 +106,11 @@ interface MountedMcpHttp {
92
106
  dispose: () => Promise<void>;
93
107
  }
94
108
  /**
95
- * Mount a stateless MCP endpoint on an h3 app at `path` — the h3 binding over
109
+ * Mount a stateless MCP endpoint on an h3 app at `path`: the h3 binding over
96
110
  * {@link createMcpFetchHandler}, which owns the per-request serving, the
97
111
  * origin gate, and the transport plumbing.
98
112
  *
99
- * The handler is web-standard — it takes the h3 event's web `Request` and
113
+ * The handler is web-standard: it takes the h3 event's web `Request` and
100
114
  * returns a web `Response` (an SSE `ReadableStream` body for a
101
115
  * `subscriptions/listen` stream). We copy that response onto `event.res` and
102
116
  * return its body rather than returning the `Response` object directly, so an