@@ -14,7 +14,11 @@ import {
1414 ListResourcesResultSchema ,
1515 LoggingMessageNotificationSchema ,
1616 ResourceListChangedNotificationSchema ,
17+ ReadResourceRequest ,
18+ ReadResourceResultSchema ,
19+ ResourceLink ,
1720} from '../../types.js' ;
21+ import { getDisplayName } from '../../shared/metadataUtils.js' ;
1822
1923// Create readline interface for user input
2024const readline = createInterface ( {
@@ -59,6 +63,7 @@ function printHelp(): void {
5963 console . log ( ' list-prompts - List available prompts' ) ;
6064 console . log ( ' get-prompt [name] [args] - Get a prompt with optional JSON arguments' ) ;
6165 console . log ( ' list-resources - List available resources' ) ;
66+ console . log ( ' read-resource <uri> - Read a specific resource by URI' ) ;
6267 console . log ( ' help - Show this help' ) ;
6368 console . log ( ' quit - Exit the program' ) ;
6469}
@@ -154,6 +159,14 @@ function commandLoop(): void {
154159 await listResources ( ) ;
155160 break ;
156161
162+ case 'read-resource' :
163+ if ( args . length < 2 ) {
164+ console . log ( 'Usage: read-resource <uri>' ) ;
165+ } else {
166+ await readResource ( args [ 1 ] ) ;
167+ }
168+ break ;
169+
157170 case 'help' :
158171 printHelp ( ) ;
159172 break ;
@@ -317,7 +330,7 @@ async function listTools(): Promise<void> {
317330 console . log ( ' No tools available' ) ;
318331 } else {
319332 for ( const tool of toolsResult . tools ) {
320- console . log ( ` - ${ tool . name } : ${ tool . description } ` ) ;
333+ console . log ( ` - id: ${ tool . name } , name: ${ getDisplayName ( tool ) } , description : ${ tool . description } ` ) ;
321334 }
322335 }
323336 } catch ( error ) {
@@ -344,13 +357,37 @@ async function callTool(name: string, args: Record<string, unknown>): Promise<vo
344357 const result = await client . request ( request , CallToolResultSchema ) ;
345358
346359 console . log ( 'Tool result:' ) ;
360+ const resourceLinks : ResourceLink [ ] = [ ] ;
361+
347362 result . content . forEach ( item => {
348363 if ( item . type === 'text' ) {
349364 console . log ( ` ${ item . text } ` ) ;
365+ } else if ( item . type === 'resource_link' ) {
366+ const resourceLink = item as ResourceLink ;
367+ resourceLinks . push ( resourceLink ) ;
368+ console . log ( ` 📁 Resource Link: ${ resourceLink . name } ` ) ;
369+ console . log ( ` URI: ${ resourceLink . uri } ` ) ;
370+ if ( resourceLink . mimeType ) {
371+ console . log ( ` Type: ${ resourceLink . mimeType } ` ) ;
372+ }
373+ if ( resourceLink . description ) {
374+ console . log ( ` Description: ${ resourceLink . description } ` ) ;
375+ }
376+ } else if ( item . type === 'resource' ) {
377+ console . log ( ` [Embedded Resource: ${ item . resource . uri } ]` ) ;
378+ } else if ( item . type === 'image' ) {
379+ console . log ( ` [Image: ${ item . mimeType } ]` ) ;
380+ } else if ( item . type === 'audio' ) {
381+ console . log ( ` [Audio: ${ item . mimeType } ]` ) ;
350382 } else {
351- console . log ( ` ${ item . type } content:` , item ) ;
383+ console . log ( ` [Unknown content type] :` , item ) ;
352384 }
353385 } ) ;
386+
387+ // Offer to read resource links
388+ if ( resourceLinks . length > 0 ) {
389+ console . log ( `\nFound ${ resourceLinks . length } resource link(s). Use 'read-resource <uri>' to read their content.` ) ;
390+ }
354391 } catch ( error ) {
355392 console . log ( `Error calling tool ${ name } : ${ error } ` ) ;
356393 }
@@ -380,7 +417,7 @@ async function runNotificationsToolWithResumability(interval: number, count: num
380417 try {
381418 console . log ( `Starting notification stream with resumability: interval=${ interval } ms, count=${ count || 'unlimited' } ` ) ;
382419 console . log ( `Using resumption token: ${ notificationsToolLastEventId || 'none' } ` ) ;
383-
420+
384421 const request : CallToolRequest = {
385422 method : 'tools/call' ,
386423 params : {
@@ -393,7 +430,7 @@ async function runNotificationsToolWithResumability(interval: number, count: num
393430 notificationsToolLastEventId = event ;
394431 console . log ( `Updated resumption token: ${ event } ` ) ;
395432 } ;
396-
433+
397434 const result = await client . request ( request , CallToolResultSchema , {
398435 resumptionToken : notificationsToolLastEventId ,
399436 onresumptiontoken : onLastEventIdUpdate
@@ -429,7 +466,7 @@ async function listPrompts(): Promise<void> {
429466 console . log ( ' No prompts available' ) ;
430467 } else {
431468 for ( const prompt of promptsResult . prompts ) {
432- console . log ( ` - ${ prompt . name } : ${ prompt . description } ` ) ;
469+ console . log ( ` - id: ${ prompt . name } , name: ${ getDisplayName ( prompt ) } , description : ${ prompt . description } ` ) ;
433470 }
434471 }
435472 } catch ( error ) {
@@ -480,14 +517,50 @@ async function listResources(): Promise<void> {
480517 console . log ( ' No resources available' ) ;
481518 } else {
482519 for ( const resource of resourcesResult . resources ) {
483- console . log ( ` - ${ resource . name } : ${ resource . uri } ` ) ;
520+ console . log ( ` - id: ${ resource . name } , name: ${ getDisplayName ( resource ) } , description : ${ resource . uri } ` ) ;
484521 }
485522 }
486523 } catch ( error ) {
487524 console . log ( `Resources not supported by this server (${ error } )` ) ;
488525 }
489526}
490527
528+ async function readResource ( uri : string ) : Promise < void > {
529+ if ( ! client ) {
530+ console . log ( 'Not connected to server.' ) ;
531+ return ;
532+ }
533+
534+ try {
535+ const request : ReadResourceRequest = {
536+ method : 'resources/read' ,
537+ params : { uri }
538+ } ;
539+
540+ console . log ( `Reading resource: ${ uri } ` ) ;
541+ const result = await client . request ( request , ReadResourceResultSchema ) ;
542+
543+ console . log ( 'Resource contents:' ) ;
544+ for ( const content of result . contents ) {
545+ console . log ( ` URI: ${ content . uri } ` ) ;
546+ if ( content . mimeType ) {
547+ console . log ( ` Type: ${ content . mimeType } ` ) ;
548+ }
549+
550+ if ( 'text' in content && typeof content . text === 'string' ) {
551+ console . log ( ' Content:' ) ;
552+ console . log ( ' ---' ) ;
553+ console . log ( content . text . split ( '\n' ) . map ( ( line : string ) => ' ' + line ) . join ( '\n' ) ) ;
554+ console . log ( ' ---' ) ;
555+ } else if ( 'blob' in content && typeof content . blob === 'string' ) {
556+ console . log ( ` [Binary data: ${ content . blob . length } bytes]` ) ;
557+ }
558+ }
559+ } catch ( error ) {
560+ console . log ( `Error reading resource ${ uri } : ${ error } ` ) ;
561+ }
562+ }
563+
491564async function cleanup ( ) : Promise < void > {
492565 if ( client && transport ) {
493566 try {
0 commit comments