AI Agents

  • Fixed

    • muster test: two races of the harness under --parallel 50, both seen once in CI on 2026-09-15. test_restart_mock_oauth_server listened again on the port the old server had just released, and any socket on the host could take it in between – the mocks listen on kernel-assigned ephemeral ports, the range every outgoing connection draws from (failed to listen again on port 45841: bind: address already in use). The mock now keeps its socket bound across the restart and replaces only the server behind it, as a Service keeps its address while the pod is replaced. And a step whose call to muster serve never returns (a wait_for_state poll still pending when its budget ran out; oauth-subject-grant-refresh failed that way with an instance that kept logging and a harness that kept finishing other scenarios) is reported as stalled instead of “expectations not met”, and the runner records where everything was: muster serve gets SIGQUIT so its goroutines end the instance stderr of the report, the harness’s goroutines are stored as harness_goroutines, and the failure line points at both. The harness also runs the muster binary it is part of before consulting PATH: a stale go install first on PATH ran the suite against the wrong muster serve.
  • Fixed

    • go install github.com/giantswarm/muster/v5@latest builds the release it resolves to. Go refuses go install <package>@<version> for a module whose go.mod carries a replace directive, and go.mod carried one since 2026-08-28: goldmark pinned to a fixed version for the nancy scan, because golang.org/x/tools required a version OSS Index flagged (#1106). Nothing in the build reaches x/tools or goldmark anymore (go mod why -m github.com/yuin/goldmark: the main module does not need it; neither is among the packages go list -deps ./... hands to nancy), so the pin changed nothing but the go install verdict and is gone. The module graph is unchanged.
  • Changed

    • The Go module is github.com/giantswarm/muster/v5; every import path carries the suffix (github.com/giantswarm/muster/v5/pkg/oauth). The module path had no /v5 while the releases were v5.x, and Go only considers v0 and v1 tags for such a path: go install github.com/giantswarm/muster@latest resolved to v1.12.0 from August and installed a month-old v1 binary, and go install github.com/giantswarm/muster@v5.23.2 was refused (“module contains a go.mod file, so module path must match major version”). go install github.com/giantswarm/muster/v5@latest now resolves to the newest release, and Go’s own VCS stamping gives a build of a tagged commit its v5 tag instead of a pseudo-version of the last v1 tag. No repository outside this one imported the old path. The goimports -local prefix of the pre-commit hook and the contributor docs follow the module. The OpenTelemetry scope name github.com/giantswarm/muster (observability.TracerName, the otel_scope_name label, the logger scope) is an identifier dashboards filter on, not an import path, and is unchanged.
  • Fixed

    • The release binaries report their release tag again. muster version on the v5.22.0 binary printed v1.12.1-0.20260915144925-e6c760a32b48: the CI build stamped the commit and the build time but no version, so the binary fell back to the version Go’s own VCS stamping had derived – and as the module path is github.com/giantswarm/muster with no /v5 suffix, Go only considers v0 and v1 tags and turned every v5 release commit into a pseudo-version of the last v1 tag. Because that version is older than every release, muster self-update re-installed the very release it was running on each time instead of reporting “Current version is the latest.” The build now links the tag into the binary (make stamp-version, run by make test between the architect orb writing its link flags and linking with them; a branch build gets git describe, e.g. v5.23.2-1-g4be8379e), a pseudo-version from the build info is no longer shown as the version, and self-update refuses a version that is not a release (dev, a bare commit) instead of panicking on it. (#1256)
  • Added

    • Homebrew: the release pipeline tells the tap giantswarm/homebrew-muster about a release once its binaries are on the GitHub Release (a muster-release repository dispatch from .circleci/custom.yml); the tap’s workflow verifies every binary against its Sigstore bundle before it regenerates the formula. brew install giantswarm/muster/muster follows each release again; the tap had been stuck at v0.7.5 since June.
  • Fixed

    • muster list tool --server <name> finds the tools of an aggregated server. The flag matched the name against the start of the exposed tool name, which for a server registered as files is x_files_<tool>, so --server files printed “No tools found” for every aggregated server, and no spelling at all selected a server whose toolPrefix differs from its name. --server now matches the server a tool belongs to as list_tools reports it (files, core, workflow), independent of the tool prefix, and accepts the exposed prefix (x_files) as well; -o wide and -o json show that server instead of the first name segment (x). (#1248)
  • Changed

    • The Substrate line moves to v0.0.30-gs.2: the worker pool can be spread over nodes and zones (giantswarm/agent-platform#472, second half; the carried patch giantswarm/giantswarm#37797, #37742 row 46). v0.0.30-gs.2 is the first release whose WorkerPool CRD carries spec.template.topologySpreadConstraints (an atomic list of at most 8) and spec.template.podAntiAffinity, mapped onto the worker pods next to nodeAffinity; every release before it pruned both at admission. components.substrate / components.substrate-crds move to >=0.0.30-gs.2 <0.0.31-0 and agent-platform.substrate.workerPoolSpreadFloor names the release, so the render guard of 4.20.0 now forwards kagent.substrateWorkerPool.template.topologySpreadConstraints / podAntiAffinity verbatim to the kagent release and the WorkerPool, and refuses them — naming the key, the floor and the range — only on an installation whose Substrate range floor is pinned below it. The worker image the kagent chart stamps stays ateom-gvisor:0.0.30-gs.1 (kagent 0.11.0-gs.14 on) and runs under the gs.2 control plane: the release changes ate-controller, the CRD and ate-api only, so the Substrate pin and the kagent pin part ways for the first time (values.yaml says when they move together: a re-pin that changes the runtime). The release also carries giantswarm/substrate#35 (a paused actor’s resume fails fast when its node is gone, LOCAL_SNAPSHOT_GONE, #37742 row 44a). The example BOM, tests/verify-components.py and make verify-workerpool follow the pin: the spread now reaches the kagent release at the floor and is refused below it, the two branches the test exercised with a temporary floor before. Every installation with kagent on rolls the Substrate control plane once (the CRDs gain the two fields, ate-api-server / ate-controller / atenet / atelet restart); the worker pods, the WorkerPool template and the goldens are untouched — UPGRADE.md.
  • Added

    • muster test: the mock OAuth server takes the profile of a real authorization server. mock_oauth_servers[].profile: github | dex | pro bundles that server’s quirks instead of one flag per bug (omit_resource_metadata, omit_token_scope, pin_authorization_server, pin_endpoints_ref, authorize_accepts_any_client, …; the flags stay and each overrides the profile for itself). github: no RFC 8414 discovery document, no Client ID Metadata Documents and no RFC 7591 registration (a pre-registered client only), scope and expires_in absent from token responses; the MCP servers that reference it answer a bare 401 without RFC 9728 metadata, file their grants under the person and are pinned to it with explicit endpoints. dex: discovery, scope omitted, an id_token with every token, RFC 7591 registration. pro (the MCP TypeScript SDK’s authorization server): discovery, registration without registration_client_uri, a client it does not know answered directly at /authorize with invalid_client, the token endpoint refusing unregistered clients, registrations held in memory. Without a profile the mock now hands out the RFC 7592 pair (registration_client_uri, registration_access_token) and answers the client read, so muster’s spec-defined registration check runs against the well-behaved default and its authorization-endpoint probe against pro. test_restart_mock_oauth_server replaces a mock authorization server’s process behind its port and issuer; under pro the registrations go with the old process. The scenarios that reproduce a named server’s bug carry its profile and fail on the release that had the bug: a server’s grant surviving the login id_token mirror on a Dex (fails on v5.12.0, #1174), a registration a pro restart forgot detected and made again (fails on v5.7.8, #1128), a pinned bare-401 GitHub-style server connectable after a muster restart with no login in the new process (fails on v5.8.3, #1150). Documented in “Authorization-server profiles” of docs/contributing/testing/oauth-testing.md. (#1239)
  • Added

    • Documentation site. docs/ is built with MkDocs (Material) and published at https://giantswarm.github.io/muster/ by the Pages workflow; the site kept serving muster-agent.json, the muster agent’s OAuth client metadata document, at its URL. A pull request that touches the documentation builds the site in strict mode, so a broken link, a page missing from the navigation or an unknown anchor fails the check. make docs-serve renders the site locally.
    • The CLI reference is generated from the command tree. make generate-cli-docs renders docs/reference/cli/ from the Cobra commands (hack/gen-cli-docs); make verify-cli-docs, part of make test, fails when the committed pages are stale. The hand-written pages, which documented flags that never existed (--port, --mcp-port) and a REST API, are gone.

    Changed

    • README and documentation reworked. The README describes muster as it is today: an aggregating MCP server with meta-tool discovery, toolsets, OAuth 2.1 protection and single sign-on through Dex, MCPServer and Workflow custom resources, workflows and observability; installation is from the signed release binaries, go install or the Helm chart in the Giant Swarm catalog. The documentation lost its duplicated getting-started and IDE pages, the invented REST API, service resources, create service, port 8080 and Homebrew instructions, and gained a quick start whose every command is verified, a tutorial for servers and workflows, guides for connecting MCP clients and authenticating the CLI, an installation guide for the chart with Dex and Valkey, an HTTP endpoints reference including the admin listener, and a rewritten contributing guide. The product is spelled muster throughout. muster --help and muster serve --help describe the current product instead of a Giant Swarm port-forwarding helper.

    Fixed

    • muster start workflow <name> no longer passes the CLI’s own flags on as workflow input. --endpoint, --auth, --context, --config-path, --debug and the output flags given after the workflow name reached the workflow engine as arguments, were recorded in the WorkflowExecution (auth: none, endpoint: http://...) and would have collided with a workflow argument of the same name. muster start workflow and muster call now tell their own flags apart through cobra’s flag set – one grammar for both, no hand-kept list to drift – and forward every other --key=value pair. After -- every pair is forwarded as it is, so a workflow or tool argument named like a CLI flag can be passed against a non-default muster: muster start workflow w --endpoint http://muster:8090/mcp -- --endpoint=https://target. muster call did not leak the flags but discarded everything after --. (#1249)
  • Changed

    • (deps) Update gsoci.azurecr.io/giantswarm/agent-manager docker tag to v1.1.7 in #474 by @renovate[bot]

    Full Changelog: https://github.com/giantswarm/agent-platform/compare/v4.20.0...v4.20.1