tmcp 1.9.1 → 1.10.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tmcp",
3
- "version": "1.9.1",
3
+ "version": "1.10.1",
4
4
  "description": "The main tmcp library",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
package/src/index.js CHANGED
@@ -4,7 +4,7 @@
4
4
  * @import { JSONRPCRequest, JSONRPCParams } from "json-rpc-2.0";
5
5
  * @import { ExtractURITemplateVariables } from "./internal/uri-template.js";
6
6
  * @import { CallToolResult, ReadResourceResult, GetPromptResult, ClientCapabilities as ClientCapabilitiesType, JSONRPCRequest as JSONRPCRequestType, JSONRPCResponse, CreateMessageRequestParams, CreateMessageResult, Resource, LoggingLevel, ToolAnnotations } from "./validation/index.js";
7
- * @import { Tool, Completion, Prompt, StoredResource, ServerOptions, ServerInfo, SubscriptionsKeys, McpEvents, Context as ContextType } from "./internal/internal.js";
7
+ * @import { Tool, Completion, Prompt, StoredResource, ServerOptions, ServerInfo, SubscriptionsKeys, McpEvents } from "./internal/internal.js";
8
8
  */
9
9
  import { JSONRPCClient, JSONRPCServer } from 'json-rpc-2.0';
10
10
  import { AsyncLocalStorage } from 'node:async_hooks';
