@daloyjs/core 1.0.0-beta.4 → 1.0.0-beta.6

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,432 @@
1
+ import type { PathString, RouteDefinition } from "./types.js";
2
+ /**
3
+ * Latest MCP protocol version DaloyJS negotiates by default.
4
+ *
5
+ * @see https://modelcontextprotocol.io/specification/2025-11-25
6
+ * @since 1.0.0
7
+ */
8
+ export declare const MCP_PROTOCOL_VERSION = "2025-11-25";
9
+ /**
10
+ * Protocol revisions accepted by {@link createMcpHandler} unless the caller
11
+ * provides an explicit `protocolVersions` list.
12
+ *
13
+ * @since 1.0.0
14
+ */
15
+ export declare const MCP_PROTOCOL_VERSIONS: readonly string[];
16
+ /**
17
+ * Default maximum accepted JSON-RPC request body for a DaloyJS MCP endpoint.
18
+ * The cap is intentionally small because MCP calls should carry parameters,
19
+ * not bulk uploads. Raise it per endpoint when a real tool needs larger input.
20
+ *
21
+ * @since 1.0.0
22
+ */
23
+ export declare const MCP_DEFAULT_MAX_BODY_BYTES: number;
24
+ /**
25
+ * JSON value accepted in MCP schemas, structured results, and metadata.
26
+ *
27
+ * @since 1.0.0
28
+ */
29
+ export type McpJsonValue = null | boolean | number | string | McpJsonValue[] | {
30
+ [key: string]: McpJsonValue;
31
+ };
32
+ /**
33
+ * JSON object used for MCP tool arguments and structured payloads.
34
+ *
35
+ * @since 1.0.0
36
+ */
37
+ export type McpJsonObject = {
38
+ [key: string]: McpJsonValue;
39
+ };
40
+ /**
41
+ * JSON Schema fragment advertised to MCP clients for a tool or prompt
42
+ * argument object. DaloyJS does not bundle a schema validator here, so the
43
+ * schema is documentation and client-side guidance. Validate sensitive inputs
44
+ * inside your handler before touching databases, files, or remote services.
45
+ *
46
+ * @since 1.0.0
47
+ */
48
+ export type McpJsonSchema = McpJsonObject;
49
+ /**
50
+ * JSON-RPC id type accepted by MCP requests.
51
+ *
52
+ * @since 1.0.0
53
+ */
54
+ export type McpJsonRpcId = string | number | null;
55
+ /**
56
+ * Identity block returned from the MCP `initialize` handshake.
57
+ *
58
+ * @since 1.0.0
59
+ */
60
+ export interface McpServerInfo {
61
+ /** Stable machine-readable server name, for example `"acme-inventory-mcp"`. */
62
+ name: string;
63
+ /** Optional human-readable display title for MCP clients. */
64
+ title?: string;
65
+ /** Server version surfaced to clients for debugging and compatibility. */
66
+ version: string;
67
+ }
68
+ /**
69
+ * Per-request context passed to tool, resource, and prompt handlers.
70
+ *
71
+ * @since 1.0.0
72
+ */
73
+ export interface McpRequestContext {
74
+ /** The original HTTP request received by the DaloyJS route. */
75
+ request: Request;
76
+ /**
77
+ * Protocol version selected for this call. Before `initialize`, this is the
78
+ * version from the `MCP-Protocol-Version` header when present, otherwise the
79
+ * handler's preferred protocol version.
80
+ */
81
+ protocolVersion: string;
82
+ /** JSON-RPC id for request/response correlation. */
83
+ id: McpJsonRpcId;
84
+ /** Raw MCP method name, such as `"tools/call"` or `"resources/read"`. */
85
+ method: string;
86
+ }
87
+ /**
88
+ * Text content block returned from an MCP tool, resource, or prompt.
89
+ *
90
+ * @since 1.0.0
91
+ */
92
+ export interface McpTextContent {
93
+ type: "text";
94
+ text: string;
95
+ }
96
+ /**
97
+ * Image content block returned from an MCP tool.
98
+ *
99
+ * `data` is base64-encoded image bytes. Keep images small; for large assets,
100
+ * return a resource link or URL-bearing text instead.
101
+ *
102
+ * @since 1.0.0
103
+ */
104
+ export interface McpImageContent {
105
+ type: "image";
106
+ data: string;
107
+ mimeType: string;
108
+ }
109
+ /**
110
+ * Embedded resource content block returned from an MCP tool.
111
+ *
112
+ * @since 1.0.0
113
+ */
114
+ export interface McpEmbeddedResourceContent {
115
+ type: "resource";
116
+ resource: McpResourceContents;
117
+ }
118
+ /**
119
+ * Content block supported by the dependency-free MCP helper.
120
+ *
121
+ * @since 1.0.0
122
+ */
123
+ export type McpContent = McpTextContent | McpImageContent | McpEmbeddedResourceContent;
124
+ /**
125
+ * Result returned by an MCP tool handler.
126
+ *
127
+ * `isError` marks caller-correctable tool failures, such as invalid input or a
128
+ * domain error. Unexpected thrown errors become JSON-RPC internal errors and
129
+ * are redacted in production.
130
+ *
131
+ * @since 1.0.0
132
+ */
133
+ export interface McpToolResult {
134
+ /** Human or model-readable content blocks returned to the MCP client. */
135
+ content: McpContent[];
136
+ /** Optional structured payload for clients that can consume typed output. */
137
+ structuredContent?: McpJsonObject;
138
+ /** Set to `true` for domain/tool errors the model may recover from. */
139
+ isError?: boolean;
140
+ }
141
+ /**
142
+ * Handler for a single MCP tool.
143
+ *
144
+ * @typeParam TArgs - Type expected in `params.arguments` for this tool.
145
+ * @param args - Tool arguments supplied by the MCP client. They are typed for
146
+ * developer experience but are still untrusted JSON at runtime.
147
+ * @param ctx - Request metadata and the original HTTP request.
148
+ * @returns Text shorthand or a full {@link McpToolResult}.
149
+ * @throws {McpToolError} for caller-correctable failures that should be
150
+ * returned as an MCP tool error result.
151
+ *
152
+ * @since 1.0.0
153
+ */
154
+ export type McpToolHandler<TArgs extends Record<string, unknown> = Record<string, unknown>> = (args: TArgs, ctx: McpRequestContext) => string | McpToolResult | Promise<string | McpToolResult>;
155
+ /**
156
+ * Definition of a callable MCP tool.
157
+ *
158
+ * Tools are model-controlled in MCP: clients may let the language model decide
159
+ * when to call them. Treat every tool as a public API operation and enforce
160
+ * authentication, authorization, rate limits, and validation before side
161
+ * effects.
162
+ *
163
+ * @typeParam TArgs - Type expected by this tool's handler.
164
+ * @since 1.0.0
165
+ */
166
+ export interface McpTool<TArgs extends Record<string, unknown> = Record<string, unknown>> {
167
+ /** Unique tool name within this MCP server. Prefer namespaced verbs. */
168
+ name: string;
169
+ /** Optional human-readable title displayed by clients. */
170
+ title?: string;
171
+ /** Clear description of when the model should use this tool. */
172
+ description: string;
173
+ /** JSON Schema for `params.arguments`. */
174
+ inputSchema: McpJsonSchema;
175
+ /** Execute the tool with untrusted JSON arguments. */
176
+ handler: McpToolHandler<TArgs>;
177
+ }
178
+ /**
179
+ * Resource metadata returned from `resources/list`.
180
+ *
181
+ * @since 1.0.0
182
+ */
183
+ export interface McpResource {
184
+ /** Unique resource URI, for example `"daloy://schema/inventory"`. */
185
+ uri: string;
186
+ /** Stable resource name. */
187
+ name: string;
188
+ /** Optional human-readable title. */
189
+ title?: string;
190
+ /** Optional description shown by clients. */
191
+ description?: string;
192
+ /** MIME type returned by `resources/read`, such as `"application/json"`. */
193
+ mimeType?: string;
194
+ }
195
+ /**
196
+ * Resource payload returned from `resources/read`.
197
+ *
198
+ * Use either `text` for UTF-8 content or `blob` for base64-encoded binary
199
+ * content. Set `mimeType` so clients know how to present the resource.
200
+ *
201
+ * @since 1.0.0
202
+ */
203
+ export interface McpResourceContents {
204
+ /** URI of the resource being returned. */
205
+ uri: string;
206
+ /** MIME type of the returned content. */
207
+ mimeType?: string;
208
+ /** UTF-8 text content. */
209
+ text?: string;
210
+ /** Base64-encoded binary content. */
211
+ blob?: string;
212
+ }
213
+ /**
214
+ * Definition of a readable MCP resource.
215
+ *
216
+ * Resources are application-controlled context. They are a good fit for
217
+ * schemas, read-only records, catalogs, runbooks, and other context a client
218
+ * can choose to include before a tool call.
219
+ *
220
+ * @since 1.0.0
221
+ */
222
+ export interface McpResourceDefinition extends McpResource {
223
+ /**
224
+ * Read the resource contents for `resources/read`.
225
+ *
226
+ * @param ctx - Request metadata and the original HTTP request.
227
+ * @returns One or more content entries for this resource.
228
+ */
229
+ read: (ctx: McpRequestContext) => McpResourceContents | McpResourceContents[] | Promise<McpResourceContents | McpResourceContents[]>;
230
+ }
231
+ /**
232
+ * Argument metadata for an MCP prompt.
233
+ *
234
+ * @since 1.0.0
235
+ */
236
+ export interface McpPromptArgument {
237
+ /** Argument name accepted by the prompt. */
238
+ name: string;
239
+ /** Optional description displayed by clients. */
240
+ description?: string;
241
+ /** Whether the argument is required. */
242
+ required?: boolean;
243
+ }
244
+ /**
245
+ * Prompt metadata returned from `prompts/list`.
246
+ *
247
+ * @since 1.0.0
248
+ */
249
+ export interface McpPrompt {
250
+ /** Unique prompt name within this MCP server. */
251
+ name: string;
252
+ /** Optional human-readable title. */
253
+ title?: string;
254
+ /** Optional prompt description. */
255
+ description?: string;
256
+ /** Prompt arguments clients may supply to `prompts/get`. */
257
+ arguments?: McpPromptArgument[];
258
+ }
259
+ /**
260
+ * Message returned from `prompts/get`.
261
+ *
262
+ * @since 1.0.0
263
+ */
264
+ export interface McpPromptMessage {
265
+ /** Role that should receive the prompt content. */
266
+ role: "user" | "assistant";
267
+ /** Prompt content block. */
268
+ content: McpTextContent | McpImageContent | McpEmbeddedResourceContent;
269
+ }
270
+ /**
271
+ * Result returned by an MCP prompt handler.
272
+ *
273
+ * @since 1.0.0
274
+ */
275
+ export interface McpPromptResult {
276
+ /** Optional description of the rendered prompt. */
277
+ description?: string;
278
+ /** Messages the client can inject into the model conversation. */
279
+ messages: McpPromptMessage[];
280
+ }
281
+ /**
282
+ * Definition of a reusable MCP prompt.
283
+ *
284
+ * @since 1.0.0
285
+ */
286
+ export interface McpPromptDefinition extends McpPrompt {
287
+ /**
288
+ * Render the prompt for `prompts/get`.
289
+ *
290
+ * @param args - Prompt arguments supplied by the MCP client.
291
+ * @param ctx - Request metadata and the original HTTP request.
292
+ * @returns Prompt messages.
293
+ */
294
+ get: (args: Record<string, unknown>, ctx: McpRequestContext) => McpPromptResult | Promise<McpPromptResult>;
295
+ }
296
+ /**
297
+ * Caller-correctable MCP tool/resource/prompt error.
298
+ *
299
+ * Throw this when the model supplied bad arguments, referenced a missing
300
+ * domain object, or otherwise made a recoverable call. Tool errors become
301
+ * `{ isError: true }` tool results; resource and prompt errors become
302
+ * JSON-RPC invalid-params errors. Unexpected errors are treated as internal
303
+ * server failures and are redacted in production.
304
+ *
305
+ * @since 1.0.0
306
+ */
307
+ export declare class McpToolError extends Error {
308
+ /**
309
+ * Create a recoverable MCP handler error.
310
+ *
311
+ * @param message - Safe, caller-visible explanation.
312
+ */
313
+ constructor(message: string);
314
+ }
315
+ /**
316
+ * Options for {@link createMcpHandler}.
317
+ *
318
+ * @since 1.0.0
319
+ */
320
+ export interface McpHandlerOptions {
321
+ /** Server identity returned from the `initialize` handshake. */
322
+ serverInfo: McpServerInfo;
323
+ /** Optional guidance returned from `initialize`. */
324
+ instructions?: string;
325
+ /** Callable tools exposed through `tools/list` and `tools/call`. */
326
+ tools?: readonly McpTool[];
327
+ /** Readable resources exposed through `resources/list` and `resources/read`. */
328
+ resources?: readonly McpResourceDefinition[];
329
+ /** Reusable prompts exposed through `prompts/list` and `prompts/get`. */
330
+ prompts?: readonly McpPromptDefinition[];
331
+ /** Accepted MCP protocol versions. Defaults to {@link MCP_PROTOCOL_VERSIONS}. */
332
+ protocolVersions?: readonly string[];
333
+ /**
334
+ * Protocol version returned when the client asks for an unsupported version.
335
+ * Defaults to {@link MCP_PROTOCOL_VERSION}.
336
+ */
337
+ preferredProtocolVersion?: string;
338
+ /** Maximum accepted JSON-RPC body size in bytes. Defaults to 256 KiB. */
339
+ maxBodyBytes?: number;
340
+ /**
341
+ * Extra headers added to every JSON response. Use this for endpoint-local
342
+ * cache, CORS, or deployment metadata. Authentication should usually live in
343
+ * DaloyJS middleware before the MCP route.
344
+ */
345
+ headers?: Record<string, string>;
346
+ /**
347
+ * Include development error details in JSON-RPC internal errors. Defaults to
348
+ * `process.env.NODE_ENV !== "production"` when `process` exists.
349
+ */
350
+ exposeInternalErrors?: boolean;
351
+ }
352
+ /**
353
+ * Fetch-compatible handler returned by {@link createMcpHandler}.
354
+ *
355
+ * @param request - Incoming HTTP request for the MCP endpoint.
356
+ * @returns A standard `Response` containing a JSON-RPC response, `202` for
357
+ * accepted notifications, or `405` for unsupported HTTP methods.
358
+ *
359
+ * @since 1.0.0
360
+ */
361
+ export type McpHandler = (request: Request) => Promise<Response>;
362
+ /**
363
+ * Create a dependency-free MCP Streamable HTTP endpoint handler.
364
+ *
365
+ * The handler implements the server side of MCP over one HTTP endpoint:
366
+ * `initialize`, `ping`, `tools/list`, `tools/call`, `resources/list`,
367
+ * `resources/read`, `prompts/list`, and `prompts/get`. It accepts JSON-RPC
368
+ * requests over `POST`, acknowledges notifications with `202`, validates the
369
+ * `MCP-Protocol-Version` header, bounds request bodies, and returns JSON-RPC
370
+ * errors for malformed input.
371
+ *
372
+ * It intentionally does not spawn stdio servers, manage OAuth metadata, keep
373
+ * durable sessions, or open server-initiated SSE streams. Use DaloyJS
374
+ * middleware for authentication and authorization, and run this on a dedicated
375
+ * Daloy app when your MCP server has a different trust boundary than your REST
376
+ * API.
377
+ *
378
+ * @param options - Server identity, capabilities, limits, and response headers.
379
+ * @returns A Fetch-compatible request handler suitable for {@link mcpRoutes}
380
+ * or for direct use in any web-standard runtime.
381
+ *
382
+ * @example
383
+ * ```ts
384
+ * const mcp = createMcpHandler({
385
+ * serverInfo: { name: "inventory-mcp", version: "1.0.0" },
386
+ * tools: [
387
+ * {
388
+ * name: "inventory_lookup",
389
+ * description: "Look up inventory by SKU.",
390
+ * inputSchema: {
391
+ * type: "object",
392
+ * properties: { sku: { type: "string" } },
393
+ * required: ["sku"],
394
+ * additionalProperties: false,
395
+ * },
396
+ * handler: async ({ sku }) => `SKU ${sku} has 42 units.`,
397
+ * },
398
+ * ],
399
+ * });
400
+ * ```
401
+ *
402
+ * @since 1.0.0
403
+ */
404
+ export declare function createMcpHandler(options: McpHandlerOptions): McpHandler;
405
+ /**
406
+ * Build the Daloy route definitions for a Streamable HTTP MCP endpoint.
407
+ *
408
+ * Register each returned route on the Daloy app that should host MCP. A
409
+ * separate app is often the cleanest production shape: the REST API can keep
410
+ * its public contract and auth policy, while the MCP server can use its own
411
+ * bearer token, rate limit, network allowlist, and tool set.
412
+ *
413
+ * @param path - Public MCP endpoint path, usually `"/mcp"`.
414
+ * @param handler - Handler returned by {@link createMcpHandler}.
415
+ * @returns Route definitions for `POST`, `GET`, and `OPTIONS` on the same
416
+ * path. `POST` is the actual MCP transport; `GET` gives a human-readable
417
+ * 405 hint because this helper does not open server-initiated SSE streams;
418
+ * `OPTIONS` supports preflight when CORS middleware is installed.
419
+ *
420
+ * @example
421
+ * ```ts
422
+ * const app = new App();
423
+ * const mcp = createMcpHandler({ serverInfo, tools });
424
+ *
425
+ * for (const route of mcpRoutes("/mcp", mcp)) {
426
+ * app.route(route);
427
+ * }
428
+ * ```
429
+ *
430
+ * @since 1.0.0
431
+ */
432
+ export declare function mcpRoutes(path: PathString, handler: McpHandler): RouteDefinition<PathString, "GET" | "POST" | "OPTIONS">[];