Flask MCP Server Implementation Guide
A Flask-based reference implementation demonstrating how to build an MCP server with stateless HTTP transport, including example tools for generating random numbers and sentences.
README
MCP Server Implementation Guide
A Flask-based implementation of the Model Context Protocol (MCP) server.
What is MCP?
MCP (Model Context Protocol) is an open-source standard for connecting AI applications to external systems. Think of it like a USB-C port for AI applications — it provides a standardized way to connect AI applications (like Cursor, Claude, or ChatGPT) to data sources, tools, and workflows.
┌─────────────────┐ ┌─────────────────┐
│ │ │ │
│ AI Client │◄───────►│ MCP Server │
│ (Cursor) │ MCP │ (Flask App) │
│ │ │ │
└─────────────────┘ └─────────────────┘
Reference: What is MCP? - modelcontextprotocol.io
JSON-RPC 2.0 Protocol
MCP uses JSON-RPC 2.0 for all communication. There are three message types:
Request
{
"jsonrpc": "2.0",
"id": 1,
"method": "method_name",
"params": { ... }
}
Response (Success)
{
"jsonrpc": "2.0",
"id": 1,
"result": { ... }
}
Response (Error)
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32600,
"message": "Invalid Request"
}
}
Notification (No Response Expected)
{
"jsonrpc": "2.0",
"method": "notifications/initialized"
}
Reference: Messages - MCP Specification
Required JSON-RPC Methods
An MCP server must implement the following methods:
| Method | Type | Description |
|---|---|---|
initialize |
Request | Handshake and capability negotiation |
notifications/initialized |
Notification | Client confirms initialization complete |
tools/list |
Request | List available tools |
tools/call |
Request | Execute a tool |
resources/list |
Request | List available resources |
resources/read |
Request | Read a resource |
prompts/list |
Request | List available prompts |
prompts/get |
Request | Get a prompt template |
Reference: MCP Specification
Method Details
1. initialize
Establishes connection and negotiates capabilities.
Request:
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-06-18",
"capabilities": {},
"clientInfo": {
"name": "Cursor",
"version": "2.1.32"
}
}
}
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-06-18",
"capabilities": {
"tools": { "listChanged": false },
"prompts": {},
"resources": {}
},
"serverInfo": {
"name": "mcp-random-tools",
"version": "1.0.0"
}
}
}
2. notifications/initialized
Client notifies server that initialization is complete. No response required (return HTTP 204).
{
"jsonrpc": "2.0",
"method": "notifications/initialized"
}
3. tools/list
Returns available tools with their schemas.
Request:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}
Response:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"tools": [
{
"name": "random_number",
"description": "Generate a random integer between min and max",
"inputSchema": {
"type": "object",
"properties": {
"min": { "type": "integer", "description": "Minimum value" },
"max": { "type": "integer", "description": "Maximum value" }
},
"required": ["min", "max"]
}
}
]
}
}
4. tools/call
Executes a tool and returns the result.
Request:
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "random_number",
"arguments": {
"min": 1,
"max": 100
}
}
}
Response: ⚠️ Important: Results must be in content array format with isError field!
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"content": [
{
"type": "text",
"text": "42"
}
],
"isError": false
}
}
The content array can contain multiple items with different types:
text— Plain text resultimage— Base64 encoded image with mimeTyperesource— Reference to a resource URI
The isError field indicates whether the tool execution failed. Even if the HTTP request succeeds (200), the tool itself may have encountered an error.
Reference: MCP Specification 2025-06-18
5. resources/list & prompts/list
Return empty arrays if not implemented:
{
"jsonrpc": "2.0",
"id": 4,
"result": {
"resources": []
}
}
{
"jsonrpc": "2.0",
"id": 5,
"result": {
"prompts": []
}
}
Reference: Tools - MCP Specification
Cursor Integration Flow
Configuration File
Add your MCP server to ~/.cursor/mcp.json:
{
"mcpServers": {
"Local Flask MCP Server": {
"headers": {},
"url": "http://127.0.0.1:5050/"
}
}
}
Communication Flow
┌──────────────────────────────────────────────────────────────────────────────┐
│ CURSOR ←→ MCP SERVER FLOW │
└──────────────────────────────────────────────────────────────────────────────┘
CURSOR MCP SERVER
│ │
│ ┌─────────────────────────────────────────────┐ │
│ │ PHASE 1: INITIALIZATION │ │
│ └─────────────────────────────────────────────┘ │
│ │
│──── POST initialize ──────────────────────────────►│
│ { protocolVersion, clientInfo, capabilities } │
│ │
│◄─── 200 OK ───────────────────────────────────────│
│ { protocolVersion, serverInfo, capabilities } │
│ │
│──── POST notifications/initialized ───────────────►│
│ │
│◄─── 204 No Content ────────────────────────────────│
│ │
│ ┌─────────────────────────────────────────────┐ │
│ │ PHASE 2: DISCOVERY │ │
│ └─────────────────────────────────────────────┘ │
│ │
│──── POST tools/list ──────────────────────────────►│
│◄─── 200 OK { tools: [...] } ───────────────────────│
│ │
│──── POST resources/list ──────────────────────────►│
│◄─── 200 OK { resources: [] } ──────────────────────│
│ │
│──── POST prompts/list ────────────────────────────►│
│◄─── 200 OK { prompts: [] } ────────────────────────│
│ │
│ ┌─────────────────────────────────────────────┐ │
│ │ PHASE 3: TOOL EXECUTION (on demand) │ │
│ └─────────────────────────────────────────────┘ │
│ │
│──── POST tools/call ──────────────────────────────►│
│ { name: "random_number", arguments: {...} } │
│ │
│◄─── 200 OK ────────────────────────────────────────│
│ { content: [...], isError: false } │
│ │
What Happens When Cursor Starts
- Cursor reads
~/.cursor/mcp.jsonto discover configured MCP servers - Sends
initializerequest to each server to establish connection - Server responds with its capabilities (tools, resources, prompts)
- Cursor sends
notifications/initializedto confirm handshake complete - Cursor queries metadata via
tools/list,resources/list,prompts/list - Tools become available for the AI model to invoke during conversations
Transport: Stateless HTTP
This Flask implementation uses Stateless HTTP transport (simple POST requests). This is suitable for:
- Simple tool servers
- Dockerized or remote deployments
- Servers that don't need bidirectional communication
Limitations of Stateless HTTP:
- ❌ No server-initiated notifications (logging, progress updates)
- ❌ No sampling (server asking the AI for information)
- ❌ No real-time bidirectional communication
For full bidirectional features, you would need SSE (Server-Sent Events) or WebSocket transport.
Reference: MCP Transports
Server Architecture
┌─────────────────────────────────────────────────────────────┐
│ MCP SERVER │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Tools │ │ Resources │ │ Prompts │ │
│ │ │ │ │ │ │ │
│ │ • random_ │ │ • files │ │ • templates │ │
│ │ number │ │ • databases │ │ • workflows │ │
│ │ • random_ │ │ • APIs │ │ │ │
│ │ sentence │ │ │ │ │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │ │
│ └──────────────────┴──────────────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ JSON-RPC 2.0 │ │
│ │ Handler │ │
│ └────────┬────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ HTTP/Flask │ │
│ │ POST / │ │
│ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
Running the Server
# Install dependencies
pip install flask
# Run the server
flask run --port 5050
# Or with debug mode
FLASK_DEBUG=1 flask run --port 5050
Error Handling
Return proper JSON-RPC error responses:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32601,
"message": "Method not found"
}
}
Standard error codes:
| Code | Message |
|---|---|
| -32700 | Parse error |
| -32600 | Invalid Request |
| -32601 | Method not found |
| -32602 | Invalid params |
| -32603 | Internal error |
References
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.