Skip to content

v1.10.2

Released on 2026-05-31 - GitHub Release

mcp — Opt-in HTTP request metadata bridge for tool handlers (#5550)

Section titled “mcp — Opt-in HTTP request metadata bridge for tool handlers (#5550)”

Added WithRequestMetadataExtractor option to the MCP server. When set, HTTP request metadata (headers, query parameters, path variables) is captured and injected into each handler’s context.Context. Handlers retrieve it via the provided context helpers:

server := mcp.NewMcpServer(conf, mcp.WithRequestMetadataExtractor(mcp.DefaultRequestMetadataExtractor))
server.AddTool(tool, func(ctx context.Context, req *mcp.ServerRequest) (*mcp.ToolResult, error) {
tenantID, _ := mcp.HeaderFromContext(ctx, "X-Tenant-ID")
userID, _ := mcp.QueryFromContext(ctx, "user_id")
// ...
})

Available helpers: RequestMetadataFromContext, HeaderFromContext, QueryFromContext, PathFromContext. Fully backward-compatible — existing NewMcpServer(c) calls are unaffected.

Go 1.26 enforces strict RFC 3986 URI parsing and rejects comma-separated hosts in the URI authority component. BuildDiscovTarget was producing URIs in the form etcd://host1:2379,host2:2379/key, which broke all gRPC services using etcd service discovery with multiple endpoints on Go 1.26+.

The etcd target URL format has been updated to place hosts in the path and the etcd key in a query parameter:

# Before (breaks Go 1.26):
etcd://host1:2379,host2:2379/my-service-key
# After (RFC 3986 compliant, works on all Go versions):
etcd:///host1:2379,host2:2379?key=my-service-key

discov — Unbounded memory growth on duplicate etcd PUT events (#5580)

Section titled “discov — Unbounded memory growth on duplicate etcd PUT events (#5580)”

Fixed two related bugs in discov that caused memory to grow without bound in long-running zRPC services:

  • Redundant OnAdd calls: handleWatchEvents called OnAdd on every etcd PUT event regardless of whether the value changed (e.g. lease refreshes, watch reconnects). Duplicate PUTs are now skipped; value changes fire OnDelete(old) followed by OnAdd(new) to keep listeners consistent.
  • Unbounded slice growth in addKv: Keys were appended to the internal container.values slice unconditionally, causing a single etcd key to accumulate thousands of duplicates over time. addKv now returns early for exact duplicates, and cleans up stale entries when a key moves to a new server address.

Full Changelog: https://github.com/zeromicro/go-zero/compare/v1.10.1…v1.10.2