@@ -31,6 +31,9 @@ const instructions = readFileSync(join(__dirname, "instructions.md"), "utf-8");
31
31
const ToolInputSchema = ToolSchema . shape . inputSchema ;
32
32
type ToolInput = z . infer < typeof ToolInputSchema > ;
33
33
34
+ const ToolOutputSchema = ToolSchema . shape . outputSchema ;
35
+ type ToolOutput = z . infer < typeof ToolOutputSchema > ;
36
+
34
37
/* Input schemas for tools implemented in this server */
35
38
const EchoSchema = z . object ( {
36
39
message : z . string ( ) . describe ( "Message to echo" ) ,
@@ -46,7 +49,10 @@ const LongRunningOperationSchema = z.object({
46
49
. number ( )
47
50
. default ( 10 )
48
51
. describe ( "Duration of the operation in seconds" ) ,
49
- steps : z . number ( ) . default ( 5 ) . describe ( "Number of steps in the operation" ) ,
52
+ steps : z
53
+ . number ( )
54
+ . default ( 5 )
55
+ . describe ( "Number of steps in the operation" ) ,
50
56
} ) ;
51
57
52
58
const PrintEnvSchema = z . object ( { } ) ;
@@ -59,13 +65,6 @@ const SampleLLMSchema = z.object({
59
65
. describe ( "Maximum number of tokens to generate" ) ,
60
66
} ) ;
61
67
62
- // Example completion values
63
- const EXAMPLE_COMPLETIONS = {
64
- style : [ "casual" , "formal" , "technical" , "friendly" ] ,
65
- temperature : [ "0" , "0.5" , "0.7" , "1.0" ] ,
66
- resourceId : [ "1" , "2" , "3" , "4" , "5" ] ,
67
- } ;
68
-
69
68
const GetTinyImageSchema = z . object ( { } ) ;
70
69
71
70
const AnnotatedMessageSchema = z . object ( {
@@ -97,6 +96,28 @@ const GetResourceLinksSchema = z.object({
97
96
. describe ( "Number of resource links to return (1-10)" ) ,
98
97
} ) ;
99
98
99
+ const StructuredContentSchema = {
100
+ input : z . object ( {
101
+ location : z
102
+ . string ( )
103
+ . trim ( )
104
+ . min ( 1 )
105
+ . describe ( "City name or zip code" ) ,
106
+ } ) ,
107
+
108
+ output : z . object ( {
109
+ temperature : z
110
+ . number ( )
111
+ . describe ( "Temperature in celsius" ) ,
112
+ conditions : z
113
+ . string ( )
114
+ . describe ( "Weather conditions description" ) ,
115
+ humidity : z
116
+ . number ( )
117
+ . describe ( "Humidity percentage" ) ,
118
+ } )
119
+ } ;
120
+
100
121
enum ToolName {
101
122
ECHO = "echo" ,
102
123
ADD = "add" ,
@@ -108,6 +129,7 @@ enum ToolName {
108
129
GET_RESOURCE_REFERENCE = "getResourceReference" ,
109
130
ELICITATION = "startElicitation" ,
110
131
GET_RESOURCE_LINKS = "getResourceLinks" ,
132
+ STRUCTURED_CONTENT = "structuredContent"
111
133
}
112
134
113
135
enum PromptName {
@@ -116,10 +138,18 @@ enum PromptName {
116
138
RESOURCE = "resource_prompt" ,
117
139
}
118
140
141
+ // Example completion values
142
+ const EXAMPLE_COMPLETIONS = {
143
+ style : [ "casual" , "formal" , "technical" , "friendly" ] ,
144
+ temperature : [ "0" , "0.5" , "0.7" , "1.0" ] ,
145
+ resourceId : [ "1" , "2" , "3" , "4" , "5" ] ,
146
+ } ;
147
+
119
148
export const createServer = ( ) => {
120
149
const server = new Server (
121
150
{
122
151
name : "example-servers/everything" ,
152
+ title : "Everything Example Server" ,
123
153
version : "1.0.0" ,
124
154
} ,
125
155
{
@@ -179,18 +209,6 @@ export const createServer = () => {
179
209
} , 20000 ) ;
180
210
181
211
182
- // Set up update interval for stderr messages
183
- stdErrUpdateInterval = setInterval ( ( ) => {
184
- const shortTimestamp = new Date ( ) . toLocaleTimeString ( [ ] , {
185
- hour : "2-digit" ,
186
- minute : "2-digit" ,
187
- second : "2-digit"
188
- } ) ;
189
- server . notification ( {
190
- method : "notifications/stderr" ,
191
- params : { content : `${ shortTimestamp } : A stderr message` } ,
192
- } ) ;
193
- } , 30000 ) ;
194
212
195
213
// Helper method to request sampling from client
196
214
const requestSampling = async (
@@ -454,18 +472,18 @@ export const createServer = () => {
454
472
description : "Adds two numbers" ,
455
473
inputSchema : zodToJsonSchema ( AddSchema ) as ToolInput ,
456
474
} ,
457
- {
458
- name : ToolName . PRINT_ENV ,
459
- description :
460
- "Prints all environment variables, helpful for debugging MCP server configuration" ,
461
- inputSchema : zodToJsonSchema ( PrintEnvSchema ) as ToolInput ,
462
- } ,
463
475
{
464
476
name : ToolName . LONG_RUNNING_OPERATION ,
465
477
description :
466
478
"Demonstrates a long running operation with progress updates" ,
467
479
inputSchema : zodToJsonSchema ( LongRunningOperationSchema ) as ToolInput ,
468
480
} ,
481
+ {
482
+ name : ToolName . PRINT_ENV ,
483
+ description :
484
+ "Prints all environment variables, helpful for debugging MCP server configuration" ,
485
+ inputSchema : zodToJsonSchema ( PrintEnvSchema ) as ToolInput ,
486
+ } ,
469
487
{
470
488
name : ToolName . SAMPLE_LLM ,
471
489
description : "Samples from an LLM using MCP's sampling feature" ,
@@ -499,6 +517,13 @@ export const createServer = () => {
499
517
"Returns multiple resource links that reference different types of resources" ,
500
518
inputSchema : zodToJsonSchema ( GetResourceLinksSchema ) as ToolInput ,
501
519
} ,
520
+ {
521
+ name : ToolName . STRUCTURED_CONTENT ,
522
+ description :
523
+ "Returns structured content along with an output schema for client data validation" ,
524
+ inputSchema : zodToJsonSchema ( StructuredContentSchema . input ) as ToolInput ,
525
+ outputSchema : zodToJsonSchema ( StructuredContentSchema . output ) as ToolOutput ,
526
+ } ,
502
527
] ;
503
528
504
529
return { tools } ;
@@ -608,35 +633,6 @@ export const createServer = () => {
608
633
} ;
609
634
}
610
635
611
- if ( name === ToolName . GET_RESOURCE_REFERENCE ) {
612
- const validatedArgs = GetResourceReferenceSchema . parse ( args ) ;
613
- const resourceId = validatedArgs . resourceId ;
614
-
615
- const resourceIndex = resourceId - 1 ;
616
- if ( resourceIndex < 0 || resourceIndex >= ALL_RESOURCES . length ) {
617
- throw new Error ( `Resource with ID ${ resourceId } does not exist` ) ;
618
- }
619
-
620
- const resource = ALL_RESOURCES [ resourceIndex ] ;
621
-
622
- return {
623
- content : [
624
- {
625
- type : "text" ,
626
- text : `Returning resource reference for Resource ${ resourceId } :` ,
627
- } ,
628
- {
629
- type : "resource" ,
630
- resource : resource ,
631
- } ,
632
- {
633
- type : "text" ,
634
- text : `You can access this resource using the URI: ${ resource . uri } ` ,
635
- } ,
636
- ] ,
637
- } ;
638
- }
639
-
640
636
if ( name === ToolName . ANNOTATED_MESSAGE ) {
641
637
const { messageType, includeImage } = AnnotatedMessageSchema . parse ( args ) ;
642
638
@@ -688,6 +684,35 @@ export const createServer = () => {
688
684
return { content } ;
689
685
}
690
686
687
+ if ( name === ToolName . GET_RESOURCE_REFERENCE ) {
688
+ const validatedArgs = GetResourceReferenceSchema . parse ( args ) ;
689
+ const resourceId = validatedArgs . resourceId ;
690
+
691
+ const resourceIndex = resourceId - 1 ;
692
+ if ( resourceIndex < 0 || resourceIndex >= ALL_RESOURCES . length ) {
693
+ throw new Error ( `Resource with ID ${ resourceId } does not exist` ) ;
694
+ }
695
+
696
+ const resource = ALL_RESOURCES [ resourceIndex ] ;
697
+
698
+ return {
699
+ content : [
700
+ {
701
+ type : "text" ,
702
+ text : `Returning resource reference for Resource ${ resourceId } :` ,
703
+ } ,
704
+ {
705
+ type : "resource" ,
706
+ resource : resource ,
707
+ } ,
708
+ {
709
+ type : "text" ,
710
+ text : `You can access this resource using the URI: ${ resource . uri } ` ,
711
+ } ,
712
+ ] ,
713
+ } ;
714
+ }
715
+
691
716
if ( name === ToolName . ELICITATION ) {
692
717
ElicitationSchema . parse ( args ) ;
693
718
@@ -709,13 +734,13 @@ export const createServer = () => {
709
734
710
735
// Handle different response actions
711
736
const content = [ ] ;
712
-
737
+
713
738
if ( elicitationResult . action === 'accept' && elicitationResult . content ) {
714
739
content . push ( {
715
740
type : "text" ,
716
741
text : `✅ User provided their favorite things!` ,
717
742
} ) ;
718
-
743
+
719
744
// Only access elicitationResult.content when action is accept
720
745
const { color, number, pets } = elicitationResult . content ;
721
746
content . push ( {
@@ -733,7 +758,7 @@ export const createServer = () => {
733
758
text : `⚠️ User cancelled the elicitation dialog.` ,
734
759
} ) ;
735
760
}
736
-
761
+
737
762
// Include raw result for debugging
738
763
content . push ( {
739
764
type : "text" ,
@@ -742,7 +767,7 @@ export const createServer = () => {
742
767
743
768
return { content } ;
744
769
}
745
-
770
+
746
771
if ( name === ToolName . GET_RESOURCE_LINKS ) {
747
772
const { count } = GetResourceLinksSchema . parse ( args ) ;
748
773
const content = [ ] ;
@@ -773,6 +798,27 @@ export const createServer = () => {
773
798
return { content } ;
774
799
}
775
800
801
+ if ( name === ToolName . STRUCTURED_CONTENT ) {
802
+ // The same response is returned for every input.
803
+ const validatedArgs = StructuredContentSchema . input . parse ( args ) ;
804
+
805
+ const weather = {
806
+ temperature : 22.5 ,
807
+ conditions : "Partly cloudy" ,
808
+ humidity : 65
809
+ }
810
+
811
+ const backwardCompatiblecontent = {
812
+ type : "text" ,
813
+ text : JSON . stringify ( weather )
814
+ }
815
+
816
+ return {
817
+ content : [ backwardCompatiblecontent ] ,
818
+ structuredContent : weather
819
+ } ;
820
+ }
821
+
776
822
throw new Error ( `Unknown tool: ${ name } ` ) ;
777
823
} ) ;
778
824
0 commit comments