Release Notes - ChristianPresley/zig-sdk GitHub Wiki

Release Notes

This page tells you what each release of zig-sdk contains. The source is the file CHANGELOG.md of the repository1. Each GitHub release has the same section of the changelog2. The Versioning page tells you how the version numbers change.

Applies to: zig-sdk 0.1.0, 0.2.0, 0.3.0, 0.4.0, 0.5.0 and 0.5.1.

0.5.1 (2026-10-09)

A patch release with two fixes for the stop of the servers. A cancel of serve now stops the server the same way as shutdown. The stop of the accept loops no longer leaves traces in Debug builds on Windows or a panic on macOS. It supports MCP specification revision 2026-07-28 only, on Zig 0.16.0. The file CHANGELOG.md has the full list, and the tag is v0.5.1.

Servers

  • A cancel of serve of the HTTP, gRPC and Unix socket servers sets the stop flag of shutdown. A new call of serve on the same server then accepts no connections. After the cancel, the connections of the HTTP server obey the stop flag, so a connection that waits ends within 60 seconds.
  • The accept loops of the HTTP, gRPC and Unix socket servers stop with util.wake.cancelAcceptLoop or util.wake.cancelUnixAcceptLoop. On Windows, the cancel usually comes before the wake connection, so a Debug build no longer writes a stack trace of error.Unexpected.
  • On a POSIX system, util.wake.wakeIp connects with a socket that does not block. A late cancel signal of std no longer makes the second connect fail with EISCONN on macOS.

0.5.0 (2026-10-08)

A minor release with time limits for the keychain storage on Linux and a fix for Unix sockets on Windows. One change breaks the public API. It supports MCP specification revision 2026-07-28 only, on Zig 0.16.0. The file CHANGELOG.md has the full list, and the tag is v0.5.0.

Keychain storage

  • KeychainTokenStorage.Options.timeout and secret_service.Options.timeout set the time limit for each answer of the D-Bus bus and of the Secret Service. The default is 25 seconds. A service that does not answer in time gives error.KeychainUnavailable. Before, the Secret Service backend waited without a limit.
  • KeychainTokenStorage.Options.prompt_timeout and secret_service.Options.prompt_timeout set the time limit for the answer of the user to a prompt. The default is 5 minutes. A prompt without an answer in time gives error.KeychainLocked.
  • The D-Bus client connects to an abstract address with a socket that does not block. Before, this connect waited without a limit, and a cancel did not stop it.

See Authorization.

Transports

  • On Windows, the Unix socket transport sees each close of the peer. The Windows driver of Unix sockets can lose the close when a receive starts at about the same time. Before, the server kept such a connection and its place in limits.unix_socket.max_connections until shutdown. A request of the client waited until its timeout. Now each read first waits in a poll of the socket. See Transport Unix Socket.

Corrections to the notes of 0.4.0

  • For an http URL, the proxy can read the requests, because that tunnel has no TLS. For an https URL, the proxy sees only the host and the port of the server.
  • The warning of the scope mcp_router for an error response with a null id also has the error code of the response.

Tests

  • On Windows, the fake D-Bus server of the keychain tests serves each connection in its own task.

Changes that break the API

  • dbus.Connection.open has a fifth parameter, the time limit for each answer of the bus. Null waits without a limit, as before. At the limit, the functions of the connection return dbus.Error.Timeout, and the connection is then not usable.

0.4.0 (2026-10-07)

A minor release with new options for the clients and fixes for the transports. It adds options for one request, HTTP proxies and a CA bundle for the OAuth client. It also corrects the failure paths of the client transports and the HTTP/2 connection of the gRPC transport. Four changes break the public API. It supports MCP specification revision 2026-07-28 only, on Zig 0.16.0. The file CHANGELOG.md has the full list, and the tag is v0.4.0.

Client

  • RequestOptions.log_level sets the log level of one request. It replaces Options.log_level of the client for that request.
  • RequestOptions.meta adds _meta entries to one request, for example traceparent. A key that meta.validateKey refuses, or a key that the SDK owns, gives the new error.InvalidMeta. Then the client sends nothing. meta.isSdkOwnedRequestKey tells which keys the SDK owns.
  • The client parses each notification into scratch memory and resets that memory after the frame. Thus a long subscriptions/listen stream does not make the request arena larger.
  • RequestOptions.inline_notifications calls the notification callbacks of a request on the reader task of the transport. A notification then gets to its callback before the response of another request that the server wrote after it. The stdio, Unix socket and WebSocket transports obey the option.
  • Diagnostics.http_status gives the HTTP status of the last response, also when the request failed. Thus a caller can tell a wrong path from a response that is not valid.

