@@ -356,4 +356,172 @@ describe('McpService', () => {
356356 expect ( text ) . toContain ( 'airbnb' ) ;
357357 } ) ;
358358 } ) ;
359+
360+ describe ( 'Error handling' , ( ) => {
361+ describe ( 'Resources errors' , ( ) => {
362+ it ( 'should throw error for invalid URI scheme' , async ( ) => {
363+ const handler = handlers . get ( 'resources/read' ) ;
364+ expect ( handler ) . toBeDefined ( ) ;
365+
366+ await expect (
367+ handler ! ( { params : { uri : 'invalid://something' } } ) ,
368+ ) . rejects . toThrow ( 'Invalid URI scheme' ) ;
369+ } ) ;
370+
371+ it ( 'should throw error when rules resource not found' , async ( ) => {
372+ vi . mocked ( mockRulesService . getRuleContent ) . mockRejectedValue (
373+ new Error ( 'File not found' ) ,
374+ ) ;
375+
376+ const handler = handlers . get ( 'resources/read' ) ;
377+ expect ( handler ) . toBeDefined ( ) ;
378+
379+ await expect (
380+ handler ! ( { params : { uri : 'rules://nonexistent.md' } } ) ,
381+ ) . rejects . toThrow ( 'Resource not found' ) ;
382+ } ) ;
383+
384+ it ( 'should throw error when config://project fails to load' , async ( ) => {
385+ handlers . clear ( ) ;
386+ const failingConfigService = createMockConfigService ( { } ) ;
387+ vi . mocked ( failingConfigService . getProjectConfig ) . mockRejectedValue (
388+ new Error ( 'Config load error' ) ,
389+ ) ;
390+
391+ const service = new McpService (
392+ mockRulesService as RulesService ,
393+ mockKeywordService as KeywordService ,
394+ failingConfigService as ConfigService ,
395+ ) ;
396+ service . onModuleInit ( ) ;
397+
398+ const handler = handlers . get ( 'resources/read' ) ;
399+ expect ( handler ) . toBeDefined ( ) ;
400+
401+ await expect (
402+ handler ! ( { params : { uri : 'config://project' } } ) ,
403+ ) . rejects . toThrow ( 'Failed to load project configuration' ) ;
404+ } ) ;
405+ } ) ;
406+
407+ describe ( 'Tools errors' , ( ) => {
408+ it ( 'should throw error for unknown tool' , async ( ) => {
409+ const handler = handlers . get ( 'tools/call' ) ;
410+ expect ( handler ) . toBeDefined ( ) ;
411+
412+ await expect (
413+ handler ! ( { params : { name : 'unknown_tool' , arguments : { } } } ) ,
414+ ) . rejects . toThrow ( 'Tool not found: unknown_tool' ) ;
415+ } ) ;
416+
417+ it ( 'should return error response when get_agent_details fails' , async ( ) => {
418+ vi . mocked ( mockRulesService . getAgent ) . mockRejectedValue (
419+ new Error ( 'Agent not found' ) ,
420+ ) ;
421+
422+ const handler = handlers . get ( 'tools/call' ) ;
423+ expect ( handler ) . toBeDefined ( ) ;
424+
425+ const result = ( await handler ! ( {
426+ params : { name : 'get_agent_details' , arguments : { agentName : 'invalid' } } ,
427+ } ) ) as { isError : boolean ; content : { text : string } [ ] } ;
428+
429+ expect ( result . isError ) . toBe ( true ) ;
430+ expect ( result . content [ 0 ] . text ) . toContain ( "Agent 'invalid' not found" ) ;
431+ } ) ;
432+
433+ it ( 'should return error response when parse_mode fails' , async ( ) => {
434+ vi . mocked ( mockKeywordService . parseMode ) . mockRejectedValue (
435+ new Error ( 'Parse error' ) ,
436+ ) ;
437+
438+ const handler = handlers . get ( 'tools/call' ) ;
439+ expect ( handler ) . toBeDefined ( ) ;
440+
441+ const result = ( await handler ! ( {
442+ params : { name : 'parse_mode' , arguments : { prompt : 'INVALID test' } } ,
443+ } ) ) as { isError : boolean ; content : { text : string } [ ] } ;
444+
445+ expect ( result . isError ) . toBe ( true ) ;
446+ expect ( result . content [ 0 ] . text ) . toContain ( 'Failed to parse mode' ) ;
447+ } ) ;
448+
449+ it ( 'should return error response when get_project_config fails' , async ( ) => {
450+ handlers . clear ( ) ;
451+ const failingConfigService = createMockConfigService ( { } ) ;
452+ vi . mocked ( failingConfigService . getSettings ) . mockRejectedValue (
453+ new Error ( 'Settings error' ) ,
454+ ) ;
455+
456+ const service = new McpService (
457+ mockRulesService as RulesService ,
458+ mockKeywordService as KeywordService ,
459+ failingConfigService as ConfigService ,
460+ ) ;
461+ service . onModuleInit ( ) ;
462+
463+ const handler = handlers . get ( 'tools/call' ) ;
464+ expect ( handler ) . toBeDefined ( ) ;
465+
466+ const result = ( await handler ! ( {
467+ params : { name : 'get_project_config' , arguments : { } } ,
468+ } ) ) as { isError : boolean ; content : { text : string } [ ] } ;
469+
470+ expect ( result . isError ) . toBe ( true ) ;
471+ expect ( result . content [ 0 ] . text ) . toContain ( 'Failed to get project config' ) ;
472+ } ) ;
473+ } ) ;
474+
475+ describe ( 'Prompts errors' , ( ) => {
476+ it ( 'should throw error when agent not found in activate_agent' , async ( ) => {
477+ vi . mocked ( mockRulesService . getAgent ) . mockRejectedValue (
478+ new Error ( 'Agent not found' ) ,
479+ ) ;
480+
481+ const handler = handlers . get ( 'prompts/get' ) ;
482+ expect ( handler ) . toBeDefined ( ) ;
483+
484+ await expect (
485+ handler ! ( {
486+ params : { name : 'activate_agent' , arguments : { role : 'invalid-agent' } } ,
487+ } ) ,
488+ ) . rejects . toThrow ( "Agent 'invalid-agent' not found" ) ;
489+ } ) ;
490+
491+ it ( 'should throw error for unknown prompt' , async ( ) => {
492+ const handler = handlers . get ( 'prompts/get' ) ;
493+ expect ( handler ) . toBeDefined ( ) ;
494+
495+ await expect (
496+ handler ! ( { params : { name : 'unknown_prompt' , arguments : { } } } ) ,
497+ ) . rejects . toThrow ( 'Prompt not found' ) ;
498+ } ) ;
499+ } ) ;
500+ } ) ;
501+
502+ describe ( 'startStdio' , ( ) => {
503+ it ( 'should connect server with StdioServerTransport' , async ( ) => {
504+ const service = new McpService (
505+ mockRulesService as RulesService ,
506+ mockKeywordService as KeywordService ,
507+ mockConfigService as ConfigService ,
508+ ) ;
509+
510+ // Should not throw
511+ await expect ( service . startStdio ( ) ) . resolves . not . toThrow ( ) ;
512+ } ) ;
513+ } ) ;
514+
515+ describe ( 'getServer' , ( ) => {
516+ it ( 'should return the MCP server instance' , ( ) => {
517+ const service = new McpService (
518+ mockRulesService as RulesService ,
519+ mockKeywordService as KeywordService ,
520+ mockConfigService as ConfigService ,
521+ ) ;
522+
523+ const server = service . getServer ( ) ;
524+ expect ( server ) . toBeDefined ( ) ;
525+ } ) ;
526+ } ) ;
359527} ) ;
0 commit comments