Turn any Python codebase into a production-grade MCP server with zero friction.
Project description
Smarter-MCP 🚀
The highest-level Python framework for building, generating, and running MCP servers.
Smarter-MCP sits on top of FastMCP and acts as the orchestration layer that handles everything a developer shouldn't have to think about: AST-based signature extraction, type coercion, class-instance lifecycle management, namespace routing, multimodal content interception, and structured error handling.
📖 Philosophy: Primitives vs. Abstractions
FastMCP gives you primitives. Smarter-MCP gives you abstractions.
- If you own the code: Write clean, decorated Python. Smarter-MCP provides
@tool,@toolkit, and@resourcestandalone decorators that plug into a powerful runtime featuring session-scoped instances, automatic type coercion, and multimodal support. - If you don't own the code: Point Smarter-MCP at it. Pass an imported module object, a directory path, or a YAML manifest. The dual-pass extraction engine (AST + inspect) handles the rest—no source modifications required.
Both paths converge into the same runtime engine. Every tool gets the same production-grade treatment regardless of how it was registered.
1. Decorators (For Writing New Tools)
Decorators provide a clean, native Python API for authoring MCP servers from scratch.
- Simple function tools & resources:
from smarter_mcp import SmarterMCP
app = SmarterMCP("my-server")
from smarter_mcp import tool, resource
@tool("Greet a user by name")
def greet(name: str) -> str:
return f"Hello, {name}!"
@resource("config://settings")
def get_settings() -> dict:
return {"debug": True, "version": "1.0"}
- Class-based toolkits (For DB clients, stateful APIs, ML pipelines):
from smarter_mcp import tool, toolkit
@toolkit(lifecycle="session")
class DatabaseClient:
def __init__(self, host: str = "localhost", port: int = 5432):
self.conn = connect(host, port)
@tool(name="run_query")
def query(self, sql: str) -> list[dict]:
"""Execute a SQL query and return results."""
return self.conn.execute(sql).fetchall()
The @toolkit() decorator automatically manages session instantiations, self binding per session, constructor argument injections, and cleanup on session termination.
2. discover_module() (Expose Any Python Module)
Import any standard library module, third-party pip package, or local file and hand it to Smarter-MCP. It automatically extracts methods, builds schemas, and serves them.
import random
import json
from smarter_mcp import SmarterMCP
app = SmarterMCP("multi-tools")
# Instantly expose safe subsets of libraries
app.discover_module(random, include=["choices", "randint", "sample"])
app.discover_module(json, include=["dumps", "loads"])
app.run()
What this unlocks: Any Python package ever published on PyPI can become an MCP server with a single line of code.
3. discover() (Scan an Entire Source Directory)
Scan local codebases with zero source modifications. It automatically detects and exposes:
- Module-level functions, class methods, static methods, and instance methods.
@propertydescriptors—mapped to MCP resources, not tools (e.g.,resource://{module}/{Class}/{property}).- Automated class instantiation using config-defined overrides, singleton factories (
get_<Class>()), or default fallbacks.
app = SmarterMCP("my-codebase-server")
app.discover("./src/mylib", exclude=["test_*"])
app.run()
4. Zero-Code CLI & YAML-driven Manifests
Spin up, validate, and test servers directly from the command line without writing Python wrapper code:
# Auto-discover a local directory
smarter-mcp serve ./mylib
# Start a decorator-based server script
smarter-mcp serve ./app.py
# Run with a manifest YAML config
smarter-mcp serve --manifest smarter-mcp.yaml
Example smarter-mcp.yaml manifest:
name: chemistry-tools
version: 0.1.0
server:
host: 0.0.0.0
port: 8000
transport: sse
sources:
- path: ./src/my_local_utils
- module: random
include: [choices, randint]
namespace: random_tools
expose:
private: false
inherited: false
unannotated: warn
variadic: skip
🛠️ The Production-Grade Runtime Pipeline
Every tool call passes through a rigorous runtime pipeline before executing:
- Schema Validation: Parameters are validated against the JSON schema before functions are called. Clear validation errors are returned to the agent, not raw Python tracebacks.
- Type Coercion: Common agent formatting errors (e.g., sending
"42"instead of42, or a stringified JSON instead of adict) are resolved automatically. - Instance Resolution: Resolves and binds classes depending on
session,singleton, orper-callconfigurations. - Context Injection: Automatically injects a FastMCP
Contextparameter if the function accepts it. - Multimodal Interception: Automatically decodes incoming
ImageContentparameters into PillowPIL.Image.Imageor NumPynp.ndarraystructures (handling base64 data, URLs, or local files). Returns images back to the agent as wrappedImageContent. - Structured Error Handling: Catches exceptions and returns them as structured MCP error objects to prevent agent confusion.
🔄 Gap Comparison: FastMCP vs. Smarter-MCP
| Capability | FastMCP | Smarter-MCP |
|---|---|---|
| Decorator API | @mcp.tool() (manual wiring) |
@tool with auto coercion, schema, multimodal |
| Class Toolkits | Manual add_tool() per method |
@toolkit with session-scoped instances |
| Expose Existing Modules | Not supported | app.discover_module(random) |
| Auto-Discover Codebase | Not supported | app.discover("./mylib") |
| CLI / YAML config | Not supported | smarter-mcp serve, full manifest |
| Instance Lifecycle | Manual | session / singleton / per-call, auto-managed |
| Type Coercion | None | "42" → 42 automatically |
| Namespace Routing | Manual mount() |
Auto-derived from module paths |
| Multimodal | Manual encoding | PIL.Image, ndarray, bytes auto-detected |
| Tool Name Collisions | Silent overwrite | Auto-namespaced (ClassName_method) |
| Property → Resource | Not supported | Automatic mapping |
| Docstring Parsing | Raw docstring only | Google/NumPy/Sphinx parsed per-parameter |
| Type Inference | None | AST-based inference from defaults + returns |
| Error Handling | Raw Python tracebacks | Structured MCP error objects (coercion vs. execution) |
| HTTP Introspection | Not supported | GET /health + GET /mcp/{ns}/schema (with ?compact=true) |
| Authentication | Manual | X-API-Key middleware + FastMCP Bearer, config-driven |
| Rate Limiting | Manual | Sliding window, per-session + global |
| LLM Descriptions | Not supported | Auto-generate missing docs via OpenAI SDK (OpenAI/OpenRouter/Anthropic), cached |
| Package Export | Not supported | smarter-mcp export → standalone package |
*args/**kwargs |
Silent runtime failure | Detected, skipped with warning |
| Schema Validation | None | Every call validated against JSON schema |
🧪 How to Setup and Test the Codebase Locally
Follow these steps to run, verify, and test Smarter-MCP locally in a clean Python virtual environment.
1. Initialize the Virtual Environment
Run these commands in the project root:
# Create a virtual environment
python3 -m venv .venv
# Activate the virtual environment
source .venv/bin/activate
# Ensure pip is up to date
pip install --upgrade pip
2. Install Smarter-MCP with All Dependencies
Install Smarter-MCP in editable mode with development and multimodal extras:
pip install -e ".[all]"
3. Run the Test Suite
We use pytest for unit testing. Execute all tests (CLI command runner, multimodal parser, AST extraction, and testing framework):
pytest
To run individual test files:
# Verify CLI command configurations
pytest tests/test_cli.py
# Verify multimodal image/blob interception
pytest tests/test_multimodal.py
# Verify tool validation & testing runner
pytest tests/test_testing_framework.py
4. Verify the CLI Manually
You can test the command line options inside your activated virtual environment:
# Check CLI help outputs
smarter-mcp --help
# Create a sample python file with tools
cat << 'EOF' > test_server.py
from smarter_mcp import SmarterMCP, tool
from PIL import Image
app = SmarterMCP("test-server")
@tool(tests=[{"params": {"name": "Bob"}, "expect": "Hello, Bob!"}])
def greet(name: str) -> str:
return f"Hello, {name}!"
@tool()
def process_img(img: Image.Image) -> Image.Image:
return img.rotate(90)
EOF
# Dry-run validation of the server
smarter-mcp validate test_server.py
# Run the predefined tests inside the file
smarter-mcp test test_server.py
# Serve the server locally (press Ctrl+C to stop)
smarter-mcp serve test_server.py --port 8000
Clean up the test server script when done:
rm test_server.py
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file smarter_mcp-0.1.0.tar.gz.
File metadata
- Download URL: smarter_mcp-0.1.0.tar.gz
- Upload date:
- Size: 211.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3502fc5dc100144707738c7138a04d57d40cc11430c0475f4bb185ff08ea80cb
|
|
| MD5 |
70cc54c27f2b8690991bbfccad96d628
|
|
| BLAKE2b-256 |
92e31829af948440ffd2c9552783e6c42c2be0a7849114deb44329231302e212
|
File details
Details for the file smarter_mcp-0.1.0-py3-none-any.whl.
File metadata
- Download URL: smarter_mcp-0.1.0-py3-none-any.whl
- Upload date:
- Size: 74.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c47d9adcee7a232ad6bb16696cd9203690f91ea6bb8af9075fd1301a7624974e
|
|
| MD5 |
c22de0360aa08a5d70fd517adcb08f67
|
|
| BLAKE2b-256 |
1996c14daf528611733abb2a94a1f838520120f07e19dcef134382594dd62cbf
|