@@ -17,13 +17,14 @@ import {
1717import { Tool } from '@modelcontextprotocol/sdk/types.js' ;
1818import { readEnv } from './util' ;
1919import { WorkerInput , WorkerOutput } from './code-tool-types' ;
20+ import { getLogger } from './logger' ;
2021import { SdkMethod } from './methods' ;
2122import { McpCodeExecutionMode } from './options' ;
2223import { ClientOptions } from '@tryfinch/finch-api' ;
2324
2425const prompt = `Runs JavaScript code to interact with the Finch API.
2526
26- You are a skilled programmer writing code to interface with the service.
27+ You are a skilled TypeScript programmer writing code to interface with the service.
2728Define an async function named "run" that takes a single parameter of an initialized SDK client and it will be run.
2829For example:
2930
@@ -40,7 +41,9 @@ You will be returned anything that your function returns, plus the results of an
4041Do not add try-catch blocks for single API calls. The tool will handle errors for you.
4142Do not add comments unless necessary for generating better code.
4243Code will run in a container, and cannot interact with the network outside of the given SDK client.
43- Variables will not persist between calls, so make sure to return or log any data you might need later.` ;
44+ Variables will not persist between calls, so make sure to return or log any data you might need later.
45+ Remember that you are writing TypeScript code, so you need to be careful with your types.
46+ Always type dynamic key-value stores explicitly as Record<string, YourValueType> instead of {}.` ;
4447
4548/**
4649 * A tool that runs code against a copy of the SDK.
@@ -82,6 +85,8 @@ export function codeTool({
8285 } ,
8386 } ;
8487
88+ const logger = getLogger ( ) ;
89+
8590 const handler = async ( {
8691 reqContext,
8792 args,
@@ -106,11 +111,27 @@ export function codeTool({
106111 }
107112 }
108113
114+ let result : ToolCallResult ;
115+ const startTime = Date . now ( ) ;
116+
109117 if ( codeExecutionMode === 'local' ) {
110- return await localDenoHandler ( { reqContext, args } ) ;
118+ logger . debug ( 'Executing code in local Deno environment' ) ;
119+ result = await localDenoHandler ( { reqContext, args } ) ;
111120 } else {
112- return await remoteStainlessHandler ( { reqContext, args } ) ;
121+ logger . debug ( 'Executing code in remote Stainless environment' ) ;
122+ result = await remoteStainlessHandler ( { reqContext, args } ) ;
113123 }
124+
125+ logger . info (
126+ {
127+ codeExecutionMode,
128+ durationMs : Date . now ( ) - startTime ,
129+ isError : result . isError ,
130+ contentRows : result . content ?. length ?? 0 ,
131+ } ,
132+ 'Got code tool execution result' ,
133+ ) ;
134+ return result ;
114135 } ;
115136
116137 return { metadata, tool, handler } ;
@@ -135,7 +156,7 @@ const remoteStainlessHandler = async ({
135156 headers : {
136157 ...( reqContext . stainlessApiKey && { Authorization : reqContext . stainlessApiKey } ) ,
137158 'Content-Type' : 'application/json' ,
138- client_envs : JSON . stringify ( {
159+ 'x-stainless-mcp-client-envs' : JSON . stringify ( {
139160 FINCH_CLIENT_ID : readEnv ( 'FINCH_CLIENT_ID' ) ?? client . clientID ?? undefined ,
140161 FINCH_CLIENT_SECRET : readEnv ( 'FINCH_CLIENT_SECRET' ) ?? client . clientSecret ?? undefined ,
141162 FINCH_WEBHOOK_SECRET : readEnv ( 'FINCH_WEBHOOK_SECRET' ) ?? client . webhookSecret ?? undefined ,
@@ -151,6 +172,11 @@ const remoteStainlessHandler = async ({
151172 } ) ;
152173
153174 if ( ! res . ok ) {
175+ if ( res . status === 404 && ! reqContext . stainlessApiKey ) {
176+ throw new Error (
177+ 'Could not access code tool for this project. You may need to provide a Stainless API key via the STAINLESS_API_KEY environment variable, the --stainless-api-key flag, or the x-stainless-api-key HTTP header.' ,
178+ ) ;
179+ }
154180 throw new Error (
155181 `${ res . status } : ${
156182 res . statusText
0 commit comments