Custom Tools Development - Map of Content

Your guide to extending Claude Code with custom tools, MCP servers, and integrations.

πŸš€ Quickstart: Your First Custom Tool

Get your first custom tool running in under 5 minutes! This Hello World example demonstrates the core concepts of MCP server development.

Step 1: Create Your Tool

Create a new file hello-tool.ts:

import { Server } from "@modelcontextprotocol/sdk/server";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
 
const server = new Server({
  name: "hello-tool",
  version: "1.0.0"
});
 
// Define a simple "greet" tool
server.setRequestHandler("tools/list", async () => ({
  tools: [{
    name: "greet",
    description: "Greet someone with a personalized message",
    inputSchema: {
      type: "object",
      properties: {
        name: { type: "string", description: "Name to greet" },
        style: { 
          type: "string", 
          enum: ["formal", "casual", "pirate"],
          description: "Greeting style"
        }
      },
      required: ["name"]
    }
  }]
}));
 
// Handle tool execution
server.setRequestHandler("tools/call", async (request) => {
  const { name, arguments: args } = request.params;
  
  if (name === "greet") {
    const greetings = {
      formal: `Good day, ${args.name}. How may I assist you?`,
      casual: `Hey ${args.name}! What's up?`,
      pirate: `Ahoy, ${args.name}! Welcome aboard, matey!`
    };
    
    return {
      content: [{
        type: "text",
        text: greetings[args.style || "casual"]
      }]
    };
  }
  
  throw new Error(`Unknown tool: ${name}`);
});
 
// Start the server
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Hello Tool MCP server running!");

Step 2: Install Dependencies

npm init -y
npm install @modelcontextprotocol/sdk zod
npm install -D @types/node typescript

Step 3: Configure Claude Code

Add to your Claude Code settings:

{
  "mcpServers": {
    "hello-tool": {
      "command": "node",
      "args": ["hello-tool.js"]
    }
  }
}

Step 4: Test Your Tool

Restart Claude Code and try: β€œUse the greet tool to say hello to Alice in pirate style!”

πŸ”— Next Steps: Ready for more? Check out the comprehensive MCP Server Development Guide for advanced features like resources, authentication, and error handling.

πŸ“š Core Documentation

πŸ› οΈ Development Resources

Getting Started

  • Prerequisites - TypeScript/JavaScript knowledge, Node.js environment
  • SDK Documentation - Official MCP SDK reference
  • Example Servers - Production-ready examples and templates

Key Topics

  • Server Architecture - Client-server model, transport methods
  • Tool Definition - Creating tools with proper schemas
  • Resource Management - Exposing data through resources
  • Authentication - Implementing secure access control

🎯 Learning Path

  1. Read MCP Overview for conceptual understanding
  2. Follow Server Development Guide for hands-on building
  3. Explore MCP Automation Experiments for advanced patterns

🌏 Leveraging Large Context Windows with Tools

Custom tools become exponentially more powerful when combined with Claude’s large context windows. Here’s how to maximize their potential:

Context-Aware Tool Design

With 1M+ token context windows, your tools can:

1. Process Entire Repositories

// Tool that analyzes full codebases
server.tool("analyze_repository", {
  description: "Analyze entire repository structure and dependencies",
  parameters: z.object({
    repoPath: z.string(),
    analysisType: z.enum(["security", "performance", "architecture"])
  }),
  execute: async ({ repoPath, analysisType }) => {
    // Load entire repository into context
    const files = await loadRepository(repoPath);
    // With 1M tokens, no need to chunk or sample!
    return performFullAnalysis(files, analysisType);
  }
});

2. Multi-Document Processing

// Tool for comprehensive document analysis
server.tool("process_documents", {
  description: "Analyze relationships across multiple large documents",
  parameters: z.object({
    documentPaths: z.array(z.string()),
    task: z.enum(["summarize", "compare", "extract_insights"])
  }),
  execute: async ({ documentPaths, task }) => {
    // Load all documents - no truncation needed!
    const documents = await Promise.all(
      documentPaths.map(path => loadDocument(path))
    );
    return processWithFullContext(documents, task);
  }
});

3. Stateful Context Management

// Tool that maintains conversation context
server.resource("conversation_history", {
  description: "Full conversation history with context",
  mimeType: "application/json",
  load: async () => {
    // Return entire conversation history
    // Large context windows mean no pruning needed!
    return JSON.stringify(conversationHistory);
  }
});

Best Practices for Large Context Tools

  1. Design for Full Context: Assume you can load entire datasets
  2. Optimize Response Generation: Focus on processing, not chunking
  3. Monitor Token Usage: Track costs with Token Analytics
  4. Implement Caching: Use Prompt Caching for repeated operations

πŸ’‘ Common Use Cases

  • Database Connectors - Query and manage databases through natural language
  • API Wrappers - Simplify complex API interactions
  • File System Tools - Safe file operations with validation
  • Workflow Automation - Multi-step process orchestration
  • Monitoring Integration - Connect to observability platforms

πŸ“¦ Production-Ready Template

// Production MCP server with error handling and logging
import { Server } from "@modelcontextprotocol/sdk/server";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
 
const server = new Server({
  name: "production-server",
  version: "1.0.0",
  capabilities: {
    tools: {},
    resources: {}
  }
});
 
// Error handling
process.on('unhandledRejection', (error) => {
  console.error('Unhandled rejection:', error);
  process.exit(1);
});
 
// Define tools with proper validation
server.setRequestHandler("tools/list", async () => ({
  tools: [{
    name: "example_tool",
    description: "Production-ready tool example",
    inputSchema: {
      type: "object",
      properties: {
        input: { type: "string" }
      },
      required: ["input"]
    }
  }]
}));
 
// Tool implementation with error handling
server.setRequestHandler("tools/call", async (request) => {
  try {
    const { name, arguments: args } = request.params;
    
    if (name === "example_tool") {
      // Validate input
      const schema = z.object({ input: z.string() });
      const validated = schema.parse(args);
      
      // Your tool logic here
      return {
        content: [{
          type: "text",
          text: `Processed: ${validated.input}`
        }]
      };
    }
    
    throw new Error(`Unknown tool: ${name}`);
  } catch (error) {
    console.error('Tool execution error:', error);
    throw error;
  }
});
 
// Start server with graceful shutdown
const transport = new StdioServerTransport();
await server.connect(transport);
 
console.error("Production MCP server started successfully");
 
// Graceful shutdown
process.on('SIGINT', async () => {
  await server.close();
  process.exit(0);
});

πŸ”’ Security Note: Always validate inputs and implement proper authentication. See Security Best Practices for comprehensive guidelines.

Tags

custom-tools mcp model-context-protocol development claude-code typescript javascript moc