Makemcp
A lightweight wrapper for creating MCP (Model Context Protocol) servers in Python
Ask AI about Makemcp
Powered by Claude Β· Grounded in docs
I know everything about Makemcp. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
MakeMCP
The fastest way to create MCP (Model Context Protocol) servers in Python. Zero boilerplate, maximum functionality.
from makemcp.quick import tool, run
@tool
def hello(name: str) -> str:
return f"Hello, {name}! π"
run() # Your MCP server is running!
MakeMCP is built on the official MCP Python SDK but removes all the complexity. Create powerful MCP servers with just decorators.
Quickstart β’ Getting Started β’ Examples β’ Documentation
Why MakeMCP?
- Zero Boilerplate: Just decorators. No classes, no handlers, no setup.
- Use Your Existing Code: Any Python file becomes an MCP server instantly
- Async Native: Async functions work automatically alongside sync ones
- Type Safe: Full type hints and schema generation
- Fast: Built on the official MCP SDK for maximum performance
- Simple: If you can write Python functions, you can build an MCP server
Installation
# Install uv if you don't have it (optional but recommended for 10-100x faster installs)
curl -LsSf https://astral.sh/uv/install.sh | sh
# Install MakeMCP
uv pip install git+https://github.com/leifmarkthaler/makemcp.git
That's it! You're ready to create MCP servers.
Alternative installation methods
Using pip (slower but works everywhere)
pip install git+https://github.com/leifmarkthaler/makemcp.git
For development
git clone https://github.com/leifmarkthaler/makemcp.git
cd makemcp
uv pip install -e ".[dev]"
For SSE/HTTP transport
uv pip install "makemcp[http] @ git+https://github.com/leifmarkthaler/makemcp.git"
Quick Start
The Simplest Example (3 lines)
from makemcp.quick import tool, run
@tool
def hello(name: str) -> str:
return f"Hello, {name}!"
run()
Use Your Existing Code (1 line)
from makemcp.quick import from_file
# Any Python file becomes an MCP server
from_file("my_utils.py").run()
Traditional Approach (More Control)
from makemcp import MakeMCPServer
# Create a server
server = MakeMCPServer("my-server")
# Add tools with decorators
@server.tool()
def add(a: float, b: float) -> float:
"""Add two numbers."""
return a + b
@server.tool()
def multiply(a: float, b: float) -> float:
"""Multiply two numbers."""
return a * b
# Add resources
@server.resource("config://{key}")
def get_config(key: str) -> str:
"""Get configuration value."""
return f"Config value for {key}"
# Add prompts
@server.prompt()
def code_review(language: str, code: str) -> str:
"""Generate a code review prompt."""
return f"Please review this {language} code:\n\n{code}"
# Run the server
if __name__ == "__main__":
server.run()
Usage Examples
Basic Server with Tools
from makemcp import MakeMCPServer
server = MakeMCPServer("calculator")
@server.tool()
def calculate(operation: str, x: float, y: float) -> float:
"""Perform basic calculations."""
operations = {
"add": lambda a, b: a + b,
"subtract": lambda a, b: a - b,
"multiply": lambda a, b: a * b,
"divide": lambda a, b: a / b if b != 0 else None,
}
if operation not in operations:
raise ValueError(f"Unknown operation: {operation}")
return operations[operation](x, y)
server.run()
Async Operations
MakeMCP has full support for async functions. Async functions are automatically detected and properly wrapped while preserving their async nature.
from makemcp import MakeMCPServer
import asyncio
import aiohttp
server = MakeMCPServer("async-example")
@server.tool()
async def fetch_url(url: str) -> dict:
"""Fetch data from a URL asynchronously."""
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return {
"url": url,
"status": response.status,
"content": await response.text()
}
@server.tool()
async def parallel_process(items: list) -> list:
"""Process multiple items in parallel."""
async def process_item(item):
await asyncio.sleep(0.1) # Simulate work
return f"Processed: {item}"
# Process all items concurrently
results = await asyncio.gather(*[process_item(item) for item in items])
return results
# Mix async and sync tools in the same server
@server.tool()
def sync_operation(x: int, y: int) -> int:
"""Synchronous operation."""
return x + y
server.run()
Resources and Prompts
from makemcp import MakeMCPServer
import json
server = MakeMCPServer("knowledge-base")
# In-memory knowledge base
knowledge = {}
@server.tool()
def store_knowledge(topic: str, content: str) -> dict:
"""Store knowledge about a topic."""
knowledge[topic] = content
return {"stored": topic}
@server.resource("knowledge://{topic}")
def get_knowledge(topic: str) -> str:
"""Retrieve knowledge about a topic."""
return knowledge.get(topic, f"No knowledge found for {topic}")
@server.prompt()
def explain_topic(topic: str, level: str = "beginner") -> str:
"""Generate a prompt to explain a topic."""
return f"""Explain {topic} at a {level} level.
Include:
- Clear definition
- Real-world examples
- Common misconceptions
- Related concepts
"""
server.run()
SSE Transport for Network Access
from makemcp import MakeMCPServer
server = MakeMCPServer("network-server")
@server.tool()
def echo(message: str) -> str:
"""Echo a message back."""
return message
# Run as SSE server on port 8080
server.run(transport="sse", port=8080)
Connect with any MCP client:
mcp-client sse http://localhost:8080/sse
MCP Factory - Auto-Generate Servers
The MCP Factory automatically creates MCP servers from existing Python code with intelligent dependency analysis, safe type conversion, and full async support. Full documentation β
Quick Examples
from makemcp.factory import create_mcp_from_module
# Create server from any Python file
server = create_mcp_from_module("my_utils.py")
server.run()
# CLI with auto-dependency detection
# mcp-factory my_utils.py --name utils-server
Smart Dependency Detection
# If dependencies are missing, get helpful errors:
$ mcp-factory my_module.py
Missing dependencies detected:
β Required: numpy, pandas
β οΈ Optional: matplotlib (in try/except block)
π‘ Quick install: uv pip install numpy pandas # Uses uv if available
Async Functions Work Automatically
# my_async_tools.py
import asyncio
import aiohttp
async def fetch_webpage(url: str) -> dict:
"""Fetch webpage content asynchronously."""
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return {
"url": url,
"status": response.status,
"content": await response.text()
}
async def parallel_requests(urls: list) -> list:
"""Fetch multiple URLs in parallel."""
tasks = [fetch_webpage(url) for url in urls]
return await asyncio.gather(*tasks, return_exceptions=True)
def sync_helper(text: str) -> str:
"""Synchronous helper function."""
return text.upper()
# Generate server automatically
if __name__ == "__main__":
from makemcp.factory import create_mcp_from_module
server = create_mcp_from_module(__file__)
server.run()
Generate from Classes with Async Methods
from makemcp.factory import MCPFactory
class AsyncDataProcessor:
"""Data processor with async methods."""
def __init__(self):
self.processed_count = 0
async def process_batch(self, items: list) -> dict:
"""Process items asynchronously."""
results = []
for item in items:
await asyncio.sleep(0.1) # Simulate async work
results.append(f"Processed: {item}")
self.processed_count += len(items)
return {
"results": results,
"total_processed": self.processed_count
}
def get_stats(self) -> dict:
"""Get processing statistics (sync method)."""
return {"processed_count": self.processed_count}
# Generate server from class
factory = MCPFactory()
server = factory.from_class(AsyncDataProcessor)
server.run()
Use Decorators for Selective Exposure
from makemcp.factory import mcp_tool, create_mcp_from_module
@mcp_tool
async def exposed_async_function(data: str) -> str:
"""This async function will be exposed as an MCP tool."""
await asyncio.sleep(0.1)
return f"Processed: {data}"
@mcp_tool(name="custom_name", description="Custom async tool")
async def another_async(value: int) -> int:
"""Another async function with custom metadata."""
await asyncio.sleep(0.1)
return value * 2
async def not_exposed(data: str) -> str:
"""This function won't be exposed (no decorator)."""
return data
# Only decorated functions become tools
server = create_mcp_from_module(__file__)
Advanced Features
Custom Tool Schemas
@server.tool(
description="Advanced calculation tool",
schema={
"type": "object",
"properties": {
"operation": {"type": "string", "enum": ["add", "multiply"]},
"values": {"type": "array", "items": {"type": "number"}}
}
}
)
def calculate_many(operation: str, values: list[float]) -> float:
"""Calculate with multiple values."""
if operation == "add":
return sum(values)
elif operation == "multiply":
import math
return math.prod(values)
Server Configuration
from makemcp import MakeMCPServer
server = MakeMCPServer(
name="my-server",
version="2.0.0",
description="My advanced MCP server",
log_level="DEBUG" # Enable debug logging
)
Standalone Decorators
You can also use decorators before creating the server:
from makemcp import tool, resource, prompt, MakeMCPServer
@tool()
def my_tool(arg: str) -> str:
return f"Processed: {arg}"
@resource("data://{id}")
def my_resource(id: str) -> str:
return f"Data for {id}"
# Later, create server and register
server = MakeMCPServer("my-server")
server.register_module(__main__) # Coming soon
server.run()
Running Your Server
As stdio (default)
python your_server.py
As SSE server
python your_server.py --transport sse --port 8080
Testing with MCP Inspector
mcp-inspector stdio -- python your_server.py
Discovery and Registration
MakeMCP provides comprehensive discovery mechanisms for both local and network-based MCP servers, making it easy to integrate with Gleitzeit and other MCP clients.
Overview
MakeMCP supports two discovery approaches:
- Registry-based discovery for stdio servers (launched as child processes)
- Network autodiscovery for SSE/HTTP servers (running as network services)
Server Registry (for stdio servers)
The server registry allows you to register MakeMCP servers that can be launched via stdio transport.
Registering Servers
# Register a server with the CLI
makemcp register my-server "python my_server.py" \
--description "My custom MCP server" \
--tool-prefix "my."
# Or register programmatically
from makemcp import register_server
register_server(
name="my-server",
command=["python", "my_server.py"],
description="My custom MCP server",
tool_prefix="my."
)
Listing Registered Servers
# List all registered servers
makemcp list
# Or programmatically
from makemcp import list_servers
for server in list_servers():
print(f"{server.name}: {server.description}")
Auto-Discovery in Filesystem
MakeMCP can automatically discover servers in your filesystem:
# Discover servers in current directory and common locations
makemcp discover --scan-filesystem
# Discover and auto-register found servers
makemcp discover --scan-filesystem --auto-register
# Specify custom search paths
makemcp discover --scan-filesystem --paths ./my-servers ~/mcp-servers
Network Autodiscovery (for SSE/HTTP servers)
Network servers automatically broadcast their presence via UDP multicast when running with SSE or HTTP transport.
Server-Side (Automatic)
from makemcp import MakeMCPServer
# Network servers automatically broadcast when running
server = MakeMCPServer("my-server")
# Add discovery metadata
server = MakeMCPServer(
"my-server",
discovery_metadata={
"author": "Your Name",
"category": "utilities",
"tags": ["ai", "tools"]
}
)
# Run as SSE server (autodiscovery enabled automatically)
server.run(transport="sse", port=8080)
Client-Side Discovery
# Discover network servers
makemcp discover --scan-network
# Discover with custom timeout
makemcp discover --scan-network --timeout 10
Or programmatically:
import asyncio
from makemcp import discover_servers
async def find_network_servers():
servers = await discover_servers(timeout=5.0)
for server in servers:
print(f"Found: {server.name} at {server.host}:{server.port}")
asyncio.run(find_network_servers())
MakeMCP CLI
The MakeMCP CLI provides comprehensive server management:
# Register a server
makemcp register <name> <command> [options]
# Unregister a server
makemcp unregister <name>
# List registered servers
makemcp list
# Show server information
makemcp info <name>
# Discover servers (filesystem and/or network)
makemcp discover [--scan-filesystem] [--scan-network]
# Export configuration for Gleitzeit
makemcp export --format yaml > ~/.gleitzeit/mcp_servers.yaml
Server Metadata
MakeMCP servers can provide metadata via the --info flag:
# Get server information
python my_server.py --info
This returns JSON with server details:
{
"name": "my-server",
"version": "1.0.0",
"description": "My custom server",
"capabilities": {
"tools": ["tool1", "tool2"],
"resources": ["resource1"],
"prompts": ["prompt1"]
}
}
Integration with Gleitzeit
MakeMCP servers work seamlessly with Gleitzeit:
Automatic Configuration Export
MakeMCP can export your registered servers directly to Gleitzeit configuration:
# Export all registered servers to Gleitzeit config
makemcp export --format yaml > ~/.gleitzeit/mcp_servers.yaml
# The generated config will look like:
mcp:
auto_discover: true
servers:
- name: "my-server"
connection_type: "stdio"
command: ["python", "my_server.py"]
tool_prefix: "my."
auto_start: true
Manual Configuration
You can also manually configure MakeMCP servers in Gleitzeit:
# ~/.gleitzeit/config.yaml
mcp:
servers:
# Stdio server (launched as child process)
- name: "my-makemcp-server"
connection_type: "stdio"
command: ["python", "path/to/my_server.py"]
working_dir: "${HOME}/my-servers"
tool_prefix: "my."
auto_start: true
# SSE server (network connection)
- name: "my-sse-server"
connection_type: "sse"
url: "http://localhost:8080/sse"
tool_prefix: "sse."
auto_start: false # Don't launch, just connect
Discovery Workflow
-
Register your servers with MakeMCP:
makemcp register my-server "python my_server.py" --tool-prefix "my." -
Export to Gleitzeit:
makemcp export > ~/.gleitzeit/mcp_servers.yaml -
Use in Gleitzeit workflows:
tasks: - name: "Use MCP tool" type: mcp provider: my-server tool: my.some_tool arguments: param: value
Network Server Discovery
For SSE/HTTP servers, Gleitzeit can discover them automatically via UDP multicast:
# Your MakeMCP server broadcasts automatically
server = MakeMCPServer("my-server")
server.run(transport="sse", port=8080) # Broadcasts on network
# Gleitzeit can discover it
# (when auto_discover: true in config)
API Reference
MakeMCPServer
Main server class for creating MCP servers.
Methods:
tool(name=None, description=None, schema=None)- Decorator for toolsresource(uri_template, name=None, description=None, mime_type="text/plain")- Decorator for resourcesprompt(name=None, description=None, arguments=None)- Decorator for promptsrun(transport="stdio", host="localhost", port=8000)- Run the serverlist_tools()- Get list of registered toolslist_resources()- Get list of registered resourceslist_prompts()- Get list of registered prompts
Types
MakeMCP provides several helpful type definitions:
ToolResult- Standard result format for toolsResourceContent- Content returned by resourcesPromptMessage- Message in a prompt templateContext- Execution context for toolsServerConfig- Server configuration
Testing
MakeMCP includes a comprehensive test suite. Run tests using:
# Using the test runner script (auto-detects uv)
./run_tests.sh
# Using uv directly (fastest)
uv run pytest tests/ -v
# Using standard pytest
pytest tests/ -v
# Run specific test file
uv run pytest tests/test_factory.py -v
# Run with coverage
uv run pytest tests/ --cov=src/makemcp --cov-report=html
Dependency Management
MakeMCP uses smart dependency detection and can automatically use uv for faster installations:
Automatic Detection
When the MCP Factory detects missing dependencies, it will:
- Check if
uvis available - Use
uv pip installif available (10-100x faster) - Fall back to
pip installif not
Example with Missing Dependencies
# If numpy is not installed, MakeMCP will detect it
import numpy as np
def calculate_mean(data: list) -> float:
"""Calculate mean using numpy."""
return np.mean(data)
When running the factory:
$ mcp-factory my_module.py
Missing dependencies detected:
β Required: numpy
π‘ Quick install: uv pip install numpy # or pip install if uv not available
Managing Dependencies
For projects using MakeMCP:
# Fast dependency installation with uv
uv pip sync # Install from requirements.txt
uv pip compile # Generate locked requirements
# Or traditional pip
pip install -r requirements.txt
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Development Setup
# Clone the repository
git clone https://github.com/leifmarkthaler/makemcp.git
cd makemcp
# Use the setup script (recommended)
./setup.sh
# Or manual setup with uv
uv venv
source .venv/bin/activate
uv pip install -e ".[dev]"
# Run tests
./run_tests.sh
License
MIT License - see LICENSE file for details.
Full Feature Set
All features MakeMCP supports
- β Tools - Functions that LLMs can call
- β Resources - Data/content LLMs can access
- β Prompts - Reusable prompt templates
- β Async/Await - Full async support
- β Type Safety - Automatic schema from type hints
- β Multiple Transports - stdio, SSE, more coming
- β Auto-discovery - Network and registry based
- β Factory System - Convert existing code instantly
- β Configuration - Safe, dev, and custom configs
- β Dependency Analysis - Smart missing package detection
- β UV Integration - 10-100x faster package management
- β Error Handling - Comprehensive error messages
- β Testing - Full test suite included
- β Examples - Many examples to learn from
Links
Important Notes
Official MCP SDK Compatibility
MakeMCP is specifically designed to work with the official MCP Python SDK (mcp package). It is not compatible with:
- FastMCP or other third-party implementations
- Older or experimental MCP libraries
The official SDK uses a handler-based approach for registering tools, resources, and prompts. MakeMCP provides a decorator-based interface that internally manages these handlers for you.
Acknowledgments
MakeMCP is built on top of the official MCP Python SDK and aims to make MCP server development more accessible and enjoyable.