See Client Guide.

Transports

  • The stdio, Unix socket and WebSocket clients make a request fail with error.InvalidResponse when the router cannot read its response. Before, the request waited until its timeout. The router logs a warning in the scope mcp_router for each frame that it drops.
  • The stdio client takes on_notification and userdata as spawn options. stdio.Client.exitStatus gives the exit status of the last server process that ended.
  • When the stdio server process ends its output and no restart is left, the client closes the input of the process and reaps it. A process that does not exit gets a termination signal after limits.shutdown_grace, also at a restart.
  • The HTTP client transport applies max_response_bytes to each SSE event, and not to the whole stream. Thus many progress notifications do not stop a long tool call. The SSE parser limits an event to max_event_bytes (4 MiB) and ignores an event ID over max_id_bytes (256).
  • The memory link (memory.ClientLink) gives the frames of one request to the sink one at a time. Its doc comments tell its limits.

See Transports.

Server

  • The server sends the acknowledgment of a subscriptions/listen stream before the first event of the stream, on all transports. Before, an event could get to the client before the acknowledgment. See Server Guide.

Authorization and proxies

  • OAuthClient.Options.ca_bundle sets the CA certificates that the OAuth client trusts for its https requests. A private CA then works without a change to the CA store of the system.
  • OAuthClient reads the stored token record again before a refresh and after the server refuses a refresh. Thus two clients with one storage can use one grant with refresh token rotation.
  • When the stored record has another client ID than the registration of OAuthClient, the client takes the registration of the record with its tokens. When these tokens are for another DPoP key, the client keeps its own registration and tokens.
  • HttpClient.Options.proxy and OAuthClient.Options.proxy send the connections through an HTTP proxy with a CONNECT tunnel. The new module transport.proxy reads the proxy variables from the environment that the application gives. By default, the clients connect directly, as before.

See Authorization and Client Guide.

gRPC and HTTP/2

  • The gRPC clients keep a response that the server sends before it reads the request message, for example an authorization challenge. Before, the client could lose that response.
  • After a complete response, the gRPC server resets a stream with the code NO_ERROR when the request did not end. Before, it sent CANCEL.
  • http2.Connection.Stream.stopWaits stops the waits on a stream without a reset, because Zig 0.16.0 can lose a cancel. The gRPC server uses it to stop the task that watches a stream for a reset. The channels reset the stream of a call with client.CallStream.
  • Stream.cancel wakes each task that waits on the stream.
  • The connection frees a peer stream that it refuses for its headers. The HPACK decoder reads the whole header block after a size error, thus the dynamic tables of the two peers stay the same.
  • A server connection ignores a header block on a peer stream that it reset, for the last 64 such streams (remembered_resets). Before, such a block ended the connection.
  • The reset for an oversized header block cannot stop the connection. Before, the read task held the connection lock while it waited for the write lock.
  • A stream that gets a cancel before its headers go out gets no id and sends no headers. Before, the server kept such a stream open until the connection ended.

See Transport gRPC.

Tests

  • util.loopback.connect and util.loopback.listen make at most five tries when an error can go away. On Windows, Zig 0.16.0 gives some of these errors as error.Unexpected. The tests of the SDK use the functions for their own sockets.

Changes that break the API

  • The method and params arguments of RequestOptions.on_notification and Hooks.on_notification are valid only during the call. A callback that keeps a part of them must copy it.
  • The fields on_notification and userdata of stdio.Client are gone. Use the spawn options with the same names.
  • Over the memory link, the callback of the acknowledgment of a listen stream runs while the server holds the lock of the stream. The callback must not publish an event of the same server.
  • sse.Parser.feed returns sse.Parser.FeedError with the new error error.EventTooLarge.

0.3.0 (2026-09-30)

