@@ -30,12 +30,12 @@ export interface McpProjectionInput {
3030 toolName : string ;
3131 args : Record < string , unknown > ;
3232 blocks : MCPContentBlock [ ] ;
33- structuredContent ?: Record < string , unknown > ;
33+ structuredContent ?: Record < string , unknown > | unknown [ ] ;
3434}
3535
3636export interface McpProjectionOutput {
3737 blocks : MCPContentBlock [ ] ;
38- structuredContent ?: Record < string , unknown > ;
38+ structuredContent ?: Record < string , unknown > | unknown [ ] ;
3939}
4040
4141export function applyMcpResultProjection (
@@ -62,7 +62,7 @@ export function applyMcpResultProjection(
6262 const structuredContent =
6363 input . structuredContent === undefined
6464 ? undefined
65- : asRecord (
65+ : asProjectedStructured (
6666 projectMcpJsonValue (
6767 input . structuredContent ,
6868 fields . keys ,
@@ -91,13 +91,10 @@ export function projectMcpJsonValue(
9191 }
9292 if ( ! isRecord ( value ) ) return value ;
9393
94- const recordArrays = Object . entries ( value ) . filter (
95- ( [ , item ] ) => Array . isArray ( item ) && item . some ( ( entry ) => isRecord ( entry ) ) ,
96- ) ;
97- if ( recordArrays . length > 0 ) {
94+ if ( isListEnvelope ( value ) ) {
9895 const out = Object . create ( null ) as Record < string , unknown > ;
9996 for ( const [ key , item ] of Object . entries ( value ) ) {
100- if ( Array . isArray ( item ) && item . some ( ( entry ) => isRecord ( entry ) ) ) {
97+ if ( isProjectedList ( item ) ) {
10198 out [ key ] = item . map ( ( entry ) =>
10299 isRecord ( entry )
103100 ? pickEntityFields ( entry , fields , shortenNestedRefs , applyAliases )
@@ -236,8 +233,31 @@ function copyField(value: unknown, shortenNestedRefs: boolean): unknown {
236233 return Object . keys ( nested ) . length > 0 ? nested : undefined ;
237234}
238235
239- function asRecord ( value : unknown ) : Record < string , unknown > | undefined {
240- return isRecord ( value ) ? value : undefined ;
236+ function asProjectedStructured (
237+ value : unknown ,
238+ ) : Record < string , unknown > | unknown [ ] | undefined {
239+ if ( isRecord ( value ) || Array . isArray ( value ) ) return value ;
240+ return undefined ;
241+ }
242+
243+ function isListEnvelope ( value : Record < string , unknown > ) : boolean {
244+ let sawRecordArray = false ;
245+ let sawEmptyArray = false ;
246+ for ( const item of Object . values ( value ) ) {
247+ if ( ! Array . isArray ( item ) ) continue ;
248+ if ( item . some ( ( entry ) => isRecord ( entry ) ) ) sawRecordArray = true ;
249+ else if ( item . length === 0 ) sawEmptyArray = true ;
250+ }
251+ if ( sawRecordArray ) return true ;
252+ if ( ! sawEmptyArray ) return false ;
253+ return ! Object . hasOwn ( value , "id" ) && ! Object . hasOwn ( value , "identifier" ) ;
254+ }
255+
256+ function isProjectedList ( value : unknown ) : value is unknown [ ] {
257+ return (
258+ Array . isArray ( value ) &&
259+ ( value . length === 0 || value . some ( ( entry ) => isRecord ( entry ) ) )
260+ ) ;
241261}
242262
243263function isRecord ( value : unknown ) : value is Record < string , unknown > {
0 commit comments