entra id · sts token exchange · mcp url-mode elicitation

Log in, authorize, inject — without the MCP server ever seeing the secret.

Goose uses Microsoft Entra ID for Solo UI / kagent login, and AgentGateway Enterprise STS for per-user credential forwarding (elicitations). This page is the lab cheat-sheet: accounts, URLs, and a repeatable test path for /github-elicit.

sebastian@maniak.io Entra admin /github-elicit STS path /github shared PAT still works lab OAuth stub not real GitHub consent

#User accounts

Autoauth is off. The Solo UI (AgentGateway and kagent tabs) redirects to Microsoft Entra ID (tenant maniak.io).

Login

Use your Entra account sebastian@maniak.io (member of security group kagent-admin → RBAC global.Admin). Prefer HTTPS :30443 if Entra redirects require it.

Solo UI · AgentGateway · kagent

WhatURLIdentityRole
Solo UI (login) http://172.16.10.155:30854 · HTTPS :30443 sebastian@maniak.io (Entra) Admin (kagent-adminglobal.Admin)
AgentGateway product …/age/ same session full AGE UI
Elicitations view …/age/elicitations/ same session authorize pending OAuth
kagent product …/ same session shared frontend

Entra apps (OIDC)

AppTypeUsed by
goose-solo-ui-frontendSPA + PKCESolo UI frontend
goose-solo-ui-backendConfidentialUI backend · middle-tier JWT for scripts / OBO
AgentGateway-MCP-SSOApp roles/mcp-secure · Mcp.Admin / Mcp.User
Bootstrap Entra

UI + MCP SSO apps: ./scripts/configure-entra.sh

Graph OBO client secret / consent: ./scripts/configure-entra-obo.sh

#What elicitations are (here)

Not a chat form. In Solo Enterprise for AgentGateway, URL-mode elicitation is per-user OAuth credential forwarding via the Security Token Service (STS).

1 · request
Client + Entra JWT hits MCP
2 · miss
STS has no upstream token
3 · 500
Return UI elicitations URL
4 · browser
User authorizes OAuth
5 · store
STS keeps access token
6 · retry
Proxy injects Bearer upstream

The MCP server never runs the OAuth dance. It only sees a normal request with a token already in Authorization. Credentials never transit the MCP client/server path.

Shared PAT (unchanged)

virtual-mcp-gateway

http://172.16.10.155:31606/github

Static PAT from Vault → github-mcp-token. Good for kagent github-agent.

Elicitation path

agentgateway-elicit · STS

http://172.16.10.155:<nodePort>/github-elicit

Dedicated Gateway with STS_URI=…/elicitations/oauth2/token (so OBO on :30160 stays intact). Script auto-discovers NodePort.

Lab OAuth stub

NodePort 30881

Stands in for a real GitHub OAuth App. After “Authorize”, STS receives the cluster PAT so MCP still works.

#How to test elicitations

Four steps: log into the UI, trigger a miss, authorize, retry.

1

Log into Solo UI (Entra)

Open http://172.16.10.155:30854 → Microsoft Entra as sebastian@maniak.io. Confirm you can open /age/elicitations/.

2

Trigger a token-exchange miss

From a machine on the lab LAN (with az login as the same Entra user), run the helper. It mints a middle-tier Entra JWT and POSTs MCP initialize to /github-elicit on the agentgateway-elicit NodePort (auto-discovered):

scripts/test-elicitation.sh
az login --tenant 8635e970-2205-4189-bc77-77519ff5064f
./scripts/test-elicitation.sh

Or the equivalent curl (resolve NodePort first):

trigger-elicit.sh
# 1) Entra JWT (middle-tier audience)
export USER_TOKEN=$(az account get-access-token \
  --tenant 8635e970-2205-4189-bc77-77519ff5064f \
  --resource api://0c00f6d2-5587-469d-9d35-7360d878fddc \
  --query accessToken -o tsv)

# 2) NodePort for agentgateway-elicit (not :30160 — that is OBO/oauth2/token)
export NP=$(kubectl --context maniak-goose -n agentgateway-system \
  get svc agentgateway-elicit -o jsonpath='{.spec.ports[0].nodePort}')

# 3) MCP initialize — expect 500 + elicitations URL on first call
curl -sS -i -X POST "http://172.16.10.155:${NP}/github-elicit" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H 'mcp-protocol-version: 2025-06-18' \
  -H "Authorization: Bearer $USER_TOKEN" \
  -d '{
    "jsonrpc":"2.0","id":1,"method":"initialize",
    "params":{
      "protocolVersion":"2025-06-18",
      "capabilities":{},
      "clientInfo":{"name":"elicit-demo","version":"1.0"}
    }
  }'

Expected (first call): HTTP 500 and a body like:

expected.json
HTTP/1.1 500
TokenExchangeInfo { url: Some("http://172.16.10.155:30854/age/elicitations"), ... }
3

Authorize in the UI

Open http://172.16.10.155:30854/age/elicitations/ (still logged in via Entra). Find the pending elicitation → Authorize.

You’ll hit the lab OAuth stub consent page at :30881 (not real GitHub). Click Continue / Authorize. You should bounce back to the elicitations view as completed.

4

Retry — MCP should succeed

Re-run the same script/curl. STS now has a per-user token; the proxy injects it and initialize should return GitHub MCP serverInfo / protocol result.

retry
./scripts/test-elicitation.sh

#Component map

PieceWhereNotes
Entra IdPlogin.microsoftonline.comUI + STS subject/api validators (JWKS)
Solo UI OIDCargocd/apps/solo-ui.yamlEntra issuer (autoauth off)
STScontrol plane :7777tokenExchange.enabled on enterprise-agentgateway
OBO / impersonation STSagentgateway-proxy-paramsSTS_URI=…/oauth2/token · NodePort 30160
Elicitation STS clientagentgateway-elicit-paramsSTS_URI=…/elicitations/oauth2/token
OAuth provider secretelicitation-oidclab stub URLs + client id/secret
OAuth stubNodePort 30881returns existing PAT as access_token
Backend + policygithub-mcp-elicitno static PAT; elicitation injects
Route/github-elicit on agentgateway-elicitNodePort auto (script discovers)

#Ops & gotchas

Quick health checks
health.sh
# Entra token (middle-tier) — requires az login
az account get-access-token \
  --tenant 8635e970-2205-4189-bc77-77519ff5064f \
  --resource api://0c00f6d2-5587-469d-9d35-7360d878fddc \
  --query accessToken -o tsv | wc -c

# Elicit Gateway + NodePort
kubectl --context maniak-goose -n agentgateway-system get gateway,svc agentgateway-elicit

# STS port on control plane
kubectl --context maniak-goose -n agentgateway-system get svc enterprise-agentgateway

# Policy accepted
kubectl --context maniak-goose get eagpol github-mcp-elicit-policy -n agentgateway-system