9
9
ListResourcesRequestSchema ,
10
10
ListResourceTemplatesRequestSchema ,
11
11
ListToolsRequestSchema ,
12
+ LoggingLevel ,
12
13
ReadResourceRequestSchema ,
13
14
Resource ,
14
15
SetLevelRequestSchema ,
@@ -60,13 +61,21 @@ const EXAMPLE_COMPLETIONS = {
60
61
61
62
const GetTinyImageSchema = z . object ( { } ) ;
62
63
64
+ const AnnotatedMessageSchema = z . object ( {
65
+ messageType : z . enum ( [ "error" , "success" , "debug" ] )
66
+ . describe ( "Type of message to demonstrate different annotation patterns" ) ,
67
+ includeImage : z . boolean ( ) . default ( false )
68
+ . describe ( "Whether to include an example image" )
69
+ } ) ;
70
+
63
71
enum ToolName {
64
72
ECHO = "echo" ,
65
73
ADD = "add" ,
66
74
LONG_RUNNING_OPERATION = "longRunningOperation" ,
67
75
PRINT_ENV = "printEnv" ,
68
76
SAMPLE_LLM = "sampleLLM" ,
69
77
GET_TINY_IMAGE = "getTinyImage" ,
78
+ ANNOTATED_MESSAGE = "annotatedMessage" ,
70
79
}
71
80
72
81
enum PromptName {
@@ -91,10 +100,10 @@ export const createServer = () => {
91
100
) ;
92
101
93
102
let subscriptions : Set < string > = new Set ( ) ;
94
- let updateInterval : NodeJS . Timeout | undefined ;
95
-
103
+ let subsUpdateInterval : NodeJS . Timeout | undefined ;
96
104
// Set up update interval for subscribed resources
97
- updateInterval = setInterval ( ( ) => {
105
+
106
+ subsUpdateInterval = setInterval ( ( ) => {
98
107
for ( const uri of subscriptions ) {
99
108
server . notification ( {
100
109
method : "notifications/resources/updated" ,
@@ -103,6 +112,34 @@ export const createServer = () => {
103
112
}
104
113
} , 5000 ) ;
105
114
115
+ let logLevel : LoggingLevel = "debug" ;
116
+ let logsUpdateInterval : NodeJS . Timeout | undefined ;
117
+ const messages = [
118
+ { level : "debug" , data : "Debug-level message" } ,
119
+ { level : "info" , data : "Info-level message" } ,
120
+ { level : "notice" , data : "Notice-level message" } ,
121
+ { level : "warning" , data : "Warning-level message" } ,
122
+ { level : "error" , data : "Error-level message" } ,
123
+ { level : "critical" , data : "Critical-level message" } ,
124
+ { level : "alert" , data : "Alert level-message" } ,
125
+ { level : "emergency" , data : "Emergency-level message" }
126
+ ]
127
+
128
+ const isMessageIgnored = ( level :LoggingLevel ) :boolean => {
129
+ const currentLevel = messages . findIndex ( ( msg ) => logLevel === msg . level ) ;
130
+ const messageLevel = messages . findIndex ( ( msg ) => level === msg . level ) ;
131
+ return messageLevel < currentLevel ;
132
+ }
133
+
134
+ // Set up update interval for random log messages
135
+ logsUpdateInterval = setInterval ( ( ) => {
136
+ let message = {
137
+ method : "notifications/message" ,
138
+ params : messages [ Math . floor ( Math . random ( ) * messages . length ) ] ,
139
+ }
140
+ if ( ! isMessageIgnored ( message . params . level as LoggingLevel ) ) server . notification ( message ) ;
141
+ } , 15000 ) ;
142
+
106
143
// Helper method to request sampling from client
107
144
const requestSampling = async (
108
145
context : string ,
@@ -329,6 +366,11 @@ export const createServer = () => {
329
366
description : "Returns the MCP_TINY_IMAGE" ,
330
367
inputSchema : zodToJsonSchema ( GetTinyImageSchema ) as ToolInput ,
331
368
} ,
369
+ {
370
+ name : ToolName . ANNOTATED_MESSAGE ,
371
+ description : "Demonstrates how annotations can be used to provide metadata about content" ,
372
+ inputSchema : zodToJsonSchema ( AnnotatedMessageSchema ) as ToolInput ,
373
+ } ,
332
374
] ;
333
375
334
376
return { tools } ;
@@ -436,6 +478,57 @@ export const createServer = () => {
436
478
} ;
437
479
}
438
480
481
+ if ( name === ToolName . ANNOTATED_MESSAGE ) {
482
+ const { messageType, includeImage } = AnnotatedMessageSchema . parse ( args ) ;
483
+
484
+ const content = [ ] ;
485
+
486
+ // Main message with different priorities/audiences based on type
487
+ if ( messageType === "error" ) {
488
+ content . push ( {
489
+ type : "text" ,
490
+ text : "Error: Operation failed" ,
491
+ annotations : {
492
+ priority : 1.0 , // Errors are highest priority
493
+ audience : [ "user" , "assistant" ] // Both need to know about errors
494
+ }
495
+ } ) ;
496
+ } else if ( messageType === "success" ) {
497
+ content . push ( {
498
+ type : "text" ,
499
+ text : "Operation completed successfully" ,
500
+ annotations : {
501
+ priority : 0.7 , // Success messages are important but not critical
502
+ audience : [ "user" ] // Success mainly for user consumption
503
+ }
504
+ } ) ;
505
+ } else if ( messageType === "debug" ) {
506
+ content . push ( {
507
+ type : "text" ,
508
+ text : "Debug: Cache hit ratio 0.95, latency 150ms" ,
509
+ annotations : {
510
+ priority : 0.3 , // Debug info is low priority
511
+ audience : [ "assistant" ] // Technical details for assistant
512
+ }
513
+ } ) ;
514
+ }
515
+
516
+ // Optional image with its own annotations
517
+ if ( includeImage ) {
518
+ content . push ( {
519
+ type : "image" ,
520
+ data : MCP_TINY_IMAGE ,
521
+ mimeType : "image/png" ,
522
+ annotations : {
523
+ priority : 0.5 ,
524
+ audience : [ "user" ] // Images primarily for user visualization
525
+ }
526
+ } ) ;
527
+ }
528
+
529
+ return { content } ;
530
+ }
531
+
439
532
throw new Error ( `Unknown tool: ${ name } ` ) ;
440
533
} ) ;
441
534
@@ -447,7 +540,7 @@ export const createServer = () => {
447
540
if ( ! resourceId ) return { completion : { values : [ ] } } ;
448
541
449
542
// Filter resource IDs that start with the input value
450
- const values = EXAMPLE_COMPLETIONS . resourceId . filter ( id =>
543
+ const values = EXAMPLE_COMPLETIONS . resourceId . filter ( id =>
451
544
id . startsWith ( argument . value )
452
545
) ;
453
546
return { completion : { values, hasMore : false , total : values . length } } ;
@@ -458,7 +551,7 @@ export const createServer = () => {
458
551
const completions = EXAMPLE_COMPLETIONS [ argument . name as keyof typeof EXAMPLE_COMPLETIONS ] ;
459
552
if ( ! completions ) return { completion : { values : [ ] } } ;
460
553
461
- const values = completions . filter ( value =>
554
+ const values = completions . filter ( value =>
462
555
value . startsWith ( argument . value )
463
556
) ;
464
557
return { completion : { values, hasMore : false , total : values . length } } ;
@@ -469,24 +562,24 @@ export const createServer = () => {
469
562
470
563
server . setRequestHandler ( SetLevelRequestSchema , async ( request ) => {
471
564
const { level } = request . params ;
565
+ logLevel = level ;
472
566
473
567
// Demonstrate different log levels
474
568
await server . notification ( {
475
569
method : "notifications/message" ,
476
570
params : {
477
571
level : "debug" ,
478
572
logger : "test-server" ,
479
- data : `Logging level set to: ${ level } ` ,
573
+ data : `Logging level set to: ${ logLevel } ` ,
480
574
} ,
481
575
} ) ;
482
576
483
577
return { } ;
484
578
} ) ;
485
579
486
580
const cleanup = async ( ) => {
487
- if ( updateInterval ) {
488
- clearInterval ( updateInterval ) ;
489
- }
581
+ if ( subsUpdateInterval ) clearInterval ( subsUpdateInterval ) ;
582
+ if ( logsUpdateInterval ) clearInterval ( logsUpdateInterval ) ;
490
583
} ;
491
584
492
585
return { server, cleanup } ;
0 commit comments