@@ -459,6 +459,168 @@ describe('lightspeed router tests', () => {
459459 expect ( receivedData ) . toEqual ( expectedData ) ;
460460 } ) ;
461461
462+ it ( 'should send MCP headers for multiple MCP servers' , async ( ) => {
463+ let capturedMcpHeaders : string | null = null ;
464+
465+ rcs . use (
466+ http . post (
467+ `${ LOCAL_LCS_ADDR } /v1/streaming_query` ,
468+ ( { request : req } ) => {
469+ capturedMcpHeaders = req . headers . get ( 'MCP-HEADERS' ) ;
470+ const textEncoder = new TextEncoder ( ) ;
471+ const mockData = [
472+ {
473+ choices : [ { delta : { content : 'Test' } , finish_reason : null } ] ,
474+ } ,
475+ { choices : [ { delta : { } , finish_reason : 'stop' } ] } ,
476+ ] ;
477+ const stream = new ReadableStream ( {
478+ start ( controller ) {
479+ mockData . forEach ( ( chunk : any ) => {
480+ controller . enqueue (
481+ textEncoder . encode ( `data: ${ JSON . stringify ( chunk ) } \n\n` ) ,
482+ ) ;
483+ } ) ;
484+ controller . close ( ) ;
485+ } ,
486+ } ) ;
487+ return new HttpResponse ( stream , {
488+ headers : { 'Content-Type' : 'text/plain' } ,
489+ } ) ;
490+ } ,
491+ ) ,
492+ ) ;
493+
494+ const backendServer = await startBackendServer ( {
495+ lightspeed : {
496+ ...BASE_CONFIG . lightspeed ,
497+ mcpServers : [
498+ { name : 'mcp-server-1' , token : 'token-1' } ,
499+ { name : 'mcp-server-2' , token : 'token-2' } ,
500+ ] ,
501+ } ,
502+ } ) ;
503+
504+ const response = await request ( backendServer )
505+ . post ( '/api/lightspeed/v1/query' )
506+ . send ( {
507+ model : mockModel ,
508+ query : 'Hello' ,
509+ provider : 'test-server' ,
510+ } ) ;
511+
512+ expect ( response . statusCode ) . toEqual ( 200 ) ;
513+ expect ( capturedMcpHeaders ) . not . toBeNull ( ) ;
514+
515+ const parsedHeaders = JSON . parse ( capturedMcpHeaders ! ) ;
516+ expect ( parsedHeaders ) . toEqual ( {
517+ 'mcp-server-1' : { Authorization : 'Bearer token-1' } ,
518+ 'mcp-server-2' : { Authorization : 'Bearer token-2' } ,
519+ } ) ;
520+ } ) ;
521+
522+ it ( 'should send empty MCP headers when no MCP servers configured' , async ( ) => {
523+ let capturedMcpHeaders : string | null = null ;
524+
525+ rcs . use (
526+ http . post (
527+ `${ LOCAL_LCS_ADDR } /v1/streaming_query` ,
528+ ( { request : req } ) => {
529+ capturedMcpHeaders = req . headers . get ( 'MCP-HEADERS' ) ;
530+ const textEncoder = new TextEncoder ( ) ;
531+ const mockData = [
532+ {
533+ choices : [ { delta : { content : 'Test' } , finish_reason : null } ] ,
534+ } ,
535+ { choices : [ { delta : { } , finish_reason : 'stop' } ] } ,
536+ ] ;
537+ const stream = new ReadableStream ( {
538+ start ( controller ) {
539+ mockData . forEach ( ( chunk : any ) => {
540+ controller . enqueue (
541+ textEncoder . encode ( `data: ${ JSON . stringify ( chunk ) } \n\n` ) ,
542+ ) ;
543+ } ) ;
544+ controller . close ( ) ;
545+ } ,
546+ } ) ;
547+ return new HttpResponse ( stream , {
548+ headers : { 'Content-Type' : 'text/plain' } ,
549+ } ) ;
550+ } ,
551+ ) ,
552+ ) ;
553+
554+ const backendServer = await startBackendServer ( ) ;
555+
556+ const response = await request ( backendServer )
557+ . post ( '/api/lightspeed/v1/query' )
558+ . send ( {
559+ model : mockModel ,
560+ query : 'Hello' ,
561+ provider : 'test-server' ,
562+ } ) ;
563+
564+ expect ( response . statusCode ) . toEqual ( 200 ) ;
565+ expect ( capturedMcpHeaders ) . toBe ( '' ) ;
566+ } ) ;
567+
568+ it ( 'should send MCP headers for single MCP server' , async ( ) => {
569+ let capturedMcpHeaders : string | null = null ;
570+
571+ rcs . use (
572+ http . post (
573+ `${ LOCAL_LCS_ADDR } /v1/streaming_query` ,
574+ ( { request : req } ) => {
575+ capturedMcpHeaders = req . headers . get ( 'MCP-HEADERS' ) ;
576+ const textEncoder = new TextEncoder ( ) ;
577+ const mockData = [
578+ {
579+ choices : [ { delta : { content : 'Test' } , finish_reason : null } ] ,
580+ } ,
581+ { choices : [ { delta : { } , finish_reason : 'stop' } ] } ,
582+ ] ;
583+ const stream = new ReadableStream ( {
584+ start ( controller ) {
585+ mockData . forEach ( ( chunk : any ) => {
586+ controller . enqueue (
587+ textEncoder . encode ( `data: ${ JSON . stringify ( chunk ) } \n\n` ) ,
588+ ) ;
589+ } ) ;
590+ controller . close ( ) ;
591+ } ,
592+ } ) ;
593+ return new HttpResponse ( stream , {
594+ headers : { 'Content-Type' : 'text/plain' } ,
595+ } ) ;
596+ } ,
597+ ) ,
598+ ) ;
599+
600+ const backendServer = await startBackendServer ( {
601+ lightspeed : {
602+ ...BASE_CONFIG . lightspeed ,
603+ mcpServers : [ { name : 'single-mcp-server' , token : 'single-token' } ] ,
604+ } ,
605+ } ) ;
606+
607+ const response = await request ( backendServer )
608+ . post ( '/api/lightspeed/v1/query' )
609+ . send ( {
610+ model : mockModel ,
611+ query : 'Hello' ,
612+ provider : 'test-server' ,
613+ } ) ;
614+
615+ expect ( response . statusCode ) . toEqual ( 200 ) ;
616+ expect ( capturedMcpHeaders ) . not . toBeNull ( ) ;
617+
618+ const parsedHeaders = JSON . parse ( capturedMcpHeaders ! ) ;
619+ expect ( parsedHeaders ) . toEqual ( {
620+ 'single-mcp-server' : { Authorization : 'Bearer single-token' } ,
621+ } ) ;
622+ } ) ;
623+
462624 it ( 'should fail with unauthorized error in chat completion API' , async ( ) => {
463625 const backendServer = await startBackendServer ( { } , AuthorizeResult . DENY ) ;
464626 const chatCompletionResponse = await request ( backendServer )
0 commit comments