Skip to main content
Glama

upload_tool

Upload custom tools to the Letta system for use with agents. Add tools to agents after creation and verify attachments.

Instructions

Upload a new tool to the Letta system. Use with attach_tool to add it to agents, or list_agent_tools to verify attachment.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
nameYesName of the tool
descriptionYesDescription of what the tool does
source_codeYesPython source code for the tool
categoryNoCategory/tag for the tool (e.g., "plane_api", "utility")custom
agent_idNoOptional agent ID to attach the tool to after creation

Implementation Reference

  • The handleUploadTool function implements the core logic of the upload_tool: validates inputs, deletes existing tool if present, creates a new tool via API, optionally attaches to an agent, and returns JSON with tool details.
    export async function handleUploadTool(server, args) { try { // Validate arguments if (!args.name || typeof args.name !== 'string') { throw new Error('Missing required argument: name (must be a string)'); } if (!args.description || typeof args.description !== 'string') { throw new Error('Missing required argument: description (must be a string)'); } if (!args.source_code || typeof args.source_code !== 'string') { throw new Error('Missing required argument: source_code (must be a string)'); } // Headers for API requests const headers = server.getApiHeaders(); // If agent_id is provided, set the user_id header if (args.agent_id) { headers['user_id'] = args.agent_id; } // Prepare category/tag const category = args.category || 'custom'; // Check if tool exists and delete if found const toolsResponse = await server.api.get('/tools/', { headers }); const existingTools = toolsResponse.data; let existingToolId = null; for (const tool of existingTools) { if (tool.name === args.name) { existingToolId = tool.id; logger.info( `Found existing tool ${args.name} with ID ${existingToolId}, will delete it first...`, ); break; } } if (existingToolId) { try { await server.api.delete(`/tools/${existingToolId}`, { headers }); logger.info(`Successfully deleted existing tool ${args.name}`); } catch (deleteError) { logger.info( `Failed to delete existing tool: ${deleteError}. Will try to continue anyway.`, ); } } // Prepare tool data const toolData = { source_code: args.source_code, description: args.description, tags: [category], source_type: 'python', }; // Create the tool logger.info(`Creating tool "${args.name}"...`); const createResponse = await server.api.post('/tools/', toolData, { headers }); const toolId = createResponse.data.id; // If agent_id is provided, attach the tool to the agent if (args.agent_id) { // Attach tool to agent const attachUrl = `/agents/${args.agent_id}/tools/attach/${toolId}`; await server.api.patch(attachUrl, {}, { headers }); // Get agent info const agentInfoResponse = await server.api.get(`/agents/${args.agent_id}`, { headers }); const agentName = agentInfoResponse.data.name || 'Unknown'; return { content: [ { type: 'text', text: JSON.stringify({ tool_id: toolId, tool_name: args.name, agent_id: args.agent_id, agent_name: agentName, category: category, }), }, ], }; } else { // Just return the created tool info return { content: [ { type: 'text', text: JSON.stringify({ tool_id: toolId, tool_name: args.name, category: category, }), }, ], }; } } catch (error) { server.createErrorResponse(error); } }
  • Defines the tool schema including name, description, inputSchema with properties for name, description, source_code (required), optional category and agent_id.
    export const uploadToolToolDefinition = { name: 'upload_tool', description: 'Upload a new tool to the Letta system. Use with attach_tool to add it to agents, or list_agent_tools to verify attachment.', inputSchema: { type: 'object', properties: { name: { type: 'string', description: 'Name of the tool', }, description: { type: 'string', description: 'Description of what the tool does', }, source_code: { type: 'string', description: 'Python source code for the tool', }, category: { type: 'string', description: 'Category/tag for the tool (e.g., "plane_api", "utility")', default: 'custom', }, agent_id: { type: 'string', description: 'Optional agent ID to attach the tool to after creation', }, }, required: ['name', 'description', 'source_code'], }, };
  • Registers the upload_tool in the MCP CallToolRequestSchema handler switch statement, dispatching calls to handleUploadTool.
    case 'upload_tool': return handleUploadTool(server, request.params.arguments);
  • Imports the handleUploadTool function and uploadToolToolDefinition from upload-tool.js.
    import { handleUploadTool, uploadToolToolDefinition } from './tools/upload-tool.js';
  • Includes uploadToolToolDefinition in the allTools array used for ListToolsRequestSchema and enhanced tool registration.
    uploadToolToolDefinition,

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/oculairmedia/Letta-MCP-server'

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