Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
The smallest useful Python MCP server is a typed function decorated with @mcp.tool(). Install the official SDK with its CLI extra, save a short server file, and run uv run mcp dev server.py to open MCP Inspector. The example below also adds a URI-template resource and shows automated in-memory testing, so you can understand what runs locally before choosing a production transport.
What you need
- Python 3.10 or newer. The official Python SDK documentation currently identifies the v2 line as stable.
- A virtual environment or project managed by
uvorpip. - The MCP CLI extra, which supplies the
mcpcommand used by the Inspector workflow.
Install the package in your project:
uv add "mcp[cli]"
With pip, use:
pip install "mcp[cli]"
These commands and the version guidance are documented at the official Python SDK documentation.
A complete minimal server
Create a file named server.py:
from mcp.server import MCPServer
mcp = MCPServer("Demo")
@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers."""
return a + b
@mcp.resource("greeting://{name}")
def greeting(name: str) -> str:
"""Greet someone by name."""
return f"Hello, {name}!"
This file creates an MCP server named Demo. The add function is exposed as a tool. Its Python type hints let the SDK derive the input schema, so you do not write JSON Schema or protocol parsing for this starter example. The greeting function is exposed at URI template greeting://{name}; a client can read greeting://World and receive Hello, World!.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsThe decorators are registered when Python imports the module. Keep the function docstrings: clients commonly display them as descriptions, and they tell a model what an operation does.
#1 Best Overall
Run it with MCP Inspector
- Open a terminal in the directory containing
server.py. - Start the development command:
uv run mcp dev server.pyIf you installed with pip and are not using uv, run the equivalent
mcp dev server.pycommand from the environment containing the package. - The command starts the server and opens MCP Inspector, an interactive browser UI.
- In Inspector, find the
addtool, enter1foraand2forb, then invoke it. The result is3. - Use the resource view to read
greeting://World. The returned text isHello, World!.
The SDK getting-started guide treats its documentation examples as complete working files and uses the same Inspector workflow for local exploration. Inspector is useful for checking names, schemas and returned values without first building a host application.
Tools, resources and prompts are different
Choose the primitive according to who initiates the interaction:
| Primitive | Purpose | Caller | Example |
|---|---|---|---|
| Tool | An action that can change state or perform computation | The model chooses and calls it | add(a, b) |
| Resource | Read-only data addressed by a URI | The application chooses to read it | greeting://World |
| Prompt | A reusable message template | A person invokes it, often from a menu or slash command | A named writing or analysis template |
Do not describe a prompt as a tool or resource: the SDK documents separate invocation roles for all three in its server reference. A first server can contain only tools; the resource above demonstrates URI-based read-only data without adding a database or network dependency.
Automated testing without a subprocess
Inspector is interactive. For a repeatable test, the SDK documents an in-memory client that connects directly to the server object. It does not open a port, start a subprocess or select a network transport.
Rank #2
Add a test file such as test_server.py:
import pytest
from mcp import Client
from server import mcp
@pytest.mark.asyncio
async def test_add():
async with Client(mcp) as client:
result = await client.call_tool("add", {"a": 1, "b": 2})
assert result.structured_content == {"result": 3}
Run it with your usual pytest command after installing pytest and an asyncio pytest plugin in the project. The important pattern is async with Client(mcp) as client, followed by client.call_tool. Keep this test separate from transport tests: it validates registration, argument handling and the returned structured value, while Inspector validates the local interactive experience.
Extending the example safely
Add validation at the function boundary
Type hints describe the expected shape, but business rules still belong in your function. Check ranges, required identifiers and permissions before performing side effects. Return predictable values and raise clear, intentional errors rather than exposing tracebacks or secrets.
Keep imports and startup cheap
Inspector imports the module to discover its primitives. Avoid doing expensive work, opening database connections or making API calls at import time. Initialize external clients inside functions or in an explicit startup path.
Expose only the capability a client needs
A tool can represent an action such as creating a ticket; a resource is better for reading a document or status snapshot. If a user needs a guided, reusable instruction, define a prompt instead of disguising it as a tool.
Move to a documented transport for deployment
The example is deliberately local. Production deployment requires choosing a transport, configuring authorization and mounting or hosting the server in your application. The official SDK documentation links to transport, authorization, deployment, FastAPI and Starlette integration guidance; do not treat the Inspector command as a production service.
Common errors and fixes
mcp: command not found
The CLI extra is missing or the active shell is outside the environment where it was installed. Install mcp[cli] again, activate the virtual environment, or run the command through uv: uv run mcp dev server.py.
Python version error during installation
Use Python 3.10 or newer, which is the requirement listed by the current SDK documentation. Check python --version and recreate the environment with a supported interpreter.
Inspector cannot start the file
Run the command from the directory containing server.py, verify the filename and fix syntax or import errors shown in the terminal. Keep application startup code out of module scope while diagnosing imports.
A tool is missing from Inspector
Confirm the function has the @mcp.tool() decorator, that the module imports successfully and that you restarted the development command after editing. The decorator must be applied to the function registered on the same MCPServer instance.
Arguments are rejected
Send the exact parameter names and JSON-compatible values defined by the function signature. For the example, the call must contain integer fields a and b; do not send a single positional string.
The in-memory test cannot import server
Place test_server.py beside server.py, run pytest from the project root and ensure the environment includes the project dependencies. Importing the module should register the server without starting a separate process.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Performance, reliability and security notes
- The arithmetic tool is local and deterministic; real tools inherit the latency and failure modes of the APIs, files or databases they call.
- Set timeouts on outbound requests, validate untrusted arguments and avoid returning credentials or sensitive raw responses.
- Use structured, bounded results. Large payloads make clients slower and can exceed a host’s context limits.
- Log failures without logging tokens, cookies or personal data. Add authentication and authorization before exposing a server outside a trusted development machine.
- Use Inspector and in-memory tests together: one catches interactive registration mistakes, the other gives a repeatable check for changes.
Or skip the browser setup
If your actual goal is to capture a web page for documentation, testing or an AI workflow rather than build a browser automation stack, ScreenshotNeo provides a website screenshot API and MCP server. A single request returns PNG, JPEG, WebP or PDF. Before capture it accepts cookie or consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing result. Its MCP server includes take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients.
Using the API is one GET request:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python:
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
See the complete parameter list and MCP setup in the ScreenshotNeo documentation. Every plan includes its features; the Free plan includes 1,000 shots per month without a card, and paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
Best Value
Where to go next
Once this server works locally, read the SDK sections on connecting to a real host, transports, authorization, testing and deployment. Add one capability at a time, keep an automated test for each tool, and decide explicitly whether new data belongs in a resource or whether an operation should be a tool.
Frequently Asked Questions
Can I use this example with Python 3.9?
No. The current official Python SDK documentation lists Python 3.10 or newer as its requirement.
Free tools Windows power users keep installed
One-click scans. No signup required.
Does the Inspector command deploy my server?
No. uv run mcp dev server.py is a local development and inspection workflow. Production hosting requires a chosen transport plus deployment and authorization configuration.
Do I need to write JSON Schema for the add tool?
Not for this example. The SDK derives the input schema from the function’s Python type hints.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

