Skip to main content
Glama

define_function

Create custom functions for AI models to execute in JavaScript, Python, or Shell environments with sandboxed security and approval workflows.

Instructions

Create a new custom MCP function that the AI can use

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
nameYesName of the new function
descriptionYesDescription of what the function does
parameters_schemaYesJSON Schema for parameters
implementation_codeYesCode to implement the function
execution_environmentNoEnvironment to execute the code injavascript

Implementation Reference

  • The core handler function for the 'define_function' tool. It validates inputs, checks for existing functions, creates a StoredTool object, registers it with the server using registerToolWithServer, stores it in customTools, and saves to database. Returns success or error response.
    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)}`, }, ], }; } }
  • Zod-based input schema defining the parameters for the define_function tool: name, description, parameters_schema (JSON schema), implementation_code, and execution_environment.
    { 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)
    The server.tool() call that registers the 'define_function' tool with the MCP server, specifying name, description, input schema, and handler function.
    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)}`, }, ], }; } } );
  • Helper function called by define_function handler to register the new tool with the MCP server. Handles schema parsing and creates the execution wrapper.
    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); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/alxspiker/ai-meta-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server