@xtrable-ltd/nanoesis 0.1.11 → 0.1.12

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/mcp.d.ts ADDED
@@ -0,0 +1,48 @@
1
+ import { ApiDeps } from '@nanoesis/editor-api';
2
+
3
+ /**
4
+ * Identity reported to MCP clients on `initialize`. Defaults: `{ name: 'nanoesis', version:
5
+ * '0.0.0' }`. Adopters embedding the HTTP route in their own host typically override `name`
6
+ * with their site identifier and `version` with their app version so client UIs identify
7
+ * the deployment, not the framework.
8
+ */
9
+ interface McpServerIdentity {
10
+ readonly name?: string;
11
+ readonly version?: string;
12
+ }
13
+
14
+ /**
15
+ * Options for {@link handleMcpRequest}. Both fields are passed straight through to the
16
+ * MCP `Server`'s `initialize` response so client UIs (Claude Desktop, Cursor, …) identify
17
+ * the deployment rather than the framework.
18
+ */
19
+ type HandleMcpRequestOptions = McpServerIdentity;
20
+ /**
21
+ * Handle a single MCP HTTP request over the SDK's web-standard Streamable HTTP transport
22
+ * (DESIGN §11c/§14). Stateless: each call builds a fresh `Server` + `Transport` pair, so
23
+ * the caller's per-request `Authorization: Bearer …` header — propagated by the SDK into
24
+ * the request handlers as `extra.requestInfo.headers` — drives the editor's per-user role
25
+ * gate exactly as `/api/*` does.
26
+ *
27
+ * The signature is Fetch-API neutral: any runtime that hands a handler a standard
28
+ * `Request` (Azure Functions v4, Cloudflare Workers, plain Node 18+, Bun, Deno, Hono)
29
+ * wires it the same way:
30
+ *
31
+ * ```ts
32
+ * import { handleMcpRequest } from '@xtrable-ltd/nanoesis/mcp';
33
+ * // ... build `deps` once at startup
34
+ * app.http('mcp', {
35
+ * methods: ['POST', 'GET', 'DELETE'],
36
+ * handler: (req) => handleMcpRequest(deps, req, { name: 'my-site', version: pkg.version }),
37
+ * });
38
+ * ```
39
+ *
40
+ * Runtimes whose request shape is not a standard `Request` (e.g. Azure Functions' enhanced
41
+ * HttpRequest, Express' IncomingMessage) translate to/from `Request`/`Response` at the
42
+ * boundary — that translation is adopter-side because it depends on the host runtime; the
43
+ * MCP server construction and transport handling, which used to be ~120 lines of inlined
44
+ * boilerplate per adopter, is now this one call.
45
+ */
46
+ declare function handleMcpRequest(deps: ApiDeps, request: Request, opts?: HandleMcpRequestOptions): Promise<Response>;
47
+
48
+ export { type HandleMcpRequestOptions, handleMcpRequest };
package/dist/mcp.js ADDED
@@ -0,0 +1,76 @@
1
+ import {
2
+ MCP_RESOURCES,
3
+ MCP_TOOLS,
4
+ callMcpTool,
5
+ readMcpResource
6
+ } from "./chunk-EN5SMEWJ.js";
7
+ import "./chunk-XO3CT6GL.js";
8
+
9
+ // ../../hosts/host-mcp/src/http.ts
10
+ import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
11
+
12
+ // ../../hosts/host-mcp/src/server.ts
13
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
14
+ import {
15
+ CallToolRequestSchema,
16
+ ListResourcesRequestSchema,
17
+ ListToolsRequestSchema,
18
+ ReadResourceRequestSchema
19
+ } from "@modelcontextprotocol/sdk/types.js";
20
+ var BEARER_PREFIX = /^Bearer\s+/i;
21
+ function bearerFrom(headers) {
22
+ if (headers === void 0) return void 0;
23
+ const raw = headers["authorization"] ?? headers["Authorization"];
24
+ const value = Array.isArray(raw) ? raw[0] : raw;
25
+ if (value === void 0) return void 0;
26
+ const match = BEARER_PREFIX.exec(value);
27
+ return match ? value.slice(match[0].length).trim() : void 0;
28
+ }
29
+ function createMcpServer(deps, identity) {
30
+ const server = new Server(
31
+ { name: identity?.name ?? "nanoesis", version: identity?.version ?? "0.0.0" },
32
+ { capabilities: { tools: {}, resources: {} } }
33
+ );
34
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [...MCP_TOOLS] }));
35
+ server.setRequestHandler(CallToolRequestSchema, async (req, extra) => {
36
+ const args = req.params.arguments ?? {};
37
+ const token = bearerFrom(extra.requestInfo?.headers);
38
+ const result = await callMcpTool(
39
+ deps,
40
+ req.params.name,
41
+ args,
42
+ token !== void 0 ? { token } : {}
43
+ );
44
+ return { content: [{ type: "text", text: result.text }], isError: result.isError };
45
+ });
46
+ server.setRequestHandler(ListResourcesRequestSchema, async () => ({
47
+ resources: [...MCP_RESOURCES]
48
+ }));
49
+ server.setRequestHandler(ReadResourceRequestSchema, async (req) => {
50
+ const { uri } = req.params;
51
+ const resource = readMcpResource(uri);
52
+ if (resource === void 0) throw new Error(`Unknown resource: ${uri}`);
53
+ return { contents: [{ uri, mimeType: resource.mimeType, text: resource.text }] };
54
+ });
55
+ return server;
56
+ }
57
+
58
+ // ../../hosts/host-mcp/src/http.ts
59
+ var DEFAULT_VERSION = true ? "0.1.12" : "0.0.0-workspace";
60
+ async function handleMcpRequest(deps, request, opts) {
61
+ const server = createMcpServer(deps, {
62
+ name: opts?.name ?? "nanoesis",
63
+ version: opts?.version ?? DEFAULT_VERSION
64
+ });
65
+ const transport = new WebStandardStreamableHTTPServerTransport({ enableJsonResponse: true });
66
+ await server.connect(transport);
67
+ try {
68
+ return await transport.handleRequest(request);
69
+ } finally {
70
+ await transport.close();
71
+ await server.close();
72
+ }
73
+ }
74
+ export {
75
+ handleMcpRequest
76
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xtrable-ltd/nanoesis",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "nanoesis: a static-first publishing compiler. The engine, the mountable editor API, the storage/image/auth adapters, and the editor UI bundle, in one package (DESIGN 11c).",
5
5
  "license": "MIT",
6
6
  "author": "Xtrable Ltd",
@@ -49,6 +49,10 @@
49
49
  "types": "./dist/editor.d.ts",
50
50
  "default": "./dist/editor.js"
51
51
  },
52
+ "./mcp": {
53
+ "types": "./dist/mcp.d.ts",
54
+ "default": "./dist/mcp.js"
55
+ },
52
56
  "./package.json": "./package.json"
53
57
  },
54
58
  "files": [
@@ -66,6 +70,7 @@
66
70
  },
67
71
  "dependencies": {
68
72
  "@azure/storage-blob": "^12.26.0",
73
+ "@modelcontextprotocol/sdk": "^1.29.0",
69
74
  "parse5": "^7.2.1",
70
75
  "sharp": "^0.33.0"
71
76
  },
@@ -79,6 +84,7 @@
79
84
  "@nanoesis/adapter-trusted-header": "*",
80
85
  "@nanoesis/editor-api": "*",
81
86
  "@nanoesis/engine": "*",
87
+ "@nanoesis/host-mcp": "*",
82
88
  "@types/node": "^22.10.0",
83
89
  "tsup": "^8.3.0"
84
90
  }