MCP Stateless Examples
by rajesamp
README.md
# MCP Stateless Examples
Educational implementation of the **MCP 2026-07-28 stateless protocol** — the largest
revision since launch, finalized July 28, 2026.
Built with raw [Starlette](https://www.starlette.io/) (no SDK dependency) to show the
wire protocol clearly. Supply-chain hardened throughout.
## What's New in 2026-07-28
| Change | Impact |
|--------|--------|
| **Stateless core** | No `initialize` handshake, no `Mcp-Session-Id` |
| **`_meta` envelope** | Every request carries `protocolVersion` + `clientCapabilities` |
| **`server/discover`** | Replaces `initialize` for capability discovery |
| **Routing headers** | `Mcp-Method` + `Mcp-Name` required on all POSTs |
| **MRTR** | `InputRequiredResult` replaces server→client SSE requests |
| **`requestState`** | HMAC-signed opaque handle for multi-round state |
| **`subscriptions/listen`** | Long-lived POST→SSE replaces GET endpoint |
Sources: [Spec](https://modelcontextprotocol.io/specification/2026-07-28/basic) ·
[Changelog](https://modelcontextprotocol.io/specification/2026-07-28/changelog) ·
[Blog](https://blog.modelcontextprotocol.io/posts/2026-07-28-release-candidate/)
## Quick Start
```bash
# Install
pip install -e ".[dev]"
# Run the server
uvicorn mcp_stateless.server:app --reload
# In another terminal, try the examples
python examples/01_basic_tool.py
python examples/02_state_handle.py
python examples/03_mrtr_elicitation.py
# Or use curl
bash examples/curl/discover.sh
bash examples/curl/tools_list.sh
bash examples/curl/tools_call.sh
```
## Examples
| # | Example | Pattern |
|---|---------|---------|
| 01 | [Basic tool call](examples/01_basic_tool.py) | Simplest stateless `tools/call` |
| 02 | [State handle](examples/02_state_handle.py) | Server-minted handle for cross-request state |
| 03 | [MRTR elicitation](examples/03_mrtr_elicitation.py) | Multi-round with user input |
| 04 | [MRTR sampling](examples/04_mrtr_sampling.py) | Multi-round with LLM sampling + decline path |
| 05 | [Subscriptions](examples/05_subscriptions.py) | `subscriptions/listen` change notifications |
| 06 | [Dual-era sketch](examples/06_dual_era.py) | Backward compat with 2025-era clients |
## Architecture
```
src/mcp_stateless/
├── server.py # Starlette app, JSON-RPC routing
├── meta.py # _meta envelope parsing + validation
├── headers.py # MCP-Protocol-Version, Mcp-Method, Mcp-Name, Origin
├── discover.py # server/discover RPC
├── request_state.py # HMAC-SHA256 requestState codec
├── mrtr.py # InputRequiredResult + inputResponses helpers
└── tools/
├── __init__.py # SENTINEL-TPD tool registry + scanning
├── weather.py # Stateless tool (no state)
├── cart.py # Stateful-via-handle tool
└── brainstorm.py # MRTR multi-round tool
```
## Security
- **SENTINEL-TPD**: Tool descriptions scanned at registration for poisoning signals
- **Origin validation**: DNS rebinding defense
- **Header-body validation**: Prevents routing spoofing
- **State handle security**: HMAC-signed, principal-bound, TTL-expiring
- **Capability enforcement**: Server rejects undeclared client capabilities
See [docs/security-model.md](docs/security-model.md) for the full threat model.
## Supply Chain
| Control | Status |
|---------|--------|
| Wolfi/distroless base | Dockerfile with pinning notes |
| SBOM (syft) | CI workflow |
| cosign signing | supply-chain.yml |
| SLSA Level 3 | slsa-github-generator |
| Pinned deps | pyproject.toml |
| Non-root container | UID 1000 |
```bash
bash scripts/verify_supply_chain.sh
```
## Testing
```bash
python -m pytest tests/ -v
```
Test coverage:
- `_meta` envelope parsing and validation
- Header mismatch detection (all required headers)
- `requestState` HMAC codec (mint, verify, tamper, expiry, principal binding)
- MRTR helpers (InputRequiredResult, inputResponses)
- SENTINEL-TPD tool scanning (poisoning detection, quarantine)
- Stateless invariants (no session, no initialize, per-request _meta)
## License
MIT
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues