@@ -15,10 +15,9 @@ import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
1515import { SIM_VIA_HEADER } from '@/lib/execution/call-chain'
1616import { parseRemainingExecutionDeadlineMs } from '@/lib/execution/execution-deadline-header'
1717import {
18- PRIVATE_TOOL_METADATA_RESPONSE_HEADER ,
19- RESOLVED_SECRET_PROVENANCE_FIELD ,
2018 RESOLVED_SECRET_PROVENANCE_METADATA_V1 ,
2119 requestsPrivateToolMetadata ,
20+ serializePrivateToolMetadataResponseEnvelope ,
2221} from '@/lib/execution/private-tool-metadata'
2322import {
2423 mcpBodyReadErrorResponse ,
@@ -33,7 +32,7 @@ import {
3332 type McpToolCall ,
3433 type McpToolResult ,
3534} from '@/lib/mcp/types'
36- import { categorizeError , createMcpErrorResponse , createMcpSuccessResponse } from '@/lib/mcp/utils'
35+ import { categorizeError } from '@/lib/mcp/utils'
3736import {
3837 assertPermissionsAllowed ,
3938 McpToolsNotAllowedError ,
@@ -66,23 +65,21 @@ function hasType(prop: unknown): prop is SchemaProperty {
6665 return typeof prop === 'object' && prop !== null && 'type' in prop
6766}
6867
69- async function attachPrivateProvenance (
70- response : NextResponse ,
71- provenance : ResolvedSecretTraceProvenanceAccumulator
72- ) : Promise < NextResponse > {
73- const parsed : unknown = await response . json ( )
74- if ( ! parsed || typeof parsed !== 'object' || Array . isArray ( parsed ) ) {
75- throw new Error ( 'MCP response is not a JSON object' )
68+ function createToolExecutionResponse (
69+ body : Record < string , unknown > ,
70+ status : number ,
71+ provenance : ResolvedSecretTraceProvenanceAccumulator | undefined
72+ ) : NextResponse {
73+ if ( ! provenance ) {
74+ return NextResponse . json ( body , { status } )
7675 }
77- const payload = parsed as Record < string , unknown >
78-
79- const headers = new Headers ( response . headers )
80- headers . delete ( 'content-length' )
81- headers . set ( PRIVATE_TOOL_METADATA_RESPONSE_HEADER , RESOLVED_SECRET_PROVENANCE_METADATA_V1 )
82- return NextResponse . json (
83- { ...payload , [ RESOLVED_SECRET_PROVENANCE_FIELD ] : provenance . exportProvenance ( ) } ,
84- { status : response . status , headers }
76+
77+ const envelope = serializePrivateToolMetadataResponseEnvelope (
78+ body ,
79+ RESOLVED_SECRET_PROVENANCE_METADATA_V1 ,
80+ provenance . exportProvenance ( )
8581 )
82+ return NextResponse . json ( envelope . body , { status, headers : envelope . headers } )
8683}
8784
8885/**
@@ -103,13 +100,22 @@ export const POST = withRouteHandler(
103100 resolvedSecretTraceProvenance . record ( provenance )
104101 }
105102 : undefined
106- const response = await ( async ( ) : Promise < NextResponse > => {
103+ const errorResponse = ( message : string , status : number ) : NextResponse =>
104+ createToolExecutionResponse (
105+ { success : false , error : message } ,
106+ status ,
107+ resolvedSecretTraceProvenance
108+ )
109+ const successResponse = < T > ( data : T , status = 200 ) : NextResponse =>
110+ createToolExecutionResponse ( { success : true , data } , status , resolvedSecretTraceProvenance )
111+
112+ return ( async ( ) : Promise < NextResponse > => {
107113 try {
108114 const rawBody = await readMcpJsonBodyWithLimit ( request )
109115 const parsedBody = mcpToolExecutionBodySchema . safeParse ( rawBody )
110116
111117 if ( ! parsedBody . success ) {
112- return createMcpErrorResponse ( parsedBody . error , 'Invalid request format' , 400 )
118+ return errorResponse ( 'Invalid request format' , 400 )
113119 }
114120
115121 const body = parsedBody . data
@@ -136,7 +142,7 @@ export const POST = withRouteHandler(
136142 } )
137143 } catch ( err ) {
138144 if ( err instanceof McpToolsNotAllowedError ) {
139- return createMcpErrorResponse ( err , err . message , 403 )
145+ return errorResponse ( err . message , 403 )
140146 }
141147 throw err
142148 }
@@ -160,11 +166,7 @@ export const POST = withRouteHandler(
160166 logger . warn ( `[${ requestId } ] Tool ${ toolName } not found on server ${ serverId } ` , {
161167 availableTools : tools . map ( ( t ) => t . name ) ,
162168 } )
163- return createMcpErrorResponse (
164- new Error ( 'Tool not found' ) ,
165- 'Tool not found on the specified server' ,
166- 404
167- )
169+ return errorResponse ( 'Tool not found on the specified server' , 404 )
168170 }
169171
170172 if ( tool . inputSchema ?. properties ) {
@@ -229,11 +231,7 @@ export const POST = withRouteHandler(
229231 const validationError = validateToolArguments ( tool , args )
230232 if ( validationError ) {
231233 logger . warn ( `[${ requestId } ] Tool validation failed: ${ validationError } ` )
232- return createMcpErrorResponse (
233- new Error ( `Invalid arguments for tool ${ toolName } : ${ validationError } ` ) ,
234- 'Invalid tool arguments' ,
235- 400
236- )
234+ return errorResponse ( 'Invalid tool arguments' , 400 )
237235 }
238236 }
239237
@@ -305,11 +303,7 @@ export const POST = withRouteHandler(
305303 logger . warn (
306304 `[${ requestId } ] Tool execution returned error for ${ toolName } on ${ serverId } `
307305 )
308- return createMcpErrorResponse (
309- transformedResult ,
310- transformedResult . error || 'Tool execution failed' ,
311- 400
312- )
306+ return errorResponse ( transformedResult . error || 'Tool execution failed' , 400 )
313307 }
314308 logger . info ( `[${ requestId } ] Successfully executed tool ${ toolName } on server ${ serverId } ` )
315309
@@ -330,7 +324,7 @@ export const POST = withRouteHandler(
330324 } )
331325 }
332326
333- return createMcpSuccessResponse ( transformedResult )
327+ return successResponse ( transformedResult )
334328 } catch ( error ) {
335329 if ( getErrorMessage ( error ) === 'Tool execution timeout' ) {
336330 resolvedSecretTraceProvenance ?. markIncomplete ( )
@@ -347,27 +341,24 @@ export const POST = withRouteHandler(
347341 logger . warn ( `[${ requestId } ] OAuth re-authorization required for MCP tool execution` , {
348342 serverId : errorServerId ,
349343 } )
350- return NextResponse . json (
344+ return createToolExecutionResponse (
351345 {
352346 success : false ,
353347 error : 'OAuth re-authorization required' ,
354348 code : 'reauth_required' ,
355349 serverId : errorServerId ,
356350 } ,
357- { status : 401 }
351+ 401 ,
352+ resolvedSecretTraceProvenance
358353 )
359354 }
360355
361356 logger . error ( `[${ requestId } ] Error executing MCP tool:` , error )
362357
363358 const { message, status } = categorizeError ( error )
364- return createMcpErrorResponse ( new Error ( message ) , message , status )
359+ return errorResponse ( message , status )
365360 }
366361 } ) ( )
367-
368- return resolvedSecretTraceProvenance
369- ? attachPrivateProvenance ( response , resolvedSecretTraceProvenance )
370- : response
371362 }
372363 )
373364)
0 commit comments