Build Your First MCP Server Step by Step
Follow this step-by-step guide to build and deploy your first Model Context Protocol server, covering setup, handlers, and tool registration.
In this article 13
- Key Takeaways
- Introduction to Model Context Protocol (MCP) in 2026
- What is MCP (Model Context Protocol) and Why Build an MCP Server?
- Prerequisites for Your MCP Server Tutorial
- Setting Up Your Development Environment for MCP Server Tutorial
- Designing Your First MCP Service
- Coding Your First MCP Server from Scratch
- Running and Testing Your MCP Server
- Replacing the Mock with a Real LLM
- Deploying Your MCP Server
- Conclusion
- FAQ
- Related Articles
Key Takeaways
- The Model Context Protocol (MCP) is becoming the standard backbone for AI applications, letting diverse models interact with contextual data.
- Building an MCP server is an essential skill for developers, given the growing demand for scalable, context-aware AI systems.
- MCP provides a standardized communication layer that offers key benefits such as contextual awareness, interoperability between various AI models, and scalability for integrating new components.
Introduction to Model Context Protocol (MCP) in 2026
The Model Context Protocol (MCP) is becoming the standard backbone for AI applications, letting diverse models interact with contextual data. Demand for scalable, context-aware AI systems keeps growing. Learning to build an MCP server is an essential skill for any developer working with AI. This guide walks through setting up, configuring, and deploying an MCP server from scratch. Here is a practical, step-by-step MCP server tutorial.
What is MCP (Model Context Protocol) and Why Build an MCP Server?
The Model Context Protocol (MCP) serves as a standardized communication layer designed to facilitate the exchange of context and model inferences between various AI components and applications. Unlike traditional API calls that often lack a unified way to manage evolving context, MCP provides a structured approach to:
- Contextual Awareness: Maintain and update dynamic context across multiple model interactions.
- Interoperability: Enable different models, regardless of their underlying frameworks, to communicate effectively.
- Scalability: Design systems that can integrate new models and handle increasing loads.
- Observability: Offer clearer insights into model decision-making processes by tracking context flow.
By choosing to build an MCP server, you are creating a central hub that intelligently routes requests, manages session context, and orchestrates complex AI workflows. This significantly simplifies the development of sophisticated AI applications, making them more modular, maintainable, and powerful.
Prerequisites for Your MCP Server Tutorial
Before we begin to build an MCP server from scratch, ensure you have the following tools installed and configured on your system:
- Python 3.9+: MCP server frameworks are typically Python-based. We recommend Python 3.10 or 3.11 for optimal compatibility in 2026.
- pip: Python’s package installer, usually bundled with Python.
- Git: For version control and potentially cloning example repositories.
- Basic understanding of RESTful APIs: While MCP adds a layer, the underlying principles of HTTP communication are relevant.
- Code Editor: VS Code, PyCharm, or your preferred IDE.
Setting Up Your Development Environment for MCP Server Tutorial
1. Create a Virtual Environment
It’s best practice to isolate your project dependencies. Open your terminal or command prompt and run:
python3 -m venv mcp_server_env
source mcp_server_env/bin/activate # On Linux/macOS
# mcp_server_env\Scripts\activate # On Windows
2. Install the MCP Server Framework
For this tutorial, we’ll use a hypothetical but representative mcp-server-framework library, which provides the necessary abstractions to easily build an MCP server. In a real-world scenario in 2026, you might choose from several emerging MCP-compliant frameworks.
pip install mcp-server-framework fastapi uvicorn
mcp-server-framework: The core library.fastapi: A modern, fast (high-performance) web framework for building APIs with Python 3.7+ based on standard Python type hints.uvicorn: An ASGI server for running FastAPI applications.
Designing Your First MCP Service
To demonstrate how to build an MCP server, let’s imagine a simple service: a ContextualSummarizer. This service will take a piece of text and a context_hint (e.g., ‘technical’, ‘casual’, ‘marketing’) and return a summary tailored to that hint. The context_hint will be part of the MCP context.
1. Define Your MCP Service Schema
An MCP server relies on clearly defined schemas for its inputs and outputs. This ensures models understand what data to expect. We’ll define these using Pydantic, which FastAPI integrates with directly.
Create a file named schemas.py:
from pydantic import BaseModel, Field
from typing import Optional
class ContextualSummaryInput(BaseModel):
text: str = Field(..., description="The text to be summarized.")
class ContextualSummaryOutput(BaseModel):
summary: str = Field(..., description="The generated summary.")
context_applied: str = Field(..., description="The context hint used for summarization.")
class MCPContext(BaseModel):
session_id: str = Field(..., description="Unique session identifier.")
user_id: Optional[str] = Field(None, description="Optional user identifier.")
context_hint: str = Field(default="general", description="Hint for summarization style (e.g., technical, casual).")
# Add more context fields as needed
Coding Your First MCP Server from Scratch
Now, let’s write the core server logic. Create main.py:
from fastapi import FastAPI, HTTPException
from mcp_server_framework.server import MCPServer
from mcp_server_framework.context import MCPContextManager
from schemas import ContextualSummaryInput, ContextualSummaryOutput, MCPContext
import time
app = FastAPI(title="Contextual Summarizer MCP Server 2026")
mcp_server = MCPServer(app=app, context_manager=MCPContextManager())
# --- Mock Model Logic (Replace with actual LLM integration) ---
def mock_summarize(text: str, context_hint: str) -> str:
# In a real application, you'd integrate with an LLM here (e.g., OpenAI, Hugging Face, custom model)
# The context_hint would guide the [prompt engineering](/en/blog/mastering-prompt-engineering-claude-beyond-gpt-centric-strategies-for-2026/) or model selection.
if "technical" in context_hint.lower():
return f"[Technical Summary]: A concise analysis of the provided data, emphasizing key operational aspects. (Text length: {len(text)})."
elif "marketing" in context_hint.lower():
return f"[Marketing Pitch]: Discover the compelling value proposition and unique selling points derived from the text. (Text length: {len(text)})."
else:
return f"[General Summary]: A brief overview of the main points in the text. (Text length: {len(text)})."
# --- MCP Endpoint Definition ---
@mcp_server.mcp_endpoint(
path="/summarize",
input_model=ContextualSummaryInput,
output_model=ContextualSummaryOutput,
description="Provides a contextual summary of input text."
)
async def contextual_summarize_service(
input_data: ContextualSummaryInput,
mcp_context: MCPContext # MCP framework injects the context
) -> ContextualSummaryOutput:
"""Process text to generate a summary based on the provided MCP context hint."""
try:
print(f"Processing request for session: {mcp_context.session_id} with hint: {mcp_context.context_hint}")
# Simulate a delay for processing
await asyncio.sleep(0.1)
summary = mock_summarize(input_data.text, mcp_context.context_hint)
return ContextualSummaryOutput(
summary=summary,
context_applied=mcp_context.context_hint
)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
# Optional: Add a simple root endpoint for health check
@app.get("/", tags=["Health Check"])
async def read_root():
return {"message": "MCP Contextual Summarizer Server is running!"}
import asyncio # Required for async operations
Explanation:
FastAPIandMCPServer: We initialize a FastAPI app and then wrap it withMCPServer, which is responsible for handling MCP-specific routing and context management.MCPContextManager: This component (provided by the framework) handles the lifecycle and storage ofMCPContextobjects for different sessions.mock_summarize: This function simulates your actual AI model integration. In a production environment of 2026, this would involve calling a large language model (LLM) API or an on-device model, potentially with sophisticated prompt engineering guided bycontext_hint.@mcp_server.mcp_endpoint: This decorator registers ourcontextual_summarize_serviceas an MCP-compliant endpoint. It automatically handles input validation (usinginput_model), output serialization (usingoutput_model), and crucially, injects theMCPContextobject into your service function. TheMCPContextis either retrieved from an existing session or initialized based on the request.
Running and Testing Your MCP Server
1. Run the Server
From your terminal, in the mcp_server_env virtual environment, run:
uvicorn main:app --reload --host 0.0.0.0 --port 8000
You should see output indicating that Uvicorn is running your FastAPI application, typically on http://0.0.0.0:8000.
2. Test with curl
Open another terminal and send some requests. First, a request without a specific context_hint in the MCP context:
curl -X POST "http://localhost:8000/summarize" \
-H "Content-Type: application/json" \
-H "X-MCP-Session-ID: session-123" \
-d '{"text": "The new quantum computing algorithm achieved unprecedented speed, reducing processing time by 99% for complex cryptographic tasks. This breakthrough promises to revolutionize data security by 2030."}'
Expected Output:
{
"summary": "[General Summary]: A brief overview of the main points in the text. (Text length: 184).",
"context_applied": "general"
}
Now try with a technical context hint passed via a custom MCP header:
curl -X POST "http://localhost:8000/summarize" \
-H "Content-Type: application/json" \
-H "X-MCP-Session-ID: session-123" \
-H "X-MCP-Context-Hint: technical" \
-d '{"text": "The new quantum computing algorithm achieved unprecedented speed, reducing processing time for complex cryptographic tasks."}'
Expected output:
{
"summary": "[Technical Summary]: A concise analysis of the provided data, emphasizing key operational aspects. (Text length: 120).",
"context_applied": "technical"
}
The FastAPI docs at http://localhost:8000/docs give you an interactive interface to explore and test all endpoints without writing curl commands.
Replacing the Mock with a Real LLM
The mock_summarize function is a placeholder. Swapping it for a real model requires changing one function, nothing else. Here is an example using the Anthropic SDK:
pip install anthropic
Replace mock_summarize in main.py:
import anthropic
_client = anthropic.Anthropic() # reads ANTHROPIC_API_KEY from environment
def real_summarize(text: str, context_hint: str) -> str:
prompt = (
f"Summarize the following text in a {context_hint} style. "
f"Be concise. Text: {text}"
)
message = _client.messages.create(
model="claude-sonnet-4-6",
max_tokens=256,
messages=[{"role": "user", "content": prompt}],
)
return message.content[0].text
Then update the endpoint to call real_summarize instead of mock_summarize. Set your API key before starting the server:
export ANTHROPIC_API_KEY=sk-ant-...
uvicorn main:app --reload --host 0.0.0.0 --port 8000
The context_hint from the MCP context flows directly into the prompt, so every summarization style is handled without branching logic in the endpoint itself.
Deploying Your MCP Server
For a home lab or small production deployment, Docker is the most portable option. Create a Dockerfile in your project root:
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Generate requirements.txt, then build and run:
pip freeze > requirements.txt
docker build -t mcp-summarizer .
docker run -d -p 8000:8000 \
-e ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY \
--name mcp-summarizer \
mcp-summarizer
On a Proxmox setup, this runs cleanly inside an LXC container or a VM. Pair it with Caddy or nginx for TLS termination, and any MCP-aware client on your network can reach the server by hostname.
If you prefer systemd over Docker, a minimal unit file works just as well:
[Unit]
Description=MCP Summarizer Server
After=network.target
[Service]
User=mcp
WorkingDirectory=/opt/mcp-summarizer
EnvironmentFile=/opt/mcp-summarizer/.env
ExecStart=/opt/mcp-summarizer/mcp_server_env/bin/uvicorn main:app --host 0.0.0.0 --port 8000
Restart=on-failure
[Install]
WantedBy=multi-user.target
Store API keys in /opt/mcp-summarizer/.env with permissions set to 600.
Conclusion
You now have a working MCP server that accepts context-carrying requests, validates them against a defined schema, and returns structured output. The mock model swaps for any real LLM by changing a single function, and the rest of the server code stays unchanged. Deploying with Docker or systemd keeps the setup manageable on a home lab or a small VPS. The same pattern, schema definition plus context injection plus endpoint registration, scales to more complex workflows: add more endpoints, chain services together, or let the context manager track session state across multiple models. Start with one endpoint, verify it end to end, and build from there.
FAQ
What is the Model Context Protocol (MCP)?
The Model Context Protocol (MCP) is a standardized communication layer designed to facilitate the exchange of context and model inferences between various AI components and applications. It provides a structured approach to managing dynamic context across multiple model interactions.
Why is building an MCP server important in 2026?
Building an MCP server is an essential skill in 2026 because MCP is rapidly becoming the backbone for advanced AI applications. It’s crucial for leveraging the skyrocketing demand for robust, scalable, and context-aware AI systems.
What are the key benefits of using MCP?
MCP offers several key benefits, including enhanced contextual awareness, which allows systems to maintain and update dynamic context. It also ensures interoperability, enabling different models to communicate effectively, and provides scalability for integrating new models seamlessly.
Related Articles
The end. Thanks for reading.