# MCP 2026-07-28: what applies to Loki, and who implements it

Slice MCP-0. Documentation only; no code changed. Written 2026-10-08.
Every claim is marked VERIFIED (read from the cited source on the fetch date) or UNVERIFIED (inferred, not run).

## Sources

| Source | URL | Fetched |
|---|---|---|
| Spec "Key Changes" (changelog vs 2025-11-25) | https://modelcontextprotocol.io/specification/2026-07-28/changelog | 2026-10-08 |
| PyPI `mcp` JSON | https://pypi.org/pypi/mcp/json | 2026-10-08 |
| PyPI `mcp` 2.3.0 wheel and `mcp-types` 2.3.0 wheel (pip download, files read) | https://pypi.org/project/mcp/2.3.0/ | 2026-10-08 |
| npm `@modelcontextprotocol/sdk` (registry via `npm view`, tarball 1.32.1 read) | https://www.npmjs.com/package/@modelcontextprotocol/sdk | 2026-10-08 |
| npm `@modelcontextprotocol/server` and `@modelcontextprotocol/client` (`npm view`) | https://www.npmjs.com/package/@modelcontextprotocol/server | 2026-10-08 |

## SDK versions found

- Python SDK latest version found: mcp 2.3.0, uploaded 2026-10-02 (VERIFIED, PyPI JSON). Also on PyPI: 2.2.0 (2026-09-07), 1.30.0 (2026-09-07). The installed copy on the build machine is mcp 1.27.0 (VERIFIED, `importlib.metadata`).
- Does Python mcp 2.3.0 implement 2026-07-28: its `mcp-types` 2.3.0 wheel lists "2026-07-28" in `MODERN_PROTOCOL_VERSIONS` (`mcp_types/version.py`), and the `mcp` wheel contains `server/_streamable_http_modern.py` and references to `server/discover` (VERIFIED, files read). Runtime behavior was not exercised: UNVERIFIED.
- Loki pins `mcp>=1.0.0,<2.0.0` in `mcp/requirements.txt`, so a fresh install can never pick up 2.x (VERIFIED, repo file). 2.3.0 requires Python >=3.10 and new dependencies (`mcp-types`, `httpx2`, `pyjwt`); compatibility with Loki's `mcp/_sdk_loader.py` is UNVERIFIED.
- npm `@modelcontextprotocol/sdk` latest: 1.32.1, modified 2026-10-05 (VERIFIED, `npm view`). Its README states it implements the spec up to 2025-11-25 and that 2026-07-28 support "is not planned for v1.x"; it lives in v2 as separate packages (VERIFIED, README in tarball).
- npm v2 packages `@modelcontextprotocol/server` and `@modelcontextprotocol/client`: latest 2.3.1, modified 2026-10-05 (VERIFIED, `npm view`). Whether they implement every item below: UNVERIFIED.

## Conformance table

"Applies" means a requirement on a stdio tool server plus a client such as Loki's (`mcp/server.py`, `mcp/lsp_proxy.py`, `src/protocols/mcp-server.js`, `src/protocols/mcp-client.js`).

| Spec change (2026-07-28) | Applies to Loki | Status of claim |
|---|---|---|
| Stateless protocol: the `initialize` / `notifications/initialized` handshake is removed (initialize removal); each request carries protocol version and client capabilities in `_meta` (`io.modelcontextprotocol/protocolVersion`, `io.modelcontextprotocol/clientCapabilities`) | Yes, server and client | VERIFIED (changelog) Slice MCP-C: JS server done (no initialize needed, `_meta` version checked, no session stored); behind LOKI_MCP_2026_07=1. |
| `server/discover` RPC: servers MUST implement it; clients MAY call it first or use it as a stdio compatibility probe | Yes, server MUST | VERIFIED (changelog) Slice MCP-C: JS server done (`supportedVersions`, `serverInfo`, `capabilities`); result field names are our reading, UNVERIFIED against the spec schema. |
| Multi Round-Trip Requests (MRTR): `InputRequiredResult` (`resultType: "input_required"`) with `inputRequests`, client retries with `inputResponses`; replaces server-initiated `roots/list`, `sampling/createMessage`, `elicitation/create`. All results carry `resultType` | Yes if Loki ever asks the client for input; today it does not (UNVERIFIED, inferred from tool list) | Spec VERIFIED (changelog) |
| Tasks moved out of core to the extension `io.modelcontextprotocol/tasks` (polling via `tasks/get`, new `tasks/update`, no `tasks/list`) | Only if Loki exposes long-running tools as tasks; optional | VERIFIED (changelog) |
| OpenTelemetry trace context in `_meta`: `traceparent`, `tracestate`, `baggage` (traceparent in _meta) | Optional; useful with the OTEL-GENAI program | VERIFIED (changelog) |
| Deprecated: Roots, Sampling, Logging (`logging/setLevel` removed; level per request via `io.modelcontextprotocol/logLevel`), HTTP+SSE transport, OAuth Dynamic Client Registration (DCR) in favor of Client ID Metadata Documents | Loki implements none of Roots/Sampling/Logging as a server; DCR applies only to remote HTTP auth (`tests/test-mcp-http-auth.sh`) | VERIFIED (changelog); Loki usage UNVERIFIED beyond grep |
| Streamable HTTP: sessions and `Mcp-Session-Id` removed; `subscriptions/listen` replaces GET and `resources/subscribe`; `Mcp-Method` and `Mcp-Name` headers required on POST; SSE resumability removed | Only for the HTTP transport; stdio unaffected | VERIFIED (changelog) |
| `ping` and `notifications/roots/list_changed` removed; `ttlMs` and `cacheScope` required on list results; deterministic `tools/list` order; resource-not-found code now -32602 | Yes for the server's list endpoints | VERIFIED (changelog) |
| Error code renumbering: HeaderMismatch -32020, MissingRequiredClientCapability -32021, UnsupportedProtocolVersion -32022 | Yes once the stateless profile is implemented | VERIFIED (changelog) Slice MCP-C: -32022 UnsupportedProtocolVersion done; the other two codes are not used yet. |

## Consequences for the plan

- Python side (MCP-B, MCP-C): do not hand-roll the 2026-07-28 profile. A pip release that carries it exists (2.3.0), so the path is an SDK bump behind a test, not new protocol code. Raising the `<2.0.0` ceiling needs a compatibility run first (UNVERIFIED today).
- JS side (MCP-A, MCP-C): the hand-rolled server cannot get 2026-07-28 from `@modelcontextprotocol/sdk` 1.x; the v2 packages are the candidate. Adding a dependency needs its own decision.
- MCP-A (legacy version negotiation fixes) is independent of this document.

## MCP-C status (JS server)

- `server/discover` is answered always; the version list includes 2026-07-28 only when `LOKI_MCP_2026_07=1` (default off until every row above passes).
- `tools/list`, `tools/call` and the other methods work with no prior `initialize`. A `_meta["io.modelcontextprotocol/protocolVersion"]` outside the advertised list gets -32022 with `data.supported`.
- `initialize` for legacy clients is unchanged; its fallback stays 2025-11-25, never 2026-07-28. No session id is stored. `tools/call` keeps the existing auth check, which runs before the version check.
- Not done: `resultType`, `ttlMs`/`cacheScope`, MRTR, Tasks, `Mcp-Method` headers, `subscriptions/listen`. Python side: SDK-only, no hand-rolled protocol (see Consequences).

## Method

Changelog text read from the fetched page on 2026-10-08. PyPI facts from the JSON API. Wheel and tarball contents read after `pip download --no-deps` and `npm pack` into scratch directories (not installed, not executed).
