@@ -23,7 +23,7 @@ describe("configureCoreTools", () => {
2323 let mockCoreApi : CoreApiMock ;
2424
2525 beforeEach ( ( ) => {
26- server = { tool : jest . fn ( ) } as unknown as McpServer ;
26+ server = { tool : jest . fn ( ) , server : { elicitInput : jest . fn ( ) } } as unknown as McpServer ;
2727 tokenProvider = jest . fn ( ) ;
2828 userAgentProvider = ( ) => "Jest" ;
2929
@@ -416,6 +416,108 @@ describe("configureCoreTools", () => {
416416 expect ( result . isError ) . toBe ( true ) ;
417417 expect ( result . content [ 0 ] . text ) . toContain ( "Error fetching project teams: Unknown error occurred" ) ;
418418 } ) ;
419+
420+ it ( "should elicit project when project is not provided and user accepts" , async ( ) => {
421+ configureCoreTools ( server , tokenProvider , connectionProvider , userAgentProvider ) ;
422+
423+ const call = ( server . tool as jest . Mock ) . mock . calls . find ( ( [ toolName ] ) => toolName === "core_list_project_teams" ) ;
424+ if ( ! call ) throw new Error ( "core_list_project_teams tool not registered" ) ;
425+ const [ , , , handler ] = call ;
426+
427+ ( mockCoreApi . getProjects as jest . Mock ) . mockResolvedValue ( [
428+ { id : "proj-1" , name : "ProjectAlpha" } ,
429+ { id : "proj-2" , name : "ProjectBeta" } ,
430+ ] ) ;
431+
432+ ( ( server as unknown as { server : { elicitInput : jest . Mock } } ) . server . elicitInput as jest . Mock ) . mockResolvedValue ( {
433+ action : "accept" ,
434+ content : { project : "ProjectAlpha" } ,
435+ } ) ;
436+
437+ ( mockCoreApi . getTeams as jest . Mock ) . mockResolvedValue ( [ { id : "team-1" , name : "Team One" } ] ) ;
438+
439+ const params = { project : undefined , mine : undefined , top : undefined , skip : undefined } ;
440+ const result = await handler ( params ) ;
441+
442+ expect ( mockCoreApi . getProjects ) . toHaveBeenCalledWith ( "wellFormed" , 100 , 0 , undefined , false ) ;
443+ expect ( ( server as unknown as { server : { elicitInput : jest . Mock } } ) . server . elicitInput ) . toHaveBeenCalled ( ) ;
444+ expect ( mockCoreApi . getTeams ) . toHaveBeenCalledWith ( "ProjectAlpha" , undefined , undefined , undefined , false ) ;
445+ expect ( result . content [ 0 ] . text ) . toContain ( "Team One" ) ;
446+ expect ( result . isError ) . toBeUndefined ( ) ;
447+ } ) ;
448+
449+ it ( "should return cancellation message when user declines elicitation" , async ( ) => {
450+ configureCoreTools ( server , tokenProvider , connectionProvider , userAgentProvider ) ;
451+
452+ const call = ( server . tool as jest . Mock ) . mock . calls . find ( ( [ toolName ] ) => toolName === "core_list_project_teams" ) ;
453+ if ( ! call ) throw new Error ( "core_list_project_teams tool not registered" ) ;
454+ const [ , , , handler ] = call ;
455+
456+ ( mockCoreApi . getProjects as jest . Mock ) . mockResolvedValue ( [ { id : "proj-1" , name : "ProjectAlpha" } ] ) ;
457+
458+ ( ( server as unknown as { server : { elicitInput : jest . Mock } } ) . server . elicitInput as jest . Mock ) . mockResolvedValue ( {
459+ action : "decline" ,
460+ } ) ;
461+
462+ const params = { project : undefined , mine : undefined , top : undefined , skip : undefined } ;
463+ const result = await handler ( params ) ;
464+
465+ expect ( mockCoreApi . getTeams ) . not . toHaveBeenCalled ( ) ;
466+ expect ( result . content [ 0 ] . text ) . toBe ( "Project selection cancelled." ) ;
467+ } ) ;
468+
469+ it ( "should fall back to project id when name is missing in elicitation options" , async ( ) => {
470+ configureCoreTools ( server , tokenProvider , connectionProvider , userAgentProvider ) ;
471+
472+ const call = ( server . tool as jest . Mock ) . mock . calls . find ( ( [ toolName ] ) => toolName === "core_list_project_teams" ) ;
473+ if ( ! call ) throw new Error ( "core_list_project_teams tool not registered" ) ;
474+ const [ , , , handler ] = call ;
475+
476+ ( mockCoreApi . getProjects as jest . Mock ) . mockResolvedValue ( [
477+ { id : "proj-1" , name : undefined } ,
478+ { id : undefined , name : undefined } ,
479+ ] ) ;
480+
481+ const elicitMock = ( server as unknown as { server : { elicitInput : jest . Mock } } ) . server . elicitInput as jest . Mock ;
482+ elicitMock . mockResolvedValue ( {
483+ action : "accept" ,
484+ content : { project : "proj-1" } ,
485+ } ) ;
486+
487+ ( mockCoreApi . getTeams as jest . Mock ) . mockResolvedValue ( [ { id : "team-1" , name : "Team One" } ] ) ;
488+
489+ const params = { project : undefined , mine : undefined , top : undefined , skip : undefined } ;
490+ const result = await handler ( params ) ;
491+
492+ const schema = elicitMock . mock . calls [ 0 ] [ 0 ] . requestedSchema ;
493+ const oneOf = schema . properties . project . oneOf ;
494+
495+ // Project with no name falls back to id
496+ expect ( oneOf [ 0 ] ) . toEqual ( { const : "proj-1" , title : "proj-1" } ) ;
497+ // Project with neither name nor id falls back to "" and "Unknown project"
498+ expect ( oneOf [ 1 ] ) . toEqual ( { const : "" , title : "Unknown project" } ) ;
499+
500+ expect ( mockCoreApi . getTeams ) . toHaveBeenCalledWith ( "proj-1" , undefined , undefined , undefined , false ) ;
501+ expect ( result . content [ 0 ] . text ) . toContain ( "Team One" ) ;
502+ } ) ;
503+
504+ it ( "should return error when no projects are available for elicitation" , async ( ) => {
505+ configureCoreTools ( server , tokenProvider , connectionProvider , userAgentProvider ) ;
506+
507+ const call = ( server . tool as jest . Mock ) . mock . calls . find ( ( [ toolName ] ) => toolName === "core_list_project_teams" ) ;
508+ if ( ! call ) throw new Error ( "core_list_project_teams tool not registered" ) ;
509+ const [ , , , handler ] = call ;
510+
511+ ( mockCoreApi . getProjects as jest . Mock ) . mockResolvedValue ( [ ] ) ;
512+
513+ const params = { project : undefined , mine : undefined , top : undefined , skip : undefined } ;
514+ const result = await handler ( params ) ;
515+
516+ expect ( ( server as unknown as { server : { elicitInput : jest . Mock } } ) . server . elicitInput ) . not . toHaveBeenCalled ( ) ;
517+ expect ( mockCoreApi . getTeams ) . not . toHaveBeenCalled ( ) ;
518+ expect ( result . isError ) . toBe ( true ) ;
519+ expect ( result . content [ 0 ] . text ) . toBe ( "No projects found to select from." ) ;
520+ } ) ;
419521 } ) ;
420522
421523 describe ( "get_identity_ids tool" , ( ) => {
0 commit comments