Skip to content

feat(go-adk): opt-in for forwarded/STS token to override static Authorization#2044

Closed
QuentinBisson wants to merge 1 commit into
kagent-dev:mainfrom
QuentinBisson:feat/forwarded-token-overrides-static-headers
Closed

feat(go-adk): opt-in for forwarded/STS token to override static Authorization#2044
QuentinBisson wants to merge 1 commit into
kagent-dev:mainfrom
QuentinBisson:feat/forwarded-token-overrides-static-headers

Conversation

@QuentinBisson

Copy link
Copy Markdown
Contributor

Problem

Static headers configured on an MCP server (RemoteMCPServer.headersFrom) are applied at the highest precedence in headerRoundTripper — they override an Authorization forwarded via KAGENT_PROPAGATE_TOKEN or minted by the STS plugin (go/adk/pkg/mcp/registry.go).

This is intentional today (guarded by TestStaticHeaders_OverrideDynamic), but it breaks a common gateway topology:

  • The controller discovers a remote MCP server's tools using RemoteMCPServer.headersFrom (an M2M / service-account token) — the gateway requires auth to list tools.
  • The agent, at call time, should forward the end-user token so the gateway can impersonate/forward the user identity downstream.

Because the static M2M Authorization wins, the agent always sends the M2M token on tool calls and the end-user token never reaches the gateway. Enabling KAGENT_PROPAGATE_TOKEN or STS has no effect when the server also carries a static Authorization.

Change

Add KAGENT_PROPAGATE_TOKEN_OVERRIDES_STATIC (default false). When set, static headers are applied first as defaults and the forwarded/STS Authorization is applied last, so:

  • a propagated / STS-exchanged Authorization wins over a static one,
  • other static headers still apply,
  • the static Authorization is still used as a fallback when no token is forwarded (e.g. autonomous runs).

Default behaviour is unchanged — existing precedence tests stay green.

Tests

  • TestOverrideStatic_PropagatedTokenWinsOverStatic
  • TestOverrideStatic_StaticAppliesWhenNoForwardedToken
  • existing precedence tests unchanged.

Follow-up

Go runtime only. Python runtime (agentsts) parity can follow if this direction is acceptable; a per-server CRD field is a possible future refinement over the env var.

…rization

Static headers configured on an MCP server (RemoteMCPServer.headersFrom) are
applied at the highest precedence, so they override an Authorization forwarded
via KAGENT_PROPAGATE_TOKEN or minted by the STS plugin. This breaks gateway
topologies where a static M2M token is needed for controller-side tool
discovery but the per-call request must carry the end-user token.

Add KAGENT_PROPAGATE_TOKEN_OVERRIDES_STATIC (default false). When set, static
headers are applied first as defaults and the forwarded/STS Authorization is
applied last, so the propagated token wins while other static headers and the
no-token fallback are preserved. Default behaviour is unchanged.
@github-actions github-actions Bot added the enhancement New feature or request label Jun 18, 2026
QuentinBisson added a commit to giantswarm/agentic-platform that referenced this pull request Jun 18, 2026
Document why the header-less muster-user server is needed for now: kagent
applies a RemoteMCPServer's static Authorization at highest precedence, so a
single muster server cannot both list tools M2M (controller) and forward the
end-user token (agent calls). Note the agent tool ref allowedHeaders option and
that this collapses back to one server once kagent-dev/kagent#2044 ships.
QuentinBisson added a commit to giantswarm/agentic-platform that referenced this pull request Jun 18, 2026
…-token propagation (#136)

* feat(kagent): add opt-in header-less muster-user RemoteMCPServer for user-token propagation

The default `muster` RemoteMCPServer pins a static Authorization header from
the SA token Secret. kagent's MCP transport applies static headers at highest
precedence, so it overrides any token the agent runtime forwards
(KAGENT_PROPAGATE_TOKEN / STS OBO). RemoteMCPServer has no per-server
header-forwarding field, so static-token and user-token modes cannot coexist
on one server.

Add an opt-in companion `muster-user` server with no static header, gated on
`agents.muster.userServer.enabled` (default false). Human-triggered agents
reference it and supply the end-user token via their spec.deployment.env; the
static-token `muster` server is unchanged for autonomous/M2M agents.

* docs(kagent): explain muster-user workaround and link upstream fix

Document why the header-less muster-user server is needed for now: kagent
applies a RemoteMCPServer's static Authorization at highest precedence, so a
single muster server cannot both list tools M2M (controller) and forward the
end-user token (agent calls). Note the agent tool ref allowedHeaders option and
that this collapses back to one server once kagent-dev/kagent#2044 ships.
QuentinBisson added a commit to giantswarm/agentic-platform that referenced this pull request Jun 21, 2026
…#159)

Add an opt-in Declarative kagent Agent (sre-agent) that reaches muster
machine-to-machine through the single static `muster` RemoteMCPServer
(kagent-muster-client SA token). deployment lives under
spec.declarative.deployment (v1alpha2); serviceAccountName is omitted so
the controller auto-creates the sre-agent SA. allowedHeaders is wired but
inert: user-token forwarding also needs kagent-dev/kagent#2044, absent
from the pinned kagent 0.9.9.

Remove agents.muster.userServer and the header-less muster-user
RemoteMCPServer: on 0.9.9 it lists zero tools (no static Authorization
for controller discovery) and #2044 is absent, so it cannot impersonate
the end user. User impersonation returns once kagent ships #2044 and
muster carries the human identity.

Mirror the values change in the agentic-platform meta-package
(forwardAllValues feeds the connectivity release).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant