# NextMCP
[](https://github.com/KeshavVarad/NextMCP/actions)
[](https://badge.fury.io/py/nextmcp)
[](https://pypi.org/project/nextmcp/)
[](https://opensource.org/licenses/MIT)
[](https://github.com/psf/black)
**Production-grade MCP server toolkit with minimal boilerplate**
NextMCP is a Python SDK built on top of FastMCP that provides a developer-friendly experience for building MCP (Model Context Protocol) servers. Inspired by Next.js, it offers minimal setup, powerful middleware, and a rich CLI for rapid development.
## Features
- **Full MCP Specification** - Complete support for Tools, Prompts, and Resources primitives
- **Minimal Boilerplate** - Get started with just a few lines of code
- **Decorator-based API** - Register tools, prompts, and resources with simple decorators
- **Async Support** - Full support for async/await across all primitives
- **Argument Completion** - Smart suggestions for prompt arguments and resource templates
- **Resource Subscriptions** - Real-time notifications when resources change
- **WebSocket Transport** - Real-time bidirectional communication for interactive applications
- **Global & Primitive-specific Middleware** - Add logging, auth, rate limiting, caching, and more
- **Rich CLI** - Scaffold projects, run servers, and generate docs with `mcp` commands
- **Configuration Management** - Support for `.env`, YAML config files, and environment variables
- **Schema Validation** - Optional Pydantic integration for type-safe inputs
- **Production Ready** - Built-in error handling, logging, and comprehensive testing
## Installation
### Basic Installation
```bash
pip install nextmcp
```
### With Optional Dependencies
```bash
# CLI tools (recommended)
pip install nextmcp[cli]
# Configuration support
pip install nextmcp[config]
# Schema validation with Pydantic
pip install nextmcp[schema]
# WebSocket transport
pip install nextmcp[websocket]
# Everything
pip install nextmcp[all]
# Development dependencies
pip install nextmcp[dev]
```
## Quick Start
### 1. Create a new project
```bash
mcp init my-bot
cd my-bot
```
### 2. Write your first tool
```python
# app.py
from nextmcp import NextMCP
app = NextMCP("my-bot")
@app.tool()
def greet(name: str) -> str:
"""Greet someone by name"""
return f"Hello, {name}!"
if __name__ == "__main__":
app.run()
```
### 3. Run your server
```bash
mcp run app.py
```
That's it! Your MCP server is now running with the `greet` tool available.
## Core Concepts
### Creating an Application
```python
from nextmcp import NextMCP
app = NextMCP(
name="my-mcp-server",
description="A custom MCP server"
)
```
### Registering Tools
```python
@app.tool()
def calculate(x: int, y: int) -> int:
"""Add two numbers"""
return x + y
# With custom name and description
@app.tool(name="custom_name", description="A custom tool")
def my_function(data: str) -> dict:
return {"result": data}
```
### Adding Middleware
Middleware wraps your tools to add cross-cutting functionality.
#### Global Middleware (applied to all tools)
```python
from nextmcp import log_calls, error_handler
# Add middleware that applies to all tools
app.add_middleware(log_calls)
app.add_middleware(error_handler)
@app.tool()
def my_tool(x: int) -> int:
return x * 2 # This will be logged and error-handled automatically
```
#### Tool-specific Middleware
```python
from nextmcp import cache_results, require_auth
@app.tool()
@cache_results(ttl_seconds=300) # Cache for 5 minutes
def expensive_operation(param: str) -> dict:
# Expensive computation here
return {"result": perform_calculation(param)}
@app.tool()
@require_auth(valid_keys={"secret-key-123"})
def protected_tool(auth_key: str, data: str) -> str:
return f"Protected: {data}"
```
### Built-in Middleware
NextMCP includes several production-ready middleware:
- **`log_calls`** - Log all tool invocations with timing
- **`error_handler`** - Catch exceptions and return structured errors
- **`require_auth(valid_keys)`** - API key authentication
- **`rate_limit(max_calls, time_window)`** - Rate limiting
- **`cache_results(ttl_seconds)`** - Response caching
- **`validate_inputs(**validators)`** - Custom input validation
- **`timeout(seconds)`** - Execution timeout
All middleware also have async variants (e.g., `log_calls_async`, `error_handler_async`, etc.) for use with async tools.
### Async Support
NextMCP has full support for async/await patterns, allowing you to build high-performance tools that can handle concurrent I/O operations.
#### Basic Async Tool
```python
from nextmcp import NextMCP
import asyncio
app = NextMCP("async-app")
@app.tool()
async def fetch_data(url: str) -> dict:
"""Fetch data from an API asynchronously"""
# Use async libraries like httpx, aiohttp, etc.
await asyncio.sleep(0.1) # Simulate API call
return {"url": url, "data": "fetched"}
```
#### Async Middleware
Use async middleware variants for async tools:
```python
from nextmcp import log_calls_async, error_handler_async, cache_results_async
app.add_middleware(log_calls_async)
app.add_middleware(error_handler_async)
@app.tool()
@cache_results_async(ttl_seconds=300)
async def expensive_async_operation(param: str) -> dict:
await asyncio.sleep(1) # Simulate expensive operation
return {"result": param}
```
#### Concurrent Operations
The real power of async is handling multiple operations concurrently:
```python
@app.tool()
async def fetch_multiple_sources(sources: list) -> dict:
"""Fetch data from multiple sources concurrently"""
async def fetch_one(source: str):
# Each fetch happens concurrently, not sequentially
await asyncio.sleep(0.1)
return {"source": source, "data": "..."}
# Gather results concurrently - much faster than sequential!
results = await asyncio.gather(*[fetch_one(s) for s in sources])
return {"sources": results}
```
**Performance Comparison:**
- Sequential: 4 sources × 0.1s = 0.4s
- Concurrent (async): ~0.1s (all at once!)
#### Mixed Sync and Async Tools
You can have both sync and async tools in the same application:
```python
@app.tool()
def sync_tool(x: int) -> int:
"""Regular synchronous tool"""
return x * 2
@app.tool()
async def async_tool(x: int) -> int:
"""Async tool for I/O operations"""
await asyncio.sleep(0.1)
return x * 3
```
#### When to Use Async
**Use async for:**
- HTTP API calls (with `httpx`, `aiohttp`)
- Database queries (with `asyncpg`, `motor`)
- File I/O operations
- Multiple concurrent operations
- WebSocket connections
**Stick with sync for:**
- CPU-bound operations (heavy computations)
- Simple operations with no I/O
- When third-party libraries don't support async
See `examples/async_weather_bot/` for a complete async example.
### Schema Validation with Pydantic
```python
from nextmcp import NextMCP
from pydantic import BaseModel
app = NextMCP("my-server")
class WeatherInput(BaseModel):
city: str
units: str = "fahrenheit"
@app.tool()
def get_weather(city: str, units: str = "fahrenheit") -> dict:
# Input automatically validated against WeatherInput schema
return {"city": city, "temp": 72, "units": units}
```
### Prompts
Prompts are user-driven workflow templates that guide AI interactions. They're explicitly invoked by users (not automatically by the AI) and can reference available tools and resources.
#### Basic Prompts
```python
from nextmcp import NextMCP
app = NextMCP("my-server")
@app.prompt()
def vacation_planner(destination: str, budget: int) -> str:
"""Plan a vacation itinerary."""
return f"""
Plan a vacation to {destination} with a budget of ${budget}.
Use these tools:
- flight_search: Find flights
- hotel_search: Find accommodations
Check these resources:
- resource://user/preferences
- resource://calendar/availability
"""
```
#### Prompts with Argument Completion
```python
from nextmcp import argument
@app.prompt(description="Research a topic", tags=["research"])
@argument("topic", description="What to research", suggestions=["Python", "MCP", "FastMCP"])
@argument("depth", suggestions=["basic", "detailed", "comprehensive"])
def research_prompt(topic: str, depth: str = "basic") -> str:
"""Generate a research prompt with the specified depth."""
return f"Research {topic} at {depth} level..."
# Dynamic completion
@app.prompt_completion("research_prompt", "topic")
async def complete_topics(partial: str) -> list[str]:
"""Provide dynamic topic suggestions."""
topics = await fetch_available_topics()
return [t for t in topics if partial.lower() in t.lower()]
```
#### Async Prompts
```python
@app.prompt(tags=["analysis"])
async def analyze_prompt(data_source: str) -> str:
"""Generate analysis prompt with real-time data."""
data = await fetch_data(data_source)
return f"Analyze this data: {data}"
```
**When to use prompts:**
- Guide complex multi-step workflows
- Provide templates for common tasks
- Structure AI interactions
- Reference available tools and resources
See `examples/knowledge_base/` for a complete example using prompts.
### Resources
Resources provide read-only access to contextual data through unique URIs. They're application-driven and give the AI access to information without triggering actions.
#### Direct Resources
```python
from nextmcp import NextMCP
app = NextMCP("my-server")
@app.resource("file:///logs/app.log", description="Application logs")
def app_logs() -> str:
"""Provide access to application logs."""
with open("/var/logs/app.log") as f:
return f.read()
@app.resource("config://app/settings", mime_type="application/json")
def app_settings() -> dict:
"""Provide application configuration."""
return {
"theme": "dark",
"language": "en",
"max_results": 100
}
```
#### Resource Templates
Templates allow parameterized access to dynamic resources:
```python
@app.resource_template("weather://forecast/{city}/{date}")
async def weather_forecast(city: str, date: str) -> dict:
"""Get weather forecast for a specific city and date."""
return await fetch_weather(city, date)
@app.resource_template("file:///docs/{category}/{filename}")
def documentation(category: str, filename: str) -> str:
"""Access documentation files."""
return Path(f"/docs/{category}/{filename}").read_text()
# Template parameter completion
@app.template_completion("weather_forecast", "city")
def complete_cities(partial: str) -> list[str]:
"""Suggest city names."""
return ["London", "Paris", "Tokyo", "New York"]
```
#### Subscribable Resources
Resources can notify subscribers when they change:
```python
@app.resource(
"config://live/settings",
subscribable=True,
max_subscribers=50
)
async def live_settings() -> dict:
"""Provide live configuration that can change."""
return await load_live_config()
# Notify subscribers when config changes
app.notify_resource_changed("config://live/settings")
# Manage subscriptions
app.subscribe_to_resource("config://live/settings", "subscriber_id")
app.unsubscribe_from_resource("config://live/settings", "subscriber_id")
```
#### Async Resources
```python
@app.resource("db://users/recent")
async def recent_users() -> list[dict]:
"""Get recently active users from database."""
return await db.query("SELECT * FROM users ORDER BY last_active DESC LIMIT 10")
```
**When to use resources:**
- Provide read-only data access
- Expose configuration and settings
- Share application state
- Offer real-time data feeds (with subscriptions)
**Resource URIs can use any scheme:**
- `file://` - File system access
- `config://` - Configuration data
- `db://` - Database queries
- `api://` - External API data
- Custom schemes for your use case
See `examples/knowledge_base/` for a complete example using resources and templates.
### Configuration
NextMCP supports multiple configuration sources with automatic merging:
```python
from nextmcp import load_config
# Load from config.yaml and .env
config = load_config(config_file="config.yaml")
# Access configuration
host = config.get_host()
port = config.get_port()
debug = config.is_debug()
# Custom config values
api_key = config.get("api_key", default="default-key")
```
**config.yaml**:
```yaml
host: "0.0.0.0"
port: 8080
log_level: "DEBUG"
api_key: "my-secret-key"
```
**.env**:
```
MCP_HOST=0.0.0.0
MCP_PORT=8080
API_KEY=my-secret-key
```
### WebSocket Transport
NextMCP supports WebSocket transport for real-time, bidirectional communication - perfect for chat applications, live updates, and interactive tools.
#### Server Setup
```python
from nextmcp import NextMCP
from nextmcp.transport import WebSocketTransport
app = NextMCP("websocket-server")
@app.tool()
async def send_message(username: str, message: str) -> dict:
return {
"status": "sent",
"username": username,
"message": message
}
# Create WebSocket transport
transport = WebSocketTransport(app)
# Run on ws://localhost:8765
transport.run(host="0.0.0.0", port=8765)
```
#### Client Usage
```python
from nextmcp.transport import WebSocketClient
async def main():
async with WebSocketClient("ws://localhost:8765") as client:
# List available tools
tools = await client.list_tools()
print(f"Available tools: {tools}")
# Invoke a tool
result = await client.invoke_tool(
"send_message",
{"username": "Alice", "message": "Hello!"}
)
print(f"Result: {result}")
```
#### WebSocket Features
- **Real-time Communication**: Persistent connections with low latency
- **Bidirectional**: Server can push updates to clients
- **JSON-RPC Protocol**: Clean message format for tool invocation
- **Multiple Clients**: Handle multiple concurrent connections
- **Async Native**: Built on Python's async/await for high performance
#### When to Use WebSocket vs HTTP
| Feature | HTTP (FastMCP) | WebSocket |
|---------|----------------|-----------|
| Connection type | One per request | Persistent |
| Latency | Higher overhead | Lower latency |
| Bidirectional | No | Yes |
| Use case | Traditional APIs | Real-time apps |
| Best for | Request/response | Chat, notifications, live data |
See `examples/websocket_chat/` for a complete WebSocket application.
## Plugin System
NextMCP features a powerful plugin system that allows you to extend functionality through modular, reusable components.
### What are Plugins?
Plugins are self-contained modules that can:
- Register new tools with your application
- Add middleware for cross-cutting concerns
- Extend core functionality
- Be easily shared and reused across projects
### Creating a Plugin
```python
from nextmcp import Plugin
class MathPlugin(Plugin):
name = "math-plugin"
version = "1.0.0"
description = "Mathematical operations"
author = "Your Name"
def on_load(self, app):
@app.tool()
def add(a: float, b: float) -> float:
"""Add two numbers"""
return a + b
@app.tool()
def multiply(a: float, b: float) -> float:
"""Multiply two numbers"""
return a * b
```
### Using Plugins
#### Method 1: Auto-discovery
```python
from nextmcp import NextMCP
app = NextMCP("my-app")
# Discover all plugins in a directory
app.discover_plugins("./plugins")
# Load all discovered plugins
app.load_plugins()
```
#### Method 2: Direct Loading
```python
from nextmcp import NextMCP
from my_plugins import MathPlugin
app = NextMCP("my-app")
# Load a specific plugin
app.use_plugin(MathPlugin)
```
### Plugin Lifecycle
Plugins have three lifecycle hooks:
1. **`on_init()`** - Called during plugin initialization
2. **`on_load(app)`** - Called when plugin is loaded (register tools here)
3. **on_unload()** - Called when plugin is unloaded (cleanup)
```python
class LifecyclePlugin(Plugin):
name = "lifecycle-example"
version = "1.0.0"
def on_init(self):
# Early initialization
self.config = {}
def on_load(self, app):
# Register tools and middleware
@app.tool()
def my_tool():
return "result"
def on_unload(self):
# Cleanup resources
self.config.clear()
```
### Plugin with Middleware
```python
class TimingPlugin(Plugin):
name = "timing"
version = "1.0.0"
def on_load(self, app):
import time
def timing_middleware(fn):
def wrapper(*args, **kwargs):
start = time.time()
result = fn(*args, **kwargs)
elapsed = (time.time() - start) * 1000
print(f"⏱️ {fn.__name__} took {elapsed:.2f}ms")
return result
return wrapper
app.add_middleware(timing_middleware)
```
### Plugin Dependencies
Plugins can declare dependencies on other plugins:
```python
class DependentPlugin(Plugin):
name = "advanced-math"
version = "1.0.0"
dependencies = ["math-plugin"] # Loads math-plugin first
def on_load(self, app):
@app.tool()
def factorial(n: int) -> int:
# Can use tools from math-plugin
return 1 if n <= 1 else n * factorial(n - 1)
```
### Managing Plugins
```python
# List all loaded plugins
for plugin in app.plugins.list_plugins():
print(f"{plugin['name']} v{plugin['version']} - {plugin['loaded']}")
# Get a specific plugin
plugin = app.plugins.get_plugin("math-plugin")
# Unload a plugin
app.plugins.unload_plugin("math-plugin")
# Check if plugin is loaded
if "math-plugin" in app.plugins:
print("Math plugin is available")
```
### Plugin Best Practices
1. **Use descriptive names** - Make plugin names clear and unique
2. **Version semantically** - Follow semver (major.minor.patch)
3. **Document thoroughly** - Add descriptions and docstrings
4. **Handle errors gracefully** - Catch exceptions in lifecycle hooks
5. **Declare dependencies** - List required plugins explicitly
6. **Implement cleanup** - Use `on_unload()` to release resources
See `examples/plugin_example/` for a complete plugin demonstration with multiple plugin types.
## Metrics & Monitoring
NextMCP includes a built-in metrics system for monitoring your MCP applications in production.
### Quick Start
```python
from nextmcp import NextMCP
app = NextMCP("my-app")
app.enable_metrics() # That's it! Automatic metrics collection
@app.tool()
def my_tool():
return "result"
```
### Automatic Metrics
When metrics are enabled, NextMCP automatically tracks:
- **`tool_invocations_total`** - Total number of tool invocations
- **`tool_duration_seconds`** - Histogram of tool execution times
- **`tool_completed_total`** - Completed invocations by status (success/error)
- **`tool_errors_total`** - Errors by error type
- **`tool_active_invocations`** - Currently executing tools
All metrics include labels for the tool name and any global labels you configure.
### Custom Metrics
Add your own metrics for business logic:
```python
@app.tool()
def process_order(order_id: int):
# Custom counter
app.metrics.inc_counter("orders_processed")
# Custom gauge
app.metrics.set_gauge("current_queue_size", get_queue_size())
# Custom histogram with timer
with app.metrics.time_histogram("processing_duration"):
result = process(order_id)
return result
```
### Metric Types
#### Counter
Monotonically increasing value. Use for: counts, totals.
```python
counter = app.metrics.counter("requests_total")
counter.inc() # Increment by 1
counter.inc(5) # Increment by 5
```
#### Gauge
Value that can go up or down. Use for: current values, temperatures, queue sizes.
```python
gauge = app.metrics.gauge("active_connections")
gauge.set(10) # Set to specific value
gauge.inc() # Increment
gauge.dec() # Decrement
```
#### Histogram
Distribution of values. Use for: durations, sizes.
```python
histogram = app.metrics.histogram("request_duration_seconds")
histogram.observe(0.25)
# Or use as timer
with app.metrics.time_histogram("duration"):
# Code to time
pass
```
### Exporting Metrics
#### Prometheus Format
```python
# Get metrics in Prometheus format
prometheus_data = app.get_metrics_prometheus()
print(prometheus_data)
```
Output:
```
# HELP my-app_tool_invocations_total Total tool invocations
# TYPE my-app_tool_invocations_total counter
my-app_tool_invocations_total{tool="my_tool"} 42.0
# HELP my-app_tool_duration_seconds Tool execution duration
# TYPE my-app_tool_duration_seconds histogram
my-app_tool_duration_seconds_bucket{tool="my_tool",le="0.005"} 10
my-app_tool_duration_seconds_bucket{tool="my_tool",le="0.01"} 25
my-app_tool_duration_seconds_sum{tool="my_tool"} 1.234
my-app_tool_duration_seconds_count{tool="my_tool"} 42
```
#### JSON Format
```python
# Get metrics as JSON
json_data = app.get_metrics_json(pretty=True)
```
### Configuration
```python
app.enable_metrics(
collect_tool_metrics=True, # Track tool invocations
collect_system_metrics=False, # Track CPU/memory (future)
collect_transport_metrics=False, # Track WebSocket/HTTP (future)
labels={"env": "prod", "region": "us-west"} # Global labels
)
```
### Metrics with Labels
Labels allow you to slice and dice your metrics:
```python
counter = app.metrics.counter(
"api_requests",
labels={"method": "GET", "endpoint": "/users"}
)
counter.inc()
```
### Integration with Monitoring Systems
The Prometheus format is compatible with:
- Prometheus for scraping and storage
- Grafana for visualization
- AlertManager for alerting
- Any Prometheus-compatible system
See `examples/metrics_example/` for a complete metrics demonstration.
## CLI Commands
NextMCP provides a rich CLI for common development tasks.
### Initialize a new project
```bash
mcp init my-project
mcp init my-project --template weather_bot
mcp init my-project --path /custom/path
```
### Run a server
```bash
mcp run app.py
mcp run app.py --host 0.0.0.0 --port 8080
mcp run app.py --reload # Auto-reload on changes
```
### Generate documentation
```bash
mcp docs app.py
mcp docs app.py --output docs.md
mcp docs app.py --format json
```
### Show version
```bash
mcp version
```
## Examples
Check out the `examples/` directory for complete working examples:
- **weather_bot** - A weather information server with multiple tools
- **async_weather_bot** - Async version demonstrating concurrent operations and async middleware
- **websocket_chat** - Real-time chat server using WebSocket transport
- **plugin_example** - Plugin system demonstration with multiple plugin types
- **metrics_example** - Metrics and monitoring demonstration with automatic and custom metrics
## Development
### Setting up for development
```bash
# Clone the repository
git clone https://github.com/KeshavVarad/NextMCP.git
cd nextmcp
# Install in editable mode with dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Run tests with coverage
pytest --cov=nextmcp --cov-report=html
# Format code
black nextmcp tests
# Lint code
ruff check nextmcp tests
# Type check
mypy nextmcp
```
### Running Tests
```bash
# Run all tests
pytest
# Run specific test file
pytest tests/test_core.py
# Run with verbose output
pytest -v
# Run with coverage
pytest --cov=nextmcp
```
## Architecture
NextMCP is organized into several modules:
- **`core.py`** - Main `NextMCP` class and application lifecycle
- **`tools.py`** - Tool registration, metadata, and documentation generation
- **`middleware.py`** - Built-in middleware for common use cases
- **`config.py`** - Configuration management (YAML, .env, environment variables)
- **`cli.py`** - Typer-based CLI commands
- **`logging.py`** - Centralized logging setup and utilities
## Comparison with FastMCP
NextMCP builds on FastMCP to provide:
| Feature | FastMCP | NextMCP |
|---------|---------|-----------|
| Basic MCP server | ✅ | ✅ |
| Tool registration | Manual | Decorator-based |
| Async/await support | ❌ | ✅ Full support |
| WebSocket transport | ❌ | ✅ Built-in |
| Middleware | ❌ | Global + tool-specific |
| Plugin system | ❌ | ✅ Full-featured |
| Metrics & monitoring | ❌ | ✅ Built-in |
| CLI commands | ❌ | `init`, `run`, `docs` |
| Project scaffolding | ❌ | Templates & examples |
| Configuration management | ❌ | YAML + .env support |
| Built-in logging | Basic | Colored, structured |
| Schema validation | ❌ | Pydantic integration |
| Testing utilities | ❌ | Included |
## Roadmap
- [x] Async tool support
- [x] WebSocket transport
- [x] Plugin system
- [x] Built-in monitoring and metrics
- [ ] Production deployment guides
- [ ] Docker support
- [ ] More example projects
- [ ] Documentation site
## Future Work
NextMCP is evolving to become a complete implementation of the Model Context Protocol specification. Currently, only the **Tools** primitive is fully supported. Future versions will include:
### v0.2.0 - Full MCP Primitives Support
- **Prompts**: User-driven workflow templates with argument completion
- **Resources**: Read-only context providers with URI-based access
- **Resource Templates**: Dynamic resources with parameter-based URIs
- **Subscriptions**: Real-time notifications for resource changes
### v0.3.0 - Convention-Based Architecture
- **File-based Auto-Discovery**: Automatic discovery of tools, prompts, and resources from directory structure
- **Project Manifest**: `nextmcp.config.yaml` for declarative configuration
- **Hot Reload**: Development mode with automatic file watching
- **Enhanced CLI**: `mcp dev`, `mcp validate`, `mcp test` commands
### v0.4.0 - Production & Deployment
- **Deployment Manifests**: Generate Docker, AWS Lambda, and serverless configs
- **One-Command Deploy**: `mcp deploy --target=aws-lambda`
- **Production Builds**: Optimized bundles with `mcp build`
- **Package Distribution**: `mcp package` for Docker, PyPI, and serverless
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
## License
This project is licensed under the MIT License - see the LICENSE file for details.
## Acknowledgments
- Built on top of [FastMCP](https://github.com/jlowin/fastmcp)
- Inspired by [Next.js](https://nextjs.org/) developer experience
- CLI powered by [Typer](https://typer.tiangolo.com/)
## Support
- GitHub Issues: [https://github.com/KeshavVarad/NextMCP/issues](https://github.com/KeshavVarad/NextMCP/issues)
- Documentation: [Coming soon]
---
**Made with ❤️ by the NextMCP community**
Raw data
{
"_id": null,
"home_page": "https://github.com/KeshavVarad/NextMCP",
"name": "nextmcp",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "mcp, server, sdk, fastmcp, framework",
"author": "NextMCP Contributors",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/03/91/93103432f3e1bed9cdbd45ff528f09b1fc9692ef6bf1be24703c13df3e68/nextmcp-0.3.0.tar.gz",
"platform": null,
"description": "# NextMCP\n\n[](https://github.com/KeshavVarad/NextMCP/actions)\n[](https://badge.fury.io/py/nextmcp)\n[](https://pypi.org/project/nextmcp/)\n[](https://opensource.org/licenses/MIT)\n[](https://github.com/psf/black)\n\n**Production-grade MCP server toolkit with minimal boilerplate**\n\nNextMCP is a Python SDK built on top of FastMCP that provides a developer-friendly experience for building MCP (Model Context Protocol) servers. Inspired by Next.js, it offers minimal setup, powerful middleware, and a rich CLI for rapid development.\n\n## Features\n\n- **Full MCP Specification** - Complete support for Tools, Prompts, and Resources primitives\n- **Minimal Boilerplate** - Get started with just a few lines of code\n- **Decorator-based API** - Register tools, prompts, and resources with simple decorators\n- **Async Support** - Full support for async/await across all primitives\n- **Argument Completion** - Smart suggestions for prompt arguments and resource templates\n- **Resource Subscriptions** - Real-time notifications when resources change\n- **WebSocket Transport** - Real-time bidirectional communication for interactive applications\n- **Global & Primitive-specific Middleware** - Add logging, auth, rate limiting, caching, and more\n- **Rich CLI** - Scaffold projects, run servers, and generate docs with `mcp` commands\n- **Configuration Management** - Support for `.env`, YAML config files, and environment variables\n- **Schema Validation** - Optional Pydantic integration for type-safe inputs\n- **Production Ready** - Built-in error handling, logging, and comprehensive testing\n\n## Installation\n\n### Basic Installation\n\n```bash\npip install nextmcp\n```\n\n### With Optional Dependencies\n\n```bash\n# CLI tools (recommended)\npip install nextmcp[cli]\n\n# Configuration support\npip install nextmcp[config]\n\n# Schema validation with Pydantic\npip install nextmcp[schema]\n\n# WebSocket transport\npip install nextmcp[websocket]\n\n# Everything\npip install nextmcp[all]\n\n# Development dependencies\npip install nextmcp[dev]\n```\n\n## Quick Start\n\n### 1. Create a new project\n\n```bash\nmcp init my-bot\ncd my-bot\n```\n\n### 2. Write your first tool\n\n```python\n# app.py\nfrom nextmcp import NextMCP\n\napp = NextMCP(\"my-bot\")\n\n@app.tool()\ndef greet(name: str) -> str:\n \"\"\"Greet someone by name\"\"\"\n return f\"Hello, {name}!\"\n\nif __name__ == \"__main__\":\n app.run()\n```\n\n### 3. Run your server\n\n```bash\nmcp run app.py\n```\n\nThat's it! Your MCP server is now running with the `greet` tool available.\n\n## Core Concepts\n\n### Creating an Application\n\n```python\nfrom nextmcp import NextMCP\n\napp = NextMCP(\n name=\"my-mcp-server\",\n description=\"A custom MCP server\"\n)\n```\n\n### Registering Tools\n\n```python\n@app.tool()\ndef calculate(x: int, y: int) -> int:\n \"\"\"Add two numbers\"\"\"\n return x + y\n\n# With custom name and description\n@app.tool(name=\"custom_name\", description=\"A custom tool\")\ndef my_function(data: str) -> dict:\n return {\"result\": data}\n```\n\n### Adding Middleware\n\nMiddleware wraps your tools to add cross-cutting functionality.\n\n#### Global Middleware (applied to all tools)\n\n```python\nfrom nextmcp import log_calls, error_handler\n\n# Add middleware that applies to all tools\napp.add_middleware(log_calls)\napp.add_middleware(error_handler)\n\n@app.tool()\ndef my_tool(x: int) -> int:\n return x * 2 # This will be logged and error-handled automatically\n```\n\n#### Tool-specific Middleware\n\n```python\nfrom nextmcp import cache_results, require_auth\n\n@app.tool()\n@cache_results(ttl_seconds=300) # Cache for 5 minutes\ndef expensive_operation(param: str) -> dict:\n # Expensive computation here\n return {\"result\": perform_calculation(param)}\n\n@app.tool()\n@require_auth(valid_keys={\"secret-key-123\"})\ndef protected_tool(auth_key: str, data: str) -> str:\n return f\"Protected: {data}\"\n```\n\n### Built-in Middleware\n\nNextMCP includes several production-ready middleware:\n\n- **`log_calls`** - Log all tool invocations with timing\n- **`error_handler`** - Catch exceptions and return structured errors\n- **`require_auth(valid_keys)`** - API key authentication\n- **`rate_limit(max_calls, time_window)`** - Rate limiting\n- **`cache_results(ttl_seconds)`** - Response caching\n- **`validate_inputs(**validators)`** - Custom input validation\n- **`timeout(seconds)`** - Execution timeout\n\nAll middleware also have async variants (e.g., `log_calls_async`, `error_handler_async`, etc.) for use with async tools.\n\n### Async Support\n\nNextMCP has full support for async/await patterns, allowing you to build high-performance tools that can handle concurrent I/O operations.\n\n#### Basic Async Tool\n\n```python\nfrom nextmcp import NextMCP\nimport asyncio\n\napp = NextMCP(\"async-app\")\n\n@app.tool()\nasync def fetch_data(url: str) -> dict:\n \"\"\"Fetch data from an API asynchronously\"\"\"\n # Use async libraries like httpx, aiohttp, etc.\n await asyncio.sleep(0.1) # Simulate API call\n return {\"url\": url, \"data\": \"fetched\"}\n```\n\n#### Async Middleware\n\nUse async middleware variants for async tools:\n\n```python\nfrom nextmcp import log_calls_async, error_handler_async, cache_results_async\n\napp.add_middleware(log_calls_async)\napp.add_middleware(error_handler_async)\n\n@app.tool()\n@cache_results_async(ttl_seconds=300)\nasync def expensive_async_operation(param: str) -> dict:\n await asyncio.sleep(1) # Simulate expensive operation\n return {\"result\": param}\n```\n\n#### Concurrent Operations\n\nThe real power of async is handling multiple operations concurrently:\n\n```python\n@app.tool()\nasync def fetch_multiple_sources(sources: list) -> dict:\n \"\"\"Fetch data from multiple sources concurrently\"\"\"\n async def fetch_one(source: str):\n # Each fetch happens concurrently, not sequentially\n await asyncio.sleep(0.1)\n return {\"source\": source, \"data\": \"...\"}\n\n # Gather results concurrently - much faster than sequential!\n results = await asyncio.gather(*[fetch_one(s) for s in sources])\n return {\"sources\": results}\n```\n\n**Performance Comparison:**\n- Sequential: 4 sources \u00d7 0.1s = 0.4s\n- Concurrent (async): ~0.1s (all at once!)\n\n#### Mixed Sync and Async Tools\n\nYou can have both sync and async tools in the same application:\n\n```python\n@app.tool()\ndef sync_tool(x: int) -> int:\n \"\"\"Regular synchronous tool\"\"\"\n return x * 2\n\n@app.tool()\nasync def async_tool(x: int) -> int:\n \"\"\"Async tool for I/O operations\"\"\"\n await asyncio.sleep(0.1)\n return x * 3\n```\n\n#### When to Use Async\n\n**Use async for:**\n- HTTP API calls (with `httpx`, `aiohttp`)\n- Database queries (with `asyncpg`, `motor`)\n- File I/O operations\n- Multiple concurrent operations\n- WebSocket connections\n\n**Stick with sync for:**\n- CPU-bound operations (heavy computations)\n- Simple operations with no I/O\n- When third-party libraries don't support async\n\nSee `examples/async_weather_bot/` for a complete async example.\n\n### Schema Validation with Pydantic\n\n```python\nfrom nextmcp import NextMCP\nfrom pydantic import BaseModel\n\napp = NextMCP(\"my-server\")\n\nclass WeatherInput(BaseModel):\n city: str\n units: str = \"fahrenheit\"\n\n@app.tool()\ndef get_weather(city: str, units: str = \"fahrenheit\") -> dict:\n # Input automatically validated against WeatherInput schema\n return {\"city\": city, \"temp\": 72, \"units\": units}\n```\n\n### Prompts\n\nPrompts are user-driven workflow templates that guide AI interactions. They're explicitly invoked by users (not automatically by the AI) and can reference available tools and resources.\n\n#### Basic Prompts\n\n```python\nfrom nextmcp import NextMCP\n\napp = NextMCP(\"my-server\")\n\n@app.prompt()\ndef vacation_planner(destination: str, budget: int) -> str:\n \"\"\"Plan a vacation itinerary.\"\"\"\n return f\"\"\"\n Plan a vacation to {destination} with a budget of ${budget}.\n\n Use these tools:\n - flight_search: Find flights\n - hotel_search: Find accommodations\n\n Check these resources:\n - resource://user/preferences\n - resource://calendar/availability\n \"\"\"\n```\n\n#### Prompts with Argument Completion\n\n```python\nfrom nextmcp import argument\n\n@app.prompt(description=\"Research a topic\", tags=[\"research\"])\n@argument(\"topic\", description=\"What to research\", suggestions=[\"Python\", \"MCP\", \"FastMCP\"])\n@argument(\"depth\", suggestions=[\"basic\", \"detailed\", \"comprehensive\"])\ndef research_prompt(topic: str, depth: str = \"basic\") -> str:\n \"\"\"Generate a research prompt with the specified depth.\"\"\"\n return f\"Research {topic} at {depth} level...\"\n\n# Dynamic completion\n@app.prompt_completion(\"research_prompt\", \"topic\")\nasync def complete_topics(partial: str) -> list[str]:\n \"\"\"Provide dynamic topic suggestions.\"\"\"\n topics = await fetch_available_topics()\n return [t for t in topics if partial.lower() in t.lower()]\n```\n\n#### Async Prompts\n\n```python\n@app.prompt(tags=[\"analysis\"])\nasync def analyze_prompt(data_source: str) -> str:\n \"\"\"Generate analysis prompt with real-time data.\"\"\"\n data = await fetch_data(data_source)\n return f\"Analyze this data: {data}\"\n```\n\n**When to use prompts:**\n- Guide complex multi-step workflows\n- Provide templates for common tasks\n- Structure AI interactions\n- Reference available tools and resources\n\nSee `examples/knowledge_base/` for a complete example using prompts.\n\n### Resources\n\nResources provide read-only access to contextual data through unique URIs. They're application-driven and give the AI access to information without triggering actions.\n\n#### Direct Resources\n\n```python\nfrom nextmcp import NextMCP\n\napp = NextMCP(\"my-server\")\n\n@app.resource(\"file:///logs/app.log\", description=\"Application logs\")\ndef app_logs() -> str:\n \"\"\"Provide access to application logs.\"\"\"\n with open(\"/var/logs/app.log\") as f:\n return f.read()\n\n@app.resource(\"config://app/settings\", mime_type=\"application/json\")\ndef app_settings() -> dict:\n \"\"\"Provide application configuration.\"\"\"\n return {\n \"theme\": \"dark\",\n \"language\": \"en\",\n \"max_results\": 100\n }\n```\n\n#### Resource Templates\n\nTemplates allow parameterized access to dynamic resources:\n\n```python\n@app.resource_template(\"weather://forecast/{city}/{date}\")\nasync def weather_forecast(city: str, date: str) -> dict:\n \"\"\"Get weather forecast for a specific city and date.\"\"\"\n return await fetch_weather(city, date)\n\n@app.resource_template(\"file:///docs/{category}/{filename}\")\ndef documentation(category: str, filename: str) -> str:\n \"\"\"Access documentation files.\"\"\"\n return Path(f\"/docs/{category}/{filename}\").read_text()\n\n# Template parameter completion\n@app.template_completion(\"weather_forecast\", \"city\")\ndef complete_cities(partial: str) -> list[str]:\n \"\"\"Suggest city names.\"\"\"\n return [\"London\", \"Paris\", \"Tokyo\", \"New York\"]\n```\n\n#### Subscribable Resources\n\nResources can notify subscribers when they change:\n\n```python\n@app.resource(\n \"config://live/settings\",\n subscribable=True,\n max_subscribers=50\n)\nasync def live_settings() -> dict:\n \"\"\"Provide live configuration that can change.\"\"\"\n return await load_live_config()\n\n# Notify subscribers when config changes\napp.notify_resource_changed(\"config://live/settings\")\n\n# Manage subscriptions\napp.subscribe_to_resource(\"config://live/settings\", \"subscriber_id\")\napp.unsubscribe_from_resource(\"config://live/settings\", \"subscriber_id\")\n```\n\n#### Async Resources\n\n```python\n@app.resource(\"db://users/recent\")\nasync def recent_users() -> list[dict]:\n \"\"\"Get recently active users from database.\"\"\"\n return await db.query(\"SELECT * FROM users ORDER BY last_active DESC LIMIT 10\")\n```\n\n**When to use resources:**\n- Provide read-only data access\n- Expose configuration and settings\n- Share application state\n- Offer real-time data feeds (with subscriptions)\n\n**Resource URIs can use any scheme:**\n- `file://` - File system access\n- `config://` - Configuration data\n- `db://` - Database queries\n- `api://` - External API data\n- Custom schemes for your use case\n\nSee `examples/knowledge_base/` for a complete example using resources and templates.\n\n### Configuration\n\nNextMCP supports multiple configuration sources with automatic merging:\n\n```python\nfrom nextmcp import load_config\n\n# Load from config.yaml and .env\nconfig = load_config(config_file=\"config.yaml\")\n\n# Access configuration\nhost = config.get_host()\nport = config.get_port()\ndebug = config.is_debug()\n\n# Custom config values\napi_key = config.get(\"api_key\", default=\"default-key\")\n```\n\n**config.yaml**:\n```yaml\nhost: \"0.0.0.0\"\nport: 8080\nlog_level: \"DEBUG\"\napi_key: \"my-secret-key\"\n```\n\n**.env**:\n```\nMCP_HOST=0.0.0.0\nMCP_PORT=8080\nAPI_KEY=my-secret-key\n```\n\n### WebSocket Transport\n\nNextMCP supports WebSocket transport for real-time, bidirectional communication - perfect for chat applications, live updates, and interactive tools.\n\n#### Server Setup\n\n```python\nfrom nextmcp import NextMCP\nfrom nextmcp.transport import WebSocketTransport\n\napp = NextMCP(\"websocket-server\")\n\n@app.tool()\nasync def send_message(username: str, message: str) -> dict:\n return {\n \"status\": \"sent\",\n \"username\": username,\n \"message\": message\n }\n\n# Create WebSocket transport\ntransport = WebSocketTransport(app)\n\n# Run on ws://localhost:8765\ntransport.run(host=\"0.0.0.0\", port=8765)\n```\n\n#### Client Usage\n\n```python\nfrom nextmcp.transport import WebSocketClient\n\nasync def main():\n async with WebSocketClient(\"ws://localhost:8765\") as client:\n # List available tools\n tools = await client.list_tools()\n print(f\"Available tools: {tools}\")\n\n # Invoke a tool\n result = await client.invoke_tool(\n \"send_message\",\n {\"username\": \"Alice\", \"message\": \"Hello!\"}\n )\n print(f\"Result: {result}\")\n```\n\n#### WebSocket Features\n\n- **Real-time Communication**: Persistent connections with low latency\n- **Bidirectional**: Server can push updates to clients\n- **JSON-RPC Protocol**: Clean message format for tool invocation\n- **Multiple Clients**: Handle multiple concurrent connections\n- **Async Native**: Built on Python's async/await for high performance\n\n#### When to Use WebSocket vs HTTP\n\n| Feature | HTTP (FastMCP) | WebSocket |\n|---------|----------------|-----------|\n| Connection type | One per request | Persistent |\n| Latency | Higher overhead | Lower latency |\n| Bidirectional | No | Yes |\n| Use case | Traditional APIs | Real-time apps |\n| Best for | Request/response | Chat, notifications, live data |\n\nSee `examples/websocket_chat/` for a complete WebSocket application.\n\n## Plugin System\n\nNextMCP features a powerful plugin system that allows you to extend functionality through modular, reusable components.\n\n### What are Plugins?\n\nPlugins are self-contained modules that can:\n- Register new tools with your application\n- Add middleware for cross-cutting concerns\n- Extend core functionality\n- Be easily shared and reused across projects\n\n### Creating a Plugin\n\n```python\nfrom nextmcp import Plugin\n\nclass MathPlugin(Plugin):\n name = \"math-plugin\"\n version = \"1.0.0\"\n description = \"Mathematical operations\"\n author = \"Your Name\"\n\n def on_load(self, app):\n @app.tool()\n def add(a: float, b: float) -> float:\n \"\"\"Add two numbers\"\"\"\n return a + b\n\n @app.tool()\n def multiply(a: float, b: float) -> float:\n \"\"\"Multiply two numbers\"\"\"\n return a * b\n```\n\n### Using Plugins\n\n#### Method 1: Auto-discovery\n\n```python\nfrom nextmcp import NextMCP\n\napp = NextMCP(\"my-app\")\n\n# Discover all plugins in a directory\napp.discover_plugins(\"./plugins\")\n\n# Load all discovered plugins\napp.load_plugins()\n```\n\n#### Method 2: Direct Loading\n\n```python\nfrom nextmcp import NextMCP\nfrom my_plugins import MathPlugin\n\napp = NextMCP(\"my-app\")\n\n# Load a specific plugin\napp.use_plugin(MathPlugin)\n```\n\n### Plugin Lifecycle\n\nPlugins have three lifecycle hooks:\n\n1. **`on_init()`** - Called during plugin initialization\n2. **`on_load(app)`** - Called when plugin is loaded (register tools here)\n3. **on_unload()** - Called when plugin is unloaded (cleanup)\n\n```python\nclass LifecyclePlugin(Plugin):\n name = \"lifecycle-example\"\n version = \"1.0.0\"\n\n def on_init(self):\n # Early initialization\n self.config = {}\n\n def on_load(self, app):\n # Register tools and middleware\n @app.tool()\n def my_tool():\n return \"result\"\n\n def on_unload(self):\n # Cleanup resources\n self.config.clear()\n```\n\n### Plugin with Middleware\n\n```python\nclass TimingPlugin(Plugin):\n name = \"timing\"\n version = \"1.0.0\"\n\n def on_load(self, app):\n import time\n\n def timing_middleware(fn):\n def wrapper(*args, **kwargs):\n start = time.time()\n result = fn(*args, **kwargs)\n elapsed = (time.time() - start) * 1000\n print(f\"\u23f1\ufe0f {fn.__name__} took {elapsed:.2f}ms\")\n return result\n return wrapper\n\n app.add_middleware(timing_middleware)\n```\n\n### Plugin Dependencies\n\nPlugins can declare dependencies on other plugins:\n\n```python\nclass DependentPlugin(Plugin):\n name = \"advanced-math\"\n version = \"1.0.0\"\n dependencies = [\"math-plugin\"] # Loads math-plugin first\n\n def on_load(self, app):\n @app.tool()\n def factorial(n: int) -> int:\n # Can use tools from math-plugin\n return 1 if n <= 1 else n * factorial(n - 1)\n```\n\n### Managing Plugins\n\n```python\n# List all loaded plugins\nfor plugin in app.plugins.list_plugins():\n print(f\"{plugin['name']} v{plugin['version']} - {plugin['loaded']}\")\n\n# Get a specific plugin\nplugin = app.plugins.get_plugin(\"math-plugin\")\n\n# Unload a plugin\napp.plugins.unload_plugin(\"math-plugin\")\n\n# Check if plugin is loaded\nif \"math-plugin\" in app.plugins:\n print(\"Math plugin is available\")\n```\n\n### Plugin Best Practices\n\n1. **Use descriptive names** - Make plugin names clear and unique\n2. **Version semantically** - Follow semver (major.minor.patch)\n3. **Document thoroughly** - Add descriptions and docstrings\n4. **Handle errors gracefully** - Catch exceptions in lifecycle hooks\n5. **Declare dependencies** - List required plugins explicitly\n6. **Implement cleanup** - Use `on_unload()` to release resources\n\nSee `examples/plugin_example/` for a complete plugin demonstration with multiple plugin types.\n\n## Metrics & Monitoring\n\nNextMCP includes a built-in metrics system for monitoring your MCP applications in production.\n\n### Quick Start\n\n```python\nfrom nextmcp import NextMCP\n\napp = NextMCP(\"my-app\")\napp.enable_metrics() # That's it! Automatic metrics collection\n\n@app.tool()\ndef my_tool():\n return \"result\"\n```\n\n### Automatic Metrics\n\nWhen metrics are enabled, NextMCP automatically tracks:\n\n- **`tool_invocations_total`** - Total number of tool invocations\n- **`tool_duration_seconds`** - Histogram of tool execution times\n- **`tool_completed_total`** - Completed invocations by status (success/error)\n- **`tool_errors_total`** - Errors by error type\n- **`tool_active_invocations`** - Currently executing tools\n\nAll metrics include labels for the tool name and any global labels you configure.\n\n### Custom Metrics\n\nAdd your own metrics for business logic:\n\n```python\n@app.tool()\ndef process_order(order_id: int):\n # Custom counter\n app.metrics.inc_counter(\"orders_processed\")\n\n # Custom gauge\n app.metrics.set_gauge(\"current_queue_size\", get_queue_size())\n\n # Custom histogram with timer\n with app.metrics.time_histogram(\"processing_duration\"):\n result = process(order_id)\n\n return result\n```\n\n### Metric Types\n\n#### Counter\nMonotonically increasing value. Use for: counts, totals.\n\n```python\ncounter = app.metrics.counter(\"requests_total\")\ncounter.inc() # Increment by 1\ncounter.inc(5) # Increment by 5\n```\n\n#### Gauge\nValue that can go up or down. Use for: current values, temperatures, queue sizes.\n\n```python\ngauge = app.metrics.gauge(\"active_connections\")\ngauge.set(10) # Set to specific value\ngauge.inc() # Increment\ngauge.dec() # Decrement\n```\n\n#### Histogram\nDistribution of values. Use for: durations, sizes.\n\n```python\nhistogram = app.metrics.histogram(\"request_duration_seconds\")\nhistogram.observe(0.25)\n\n# Or use as timer\nwith app.metrics.time_histogram(\"duration\"):\n # Code to time\n pass\n```\n\n### Exporting Metrics\n\n#### Prometheus Format\n\n```python\n# Get metrics in Prometheus format\nprometheus_data = app.get_metrics_prometheus()\nprint(prometheus_data)\n```\n\nOutput:\n```\n# HELP my-app_tool_invocations_total Total tool invocations\n# TYPE my-app_tool_invocations_total counter\nmy-app_tool_invocations_total{tool=\"my_tool\"} 42.0\n\n# HELP my-app_tool_duration_seconds Tool execution duration\n# TYPE my-app_tool_duration_seconds histogram\nmy-app_tool_duration_seconds_bucket{tool=\"my_tool\",le=\"0.005\"} 10\nmy-app_tool_duration_seconds_bucket{tool=\"my_tool\",le=\"0.01\"} 25\nmy-app_tool_duration_seconds_sum{tool=\"my_tool\"} 1.234\nmy-app_tool_duration_seconds_count{tool=\"my_tool\"} 42\n```\n\n#### JSON Format\n\n```python\n# Get metrics as JSON\njson_data = app.get_metrics_json(pretty=True)\n```\n\n### Configuration\n\n```python\napp.enable_metrics(\n collect_tool_metrics=True, # Track tool invocations\n collect_system_metrics=False, # Track CPU/memory (future)\n collect_transport_metrics=False, # Track WebSocket/HTTP (future)\n labels={\"env\": \"prod\", \"region\": \"us-west\"} # Global labels\n)\n```\n\n### Metrics with Labels\n\nLabels allow you to slice and dice your metrics:\n\n```python\ncounter = app.metrics.counter(\n \"api_requests\",\n labels={\"method\": \"GET\", \"endpoint\": \"/users\"}\n)\ncounter.inc()\n```\n\n### Integration with Monitoring Systems\n\nThe Prometheus format is compatible with:\n- Prometheus for scraping and storage\n- Grafana for visualization\n- AlertManager for alerting\n- Any Prometheus-compatible system\n\nSee `examples/metrics_example/` for a complete metrics demonstration.\n\n## CLI Commands\n\nNextMCP provides a rich CLI for common development tasks.\n\n### Initialize a new project\n\n```bash\nmcp init my-project\nmcp init my-project --template weather_bot\nmcp init my-project --path /custom/path\n```\n\n### Run a server\n\n```bash\nmcp run app.py\nmcp run app.py --host 0.0.0.0 --port 8080\nmcp run app.py --reload # Auto-reload on changes\n```\n\n### Generate documentation\n\n```bash\nmcp docs app.py\nmcp docs app.py --output docs.md\nmcp docs app.py --format json\n```\n\n### Show version\n\n```bash\nmcp version\n```\n\n## Examples\n\nCheck out the `examples/` directory for complete working examples:\n\n- **weather_bot** - A weather information server with multiple tools\n- **async_weather_bot** - Async version demonstrating concurrent operations and async middleware\n- **websocket_chat** - Real-time chat server using WebSocket transport\n- **plugin_example** - Plugin system demonstration with multiple plugin types\n- **metrics_example** - Metrics and monitoring demonstration with automatic and custom metrics\n\n## Development\n\n### Setting up for development\n\n```bash\n# Clone the repository\ngit clone https://github.com/KeshavVarad/NextMCP.git\ncd nextmcp\n\n# Install in editable mode with dev dependencies\npip install -e \".[dev]\"\n\n# Run tests\npytest\n\n# Run tests with coverage\npytest --cov=nextmcp --cov-report=html\n\n# Format code\nblack nextmcp tests\n\n# Lint code\nruff check nextmcp tests\n\n# Type check\nmypy nextmcp\n```\n\n### Running Tests\n\n```bash\n# Run all tests\npytest\n\n# Run specific test file\npytest tests/test_core.py\n\n# Run with verbose output\npytest -v\n\n# Run with coverage\npytest --cov=nextmcp\n```\n\n## Architecture\n\nNextMCP is organized into several modules:\n\n- **`core.py`** - Main `NextMCP` class and application lifecycle\n- **`tools.py`** - Tool registration, metadata, and documentation generation\n- **`middleware.py`** - Built-in middleware for common use cases\n- **`config.py`** - Configuration management (YAML, .env, environment variables)\n- **`cli.py`** - Typer-based CLI commands\n- **`logging.py`** - Centralized logging setup and utilities\n\n## Comparison with FastMCP\n\nNextMCP builds on FastMCP to provide:\n\n| Feature | FastMCP | NextMCP |\n|---------|---------|-----------|\n| Basic MCP server | \u2705 | \u2705 |\n| Tool registration | Manual | Decorator-based |\n| Async/await support | \u274c | \u2705 Full support |\n| WebSocket transport | \u274c | \u2705 Built-in |\n| Middleware | \u274c | Global + tool-specific |\n| Plugin system | \u274c | \u2705 Full-featured |\n| Metrics & monitoring | \u274c | \u2705 Built-in |\n| CLI commands | \u274c | `init`, `run`, `docs` |\n| Project scaffolding | \u274c | Templates & examples |\n| Configuration management | \u274c | YAML + .env support |\n| Built-in logging | Basic | Colored, structured |\n| Schema validation | \u274c | Pydantic integration |\n| Testing utilities | \u274c | Included |\n\n## Roadmap\n\n- [x] Async tool support\n- [x] WebSocket transport\n- [x] Plugin system\n- [x] Built-in monitoring and metrics\n- [ ] Production deployment guides\n- [ ] Docker support\n- [ ] More example projects\n- [ ] Documentation site\n\n## Future Work\n\nNextMCP is evolving to become a complete implementation of the Model Context Protocol specification. Currently, only the **Tools** primitive is fully supported. Future versions will include:\n\n### v0.2.0 - Full MCP Primitives Support\n- **Prompts**: User-driven workflow templates with argument completion\n- **Resources**: Read-only context providers with URI-based access\n- **Resource Templates**: Dynamic resources with parameter-based URIs\n- **Subscriptions**: Real-time notifications for resource changes\n\n### v0.3.0 - Convention-Based Architecture\n- **File-based Auto-Discovery**: Automatic discovery of tools, prompts, and resources from directory structure\n- **Project Manifest**: `nextmcp.config.yaml` for declarative configuration\n- **Hot Reload**: Development mode with automatic file watching\n- **Enhanced CLI**: `mcp dev`, `mcp validate`, `mcp test` commands\n\n### v0.4.0 - Production & Deployment\n- **Deployment Manifests**: Generate Docker, AWS Lambda, and serverless configs\n- **One-Command Deploy**: `mcp deploy --target=aws-lambda`\n- **Production Builds**: Optimized bundles with `mcp build`\n- **Package Distribution**: `mcp package` for Docker, PyPI, and serverless\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n1. Fork the repository\n2. Create your feature branch (`git checkout -b feature/amazing-feature`)\n3. Commit your changes (`git commit -m 'Add some amazing feature'`)\n4. Push to the branch (`git push origin feature/amazing-feature`)\n5. Open a Pull Request\n\n## License\n\nThis project is licensed under the MIT License - see the LICENSE file for details.\n\n## Acknowledgments\n\n- Built on top of [FastMCP](https://github.com/jlowin/fastmcp)\n- Inspired by [Next.js](https://nextjs.org/) developer experience\n- CLI powered by [Typer](https://typer.tiangolo.com/)\n\n## Support\n\n- GitHub Issues: [https://github.com/KeshavVarad/NextMCP/issues](https://github.com/KeshavVarad/NextMCP/issues)\n- Documentation: [Coming soon]\n\n---\n\n**Made with \u2764\ufe0f by the NextMCP community**\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Production-grade MCP server toolkit with minimal boilerplate",
"version": "0.3.0",
"project_urls": {
"Documentation": "https://github.com/KeshavVarad/NextMCP#readme",
"Homepage": "https://github.com/KeshavVarad/NextMCP",
"Issues": "https://github.com/KeshavVarad/NextMCP/issues",
"Repository": "https://github.com/KeshavVarad/NextMCP"
},
"split_keywords": [
"mcp",
" server",
" sdk",
" fastmcp",
" framework"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "858ed4c1ee389b35c83a6a0cddc8b25d4892d228ad69ef1786dea2494eb5ded9",
"md5": "48c69f3c37c27feb4befaec0cc790bde",
"sha256": "dcdd64928d7e088e7af61ed36a6b7ef5883ab00e7fd45f4b59c81185ab2bb151"
},
"downloads": -1,
"filename": "nextmcp-0.3.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "48c69f3c37c27feb4befaec0cc790bde",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 59946,
"upload_time": "2025-11-04T18:33:09",
"upload_time_iso_8601": "2025-11-04T18:33:09.350052Z",
"url": "https://files.pythonhosted.org/packages/85/8e/d4c1ee389b35c83a6a0cddc8b25d4892d228ad69ef1786dea2494eb5ded9/nextmcp-0.3.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "039193103432f3e1bed9cdbd45ff528f09b1fc9692ef6bf1be24703c13df3e68",
"md5": "8ebf817031c0008297df79ff4aafbaad",
"sha256": "8408b3b3ccb80f0dd4f7cfc293f036cb87d459c1e71dd4aefbf9313a52121f42"
},
"downloads": -1,
"filename": "nextmcp-0.3.0.tar.gz",
"has_sig": false,
"md5_digest": "8ebf817031c0008297df79ff4aafbaad",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 79736,
"upload_time": "2025-11-04T18:33:10",
"upload_time_iso_8601": "2025-11-04T18:33:10.967213Z",
"url": "https://files.pythonhosted.org/packages/03/91/93103432f3e1bed9cdbd45ff528f09b1fc9692ef6bf1be24703c13df3e68/nextmcp-0.3.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-11-04 18:33:10",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "KeshavVarad",
"github_project": "NextMCP",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [
{
"name": "fastmcp",
"specs": [
[
">=",
"0.1.0"
]
]
},
{
"name": "typer",
"specs": [
[
">=",
"0.9.0"
]
]
},
{
"name": "rich",
"specs": [
[
">=",
"13.0.0"
]
]
},
{
"name": "python-dotenv",
"specs": [
[
">=",
"1.0.0"
]
]
},
{
"name": "pyyaml",
"specs": [
[
">=",
"6.0.0"
]
]
},
{
"name": "pydantic",
"specs": [
[
">=",
"2.0.0"
]
]
},
{
"name": "websockets",
"specs": [
[
">=",
"12.0"
]
]
}
],
"lcname": "nextmcp"
}