tmcp 1.12.0 → 1.12.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/README.md CHANGED
@@ -201,12 +201,78 @@ server.template(
201
201
  );
202
202
  ```
203
203
 
204
- ##### `receive(request, sessionId)`
204
+ ##### `withContext<T>()`
205
205
 
206
- Process an incoming MCP request.
206
+ Specify the type of custom context for type-safe access to application-specific data.
207
207
 
208
208
  ```javascript
209
- const response = server.receive(jsonRpcRequest, sessionId);
209
+ interface MyCustomContext {
210
+ userId: string;
211
+ permissions: string[];
212
+ database: DatabaseConnection;
213
+ }
214
+
215
+ const server = new McpServer(serverInfo, options).withContext<MyCustomContext>();
216
+
217
+ // Now you can access typed custom context in handlers
218
+ server.tool(
219
+ {
220
+ name: 'get-user-data',
221
+ description: 'Get current user data',
222
+ },
223
+ async () => {
224
+ const { userId, database } = server.ctx.custom!;
225
+ const userData = await database.users.findById(userId);
226
+ return {
227
+ content: [{ type: 'text', text: JSON.stringify(userData) }],
228
+ };
229
+ },
230
+ );
231
+ ```
232
+
233
+ ##### `ctx`
234
+
235
+ Access the current request context, including session ID, auth info, and custom context.
236
+
237
+ ```javascript
238
+ server.tool(
239
+ {
240
+ name: 'context-aware-tool',
241
+ description: 'Tool that uses request context',
242
+ },
243
+ async () => {
244
+ const { sessionId, auth, custom } = server.ctx;
245
+
246
+ if (!custom?.userId) {
247
+ throw new Error('User authentication required');
248
+ }
249
+
250
+ return {
251
+ content: [
252
+ {
253
+ type: 'text',
254
+ text: `Hello user ${custom.userId} in session ${sessionId}`,
255
+ },
256
+ ],
257
+ };
258
+ },
259
+ );
260
+ ```
261
+
262
+ ##### `receive(request, context?)`
263
+
264
+ Process an incoming MCP request with optional context.
265
+
266
+ ```javascript
267
+ // Basic usage
268
+ const response = server.receive(jsonRpcRequest);
269
+
270
+ // With custom context (typically used by transports)
271
+ const response = server.receive(jsonRpcRequest, {
272
+ sessionId: 'session-123',
273
+ auth: authInfo,
274
+ custom: customContextData,
275
+ });
210
276
  ```
211
277
 
212
278
  ##### `elicitation(schema)`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tmcp",
3
- "version": "1.12.0",
3
+ "version": "1.12.1",
4
4
  "description": "The main tmcp library",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
package/src/index.js CHANGED
@@ -5,7 +5,7 @@
5
5
  * @import { JSONRPCRequest, JSONRPCParams } from "json-rpc-2.0";
6
6
  * @import { ExtractURITemplateVariables } from "./internal/uri-template.js";
7
7
  * @import { CallToolResult, ReadResourceResult, GetPromptResult, ClientCapabilities as ClientCapabilitiesType, JSONRPCRequest as JSONRPCRequestType, JSONRPCResponse, CreateMessageRequestParams, CreateMessageResult, Resource, LoggingLevel, ToolAnnotations, ClientInfo } from "./validation/index.js";
8
- * @import { Tool, Completion, Prompt, StoredResource, ServerOptions, ServerInfo, SubscriptionsKeys, McpEvents } from "./internal/internal.js";
8
+ * @import { Tool, Completion, Prompt, StoredResource, ServerOptions, ServerInfo, SubscriptionsKeys, ChangedArgs, McpEvents } from "./internal/internal.js";
9
9
  */
10
10
  import { JSONRPCClient, JSONRPCServer } from 'json-rpc-2.0';
11
11
  import { AsyncLocalStorage } from 'node:async_hooks';
@@ -762,6 +762,25 @@ export class McpServer {
762
762
  return {};
763
763
  });
764
764
  }
765
+
766
+ #notify_tools_list_changed() {
767
+ if (this.#options.capabilities?.tools?.listChanged) {
768
+ this.#notify('notifications/tools/list_changed', {});
769
+ }
770
+ }
771
+
772
+ #notify_prompts_list_changed() {
773
+ if (this.#options.capabilities?.prompts?.listChanged) {
774
+ this.#notify('notifications/prompts/list_changed', {});
775
+ }
776
+ }
777
+
778
+ #notify_resources_list_changed() {
779
+ if (this.#options.capabilities?.resources?.listChanged) {
780
+ this.#notify('notifications/resources/list_changed', {});
781
+ }
782
+ }
783
+
765
784
  /**
766
785
  * Add a tool to the server. If you want to receive any input you need to provide a schema. The schema needs to be a valid Standard Schema V1 schema and needs to be an Object with the properties you need,
767
786
  * Use the description and title to help the LLM to understand what the tool does and when to use it. If you provide an outputSchema, you need to return a structuredContent that matches the schema.
@@ -784,9 +803,7 @@ export class McpServer {
784
803
  },
785
804
  execute,
786
805
  ) {
787
- if (this.#options.capabilities?.tools?.listChanged) {
788
- this.#notify('notifications/tools/list_changed', {});
789
- }
806
+ this.#notify_tools_list_changed();
790
807
  this.#tools.set(name, {
791
808
  description,
792
809
  title,
@@ -811,9 +828,7 @@ export class McpServer {
811
828
  if (complete) {
812
829
  this.#completions['ref/prompt'].set(name, complete);
813
830
  }
814
- if (this.#options.capabilities?.prompts?.listChanged) {
815
- this.#notify('notifications/prompts/list_changed', {});
816
- }
831
+ this.#notify_prompts_list_changed();
817
832
  this.#prompts.set(name, {
818
833
  description,
819
834
  title,
@@ -832,9 +847,7 @@ export class McpServer {
832
847
  if (resource.template) {
833
848
  this.#templates.add(uri);
834
849
  }
835
- if (this.#options.capabilities?.resources?.listChanged) {
836
- this.#notify('notifications/resources/list_changed', {});
837
- }
850
+ this.#notify_resources_list_changed();
838
851
  this.#resources.set(uri, resource);
839
852
  }
840
853
 
@@ -937,24 +950,40 @@ export class McpServer {
937
950
 
938
951
  /**
939
952
  * Send a notification for subscriptions
940
- * @param {SubscriptionsKeys} what
941
- * @param {string} id
953
+ * @template {keyof ChangedArgs} TWhat
954
+ * @param {[what: TWhat, ...ChangedArgs[TWhat]]} args
942
955
  */
943
- changed(what, id) {
944
- if (this.#subscriptions[what].has(id)) {
945
- const resource = this.#resources.get(id);
946
- if (!resource) return;
947
- const sessions = this.#subscriptions[what].get(id);
948
- this.#notify(
949
- `notifications/resources/updated`,
950
- {
951
- uri: id,
952
- title: resource.name,
953
- },
954
- {
955
- sessions: sessions ? [...sessions] : undefined,
956
- },
957
- );
956
+ changed(...args) {
957
+ const [what, id] = args;
958
+ if (what === 'prompts') {
959
+ this.#notify_prompts_list_changed();
960
+ } else if (what === 'tools') {
961
+ this.#notify_tools_list_changed();
962
+ } else if (what === 'resources') {
963
+ this.#notify_resources_list_changed();
964
+ } else {
965
+ if (
966
+ this.#subscriptions[
967
+ /** @type {SubscriptionsKeys} */ (what)
968
+ ].has(id)
969
+ ) {
970
+ const resource = this.#resources.get(id);
971
+ if (!resource) return;
972
+ const sessions =
973
+ this.#subscriptions[
974
+ /** @type {SubscriptionsKeys} */ (what)
975
+ ].get(id);
976
+ this.#notify(
977
+ `notifications/resources/updated`,
978
+ {
979
+ uri: id,
980
+ title: resource.name,
981
+ },
982
+ {
983
+ sessions: sessions ? [...sessions] : undefined,
984
+ },
985
+ );
986
+ }
958
987
  }
959
988
  }
960
989
 
@@ -85,7 +85,18 @@ export type ServerInfo = {
85
85
  description: string;
86
86
  };
87
87
 
88
- export type SubscriptionsKeys = 'resource';
88
+ export type ChangedArgs = {
89
+ 'resource': [id: string];
90
+ 'tools': [];
91
+ 'prompts': [];
92
+ 'resources': [];
93
+ }
94
+
95
+ type SubscriptionsKeysObj = {
96
+ [K in keyof ChangedArgs as ChangedArgs[K]["length"] extends 0 ? "without_args" : "with_args"]: K
97
+ };
98
+
99
+ export type SubscriptionsKeys = SubscriptionsKeysObj["with_args"];
89
100
 
90
101
  export type McpEvents = {
91
102
  send: (message: {
@@ -107,7 +107,7 @@ declare module 'tmcp' {
107
107
  /**
108
108
  * Send a notification for subscriptions
109
109
  * */
110
- changed(what: SubscriptionsKeys, id: string): void;
110
+ changed<TWhat extends keyof ChangedArgs>(what: TWhat, ...args: ChangedArgs[TWhat]): void;
111
111
  /**
112
112
  * Refresh roots list from client
113
113
  */
@@ -202,7 +202,12 @@ declare module 'tmcp' {
202
202
  description: string;
203
203
  };
204
204
 
205
- type SubscriptionsKeys = 'resource';
205
+ type ChangedArgs = {
206
+ 'resource': [id: string];
207
+ 'tools': [];
208
+ 'prompts': [];
209
+ 'resources': [];
210
+ }
206
211
 
207
212
  type McpEvents = {
208
213
  send: (message: {
@@ -7,7 +7,7 @@
7
7
  "Completion",
8
8
  "ServerOptions",
9
9
  "ServerInfo",
10
- "SubscriptionsKeys",
10
+ "ChangedArgs",
11
11
  "McpEvents",
12
12
  "JSONRPCResponseSchema",
13
13
  "ClientCapabilitiesSchema",
@@ -55,6 +55,6 @@
55
55
  null,
56
56
  null
57
57
  ],
58
- "mappings": ";;;;;cAqGaA,SAASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aCk2CsCC,kBAAkBA;MC56ClEC,UAAUA;;;;;MAyCVC,aAAaA;;;;;;;;;;;;;MAabC,UAAUA;;;;;;MAMVC,iBAAiBA;;MAEjBC,SAASA;;;;;;;;;;;;ODWRC,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",
58
+ "mappings": ";;;;;cAqGaA,SAASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aCk2CsCC,kBAAkBA;MC56ClEC,UAAUA;;;;;MAyCVC,aAAaA;;;;;;;;;;;;;MAabC,UAAUA;;;;;;MAMVC,WAAWA;;;;;;;MAaXC,SAASA;;;;;;;;;;;;ODARC,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",
59
59
  "ignoreList": []
60
60
  }