@node-in-layers/mcp-server 2.3.1 → 2.5.0

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/types.d.ts CHANGED
@@ -1,144 +1,615 @@
1
- import { ExpressRoute, ExpressMiddleware } from '@l4t/mcp-ai/common/types.js';
2
- import { ServerTool } from '@l4t/mcp-ai/simple-server/types.js';
3
- import { ServerHttpConfig, ServerCliConfig, ServerSseConfig, ServerStatelessHttpConfig } from '@l4t/mcp-ai';
4
- import { Config, LogLevelNames, LayerContext } from '@node-in-layers/core';
5
- import { Express } from 'express';
1
+ import { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
2
+ import { Config, LogLevelNames, LayerContext, XOR, CrossLayerProps } from '@node-in-layers/core';
3
+ import express from 'express';
6
4
  import { JsonAble } from 'functional-models';
7
- type Connection = ServerHttpConfig | ServerCliConfig | ServerSseConfig | ServerStatelessHttpConfig;
5
+ /**
6
+ * The namespace key used to scope all `@node-in-layers/mcp-server` configuration
7
+ * inside the system config object.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * const config = {
12
+ * [McpNamespace]: {
13
+ * version: '1.0.0',
14
+ * server: { connection: { type: 'http', url: 'http://localhost:3000' } },
15
+ * },
16
+ * }
17
+ * ```
18
+ */
19
+ export declare const McpNamespace = "@node-in-layers/mcp-server";
20
+ /**
21
+ * @interface
22
+ * CLI (stdio) connection configuration. Use this when the MCP server is
23
+ * launched as a subprocess and communicates over stdin/stdout.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * const connection: CliConnection = { type: 'cli' }
28
+ * ```
29
+ */
30
+ export type CliConnection = Readonly<{
31
+ type: 'cli';
32
+ }>;
33
+ /**
34
+ * @interface
35
+ * HTTP connection configuration. Use this when the MCP server is exposed over
36
+ * a network via the Streamable HTTP transport.
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * const connection: HttpConnection = {
41
+ * type: 'http',
42
+ * url: 'http://localhost:3000/mcp',
43
+ * headers: { 'x-api-key': 'secret' },
44
+ * timeout: 5000,
45
+ * retry: { attempts: 3, backoff: 500 },
46
+ * }
47
+ * ```
48
+ */
49
+ export type HttpConnection = Readonly<{
50
+ type: 'http';
51
+ /** Base URL of the MCP HTTP endpoint (e.g. `http://localhost:3000/mcp`). */
52
+ url: string;
53
+ /** Static headers sent with every request to the server. */
54
+ headers?: Readonly<Record<string, string>>;
55
+ /** Request timeout in milliseconds. */
56
+ timeout?: number;
57
+ /** Retry policy for failed requests. */
58
+ retry?: Readonly<{
59
+ /** Number of retry attempts before giving up. */
60
+ attempts: number;
61
+ /** Base backoff interval in milliseconds between retries. */
62
+ backoff: number;
63
+ }>;
64
+ }>;
65
+ /**
66
+ * A discriminated union of the supported MCP transport connections.
67
+ * Exactly one of `CliConnection` or `HttpConnection` must be provided.
68
+ *
69
+ * @see {@link CliConnection}
70
+ * @see {@link HttpConnection}
71
+ */
72
+ export type Connection = XOR<CliConnection, HttpConnection>;
73
+ /**
74
+ * @interface
75
+ * A named example of system usage, shown in the `START_HERE` tool response to
76
+ * give AI clients concrete guidance on how to use the system.
77
+ */
8
78
  export type SystemUseExample = Readonly<{
79
+ /** Short label for the example (e.g. `"Create a user"`). */
9
80
  name: string;
81
+ /** One-sentence description of what the example demonstrates. */
10
82
  description?: string;
83
+ /** A representative value or input to show. */
11
84
  value?: string;
85
+ /** Optional tags for categorisation. */
12
86
  tags?: string[];
87
+ /** Longer free-form explanation. */
13
88
  details?: string;
89
+ /** Concrete example payload or invocation. */
14
90
  example?: string;
15
91
  }>;
16
92
  /**
17
- * Configuration for the MCP server.
18
93
  * @interface
94
+ * Top-level configuration for the `@node-in-layers/mcp-server` package.
95
+ * Placed under the `McpNamespace` key inside the system config.
96
+ *
97
+ * @example
98
+ * ```ts
99
+ * const config: McpServerConfig = {
100
+ * [McpNamespace]: {
101
+ * version: '1.0.0',
102
+ * stateful: false,
103
+ * server: {
104
+ * connection: { type: 'http', url: 'http://localhost:3000' },
105
+ * },
106
+ * },
107
+ * }
108
+ * ```
19
109
  */
20
110
  export type McpServerConfig = Readonly<{
21
111
  [McpNamespace]: {
22
112
  /**
23
- * The name of the MCP server.
24
- */
25
- name?: string;
26
- /**
27
- * The version of the MCP server.
113
+ * Semver string reported by the MCP server during the initialize handshake.
114
+ * Defaults to `'1.0.0'` if omitted.
28
115
  */
29
116
  version?: string;
30
117
  /**
31
- * Whether the MCP server is stateless.
118
+ * When `true` the HTTP transport manages persistent sessions (one
119
+ * `McpServer` instance per session). When `false` (the default) each
120
+ * HTTP request spins up a fresh server instance (stateless mode).
121
+ *
122
+ * Stateful mode is required when you need server-sent events or long-lived
123
+ * session state. Stateless mode is simpler and works well for most REST-style
124
+ * AI tool calls.
32
125
  */
33
- stateless?: boolean;
126
+ stateful?: boolean;
34
127
  /**
35
- * The server configuration.
128
+ * Transport configuration. Must specify a `connection` that selects either
129
+ * CLI (stdio) or HTTP transport.
36
130
  */
37
131
  server: {
38
132
  /**
39
- * Connection configuration.
133
+ * Transport connection — either `{ type: 'cli' }` or
134
+ * `{ type: 'http', url: '...', ... }`.
135
+ *
136
+ * @see {@link Connection}
40
137
  */
41
138
  connection: Connection;
42
139
  };
43
140
  /**
44
- * Overrides for the start here tool.
141
+ * Configuration for the built-in `START_HERE` tool.
142
+ * This tool is always registered and is the recommended first call for any
143
+ * AI client — it returns a system overview that helps the client navigate
144
+ * the available domains, features, and models.
45
145
  */
46
146
  startHere?: {
47
147
  /**
48
- * Overrides the name of the tool. Default: 'START_HERE'
148
+ * Override the tool name. Default: `'START_HERE'`.
49
149
  */
50
- name: string;
150
+ name?: string;
51
151
  /**
52
- * Overrides the description of the tool.
152
+ * Override the tool description shown to the AI client.
53
153
  */
54
- description: string;
154
+ description?: string;
155
+ /**
156
+ * When `true`, suppresses the built-in Node-in-Layers navigation
157
+ * documentation from the response. Generally not recommended unless you
158
+ * are providing a completely custom system description.
159
+ */
160
+ hideDefaultSystemEntries?: boolean;
161
+ /**
162
+ * When `true`, the response includes the domain list (equivalent to
163
+ * calling `list_domains` first).
164
+ */
165
+ includeDomains?: boolean;
166
+ /**
167
+ * When `true`, the response includes the full feature list per domain
168
+ * (equivalent to calling `list_features` for every domain). Implies
169
+ * `includeDomains: true`.
170
+ */
171
+ includeFeatures?: boolean;
172
+ /**
173
+ * Optional worked examples of end-to-end usage flows to include in the
174
+ * `START_HERE` response. Prefer JSON object examples with minimal prose.
175
+ *
176
+ * @see {@link SystemUseExample}
177
+ */
178
+ examplesOfUse?: ReadonlyArray<SystemUseExample>;
55
179
  };
56
180
  /**
57
- * (Deprecated) Dot paths, to hide from the server.
58
- * Use hideComponents instead.
181
+ * @deprecated Use `hideComponents` instead.
182
+ * Dot-path strings of tools/domains to suppress.
59
183
  */
60
184
  hiddenPaths?: string[];
61
185
  /**
62
- * If provided, hides the components configured.
186
+ * Fine-grained control over which tools are exposed to AI clients.
187
+ * All suppressed items are completely omitted — they will not appear in
188
+ * tool listings or `START_HERE` output.
189
+ *
190
+ * Dot-path format for `paths`:
191
+ * - `'myDomain'` — hides the entire domain and all its features/models.
192
+ * - `'myDomain.myFeature'` — hides one specific feature.
193
+ * - `'myDomain.cruds'` — hides all model CRUD tools for a domain.
194
+ * - `'myDomain.cruds.MyModel'` — hides CRUD tools for one specific model.
63
195
  */
64
196
  hideComponents?: {
65
197
  /**
66
- * Dot paths, to hide from the server.
67
- * Example:
68
- * myDomain - hides an entire domain.
69
- * myDomain.myFeature - hides a feature.
70
- * myDomain.cruds - hides ALL models of the domain
71
- * myDomain.cruds.MyModel - hides a specific model
198
+ * Dot-path strings identifying individual tools, features, or model CRUD
199
+ * groups to suppress.
72
200
  */
73
201
  paths?: ReadonlyArray<string>;
74
202
  /**
75
- * Which domains to completely hide. (Will not show up in the domain list).
203
+ * Domain names to hide entirely (domain will not appear in `list_domains`).
76
204
  */
77
205
  domains?: string[];
78
206
  /**
79
- * Whether to hide all model cruds entirely.
80
- * This will not show any tools related to models.
207
+ * When `true`, suppresses ALL model CRUD tools across every domain.
81
208
  */
82
209
  allModels?: boolean;
83
210
  };
84
211
  /**
85
- * Ability to set information about the system so that it can be fed to AI consumers.
86
- *
212
+ * Static metadata injected into the `START_HERE` response.
87
213
  */
88
214
  systemDescription?: {
215
+ /** Human-readable description of the system shown to the AI client. */
89
216
  description?: string;
217
+ /** System version string shown to the AI client. */
90
218
  version?: string;
91
- examplesOfUse?: ReadonlyArray<SystemUseExample>;
92
219
  };
93
220
  /**
94
- * Logging configuration.
221
+ * Logging configuration for inbound tool calls and their responses.
222
+ * All logging uses the Node-in-Layers logger already present in the context.
95
223
  */
96
224
  logging?: {
97
225
  /**
98
- * The log level for requests.
226
+ * Log level used when logging the incoming tool request.
227
+ * Defaults to `'info'`.
228
+ * One of the `LogLevelNames` string literals from `@node-in-layers/core`
229
+ * (e.g. `'info'`, `'warn'`, `'error'`, `'debug'`).
99
230
  */
100
231
  requestLogLevel?: LogLevelNames;
101
232
  /**
102
- * The log level for responses.
233
+ * Log level used when logging the tool response.
234
+ * Defaults to `'info'`.
235
+ * One of the `LogLevelNames` string literals from `@node-in-layers/core`
236
+ * (e.g. `'info'`, `'warn'`, `'error'`, `'debug'`).
103
237
  */
104
238
  responseLogLevel?: LogLevelNames;
105
239
  /**
106
- * The data to get for requests.
240
+ * Optional callback that extracts additional structured fields to merge
241
+ * into the request log entry. Return a plain object of key/value pairs.
107
242
  */
108
243
  requestLogGetData?: (req: Request) => Record<string, any>;
109
244
  /**
110
- * The data to get for responses.
245
+ * Optional callback that extracts additional structured fields to merge
246
+ * into the response log entry. Return a plain object of key/value pairs.
111
247
  */
112
248
  responseLogGetData?: (req: Request) => Record<string, any>;
113
249
  };
114
250
  };
115
251
  }>;
116
- export declare const McpNamespace = "@node-in-layers/mcp-server";
252
+ /**
253
+ * @interface
254
+ * Schema-only metadata for an MCP tool — everything except the `execute`
255
+ * handler. Used when building tool definitions before the execute function is
256
+ * attached (e.g. in `nil.ts` / `models.ts` helper factories).
257
+ *
258
+ * @see {@link McpTool}
259
+ */
260
+ export type McpToolSchema = Readonly<{
261
+ /** Unique tool name as it appears in the MCP tool listing. */
262
+ name: string;
263
+ /** Description shown to the AI client to explain what this tool does. */
264
+ description?: string;
265
+ /**
266
+ * JSON Schema (or Zod schema) describing the tool's input object.
267
+ * The SDK validates incoming tool calls against this schema before invoking
268
+ * the execute handler.
269
+ */
270
+ inputSchema: any;
271
+ /**
272
+ * Optional JSON Schema describing the tool's output object.
273
+ * Provided for documentation/type-generation purposes; the MCP SDK does not
274
+ * currently enforce it at runtime.
275
+ */
276
+ outputSchema?: any;
277
+ }>;
278
+ /**
279
+ * @interface
280
+ * A fully-defined MCP tool: schema metadata plus an execute handler.
281
+ *
282
+ * The `execute` function is called by the server for every matching tool
283
+ * invocation. The second argument (`crossLayerProps`) carries the merged
284
+ * {@link RequestCrossLayerProps} for the request, including `requestInfo`,
285
+ * `authInfo`, and logger correlation IDs.
286
+ *
287
+ * @example
288
+ * ```ts
289
+ * const myTool: McpTool = {
290
+ * name: 'greet',
291
+ * description: 'Returns a greeting.',
292
+ * inputSchema: { type: 'object', properties: { name: { type: 'string' } } },
293
+ * execute: async (input, crossLayerProps) => createMcpResponse({ hello: input.name }),
294
+ * }
295
+ * ```
296
+ *
297
+ * @see {@link McpToolSchema}
298
+ * @see {@link RequestCrossLayerProps}
299
+ */
300
+ export type McpTool = McpToolSchema & Readonly<{
301
+ /**
302
+ * Async handler invoked for each tool call.
303
+ *
304
+ * @param input - The validated tool arguments as received from the AI client.
305
+ * Will always contain a `crossLayerProps` field injected by the server
306
+ * (merged from the client-supplied value, the HTTP transport headers, and
307
+ * auth info).
308
+ * @param crossLayerProps - The fully-merged {@link RequestCrossLayerProps} for
309
+ * this request. Passed as a convenience — identical to `input.crossLayerProps`.
310
+ */
311
+ execute: (input: any, crossLayerProps?: any) => Promise<CallToolResult>;
312
+ }>;
313
+ /**
314
+ * @interface
315
+ * An additional Express route to mount on the HTTP server alongside the MCP
316
+ * endpoint. Useful for health checks, webhooks, or any non-MCP HTTP traffic
317
+ * that should share the same process.
318
+ *
319
+ * @example
320
+ * ```ts
321
+ * const healthRoute: ExpressRoute = {
322
+ * path: '/health',
323
+ * method: 'GET',
324
+ * handler: async (_req, res) => { res.json({ ok: true }) },
325
+ * }
326
+ * ```
327
+ */
328
+ export type ExpressRoute = Readonly<{
329
+ /** URL path for the route (e.g. `'/health'`). */
330
+ path: string;
331
+ /** HTTP method for the route. */
332
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE';
333
+ /** Async Express request handler. */
334
+ handler: (req: express.Request, res: express.Response) => Promise<void>;
335
+ }>;
336
+ /**
337
+ * An Express middleware function to mount before the MCP route handler.
338
+ * Standard use-cases include authentication, request logging, and rate limiting.
339
+ *
340
+ * @example
341
+ * ```ts
342
+ * const authMiddleware: ExpressMiddleware = async (req, res, next) => {
343
+ * if (!req.headers.authorization) {
344
+ * res.status(401).json({ error: 'Unauthorized' })
345
+ * return
346
+ * }
347
+ * await next()
348
+ * }
349
+ * ```
350
+ */
351
+ export type ExpressMiddleware = (req: express.Request, res: express.Response, next: express.NextFunction) => Promise<void>;
352
+ /**
353
+ * @interface
354
+ * Full Express configuration accepted when building the HTTP app via
355
+ * `getApp()` or `start()`.
356
+ *
357
+ * @see {@link McpServerMcp.getApp}
358
+ */
359
+ export type ExpressOptions = Readonly<{
360
+ /** Additional routes to mount on the Express app. @see {@link ExpressRoute} */
361
+ additionalRoutes?: ExpressRoute[];
362
+ /** Middleware to run before the MCP route handler. @see {@link ExpressMiddleware} */
363
+ preRouteMiddleware?: ExpressMiddleware[];
364
+ /**
365
+ * Optional callback invoked after every route handler completes.
366
+ * Useful for post-request instrumentation or cleanup.
367
+ */
368
+ afterRouteCallback?: (req: express.Request, res: express.Response) => Promise<void> | void;
369
+ /** Body-size limit forwarded to `body-parser` (e.g. `'10mb'`). */
370
+ limit?: string;
371
+ /** Fine-grained options passed directly to `bodyParser.json()`. */
372
+ jsonBodyParser?: {
373
+ /** Maximum request body size (e.g. `'1mb'`). */
374
+ limit?: string;
375
+ /** When `false`, allows non-object/array JSON at the top level. */
376
+ strict?: boolean;
377
+ };
378
+ }>;
379
+ /**
380
+ * @interface
381
+ * Subset of {@link ExpressOptions} accepted by `start()` and `getApp()` on the
382
+ * public API. Currently covers only the `jsonBodyParser` settings; additional
383
+ * options (routes, middleware) are registered via dedicated methods instead.
384
+ *
385
+ * @see {@link McpServerMcp.start}
386
+ * @see {@link McpServerMcp.getApp}
387
+ */
388
+ export type AppOptions = Readonly<{
389
+ /** Fine-grained options passed directly to `bodyParser.json()`. */
390
+ jsonBodyParser?: {
391
+ /** Maximum request body size (e.g. `'1mb'`). */
392
+ limit?: string;
393
+ /** When `false`, allows non-object/array JSON at the top level. */
394
+ strict?: boolean;
395
+ };
396
+ }>;
397
+ /**
398
+ * @interface
399
+ * HTTP request metadata extracted from the MCP transport layer and made
400
+ * available to every tool call via {@link RequestCrossLayerProps}.
401
+ *
402
+ * For HTTP connections, `headers` is populated from the live HTTP request
403
+ * (via the MCP SDK's `RequestHandlerExtra.requestInfo`). The remaining fields
404
+ * (`body`, `query`, `params`, `path`, `method`, `url`, `protocol`) are
405
+ * populated when an Express request is available; for CLI (stdio) connections
406
+ * they default to empty strings / empty objects.
407
+ */
408
+ export type RequestInfo = Readonly<{
409
+ /** Normalised HTTP request headers (all values coerced to strings). */
410
+ headers: Record<string, string>;
411
+ /** Parsed request body (JSON object). Empty object for CLI connections. */
412
+ body: Record<string, any>;
413
+ /** Parsed query-string parameters. Empty object for CLI connections. */
414
+ query: Record<string, string>;
415
+ /** URL path parameters (e.g. from `/users/:id`). Empty object for CLI connections. */
416
+ params: Record<string, string>;
417
+ /** URL path component (e.g. `'/mcp'`). Empty string for CLI connections. */
418
+ path: string;
419
+ /** HTTP method in upper-case (e.g. `'POST'`). Empty string for CLI connections. */
420
+ method: string;
421
+ /** Full request URL including query string. Empty string for CLI connections. */
422
+ url: string;
423
+ /** Protocol (e.g. `'http'` or `'https'`). Empty string for CLI connections. */
424
+ protocol: string;
425
+ }>;
426
+ /**
427
+ * @interface
428
+ * OAuth / token auth information for the current request, sourced from the
429
+ * MCP SDK's `RequestHandlerExtra.authInfo`. Only present when the MCP server
430
+ * is configured with an OAuth provider and the client has authenticated.
431
+ *
432
+ * @see {@link RequestCrossLayerProps}
433
+ */
434
+ export type AuthInfo = Readonly<{
435
+ /** The raw bearer access token string. */
436
+ token: string;
437
+ /** The OAuth client ID that obtained this token. */
438
+ clientId: string;
439
+ /** Scopes granted to this token (e.g. `['read', 'write']`). */
440
+ scopes: string[];
441
+ /**
442
+ * Unix timestamp (seconds since epoch) at which the token expires.
443
+ * Omitted if the token has no expiry.
444
+ */
445
+ expiresAt?: number;
446
+ /**
447
+ * The RFC 8707 resource server identifier for which this token is valid.
448
+ * When set, must match the MCP server's own resource identifier.
449
+ */
450
+ resource?: URL;
451
+ /** Any additional provider-specific data attached to the token. */
452
+ extra?: Record<string, unknown>;
453
+ }>;
454
+ /**
455
+ * @interface
456
+ * The cross-layer props shape used throughout `@node-in-layers/mcp-server`.
457
+ * Extends the base `CrossLayerProps` from `@node-in-layers/core` with MCP-specific request context.
458
+ *
459
+ * This object is automatically built and merged by the server on every tool
460
+ * call — you should never construct it manually. Use `combineCrossLayerProps`
461
+ * or `createCrossLayerProps` from `@node-in-layers/core` if you need to merge
462
+ * additional data into an existing instance.
463
+ *
464
+ * Sources merged into every tool call (in order):
465
+ * 1. `crossLayerProps` supplied by the AI client in the tool arguments
466
+ * 2. `crossLayerProps` nested inside `args` (used by feature-executor tools)
467
+ * 3. `requestInfo` from the HTTP transport (headers) and `authInfo` if present
468
+ * 4. Logger correlation IDs from the per-request logger
469
+ *
470
+ * @example
471
+ * ```ts
472
+ * // Accessing in a feature function:
473
+ * const myFeature = async (args: MyArgs, crossLayerProps: McpCrossLayerProps) => {
474
+ * const { headers } = crossLayerProps.requestInfo
475
+ * const token = crossLayerProps.authInfo?.token
476
+ * // ...
477
+ * }
478
+ * ```
479
+ *
480
+ * @see {@link RequestInfo}
481
+ * @see {@link AuthInfo}
482
+ */
483
+ export type RequestCrossLayerProps = Readonly<{
484
+ /** HTTP request metadata for the current tool call. @see {@link RequestInfo} */
485
+ requestInfo: RequestInfo;
486
+ /**
487
+ * OAuth auth info for the current request, if the server is configured with
488
+ * an OAuth provider and the client has authenticated.
489
+ * @see {@link AuthInfo}
490
+ */
491
+ authInfo?: AuthInfo;
492
+ }> & CrossLayerProps;
493
+ /**
494
+ * @interface
495
+ * The public interface returned by `create()` in `mcp.ts` and stored in the
496
+ * MCP layer of the Node-in-Layers system context.
497
+ *
498
+ * Typical usage:
499
+ * ```ts
500
+ * const mcpServer = mcp.create(context)
501
+ * mcpServer.addTool(myTool)
502
+ * await mcpServer.start(systemContext)
503
+ * ```
504
+ */
117
505
  export type McpServerMcp = Readonly<{
506
+ /**
507
+ * Starts the MCP server. For HTTP connections, binds an Express app to the
508
+ * configured port. For CLI connections, connects the stdio transport.
509
+ *
510
+ * @param systemContext - The fully-initialised Node-in-Layers system context,
511
+ * used to resolve features and models at runtime.
512
+ * @param options - Optional Express body-parser settings.
513
+ */
118
514
  start: <T extends McpServerConfig & Config>(systemContext: LayerContext<T, any>, options?: AppOptions) => Promise<void>;
119
- addTool: (tool: ServerTool) => void;
120
- getApp: (options?: AppOptions) => Express;
515
+ /**
516
+ * Registers a custom {@link McpTool} with the server. Call this before
517
+ * `start()` or `getApp()`.
518
+ *
519
+ * @param tool - The tool definition to register.
520
+ */
521
+ addTool: (tool: McpTool) => void;
522
+ /**
523
+ * Builds and returns the configured Express app without starting the HTTP
524
+ * listener. Useful when you want to integrate the MCP server into an existing
525
+ * Express application or test the app directly.
526
+ *
527
+ * Throws if the connection type is not `'http'`.
528
+ *
529
+ * @param systemContext - The fully-initialised Node-in-Layers system context.
530
+ * @param options - Optional Express body-parser settings.
531
+ */
532
+ getApp: <T extends McpServerConfig & Config>(systemContext: LayerContext<T, any>, options?: AppOptions) => Promise<express.Express>;
533
+ /**
534
+ * Calls `app.set(key, value)` on the underlying Express app. Must be called
535
+ * before `start()` or `getApp()`.
536
+ *
537
+ * @param key - Express setting name (e.g. `'trust proxy'`).
538
+ * @param value - Value to assign.
539
+ */
121
540
  set: (key: string, value: any) => void;
541
+ /**
542
+ * Registers an Express middleware to run before the MCP route handler.
543
+ * Useful for auth, logging, or rate-limiting. Must be called before
544
+ * `start()` or `getApp()`.
545
+ *
546
+ * @param middleware - An {@link ExpressMiddleware} function.
547
+ */
122
548
  addPreRouteMiddleware: (middleware: ExpressMiddleware) => void;
549
+ /**
550
+ * Registers an additional Express route alongside the MCP endpoint. Must be
551
+ * called before `start()` or `getApp()`.
552
+ *
553
+ * @param route - An {@link ExpressRoute} definition.
554
+ */
123
555
  addAdditionalRoute: (route: ExpressRoute) => void;
124
556
  }>;
557
+ /**
558
+ * @interface
559
+ * The MCP layer slice of the Node-in-Layers system context, keyed by
560
+ * {@link McpNamespace}.
561
+ */
125
562
  export type McpServerMcpLayer = Readonly<{
126
563
  [McpNamespace]: McpServerMcp;
127
564
  }>;
128
- export type AppOptions = Readonly<{
129
- jsonBodyParser?: {
130
- limit?: string;
131
- strict?: boolean;
132
- };
133
- }>;
565
+ /**
566
+ * The full Node-in-Layers `LayerContext` shape expected by MCP server
567
+ * internals. Parameterised over config, features, and any additional MCP-layer
568
+ * services the consuming application adds.
569
+ *
570
+ * @template TConfig - System config type (must extend `Config`).
571
+ * @template TFeatures - Features layer shape (domain → feature functions).
572
+ * @template TMcpLayer - Any additional entries in the MCP layer beyond the
573
+ * built-in `McpServerMcpLayer`.
574
+ */
134
575
  export type McpContext<TConfig extends Config = Config, TFeatures extends object = object, TMcpLayer extends object = object> = LayerContext<TConfig, {
135
576
  features: TFeatures;
136
577
  mcp: McpServerMcpLayer & TMcpLayer;
137
578
  }>;
579
+ /**
580
+ * @interface
581
+ * A simplified OpenAPI-style description of a single function, used to
582
+ * generate tool input/output schemas for non-NIL-annotated features.
583
+ */
138
584
  export type OpenApiFunctionDescription = Readonly<{
585
+ /** Function name as it appears in the tool listing. */
139
586
  name: string;
587
+ /** Optional description shown to the AI client. */
140
588
  description?: string;
589
+ /** JSON Schema object describing the function's input. */
141
590
  input: Record<string, JsonAble>;
591
+ /** JSON Schema object describing the function's output. */
142
592
  output: Record<string, JsonAble>;
143
593
  }>;
144
- export {};
594
+ /**
595
+ * @interface
596
+ * A lightweight optional-value container (similar to `Option<T>` in functional
597
+ * languages). Avoids returning `null` / `undefined` directly from functions
598
+ * that may not produce a value.
599
+ *
600
+ * @template T - The type of the wrapped value.
601
+ *
602
+ * @example
603
+ * ```ts
604
+ * const maybeUser: Maybe<User> = findUser(id)
605
+ * if (maybeUser.hasValue()) {
606
+ * const user = maybeUser.instance()
607
+ * }
608
+ * ```
609
+ */
610
+ export type Maybe<T> = Readonly<{
611
+ /** Returns the wrapped value, or `undefined` if absent. */
612
+ instance: () => T | undefined;
613
+ /** Returns `true` if a value is present. */
614
+ hasValue: () => boolean;
615
+ }>;
package/types.js CHANGED
@@ -1,2 +1,16 @@
1
+ /**
2
+ * The namespace key used to scope all `@node-in-layers/mcp-server` configuration
3
+ * inside the system config object.
4
+ *
5
+ * @example
6
+ * ```ts
7
+ * const config = {
8
+ * [McpNamespace]: {
9
+ * version: '1.0.0',
10
+ * server: { connection: { type: 'http', url: 'http://localhost:3000' } },
11
+ * },
12
+ * }
13
+ * ```
14
+ */
1
15
  export const McpNamespace = '@node-in-layers/mcp-server';
2
16
  //# sourceMappingURL=types.js.map
package/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAgIA,MAAM,CAAC,MAAM,YAAY,GAAG,4BAA4B,CAAA"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAWA;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,4BAA4B,CAAA"}