Build a Simple MCP Server in PythonΒΆ
This notebook walks you through building a minimal MCP (Model Context Protocol) server from scratch. By the end you will have a working server that exposes two tools an AI agent can call:
word_countβ count words in a textsearch_glossaryβ look up AI/ML terms in a small glossary
What you will learn:
The structure of an MCP server
How to define tools with typed parameters
How to register tools with the MCP SDK
How to configure VS Code to use your server
Prerequisites: Python 3.10+, mcp package
1 β Install the MCP SDKΒΆ
The mcp package is the official Python SDK for building MCP servers.
# Check if mcp is available (install if needed)
try:
import mcp
print(f"MCP SDK version: {mcp.__version__}")
except ImportError:
print("MCP SDK not installed. Install with: pip install mcp")
print("For this notebook, we'll demonstrate the server code structure")
print("without requiring the mcp package to be installed.")
2 β Define Your ToolsΒΆ
An MCP tool is a Python function with:
A name (string, snake_case)
A description (what the tool does, read by the AI to decide when to use it)
Parameters with types and descriptions
A return value (string or structured data)
Letβs define two simple tools.
# ββ Tool 1: Word Count ββββββββββββββββββββββββββββββββββββββββββββ
def word_count(text: str) -> dict:
"""Count words, sentences, and characters in the given text."""
words = text.split()
sentences = text.count(".") + text.count("!") + text.count("?")
return {
"words": len(words),
"sentences": max(sentences, 1),
"characters": len(text),
"avg_word_length": round(sum(len(w) for w in words) / max(len(words), 1), 1),
}
# ββ Tool 2: Glossary Lookup βββββββββββββββββββββββββββββββββββββββ
GLOSSARY = {
"rag": "Retrieval-Augmented Generation: combining retrieval from a knowledge base with LLM generation to produce grounded answers.",
"mcp": "Model Context Protocol: an open standard for connecting AI clients to external tools and data sources.",
"embedding": "A dense vector representation of text (or other data) that captures semantic meaning in a continuous space.",
"fine-tuning": "Adapting a pre-trained model to a specific task or domain by training on a smaller, targeted dataset.",
"lora": "Low-Rank Adaptation: a parameter-efficient fine-tuning method that trains small rank-decomposition matrices instead of all weights.",
"vector database": "A database optimized for storing and querying high-dimensional vectors, used for similarity search in AI applications.",
"tokenizer": "A component that splits text into tokens (subwords, characters, or words) for processing by a language model.",
"transformer": "A neural network architecture based on self-attention, the foundation of modern LLMs like GPT and BERT.",
"hyde": "Hypothetical Document Embeddings: generating a hypothetical answer to a query, then using its embedding for retrieval.",
"crag": "Corrective RAG: a pattern that grades retrieval quality and retries or abstains when evidence is weak.",
}
def search_glossary(term: str) -> dict:
"""Look up an AI/ML term in the glossary. Returns the definition if found."""
key = term.lower().strip()
if key in GLOSSARY:
return {"term": key, "definition": GLOSSARY[key], "found": True}
# Fuzzy match: check if the search term appears in any key
matches = [k for k in GLOSSARY if key in k or k in key]
if matches:
return {"term": matches[0], "definition": GLOSSARY[matches[0]], "found": True, "note": "fuzzy match"}
return {"term": key, "found": False, "available_terms": sorted(GLOSSARY.keys())}
# Quick test
print("=== word_count ===")
print(word_count("The quick brown fox jumps over the lazy dog."))
print("\n=== search_glossary ===")
print(search_glossary("RAG"))
print(search_glossary("attention"))
3 β The MCP Server ScriptΒΆ
Below is the complete server script that registers both tools with the MCP
framework. In production you would save this as a .py file and point your
MCP config at it.
We display it here as a string so the notebook runs without requiring the
mcp package. You can copy this to a file and run it directly.
SERVER_CODE = '''
#!/usr/bin/env python3
"""Minimal MCP server exposing word_count and search_glossary tools."""
from mcp.server.fastmcp import FastMCP
# Create server instance
mcp = FastMCP("glossary-server")
# ββ Tool 1: Word Count ββββββββββββββββββββββββββββββββββββββββββββ
@mcp.tool()
def word_count(text: str) -> str:
"""Count words, sentences, and characters in the given text."""
words = text.split()
sentences = text.count(".") + text.count("!") + text.count("?")
w = len(words)
s = max(sentences, 1)
c = len(text)
avg = round(sum(len(w_) for w_ in words) / max(w, 1), 1)
return f"Words: {w}, Sentences: {s}, Characters: {c}, Avg word length: {avg}"
# ββ Tool 2: Glossary Lookup βββββββββββββββββββββββββββββββββββββββ
GLOSSARY = {
"rag": "Retrieval-Augmented Generation: combining retrieval from a knowledge base with LLM generation.",
"mcp": "Model Context Protocol: an open standard for connecting AI clients to external tools.",
"embedding": "A dense vector representation of text that captures semantic meaning.",
"fine-tuning": "Adapting a pre-trained model to a specific task by training on targeted data.",
"lora": "Low-Rank Adaptation: parameter-efficient fine-tuning via rank-decomposition matrices.",
"vector database": "A database optimized for storing and querying high-dimensional vectors.",
"tokenizer": "Splits text into tokens (subwords, characters, or words) for a language model.",
"transformer": "Neural network architecture based on self-attention, foundation of modern LLMs.",
"hyde": "Hypothetical Document Embeddings: generate a hypothetical answer, embed it for retrieval.",
"crag": "Corrective RAG: grade retrieval quality and retry or abstain when evidence is weak.",
}
@mcp.tool()
def search_glossary(term: str) -> str:
"""Look up an AI/ML term in the glossary. Returns the definition if found."""
key = term.lower().strip()
if key in GLOSSARY:
return f"{key}: {GLOSSARY[key]}"
matches = [k for k in GLOSSARY if key in k or k in key]
if matches:
return f"{matches[0]} (fuzzy match): {GLOSSARY[matches[0]]}"
return f"Term \'{key}\' not found. Available: {\', \'.join(sorted(GLOSSARY.keys()))}"
if __name__ == "__main__":
mcp.run(transport="stdio")
'''
print(SERVER_CODE)
4 β Save the Server ScriptΒΆ
Run the cell below to write the server to a file you can actually use.
from pathlib import Path
server_path = Path("glossary_mcp_server.py")
server_path.write_text(SERVER_CODE.strip() + "\n")
print(f"Server script saved to: {server_path.resolve()}")
print(f"\nTo test manually:")
print(f" python {server_path}")
print(f"\nTo use in VS Code, add to .vscode/mcp.json:")
print(f''' {{"servers": {{"glossary": {{"command": "python", "args": ["{server_path.resolve()}"]}}}}}}''')
5 β Configure Your IDEΒΆ
VS Code (.vscode/mcp.json)ΒΆ
{
"servers": {
"glossary": {
"command": "python",
"args": ["31-ai-powered-dev-tools/glossary_mcp_server.py"]
}
}
}
Project Root (.mcp.json)ΒΆ
{
"mcpServers": {
"glossary": {
"command": "python",
"args": ["31-ai-powered-dev-tools/glossary_mcp_server.py"]
}
}
}
Once configured, open Copilot Agent Mode and try:
Look up what RAG means in the glossary, then count the words in its definition.
The agent should call search_glossary("RAG"), get the definition, then call
word_count() on the result.
6 β Extending the ServerΒΆ
Add a new toolΒΆ
To add a tool that lists all glossary terms:
@mcp.tool()
def list_glossary_terms() -> str:
"""List all available terms in the AI/ML glossary."""
return ", ".join(sorted(GLOSSARY.keys()))
Add a resource (read-only data)ΒΆ
Resources let the AI read data without calling a tool:
@mcp.resource("glossary://terms")
def glossary_resource() -> str:
"""The complete AI/ML glossary."""
lines = [f"- **{k}**: {v}" for k, v in sorted(GLOSSARY.items())]
return "\n".join(lines)
Add a prompt templateΒΆ
Prompts are pre-written templates the AI can use:
@mcp.prompt()
def explain_term(term: str) -> str:
"""Generate a prompt to explain an AI/ML term to a beginner."""
return f"Explain the AI/ML concept '{term}' in simple terms. Use an analogy."
Production patternsΒΆ
For real-world servers, consider:
Database access: Replace the dict with a SQLite or PostgreSQL query
API wrapper: Wrap an internal REST API as MCP tools
W&B integration: Expose experiment metrics as tools (
get_run_metrics,compare_runs)Vector store: Expose your RAG pipeline (
search_docs,get_chunk)Error handling: Catch exceptions and return user-friendly error messages
7 β Key TakeawaysΒΆ
Concept |
Details |
|---|---|
MCP server |
A Python (or Node.js) process that exposes tools, resources, and prompts |
Tool |
A function the AI agent can call with typed parameters |
Resource |
Read-only data the AI can access |
Prompt |
A pre-written template the AI can use |
Transport |
stdio (local) or HTTP/SSE (remote) |
Configuration |
|
The key insight: MCP turns domain-specific functions into tools any AI agent can use.
If you can write a Python function, you can build an MCP server.
Next stepsΒΆ
Build an MCP server that wraps your projectβs test suite
Connect a database MCP server and use agent mode to generate queries
Review the MCP specification for the full protocol reference
Browse community servers at github.com/modelcontextprotocol/servers