A minor release with fixes for the limits of release 0.2.0. It removes two fields of mcp.Limits, thus it changes the public API. It supports MCP specification revision 2026-07-28 only, on Zig 0.16.0. The file CHANGELOG.md has the full list. The tag is v0.3.0.

  • The Streamable HTTP server obeys http.head_timeout and http.idle_timeout. A slow client cannot keep a connection without end.
  • At a shutdown, the HTTP server closes a connection that waits for a request at once. It does not wait for the peer.
  • The servers of all transports check json_max_depth before the parse. A deeper message gets -32700.
  • The server checks max_filter_bytes for a subscriptions/listen filter.
  • The client obeys listen_ack_timeout on all transports. The field moved from http to the top level of mcp.Limits.
  • The HTTP client gives each SSE event to the request when its bytes arrive. Before, an event waited for the next bytes.
  • The HTTP/2 connection of the gRPC transport answers a frame that is too large with FRAME_SIZE_ERROR.
  • Removed: Limits.cancel_notify_timeout and Limits.max_step_up_attempts. Each authorization client keeps its own option max_step_up_attempts.

See Limits and Security.

0.2.0 (2026-09-30)

The second release. It supports MCP specification revision 2026-07-28 only, on Zig 0.16.0. It has the work of milestones M10 to M12. The file CHANGELOG.md has the full list. The tag is v0.2.0.

Transports

  • The Unix socket transport, with a private directory and an owner-only socket file on POSIX and on Windows. See Transport Unix Socket.
  • The WebSocket transport on RFC 6455 connections with the subprotocol mcp. See Transport WebSocket.
  • The typed gRPC binding of the Google Cloud proto files, next to the JSON-RPC tunnel. See Transport gRPC.
  • Rate limits for each caller: tool calls and log messages. See Limits and Security.

TLS

  • RSA and RSA-PSS certificate keys, and the hybrid key exchange X25519MLKEM768 as the first choice.
  • The AEGIS cipher suites as an option, and record padding.
  • The certificate_authorities extension, name constraints, revocation with CRLs and OCSP stapling, and the check of the extended key usage.
  • The fixes of the internal security review. The file docs/security/tls-review.md lists them.

See TLS and Certificates.

Authorization

  • The authorization extensions: client credentials, enterprise-managed authorization, DPoP-bound tokens and workload identity federation.
  • Refresh tokens, and the token storage in memory, in encrypted files or in the keychain of the host.
  • An OAuth 2.1 authorization server. See Authorization Server.

See Authorization.

Protocol, client and server

  • All keywords of JSON Schema 2020-12, with a regular expression engine that runs in linear time.
  • The Skills extension and the MCP Apps extension. See Skills Extension and Apps Extension.
  • Client icon rules, default request timeouts and more checks of the client and of the server.

Tests and CI

  • The requirement matrix maps each normative sentence of the specification to a test or a reason. See Conformance.
  • The CI job conformance also gates the scenarios that the suite does not score, and runs the authorization server scenarios.
  • Interoperability jobs for WebSocket and for the typed gRPC binding. See Interoperability.
  • The documentation site: zig build site builds a first page and the API reference of the modules mcp and mcp_grpc. The workflow docs.yml deploys it to GitHub Pages.
  • zig build lint-docs has the warning rules of the project profile and runs in strict mode. See Style Guide (STE).
  • The new build steps site, extract-requirements, spec-matrix and conformance-authorization-server.

Changes that break the API

  • tls.verify.verifyChain takes (certs, trust, ChainOptions).
  • mcp.tls.PrivateKey.publicKeyBytes takes a larger buffer.
  • Registration.pre_registered of OAuthClient is a list of credentials, each bound to an issuer.

Fixes

  • Five defects gave a peer a way to stop the process or to access memory out of bounds. The defects were in the TLS record layer, the TLS message parsers, the HPACK decoder, the grpc-timeout parser and the JWT time claims. The fuzz job found three of them.
  • The HTTP/1.1 client, the WebSocket client and the authorization fetcher refuse control characters in a request head.
  • The TLS chain validation checks the extended key usage and the basic constraints of each intermediate. The client compares the host name only with the subject alternative names.

0.1.0 (2026-09-30)

The first release. It supports MCP specification revision 2026-07-28 only, on Zig 0.16.0. The tag is v0.1.0.

