MCP 2026-07-28 / Python SDK — opportunities for Dazzle¶
Date: 2026-08-10
Adopted: mcp>=2,<3 (SDK 2.0.0, protocol 2026-07-28)
Server: lowlevel Server with constructor on_* handlers; stdio transport
Related: ADR-0002 (MCP/CLI boundary), src/dazzle/mcp/server/
Status: Full SDK v2 adoption landed 2026-08-10. Remaining opportunities (Streamable HTTP, Tasks, MRTR for select_project) are optional scale-out, not blockers for local Claude Code / stdio hosts.
Will MCP “survive” now that hosts tool-call natively? Short answer: as a portable tool/resource contract across hosts, yes; as a bidirectional session fabric, the 2026-07-28 rewrite is how it survives. Dazzle already fought session and blocking pain months ago; the new doctrine aligns with us more than it threatens us.
What changed (upstream)¶
Sources: MCP blog 2026-07-28, Python SDK README / PyPI 2.0, Cloudflare MCP v2.
| Theme | 2025-era | 2026-07-28 |
|---|---|---|
| Session | initialize + Mcp-Session-Id, sticky routing |
Stateless core; each request self-describing |
| Interactivity | Server→client on open stream (elicitation/sampling) | MRTR (input_required + client retry with answers) |
| HTTP | Body-only routing | Mcp-Method / Mcp-Name headers for gateways |
| Lists | Re-fetch often | ttlMs / cacheScope on list results |
| Long work | Ad-hoc | Tasks extension (poll tasks/get) |
| Auth | DCR heavy | CIMD preferred; DCR deprecated |
| Python API | mcp.server.Server + stdio patterns |
v2: MCPServer, snake_case fields, transport split |
Legacy HTTP+SSE and several features have a ≥12 month deprecation window.
What Dazzle already solved (local oral history)¶
| Dazzle investment | Why it existed | Relation to new MCP |
|---|---|---|
| ADR-0002 read vs side-effect boundary | MCP calls blocked agent thread | Still correct; long work → CLI or Tasks |
process_lock.py / mcp-sessions |
Multi-client stdio / shared state races | Less necessary for pure stateless HTTP; still useful for app state (project root, KG cache) |
| Consolidated tools | Huge tool lists | Cacheable tools/list is a free win |
| Dev mode multi-project | Hosts bind one cwd | Explicit handles (project id) match “state as tool args” doctrine |
Upstream’s line: drop protocol session; if you need state, mint a handle and pass it as an argument. That is exactly “select_project → subsequent tools” without transport sticky sessions.
Opportunities if we embrace v2 / 2026-07-28¶
1. Stateless HTTP transport for hosted Dazzle MCP¶
Today the primary path is stdio (mcp.server.stdio). Stateless Streamable
HTTP enables:
- Multiple replicas behind a load balancer (no session affinity)
- Edge / Worker-style deployment (Cloudflare already marketing this)
- Ordinary HTTP observability on
Mcp-Method/Mcp-Name
Action: spike streamable_http app alongside stdio; keep stdio for Claude
Code local. Do not delete process_lock until stdio multi-writer is gone.
2. Tool catalog caching¶
tools/list with ttlMs reduces host re-init cost. Our consolidated tool list
is large — mark list responses cacheable once on v2.
3. MRTR for “missing project / confirm destructive”¶
Replace awkward “error: select project first” loops with
input_required-style continuation if the host supports MRTR. Until then,
keep structured errors (hosts on old SDK).
4. Tasks for long digs (optional)¶
Improve / QA captures are CLI for a reason. Tasks extension is the MCP-native form of “don’t block the conversation.” Only expose Tasks for operations we already allow as long-running CLI, with the same auth posture.
5. Explicit state handles (align code with doctrine)¶
Audit tools that assume ambient session (cwd, last project). Prefer:
That migrates cleanly to stateless multi-instance.
6. Pin strategy¶
pip install mcp now resolves 2.x. Without an upper bound, a clean venv
can break imports (Server vs MCPServer, field renames). Add <2 soon even
if we do not migrate yet.
7. ADR-0002 revision note (not rewrite)¶
Keep the boundary test. Add: protocol sessions are gone upstream; Dazzle app state remains explicit handles; long/side-effect work remains CLI or Tasks.
What not to do¶
- Do not expose generate/LLM/write as MCP tools “because MRTR exists.”
- Do not treat MCP death rumors as a reason to delete the server — hosts still need a standard tool schema for non-code-exec agents.
- Do not migrate to v2 mid-improve-campaign without a test plan
(
tests/unit/test_mcp_*, session, process_lock).
Done (2026-08-10)¶
- Pin
mcp>=2,<3in pyproject. - Rewrite
src/dazzle/mcp/server/__init__.pyforon_*handlers + full result types. - snake_case field access (
input_schema,progress_token,mime_type). - Cache hints on
tools/list/resources/list/prompts/list. - Unit tests +
scripts/verify-mcp.pygreen on v2.
Follow-ups (optional scale-out)¶
- Dual-stack: stdio + Streamable HTTP (
stateless_http=True). - Host matrix notes (Claude Code / Cursor / Grok) vs protocol version.
- Tasks for
qa captureclass work (only if product wants MCP-native long jobs). - MRTR for “select project / confirm” when hosts support it.
Bottom line¶
MCP’s new doctrine is stateless, header-routable, cacheable, MRTR for interactivity — the same pressures that produced ADR-0002 and our process lock. Embracing it is mostly delete session mythology, keep the boundary, pin until migrated, then HTTP scale. Direct tool-calling does not replace a cross-host tool contract; it increases the number of hosts that will speak MCP if the protocol stays easy to run.