@@ -1945,6 +1945,98 @@ describe('outputSchema validation', () => {
19451945 ) ;
19461946 } ) ;
19471947
1948+ /***
1949+ * Test: Skip structuredContent validation when isError is true
1950+ */
1951+ test ( 'should not validate structuredContent when isError is true' , async ( ) => {
1952+ const server = new Server (
1953+ {
1954+ name : 'test-server' ,
1955+ version : '1.0.0'
1956+ } ,
1957+ {
1958+ capabilities : {
1959+ tools : { }
1960+ }
1961+ }
1962+ ) ;
1963+
1964+ // Set up server handlers
1965+ server . setRequestHandler ( 'initialize' , async request => ( {
1966+ protocolVersion : request . params . protocolVersion ,
1967+ capabilities : { tools : { } } ,
1968+ serverInfo : {
1969+ name : 'test-server' ,
1970+ version : '1.0.0'
1971+ }
1972+ } ) ) ;
1973+
1974+ server . setRequestHandler ( 'tools/list' , async ( ) => ( {
1975+ tools : [
1976+ {
1977+ name : 'test-tool' ,
1978+ description : 'A test tool' ,
1979+ inputSchema : {
1980+ type : 'object' ,
1981+ properties : { }
1982+ } ,
1983+ outputSchema : {
1984+ type : 'object' ,
1985+ properties : {
1986+ result : { type : 'string' }
1987+ } ,
1988+ required : [ 'result' ]
1989+ }
1990+ }
1991+ ]
1992+ } ) ) ;
1993+
1994+ server . setRequestHandler ( 'tools/call' , async ( ) => {
1995+ // Return isError with structuredContent that does NOT match the schema
1996+ return {
1997+ isError : true ,
1998+ content : [ { type : 'text' , text : 'Something went wrong' } ] ,
1999+ structuredContent : { wrongField : 123 }
2000+ } ;
2001+ } ) ;
2002+
2003+ const client = new Client (
2004+ {
2005+ name : 'test-client' ,
2006+ version : '1.0.0'
2007+ } ,
2008+ {
2009+ capabilities : {
2010+ tasks : {
2011+ requests : {
2012+ tools : {
2013+ call : { }
2014+ } ,
2015+ tasks : {
2016+ get : true ,
2017+ list : { } ,
2018+ result : true
2019+ }
2020+ }
2021+ }
2022+ }
2023+ }
2024+ ) ;
2025+
2026+ const [ clientTransport , serverTransport ] = InMemoryTransport . createLinkedPair ( ) ;
2027+
2028+ await Promise . all ( [ client . connect ( clientTransport ) , server . connect ( serverTransport ) ] ) ;
2029+
2030+ // List tools to cache the schemas
2031+ await client . listTools ( ) ;
2032+
2033+ // Call the tool - should NOT throw, error results skip validation
2034+ const result = await client . callTool ( { name : 'test-tool' } ) ;
2035+ expect ( result . isError ) . toBe ( true ) ;
2036+ expect ( result . content ) . toEqual ( [ { type : 'text' , text : 'Something went wrong' } ] ) ;
2037+ expect ( result . structuredContent ) . toEqual ( { wrongField : 123 } ) ;
2038+ } ) ;
2039+
19482040 /***
19492041 * Test: Handle Tools Without outputSchema Normally
19502042 */
@@ -3998,6 +4090,83 @@ test('callToolStream() should not validate structuredContent when isError is tru
39984090 await server . close ( ) ;
39994091} ) ;
40004092
4093+ test ( 'callToolStream() should not validate structuredContent when isError is true and structuredContent is invalid' , async ( ) => {
4094+ const server = new Server (
4095+ {
4096+ name : 'test-server' ,
4097+ version : '1.0.0'
4098+ } ,
4099+ {
4100+ capabilities : {
4101+ tools : { }
4102+ }
4103+ }
4104+ ) ;
4105+
4106+ server . setRequestHandler ( 'tools/list' , async ( ) => ( {
4107+ tools : [
4108+ {
4109+ name : 'test-tool' ,
4110+ description : 'A test tool' ,
4111+ inputSchema : {
4112+ type : 'object' ,
4113+ properties : { }
4114+ } ,
4115+ outputSchema : {
4116+ type : 'object' ,
4117+ properties : {
4118+ result : { type : 'string' }
4119+ } ,
4120+ required : [ 'result' ]
4121+ }
4122+ }
4123+ ]
4124+ } ) ) ;
4125+
4126+ server . setRequestHandler ( 'tools/call' , async ( ) => {
4127+ // Return isError with structuredContent that does NOT match the schema
4128+ return {
4129+ isError : true ,
4130+ content : [ { type : 'text' , text : 'Something went wrong' } ] ,
4131+ structuredContent : { wrongField : 123 }
4132+ } ;
4133+ } ) ;
4134+
4135+ const [ clientTransport , serverTransport ] = InMemoryTransport . createLinkedPair ( ) ;
4136+
4137+ const client = new Client (
4138+ {
4139+ name : 'test-client' ,
4140+ version : '1.0.0'
4141+ } ,
4142+ {
4143+ capabilities : { }
4144+ }
4145+ ) ;
4146+
4147+ await Promise . all ( [ client . connect ( clientTransport ) , server . connect ( serverTransport ) ] ) ;
4148+
4149+ await client . listTools ( ) ;
4150+
4151+ const stream = client . experimental . tasks . callToolStream ( { name : 'test-tool' , arguments : { } } ) ;
4152+
4153+ const messages = [ ] ;
4154+ for await ( const message of stream ) {
4155+ messages . push ( message ) ;
4156+ }
4157+
4158+ // Should have received result (not error), with isError flag set
4159+ expect ( messages . length ) . toBe ( 1 ) ;
4160+ expect ( messages [ 0 ] ! . type ) . toBe ( 'result' ) ;
4161+ if ( messages [ 0 ] ! . type === 'result' ) {
4162+ expect ( messages [ 0 ] ! . result . isError ) . toBe ( true ) ;
4163+ expect ( messages [ 0 ] ! . result . content ) . toEqual ( [ { type : 'text' , text : 'Something went wrong' } ] ) ;
4164+ }
4165+
4166+ await client . close ( ) ;
4167+ await server . close ( ) ;
4168+ } ) ;
4169+
40014170describe ( 'getSupportedElicitationModes' , ( ) => {
40024171 test ( 'should support nothing when capabilities are undefined' , ( ) => {
40034172 const result = getSupportedElicitationModes ( undefined ) ;
0 commit comments