DIY Tools MCP Server
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@DIY Tools MCP Serveradd a Python function to calculate Fibonacci numbers"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
DIY Tools MCP Server
A Model Context Protocol (MCP) server that allows you to create custom tools/functions at runtime in any programming language and expose them to Claude or other MCP clients.
Overview
The DIY Tools MCP server enables you to dynamically add custom tools without needing to write a full MCP server. Simply provide the function code, parameters schema, and the server handles the rest - validation, execution, persistence, and MCP protocol integration.
This server bridges the gap between simple function definitions and the MCP protocol, making it easy to extend Claude's capabilities with custom tools written in Python, JavaScript, Bash, Ruby, or TypeScript.
Related MCP server: MCP Proxy
Features
Dynamic Tool Registration: Add new tools at runtime without restarting the server
Multi-Language Support: Write functions in Python, JavaScript, Bash, and more
File-Based Functions: Define functions in separate files for better maintainability
Automatic Validation: Functions are validated for syntax before registration
Security Validation: Comprehensive security checks for file-based functions
Persistence: Registered tools are saved and automatically loaded on server restart
Type Safety: Full JSON Schema validation for function parameters
Error Handling: Comprehensive error messages and timeout protection
Source Code Viewer: Built-in tool to inspect function source code
Installation
# Clone the repository
git clone https://github.com/yourusername/diy-tools-mcp.git
cd diy-tools-mcp
# Install dependencies
npm install
# Build the project
npm run buildUsage
Starting the Server
# Start the server
npm start
# Or for development with auto-reload
npm run devAdding Tools
The server provides four built-in tools:
add_tool- Register a new custom functionremove_tool- Remove a registered functionlist_tools- List all available custom toolsview_source- View the source code of a registered tool
Example: Adding a Python Tool
{
"name": "calculate_factorial",
"description": "Calculate the factorial of a number",
"language": "python",
"code": "def main(n):\n if n <= 1:\n return 1\n return n * main(n - 1)",
"parameters": {
"type": "object",
"properties": {
"n": {
"type": "integer",
"description": "The number to calculate factorial for",
"minimum": 0
}
},
"required": ["n"]
},
"returns": "The factorial of the input number"
}Example: Adding a JavaScript Tool
{
"name": "format_date",
"description": "Format a date string",
"language": "javascript",
"code": "function main({ date, format }) {\n const d = new Date(date);\n if (format === 'short') {\n return d.toLocaleDateString();\n }\n return d.toLocaleString();\n}",
"parameters": {
"type": "object",
"properties": {
"date": {
"type": "string",
"description": "Date string to format"
},
"format": {
"type": "string",
"enum": ["short", "long"],
"default": "long"
}
},
"required": ["date"]
}
}Example: Adding a Bash Tool
{
"name": "system_info",
"description": "Get basic system information",
"language": "bash",
"code": "main() {\n echo '{\"os\": \"'$(uname -s)'\", \"kernel\": \"'$(uname -r)'\", \"arch\": \"'$(uname -m)'\"}'\n}",
"parameters": {
"type": "object",
"properties": {}
}
}File-Based Functions
You can now define functions in separate files instead of inline code. This is useful for:
Complex functions that are easier to maintain in dedicated files
Functions you want to version control separately
Reusing existing code without modification
Example: Adding a Python Function from File
Create your function file
my_function.py:
from datetime import datetime
def main(name, age):
"""
Generate a personalized greeting.
"""
return {
"greeting": f"Hello {name}!",
"message": f"You are {age} years old.",
"timestamp": datetime.now().isoformat()
}Register the function:
{
"name": "personalized_greeting",
"description": "Generate a personalized greeting with timestamp",
"language": "python",
"codePath": "./my_function.py",
"parameters": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Person's name"
},
"age": {
"type": "integer",
"description": "Person's age"
}
},
"required": ["name", "age"]
}
}Example: Adding a JavaScript Function from File
Create your function file
data_processor.js:
async function main({ data, format }) {
// Process data based on format
if (format === 'csv') {
return processCSV(data);
} else if (format === 'json') {
return processJSON(data);
}
throw new Error(`Unsupported format: ${format}`);
}
function processCSV(data) {
// CSV processing logic
return { processed: true, format: 'csv', rows: data.split('\n').length };
}
function processJSON(data) {
// JSON processing logic
const parsed = JSON.parse(data);
return { processed: true, format: 'json', keys: Object.keys(parsed) };
}
module.exports = { main };Register the function:
{
"name": "data_processor",
"description": "Process data in various formats",
"language": "javascript",
"codePath": "./data_processor.js",
"parameters": {
"type": "object",
"properties": {
"data": {
"type": "string",
"description": "Raw data to process"
},
"format": {
"type": "string",
"enum": ["csv", "json"],
"description": "Data format"
}
},
"required": ["data", "format"]
}
}Configurable Entry Points (New in v1.2.0)
You can now specify any function name as the entry point, not just main. This allows you to:
Use existing code without renaming functions
Share a single file between multiple tools with different entry points
Better organize related functions
Example: Multiple Tools from One File
Create a file with multiple functions
math_utils.py:
def calculate_tax(income, tax_rate):
"""Calculate tax amount."""
return {
"tax_amount": income * tax_rate,
"net_income": income * (1 - tax_rate)
}
def compound_interest(principal, rate, time):
"""Calculate compound interest."""
amount = principal * (1 + rate) ** time
return {
"principal": principal,
"interest": amount - principal,
"total": amount
}Register multiple tools using different entry points:
// Tax calculator tool
{
"name": "tax_calculator",
"description": "Calculate tax and net income",
"language": "python",
"codePath": "./math_utils.py",
"entryPoint": "calculate_tax", // Specify which function to use
"parameters": {
"type": "object",
"properties": {
"income": { "type": "number" },
"tax_rate": { "type": "number" }
},
"required": ["income", "tax_rate"]
}
}
// Interest calculator tool
{
"name": "interest_calculator",
"description": "Calculate compound interest",
"language": "python",
"codePath": "./math_utils.py",
"entryPoint": "compound_interest", // Different function from same file
"parameters": {
"type": "object",
"properties": {
"principal": { "type": "number" },
"rate": { "type": "number" },
"time": { "type": "number" }
},
"required": ["principal", "rate", "time"]
}
}If no entryPoint is specified, the system defaults to looking for a function named main for backward compatibility.
Viewing Function Source Code
Use the view_source tool to inspect any registered function:
{
"name": "view_source",
"arguments": {
"name": "data_processor",
"verbose": true
}
}The verbose option includes full metadata about the tool in addition to the source code.
Supported Languages
Python (
python) - Requires Python 3.xJavaScript (
javascriptornode) - Requires Node.jsBash (
bash) - Requires Bash shellTypeScript (
typescript) - Transpiled and run as JavaScriptRuby (
ruby) - Requires Ruby
Function Requirements
Python Functions
Must define a
mainfunction that accepts keyword argumentsShould return JSON-serializable data
Example:
def main(x, y): return x + y
JavaScript Functions
Must define a
mainfunction (regular or async)Receives parameters as a single object
Example:
function main({ x, y }) { return x + y; }
Bash Functions
Must define a
mainfunctionReceives JSON arguments as first parameter
Should output JSON to stdout
Example:
main() { # Parse JSON args if needed echo '{"result": "success"}' }
Ruby Functions
Must define a
mainmethod that accepts keyword argumentsShould return JSON-serializable data
Example:
def main(name:, age:) { greeting: "Hello #{name}, you are #{age} years old!" } end
Configuration
Timeout Settings
You can specify a timeout for each function (in milliseconds):
{
"timeout": 5000 // 5 seconds
}Maximum timeout is 300000ms (5 minutes).
Dependencies
For Python functions, you can specify required packages:
{
"dependencies": ["numpy", "pandas"]
}Note: Automatic dependency installation is not yet implemented.
Error Handling
The server provides detailed error messages for:
Syntax errors in function code
Invalid parameter schemas
Runtime execution errors
Timeout violations
Missing dependencies
Storage
Functions are stored in the functions/ directory as JSON files. Each file contains:
Function specification
Unique ID
Creation and update timestamps
Development
# Run in development mode with auto-reload
npm run dev
# Run tests
npm test
# Build for production
npm run build
# Clean build artifacts
npm run cleanSecurity Considerations
File-Based Functions Security
When using file-based functions, the server implements multiple security layers:
Path Traversal Protection: Prevents access to files outside the intended directories
Symbolic Link Detection: Blocks symbolic links to prevent unauthorized file access
System Directory Protection: Restricts access to critical system directories including:
/etc,/usr/bin,/System(macOS),C:\WindowsUser-specific sensitive directories (
~/.ssh,~/.aws, etc.)
File Size Limits: Files are limited to 10MB to prevent resource exhaustion
Dangerous Pattern Detection: Scans for potentially malicious code patterns:
eval()andexec()callsDynamic imports and requires
Dangerous shell commands (
rm -rf /, etc.)Subprocess calls with shell=True
File Extension Validation: Only allows appropriate extensions for each language
Main Function Requirement: Enforces that all functions have a proper
mainentry point
General Security Notes
Functions run with the same permissions as the server
No built-in sandboxing (use with trusted code only)
Network and file system access depends on the language runtime
Consider running in a containerized environment for production use
When copying function files, the server creates isolated copies to prevent external modifications
Best Practices
When to Use File-Based vs Inline Functions
Use file-based functions for:
Complex logic that benefits from IDE features (syntax highlighting, linting, debugging)
Functions you want to unit test separately
Shared utilities across multiple tools
Functions that require multiple helper functions
Code that you want to version control independently
Use inline functions for:
Simple, single-purpose operations (< 20 lines)
Quick prototypes and experiments
Functions that are tightly coupled to their tool definition
One-off utilities that don't need separate maintenance
Directory Organization
Organize your functions for maintainability:
my-mcp-tools/
├── functions/ # Auto-managed metadata (don't edit)
├── function-code/ # Auto-managed copies (don't edit)
└── my-functions/ # Your source files
├── data/
│ ├── processor.js
│ └── validator.py
├── ml/
│ ├── predictor.py
│ └── trainer.py
└── tests/
├── test_processor.js
└── test_validator.pyFunction Design Guidelines
Keep functions focused: Each function should do one thing well
Use clear parameter names: Make your API intuitive
Provide comprehensive descriptions: Help users understand what your tool does
Handle errors gracefully: Return meaningful error messages
Validate inputs early: Check parameters before processing
Document edge cases: Use the
returnsfield to explain output format
Migration Guide
Migrating from Inline to File-Based Functions
Existing inline functions continue to work without changes. To migrate an inline function to file-based:
Extract the code to a new file:
# Before (inline) "code": "def main(x, y):\n return x + y" # After (calculator.py) def main(x, y): return x + yUpdate the tool definition:
// Before { "name": "calculator", "code": "def main(x, y):\n return x + y", ... } // After { "name": "calculator", "codePath": "./my-functions/calculator.py", ... }Re-register the tool:
Use
remove_toolto remove the old inline versionUse
add_toolwith the new file-based definition
The server automatically handles the transition, copying the file to its managed directory and preserving all functionality.
Gradual Migration Strategy
Start with new functions: Write all new functions as files
Migrate complex functions first: Move functions that would benefit most from IDE support
Keep simple functions inline: Don't migrate unless there's a clear benefit
Test after migration: Ensure functions work identically after migration
Roadmap
Completed Features ✅
Allow users to write functions in stand-alone files, as opposed to inline in the tool definition
Add tool to view function source code (
view_source)Enforce single
mainfunction entry point with comprehensive validationComprehensive security validation for file-based functions
Future Enhancements
Configurable entry points (use any function name instead of requiring
main)Support for multiple entry points per file (share code between tools)
File watching and hot-reload for development workflow
Dependency resolution for local imports
Version tracking and rollback capabilities
Streaming output for long-running functions
Function composition and chaining
Contributing
Contributions are welcome! Please:
Fork the repository
Create a feature branch
Add tests for new functionality
Submit a pull request
License
MIT
Available Tools
4 toolsadd_toolB
Add a new custom tool/function to the server
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | The name of the tool (must be unique) | |
| description | Yes | A description of what the tool does | |
| language | Yes | The programming language the function is written in | |
| code | No | The function code (inline). Must define a function named "main". Mutually exclusive with codePath | |
| codePath | No | Path to file containing the function code. Mutually exclusive with code | |
| parameters | Yes | JSON Schema defining the input parameters for the function | |
| returns | No | Optional description of what the function returns | |
| dependencies | No | Optional list of dependencies (e.g., Python packages) | |
| timeout | No | Optional timeout in milliseconds (max 300000ms = 5 minutes) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It only states 'Add a new custom tool/function' without disclosing side effects (e.g., overwriting, error handling for duplicate names), permissions, or return behavior. Schema notes uniqueness but description adds no behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence with no extraneous text, perfectly concise for the core purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 9 parameters and no output schema, the description is too brief. It does not explain what happens upon success/failure, return format, or relationships with siblings. More detail is needed for a tool of this complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3. The description adds no parameter-specific information beyond what the schema already provides, neither enhancing nor detracting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description 'Add a new custom tool/function to the server' uses a specific verb and clearly identifies the resource. It distinguishes from sibling tools (list_tools, remove_tool, view_source) by implying addition rather than listing, removal, or viewing.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to use this tool versus alternatives. The purpose is clear but lacks context about prerequisites or when not to use it. Sibling names hint at different functions but no comparison is provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_toolsA
List all available custom tools
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden. It is straightforward for a read-only listing tool, but it does not disclose any behavioral details like whether the output includes full tool definitions or just names, which is important given no output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, concise sentence that is front-loaded with the verb and resource. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description is somewhat incomplete—it does not hint at the format or content of the list (e.g., names only, full details). While the purpose is clear, an agent might need more context about the output.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are no parameters, and schema coverage is 100% (trivially). The description does not need to add parameter information. Baseline 4 is appropriate as the description adds no additional meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('List') and the resource ('all available custom tools'), distinguishing it from sibling tools like add_tool, remove_tool, and view_source.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool versus alternatives, such as to discover available tools before adding or removing them. The description only states what it does.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
remove_toolB
Remove a custom tool/function from the server
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | The name of the tool to remove |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must provide behavioral details. It only states removal, omitting consequences like irreversibility, permissions needed, or side effects. This is minimal transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence with no unnecessary words, conveying the essential information efficiently. It is appropriately sized and front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple mutation tool with one parameter and no output schema, the description is adequate but lacks safety or error context, such as whether removal is immediate or reversible. It is minimally complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 100% schema description coverage, the schema already documents the single parameter 'name' as 'The name of the tool to remove'. The description adds no extra meaning beyond the schema, so baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description 'Remove a custom tool/function from the server' is clear and specific, stating the verb (remove) and resource (custom tool/function). It distinguishes from siblings like add_tool, list_tools, and view_source.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool versus alternatives, such as when a tool should be removed or any prerequisites. The description lacks context for appropriate usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
view_sourceB
View the source code of a registered custom tool
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | The name of the tool to view | |
| verbose | No | Include full metadata in addition to source code |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It only states what the tool does without disclosing behavior on missing tool, error handling, permissions, or output format. The verbose parameter's effect (including metadata) is only hinted in the schema, not in the description.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence that front-loads the purpose. No unnecessary words or fluff. Efficiently communicates core functionality.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no output schema and no annotations, the description omits critical details: what happens when the name doesn't exist, what the output includes (source code only? metadata?), and any side effects. The verbose parameter description in schema suggests metadata is included, but the tool description doesn't clarify this.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with both parameters described in input schema. Description adds no additional meaning beyond schema. Baseline 3 is appropriate since schema adequately documents parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states the action ('view') and resource ('source code of a registered custom tool'). It distinguishes from siblings 'list_tools' (which lists tools) and 'add_tool'/'remove_tool' (which modify tools).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to use this tool versus alternatives, or any conditions or prerequisites. The description does not mention when not to use it or suggest alternative tools for related tasks.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
4 tool updates
v2.0.0- First observed
add_tool - First observed
list_tools - First observed
remove_tool - First observed
view_source
TDQS
Each tool has a clearly distinct purpose: adding, listing, removing, or viewing source of custom tools. No ambiguity exists between them.
All tool names follow a consistent verb_noun pattern (add_tool, list_tools, remove_tool, view_source) using snake_case, making them predictable.
With 4 tools, the set is well-scoped for managing custom tool definitions. It covers essential operations without being sparse or excessive.
The tools cover basic CRUD and inspection (add, list, remove, view source). An update/modify tool is missing, but the set is functional for typical DIY scenarios.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Hosted MCP runtime where the agent is the operator: sign up by tool call, publish your own tools.
171The OpenRouter for tools. One MCP connection gives any AI agent 254 hosted tools, pay per call.
471Give any MCP-compatible AI assistant a builder for live, hosted web tools and workflows.
Build, validate, deploy — HTTP APIs, cron jobs, webhooks and MCP tools — from your AI client.
Related MCP Servers
- AlicenseAqualityFmaintenanceEnables AI models to dynamically create and execute their own custom tools through a meta-function architecture, supporting JavaScript, Python, and Shell runtimes with sandboxed security and human approval flows.510MIT
- FlicenseNot gradedqualityDmaintenanceEnables dynamic loading, hot-reloading, and orchestration of MCP servers without restarting Claude Code, allowing programmatic tool calling and workflow automation across multiple servers.2-
- AlicenseAqualityDmaintenanceA meta-MCP server that dynamically manages and invokes any MCP server on the fly, enabling runtime addition, removal, and tool invocation without restarting Claude Code.513MIT
- FlicenseNot gradedqualityCmaintenanceA dynamic tool management platform that allows creating, editing, and executing Python code tools via a web UI, exposing them as MCP tools through Streamable HTTP.-
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/hesreallyhim/diy-tools-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server