@@ -92,7 +92,7 @@ export class McpServer {
92
92
  #client;
93
93
  #options;
94
94
  /**
95
- * @type {Map<string, Tool<any>>}
95
+ * @type {Map<string, Tool<any, any>>}
96
96
  */
97
97
  #tools = new Map();
98
98
  /**
@@ -328,12 +328,25 @@ export class McpServer {
328
328
  name,
329
329
  title: tool.title || tool.description,
330
330
  description: tool.description,
331
- annotations: tool.annotations,
331
+
332
332
  inputSchema: tool.schema
333
333
  ? await this.#options.adapter.toJsonSchema(
334
334
  tool.schema,
335
335
  )
336
336
  : { type: 'object', properties: {} },
337
+ ...(tool.outputSchema
338
+ ? {
339
+ outputSchema:
340
+ await this.#options.adapter.toJsonSchema(
341
+ tool.outputSchema,
342
+ ),
343
+ }
344
+ : {}),
345
+ ...(tool.annotations
346
+ ? {
347
+ annotations: tool.annotations,
348
+ }
349
+ : {}),
337
350
  };
338
351
  }),
339
352
  );
@@ -348,22 +361,55 @@ export class McpServer {
348
361
  if (!tool) {
349
362
  throw new McpError(-32601, `Tool ${name} not found`);
350
363
  }
351
- if (!tool.schema) {
352
- return v.parse(CallToolResultSchema, await tool.execute());
353
- }
354
- let validated_args = tool.schema['~standard'].validate(args);
355
- if (validated_args instanceof Promise)
356
- validated_args = await validated_args;
357
- if (validated_args.issues) {
358
- throw new McpError(
359
- -32602,
360
- `Invalid arguments for tool ${name}: ${JSON.stringify(validated_args.issues)}`,
361
- );
364
+
365
+ // Validate input arguments if schema is provided
366
+ let validated_args = args;
367
+ if (tool.schema) {
368
+ let validation_result =
369
+ tool.schema['~standard'].validate(args);
370
+ if (validation_result instanceof Promise)
371
+ validation_result = await validation_result;
372
+ if (validation_result.issues) {
373
+ throw new McpError(
374
+ -32602,
375
+ `Invalid arguments for tool ${name}: ${JSON.stringify(validation_result.issues)}`,
376
+ );
377
+ }
378
+ validated_args = validation_result.value;
362
379
  }
363
- return v.parse(
380
+
381
+ // Execute the tool
382
+ const tool_result = tool.schema
383
+ ? await tool.execute(validated_args)
384
+ : await tool.execute();
385
+
386
+ // Parse the basic result structure
387
+ const parsed_result = v.parse(
364
388
  CallToolResultSchema,
365
- await tool.execute(validated_args.value),
389
+ tool_result,
366
390
  );
391
+
392
+ // If tool has outputSchema, validate and populate structuredContent
393
+ if (
394
+ tool.outputSchema &&
395
+ parsed_result.structuredContent !== undefined
396
+ ) {
397
+ let output_validation = tool.outputSchema[
398
+ '~standard'
399
+ ].validate(parsed_result.structuredContent);
400
+ if (output_validation instanceof Promise)
401
+ output_validation = await output_validation;
402
+ if (output_validation.issues) {
403
+ throw new McpError(
404
+ -32603,
405
+ `Tool ${name} returned invalid structured content: ${JSON.stringify(output_validation.issues)}`,
406
+ );
407
+ }
408
+ // Update with validated structured content
409
+ parsed_result.structuredContent = output_validation.value;
410
+ }
411
+
412
+ return parsed_result;
367
413
  },
368
414
  );
369
415
  }
@@ -627,10 +673,14 @@ export class McpServer {
627
673
  }
628
674
  /**
629
675
  * @template {StandardSchema | undefined} [TSchema=undefined]
630
- * @param {{ name: string; description: string; title?: string; schema?: StandardSchemaV1.InferInput<TSchema extends undefined ? never : TSchema> extends Record<string, unknown> ? TSchema : never; annotations?: ToolAnnotations }} options
631
- * @param {TSchema extends undefined ? (()=>Promise<CallToolResult> | CallToolResult) : ((input: StandardSchemaV1.InferInput<TSchema extends undefined ? never : TSchema>) => Promise<CallToolResult> | CallToolResult)} execute
676
+ * @template {StandardSchema | undefined} [TOutputSchema=undefined]
677
+ * @param {{ name: string; description: string; title?: string; schema?: StandardSchemaV1.InferInput<TSchema extends undefined ? never : TSchema> extends Record<string, unknown> ? TSchema : never; outputSchema?: StandardSchemaV1.InferOutput<TOutputSchema extends undefined ? never : TOutputSchema> extends Record<string, unknown> ? TOutputSchema : never; annotations?: ToolAnnotations }} options
678
+ * @param {TSchema extends undefined ? (()=>Promise<CallToolResult<TOutputSchema extends undefined ? undefined : StandardSchemaV1.InferInput<TOutputSchema extends undefined ? never : TOutputSchema>>> | CallToolResult<TOutputSchema extends undefined ? undefined : StandardSchemaV1.InferInput<TOutputSchema extends undefined ? never : TOutputSchema>>) : ((input: StandardSchemaV1.InferInput<TSchema extends undefined ? never : TSchema>) => Promise<CallToolResult<TOutputSchema extends undefined ? undefined : StandardSchemaV1.InferInput<TOutputSchema extends undefined ? never : TOutputSchema>>> | CallToolResult<TOutputSchema extends undefined ? undefined : StandardSchemaV1.InferInput<TOutputSchema extends undefined ? never : TOutputSchema>>)} execute
632
679
  */
633
- tool({ name, description, title, schema, annotations }, execute) {
680
+ tool(
681
+ { name, description, title, schema, outputSchema, annotations },
682
+ execute,
683
+ ) {
634
684
  if (this.#options.capabilities?.tools?.listChanged) {
635
685
  this.#notify('notifications/tools/list_changed', {});
636
686
  }
@@ -638,6 +688,7 @@ export class McpServer {
638
688
  description,
639
689
  title,
640
690
  schema,
691
+ outputSchema,
641
692
  execute,
642
693
  annotations,
643
694
  });
@@ -13,9 +13,10 @@ import {
13
13
  ToolAnnotations
14
14
  } from '../validation/index.js';
15
15
 
16
- export type Tool<TSchema extends StandardSchemaV1 = StandardSchemaV1<any>> = {
16
+ export type Tool<TSchema extends StandardSchemaV1 = StandardSchemaV1<any>, TOutputSchema extends StandardSchemaV1 = StandardSchemaV1<any>> = {
17
17
  description: string;
18
18
  schema: TSchema;
19
+ outputSchema?: TOutputSchema;
19
20
  title?: string;
20
21
  annotations?: ToolAnnotations;
21
22
  execute: (
@@ -23,13 +23,14 @@ declare module 'tmcp' {
23
23
 
24
24
  on<TEvent extends keyof McpEvents>(event: TEvent, callback: McpEvents[TEvent], options?: AddEventListenerOptions): () => void;
25
25
 
26
- tool<TSchema extends StandardSchema | undefined = undefined>({ name, description, title, schema, annotations }: {
26
+ tool<TSchema extends StandardSchema | undefined = undefined, TOutputSchema extends StandardSchema | undefined = undefined>({ name, description, title, schema, outputSchema, annotations }: {
27
27
  name: string;
28
28
  description: string;
29
29
  title?: string;
30
30
  schema?: StandardSchemaV1.InferInput<TSchema extends undefined ? never : TSchema> extends Record<string, unknown> ? TSchema : never;
31
+ outputSchema?: StandardSchemaV1.InferOutput<TOutputSchema extends undefined ? never : TOutputSchema> extends Record<string, unknown> ? TOutputSchema : never;
31
32
  annotations?: ToolAnnotations;
32
- }, execute: TSchema extends undefined ? (() => Promise<CallToolResult> | CallToolResult) : ((input: StandardSchemaV1.InferInput<TSchema extends undefined ? never : TSchema>) => Promise<CallToolResult> | CallToolResult)): void;
33
+ }, execute: TSchema extends undefined ? (() => Promise<CallToolResult<TOutputSchema extends undefined ? undefined : StandardSchemaV1.InferInput<TOutputSchema extends undefined ? never : TOutputSchema>>> | CallToolResult<TOutputSchema extends undefined ? undefined : StandardSchemaV1.InferInput<TOutputSchema extends undefined ? never : TOutputSchema>>) : ((input: StandardSchemaV1.InferInput<TSchema extends undefined ? never : TSchema>) => Promise<CallToolResult<TOutputSchema extends undefined ? undefined : StandardSchemaV1.InferInput<TOutputSchema extends undefined ? never : TOutputSchema>>> | CallToolResult<TOutputSchema extends undefined ? undefined : StandardSchemaV1.InferInput<TOutputSchema extends undefined ? never : TOutputSchema>>)): void;
33
34
 
34
35
  prompt<TSchema extends StandardSchema | undefined = undefined>({ name, description, title, schema, complete }: {
35
36
  name: string;
@@ -895,7 +896,11 @@ declare module 'tmcp' {
895
896
  type ClientCapabilities_1 = v.InferInput<typeof ClientCapabilitiesSchema>;
896
897
  type ServerCapabilities = v.InferInput<typeof ServerCapabilitiesSchema>;
897
898
  type InitializeRequestParams = v.InferInput<typeof InitializeRequestParamsSchema>;
898
- type CallToolResult = v.InferInput<typeof CallToolResultSchema>;
899
+ type CallToolResult<TStructuredContent extends Record<string, unknown> | undefined> = Omit<v.InferInput<typeof CallToolResultSchema>, "structuredContent"> & (undefined extends TStructuredContent ? {
900
+ structuredContent?: undefined;
901
+ } : {
902
+ structuredContent: TStructuredContent;
903
+ });
899
904
  type ReadResourceResult = v.InferInput<typeof ReadResourceResultSchema>;
900
905
  type GetPromptResult = v.InferInput<typeof GetPromptResultSchema>;
901
906
  type CompleteResult = v.InferInput<typeof CompleteResultSchema>;
@@ -24,7 +24,6 @@
24
24
  "CompleteResultSchema",
25
25
  "ServerCapabilities",
26
26
  "InitializeRequestParams",
27
- "CallToolResult",
28
27
  "ReadResourceResult",
29
28
  "GetPromptResult",
30
29
  "CompleteResult",
@@ -56,6 +55,6 @@
56
55
  null,
57
56
  null
58
57
  ],
59
- "mappings": ";;;;;cAsFaA,SAASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aCi3CsCC,kBAAkBA;MC96ClEC,UAAUA;;;;;MAsCVC,aAAaA;;;;;;;;;;;;;MAabC,UAAUA;;;;;;MAMVC,iBAAiBA;;MAEjBC,SAASA;;;;;;;;;;;;ODgBRC,qBAAqBA;;;;;;;;;;;;;;OAuGrBC,wBAAwBA;;;;;;;;;;;;;;;;;;;;;;;OA6BxBC,6BAA6BA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuB7BC,wBAAwBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmMxBC,cAAcA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4GdC,wBAAwBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8PxBC,qBAAqBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BrBC,qBAAqBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2GrBC,oBAAoBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAoEpBC,kBAAkBA;OAuGlBC,gCAAgCA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8ChCC,yBAAyBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+LzBC,oBAAoBA;;;;;;;;;;;;;;;;;;;;;;MA8H2BC,kBAAkBA;MASbC,uBAAuBA;MAGhCC,cAAcA;MAGVC,kBAAkBA;MAGrBC,eAAeA;MAGhBC,cAAcA;MAGFC,0BAA0BA;MAGjCC,mBAAmBA;MAY9BC,QAAQA;MAMDC,eAAeA;MAGlBC,YAAYA;MAGTC,eAAeA;;ME5/CnEC,IAAIA;;;;;;;MAOJC,cAAcA;;;;;;;MAOdC,cAAcA;;;;;MAKdC,qBAAqBA;;;;;;;;;;;;;;;;;MAiBrBC,4BAA4BA;;;;;;MAMrBC,2BAA2BA;;;;;;;OCjC1BC,iBAAiBA;;;;;;;;;;;;;;;;cAAjBA,iBAAiBA",
58
+ "mappings": ";;;;;cAsFaA,SAASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aCi3CsCC,kBAAkBA;MC76ClEC,UAAUA;;;;;MAsCVC,aAAaA;;;;;;;;;;;;;MAabC,UAAUA;;;;;;MAMVC,iBAAiBA;;MAEjBC,SAASA;;;;;;;;;;;;ODeRC,qBAAqBA;;;;;;;;;;;;;;OAuGrBC,wBAAwBA;;;;;;;;;;;;;;;;;;;;;;;OA6BxBC,6BAA6BA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuB7BC,wBAAwBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmMxBC,cAAcA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4GdC,wBAAwBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8PxBC,qBAAqBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BrBC,qBAAqBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2GrBC,oBAAoBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAoEpBC,kBAAkBA;OAuGlBC,gCAAgCA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8ChCC,yBAAyBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+LzBC,oBAAoBA;;;;;;;;;;;;;;;;;;;;;;MA8H2BC,kBAAkBA;MASbC,uBAAuBA;;;;;;MAO5BC,kBAAkBA;MAGrBC,eAAeA;MAGhBC,cAAcA;MAGFC,0BAA0BA;MAGjCC,mBAAmBA;MAY9BC,QAAQA;MAMDC,eAAeA;MAGlBC,YAAYA;MAGTC,eAAeA;;ME7/CnEC,IAAIA;;;;;;;MAOJC,cAAcA;;;;;;;MAOdC,cAAcA;;;;;MAKdC,qBAAqBA;;;;;;;;;;;;;;;;;MAiBrBC,4BAA4BA;;;;;;MAMrBC,2BAA2BA;;;;;;;OCjC1BC,iBAAiBA;;;;;;;;;;;;;;;;cAAjBA,iBAAiBA",
60
59
  "ignoreList": []
61
60
  }
@@ -1492,7 +1492,8 @@ export const ServerResultSchema = v.union([
1492
1492
  * @typedef {v.InferInput<typeof InitializeRequestParamsSchema>} InitializeRequestParams
1493
1493
  */
1494
1494
  /**
1495
- * @typedef {v.InferInput<typeof CallToolResultSchema>} CallToolResult
1495
+ * @template {Record<string, unknown> | undefined} TStructuredContent
1496
+ * @typedef {Omit<v.InferInput<typeof CallToolResultSchema>, "structuredContent"> & (undefined extends TStructuredContent ? { structuredContent?: undefined } : { structuredContent: TStructuredContent })} CallToolResult
1496
1497
  */
1497
1498
  /**
1498
1499
  * @typedef {v.InferInput<typeof ReadResourceResultSchema>} ReadResourceResult