define_function
Define custom MCP functions for AI models by specifying name, description, parameters, and implementation code in supported environments like JavaScript, Python, or Shell.
Instructions
Create a new custom MCP function that the AI can use
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| description | Yes | Description of what the function does | |
| execution_environment | No | Environment to execute the code in | javascript |
| implementation_code | Yes | Code to implement the function | |
| name | Yes | Name of the new function | |
| parameters_schema | Yes | JSON Schema for parameters |
Implementation Reference
- src/index.ts:215-305 (handler)Handler function for the define_function tool. Validates inputs, creates a StoredTool object, registers it using registerToolWithServer, stores it in customTools, and saves to database.async ({ name, description, parameters_schema, implementation_code, execution_environment }) => { console.error(`Defining new function: ${name}`); // Check if function already exists if (customTools[name]) { return { isError: true, content: [ { type: "text", text: `A function named "${name}" already exists. Use update_function to modify it.`, }, ], }; } // Validate execution environment if (execution_environment === "javascript" && !ALLOW_JS_EXECUTION) { return { isError: true, content: [ { type: "text", text: "JavaScript execution is not allowed in this environment.", }, ], }; } if (execution_environment === "python" && !ALLOW_PYTHON_EXECUTION) { return { isError: true, content: [ { type: "text", text: "Python execution is not allowed in this environment.", }, ], }; } if (execution_environment === "shell" && !ALLOW_SHELL_EXECUTION) { return { isError: true, content: [ { type: "text", text: "Shell execution is not allowed in this environment.", }, ], }; } // Create a new tool definition const now = new Date(); const toolDef: StoredTool = { name, description, inputSchema: parameters_schema, implementation: implementation_code, executionEnvironment: execution_environment, createdAt: now, updatedAt: now, }; // Register the tool try { registerToolWithServer(toolDef); // Store the tool customTools[name] = toolDef; await saveToolsDatabase(); return { content: [ { type: "text", text: `Successfully created new function "${name}". You can now use it as a tool.`, }, ], }; } catch (error) { return { isError: true, content: [ { type: "text", text: `Error creating function: ${error instanceof Error ? error.message : String(error)}`, }, ], }; } }
- src/index.ts:208-214 (schema)Zod-based input schema for the define_function tool parameters.{ name: z.string().min(1).describe("Name of the new function"), description: z.string().describe("Description of what the function does"), parameters_schema: z.record(z.any()).describe("JSON Schema for parameters"), implementation_code: z.string().min(1).describe("Code to implement the function"), execution_environment: z.enum(["javascript", "python", "shell"]).default("javascript").describe("Environment to execute the code in"), },
- src/index.ts:205-306 (registration)MCP server registration of the define_function tool, including name, description, schema, and handler.server.tool( "define_function", "Create a new custom MCP function that the AI can use", { name: z.string().min(1).describe("Name of the new function"), description: z.string().describe("Description of what the function does"), parameters_schema: z.record(z.any()).describe("JSON Schema for parameters"), implementation_code: z.string().min(1).describe("Code to implement the function"), execution_environment: z.enum(["javascript", "python", "shell"]).default("javascript").describe("Environment to execute the code in"), }, async ({ name, description, parameters_schema, implementation_code, execution_environment }) => { console.error(`Defining new function: ${name}`); // Check if function already exists if (customTools[name]) { return { isError: true, content: [ { type: "text", text: `A function named "${name}" already exists. Use update_function to modify it.`, }, ], }; } // Validate execution environment if (execution_environment === "javascript" && !ALLOW_JS_EXECUTION) { return { isError: true, content: [ { type: "text", text: "JavaScript execution is not allowed in this environment.", }, ], }; } if (execution_environment === "python" && !ALLOW_PYTHON_EXECUTION) { return { isError: true, content: [ { type: "text", text: "Python execution is not allowed in this environment.", }, ], }; } if (execution_environment === "shell" && !ALLOW_SHELL_EXECUTION) { return { isError: true, content: [ { type: "text", text: "Shell execution is not allowed in this environment.", }, ], }; } // Create a new tool definition const now = new Date(); const toolDef: StoredTool = { name, description, inputSchema: parameters_schema, implementation: implementation_code, executionEnvironment: execution_environment, createdAt: now, updatedAt: now, }; // Register the tool try { registerToolWithServer(toolDef); // Store the tool customTools[name] = toolDef; await saveToolsDatabase(); return { content: [ { type: "text", text: `Successfully created new function "${name}". You can now use it as a tool.`, }, ], }; } catch (error) { return { isError: true, content: [ { type: "text", text: `Error creating function: ${error instanceof Error ? error.message : String(error)}`, }, ], }; } } );
- src/index.ts:132-202 (helper)Helper function called by define_function to register the new custom tool with the MCP server. Handles schema parsing and sets up the execution handler based on the environment.function registerToolWithServer(toolDef: StoredTool) { try { let paramsSchema: z.ZodRawShape = {}; // Handle both string schemas and ZodType objects if (typeof toolDef.inputSchema === "string") { try { paramsSchema = JSON.parse(toolDef.inputSchema as string); } catch (e) { console.error(`Failed to parse schema for tool ${toolDef.name}:`, e); // Keep empty object as default } } else if (toolDef.inputSchema instanceof z.ZodObject) { // If it's a ZodObject, extract its shape which is a ZodRawShape paramsSchema = toolDef.inputSchema.shape; } else if (typeof toolDef.inputSchema === "object" && toolDef.inputSchema !== null) { // Assume it's a raw object schema paramsSchema = toolDef.inputSchema as Record<string, any>; } // Register the tool with the server server.tool( toolDef.name, toolDef.description, paramsSchema, async (params) => { console.error(`Executing custom tool ${toolDef.name} with parameters:`, params); try { let result; switch (toolDef.executionEnvironment) { case "javascript": result = await executeJavaScript(toolDef.implementation, params); break; case "python": result = await executePython(toolDef.implementation, params); break; case "shell": result = await executeShell(toolDef.implementation, params); break; default: throw new Error(`Unsupported execution environment: ${toolDef.executionEnvironment}`); } // Ensure we return a proper CallToolResult return { content: [ { type: "text", text: typeof result === "string" ? result : JSON.stringify(result, null, 2), }, ], }; } catch (error) { console.error(`Error executing tool ${toolDef.name}:`, error); return { isError: true, content: [ { type: "text", text: `Error executing tool: ${error instanceof Error ? error.message : String(error)}`, }, ], }; } } ); console.error(`Registered custom tool: ${toolDef.name}`); } catch (error) { console.error(`Failed to register tool ${toolDef.name}:`, error); } }