# Beta4 Is Here. Upgrade All Your MCP Servers With One Line.

> Source: <https://naftiko.io/blog/beta4-is-here-upgrade-all-your-mcp-servers-with-one-line/>
> Published: 2026-08-18 00:00:00+00:00

Three weeks ago [we wrote](/blog/the-2026-07-28-mcp-spec-and-why-your-capabilities-dont-need-recertifying/) that the `2026-07-28`

MCP revision was the biggest breaking change since the protocol launched, and that capabilities running on Ikanos would ride through it as one engine upgrade with zero edits to any capability file. At the end of that post, we said we would show the diff when Ikanos shipped support.

Ikanos `v1.0.0-beta4`

shipped this week with `2026-07-28`

support. This is that post.

We took two capabilities from earlier write-ups, the [Notion to GitHub spec sync](/blog/sync-a-notion-spec-into-a-github-issue-with-one-ikanos-capability/) and the [support voice assistant](/blog/voice-assistants-and-the-200-tool-bottleneck/), ran them on beta3, changed one thing, and pointed a real MCP client at both before and after. Every command and diff below was run against the real engine.

## The bump

The engine is a plain `docker run`

, straight from the install docs. The version is the image tag. Moving from beta3 to beta4 means changing that tag:

```
- ghcr.io/naftiko/ikanos:v1.0.0-beta3
+ ghcr.io/naftiko/ikanos:v1.0.0-beta4
bash
$ docker run -p 9095:9095 -p 9198:9198 \
    -v $(pwd)/capabilities/notion-github-spec-sync.yaml:/app/ikanos.yaml \
    ghcr.io/naftiko/ikanos:v1.0.0-beta4
MCP Server started on 0.0.0.0:9095 (namespace: spec-sync)
Capability started successfully.
```

If you manage the engine through `docker-compose.yml`

, it’s the same edit in a file instead of on the command line. Ikanos doesn’t care how the image gets pulled, only which tag it is. Compose just means the tag lives somewhere you can diff:

``` bash
$ docker compose up -d
notion-github-spec-sync-1  | MCP Server started on 0.0.0.0:9095 (namespace: spec-sync)
support-voice-assistant-1  | MCP Server started on 0.0.0.0:9096 (namespace: voice)
notion-github-spec-sync-1  | Capability started successfully.
support-voice-assistant-1  | Capability started successfully.
```

Both capabilities are back up on the current MCP specification. Their own files were not touched, including the `ikanos:`

line inside each one.

## The diff on every capability

A real `git diff`

across the tagged commits, on both capability files, before the bump and after:

``` bash
$ git diff before after -- 'capabilities/*.yaml'
(exit code: 0)
```

Zero files changed. Zero insertions. Zero deletions. Not “no breaking changes we noticed.” Zero bytes.

The file that describes what your capability does was never a place the transport migration could touch, because the transport never lived there. It lives in the engine.

## The diff on the tool contract

Unchanged YAML is half the promise. The other half is that the agent sees the same thing before and after. We captured `tools/list`

against both engine versions and diffed the raw responses:

``` bash
$ diff fixtures/beta3/tools-list.json fixtures/beta4/tools-list.json
       ]
+      "resultType": "complete",
+      "ttlMs": 0,
+      "cacheScope": "private",
+      "_meta": {
+        "io.modelcontextprotocol/serverInfo": {
+          "name": "spec-sync",
+          "version": "unspecified"
+        }
+      }
```

That is the entire substantive difference, and it repeats identically for the second capability. The tool itself is identical left to right — same `name`

, `title`

, `description`

, `inputSchema`

, and safety hints, byte for byte, for all three tools across both capabilities.

The only additions sit outside the tool definition: `ttlMs`

and `cacheScope`

, response-level caching hints from the `2026-07-28`

spec. A client can use them. A capability author never has to think about them.

## The transport actually moved

The wire underneath changed shape, which is the reason a migration post exists at all. beta3 spoke the old session-based handshake:

```
# beta3 · POST /mcp · initialize
HTTP/1.1 200 OK
Mcp-Session-Id: 6f04252a-5320-4aca-99b4-ecb6175ab30c

{"result":{"protocolVersion":"2025-11-25", ...}}
```

Send that same request to beta4 and it doesn’t get as far as being an unknown method:

```
HTTP/1.1 400 Bad Request

{"jsonrpc":"2.0","id":1,"error":{"code":-32020,
  "message":"Missing mandatory header: Mcp-Method"}}
```

beta4 speaks the stateless `2026-07-28`

core. No handshake. Protocol version and method travel with every request instead of being negotiated once:

```
# beta4 · POST /mcp · tools/list, no prior handshake
Mcp-Method: tools/list
MCP-Protocol-Version: 2026-07-28

{"result":{"tools":[...], "resultType":"complete",
  "ttlMs":0, "cacheScope":"private"}}
```

That is a real break for a client hardcoded to the old handshake, and it is meant to be. The MCP spec’s own [compatibility matrix](https://modelcontextprotocol.io/specification/2026-07-28/basic/versioning#backward-compatibility-with-initialization-based-versions) documents *legacy client × modern server → fails* as the expected outcome for a modern-only server. It’s not an Ikanos choice.

The current Tier-1 SDKs (TypeScript, Python, Go, C#) already speak `2026-07-28`

, and the Python and TypeScript v2 SDKs support every earlier revision too. The one thing to check before you change the tag in production is what your agent’s client dependency is running. Not your capability files.

## One certification, not many

Before Ikanos, verifying a transport migration was safe meant re-reviewing every capability that touches MCP. Two capabilities meant you had to do two reviews. Here it is one engine, reviewed once, inherited by both. Every capability you add later inherits the same guarantee without a second audit, because the thing that changed was never expressed in any of them.

What we verified:

**Capability YAML**— 0 bytes changed across both files** Tool contract**— identical name, description, schema, hints** Engine**— started clean on beta4, serving both capabilities** Wire protocol**— checked against the public`2026-07-28`

spec, not just the release notes

## Also in beta4

Naftiko’s `1.0.0-beta4`

releases didn’t stop there. The rest of the releases are about testing what we say holds.

- Ikanos has its first real end-to-end suite. CI brings up Keycloak and Microcks in Docker Compose, starts Ikanos against them, and exercises the OAuth 2.1 and Bearer paths with real tokens and real JWKS discovery, plus an invalid token to confirm rejection works.
- A feature coverage tracker maps all 32 blueprint features against test depth and delivery progress. It works as a roadmap and as a plain list of what is still thin.
- Polychro’s “iso-functional with Spectral” claim is now a harness rather than a sentence. Same ruleset, same document, run through both engines, diagnostics diffed.
- Trivy scans now gate Polychro’s Maven and CLI release pipelines. CLI binaries ship with SHA256 checksums. Five CVEs patched.
- Polychro fix: paths in
`.polychro.yml`

resolve against the config file, not the working directory.

Crafter, Warden, and Skipper picked up the beta4 schema and engine versions in the same coordinated release.

## The takeaway

The migration cost was real. It landed where the architecture said it would: in the engine, once, instead of in every capability, every time.

If you run Ikanos today, the action item is not “audit your YAML.” It’s “change the image tag, and make sure whatever calls you is on a current MCP client.”
