MCP Smith
Generate MCP servers
MCPSmith
MCPSmith creates project-local MCP servers on-demand. When your workflow needs a custom tool - a GitHub analyzer, a database inspector, a file converter - MCPSmith builds it, runs it, and gives you the result. No global installation, no dependency conflicts, no context pollution.
Why MCPSmith Exists
The Problem You Face: During development, you need specialized tools - analyze a repo, query an API, transform data. Installing MCP servers globally is heavyweight. Writing custom tools interrupts your flow. And the work of creating tools clutters your conversation context.
How MCPSmith Helps:
1. Project-Local: MCP servers live in your project's `.aiwg/smiths/` directory. They're part of your project, not your system.
2. On-Demand Execution: Even with 100 tool definitions, only the ones you actually use get spun up. No resource waste.
3. Agent-Delegated: MCPSmith runs as a separate agent via `Task()`. The work of building containers, writing code, and testing protocols happens in isolated context - you just get the result.
4. Cached & Reusable: Once created, tools are cataloged. Ask for something similar later, get the existing tool instantly.
You: "I need to analyze GitHub repos for security issues"
↓
Task(MCPSmith) → [builds container, tests MCP protocol, registers in catalog]
↓
You get: "Tool ready. Use: docker run -i aiwg-mcp/github-security:1.0.0"
Your context stays clean. You asked for a tool, you got a tool.
Getting Started
1. Generate MCP Environment Definition
Before using MCPSmith, generate an MCP environment definition:
/smith-mcpdef
This probes your system and creates `.aiwg/smiths/mcp-definition.yaml` with:
- Docker availability and version
- Node.js version
- MCP SDK version
- Available base images
- Network configuration
2. Request an MCP Tool
Orchestrating agents can request MCP tools via the Task tool:
Task(MCPSmith) -> "Create an MCP tool to fetch and parse JSON from URLs"
MCPSmith will: 1. Check if a matching tool exists in the catalog 2. If not, design and implement the tool 3. Build a Docker container 4. Test the MCP protocol 5. Register in the catalog 6. Return the container image and usage instructions
3. Use the MCP Tool
Tools are run as Docker containers with stdio transport:
# Run the container
docker run -i --rm aiwg-mcp/json-fetcher:1.0.0
# Send MCP requests via stdin
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"fetch-json","arguments":{"url":"https://api.example.com"}}}' | \
docker run -i --rm aiwg-mcp/json-fetcher:1.0.0
Directory Structure
.aiwg/smiths/
├── mcp-definition.yaml # MCP/Docker environment
└── mcpsmith/
├── catalog.yaml # Index of MCP tools
├── tools/ # Tool specifications (YAML)
│ └── json-fetcher.yaml
├── implementations/ # Generated MCP tool code
│ └── json-fetcher/
│ ├── index.mjs
│ ├── package.json
│ └── Dockerfile
├── templates/ # Base templates
│ ├── Dockerfile.template
│ ├── index.mjs.template
│ └── package.json.template
└── images/ # Built image metadata
└── json-fetcher.json
MCP Environment Definition
The environment definition (`mcp-definition.yaml`) describes:
docker:
available: true
version: "24.0.7"
daemon_running: true
node:
available: true
version: "20.10.0"
mcp:
sdk_version: "1.24.0"
spec_version: "2025-11-25"
transports:
- stdio
base_images:
node_alpine:
image: "node:20-alpine"
cached: true
network:
name: "aiwg-mcp-network"
exists: false
ports:
range_start: 9100
range_end: 9199
Tool Specification
MCP tools are defined with YAML specifications:
name: json-fetcher
version: "1.0.0"
description: "Fetches and parses JSON from URLs"
mcp:
tool_name: "fetch-json"
title: "JSON Fetcher"
description: "Fetches JSON data from a URL and returns parsed content"
inputs:
- name: url
type: string
required: true
description: "URL to fetch JSON from"
- name: headers
type: object
required: false
description: "Optional HTTP headers"
outputs:
- name: data
type: json
description: "Parsed JSON data"
docker:
base_image: "node:20-alpine"
transport: stdio
dependencies:
- node-fetch
tests:
- name: "Basic fetch"
input:
url: "https://jsonplaceholder.typicode.com/posts/1"
expect_contains: "userId"
tags: [http, json, fetch, api]
Workflow
┌─────────────────────┐
│ Orchestrating Agent │
└──────────┬──────────┘
│
│ "Need an MCP tool to..."
▼
┌─────────────────────┐
│ MCPSmith │
└──────────┬──────────┘
│
┌─────┴─────┐
▼ ▼
┌─────────┐ ┌─────────┐
│ Catalog │ │ MCP-Def │
│ Check │ │ │
└────┬────┘ └────┬────┘
│ │
├───────────┤
▼ ▼
┌─────────┐ ┌─────────┐
│ Reuse │ │ Create │
│ Image │ │ Image │
└────┬────┘ └────┬────┘
│ │
│ ┌────┴────┐
│ ▼ ▼
│ Generate Build
│ Code Container
│ │ │
│ └────┬────┘
│ ▼
│ Test MCP
│ │
└─────┬─────┘
▼
┌─────────────────────┐
│ Return Image Name │
│ + Usage Instructions│
└─────────────────────┘
Commands
/smith-mcpdef
Generate or update the MCP environment definition.
# Generate full MCP definition
/smith-mcpdef
# Verify existing definition
/smith-mcpdef --verify-only
# Update with changes and create network
/smith-mcpdef --update --create-network
Container Lifecycle
Build
docker build -t aiwg-mcp/<name>:<version> .aiwg/smiths/mcpsmith/implementations/<name>/
Run (stdio mode)
docker run -i --rm aiwg-mcp/<name>:<version>
Stop
docker stop <container_id>
Cleanup
docker rmi aiwg-mcp/<name>:<version>
MCP Protocol Integration
MCPSmith creates tools that follow the MCP specification (2025-11-25):
Initialize Handshake
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {"name": "client", "version": "1.0.0"}
}
}
Tool Call
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "fetch-json",
"arguments": {
"url": "https://api.example.com/data"
}
}
}
Response
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{"type": "text", "text": "{\"data\": ...}"}
]
}
}
Best Practices
For Orchestrating Agents
1. Be specific in requests: "Fetch JSON from URL with custom headers" is better than "get data" 2. Include error handling needs: Specify how errors should be reported 3. Check catalog first: The catalog may already have what you need
For Tool Design
1. Use Zod validation: Always validate inputs before processing 2. Return structured data: Use JSON for complex outputs 3. Handle errors gracefully: Return `isError: true` for failures 4. Include tests: At least one test case per tool
For Docker Images
1. Use Alpine base: Smaller images, faster builds 2. Pin dependency versions: Reproducible builds 3. Don't include dev dependencies: Production only 4. Test locally first: Verify before building
Limitations
- Stdio transport only: HTTP transport planned for future
- Single tool per container: Each container hosts one MCP tool
- Local Docker required: Cannot use remote Docker hosts (yet)
- No GPU support: ML tools require additional configuration
Troubleshooting
"Docker not available"
Ensure Docker is installed and running:
docker --version
docker info
"Image build failed"
Check the build output for errors:
docker build -t test .aiwg/smiths/mcpsmith/implementations/<name>/
"MCP protocol error"
Verify the container responds to MCP:
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0.0"}}}' | \
docker run -i --rm aiwg-mcp/<name>:<version>
References
- MCPSmith Agent: `agentic/code/frameworks/sdlc-complete/agents/mcpsmith.md`
- MCP Definition Command: `agentic/code/frameworks/sdlc-complete/commands/smith-mcpdef.md`
- MCP Specification: `docs/references/REF-066-mcp-specification-2025.md`
- ToolSmith (sibling): `docs/smithing/README.md`