tmcp 1.15.5 → 1.16.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/README.md +65 -35
- package/package.json +1 -1
- package/src/index.js +71 -137
- package/src/internal/internal.d.ts +6 -3
- package/src/types/index.d.ts +22 -5
- package/src/types/index.d.ts.map +4 -1
- package/src/validation/index.js +1 -2
package/README.md
CHANGED
|
@@ -129,6 +129,8 @@ server.tool(
|
|
|
129
129
|
);
|
|
130
130
|
```
|
|
131
131
|
|
|
132
|
+
`sessionInfo` contains the latest `clientCapabilities`, `clientInfo`, and `logLevel` reported by the connected client. Built-in transports populate it automatically, so every handler can branch on client features without additional bookkeeping.
|
|
133
|
+
|
|
132
134
|
##### `prompt(definition, handler)`
|
|
133
135
|
|
|
134
136
|
Register a prompt template with optional schema validation.
|
|
@@ -232,30 +234,34 @@ server.tool(
|
|
|
232
234
|
|
|
233
235
|
##### `ctx`
|
|
234
236
|
|
|
235
|
-
Access the current request context, including session ID, auth info, and custom context.
|
|
237
|
+
Access the current request context, including session ID, auth info, client metadata, and custom context.
|
|
236
238
|
|
|
237
239
|
```javascript
|
|
238
240
|
server.tool(
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
241
|
+
{
|
|
242
|
+
name: 'context-aware-tool',
|
|
243
|
+
description: 'Tool that uses request context',
|
|
244
|
+
},
|
|
245
|
+
async () => {
|
|
246
|
+
const { sessionId, auth, sessionInfo, custom } = server.ctx;
|
|
247
|
+
|
|
248
|
+
if (!custom?.userId) {
|
|
249
|
+
throw new Error('User authentication required');
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (sessionInfo?.clientInfo) {
|
|
253
|
+
console.log(`Serving ${sessionInfo.clientInfo.name}`);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return {
|
|
257
|
+
content: [
|
|
258
|
+
{
|
|
259
|
+
type: 'text',
|
|
260
|
+
text: `Hello user ${custom.userId} in session ${sessionId}`,
|
|
261
|
+
},
|
|
262
|
+
],
|
|
263
|
+
};
|
|
264
|
+
},
|
|
259
265
|
);
|
|
260
266
|
```
|
|
261
267
|
|
|
@@ -269,9 +275,14 @@ const response = server.receive(jsonRpcRequest);
|
|
|
269
275
|
|
|
270
276
|
// With custom context (typically used by transports)
|
|
271
277
|
const response = server.receive(jsonRpcRequest, {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
278
|
+
sessionId: 'session-123',
|
|
279
|
+
auth: authInfo,
|
|
280
|
+
sessionInfo: {
|
|
281
|
+
clientCapabilities,
|
|
282
|
+
clientInfo,
|
|
283
|
+
logLevel,
|
|
284
|
+
},
|
|
285
|
+
custom: customContextData,
|
|
275
286
|
});
|
|
276
287
|
```
|
|
277
288
|
|
|
@@ -309,7 +320,7 @@ console.log(server.roots); // Access current roots
|
|
|
309
320
|
|
|
310
321
|
##### `changed(type, id)`
|
|
311
322
|
|
|
312
|
-
Send notifications for subscriptions.
|
|
323
|
+
Send notifications for subscriptions. When you call `changed('resource', uri)` the server now emits a broadcast notification, and the built-in transports look up which sessions subscribed to that URI before delivering it.
|
|
313
324
|
|
|
314
325
|
```javascript
|
|
315
326
|
server.changed('resource', 'file://path/to/resource');
|
|
@@ -380,13 +391,25 @@ server.log('error', 'Failed to connect to database', 'database-logger');
|
|
|
380
391
|
|
|
381
392
|
Listen to server events.
|
|
382
393
|
|
|
394
|
+
Available events:
|
|
395
|
+
|
|
396
|
+
- `initialize` – fired after the client handshake with the parsed initialize payload
|
|
397
|
+
- `send` – emitted for point-to-point responses/notifications destined for the active session
|
|
398
|
+
- `broadcast` – emitted for fan-out notifications (for example `notifications/resources/updated`)
|
|
399
|
+
- `subscription` – raised when the client subscribes to a resource URI
|
|
400
|
+
- `loglevelchange` – fired when the client requests a different log level
|
|
401
|
+
|
|
383
402
|
```javascript
|
|
384
|
-
server.on('initialize', (
|
|
385
|
-
console.log('Client initialized:',
|
|
403
|
+
server.on('initialize', ({ clientInfo }) => {
|
|
404
|
+
console.log('Client initialized:', clientInfo?.name);
|
|
386
405
|
});
|
|
387
406
|
|
|
388
|
-
server.on('send', ({ request
|
|
389
|
-
console.log('Sending
|
|
407
|
+
server.on('send', ({ request }) => {
|
|
408
|
+
console.log('Sending message:', request);
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
server.on('broadcast', ({ request }) => {
|
|
412
|
+
console.log('Broadcasting:', request.method);
|
|
390
413
|
});
|
|
391
414
|
```
|
|
392
415
|
|
|
@@ -516,9 +539,15 @@ server.on('initialize', (data) => {
|
|
|
516
539
|
console.log('Client capabilities:', data.capabilities);
|
|
517
540
|
});
|
|
518
541
|
|
|
519
|
-
server.on('send', ({ request
|
|
542
|
+
server.on('send', ({ request }) => {
|
|
520
543
|
console.log('Outgoing request:', request.method);
|
|
521
544
|
});
|
|
545
|
+
|
|
546
|
+
server.on('broadcast', ({ request }) => {
|
|
547
|
+
if (request.method === 'notifications/resources/updated') {
|
|
548
|
+
console.log('Resource updated:', request.params.uri);
|
|
549
|
+
}
|
|
550
|
+
});
|
|
522
551
|
```
|
|
523
552
|
|
|
524
553
|
### Resource Subscriptions
|
|
@@ -923,7 +952,7 @@ server.prompt(
|
|
|
923
952
|
);
|
|
924
953
|
```
|
|
925
954
|
|
|
926
|
-
or enable
|
|
955
|
+
or enable something based on client capabilities or info
|
|
927
956
|
|
|
928
957
|
```javascript
|
|
929
958
|
server.prompt(
|
|
@@ -932,8 +961,8 @@ server.prompt(
|
|
|
932
961
|
description: 'Claude Code prompt',
|
|
933
962
|
enabled: () => {
|
|
934
963
|
// Access session information
|
|
935
|
-
const clientInfo = server.
|
|
936
|
-
return clientInfo
|
|
964
|
+
const clientInfo = server.ctx.sessionInfo?.clientInfo;
|
|
965
|
+
return clientInfo?.name === 'Claude Code';
|
|
937
966
|
},
|
|
938
967
|
},
|
|
939
968
|
async (input) => {
|
|
@@ -958,8 +987,9 @@ server.prompt(
|
|
|
958
987
|
description: 'fetch the repositories of the user',
|
|
959
988
|
enabled: () => {
|
|
960
989
|
// Access session information
|
|
961
|
-
const
|
|
962
|
-
|
|
990
|
+
const clientCapabilities =
|
|
991
|
+
server.ctx.sessionInfo?.clientCapabilities;
|
|
992
|
+
return clientCapabilities?.elicitation != null;
|
|
963
993
|
},
|
|
964
994
|
},
|
|
965
995
|
async (input) => {
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -49,6 +49,7 @@ import { should_version_negotiation_fail } from './validation/version.js';
|
|
|
49
49
|
* @template {Record<string, unknown> | undefined} [TCustom=undefined]
|
|
50
50
|
* @typedef {Object} Context
|
|
51
51
|
* @property {string} [sessionId]
|
|
52
|
+
* @property {{ clientCapabilities?: ClientCapabilitiesType, clientInfo?: ClientInfoType, logLevel?: LoggingLevel }} [sessionInfo]
|
|
52
53
|
* @property {AuthInfo} [auth]
|
|
53
54
|
* @property {TCustom} [custom]
|
|
54
55
|
*/
|
|
@@ -57,6 +58,10 @@ import { should_version_negotiation_fail } from './validation/version.js';
|
|
|
57
58
|
* @typedef {IconsType} Icons
|
|
58
59
|
*/
|
|
59
60
|
|
|
61
|
+
/**
|
|
62
|
+
* @typedef {Record<SubscriptionsKeys, string[]>} Subscriptions
|
|
63
|
+
*/
|
|
64
|
+
|
|
60
65
|
/**
|
|
61
66
|
* @template {Record<string, unknown> | undefined} TStructuredContent
|
|
62
67
|
* @typedef {CallToolResultType<TStructuredContent>} CallToolResult
|
|
@@ -149,7 +154,7 @@ async function safe_enabled(enabled) {
|
|
|
149
154
|
export class McpServer {
|
|
150
155
|
#server = new JSONRPCServer();
|
|
151
156
|
/**
|
|
152
|
-
* @type {JSONRPCClient<
|
|
157
|
+
* @type {JSONRPCClient<"broadcast" | "standalone"> | undefined}
|
|
153
158
|
*/
|
|
154
159
|
#client;
|
|
155
160
|
#options;
|
|
@@ -180,36 +185,11 @@ export class McpServer {
|
|
|
180
185
|
|
|
181
186
|
#event_target = new EventTarget();
|
|
182
187
|
|
|
183
|
-
/**
|
|
184
|
-
* @type {Record<SubscriptionsKeys, Map<string, Set<string | undefined>>>}
|
|
185
|
-
*/
|
|
186
|
-
#subscriptions = {
|
|
187
|
-
/**
|
|
188
|
-
* @type {Map<string, Set<string>>}
|
|
189
|
-
*/
|
|
190
|
-
resource: new Map(),
|
|
191
|
-
};
|
|
192
|
-
|
|
193
188
|
/**
|
|
194
189
|
* @type {AsyncLocalStorage<Context<CustomContext> & { progress_token?: string }>}
|
|
195
190
|
*/
|
|
196
191
|
#ctx_storage = new AsyncLocalStorage();
|
|
197
192
|
|
|
198
|
-
/**
|
|
199
|
-
* @type {Map<string|undefined, ClientCapabilities>}
|
|
200
|
-
*/
|
|
201
|
-
#client_capabilities_map = new Map();
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* @type {Map<string|undefined, ClientInfo>}
|
|
205
|
-
*/
|
|
206
|
-
#client_info_map = new Map();
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* @type {Map<string|undefined, LoggingLevel>}
|
|
210
|
-
*/
|
|
211
|
-
#session_log_levels = new Map();
|
|
212
|
-
|
|
213
193
|
/**
|
|
214
194
|
* @param {ServerInfo} server_info
|
|
215
195
|
* @param {ServerOptions<StandardSchema>} options
|
|
@@ -224,8 +204,6 @@ export class McpServer {
|
|
|
224
204
|
initialize_request,
|
|
225
205
|
);
|
|
226
206
|
|
|
227
|
-
const session_id = this.#session_id;
|
|
228
|
-
|
|
229
207
|
// Validate protocol version format
|
|
230
208
|
if (
|
|
231
209
|
should_version_negotiation_fail(
|
|
@@ -245,18 +223,6 @@ export class McpServer {
|
|
|
245
223
|
validated_initialize.protocolVersion,
|
|
246
224
|
);
|
|
247
225
|
|
|
248
|
-
// Store client capabilities
|
|
249
|
-
this.#client_capabilities_map.set(
|
|
250
|
-
session_id,
|
|
251
|
-
validated_initialize.capabilities,
|
|
252
|
-
);
|
|
253
|
-
|
|
254
|
-
// Store client info
|
|
255
|
-
this.#client_info_map.set(
|
|
256
|
-
session_id,
|
|
257
|
-
validated_initialize.clientInfo,
|
|
258
|
-
);
|
|
259
|
-
|
|
260
226
|
// Dispatch initialization event
|
|
261
227
|
this.#event_target.dispatchEvent(
|
|
262
228
|
new CustomEvent('initialize', {
|
|
@@ -324,10 +290,6 @@ export class McpServer {
|
|
|
324
290
|
);
|
|
325
291
|
}
|
|
326
292
|
|
|
327
|
-
get #session_id() {
|
|
328
|
-
return this.#ctx_storage.getStore()?.sessionId;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
293
|
get #progress_token() {
|
|
332
294
|
return this.#ctx_storage.getStore()?.progress_token;
|
|
333
295
|
}
|
|
@@ -343,18 +305,20 @@ export class McpServer {
|
|
|
343
305
|
}
|
|
344
306
|
|
|
345
307
|
get #client_capabilities() {
|
|
346
|
-
return this.#
|
|
308
|
+
return this.#ctx_storage.getStore()?.sessionInfo?.clientCapabilities;
|
|
347
309
|
}
|
|
348
310
|
|
|
349
311
|
/**
|
|
350
312
|
* Get the client information (name, version, etc.) of the client that initiated the current request...useful if you want to do something different based on the client.
|
|
313
|
+
* @deprecated Use `server.ctx.sessionInfo.clientInfo` instead.
|
|
351
314
|
*/
|
|
352
315
|
currentClientInfo() {
|
|
353
|
-
return this.#
|
|
316
|
+
return this.#ctx_storage.getStore()?.sessionInfo?.clientInfo;
|
|
354
317
|
}
|
|
355
318
|
|
|
356
319
|
/**
|
|
357
320
|
* Get the client capabilities of the client that initiated the current request, you can use this to verify the client support something before invoking the respective method.
|
|
321
|
+
* @deprecated Use `server.ctx.sessionInfo.clientCapabilities` instead.
|
|
358
322
|
*/
|
|
359
323
|
currentClientCapabilities() {
|
|
360
324
|
return this.#client_capabilities;
|
|
@@ -362,10 +326,18 @@ export class McpServer {
|
|
|
362
326
|
|
|
363
327
|
#lazyily_create_client() {
|
|
364
328
|
if (!this.#client) {
|
|
365
|
-
this.#client = new JSONRPCClient((payload,
|
|
329
|
+
this.#client = new JSONRPCClient((payload, kind) => {
|
|
330
|
+
if (kind === 'broadcast') {
|
|
331
|
+
this.#event_target.dispatchEvent(
|
|
332
|
+
new CustomEvent('broadcast', {
|
|
333
|
+
detail: { request: payload },
|
|
334
|
+
}),
|
|
335
|
+
);
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
366
338
|
this.#event_target.dispatchEvent(
|
|
367
339
|
new CustomEvent('send', {
|
|
368
|
-
detail: { request: payload
|
|
340
|
+
detail: { request: payload },
|
|
369
341
|
}),
|
|
370
342
|
);
|
|
371
343
|
});
|
|
@@ -379,7 +351,7 @@ export class McpServer {
|
|
|
379
351
|
* @param {AddEventListenerOptions} [options]
|
|
380
352
|
*/
|
|
381
353
|
on(event, callback, options) {
|
|
382
|
-
if (event === 'send') {
|
|
354
|
+
if (event === 'send' || event === 'broadcast') {
|
|
383
355
|
this.#lazyily_create_client();
|
|
384
356
|
}
|
|
385
357
|
|
|
@@ -400,10 +372,10 @@ export class McpServer {
|
|
|
400
372
|
/**
|
|
401
373
|
* @param {string} method
|
|
402
374
|
* @param {JSONRPCParams} [params]
|
|
403
|
-
* @param {
|
|
375
|
+
* @param {"broadcast" | "standalone"} [kind]
|
|
404
376
|
*/
|
|
405
|
-
#notify(method, params,
|
|
406
|
-
this.#client?.notify(method, params,
|
|
377
|
+
#notify(method, params, kind = 'standalone') {
|
|
378
|
+
this.#client?.notify(method, params, kind);
|
|
407
379
|
}
|
|
408
380
|
|
|
409
381
|
/**
|
|
@@ -425,6 +397,7 @@ export class McpServer {
|
|
|
425
397
|
title: tool.title || tool.description,
|
|
426
398
|
description: tool.description,
|
|
427
399
|
icons: tool.icons,
|
|
400
|
+
_meta: tool._meta,
|
|
428
401
|
inputSchema: tool.schema
|
|
429
402
|
? await this.#options.adapter.toJsonSchema(
|
|
430
403
|
tool.schema,
|
|
@@ -637,12 +610,11 @@ export class McpServer {
|
|
|
637
610
|
|
|
638
611
|
if (this.#options.capabilities?.resources?.subscribe) {
|
|
639
612
|
this.#server.addMethod('resources/subscribe', async ({ uri }) => {
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
subscriptions.add(this.#session_id);
|
|
613
|
+
this.#event_target.dispatchEvent(
|
|
614
|
+
new CustomEvent('subscription', {
|
|
615
|
+
detail: { uri },
|
|
616
|
+
}),
|
|
617
|
+
);
|
|
646
618
|
return {};
|
|
647
619
|
});
|
|
648
620
|
}
|
|
@@ -786,9 +758,7 @@ export class McpServer {
|
|
|
786
758
|
const response = await this.#client?.request(
|
|
787
759
|
'roots/list',
|
|
788
760
|
undefined,
|
|
789
|
-
|
|
790
|
-
sessions: [this.#session_id],
|
|
791
|
-
},
|
|
761
|
+
'standalone',
|
|
792
762
|
);
|
|
793
763
|
this.roots = response?.roots || [];
|
|
794
764
|
} catch {
|
|
@@ -819,26 +789,34 @@ export class McpServer {
|
|
|
819
789
|
if (!this.#options.capabilities?.logging) return;
|
|
820
790
|
|
|
821
791
|
this.#server.addMethod('logging/setLevel', ({ level }) => {
|
|
822
|
-
this.#
|
|
792
|
+
this.#event_target.dispatchEvent(
|
|
793
|
+
new CustomEvent('loglevelchange', {
|
|
794
|
+
detail: { level },
|
|
795
|
+
}),
|
|
796
|
+
);
|
|
823
797
|
return {};
|
|
824
798
|
});
|
|
825
799
|
}
|
|
826
800
|
|
|
827
801
|
#notify_tools_list_changed() {
|
|
828
802
|
if (this.#options.capabilities?.tools?.listChanged) {
|
|
829
|
-
this.#notify('notifications/tools/list_changed', {});
|
|
803
|
+
this.#notify('notifications/tools/list_changed', {}, 'broadcast');
|
|
830
804
|
}
|
|
831
805
|
}
|
|
832
806
|
|
|
833
807
|
#notify_prompts_list_changed() {
|
|
834
808
|
if (this.#options.capabilities?.prompts?.listChanged) {
|
|
835
|
-
this.#notify('notifications/prompts/list_changed', {});
|
|
809
|
+
this.#notify('notifications/prompts/list_changed', {}, 'broadcast');
|
|
836
810
|
}
|
|
837
811
|
}
|
|
838
812
|
|
|
839
813
|
#notify_resources_list_changed() {
|
|
840
814
|
if (this.#options.capabilities?.resources?.listChanged) {
|
|
841
|
-
this.#notify(
|
|
815
|
+
this.#notify(
|
|
816
|
+
'notifications/resources/list_changed',
|
|
817
|
+
{},
|
|
818
|
+
'broadcast',
|
|
819
|
+
);
|
|
842
820
|
}
|
|
843
821
|
}
|
|
844
822
|
|
|
@@ -849,7 +827,7 @@ export class McpServer {
|
|
|
849
827
|
* Tools will be invoked by the LLM when it thinks it needs to use them, you can use the annotations to provide additional information about the tool, like what it does, how to use it, etc.
|
|
850
828
|
* @template {StandardSchema | undefined} [TSchema=undefined]
|
|
851
829
|
* @template {StandardSchema | undefined} [TOutputSchema=undefined]
|
|
852
|
-
* @param {{ name: string; description: string; title?: string; enabled?: ()=>boolean | Promise<boolean>; 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 } & Icons} options
|
|
830
|
+
* @param {{ name: string; _meta?: Record<string, any>; description: string; title?: string; enabled?: ()=>boolean | Promise<boolean>; 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 } & Icons} options
|
|
853
831
|
* @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
|
|
854
832
|
*/
|
|
855
833
|
tool(
|
|
@@ -862,6 +840,7 @@ export class McpServer {
|
|
|
862
840
|
annotations,
|
|
863
841
|
enabled,
|
|
864
842
|
icons,
|
|
843
|
+
_meta,
|
|
865
844
|
},
|
|
866
845
|
execute,
|
|
867
846
|
) {
|
|
@@ -875,6 +854,7 @@ export class McpServer {
|
|
|
875
854
|
execute,
|
|
876
855
|
annotations,
|
|
877
856
|
icons,
|
|
857
|
+
_meta,
|
|
878
858
|
});
|
|
879
859
|
}
|
|
880
860
|
/**
|
|
@@ -989,18 +969,6 @@ export class McpServer {
|
|
|
989
969
|
|
|
990
970
|
// Check if it's a request or response
|
|
991
971
|
if (validated_message.success) {
|
|
992
|
-
// we want to set a default log level for each session
|
|
993
|
-
// so that if the user calls `log` it can send a notification
|
|
994
|
-
// to each client that didn't explicitly set a log level too
|
|
995
|
-
if (
|
|
996
|
-
!!this.#options.capabilities?.logging &&
|
|
997
|
-
!this.#session_log_levels.has(ctx?.sessionId)
|
|
998
|
-
) {
|
|
999
|
-
this.#session_log_levels.set(
|
|
1000
|
-
ctx?.sessionId,
|
|
1001
|
-
this.#options.logging?.default ?? 'info',
|
|
1002
|
-
);
|
|
1003
|
-
}
|
|
1004
972
|
const progress_token = /** @type {string | undefined} */ (
|
|
1005
973
|
validated_message.output.params?._meta?.progressToken
|
|
1006
974
|
);
|
|
@@ -1035,28 +1003,16 @@ export class McpServer {
|
|
|
1035
1003
|
} else if (what === 'resources') {
|
|
1036
1004
|
this.#notify_resources_list_changed();
|
|
1037
1005
|
} else {
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
].get(id);
|
|
1049
|
-
this.#notify(
|
|
1050
|
-
`notifications/resources/updated`,
|
|
1051
|
-
{
|
|
1052
|
-
uri: id,
|
|
1053
|
-
title: resource.name,
|
|
1054
|
-
},
|
|
1055
|
-
{
|
|
1056
|
-
sessions: sessions ? [...sessions] : undefined,
|
|
1057
|
-
},
|
|
1058
|
-
);
|
|
1059
|
-
}
|
|
1006
|
+
const resource = this.#resources.get(id);
|
|
1007
|
+
if (!resource) return;
|
|
1008
|
+
this.#notify(
|
|
1009
|
+
`notifications/resources/updated`,
|
|
1010
|
+
{
|
|
1011
|
+
uri: id,
|
|
1012
|
+
title: resource.name,
|
|
1013
|
+
},
|
|
1014
|
+
'broadcast',
|
|
1015
|
+
);
|
|
1060
1016
|
}
|
|
1061
1017
|
}
|
|
1062
1018
|
|
|
@@ -1091,9 +1047,7 @@ export class McpServer {
|
|
|
1091
1047
|
requestedSchema:
|
|
1092
1048
|
await this.#options.adapter.toJsonSchema(schema),
|
|
1093
1049
|
},
|
|
1094
|
-
|
|
1095
|
-
sessions: [this.#session_id],
|
|
1096
|
-
},
|
|
1050
|
+
'standalone',
|
|
1097
1051
|
);
|
|
1098
1052
|
const elicit_result = v.parse(ElicitResultSchema, result);
|
|
1099
1053
|
let validated_result = schema['~standard'].validate(
|
|
@@ -1131,9 +1085,7 @@ export class McpServer {
|
|
|
1131
1085
|
const response = await this.#client?.request(
|
|
1132
1086
|
'sampling/createMessage',
|
|
1133
1087
|
validated_request,
|
|
1134
|
-
|
|
1135
|
-
sessions: [this.#session_id],
|
|
1136
|
-
},
|
|
1088
|
+
'standalone',
|
|
1137
1089
|
);
|
|
1138
1090
|
|
|
1139
1091
|
// Validate and return the response
|
|
@@ -1149,18 +1101,12 @@ export class McpServer {
|
|
|
1149
1101
|
*/
|
|
1150
1102
|
progress(progress, total = 1, message = undefined) {
|
|
1151
1103
|
if (this.#progress_token != null) {
|
|
1152
|
-
this.#notify(
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
progressToken: this.#progress_token,
|
|
1159
|
-
},
|
|
1160
|
-
{
|
|
1161
|
-
sessions: this.#session_id ? [this.#session_id] : undefined,
|
|
1162
|
-
},
|
|
1163
|
-
);
|
|
1104
|
+
this.#notify('notifications/progress', {
|
|
1105
|
+
progress,
|
|
1106
|
+
total,
|
|
1107
|
+
message,
|
|
1108
|
+
progressToken: this.#progress_token,
|
|
1109
|
+
});
|
|
1164
1110
|
}
|
|
1165
1111
|
}
|
|
1166
1112
|
|
|
@@ -1179,33 +1125,21 @@ export class McpServer {
|
|
|
1179
1125
|
);
|
|
1180
1126
|
}
|
|
1181
1127
|
|
|
1182
|
-
const
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
);
|
|
1128
|
+
const current_session_level =
|
|
1129
|
+
this.#ctx_storage.getStore()?.sessionInfo?.logLevel ??
|
|
1130
|
+
this.#options.logging?.default ??
|
|
1131
|
+
'info';
|
|
1187
1132
|
|
|
1188
1133
|
if (
|
|
1189
1134
|
current_session_level &&
|
|
1190
1135
|
this.#should_log(level, current_session_level)
|
|
1191
1136
|
) {
|
|
1192
|
-
|
|
1193
|
-
}
|
|
1194
|
-
|
|
1195
|
-
if (sessions.length === 0) return;
|
|
1196
|
-
|
|
1197
|
-
// Send the log notification to the client
|
|
1198
|
-
this.#notify(
|
|
1199
|
-
'notifications/message',
|
|
1200
|
-
{
|
|
1137
|
+
this.#notify('notifications/message', {
|
|
1201
1138
|
level,
|
|
1202
1139
|
data,
|
|
1203
1140
|
logger,
|
|
1204
|
-
}
|
|
1205
|
-
|
|
1206
|
-
sessions,
|
|
1207
|
-
},
|
|
1208
|
-
);
|
|
1141
|
+
});
|
|
1142
|
+
}
|
|
1209
1143
|
}
|
|
1210
1144
|
|
|
1211
1145
|
/**
|
|
@@ -20,6 +20,7 @@ export type Tool<TSchema extends StandardSchemaV1 = StandardSchemaV1<any>, TOutp
|
|
|
20
20
|
outputSchema?: TOutputSchema;
|
|
21
21
|
title?: string;
|
|
22
22
|
annotations?: ToolAnnotations;
|
|
23
|
+
_meta?: Record<string, unknown>;
|
|
23
24
|
enabled?: () => boolean | Promise<boolean>;
|
|
24
25
|
execute: (
|
|
25
26
|
input?: StandardSchemaV1.InferInput<TSchema>,
|
|
@@ -96,9 +97,11 @@ export type SubscriptionsKeys = SubscriptionsKeysObj["with_args"];
|
|
|
96
97
|
export type McpEvents = {
|
|
97
98
|
send: (message: {
|
|
98
99
|
request: JSONRPCRequest;
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
}) => void;
|
|
101
|
+
broadcast: (message: {
|
|
102
|
+
request: JSONRPCRequest;
|
|
102
103
|
}) => void;
|
|
103
104
|
initialize: (initialize_request: InitializeRequestParams) => void;
|
|
105
|
+
subscription: (subscriptions_request: { uri: string }) => void;
|
|
106
|
+
loglevelchange: (change: { level: LoggingLevel }) => void;
|
|
104
107
|
};
|
package/src/types/index.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ declare module 'tmcp' {
|
|
|
23
23
|
get ctx(): Context<CustomContext>;
|
|
24
24
|
/**
|
|
25
25
|
* Get the client information (name, version, etc.) of the client that initiated the current request...useful if you want to do something different based on the client.
|
|
26
|
+
* @deprecated Use `server.ctx.sessionInfo.clientInfo` instead.
|
|
26
27
|
*/
|
|
27
28
|
currentClientInfo(): {
|
|
28
29
|
icons?: {
|
|
@@ -37,6 +38,7 @@ declare module 'tmcp' {
|
|
|
37
38
|
} | undefined;
|
|
38
39
|
/**
|
|
39
40
|
* Get the client capabilities of the client that initiated the current request, you can use this to verify the client support something before invoking the respective method.
|
|
41
|
+
* @deprecated Use `server.ctx.sessionInfo.clientCapabilities` instead.
|
|
40
42
|
*/
|
|
41
43
|
currentClientCapabilities(): {
|
|
42
44
|
experimental?: {} | undefined;
|
|
@@ -54,8 +56,9 @@ declare module 'tmcp' {
|
|
|
54
56
|
*
|
|
55
57
|
* Tools will be invoked by the LLM when it thinks it needs to use them, you can use the annotations to provide additional information about the tool, like what it does, how to use it, etc.
|
|
56
58
|
* */
|
|
57
|
-
tool<TSchema extends StandardSchema | undefined = undefined, TOutputSchema extends StandardSchema | undefined = undefined>({ name, description, title, schema, outputSchema, annotations, enabled, icons, }: {
|
|
59
|
+
tool<TSchema extends StandardSchema | undefined = undefined, TOutputSchema extends StandardSchema | undefined = undefined>({ name, description, title, schema, outputSchema, annotations, enabled, icons, _meta, }: {
|
|
58
60
|
name: string;
|
|
61
|
+
_meta?: Record<string, any>;
|
|
59
62
|
description: string;
|
|
60
63
|
title?: string;
|
|
61
64
|
enabled?: () => boolean | Promise<boolean>;
|
|
@@ -182,10 +185,16 @@ declare module 'tmcp' {
|
|
|
182
185
|
};
|
|
183
186
|
export type Context<TCustom extends Record<string, unknown> | undefined = undefined> = {
|
|
184
187
|
sessionId?: string | undefined;
|
|
188
|
+
sessionInfo?: {
|
|
189
|
+
clientCapabilities?: ClientCapabilities_1;
|
|
190
|
+
clientInfo?: ClientInfo_1;
|
|
191
|
+
logLevel?: LoggingLevel;
|
|
192
|
+
} | undefined;
|
|
185
193
|
auth?: AuthInfo | undefined;
|
|
186
194
|
custom?: TCustom | undefined;
|
|
187
195
|
};
|
|
188
196
|
export type Icons = Icons_1;
|
|
197
|
+
export type Subscriptions = Record<SubscriptionsKeys, string[]>;
|
|
189
198
|
export type CallToolResult<TStructuredContent extends Record<string, unknown> | undefined> = CallToolResult_1<TStructuredContent>;
|
|
190
199
|
export type ReadResourceResult = ReadResourceResult_1;
|
|
191
200
|
export type GetPromptResult = GetPromptResult_1;
|
|
@@ -222,14 +231,22 @@ declare module 'tmcp' {
|
|
|
222
231
|
'resources': [];
|
|
223
232
|
}
|
|
224
233
|
|
|
234
|
+
type SubscriptionsKeysObj = {
|
|
235
|
+
[K in keyof ChangedArgs as ChangedArgs[K]["length"] extends 0 ? "without_args" : "with_args"]: K
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
type SubscriptionsKeys = SubscriptionsKeysObj["with_args"];
|
|
239
|
+
|
|
225
240
|
type McpEvents = {
|
|
226
241
|
send: (message: {
|
|
227
242
|
request: JSONRPCRequest;
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
243
|
+
}) => void;
|
|
244
|
+
broadcast: (message: {
|
|
245
|
+
request: JSONRPCRequest;
|
|
231
246
|
}) => void;
|
|
232
247
|
initialize: (initialize_request: InitializeRequestParams) => void;
|
|
248
|
+
subscription: (subscriptions_request: { uri: string }) => void;
|
|
249
|
+
loglevelchange: (change: { level: LoggingLevel_1 }) => void;
|
|
233
250
|
};
|
|
234
251
|
/**
|
|
235
252
|
* A successful (non-error) response to a request.
|
|
@@ -237,7 +254,7 @@ declare module 'tmcp' {
|
|
|
237
254
|
const JSONRPCResponseSchema: v.StrictObjectSchema<{
|
|
238
255
|
readonly jsonrpc: v.LiteralSchema<"2.0", undefined>;
|
|
239
256
|
readonly id: v.UnionSchema<[v.StringSchema<undefined>, v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>]>], undefined>;
|
|
240
|
-
readonly result: v.
|
|
257
|
+
readonly result: v.LooseObjectSchema<{
|
|
241
258
|
/**
|
|
242
259
|
* See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields)
|
|
243
260
|
* for notes on _meta usage.
|
package/src/types/index.d.ts.map
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
"names": [
|
|
5
5
|
"McpServer",
|
|
6
6
|
"Icons",
|
|
7
|
+
"Subscriptions",
|
|
7
8
|
"ReadResourceResult",
|
|
8
9
|
"GetPromptResult",
|
|
9
10
|
"ClientCapabilities",
|
|
@@ -17,6 +18,8 @@
|
|
|
17
18
|
"Completion",
|
|
18
19
|
"ServerOptions",
|
|
19
20
|
"ChangedArgs",
|
|
21
|
+
"SubscriptionsKeysObj",
|
|
22
|
+
"SubscriptionsKeys",
|
|
20
23
|
"McpEvents",
|
|
21
24
|
"JSONRPCResponseSchema",
|
|
22
25
|
"IconsSchema",
|
|
@@ -61,6 +64,6 @@
|
|
|
61
64
|
null,
|
|
62
65
|
null
|
|
63
66
|
],
|
|
64
|
-
"mappings": ";;;;;
|
|
67
|
+
"mappings": ";;;;;cAyJaA,SAASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aCw1CyBC,KAAKA;aDp7CFC,aAAaA;;aC28CHC,kBAAkBA;aAGrBC,eAAeA;aAvBZC,kBAAkBA;aAUKC,UAAUA;aAmBzBC,0BAA0BA;aAGjCC,mBAAmBA;aAY9BC,QAAQA;aASJC,YAAYA;aA/CVC,UAAUA;aAqDZC,YAAYA;MClhDtDC,UAAUA;;;;;MAyCVC,aAAaA;;;;;;;;;;;;;MAabC,WAAWA;;;;;;;MAOlBC,oBAAoBA;;;;MAIbC,iBAAiBA;;MAEjBC,SAASA;;;;;;;;;;;;;;ODGRC,qBAAqBA;;;;;;;;;;;OAgHrBC,WAAWA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAoBXC,oBAAoBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAUpBC,wBAAwBA;;;;;;;;;;;;;;;;;;;;;;;OA6BxBC,6BAA6BA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuB7BC,wBAAwBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmMxBC,cAAcA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8GdC,wBAAwBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+PxBC,qBAAqBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BrBC,qBAAqBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4GrBC,oBAAoBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAoEpBC,kBAAkBA;OAuGlBC,gCAAgCA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8ChCC,yBAAyBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6GzBC,kBAAkBA;;;;;;;;;;;;;;;;;;OAkFlBC,oBAAoBA;;;;;;;;;;;;;;;;;;;;;;;MAiI2BC,kBAAkBA;;;;;MAUbC,uBAAuBA;;;;;;;;;;;;;MAahCC,cAAcA;;;;MAwBbC,eAAeA;;MAMfC,eAAeA;;;ME3iDnEC,IAAIA;;;;;;;MAOJC,cAAcA;;;;;;;MAOdC,cAAcA;;;;;MAKdC,qBAAqBA;;;;;;;;;;;;;;;;;MAiBrBC,4BAA4BA;;;;;;MAMrBC,2BAA2BA;;;;;;;OCjC1BC,iBAAiBA;;;;;;;;;;;;;;;;cAAjBA,iBAAiBA",
|
|
65
68
|
"ignoreList": []
|
|
66
69
|
}
|
package/src/validation/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable jsdoc/no-undefined-types */
|
|
2
1
|
import * as v from 'valibot';
|
|
3
2
|
export const LATEST_PROTOCOL_VERSION = '2025-06-18';
|
|
4
3
|
export const DEFAULT_NEGOTIATED_PROTOCOL_VERSION = '2025-03-26';
|
|
@@ -62,7 +61,7 @@ export const NotificationSchema = v.object({
|
|
|
62
61
|
method: v.string(),
|
|
63
62
|
params: v.optional(BaseNotificationParamsSchema),
|
|
64
63
|
});
|
|
65
|
-
export const ResultSchema = v.
|
|
64
|
+
export const ResultSchema = v.looseObject({
|
|
66
65
|
/**
|
|
67
66
|
* See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields)
|
|
68
67
|
* for notes on _meta usage.
|