@@ -15,7 +15,11 @@ import {
1515 LoggingMessageNotificationSchema ,
1616 ResourceListChangedNotificationSchema ,
1717 ElicitRequestSchema ,
18+ ResourceLink ,
19+ ReadResourceRequest ,
20+ ReadResourceResultSchema ,
1821} from '../../types.js' ;
22+ import { getDisplayName } from '../../shared/metadataUtils.js' ;
1923import Ajv from "ajv" ;
2024
2125// Create readline interface for user input
@@ -62,6 +66,7 @@ function printHelp(): void {
6266 console . log ( ' list-prompts - List available prompts' ) ;
6367 console . log ( ' get-prompt [name] [args] - Get a prompt with optional JSON arguments' ) ;
6468 console . log ( ' list-resources - List available resources' ) ;
69+ console . log ( ' read-resource <uri> - Read a specific resource by URI' ) ;
6570 console . log ( ' help - Show this help' ) ;
6671 console . log ( ' quit - Exit the program' ) ;
6772}
@@ -161,6 +166,14 @@ function commandLoop(): void {
161166 await listResources ( ) ;
162167 break ;
163168
169+ case 'read-resource' :
170+ if ( args . length < 2 ) {
171+ console . log ( 'Usage: read-resource <uri>' ) ;
172+ } else {
173+ await readResource ( args [ 1 ] ) ;
174+ }
175+ break ;
176+
164177 case 'help' :
165178 printHelp ( ) ;
166179 break ;
@@ -521,7 +534,7 @@ async function listTools(): Promise<void> {
521534 console . log ( ' No tools available' ) ;
522535 } else {
523536 for ( const tool of toolsResult . tools ) {
524- console . log ( ` - ${ tool . name } : ${ tool . description } ` ) ;
537+ console . log ( ` - id: ${ tool . name } , name: ${ getDisplayName ( tool ) } , description : ${ tool . description } ` ) ;
525538 }
526539 }
527540 } catch ( error ) {
@@ -548,13 +561,37 @@ async function callTool(name: string, args: Record<string, unknown>): Promise<vo
548561 const result = await client . request ( request , CallToolResultSchema ) ;
549562
550563 console . log ( 'Tool result:' ) ;
564+ const resourceLinks : ResourceLink [ ] = [ ] ;
565+
551566 result . content . forEach ( item => {
552567 if ( item . type === 'text' ) {
553568 console . log ( ` ${ item . text } ` ) ;
569+ } else if ( item . type === 'resource_link' ) {
570+ const resourceLink = item as ResourceLink ;
571+ resourceLinks . push ( resourceLink ) ;
572+ console . log ( ` 📁 Resource Link: ${ resourceLink . name } ` ) ;
573+ console . log ( ` URI: ${ resourceLink . uri } ` ) ;
574+ if ( resourceLink . mimeType ) {
575+ console . log ( ` Type: ${ resourceLink . mimeType } ` ) ;
576+ }
577+ if ( resourceLink . description ) {
578+ console . log ( ` Description: ${ resourceLink . description } ` ) ;
579+ }
580+ } else if ( item . type === 'resource' ) {
581+ console . log ( ` [Embedded Resource: ${ item . resource . uri } ]` ) ;
582+ } else if ( item . type === 'image' ) {
583+ console . log ( ` [Image: ${ item . mimeType } ]` ) ;
584+ } else if ( item . type === 'audio' ) {
585+ console . log ( ` [Audio: ${ item . mimeType } ]` ) ;
554586 } else {
555- console . log ( ` ${ item . type } content:` , item ) ;
587+ console . log ( ` [Unknown content type] :` , item ) ;
556588 }
557589 } ) ;
590+
591+ // Offer to read resource links
592+ if ( resourceLinks . length > 0 ) {
593+ console . log ( `\nFound ${ resourceLinks . length } resource link(s). Use 'read-resource <uri>' to read their content.` ) ;
594+ }
558595 } catch ( error ) {
559596 console . log ( `Error calling tool ${ name } : ${ error } ` ) ;
560597 }
@@ -589,7 +626,7 @@ async function runNotificationsToolWithResumability(interval: number, count: num
589626 try {
590627 console . log ( `Starting notification stream with resumability: interval=${ interval } ms, count=${ count || 'unlimited' } ` ) ;
591628 console . log ( `Using resumption token: ${ notificationsToolLastEventId || 'none' } ` ) ;
592-
629+
593630 const request : CallToolRequest = {
594631 method : 'tools/call' ,
595632 params : {
@@ -602,7 +639,7 @@ async function runNotificationsToolWithResumability(interval: number, count: num
602639 notificationsToolLastEventId = event ;
603640 console . log ( `Updated resumption token: ${ event } ` ) ;
604641 } ;
605-
642+
606643 const result = await client . request ( request , CallToolResultSchema , {
607644 resumptionToken : notificationsToolLastEventId ,
608645 onresumptiontoken : onLastEventIdUpdate
@@ -638,7 +675,7 @@ async function listPrompts(): Promise<void> {
638675 console . log ( ' No prompts available' ) ;
639676 } else {
640677 for ( const prompt of promptsResult . prompts ) {
641- console . log ( ` - ${ prompt . name } : ${ prompt . description } ` ) ;
678+ console . log ( ` - id: ${ prompt . name } , name: ${ getDisplayName ( prompt ) } , description : ${ prompt . description } ` ) ;
642679 }
643680 }
644681 } catch ( error ) {
@@ -689,14 +726,50 @@ async function listResources(): Promise<void> {
689726 console . log ( ' No resources available' ) ;
690727 } else {
691728 for ( const resource of resourcesResult . resources ) {
692- console . log ( ` - ${ resource . name } : ${ resource . uri } ` ) ;
729+ console . log ( ` - id: ${ resource . name } , name: ${ getDisplayName ( resource ) } , description : ${ resource . uri } ` ) ;
693730 }
694731 }
695732 } catch ( error ) {
696733 console . log ( `Resources not supported by this server (${ error } )` ) ;
697734 }
698735}
699736
737+ async function readResource ( uri : string ) : Promise < void > {
738+ if ( ! client ) {
739+ console . log ( 'Not connected to server.' ) ;
740+ return ;
741+ }
742+
743+ try {
744+ const request : ReadResourceRequest = {
745+ method : 'resources/read' ,
746+ params : { uri }
747+ } ;
748+
749+ console . log ( `Reading resource: ${ uri } ` ) ;
750+ const result = await client . request ( request , ReadResourceResultSchema ) ;
751+
752+ console . log ( 'Resource contents:' ) ;
753+ for ( const content of result . contents ) {
754+ console . log ( ` URI: ${ content . uri } ` ) ;
755+ if ( content . mimeType ) {
756+ console . log ( ` Type: ${ content . mimeType } ` ) ;
757+ }
758+
759+ if ( 'text' in content && typeof content . text === 'string' ) {
760+ console . log ( ' Content:' ) ;
761+ console . log ( ' ---' ) ;
762+ console . log ( content . text . split ( '\n' ) . map ( ( line : string ) => ' ' + line ) . join ( '\n' ) ) ;
763+ console . log ( ' ---' ) ;
764+ } else if ( 'blob' in content && typeof content . blob === 'string' ) {
765+ console . log ( ` [Binary data: ${ content . blob . length } bytes]` ) ;
766+ }
767+ }
768+ } catch ( error ) {
769+ console . log ( `Error reading resource ${ uri } : ${ error } ` ) ;
770+ }
771+ }
772+
700773async function cleanup ( ) : Promise < void > {
701774 if ( client && transport ) {
702775 try {
0 commit comments