A Model Context Protocol (MCP) server that provides ordered, Kafka-based resource retrieval with automatic buffering for out-of-order sequences.
- Overview
- Architecture
- Requirements
- Setup
- Running the Services
- Running Tests
- MCP Server Usage
- API Reference
- Code Quality
This service implements a retrieval gateway that:
- Ensures ordered processing of requests per ordering key (e.g., user ID)
- Buffers out-of-order requests automatically
- Provides idempotency using request IDs
- Operates via Kafka
- Exposes functionality through an MCP server for AI assistant integration
┌─────────────────┐
│ MCP Client │ (Claude Desktop, Inspector, etc.)
│ (STDIO/SSE) │
└────────┬────────┘
│
▼
┌─────────────────┐
│ MCP Server │ FastMCP-based tool server
│ (retrieve) │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Kafka Topics │ Request/Response flow
│ mcp.retrieval │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Consumer Worker │ RequestProcessor
│ + Database │ PostgreSQL state tracking
└────────┬────────┘
│
▼
┌─────────────────┐
│ Mock Upstream │ Simulated resource service
│ (FastAPI) │
└─────────────────┘
-
RequestProcessor (
src/retrieval_gateway_mcp/req_processor.py)- Core business logic for ordered processing
- Handles buffering, idempotency, and state management
- Database-backed with PostgreSQL
-
MCP Server (
src/retrieval_gateway_mcp/mcp_server.py)- Exposes
retrievetool via MCP protocol - Produces requests to Kafka
- Polls for responses (primary + buffered)
- Exposes
-
Kafka Consumer (
src/retrieval_gateway_mcp/kafka/consumer.py)- Consumes requests from Kafka topics
- Calls upstream service
- Produces responses back to Kafka
-
Mock Upstream (
src/retrieval_gateway_mcp/mock_upstream.py)- FastAPI server simulating a resource service
- Supports contacts, orders, users
- Includes configurable delays
The system handles failures with a DLQ (Dead Letter Queue) using Kafka topics:
- Malformed messages →
mcp.retrieval.dlqtopic- JSON decode errors
- Schema validation failures
- Processing exceptions
Design choice: DLQ uses Kafka topic only (not database). Rationale: malformed messages often lack valid request_id or schema, which would require synthetic IDs and/or placeholder values to force into the database. Kafka topic provides durable storage for forensic analysis without compromising data integrity.
- Python: >=3.12, <4.0
- Poetry: Dependency management
- Docker: For PostgreSQL and Kafka
- Docker Compose: Multi-container orchestration
poetry installCopy the example environment file and update with your values:
cp .env.example .envEdit .env to set your credentials (the defaults work for local development):
# Database credentials
POSTGRES_USER=mcp_user
POSTGRES_PASSWORD=mcp_password
POSTGRES_DB=mcp_gateway
POSTGRES_DB_TEST=mcp_gateway_test
# Database ports
POSTGRES_PORT=5433
POSTGRES_TEST_PORT=5434
# Kafka configuration
KAFKA_CLUSTER_ID=MkU3OEVBNTcwNTJENDM2QkStart PostgreSQL and Kafka:
docker-compose up -dpoetry run python -c "from src.retrieval_gateway_mcp.models import *; from src.retrieval_gateway_mcp.config import Config; init_database(create_database_engine(Config.DATABASE_URL))"poetry run pre-commit installYou need three separate terminals for the full system:
poetry run python -m retrieval_gateway_mcp.mock_upstreamRuns on http://localhost:8001
poetry run python -m retrieval_gateway_mcp.kafka.consumerProcesses requests from Kafka and calls upstream.
poetry run python -m retrieval_gateway_mcp.mcp_serverExposes the retrieve tool via STDIO transport.
poetry run pytestpoetry run pytest tests/unit/# Requires infrastructure running (docker-compose up -d)
poetry run pytest tests/integration/-
Unit Tests (
tests/unit/test_req_processor.py) - 14 tests- Core business logic
- Buffering scenarios
- Error handling
- Idempotency
-
RequestProcessor Integration (
tests/integration/test_req_processor.py) - 2 tests- Database interactions
- End-to-end request flow
-
Kafka Integration (
tests/integration/test_kafka.py) - 2 tests- Idempotency with duplicate delivery
- Offset replay behavior
-
MCP Integration (
tests/integration/test_mcp.py) - 2 tests- Simple retrieve tool usage
- Out-of-order buffering with MCP client
npx @modelcontextprotocol/inspector poetry run python -m retrieval_gateway_mcp.mcp_serverOpens web UI at http://localhost:5173 for interactive testing.
See test_mcp_client.py for example Python client code.
Retrieve a resource with ordered processing.
Parameters:
ordering_key(string, required): Key for ordering (e.g., user ID)sequence(int, required): Sequence number for this ordering keyresource_type(string, required): Resource type (e.g., "contact")resource_key(string, required): Resource identifiertenant_id(string, optional): Tenant ID (default: "default")client_id(string, optional): Client ID (default: "mcp")
Returns:
{
"res": {
"request_id": "01KD1...",
"status": "OK|ACCEPTED",
"payload": { ... },
"served_at": 1234567890
},
"processed_from_buffer": [
{
"request_id": "01KD2...",
"status": "OK",
"payload": { ... }
}
]
}Status Codes:
OK: Request processed successfullyACCEPTED: Request buffered (out of order)
request_id(PK): Unique ULIDordering_key: Grouping keysequence: Order within groupstatus: PENDING | COMPLETED | FAILEDresponse_payload: JSON responsecreated_at,updated_at: Timestamps
ordering_key(PK): Grouping keylast_completed_sequence: Last processed sequenceupdated_at: Timestamp
id(PK): Auto-incrementordering_key,sequence: Buffered requestrequest_id: Reference to requestsraw_request: Original JSON payload
This project uses ruff for linting and formatting via pre-commit.
# Run on all files
poetry run pre-commit run --all-files
# Run ruff only
poetry run ruff check .
poetry run ruff format .Pre-commit hooks run automatically on git commit if installed.
Environment variables (.env or shell):
# Database
DATABASE_URL=postgresql://mcp_user:mcp_password@localhost:5432/mcp_gateway
# Kafka
KAFKA_BOOTSTRAP_SERVERS=localhost:29092
KAFKA_REQUEST_TOPIC=mcp.retrieval.request.v1
KAFKA_RESPONSE_TOPIC=mcp.retrieval.response.v1
# Mock Upstream
UPSTREAM_BASE_URL=http://localhost:8001
# Logging
LOG_LEVEL=INFOretrieval-gateway-mcp/
├── src/retrieval_gateway_mcp/
│ ├── req_processor.py # Core processing logic
│ ├── mcp_server.py # MCP tool server
│ ├── models.py # SQLAlchemy models
│ ├── config.py # Configuration
│ ├── mock_upstream.py # Test upstream server
│ └── kafka/
│ ├── consumer.py # Kafka consumer worker
│ └── producer.py # Kafka producer
├── tests/
│ ├── unit/ # Unit tests
│ └── integration/ # Integration tests
├── docker-compose.yml # Infrastructure
├── pyproject.toml # Dependencies
└── README.md # This file
- MCP Buffering Test:
test_retrieve_tool_bufferinghas ~95% reliability due to Kafka async timing
MIT