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 typescriptStep 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
- Building Custom MCP Servers - Comprehensive guide to TypeScript and JavaScript MCP server development
- MCP Comprehensive Guide - Understanding the Model Context Protocol
- Plugin Development Architecture - Building extensible plugins
π οΈ 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
- Read MCP Overview for conceptual understanding
- Follow Server Development Guide for hands-on building
- 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
- Design for Full Context: Assume you can load entire datasets
- Optimize Response Generation: Focus on processing, not chunking
- Monitor Token Usage: Track costs with Token Analytics
- 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
π Related Topics
π¦ 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