@@ -12,7 +12,7 @@ import { type LoggingLevel, SetLevelRequestSchema } from '@modelcontextprotocol/
12
12
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
13
13
import { z } from 'zod'
14
14
import { Buffer } from 'node:buffer'
15
- import { asXml , runCode , runCodeWithToolInjection , type ToolInjectionConfig } from './runCode.ts'
15
+ import { asXml , runCode , type RunError , type RunSuccess , type ToolInjectionConfig } from './runCode.ts'
16
16
17
17
const VERSION = '0.0.14'
18
18
@@ -50,6 +50,85 @@ options:
50
50
}
51
51
}
52
52
53
+ /*
54
+ * Helper function to create a logging handler
55
+ */
56
+ function createLogHandler (
57
+ setLogLevel : LoggingLevel ,
58
+ logPromises : Promise < void > [ ] ,
59
+ server : McpServer ,
60
+ ) {
61
+ return ( level : LoggingLevel , data : string ) => {
62
+ if ( LogLevels . indexOf ( level ) >= LogLevels . indexOf ( setLogLevel ) ) {
63
+ logPromises . push ( server . server . sendLoggingMessage ( { level, data } ) )
64
+ }
65
+ }
66
+ }
67
+
68
+ /*
69
+ * Helper function to build unified response
70
+ */
71
+ async function buildResponse (
72
+ result : RunSuccess | RunError ,
73
+ logPromises : Promise < void > [ ] ,
74
+ ) {
75
+ await Promise . all ( logPromises )
76
+ return {
77
+ content : [ { type : 'text' as const , text : asXml ( result ) } ] ,
78
+ }
79
+ }
80
+
81
+ /*
82
+ * Create elicitation callback for tool execution
83
+ */
84
+ function createElicitationCallback (
85
+ server : McpServer ,
86
+ logPromises : Promise < void > [ ] ,
87
+ ) {
88
+ // deno-lint-ignore no-explicit-any
89
+ return async ( elicitationRequest : any ) => {
90
+ // Convert Python dict to JavaScript object if needed
91
+ let jsRequest
92
+ if ( elicitationRequest && typeof elicitationRequest === 'object' && elicitationRequest . toJs ) {
93
+ jsRequest = elicitationRequest . toJs ( )
94
+ } else if ( elicitationRequest && typeof elicitationRequest === 'object' ) {
95
+ // Handle Python dict-like objects
96
+ jsRequest = {
97
+ message : elicitationRequest . message || elicitationRequest . get ?.( 'message' ) ,
98
+ requestedSchema : elicitationRequest . requestedSchema || elicitationRequest . get ?.( 'requestedSchema' ) ,
99
+ }
100
+ } else {
101
+ jsRequest = elicitationRequest
102
+ }
103
+
104
+ try {
105
+ const elicitationResult = await server . server . request (
106
+ {
107
+ method : 'elicitation/create' ,
108
+ params : {
109
+ message : jsRequest . message ,
110
+ requestedSchema : jsRequest . requestedSchema ,
111
+ } ,
112
+ } ,
113
+ z . object ( {
114
+ action : z . enum ( [ 'accept' , 'decline' , 'cancel' ] ) ,
115
+ content : z . optional ( z . record ( z . string ( ) , z . unknown ( ) ) ) ,
116
+ } ) ,
117
+ )
118
+
119
+ return elicitationResult
120
+ } catch ( error ) {
121
+ logPromises . push (
122
+ server . server . sendLoggingMessage ( {
123
+ level : 'error' ,
124
+ data : `Elicitation error: ${ error } ` ,
125
+ } ) ,
126
+ )
127
+ throw error
128
+ }
129
+ }
130
+ }
131
+
53
132
/*
54
133
* Create an MCP server with the `run_python_code` tool registered.
55
134
*/
@@ -118,64 +197,18 @@ The tools are injected into the global namespace automatically - no discovery fu
118
197
119
198
// Check if tools are provided
120
199
if ( tools . length > 0 ) {
121
- // Create elicitation callback
122
- // deno-lint-ignore no-explicit-any
123
- const elicitationCallback = async ( elicitationRequest : any ) => {
124
- // Convert Python dict to JavaScript object if needed
125
- let jsRequest
126
- if ( elicitationRequest && typeof elicitationRequest === 'object' && elicitationRequest . toJs ) {
127
- jsRequest = elicitationRequest . toJs ( )
128
- } else if ( elicitationRequest && typeof elicitationRequest === 'object' ) {
129
- // Handle Python dict-like objects
130
- jsRequest = {
131
- message : elicitationRequest . message || elicitationRequest . get ?.( 'message' ) ,
132
- requestedSchema : elicitationRequest . requestedSchema || elicitationRequest . get ?.( 'requestedSchema' ) ,
133
- }
134
- } else {
135
- jsRequest = elicitationRequest
136
- }
137
-
138
- try {
139
- const elicitationResult = await server . server . request (
140
- {
141
- method : 'elicitation/create' ,
142
- params : {
143
- message : jsRequest . message ,
144
- requestedSchema : jsRequest . requestedSchema ,
145
- } ,
146
- } ,
147
- z . object ( {
148
- action : z . enum ( [ 'accept' , 'decline' , 'cancel' ] ) ,
149
- content : z . optional ( z . record ( z . string ( ) , z . unknown ( ) ) ) ,
150
- } ) ,
151
- )
152
-
153
- return elicitationResult
154
- } catch ( error ) {
155
- logPromises . push (
156
- server . server . sendLoggingMessage ( {
157
- level : 'error' ,
158
- data : `Elicitation error: ${ error } ` ,
159
- } ) ,
160
- )
161
- throw error
162
- }
163
- }
200
+ const elicitationCallback = createElicitationCallback ( server , logPromises )
164
201
165
202
// Use tool injection mode
166
- const result = await runCodeWithToolInjection (
203
+ const result = await runCode (
167
204
[
168
205
{
169
206
name : 'main.py' ,
170
207
content : python_code ,
171
208
active : true ,
172
209
} ,
173
210
] ,
174
- ( level , data ) => {
175
- if ( LogLevels . indexOf ( level ) >= LogLevels . indexOf ( setLogLevel ) ) {
176
- logPromises . push ( server . server . sendLoggingMessage ( { level, data } ) )
177
- }
178
- } ,
211
+ createLogHandler ( setLogLevel , logPromises , server ) ,
179
212
{
180
213
enableToolInjection : true ,
181
214
availableTools : tools ,
@@ -184,11 +217,7 @@ The tools are injected into the global namespace automatically - no discovery fu
184
217
} as ToolInjectionConfig ,
185
218
)
186
219
187
- await Promise . all ( logPromises )
188
-
189
- return {
190
- content : [ { type : 'text' , text : asXml ( result ) } ] ,
191
- }
220
+ return await buildResponse ( result , logPromises )
192
221
} else {
193
222
// Use basic mode without tool injection
194
223
const result = await runCode (
@@ -199,16 +228,10 @@ The tools are injected into the global namespace automatically - no discovery fu
199
228
active : true ,
200
229
} ,
201
230
] ,
202
- ( level , data ) => {
203
- if ( LogLevels . indexOf ( level ) >= LogLevels . indexOf ( setLogLevel ) ) {
204
- logPromises . push ( server . server . sendLoggingMessage ( { level, data } ) )
205
- }
206
- } ,
231
+ createLogHandler ( setLogLevel , logPromises , server ) ,
232
+ undefined ,
207
233
)
208
- await Promise . all ( logPromises )
209
- return {
210
- content : [ { type : 'text' , text : asXml ( result ) } ] ,
211
- }
234
+ return await buildResponse ( result , logPromises )
212
235
}
213
236
} ,
214
237
)
@@ -439,7 +462,7 @@ print(f"Tool result: {result}")
439
462
`
440
463
441
464
try {
442
- const toolResult = await runCodeWithToolInjection (
465
+ const toolResult = await runCode (
443
466
[
444
467
{
445
468
name : 'tool_test.py' ,
0 commit comments