Protocol and server

  • Protocol types for revision 2026-07-28, and the JSON-RPC envelope with its parser and writers.
  • The server engine: tools, resources, resource templates, prompts, completion, pagination, multi round-trip requests and subscriptions. See Server Guide and Resource Templates.
  • The SDK derives the JSON Schema of a tool from a Zig type at compile time.
  • A JSON Schema 2020-12 validator for a subset of the keywords. The server checks tool arguments against the input schema and structured output against the output schema. See JSON Schema Support.

Transports

  • The stdio transport for servers and clients. The client manages the server process with process groups on POSIX and a job object on Windows. It stops the server with SIGTERM and then SIGKILL, and it can start the server again with max_restarts. See Transport stdio.
  • The Streamable HTTP transport for servers and clients, with SSE responses and header mirroring. The client runs on an HTTP/1.1 connection of the SDK. See Transport Streamable HTTP.
  • The gRPC transport in the module mcp_grpc: a JSON-RPC tunnel over HTTP/2 with its own protobuf format, HPACK, HTTP/2 connection and gRPC layers. Metadata mirrors the HTTP headers. An error before the first message travels in the trailers. See Transport gRPC.
  • An in-memory link for tests.

TLS

  • A TLS 1.3 server in the SDK with ECDSA P-256, P-384 and Ed25519 certificates. It supports the key exchange groups X25519, P-256 and P-384, HelloRetryRequest, ALPN and server name indication. The HTTP transport serves HTTPS with the tls option.
  • A TLS 1.3 client in the SDK. It verifies the chain against a CA set, the std bundle, a pinned leaf or a self-signed policy. It checks the host name or the IP address, the CA constraints and ALPN, and it can send a client certificate. The server can ask for client certificates.
  • A precheck rejects malformed peer certificates before the std parser reads them. The first fuzz run found that the std parser reads out of bounds on a certificate that is too short.

See TLS and Certificates.

Client

  • mcp.Client with typed requests, progress and log callbacks, and the multi round-trip driver with application hooks.
  • A result cache: Client.Options.cache and RequestOptions.cache_mode. The client uses a result with a positive ttlMs again until it expires, until a list-changed notification arrives, or until invalidateCache runs.
  • The client sends a request again when it lost the stream before a response byte: RequestOptions.retry with auto, never or force, up to limits.max_lost_stream_retries.

See Client Guide.

Authorization

  • An OAuth 2.1 client. It discovers the protected resource metadata and the authorization server metadata, and it has three registration methods. It uses PKCE S256, resource indicators and iss validation. It selects the scope with step-up limits and keeps credentials per issuer. The HTTP client transport answers 401 and 403 challenges with it.
  • Helpers for resource servers: the protected resource metadata, bearer token checks with WWW-Authenticate challenges, and JWT verification with HS256, ES256, RS256 and PS256. The request context has the principal. The HTTP server uses them with the auth option.

See Authorization.

Tasks extension

  • Servers: the tasks option, task_support for each tool, the .start_task outcome, tasks/get, tasks/update and tasks/cancel, input requests inside a task, cancellation and the -32021 gate.
  • Clients: callTool waits for a task and answers its input requests with the hooks. callToolOrTask, getTask, updateTask, cancelTask and awaitTask give full control. The HTTP client mirrors the task id into Mcp-Name.

See Tasks Extension.

Tools, tests and CI

  • The build steps test, fmt, examples, docs, lint-docs, census, commit-policy, conformance-server, conformance-client, gen-bibliography, gen-dictionary, bench, check-version and changelog-section.
  • A conformance fixture server and a CI job that runs the official conformance suite. The fixture server also serves gRPC. The CI job grpc-interop calls it from a Node http2 peer and from curl. See Conformance and Interoperability.
  • Benchmarks for the request dispatch, HPACK decoding and the TLS handshake, with a baseline and a nightly smoke run.
  • Fuzz targets for every parser. The nightly workflow runs them.
  • CI with its own Zig installation step, a consumer build through b.dependency, a nightly workflow and a release workflow. The release workflow verifies the signed tag and publishes the section of the changelog.

References

  1. KEEPACHANGELOG: "Keep a Changelog" 1.1.0.
  2. GH-RELEASE-NOTES: Release notes on GitHub.
⚠️ **GitHub.com Fallback** ⚠️