Skip to main content
Glama
sergiuiacob1

Flask MCP Server Implementation Guide

by sergiuiacob1

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 result

  • image — Base64 encoded image with mimeType

  • resource — 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

  1. Cursor reads ~/.cursor/mcp.json to discover configured MCP servers

  2. Sends initialize request to each server to establish connection

  3. Server responds with its capabilities (tools, resources, prompts)

  4. Cursor sends notifications/initialized to confirm handshake complete

  5. Cursor queries metadata via tools/list, resources/list, prompts/list

  6. 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

-
security - not tested
F
license - not found
-
quality - not tested

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sergiuiacob1/mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server