Skip to content

Custom Tool Implementation for MCP Server: 5-Minute Guide to Adding Unique Features

Target Audience

  • Intermediate developers with Python basics who want to leverage custom tools in Claude Code

Key Points

  1. Add custom tools to MCP server
  2. Execute those tools from Claude Code
  3. Build foundation for practical automation tools

Why This Matters Now

MCP is the core of Claude Code extensibility, but practical implementation examples beyond standard tools are scarce, making custom business workflow automation unclear.

Solution Steps Overview

StepContentSuccess Metric
1Implement basic MCP structureserver.py operational
2Add custom tool functionsTool registration success
3Test Claude Code connectionActual tool execution

Step 1: Basic MCP Server Implementation

Create minimal MCP server and prepare foundation for custom tools.

# server.py
import asyncio
from mcp import Tool
from mcp.server import Server
from mcp.types import ToolResult

server = Server("custom-tools")

@server.list_tools()
async def list_tools():
    return [
        Tool(
            name="file_validator",
            description="File existence check and basic info retrieval",
            inputSchema={
                "type": "object",
                "properties": {
                    "filepath": {"type": "string"}
                },
                "required": ["filepath"]
            }
        )
    ]

Step 2: Custom Tool Function Implementation

Implement practical file validation tool and register it with MCP server.

import os
import stat
from datetime import datetime

@server.call_tool()
async def call_tool(name: str, arguments: dict):
    if name == "file_validator":
        filepath = arguments["filepath"]

        try:
            if not os.path.exists(filepath):
                return ToolResult(content=f"❌ File not found: {filepath}")

            file_stat = os.stat(filepath)
            size_mb = file_stat.st_size / 1024 / 1024
            modified = datetime.fromtimestamp(file_stat.st_mtime)

            permissions = stat.filemode(file_stat.st_mode)

            result = f"""✅ File validation result:
📄 Path: {filepath}
📊 Size: {size_mb:.2f} MB
🕐 Last modified: {modified}
🔒 Permissions: {permissions}"""

            return ToolResult(content=result)

        except Exception as e:
            return ToolResult(content=f"❌ Error: {str(e)}", isError=True)

if __name__ == "__main__":
    asyncio.run(server.run())

Step 3: Claude Code Connection Setup

Add server information to claude_desktop_config.json to make it available from Claude Code.

{
  "mcpServers": {
    "custom-tools": {
      "command": "python",
      "args": ["path/to/server.py"],
      "env": {}
    }
  }
}

Common Pitfalls and Solutions

SymptomCauseImmediate Fix
Tools not showingConfig file path errorUse absolute path
Execution errorsPython environment mismatchUnify with virtual env
Permission errorsFile access permissionschmod +x server.py
Advanced Configuration (Optimization) ### Multiple Tools Support
tools = [
    Tool(name="file_validator", ...),
    Tool(name="log_analyzer", ...),
    Tool(name="config_generator", ...)
]
### Enhanced Error Handling
try:
    # Tool execution
except FileNotFoundError:
    return ToolResult(content="File not detected", isError=True)
except PermissionError:
    return ToolResult(content="Insufficient access rights", isError=True)