Repository navigation
feat(http): send x-mcp-user-id header with the caller's DGC user UUID - #164
charlie-ang-collibra wants to merge 3 commits into
Conversation
Resolve the caller's DGC user UUID via GET /rest/2.0/users/current, cached per credential for 10 minutes in a bounded LRU cache, and send it as x-mcp-user-id. Failed lookups are cached too and leave the header off. The TASK_BRIEF file was not present in the workspace; the acceptance criteria were used as the specification. Co-authored-by: betty-pr-factory-app[bot] <316249552+betty-pr-factory-app[bot]@users.noreply.github.com>
|
This pull request was created by the BETTY PR Factory App GitHub App on behalf of charlie-ang-collibra, through PESTO engineer git delegation. PESTO run: The commits and the pull request are authored by the engineer's own GitHub account; the App's involvement is recorded by this comment, by the |
charlie-ang-collibra
left a comment
There was a problem hiding this comment.
Review: DEV-233767 send x-mcp-user-id header to DGC
The task brief wasn't in the workspace, so I reviewed against the acceptance criteria stated in the commit message and docs/CONFIG.md, plus docs/TOOL_CONTRIBUTION_STANDARDS.md. This change adds no MCP tool, so most of the standards don't apply. It follows 8.1 (public /rest/2.0/users/current), and the stepdown ordering is followed.
Verification: go build ./..., go vet ./cmd/... and golangci-lint run ./cmd/... (0 issues) are clean. go test ./cmd/chip/ passes, and the new tests pass 20 times in a row (-count=20). Every criterion has a test: lookup sharing, per-credential caching, TTL, LRU eviction, failure modes, no-auth, and inbound header stripping. (-count>1 on the whole package panics in the existing TestDataQualityConfigPrecedence with flag redefined: api-url. This PR didn't cause it.)
Findings (none block the merge):
- Transient failures turn the header off for 10 min.
user_id.goresolvecaches timeouts and 5xx the same way as a success. If that's intended, fine. Otherwise consider a shorter error TTL, or caching only 401/403. - The first call per credential can take up to 10s longer (
userIDLookupTimeout), and so can its concurrent callers. The header only serves attribution, so a shorter timeout would cap the cost. Worth mentioning in the impact analysis. - No test covers the configured
Api.Username/Passwordpath. In that case the lookup runs as the service account. clients.GetCurrentUseralready calls/users/current. Using it here would recurse back through this transport, so going direct is fine; add a one-line comment saying why.- CONFIG.md's opening line says every request carries the header. The bullets below list the exceptions, so reword the opening to match.
- A panic in
next.RoundTripwould skipcompleteand leave waiters blocked.deferthe completion to close this off (low risk).
Shorten the lookup timeout to 2s, release waiters if a lookup panics, explain why clients.GetCurrentUser is not reused, test server-wide credentials and reword the CONFIG.md section. Failure caching for 10 minutes is kept as required by the acceptance criteria. Co-authored-by: betty-pr-factory-app[bot] <316249552+betty-pr-factory-app[bot]@users.noreply.github.com>
charlie-ang-collibra
left a comment
There was a problem hiding this comment.
Runtime validation of PR #164 (collibra/chip): x-mcp-user-id header
What was tested
git rev-parse HEAD=70be0c4ada6ae1735654d46fedb09a5d171e6a2e.git ls-remote origin refs/pull/164/head=70be0c4ada6ae1735654d46fedb09a5d171e6a2e. They match.- PR binary:
go build -o /tmp/v/chip-pr ./cmd/chipat that SHA. Default-branch binary:chip-mainbuilt frommain@791fb15ae0650f9cb8b96511d706773f6c9e37b0(git worktree). - DGC:
http://dgc-gateway.dgc-f8e0ded1c023.svc.cluster.local:4400, taken from provision-envdgcEndpointDetails. It was reachable directly from this pod (GET /rest/2.0/users/currentreturned 200), so no port-forward was needed. The gateway is an nginx (Server: nginx/1.31.8, magneto-managed configmapdgc-gateway). It routes/rest/oauth/v2/*to the auth service and everything else to DGC. - Every chip ran as a customer runs it, with
COLLIBRA_MCP_API_URLset to the URL above. Tools were called with raw MCP JSON-RPCtools/call(list_asset_types,{"limit":1}), with no model in the loop.
How chip's outbound headers were observed
chip has no log-level setting. cmd/chip/config.go has no log-level flag or env var, and the PR adds no debug line that prints x-mcp-user-id. chip's only output is INFO/WARN slog lines, and the PR's only new log line is a WARN when the lookup fails. The "chip debug log line" evidence that AC-2 and AC-7 ask for does not exist and cannot be produced without a code change. I did not change code.
Instead I used chip's existing proxy setting, COLLIBRA_MCP_API_PROXY=http://127.0.0.1:3128, pointed at a small logging HTTP forward proxy I ran locally. Because the target is plain http, the proxy sees every request chip sends upstream, with all headers. Authorization values were masked as a sha256 prefix. The proxy only forwards; it does not change requests.
Credential probe (DGC)
| form | request | result |
|---|---|---|
Basic, stack user Admin |
GET /rest/2.0/users/current |
200, id=00000000-0000-0000-0000-000000900002, userName Admin |
Bearer, grant_type=client_credentials with each global client in secret auth-global-clients-external (microsoft-copilot, databricks, openai) |
POST /rest/oauth/v2/token |
401 invalid_client |
Bearer, grant_type=password (client microsoft-copilot, user Admin) |
POST /rest/oauth/v2/token |
200. JWT uid=00000000-0000-0000-0000-000000900002, sub=urn:usr:env:…:id:…900002, expires_in=299 |
| Bearer from the password grant | GET /rest/2.0/users/current |
200, id=00000000-0000-0000-0000-000000900002 (Admin) |
Register a client_credentials app: POST /rest/oauth/v2/clients (RFC 7591) with Admin's Bearer |
403. I could not mint a client-application token. |
chip runs (all PR build unless noted)
| run | mode | credentials |
|---|---|---|
| port 18080 | http (streamable, stateless) | no server creds; client sends Authorization per request |
| port 18081 | http | server-wide COLLIBRA_MCP_API_USR=Admin / COLLIBRA_MCP_API_PWD=admin |
| port 18082 | http | server-wide Admin / wrongpass |
| port 18083 | http, main build | server-wide Admin / admin |
| stdio | stdio | server-wide Admin / admin |
Every request chip sent upstream (from the logging proxy)
Columns: epoch ts, method, path, DGC status, Authorization (masked), x-mcp-user-id, X-MCP-Tool-Name, traceparent trace-id prefix.
Masked credential keys: fd69ab017215 = Basic Admin:admin, 9fea82925cc0 = Basic pesto-ac4-user2, 381616302245 = Basic Admin:wrongpass, 3f9e3ee6955c = Bearer bogus-token-123, 10a15071e085 = Bearer Admin, 986b11129851 = Bearer user2.
1794593537.216 GET /rest/2.0/assetTypes?excludeMeta=true&limit=1 401 auth=- x-mcp-user-id=<absent> tool=list_asset_types tp=9ca91bf07889
1794593549.600 GET /rest/2.0/assetTypes?excludeMeta=true&limit=1 401 auth=- x-mcp-user-id=<absent> tool=list_asset_types tp=51834a34eb1d
1794593549.637 GET /rest/2.0/users/current 200 auth=Basic <sha256:fd69ab017215> x-mcp-user-id=<absent> tool=- tp=
1794593549.691 GET /rest/2.0/assetTypes?excludeMeta=true&limit=1 200 auth=Basic <sha256:fd69ab017215> x-mcp-user-id=00000000-0000-0000-0000-000000900002 tool=list_asset_types tp=57bd73d3f8d3
1794593549.812 GET /rest/2.0/users/current 200 auth=Basic <sha256:9fea82925cc0> x-mcp-user-id=<absent> tool=- tp=
1794593549.873 GET /rest/2.0/assetTypes?excludeMeta=true&limit=1 200 auth=Basic <sha256:9fea82925cc0> x-mcp-user-id=01a1d61a-8c89-708b-815c-d22dc8becba8 tool=list_asset_types tp=4c59348349c0
1794593549.961 GET /rest/2.0/assetTypes?excludeMeta=true&limit=1 200 auth=Basic <sha256:fd69ab017215> x-mcp-user-id=00000000-0000-0000-0000-000000900002 tool=list_asset_types tp=0dc728c3f5c8
1794593550.054 GET /rest/2.0/assetTypes?excludeMeta=true&limit=1 200 auth=Basic <sha256:9fea82925cc0> x-mcp-user-id=01a1d61a-8c89-708b-815c-d22dc8becba8 tool=list_asset_types tp=e1f03e0ef518
1794593581.420 GET /rest/2.0/users/current 200 auth=Bearer <sha256:10a15071e085> x-mcp-user-id=<absent> tool=- tp=
1794593581.441 GET /rest/2.0/assetTypes?excludeMeta=true&limit=1 200 auth=Bearer <sha256:10a15071e085> x-mcp-user-id=00000000-0000-0000-0000-000000900002 tool=list_asset_types tp=b588fd415ed1
1794593581.535 GET /rest/2.0/assetTypes?excludeMeta=true&limit=1 200 auth=Bearer <sha256:10a15071e085> x-mcp-user-id=00000000-0000-0000-0000-000000900002 tool=list_asset_types tp=595705454676
1794593581.630 GET /rest/2.0/users/current 200 auth=Bearer <sha256:986b11129851> x-mcp-user-id=<absent> tool=- tp=
1794593581.688 GET /rest/2.0/assetTypes?excludeMeta=true&limit=1 200 auth=Bearer <sha256:986b11129851> x-mcp-user-id=01a1d61a-8c89-708b-815c-d22dc8becba8 tool=list_asset_types tp=b620da75405c
1794593581.781 GET /rest/2.0/users/current 401 auth=Bearer <sha256:3f9e3ee6955c> x-mcp-user-id=<absent> tool=- tp=
1794593581.835 GET /rest/2.0/assetTypes?excludeMeta=true&limit=1 401 auth=Bearer <sha256:3f9e3ee6955c> x-mcp-user-id=<absent> tool=list_asset_types tp=2767394a8d2d
1794593581.907 GET /rest/2.0/assetTypes?excludeMeta=true&limit=1 401 auth=Bearer <sha256:3f9e3ee6955c> x-mcp-user-id=<absent> tool=list_asset_types tp=ef27f0d760bb
1794593581.982 GET /rest/2.0/users/current 401 auth=Basic <sha256:381616302245> x-mcp-user-id=<absent> tool=- tp=
1794593582.496 GET /rest/2.0/assetTypes?excludeMeta=true&limit=1 401 auth=Basic <sha256:381616302245> x-mcp-user-id=<absent> tool=list_asset_types tp=1579ef3cd801
1794593583.006 GET /rest/2.0/assetTypes?excludeMeta=true&limit=1 401 auth=Basic <sha256:381616302245> x-mcp-user-id=<absent> tool=list_asset_types tp=a452e9c9734a
1794593597.209 GET /rest/2.0/users/current 200 auth=Basic <sha256:fd69ab017215> x-mcp-user-id=<absent> tool=- tp=
1794593597.252 GET /rest/2.0/assetTypes?excludeMeta=true&limit=1 200 auth=Basic <sha256:fd69ab017215> x-mcp-user-id=00000000-0000-0000-0000-000000900002 tool=list_asset_types tp=1ffee5eefb85
1794593597.335 GET /rest/2.0/assetTypes?excludeMeta=true&limit=1 200 auth=Basic <sha256:fd69ab017215> x-mcp-user-id=00000000-0000-0000-0000-000000900002 tool=list_asset_types tp=d034350843f6
1794593597.417 GET /rest/2.0/assetTypes?excludeMeta=true&limit=1 200 auth=Basic <sha256:fd69ab017215> x-mcp-user-id=<absent> tool=list_asset_types tp=3ec87d99246a
1794593597.460 GET /rest/2.0/users/current 401 auth=Basic <sha256:381616302245> x-mcp-user-id=<absent> tool=- tp=
1794593597.893 GET /rest/2.0/assetTypes?excludeMeta=true&limit=1 401 auth=Basic <sha256:381616302245> x-mcp-user-id=<absent> tool=list_asset_types tp=ac50fa28cf39
1794593598.376 GET /rest/2.0/assetTypes?excludeMeta=true&limit=1 401 auth=Basic <sha256:381616302245> x-mcp-user-id=<absent> tool=list_asset_types tp=fe998916ef16
1794593598.926 GET /rest/2.0/users/current 200 auth=Basic <sha256:fd69ab017215> x-mcp-user-id=<absent> tool=- tp=
1794593598.943 GET /rest/2.0/assetTypes?excludeMeta=true&limit=1 200 auth=Basic <sha256:fd69ab017215> x-mcp-user-id=00000000-0000-0000-0000-000000900002 tool=list_asset_types tp=3bb50fffc4f8
Call markers (label, epoch at which the MCP call started), used to map the rows above to calls:
PROXYMARK probe-noauth 1794593537.207181607
PROXYMARK ac8-noauth-2 1794593549.593049844
PROXYMARK ac4-admin-1 1794593549.631270943
PROXYMARK ac4-user2-1 1794593549.805670531
PROXYMARK ac4-admin-2 1794593549.954463309
PROXYMARK ac4-user2-2 1794593550.047655448
PROXYMARK ac5-bearer-admin-1 1794593581.413122580
PROXYMARK ac5-bearer-admin-2 1794593581.529041449
PROXYMARK ac5-bearer-user2-1 1794593581.622806768
PROXYMARK ac7-bogus-bearer-1 1794593581.774816946
PROXYMARK ac7-bogus-bearer-2 1794593581.900908654
PROXYMARK ac7-http-wrongpw-1 1794593581.975344834
PROXYMARK ac7-http-wrongpw-2 1794593583.000064701
PROXYMARK ac2-sw-pr-1 1794593597.199664615
PROXYMARK ac2-sw-pr-2 1794593597.328402904
PROXYMARK ac6-sw-main-1 1794593597.410003623
PROXYMARK ac7-sw-wrongpw-1 1794593597.452899272
PROXYMARK ac7-sw-wrongpw-2 1794593598.368939691
PROXYMARK ac2-stdio-pr 1794593598.891721314
An example of one full set of upstream headers (the server-wide Basic tool call):
{"Host": "dgc-gateway.dgc-f8e0ded1c023.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Authorization": "Basic <sha256:fd69ab017215>", "Content-Type": "application/json", "Traceparent": "00-57bd73d3f8d34f6cd90c2f052e638eb2-9b5bfc8b33bafe6a-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "X-Mcp-User-Id": "00000000-0000-0000-0000-000000900002", "Accept-Encoding": "gzip"}
The users/current lookup itself carries User-Agent: Collibra MCP/…, but no traceparent, X-MCP-Tool-Name or x-mcp-user-id.
Raw MCP request/response for each call
Each request was POST http://localhost:<port>/ with {"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"list_asset_types","arguments":{"limit":1}}}, plus the Authorization header shown in the proxy table. Responses are trimmed to 330 chars:
### probe-noauth 2026-11-13T18:12:17.236Z port=18080
data: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"HTTP 401: {\"statusCode\":401,\"titleMessage\":\"Unauthorized\",\"helpMessage\":\"Please check the application logs for more information.\",\"userMessage\":\"Failed to authenticate request\",\"errorCode\":\"authenticationFailed\"}"}],"isError":true}}…
### ac8-noauth-2 2026-11-13T18:12:29.617Z port=18080
data: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"HTTP 401: {\"statusCode\":401,\"titleMessage\":\"Unauthorized\",\"helpMessage\":\"Please check the application logs for more information.\",\"userMessage\":\"Failed to authenticate request\",\"errorCode\":\"authenticationFailed\"}"}],"isError":true}}…
### ac4-admin-1 2026-11-13T18:12:29.793Z port=18080
data: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"{\"assetTypes\":[{\"description\":\"An asset type that represents an Azure Data Lake Container, which is a logical unit of storage containing Azure Data Lake Storage objects.\",\"displayNameEnabled\":true,\"finalType\":false,\"id\":\"00000000-0000-0000-0001-0028…
### ac4-user2-1 2026-11-13T18:12:29.942Z port=18080
data: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"{\"assetTypes\":[{\"description\":\"An asset type that represents an Azure Data Lake Container, which is a logical unit of storage containing Azure Data Lake Storage objects.\",\"displayNameEnabled\":true,\"finalType\":false,\"id\":\"00000000-0000-0000-0001-0028…
### ac4-admin-2 2026-11-13T18:12:30.034Z port=18080
data: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"{\"assetTypes\":[{\"description\":\"An asset type that represents an Azure Data Lake Container, which is a logical unit of storage containing Azure Data Lake Storage objects.\",\"displayNameEnabled\":true,\"finalType\":false,\"id\":\"00000000-0000-0000-0001-0028…
### ac4-user2-2 2026-11-13T18:12:30.124Z port=18080
data: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"{\"assetTypes\":[{\"description\":\"An asset type that represents an Azure Data Lake Container, which is a logical unit of storage containing Azure Data Lake Storage objects.\",\"displayNameEnabled\":true,\"finalType\":false,\"id\":\"00000000-0000-0000-0001-0028…
### ac5-bearer-admin-1 2026-11-13T18:13:01.516Z port=18080
data: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"{\"assetTypes\":[{\"description\":\"An asset type that represents an Azure Data Lake Container, which is a logical unit of storage containing Azure Data Lake Storage objects.\",\"displayNameEnabled\":true,\"finalType\":false,\"id\":\"00000000-0000-0000-0001-0028…
### ac5-bearer-admin-2 2026-11-13T18:13:01.609Z port=18080
data: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"{\"assetTypes\":[{\"description\":\"An asset type that represents an Azure Data Lake Container, which is a logical unit of storage containing Azure Data Lake Storage objects.\",\"displayNameEnabled\":true,\"finalType\":false,\"id\":\"00000000-0000-0000-0001-0028…
### ac5-bearer-user2-1 2026-11-13T18:13:01.760Z port=18080
data: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"{\"assetTypes\":[{\"description\":\"An asset type that represents an Azure Data Lake Container, which is a logical unit of storage containing Azure Data Lake Storage objects.\",\"displayNameEnabled\":true,\"finalType\":false,\"id\":\"00000000-0000-0000-0001-0028…
### ac7-bogus-bearer-1 2026-11-13T18:13:01.887Z port=18080
data: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"HTTP 401: {\"statusCode\":401,\"titleMessage\":\"Unauthorized\",\"helpMessage\":\"Please check the application logs for more information.\",\"userMessage\":\"The bearer token is incorrectly encoded or has wrong syntax\",\"errorCode\":\"malformedToken\"}"}],"isEr…
### ac7-bogus-bearer-2 2026-11-13T18:13:01.960Z port=18080
data: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"HTTP 401: {\"statusCode\":401,\"titleMessage\":\"Unauthorized\",\"helpMessage\":\"Please check the application logs for more information.\",\"userMessage\":\"The bearer token is incorrectly encoded or has wrong syntax\",\"errorCode\":\"malformedToken\"}"}],"isEr…
### ac7-http-wrongpw-1 2026-11-13T18:13:02.988Z port=18080
data: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"HTTP 401: {\"statusCode\":401,\"titleMessage\":\"Unauthorized\",\"helpMessage\":\"Please check the application logs for more information.\",\"userMessage\":\"Failed to authenticate request through basic credentials\",\"errorCode\":\"authenticationFailed\"}"}],"i…
### ac7-http-wrongpw-2 2026-11-13T18:13:03.513Z port=18080
data: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"HTTP 401: {\"statusCode\":401,\"titleMessage\":\"Unauthorized\",\"helpMessage\":\"Please check the application logs for more information.\",\"userMessage\":\"Failed to authenticate request through basic credentials\",\"errorCode\":\"authenticationFailed\"}"}],"i…
### ac2-sw-pr-1 2026-11-13T18:13:17.318Z port=18081
data: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"{\"assetTypes\":[{\"description\":\"An asset type that represents an Azure Data Lake Container, which is a logical unit of storage containing Azure Data Lake Storage objects.\",\"displayNameEnabled\":true,\"finalType\":false,\"id\":\"00000000-0000-0000-0001-0028…
### ac2-sw-pr-2 2026-11-13T18:13:17.399Z port=18081
data: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"{\"assetTypes\":[{\"description\":\"An asset type that represents an Azure Data Lake Container, which is a logical unit of storage containing Azure Data Lake Storage objects.\",\"displayNameEnabled\":true,\"finalType\":false,\"id\":\"00000000-0000-0000-0001-0028…
### ac6-sw-main-1 2026-11-13T18:13:17.443Z port=18083
data: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"{\"assetTypes\":[{\"description\":\"An asset type that represents an Azure Data Lake Container, which is a logical unit of storage containing Azure Data Lake Storage objects.\",\"displayNameEnabled\":true,\"finalType\":false,\"id\":\"00000000-0000-0000-0001-0028…
### ac7-sw-wrongpw-1 2026-11-13T18:13:18.359Z port=18082
data: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"HTTP 401: {\"statusCode\":401,\"titleMessage\":\"Unauthorized\",\"helpMessage\":\"Please check the application logs for more information.\",\"userMessage\":\"Failed to authenticate request through basic credentials\",\"errorCode\":\"authenticationFailed\"}"}],"i…
### ac7-sw-wrongpw-2 2026-11-13T18:13:18.886Z port=18082
data: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"HTTP 401: {\"statusCode\":401,\"titleMessage\":\"Unauthorized\",\"helpMessage\":\"Please check the application logs for more information.\",\"userMessage\":\"Failed to authenticate request through basic credentials\",\"errorCode\":\"authenticationFailed\"}"}],"i…
stdio run (initialize, notifications/initialized, tools/call): the response was {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"{\"assetTypes\":[{…\"name\":\"ADLS Container\"… (success). Proxy rows at 1794593598.926/.943 show the lookup followed by the tool call with x-mcp-user-id=…900002.
Results per criterion
AC-1: MET. With Basic Admin:admin, GET /rest/2.0/users/current returned "id":"00000000-0000-0000-0000-000000900002". GET /rest/2.0/users?name=Admin returned {"total":1,…"results":[{"id":"00000000-0000-0000-0000-000000900002",…"userName":"Admin"…}]}. The ids are equal.
AC-2: MET on the header value; NOT MET on the stated proof. With server-wide basic creds, in both http mode (18081) and stdio mode, chip sent exactly one users/current lookup (200). Every tool call afterwards carried x-mcp-user-id: 00000000-0000-0000-0000-000000900002, the AC-1 UUID. The stated proof, "chip's debug log line", cannot be met: chip has no log-level setting and logs no such line. The value was observed on the wire through chip's existing api.proxy setting.
AC-3: NOT MET. DGC wrote no xCollibraApiLoggingFilter line for any of chip's requests, successful or failed. The whole aggregator log has 8 such lines, all from DGC-internal callers at 18:06 (Collibra-Protect/1.0, ReactorNetty, Java-http-client, Apache-HttpClient; event identity:x_collibra_api_request). Searching the aggregator log for Collibra MCP, chip's traceparent trace-ids (e.g. 57bd73d3f8d3, 1ffee5eefb85) or assetTypes found only the Filters "Returning HTTP 401 …" lines for failed calls. None of them has a user_id, user_agent or traceparent field. That filter appears to log only x-collibra-api (service-to-service) requests, not external Basic/Bearer REST calls, so this DGC log cannot show the UUID matching for chip's requests.
AC-4: MET. http mode (18080), client-supplied Basic, interleaved Admin, user2, Admin, user2. Each credential got exactly one lookup on first use. Admin's tool calls carried …900002 both times. user2's (pesto-ac4-user2) carried 01a1d61a-8c89-708b-815c-d22dc8becba8 both times. There was no cross-talk. All four tool calls returned success. The same holds for Bearer (Admin token → …900002, user2 token → 01a1d61a-…).
AC-5: MET (human account), with one gap. A Bearer token minted at /rest/oauth/v2/token (password grant) makes GET /rest/2.0/users/current return a UUID (…900002). The account is a human user (userName=Admin, apiUser:false, userSource:INTERNAL). Through chip, the Bearer tool calls carried that UUID. The stack minted no client-application token: client_credentials returned 401 invalid_client for all three global clients, and registering a client returned 403. So the behaviour for a client-application account was not tested.
AC-6: MET. The same list_asset_types call on the PR build (18081, with x-mcp-user-id) and the main build (18083, without the header; proxy row 1794593597.417 shows it absent) both returned HTTP 200 from DGC. Both returned the same successful result ("total":260, first type "ADLS Container"). DGC does not reject the unknown header.
AC-7: MET. chip has no debug level (see AC-2), but its WARN/ERROR lines, the wire and DGC's log all show the behaviour:
- Server-wide wrong password (18082). One
users/current→ 401. Then 2 tool calls → 401, neither withx-mcp-user-id, and no second lookup. The MCP result for both wasisError:true,"HTTP 401: {…\"userMessage\":\"Failed to authenticate request through basic credentials\"…}". DGC's log matches:18:13:17.889 Returning HTTP 401 … 'GET /rest/2.0/users/current', then18:13:18.313and18:13:18.838 … 'GET /rest/2.0/assetTypes'. The gateway log matches too (lines 196–198). - http mode with a client-supplied wrong-password Basic, and with
Bearer bogus-token-123: same pattern. One lookup → 401, then two tool calls → 401 without the header, and the 401 surfaced as the tool error. DGC loggedInvalid JWT serialization: Missing dot delimiter(s)for the bogus Bearer. - chip's own stderr (INFO/WARN/ERROR; no debug level exists) shows the WARN only on the first call of each bad credential. That is the single lookup; the repeat call has no WARN and so made no new lookup:
- http mode, 18080 (bogus Bearer ×2, then wrong-password Basic ×2; earlier Bearer-success lines included):
2026/11/13 18:13:01 INFO Calling tool: list_asset_types tool_name=list_asset_types
2026/11/13 18:13:01 INFO Calling tool: list_asset_types tool_name=list_asset_types
2026/11/13 18:13:01 INFO Calling tool: list_asset_types tool_name=list_asset_types
2026/11/13 18:13:01 INFO Calling tool: list_asset_types tool_name=list_asset_types
2026/11/13 18:13:01 WARN Could not resolve the current user, x-mcp-user-id will not be sent: status 401
2026/11/13 18:13:01 ERROR error while calling tool function error="HTTP 401: {\"statusCode\":401,\"titleMessage\":\"Unauthorized\",\"helpMessage\":\"Please check the application logs for more information.\",\"userMessage\":\"The bearer token is incorrectly encoded or has wrong syntax\",\"errorCode\":\"malformedToken\"}"
2026/11/13 18:13:01 INFO Calling tool: list_asset_types tool_name=list_asset_types
2026/11/13 18:13:01 ERROR error while calling tool function error="HTTP 401: {\"statusCode\":401,\"titleMessage\":\"Unauthorized\",\"helpMessage\":\"Please check the application logs for more information.\",\"userMessage\":\"The bearer token is incorrectly encoded or has wrong syntax\",\"errorCode\":\"malformedToken\"}"
2026/11/13 18:13:01 INFO Calling tool: list_asset_types tool_name=list_asset_types
2026/11/13 18:13:02 WARN Could not resolve the current user, x-mcp-user-id will not be sent: status 401
2026/11/13 18:13:02 ERROR error while calling tool function error="HTTP 401: {\"statusCode\":401,\"titleMessage\":\"Unauthorized\",\"helpMessage\":\"Please check the application logs for more information.\",\"userMessage\":\"Failed to authenticate request through basic credentials\",\"errorCode\":\"authenticationFailed\"}"
2026/11/13 18:13:03 INFO Calling tool: list_asset_types tool_name=list_asset_types
2026/11/13 18:13:03 ERROR error while calling tool function error="HTTP 401: {\"statusCode\":401,\"titleMessage\":\"Unauthorized\",\"helpMessage\":\"Please check the application logs for more information.\",\"userMessage\":\"Failed to authenticate request through basic credentials\",\"errorCode\":\"authenticationFailed\"}"
- server-wide wrong password, 18082:
2026/11/13 18:13:17 INFO Calling tool: list_asset_types tool_name=list_asset_types
2026/11/13 18:13:17 WARN Could not resolve the current user, x-mcp-user-id will not be sent: status 401
2026/11/13 18:13:18 ERROR error while calling tool function error="HTTP 401: {\"statusCode\":401,\"titleMessage\":\"Unauthorized\",\"helpMessage\":\"Please check the application logs for more information.\",\"userMessage\":\"Failed to authenticate request through basic credentials\",\"errorCode\":\"authenticationFailed\"}"
2026/11/13 18:13:18 INFO Calling tool: list_asset_types tool_name=list_asset_types
2026/11/13 18:13:18 ERROR error while calling tool function error="HTTP 401: {\"statusCode\":401,\"titleMessage\":\"Unauthorized\",\"helpMessage\":\"Please check the application logs for more information.\",\"userMessage\":\"Failed to authenticate request through basic credentials\",\"errorCode\":\"authenticationFailed\"}"
- Cost: a failed Basic lookup took ~430–480 ms at DGC (see AC-9), and that time is added to the first call.
AC-8: MET. In http mode with no Authorization (2 calls), the proxy shows only GET /rest/2.0/assetTypes → 401, with no users/current lookup and no x-mcp-user-id. DGC's log shows only 18:12:17.229 and 18:12:29.612 Returning HTTP 401 Unauthorized on request 'GET /rest/2.0/assetTypes' and no users/current line. The tool result was isError:true, HTTP 401 …"Failed to authenticate request".
AC-9: MET. GET /rest/2.0/users/current from this pod through the gateway, timed with curl time_total:
- Basic Admin, n=30, all 200: median 10.7 ms, p95 11.9 ms (min 9.3, max 17.3)
- Bearer Admin, n=30, all 200: median 17.7 ms, p95 22.0 ms (min 15.7, max 26.0)
- Basic wrong password, n=25, all 401: median 485.0 ms, p95 630.0 ms (min 435.4, max 634.4)
The 2 s lookup timeout is far above all three.
AC-10: MET.
- Proxy: the only proxy in front of DGC is the magneto
dgc-gatewaynginx. Its config (configmapdgc-gateway) defines nolog_format, so it uses nginx's defaultcombinedformat. That format does not logx-mcp-user-idor any custom request header. Its log lines for chip look like10.20.11.17 - Admin [13/Nov/2026:18:13:17 +0000] "GET /rest/2.0/assetTypes?excludeMeta=true&limit=1 HTTP/1.1" 200 856 "-" "Collibra MCP/0.0.0-SNAPSHOT". Note that it logs the Basic username ($remote_user). - DGC:
xCollibraApiLoggingFilterlines carry the authenticateduser_idplusclient_address,method,uri,status_codeanduser_agent. They carry no request headers: there is nox-mcp-user-idfield and no traceparent. Example:{"logger_name":"xCollibraApiLoggingFilter",…"uri":"/rest/2.0/license/capabilities?name=DQ_CLOUD_DATA_SOURCES","user_agent":"Java/21.0.13.0.3","user_id":"00000000-0000-0000-0000-000000900006",…}. No such line was written for chip's own requests (see AC-3). - There is no separate ingress in this stack.
Review observations (no code changed)
- No way to see the header in chip's own logs. The PR documents the behaviour but logs nothing on success, and chip has no log level. Operators cannot confirm attribution from chip's side, and the "debug log" proofs here could not be met.
- DGC's request log will not attribute chip traffic in this build.
xCollibraApiLoggingFilterdid not log external Basic/Bearer REST calls at all, so whatever consumesx-mcp-user-idmust be something other than that filter. - The lookup carries no
traceparentorX-MCP-*headers, so it cannot be correlated with the tool call that triggered it. - A failed lookup costs ~0.5 s for wrong Basic credentials, on top of the 401 tool call. That happens once per credential per 10 minutes because failures are cached, and the behaviour matched the docs.
- Short-lived Bearer tokens (
expires_in=299) get a new cache key each time, so expect about one lookup per token per user.
Fixtures and cluster-side changes (environment is reclaimed after the run)
- User
pesto-ac4-user2, id01a1d61a-8c89-708b-815c-d22dc8becba8, created withPOST /rest/2.0/users. - Direct DB change: in pg-dgc (
dgc.users), row01a1d61a-8c89-708b-815c-d22dc8becba8got Admin's password hash copied in (so its password =admin) andactivated=true. I did this becausePATCH /rest/2.0/users/passwordreturned 400 "problem with parameter userId" andPATCH /rest/2.0/users/{id}withactivated:truedid not activate the user. No other rows were touched. - Responsibility
01a1d61b-b44f-751a-8e60-c31786debbf4: global role "Catalog" (00000000-0000-0000-0000-000000005042) granted to user2. Without it, login failed with NoProductPermissionsException. POST /rest/oauth/v2/clientsreturned 403, so nothing was created.- I read k8s secret
auth-global-clients-externalto get the dev global client secrets for the token probe. They are not reproduced here. - Nothing was deleted. No cluster resources were changed beyond the above. The local proxy and chip processes ran only in this pod and were stopped.
Acceptance criteria evidence
AC-1 — met
HEAD 70be0c4 == refs/pull/164/head. Basic Admin:admin against the DGC gateway: GET
/rest/2.0/users/current -> 200 id=00000000-0000-0000-0000-000000900002; GET
/rest/2.0/users?name=Admin -> total 1, results[0].id=00000000-0000-0000-0000-000000900002. Equal.
AC-2 — met
Ran the PR-built chip with COLLIBRA_MCP_API_USR=Admin/PWD=admin in http and stdio mode and made raw
tools/call list_asset_types. A logging forward proxy set through chip's existing
COLLIBRA_MCP_API_PROXY shows one GET users/current (200), then each tool call with header
X-Mcp-User-Id: 00000000-0000-0000-0000-000000900002 (the AC-1 id). CAVEAT: chip has no log-level
setting and no debug line prints the header, so the stated proof (chip debug log line) cannot be
produced without a code change; the value was observed on the wire instead.
AC-3 — not met
DGC wrote no xCollibraApiLoggingFilter line for any chip request. The aggregator log has 8 such
lines in total, all DGC-internal callers at 18:06 (Collibra-Protect, ReactorNetty,
Java-http-client). Searching for 'Collibra MCP', chip traceparent ids (57bd73d3f8d3, 1ffee5eefb85)
and 'assetTypes' found only 'Filters: Returning HTTP 401' lines for failed calls, with no user_id or
user_agent. The filter appears to log only x-collibra-api service-to-service requests, so the UUID
cannot be matched in DGC's log.
AC-4 — met
http mode, client-supplied Basic, interleaved Admin/user2/Admin/user2 (created user pesto-ac4-user2
id 01a1d61a-8c89-708b-815c-d22dc8becba8). The proxy shows one lookup per credential; Admin tool
calls carried 00000000-0000-0000-0000-000000900002 and user2 tool calls carried
01a1d61a-8c89-708b-815c-d22dc8becba8 every time. No cross-talk; all calls succeeded. Bearer per user
gave the same result.
AC-5 — met
A Bearer token minted at /rest/oauth/v2/token (grant_type=password, global client microsoft-copilot)
makes GET /rest/2.0/users/current return 200 id=...900002, a HUMAN user (userName Admin,
apiUser:false, userSource INTERNAL); JWT uid matches. Through chip, the Bearer tool calls carried
that UUID. No client-application token could be minted: client_credentials -> 401 invalid_client for
all 3 global clients, and POST /rest/oauth/v2/clients -> 403. Client-app accounts were not tested.
AC-6 — met
Same tools/call list_asset_types with server-wide Admin creds: the PR build (header X-Mcp-User-Id
sent) -> DGC 200, success total=260; the main build 791fb15 (no header, per proxy) -> DGC 200,
identical result. The header is not rejected.
AC-7 — met
Server-wide wrong password and http-mode wrong Basic / Bearer bogus-token-123, 2 calls each: the
proxy shows one users/current -> 401, then 2 tool calls -> 401 with no X-Mcp-User-Id and no second
lookup. The tool result was isError:true 'HTTP 401: ...Failed to authenticate request through basic
credentials'. chip stderr shows 'WARN Could not resolve the current user, x-mcp-user-id will not be
sent: status 401' once per credential. DGC log: 18:13:17.889 401 users/current, then 18:13:18.313
and .838 401 assetTypes. chip has no debug level; INFO/WARN were used.
AC-8 — met
http mode with no Authorization, 2 calls: the proxy shows only GET /rest/2.0/assetTypes -> 401, with
no users/current and no X-Mcp-User-Id. DGC log shows only 'Returning HTTP 401 Unauthorized on
request GET /rest/2.0/assetTypes' at 18:12:17.229 and 18:12:29.612, no users/current. Tool result
isError HTTP 401.
AC-9 — met
GET /rest/2.0/users/current via the gateway, curl time_total: Basic n=30 all 200 median 10.7ms p95
11.9ms; Bearer n=30 all 200 median 17.7ms p95 22.0ms; wrong-password Basic n=25 all 401 median
485.0ms p95 630.0ms.
AC-10 — met
The only proxy is the magneto dgc-gateway nginx; its config has no log_format (default combined),
and its log lines for chip are e.g. '10.20.11.17 - Admin [...] "GET /rest/2.0/assetTypes?...
HTTP/1.1" 200 856 "-" "Collibra MCP/0.0.0-SNAPSHOT"', so it does NOT log x-mcp-user-id (it does log
the Basic username). DGC xCollibraApiLoggingFilter lines record the authenticated user_id plus
uri/status/user_agent and no request headers, but no such line was written for chip's requests (see
AC-3). No separate ingress exists.
charlie-ang-collibra
left a comment
There was a problem hiding this comment.
validate-ac — collibra/chip PR #164 (x-mcp-user-id header) on a Magneto stack
Bytes under test
git rev-parse HEAD→70be0c4ada6ae1735654d46fedb09a5d171e6a2egit ls-remote origin 'refs/pull/164/*'→70be0c4ada6ae1735654d46fedb09a5d171e6a2e refs/pull/164/head— matches.- PR build:
go build -o /tmp/v/chip-pr ./cmd/chipat that SHA. Default-branch build: worktree at merge-base791fb15(main),go build -o /tmp/v/chip-main ./cmd/chip. (No localmainref existed; 791fb15 is the merge-base, the commit right before the PR's two commits.) chip's code was not changed.
Environment and how it was reached
- DGC from provision-env
dgcEndpointDetails:http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400, userAdmin. It was directly reachable from this pod (curl -u Admin:admin …/rest/2.0/users/current→ 200), so no port-forward was needed. DGC aggregator 2027.01.261, auth service 0.153.10, gatewaynginx:alpine(magneto-manageddgc-gateway). - Every chip run:
COLLIBRA_MCP_API_URL=<above>,COLLIBRA_MCP_API_PROXY=http://127.0.0.1:3128, where 3128 is a small Python logging forward proxy started in this pod that writes each request's method, URL, all request headers, status, latency, and response body as JSONL. - MCP driven with raw JSON-RPC (
initialize,notifications/initialized,tools/call list_asset_types), with no model in the loop. stdio mode: server-wideCOLLIBRA_MCP_API_USR/PWD. http mode:COLLIBRA_MCP_MODE=http COLLIBRA_MCP_HTTP_PORT=8091with no server credentials, and the client sendsAuthorizationon each POST.
Credential forms DGC accepts (GET /rest/2.0/users/current)
| Form | Result |
|---|---|
Authorization: Basic Admin:admin |
200, id=00000000-0000-0000-0000-000000900002 |
Authorization: Bearer from POST /rest/oauth/v2/token grant_type=password&username=Admin&password=admin (no client auth needed) |
token minted (RS256, iss=http://auth.iam, expires_in=299); users/current 200 with the same id …900002 |
POST /rest/oauth/v2/token grant_type=client_credentials (no client) |
401; with Basic Admin → 401 invalid_client "Client authentication failed: client_id" |
| Basic Admin:wrong | 401 authenticationFailed |
Bearer bogus |
401 malformedToken |
Fixtures created (nothing else was created or deleted)
- DGC user
pesto-vac-user2, id01a1d684-7fce-71cd-a1fc-fd153d0ec38b, created withPOST /rest/2.0/usersas Admin (201). - Global responsibility id
01a1d688-343e-7566-8a19-72c88e51f278: role Catalog00000000-0000-0000-0000-000000005042→ pesto-vac-user2, created withPOST /rest/2.0/responsibilities(201). Without it, login failed withNoProductPermissionsException. - DB write on that fixture row only (deviation from "through /rest/2.0"): this DGC build exposes no admin set-password REST call.
PATCH /rest/2.0/users/changePassword→ 400 (DGC log shows the path is routed asPATCH /users/{userId}→ PathParamException)./users/{id}/password|passwordChange|changePassword|resetPassword|credentials→ 404/405 for POST/PATCH/PUT./rest/1.0/user/{id}/password→ 404.POST /rest/2.0/internal/users/password/request_reset email=…→ 200, but the key is emailed and not stored in the DB. Through magnetomagneto_query_database(pg-dgc, db dgc) I ran:update dgc.users u set password=a.password, salt=a.salt, activated=true from dgc.users a where a.username='Admin' and u.id='01a1d684-7fce-71cd-a1fc-fd153d0ec38b' and u.username='pesto-vac-user2'→ UPDATE 1. pesto-vac-user2's password is thereforeadmin. Admin's row was only read. - Side effect: a password-reset request was issued for pesto-vac-user2 (the email went nowhere observable).
Cluster-side changes (not reverted; the stack is disposable)
- ConfigMap
dgc-gateway(nsdgc-af3a7b6ebec4), keynginx.conf, patched with magnetok8s_patch_resource(→patched:true). Before: the original config had nolog_formatand noaccess_log, so nginx's defaultcombinedformat applied. Added athttp{}level:and insidelog_format mcpuid '$remote_addr [$time_local] "$request" $status x_mcp_user_id="$http_x_mcp_user_id" x_mcp_tool="$http_x_mcp_tool_name"'; access_log /dev/stdout mcpuid;location / {}:add_header X-Seen-User-Id $http_x_mcp_user_id always;. Nothing else changed. The full before config is the "BEFORE" block at the end of this file; after = before + those 3 lines. - Reload: magneto
k8s_exec_in_podis unavailable (exec is not available in k8s provisioner mode: it needs a SPDY connection upgrade), songinx -s reloadcould not be run. nginx was reloaded by deleting poddgc-gateway-675d9f5979-l4667with magnetok8s_delete_pod(deleted:true). The Deployment recreated it asdgc-gateway-675d9f5979-fjhbz, which read the patched ConfigMap. Check:curl -D- -H 'x-mcp-user-id: probe-curl' …/users/current→X-Seen-User-Id: probe-curl.
Acceptance criteria
AC-1: MET. With Basic Admin:admin, GET /rest/2.0/users/current → "id":"00000000-0000-0000-0000-000000900002","userName":"Admin", and GET /rest/2.0/users?name=Admin → {"total":1,…"results":[{"id":"00000000-0000-0000-0000-000000900002",…"userName":"Admin"…}]}. The ids are equal. Also for pesto-vac-user2: users/current (as user2) and users?name=pesto-vac-user2 (as Admin) both return 01a1d684-7fce-71cd-a1fc-fd153d0ec38b.
AC-2: MET. In stdio mode with COLLIBRA_MCP_API_USR=Admin COLLIBRA_MCP_API_PWD=admin, two tools/call list_asset_types produced in the proxy: GET /rest/2.0/users/current 200 (no x-mcp-user-id on the lookup), then two GET /rest/2.0/assetTypes… each with X-Mcp-User-Id: 00000000-0000-0000-0000-000000900002, which is exactly the AC-1 UUID. There was one lookup for two calls (cached). The same happened in the http-mode Basic Admin run (Run 2a).
AC-3: MET. After the nginx patch above, one chip stdio call (Basic Admin) and one http-mode call (Basic pesto-vac-user2) produced these lines in the gateway pod dgc-gateway-675d9f5979-fjhbz stdout access log (magneto k8s_get_pod_logs):
10.20.0.180 [13/Nov/2026:20:11:43 +0000] "GET /rest/2.0/users/current HTTP/1.1" 200 x_mcp_user_id="-" x_mcp_tool="-"
10.20.0.180 [13/Nov/2026:20:11:43 +0000] "GET /rest/2.0/assetTypes?excludeMeta=true&limit=1&name=Business+Term HTTP/1.1" 200 x_mcp_user_id="00000000-0000-0000-0000-000000900002" x_mcp_tool="list_asset_types"
10.20.0.180 [13/Nov/2026:20:11:43 +0000] "GET /rest/2.0/assetTypes?excludeMeta=true&limit=1&name=Business+Term HTTP/1.1" 200 x_mcp_user_id="01a1d684-7fce-71cd-a1fc-fd153d0ec38b" x_mcp_tool="list_asset_types"
In the proxy record for the same calls, chip sent 00000000-0000-0000-0000-000000900002 and 01a1d684-7fce-71cd-a1fc-fd153d0ec38b, the same UUIDs nginx logged.
AC-4: MET. In http mode against one chip process with no server credentials, client Authorization: Basic alternated Admin:admin and pesto-vac-user2:admin (2 sequential rounds), followed by 3 concurrent Admin/user2 pairs. The proxy recorded 10 tool requests, and a script that decodes each request's Authorization user and compares X-Mcp-User-Id to that user's UUID reported tool requests=10 mismatches=0. Every Admin request carried …900002 and every user2 request carried 01a1d684-…ec38b. user2's credential caused exactly one users/current lookup. All tool calls returned results (no isError).
AC-5: MET (recorded). The stack mints a usable Bearer token at /rest/oauth/v2/token with grant_type=password. Claims: sub=urn:usr:env:00000000-0000-0000-0000-000000000001:id:00000000-0000-0000-0000-000000900002, uid=…900002, iss=http://auth.iam, aud=collibra, 75 scopes, 300 s lifetime. GET /rest/2.0/users/current with that Bearer → 200 and returns a UUID: {'id': '00000000-0000-0000-0000-000000900002', 'userName': 'Admin', 'apiUser': False, 'system': False, 'guestUser': False, 'userSource': 'INTERNAL'}. That is a human user account (apiUser:false, urn:usr subject), not a client-application account. Through chip in http mode with that Bearer (Run 2b), the lookup returned 200 and both tool requests carried X-Mcp-User-Id: 00000000-0000-0000-0000-000000900002. Not tested: a client-application (client_credentials) token. The stack has no registered OAuth client: client_credentials → invalid_client, and /rest/oauth/v2/applications|register → 404. What users/current returns for a client-app token on this stack is therefore unknown.
AC-6: MET. The same two tools/call list_asset_types ran in stdio mode with server-wide Basic Admin, first with the PR build and then with the default-branch build (791fb15). PR: tool requests carried X-Mcp-User-Id: …900002, DGC answered 200/200, and neither result had isError. Default: no header, 200/200. A JSON comparison of the two runs' result objects reported results identical: True. DGC did not reject or alter the response because of the unknown header.
AC-7: MET. (a) http mode, client Basic Admin:wrong, two calls. Proxy: GET /rest/2.0/users/current 401 (once), then assetTypes 401, assetTypes 401, neither carrying x-mcp-user-id. Both tool results were "isError":true with text HTTP 401: {"statusCode":401,…"userMessage":"Failed to authenticate request through basic credentials","errorCode":"authenticationFailed"}. chip log: WARN Could not resolve the current user, x-mcp-user-id will not be sent: status 401. DGC log (dgc-aggregator) shows exactly one users/current for that credential: 20:08:17.611 Returning HTTP 401 Unauthorized on request 'GET /rest/2.0/users/current', then 20:08:18.052 … 'GET /rest/2.0/assetTypes' and 20:08:18.541 … 'GET /rest/2.0/assetTypes', each preceded by User failed to log in: userName='Admin'. (b) http mode, Bearer bogus.token.value: one users/current 401, then two assetTypes 401 without the header, and tool errors with "errorCode":"malformedToken". (c) stdio mode, server-wide Admin/wrong: one users/current 401 and two assetTypes 401 without the header (DGC log 20:10:37.389 users/current, 20:10:37.814 and 20:10:38.289 assetTypes). Both tool results were isError:true with HTTP 401. The repeat call made no second lookup in all three cases. Latency note: each wrong-password Basic request takes ~425–445 ms at DGC (LDAP realm attempt), and the failed lookup adds one of those to the first call.
AC-8: MET. In http mode with no Authorization, two calls. Proxy record: only GET /rest/2.0/assetTypes… 401 ×2 (Authorization absent, no X-Mcp-User-Id) and no /rest/2.0/users/current request. Tool results: isError:true with HTTP 401 … "Failed to authenticate request".
AC-9: MET. GET /rest/2.0/users/current was timed from this pod via the gateway with curl -w %{time_total}, 25 calls per form, all 200. Basic: median 14.4 ms, p95 16.2 ms (min 12.9, max 24.4). Bearer: median 18.1 ms, p95 21.6 ms (min 15.5, max 22.9). Through chip and the proxy, the cold lookups observed were 16.8–55.6 ms (20 ms through proxy+gateway is typical). A failed Basic lookup costs ~430 ms.
AC-10: MET, with one qualification. (1) DGC's log does not record x-mcp-user-id. A search of the whole dgc-aggregator log for (?i)x-mcp|mcp-user|mcp_user|X-MCP-Tool|list_asset_types|probe-curl → No matches found … in 2379 log lines, after all chip calls had been made. Successful chip requests to /rest/2.0/assetTypes produce no request-log line at all. Only 401s are logged (Returning HTTP 401 Unauthorized on request 'GET /rest/2.0/assetTypes'), without headers. DGC logs its own authenticated_id field on some lines (e.g. User logged in … authenticated_id:01a1d684-…). (2) nginx's default format does not record it. The gateway config before the patch had no log_format or access_log, so nginx's built-in combined format applied. A line from the unpatched gateway for a request: 10.20.0.180 - pesto-vac-user2 [13/Nov/2026:20:06:31 +0000] "GET /rest/2.0/users/current HTTP/1.1" 401 228 "-" "curl/7.76.1" has no custom request headers. (3) Allowlist to change: in this stack it is the log_format of the nginx.conf key in ConfigMap dgc-gateway (ns dgc-af3a7b6ebec4). It needs $http_x_mcp_user_id (as done for AC-3), plus an access_log that uses that format. Qualification: this stack has no other gateway, so the name or location of a production gateway's header/log allowlist (outside magneto) could not be observed here and is not verified.
Other observations (not in the ACs)
- In all 28 recorded tool requests, in both stdio and http (stateless) modes, chip sent
X-Mcp-Session-Id: ""(an empty value). This also happens on the default branch, so the PR did not cause it. Downstream consumers should not treat the session id as a correlation key. - The
users/currentlookup itself carries noX-Mcp-Tool-Name/traceparent, and nginx logs it withx_mcp_user_id="-". If you correlate traffic at the gateway, the lookup appears as an anonymous-attribution request. - In http mode, a credential's result (including a failure) is cached for 10 min per chip process. A user who fixes a wrong password keeps getting no header until the TTL expires (by design per docs/CONFIG.md).
Raw evidence
The raw MCP JSON-RPC requests and responses, and the logging-proxy record, for every run follow. Long tool results and the initialize response are truncated. Authorization values are the stack's disposable test credentials.
Run 1 — stdio, server-wide Basic (COLLIBRA_MCP_API_USR=Admin/PWD=admin), PR build
MCP JSON-RPC (raw):
>>> {"jsonrpc": "2.0", "id": 0, "method": "initialize", "params": {"protocolVersion": "2025-06-18", "capabilities": {}, "clientInfo": {"name": "validate-ac", "v …(initialize, truncated)
<<< {"jsonrpc":"2.0","id":0,"result":{"capabilities":{"logging":{},"tools":{"listChanged":true}},"instructions":"# Collibra MCP Server\n\nThis server connects y …(initialize, truncated)
>>> {"jsonrpc": "2.0", "method": "notifications/initialized"}
>>> {"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "list_asset_types", "arguments": {"limit": 2}}}
<<< {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"{\"assetTypes\":[{\"description\":\"An asset type that represents an Azure Data Lake Container, which is a logical unit of storage containing Azure Data Lake Storage objects.\",\"displayNameEnabled\":true,\"finalType\":false,\"id\":\"00000000-0000-0000-0001-002800000003\",\"name\":\"ADLS Container\",\"product\":\"CATALOG\",\"publicId\":\"AdlsContainer\",\"ratingEnabled\":false,\"system\":true},{\"description\":\"An asset type that represents Azure Data Lake Storage file system.\",\"displayNameEnabled\":true,\"finalType\":false,\"id\":\"00000000-0000-0000-0001-002800000001\",\"name\":\"ADLS File System\",\"product\":\"CATALOG\",\"publicId\":\"AdlsFileSystem\",\"ratingEnabled\":false,\"system\":true}],\"limit\":2,\"offset\":0,\"resultsTruncated\":false,\"scanned\":0,\"status\":\"success\",\"total\":260}"}],"structuredC
>>> {"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "list_asset_types", "arguments": {"limit": 1, "name": "Business Term"}}}
<<< {"jsonrpc":"2.0","id":2,"result":{"content":[{"type":"text","text":"{\"assetTypes\":[{\"description\":\"A word or phrase that is used to describe something or to express a concept in a particular kind of language or branch of business.\\n\\nExamples: Customer, Person Purchase Count, Loan Amount.\",\"displayNameEnabled\":false,\"finalType\":false,\"id\":\"00000000-0000-0000-0000-000000011001\",\"name\":\"Business Term\",\"product\":\"GLOSSARY\",\"publicId\":\"BusinessTerm\",\"ratingEnabled\":false,\"system\":true}],\"limit\":1,\"offset\":0,\"resultsTruncated\":false,\"scanned\":0,\"status\":\"success\",\"total\":1}"}],"structuredContent":{"assetTypes":[{"description":"A word or phrase that is used to describe something or to express a concept in a particular kind of language or branch of business.\n\nExamples: Customer, Person Purchase Count, Loan Amount.","displayNameEnabled":false,"
2026/11/13 20:07:42 WARN Using a single basic auth header for all requests is not recommended as it will result in all actions being attributed to the same account. Consider setting an appropriate basic auth header for each request.
2026/11/13 20:07:42 INFO Calling tool: list_asset_types tool_name=list_asset_types
2026/11/13 20:07:42 INFO Calling tool: list_asset_types tool_name=list_asset_types
Logging proxy record (chip -> DGC):
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/users/current -> 200 (55.6ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Accept": "application/json", "Authorization": "Basic QWRtaW46YWRtaW4=", "Content-Type": "application/json", "Accept-Encoding": "gzip"}
resp body: {"id":"00000000-0000-0000-0000-000000900002","createdBy":"00000000-0000-0000-0000-000000900001","createdOn":1794599788313,"lastModifiedBy":"00000000-0000-0000-0000-000000900001","lastModifiedOn":1794600222152,"system":fa
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=2 -> 200 (77.5ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Authorization": "Basic QWRtaW46YWRtaW4=", "Content-Type": "application/json", "Traceparent": "00-bdfab97472aa1a4f90ded03e1b21e63f-92d17ff262a47005-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "X-Mcp-User-Id": "00000000-0000-0000-0000-000000900002", "Accept-Encoding": "gzip"}
resp body: {"total":260,"offset":0,"limit":2,"results":[{"id":"00000000-0000-0000-0001-002800000003","createdBy":"00000000-0000-0000-0000-000000900001","createdOn":1794599788313,"lastModifiedBy":"00000000-0000-0000-0000-00000090000
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=1&name=Business+Term -> 200 (36.9ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Authorization": "Basic QWRtaW46YWRtaW4=", "Content-Type": "application/json", "Traceparent": "00-caf31e415be5d060986c8ef1dd99b54f-5d31d10f0aca1f5d-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "X-Mcp-User-Id": "00000000-0000-0000-0000-000000900002", "Accept-Encoding": "gzip"}
resp body: {"total":1,"offset":0,"limit":1,"results":[{"id":"00000000-0000-0000-0000-000000011001","createdBy":"00000000-0000-0000-0000-000000900001","createdOn":1794599788313,"lastModifiedBy":"00000000-0000-0000-0000-000000900001"
Run 1b — same, DEFAULT-BRANCH build (791fb15)
MCP JSON-RPC (raw):
>>> {"jsonrpc": "2.0", "id": 0, "method": "initialize", "params": {"protocolVersion": "2025-06-18", "capabilities": {}, "clientInfo": {"name": "validate-ac", "v …(initialize, truncated)
<<< {"jsonrpc":"2.0","id":0,"result":{"capabilities":{"logging":{},"tools":{"listChanged":true}},"instructions":"# Collibra MCP Server\n\nThis server connects y …(initialize, truncated)
>>> {"jsonrpc": "2.0", "method": "notifications/initialized"}
>>> {"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "list_asset_types", "arguments": {"limit": 2}}}
<<< {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"{\"assetTypes\":[{\"description\":\"An asset type that represents an Azure Data Lake Container, which is a logical unit of storage containing Azure Data Lake Storage objects.\",\"displayNameEnabled\":true,\"finalType\":false,\"id\":\"00000000-0000-0000-0001-002800000003\",\"name\":\"ADLS Container\",\"product\":\"CATALOG\",\"publicId\":\"AdlsContainer\",\"ratingEnabled\":false,\"system\":true},{\"description\":\"An asset type that represents Azure Data Lake Storage file system.\",\"displayNameEnabled\":true,\"finalType\":false,\"id\":\"00000000-0000-0000-0001-002800000001\",\"name\":\"ADLS File System\",\"product\":\"CATALOG\",\"publicId\":\"AdlsFileSystem\",\"ratingEnabled\":false,\"system\":true}],\"limit\":2,\"offset\":0,\"resultsTruncated\":false,\"scanned\":0,\"status\":\"success\",\"total\":260}"}],"structuredC
>>> {"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "list_asset_types", "arguments": {"limit": 1, "name": "Business Term"}}}
<<< {"jsonrpc":"2.0","id":2,"result":{"content":[{"type":"text","text":"{\"assetTypes\":[{\"description\":\"A word or phrase that is used to describe something or to express a concept in a particular kind of language or branch of business.\\n\\nExamples: Customer, Person Purchase Count, Loan Amount.\",\"displayNameEnabled\":false,\"finalType\":false,\"id\":\"00000000-0000-0000-0000-000000011001\",\"name\":\"Business Term\",\"product\":\"GLOSSARY\",\"publicId\":\"BusinessTerm\",\"ratingEnabled\":false,\"system\":true}],\"limit\":1,\"offset\":0,\"resultsTruncated\":false,\"scanned\":0,\"status\":\"success\",\"total\":1}"}],"structuredContent":{"assetTypes":[{"description":"A word or phrase that is used to describe something or to express a concept in a particular kind of language or branch of business.\n\nExamples: Customer, Person Purchase Count, Loan Amount.","displayNameEnabled":false,"
2026/11/13 20:07:50 WARN Using a single basic auth header for all requests is not recommended as it will result in all actions being attributed to the same account. Consider setting an appropriate basic auth header for each request.
2026/11/13 20:07:50 INFO Calling tool: list_asset_types tool_name=list_asset_types
2026/11/13 20:07:50 INFO Calling tool: list_asset_types tool_name=list_asset_types
Logging proxy record (chip -> DGC):
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=2 -> 200 (39.0ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Authorization": "Basic QWRtaW46YWRtaW4=", "Content-Type": "application/json", "Traceparent": "00-fd713b593305c8ec25e1b4f442cb6141-40bb457cc17d28fa-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "Accept-Encoding": "gzip"}
resp body: {"total":260,"offset":0,"limit":2,"results":[{"id":"00000000-0000-0000-0001-002800000003","createdBy":"00000000-0000-0000-0000-000000900001","createdOn":1794599788313,"lastModifiedBy":"00000000-0000-0000-0000-00000090000
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=1&name=Business+Term -> 200 (25.5ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Authorization": "Basic QWRtaW46YWRtaW4=", "Content-Type": "application/json", "Traceparent": "00-98bbe41250622ad1947798af9e9ee7b4-ca9abd114cdaf464-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "Accept-Encoding": "gzip"}
resp body: {"total":1,"offset":0,"limit":1,"results":[{"id":"00000000-0000-0000-0000-000000011001","createdBy":"00000000-0000-0000-0000-000000900001","createdOn":1794599788313,"lastModifiedBy":"00000000-0000-0000-0000-000000900001"
Run 2a — http mode, client Authorization: Basic Admin
MCP JSON-RPC (raw):
>>> POST http://localhost:8091/ headers={"Content-Type": "application/json", "Accept": "application/json, text/event-stream", "Authorization": "Basic QWRtaW46YWRtaW4="}
>>> {"jsonrpc": "2.0", "id": 0, "method": "initialize", "params": {"protocolVersion": "2025-06-18", "capabilities": {}, "clientInfo": {"name": "validate-ac", "v …(initialize, truncated)
<<< HTTP 200
<<< event: message
data: {"jsonrpc":"2.0","id":0,"result":{"capabilities":{"logging":{},"tools":{"listChanged":true}},"instructions":"# Collibra MCP Server\n\nThis server connects …(initialize, truncated)
>>> POST http://localhost:8091/ headers={"Content-Type": "application/json", "Accept": "application/json, text/event-stream", "Authorization": "Basic QWRtaW46YWRtaW4="}
>>> {"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "list_asset_types", "arguments": {"limit": 1}}}
<<< HTTP 200
<<< event: message
data: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"{\"assetTypes\":[{\"description\":\"An asset type that represents an Azure Data Lake Container, which is a logical unit of storage containing Azure Data Lake Storage objects.\",\"displayNameEnabled\":true,\"finalType\":false,\"id\":\"00000000-0000-0000-0001-002800000003\",\"name\":\"ADLS Container\",\"product\":\"CATALOG\",\"publicId\":\"AdlsContainer\",\"ratingEnabled\":false,\"system\":true}],\"limit\":1,\"offset\":0,\"resultsTruncated\":false,\"scanned\":0,\"status\":\"success\",\"total\":260}"}],"structuredContent":{"assetTypes":[{"description":"An asset type that represents an Azure Data Lake Container, which is a logical unit of storage containing Azure Data Lake Storage objects.","displayNameEnabled":true,"finalType":false,"id":"00000000-0000-0000-0001-002800000003","name":"ADLS Container","product":"CATALOG
>>> POST http://localhost:8091/ headers={"Content-Type": "application/json", "Accept": "application/json, text/event-stream", "Authorization": "Basic QWRtaW46YWRtaW4="}
>>> {"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "list_asset_types", "arguments": {"limit": 1, "name": "Business Term"}}}
<<< HTTP 200
<<< event: message
data: {"jsonrpc":"2.0","id":2,"result":{"content":[{"type":"text","text":"{\"assetTypes\":[{\"description\":\"A word or phrase that is used to describe something or to express a concept in a particular kind of language or branch of business.\\n\\nExamples: Customer, Person Purchase Count, Loan Amount.\",\"displayNameEnabled\":false,\"finalType\":false,\"id\":\"00000000-0000-0000-0000-000000011001\",\"name\":\"Business Term\",\"product\":\"GLOSSARY\",\"publicId\":\"BusinessTerm\",\"ratingEnabled\":false,\"system\":true}],\"limit\":1,\"offset\":0,\"resultsTruncated\":false,\"scanned\":0,\"status\":\"success\",\"total\":1}"}],"structuredContent":{"assetTypes":[{"description":"A word or phrase that is used to describe something or to express a concept in a particular kind of language or branch of business.\n\nExamples: Customer, Person Purchase Count, Loan Amount.","displayNameEnabled":false
Logging proxy record (chip -> DGC):
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/users/current -> 200 (51.0ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Accept": "application/json", "Authorization": "Basic QWRtaW46YWRtaW4=", "Content-Type": "application/json", "Accept-Encoding": "gzip"}
resp body: {"id":"00000000-0000-0000-0000-000000900002","createdBy":"00000000-0000-0000-0000-000000900001","createdOn":1794599788313,"lastModifiedBy":"00000000-0000-0000-0000-000000900001","lastModifiedOn":1794600222152,"system":fa
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=1 -> 200 (24.3ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Authorization": "Basic QWRtaW46YWRtaW4=", "Content-Type": "application/json", "Traceparent": "00-077e29395b99ab1d5a72bf3c3699bc8c-d935f9cc73b080ce-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "X-Mcp-User-Id": "00000000-0000-0000-0000-000000900002", "Accept-Encoding": "gzip"}
resp body: {"total":260,"offset":0,"limit":1,"results":[{"id":"00000000-0000-0000-0001-002800000003","createdBy":"00000000-0000-0000-0000-000000900001","createdOn":1794599788313,"lastModifiedBy":"00000000-0000-0000-0000-00000090000
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=1&name=Business+Term -> 200 (23.3ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Authorization": "Basic QWRtaW46YWRtaW4=", "Content-Type": "application/json", "Traceparent": "00-73caf963404e30365d0558f779fe91ee-ee7eea2f11246592-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "X-Mcp-User-Id": "00000000-0000-0000-0000-000000900002", "Accept-Encoding": "gzip"}
resp body: {"total":1,"offset":0,"limit":1,"results":[{"id":"00000000-0000-0000-0000-000000011001","createdBy":"00000000-0000-0000-0000-000000900001","createdOn":1794599788313,"lastModifiedBy":"00000000-0000-0000-0000-000000900001"
Run 2b — http mode, client Authorization: Bearer (password-grant token, Admin)
MCP JSON-RPC (raw):
>>> POST http://localhost:8091/ headers={"Content-Type": "application/json", "Accept": "application/json, text/event-stream", "Authorization": "Bearer eyJra..."}
>>> {"jsonrpc": "2.0", "id": 0, "method": "initialize", "params": {"protocolVersion": "2025-06-18", "capabilities": {}, "clientInfo": {"name": "validate-ac", "v …(initialize, truncated)
<<< HTTP 200
<<< event: message
data: {"jsonrpc":"2.0","id":0,"result":{"capabilities":{"logging":{},"tools":{"listChanged":true}},"instructions":"# Collibra MCP Server\n\nThis server connects …(initialize, truncated)
>>> POST http://localhost:8091/ headers={"Content-Type": "application/json", "Accept": "application/json, text/event-stream", "Authorization": "Bearer eyJra..."}
>>> {"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "list_asset_types", "arguments": {"limit": 1}}}
<<< HTTP 200
<<< event: message
data: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"{\"assetTypes\":[{\"description\":\"An asset type that represents an Azure Data Lake Container, which is a logical unit of storage containing Azure Data Lake Storage objects.\",\"displayNameEnabled\":true,\"finalType\":false,\"id\":\"00000000-0000-0000-0001-002800000003\",\"name\":\"ADLS Container\",\"product\":\"CATALOG\",\"publicId\":\"AdlsContainer\",\"ratingEnabled\":false,\"system\":true}],\"limit\":1,\"offset\":0,\"resultsTruncated\":false,\"scanned\":0,\"status\":\"success\",\"total\":260}"}],"structuredContent":{"assetTypes":[{"description":"An asset type that represents an Azure Data Lake Container, which is a logical unit of storage containing Azure Data Lake Storage objects.","displayNameEnabled":true,"finalType":false,"id":"00000000-0000-0000-0001-002800000003","name":"ADLS Container","product":"CATALOG
>>> POST http://localhost:8091/ headers={"Content-Type": "application/json", "Accept": "application/json, text/event-stream", "Authorization": "Bearer eyJra..."}
>>> {"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "list_asset_types", "arguments": {"limit": 1, "name": "Business Term"}}}
<<< HTTP 200
<<< event: message
data: {"jsonrpc":"2.0","id":2,"result":{"content":[{"type":"text","text":"{\"assetTypes\":[{\"description\":\"A word or phrase that is used to describe something or to express a concept in a particular kind of language or branch of business.\\n\\nExamples: Customer, Person Purchase Count, Loan Amount.\",\"displayNameEnabled\":false,\"finalType\":false,\"id\":\"00000000-0000-0000-0000-000000011001\",\"name\":\"Business Term\",\"product\":\"GLOSSARY\",\"publicId\":\"BusinessTerm\",\"ratingEnabled\":false,\"system\":true}],\"limit\":1,\"offset\":0,\"resultsTruncated\":false,\"scanned\":0,\"status\":\"success\",\"total\":1}"}],"structuredContent":{"assetTypes":[{"description":"A word or phrase that is used to describe something or to express a concept in a particular kind of language or branch of business.\n\nExamples: Customer, Person Purchase Count, Loan Amount.","displayNameEnabled":false
Logging proxy record (chip -> DGC):
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/users/current -> 200 (21.1ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Accept": "application/json", "Authorization": "Bearer eyJraWQiOiJkZ\u2026", "Content-Type": "application/json", "Accept-Encoding": "gzip"}
resp body: {"id":"00000000-0000-0000-0000-000000900002","createdBy":"00000000-0000-0000-0000-000000900001","createdOn":1794599788313,"lastModifiedBy":"00000000-0000-0000-0000-000000900001","lastModifiedOn":1794600222152,"system":fa
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=1 -> 200 (31.4ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Authorization": "Bearer eyJraWQiOiJkZ\u2026", "Content-Type": "application/json", "Traceparent": "00-14e571afde5600904fcbdcdfed87fd32-b805f76dab02c624-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "X-Mcp-User-Id": "00000000-0000-0000-0000-000000900002", "Accept-Encoding": "gzip"}
resp body: {"total":260,"offset":0,"limit":1,"results":[{"id":"00000000-0000-0000-0001-002800000003","createdBy":"00000000-0000-0000-0000-000000900001","createdOn":1794599788313,"lastModifiedBy":"00000000-0000-0000-0000-00000090000
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=1&name=Business+Term -> 200 (27.1ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Authorization": "Bearer eyJraWQiOiJkZ\u2026", "Content-Type": "application/json", "Traceparent": "00-db844befbae2fd679571a94d0ed9bcf1-26cbcc96e9841ed3-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "X-Mcp-User-Id": "00000000-0000-0000-0000-000000900002", "Accept-Encoding": "gzip"}
resp body: {"total":1,"offset":0,"limit":1,"results":[{"id":"00000000-0000-0000-0000-000000011001","createdBy":"00000000-0000-0000-0000-000000900001","createdOn":1794599788313,"lastModifiedBy":"00000000-0000-0000-0000-000000900001"
Run 2c — http mode, NO Authorization
MCP JSON-RPC (raw):
>>> POST http://localhost:8091/ headers={"Content-Type": "application/json", "Accept": "application/json, text/event-stream"}
>>> {"jsonrpc": "2.0", "id": 0, "method": "initialize", "params": {"protocolVersion": "2025-06-18", "capabilities": {}, "clientInfo": {"name": "validate-ac", "v …(initialize, truncated)
<<< HTTP 200
<<< event: message
data: {"jsonrpc":"2.0","id":0,"result":{"capabilities":{"logging":{},"tools":{"listChanged":true}},"instructions":"# Collibra MCP Server\n\nThis server connects …(initialize, truncated)
>>> POST http://localhost:8091/ headers={"Content-Type": "application/json", "Accept": "application/json, text/event-stream"}
>>> {"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "list_asset_types", "arguments": {"limit": 1}}}
<<< HTTP 200
<<< event: message
data: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"HTTP 401: {\"statusCode\":401,\"titleMessage\":\"Unauthorized\",\"helpMessage\":\"Please check the application logs for more information.\",\"userMessage\":\"Failed to authenticate request\",\"errorCode\":\"authenticationFailed\"}"}],"isError":true}}
>>> POST http://localhost:8091/ headers={"Content-Type": "application/json", "Accept": "application/json, text/event-stream"}
>>> {"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "list_asset_types", "arguments": {"limit": 1, "name": "Business Term"}}}
<<< HTTP 200
<<< event: message
data: {"jsonrpc":"2.0","id":2,"result":{"content":[{"type":"text","text":"HTTP 401: {\"statusCode\":401,\"titleMessage\":\"Unauthorized\",\"helpMessage\":\"Please check the application logs for more information.\",\"userMessage\":\"Failed to authenticate request\",\"errorCode\":\"authenticationFailed\"}"}],"isError":true}}
Logging proxy record (chip -> DGC):
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=1 -> 401 (11.6ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Content-Type": "application/json", "Traceparent": "00-f93a0656c36e003583ec679f89862af9-06984ff55e41d187-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "Accept-Encoding": "gzip"}
resp body: {"statusCode":401,"titleMessage":"Unauthorized","helpMessage":"Please check the application logs for more information.","userMessage":"Failed to authenticate request","errorCode":"authenticationFailed"}
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=1&name=Business+Term -> 401 (9.9ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Content-Type": "application/json", "Traceparent": "00-f8dae126d2e0c84b1c7a716a90074035-69e0277e8cb322c5-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "Accept-Encoding": "gzip"}
resp body: {"statusCode":401,"titleMessage":"Unauthorized","helpMessage":"Please check the application logs for more information.","userMessage":"Failed to authenticate request","errorCode":"authenticationFailed"}
Run 2d — http mode, Basic Admin:wrong
MCP JSON-RPC (raw):
>>> POST http://localhost:8091/ headers={"Content-Type": "application/json", "Accept": "application/json, text/event-stream", "Authorization": "Basic QWRtaW46d3Jvbmc="}
>>> {"jsonrpc": "2.0", "id": 0, "method": "initialize", "params": {"protocolVersion": "2025-06-18", "capabilities": {}, "clientInfo": {"name": "validate-ac", "v …(initialize, truncated)
<<< HTTP 200
<<< event: message
data: {"jsonrpc":"2.0","id":0,"result":{"capabilities":{"logging":{},"tools":{"listChanged":true}},"instructions":"# Collibra MCP Server\n\nThis server connects …(initialize, truncated)
>>> POST http://localhost:8091/ headers={"Content-Type": "application/json", "Accept": "application/json, text/event-stream", "Authorization": "Basic QWRtaW46d3Jvbmc="}
>>> {"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "list_asset_types", "arguments": {"limit": 1}}}
<<< HTTP 200
<<< event: message
data: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"HTTP 401: {\"statusCode\":401,\"titleMessage\":\"Unauthorized\",\"helpMessage\":\"Please check the application logs for more information.\",\"userMessage\":\"Failed to authenticate request through basic credentials\",\"errorCode\":\"authenticationFailed\"}"}],"isError":true}}
>>> POST http://localhost:8091/ headers={"Content-Type": "application/json", "Accept": "application/json, text/event-stream", "Authorization": "Basic QWRtaW46d3Jvbmc="}
>>> {"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "list_asset_types", "arguments": {"limit": 1, "name": "Business Term"}}}
<<< HTTP 200
<<< event: message
data: {"jsonrpc":"2.0","id":2,"result":{"content":[{"type":"text","text":"HTTP 401: {\"statusCode\":401,\"titleMessage\":\"Unauthorized\",\"helpMessage\":\"Please check the application logs for more information.\",\"userMessage\":\"Failed to authenticate request through basic credentials\",\"errorCode\":\"authenticationFailed\"}"}],"isError":true}}
Logging proxy record (chip -> DGC):
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/users/current -> 401 (437.6ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Accept": "application/json", "Authorization": "Basic QWRtaW46d3Jvbmc=", "Content-Type": "application/json", "Accept-Encoding": "gzip"}
resp body: {"statusCode":401,"titleMessage":"Unauthorized","helpMessage":"Please check the application logs for more information.","userMessage":"Failed to authenticate request through basic credentials","errorCode":"authentication
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=1 -> 401 (439.1ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Authorization": "Basic QWRtaW46d3Jvbmc=", "Content-Type": "application/json", "Traceparent": "00-c02e95a001c681c1768aa910ac2a0b78-8711d47d0b21da09-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "Accept-Encoding": "gzip"}
resp body: {"statusCode":401,"titleMessage":"Unauthorized","helpMessage":"Please check the application logs for more information.","userMessage":"Failed to authenticate request through basic credentials","errorCode":"authentication
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=1&name=Business+Term -> 401 (445.2ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Authorization": "Basic QWRtaW46d3Jvbmc=", "Content-Type": "application/json", "Traceparent": "00-1d2a7a6a9bd9d034ddec33556c16911f-090b61755d221d16-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "Accept-Encoding": "gzip"}
resp body: {"statusCode":401,"titleMessage":"Unauthorized","helpMessage":"Please check the application logs for more information.","userMessage":"Failed to authenticate request through basic credentials","errorCode":"authentication
Run 2e — http mode, Bearer bogus.token.value
MCP JSON-RPC (raw):
>>> POST http://localhost:8091/ headers={"Content-Type": "application/json", "Accept": "application/json, text/event-stream", "Authorization": "Bearer bogus.token.value"}
>>> {"jsonrpc": "2.0", "id": 0, "method": "initialize", "params": {"protocolVersion": "2025-06-18", "capabilities": {}, "clientInfo": {"name": "validate-ac", "v …(initialize, truncated)
<<< HTTP 200
<<< event: message
data: {"jsonrpc":"2.0","id":0,"result":{"capabilities":{"logging":{},"tools":{"listChanged":true}},"instructions":"# Collibra MCP Server\n\nThis server connects …(initialize, truncated)
>>> POST http://localhost:8091/ headers={"Content-Type": "application/json", "Accept": "application/json, text/event-stream", "Authorization": "Bearer bogus.token.value"}
>>> {"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "list_asset_types", "arguments": {"limit": 1}}}
<<< HTTP 200
<<< event: message
data: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"HTTP 401: {\"statusCode\":401,\"titleMessage\":\"Unauthorized\",\"helpMessage\":\"Please check the application logs for more information.\",\"userMessage\":\"The bearer token is incorrectly encoded or has wrong syntax\",\"errorCode\":\"malformedToken\"}"}],"isError":true}}
>>> POST http://localhost:8091/ headers={"Content-Type": "application/json", "Accept": "application/json, text/event-stream", "Authorization": "Bearer bogus.token.value"}
>>> {"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "list_asset_types", "arguments": {"limit": 1, "name": "Business Term"}}}
<<< HTTP 200
<<< event: message
data: {"jsonrpc":"2.0","id":2,"result":{"content":[{"type":"text","text":"HTTP 401: {\"statusCode\":401,\"titleMessage\":\"Unauthorized\",\"helpMessage\":\"Please check the application logs for more information.\",\"userMessage\":\"The bearer token is incorrectly encoded or has wrong syntax\",\"errorCode\":\"malformedToken\"}"}],"isError":true}}
Logging proxy record (chip -> DGC):
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/users/current -> 401 (10.5ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Accept": "application/json", "Authorization": "Bearer bogus.token.value", "Content-Type": "application/json", "Accept-Encoding": "gzip"}
resp body: {"statusCode":401,"titleMessage":"Unauthorized","helpMessage":"Please check the application logs for more information.","userMessage":"The bearer token is incorrectly encoded or has wrong syntax","errorCode":"malformedTo
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=1 -> 401 (8.4ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Authorization": "Bearer bogus.token.value", "Content-Type": "application/json", "Traceparent": "00-34ea4b5319b7e47e19a01bdbb96da00d-2d850bc4bedc614f-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "Accept-Encoding": "gzip"}
resp body: {"statusCode":401,"titleMessage":"Unauthorized","helpMessage":"Please check the application logs for more information.","userMessage":"The bearer token is incorrectly encoded or has wrong syntax","errorCode":"malformedTo
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=1&name=Business+Term -> 401 (11.1ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Authorization": "Bearer bogus.token.value", "Content-Type": "application/json", "Traceparent": "00-1a93bab87ffc09847eb10335b6e73562-aec6340a2086f389-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "Accept-Encoding": "gzip"}
resp body: {"statusCode":401,"titleMessage":"Unauthorized","helpMessage":"Please check the application logs for more information.","userMessage":"The bearer token is incorrectly encoded or has wrong syntax","errorCode":"malformedTo
Run 3 — http mode, Admin and pesto-vac-user2 interleaved + 3 concurrent pairs (proxy record)
Logging proxy record (chip -> DGC):
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=1 -> 200 (36.1ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Authorization": "Basic QWRtaW46YWRtaW4=", "Content-Type": "application/json", "Traceparent": "00-aa872324f0597e0bdf62c33f4c70709c-074382aa947dac05-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "X-Mcp-User-Id": "00000000-0000-0000-0000-000000900002", "Accept-Encoding": "gzip"}
resp body: {"total":260,"offset":0,"limit":1,"results":[{"id":"00000000-0000-0000-0001-002800000003","createdBy":"00000000-0000-0000-0000-000000900001","createdOn":1794599788313,"lastModifiedBy":"00000000-0000-0000-0000-00000090000
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/users/current -> 200 (16.8ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Accept": "application/json", "Authorization": "Basic cGVzdG8tdmFjLXVzZXIyOmFkbWlu", "Content-Type": "application/json", "Accept-Encoding": "gzip"}
resp body: {"id":"01a1d684-7fce-71cd-a1fc-fd153d0ec38b","createdBy":"00000000-0000-0000-0000-000000900002","createdOn":1794600370126,"lastModifiedBy":"00000000-0000-0000-0000-000000900002","lastModifiedOn":1794600370126,"system":fa
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=1 -> 200 (23.8ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Authorization": "Basic cGVzdG8tdmFjLXVzZXIyOmFkbWlu", "Content-Type": "application/json", "Traceparent": "00-2523028e4a44c5e497c78834312632dd-e238ad36930211bd-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "X-Mcp-User-Id": "01a1d684-7fce-71cd-a1fc-fd153d0ec38b", "Accept-Encoding": "gzip"}
resp body: {"total":260,"offset":0,"limit":1,"results":[{"id":"00000000-0000-0000-0001-002800000003","createdBy":"00000000-0000-0000-0000-000000900001","createdOn":1794599788313,"lastModifiedBy":"00000000-0000-0000-0000-00000090000
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=1 -> 200 (20.6ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Authorization": "Basic QWRtaW46YWRtaW4=", "Content-Type": "application/json", "Traceparent": "00-4c4a1cdcc22791a31d65d35f76fab65c-1b3fa00cadce4bd7-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "X-Mcp-User-Id": "00000000-0000-0000-0000-000000900002", "Accept-Encoding": "gzip"}
resp body: {"total":260,"offset":0,"limit":1,"results":[{"id":"00000000-0000-0000-0001-002800000003","createdBy":"00000000-0000-0000-0000-000000900001","createdOn":1794599788313,"lastModifiedBy":"00000000-0000-0000-0000-00000090000
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=1 -> 200 (25.0ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Authorization": "Basic cGVzdG8tdmFjLXVzZXIyOmFkbWlu", "Content-Type": "application/json", "Traceparent": "00-f8a669173cf5ce85c1bb76ec909bd77b-98d29627f5dbe2ab-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "X-Mcp-User-Id": "01a1d684-7fce-71cd-a1fc-fd153d0ec38b", "Accept-Encoding": "gzip"}
resp body: {"total":260,"offset":0,"limit":1,"results":[{"id":"00000000-0000-0000-0001-002800000003","createdBy":"00000000-0000-0000-0000-000000900001","createdOn":1794599788313,"lastModifiedBy":"00000000-0000-0000-0000-00000090000
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=1 -> 200 (23.2ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Authorization": "Basic cGVzdG8tdmFjLXVzZXIyOmFkbWlu", "Content-Type": "application/json", "Traceparent": "00-6521bf9053eaba644fdb98de533f7c08-10124c08bd19dd1b-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "X-Mcp-User-Id": "01a1d684-7fce-71cd-a1fc-fd153d0ec38b", "Accept-Encoding": "gzip"}
resp body: {"total":260,"offset":0,"limit":1,"results":[{"id":"00000000-0000-0000-0001-002800000003","createdBy":"00000000-0000-0000-0000-000000900001","createdOn":1794599788313,"lastModifiedBy":"00000000-0000-0000-0000-00000090000
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=1 -> 200 (44.4ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Authorization": "Basic QWRtaW46YWRtaW4=", "Content-Type": "application/json", "Traceparent": "00-b4ecbcb3f6bc476d7e8b778280122ee0-32c14aaafea897aa-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "X-Mcp-User-Id": "00000000-0000-0000-0000-000000900002", "Accept-Encoding": "gzip"}
resp body: {"total":260,"offset":0,"limit":1,"results":[{"id":"00000000-0000-0000-0001-002800000003","createdBy":"00000000-0000-0000-0000-000000900001","createdOn":1794599788313,"lastModifiedBy":"00000000-0000-0000-0000-00000090000
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=1 -> 200 (22.8ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Authorization": "Basic QWRtaW46YWRtaW4=", "Content-Type": "application/json", "Traceparent": "00-8fbeffb0d15a4f0a59753794351a1fcc-38b8a4c0704ea282-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "X-Mcp-User-Id": "00000000-0000-0000-0000-000000900002", "Accept-Encoding": "gzip"}
resp body: {"total":260,"offset":0,"limit":1,"results":[{"id":"00000000-0000-0000-0001-002800000003","createdBy":"00000000-0000-0000-0000-000000900001","createdOn":1794599788313,"lastModifiedBy":"00000000-0000-0000-0000-00000090000
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=1 -> 200 (26.7ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Authorization": "Basic cGVzdG8tdmFjLXVzZXIyOmFkbWlu", "Content-Type": "application/json", "Traceparent": "00-1a75d6694d604b557800b9a26bb09d0b-61f647c933f7fb32-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "X-Mcp-User-Id": "01a1d684-7fce-71cd-a1fc-fd153d0ec38b", "Accept-Encoding": "gzip"}
resp body: {"total":260,"offset":0,"limit":1,"results":[{"id":"00000000-0000-0000-0001-002800000003","createdBy":"00000000-0000-0000-0000-000000900001","createdOn":1794599788313,"lastModifiedBy":"00000000-0000-0000-0000-00000090000
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=1 -> 200 (32.6ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Authorization": "Basic cGVzdG8tdmFjLXVzZXIyOmFkbWlu", "Content-Type": "application/json", "Traceparent": "00-7bc628f5707e4513a6ab5c8d28b09bf9-dabfbc4581750708-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "X-Mcp-User-Id": "01a1d684-7fce-71cd-a1fc-fd153d0ec38b", "Accept-Encoding": "gzip"}
resp body: {"total":260,"offset":0,"limit":1,"results":[{"id":"00000000-0000-0000-0001-002800000003","createdBy":"00000000-0000-0000-0000-000000900001","createdOn":1794599788313,"lastModifiedBy":"00000000-0000-0000-0000-00000090000
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=1 -> 200 (29.7ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Authorization": "Basic QWRtaW46YWRtaW4=", "Content-Type": "application/json", "Traceparent": "00-226ea4fdbcf0726016c75f5acaf4ef94-7c80b02c81a77770-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "X-Mcp-User-Id": "00000000-0000-0000-0000-000000900002", "Accept-Encoding": "gzip"}
resp body: {"total":260,"offset":0,"limit":1,"results":[{"id":"00000000-0000-0000-0001-002800000003","createdBy":"00000000-0000-0000-0000-000000900001","createdOn":1794599788313,"lastModifiedBy":"00000000-0000-0000-0000-00000090000
Run 4 — stdio, server-wide Basic Admin:wrong, two calls
MCP JSON-RPC (raw):
>>> {"jsonrpc": "2.0", "id": 0, "method": "initialize", "params": {"protocolVersion": "2025-06-18", "capabilities": {}, "clientInfo": {"name": "validate-ac", "v …(initialize, truncated)
<<< {"jsonrpc":"2.0","id":0,"result":{"capabilities":{"logging":{},"tools":{"listChanged":true}},"instructions":"# Collibra MCP Server\n\nThis server connects y …(initialize, truncated)
>>> {"jsonrpc": "2.0", "method": "notifications/initialized"}
>>> {"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "list_asset_types", "arguments": {"limit": 1}}}
<<< {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"HTTP 401: {\"statusCode\":401,\"titleMessage\":\"Unauthorized\",\"helpMessage\":\"Please check the application logs for more information.\",\"userMessage\":\"Failed to authenticate request through basic credentials\",\"errorCode\":\"authenticationFailed\"}"}],"isError":true}}
>>> {"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "list_asset_types", "arguments": {"limit": 1}}}
<<< {"jsonrpc":"2.0","id":2,"result":{"content":[{"type":"text","text":"HTTP 401: {\"statusCode\":401,\"titleMessage\":\"Unauthorized\",\"helpMessage\":\"Please check the application logs for more information.\",\"userMessage\":\"Failed to authenticate request through basic credentials\",\"errorCode\":\"authenticationFailed\"}"}],"isError":true}}
2026/11/13 20:10:36 WARN Using a single basic auth header for all requests is not recommended as it will result in all actions being attributed to the same account. Consider setting an appropriate basic auth header for each request.
2026/11/13 20:10:36 INFO Calling tool: list_asset_types tool_name=list_asset_types
2026/11/13 20:10:37 WARN Could not resolve the current user, x-mcp-user-id will not be sent: status 401
2026/11/13 20:10:37 INFO Calling tool: list_asset_types tool_name=list_asset_types
Logging proxy record (chip -> DGC):
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/users/current -> 401 (426.5ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Accept": "application/json", "Authorization": "Basic QWRtaW46d3Jvbmc=", "Content-Type": "application/json", "Accept-Encoding": "gzip"}
resp body: {"statusCode":401,"titleMessage":"Unauthorized","helpMessage":"Please check the application logs for more information.","userMessage":"Failed to authenticate request through basic credentials","errorCode":"authentication
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=1 -> 401 (423.8ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Authorization": "Basic QWRtaW46d3Jvbmc=", "Content-Type": "application/json", "Traceparent": "00-4dfcf3a74f87d99bf36ca299e6163ab4-64709ad4ca000844-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "Accept-Encoding": "gzip"}
resp body: {"statusCode":401,"titleMessage":"Unauthorized","helpMessage":"Please check the application logs for more information.","userMessage":"Failed to authenticate request through basic credentials","errorCode":"authentication
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=1 -> 401 (429.6ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Authorization": "Basic QWRtaW46d3Jvbmc=", "Content-Type": "application/json", "Traceparent": "00-182986fe2030ba3ee0017aab6efe987f-a774c126e028f5d0-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "Accept-Encoding": "gzip"}
resp body: {"statusCode":401,"titleMessage":"Unauthorized","helpMessage":"Please check the application logs for more information.","userMessage":"Failed to authenticate request through basic credentials","errorCode":"authentication
Run 5 — after nginx patch: stdio Basic Admin, then http Basic pesto-vac-user2
MCP JSON-RPC (raw):
>>> {"jsonrpc": "2.0", "id": 0, "method": "initialize", "params": {"protocolVersion": "2025-06-18", "capabilities": {}, "clientInfo": {"name": "validate-ac", "v …(initialize, truncated)
<<< {"jsonrpc":"2.0","id":0,"result":{"capabilities":{"logging":{},"tools":{"listChanged":true}},"instructions":"# Collibra MCP Server\n\nThis server connects y …(initialize, truncated)
>>> {"jsonrpc": "2.0", "method": "notifications/initialized"}
>>> {"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "list_asset_types", "arguments": {"limit": 1, "name": "Business Term"}}}
<<< {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"{\"assetTypes\":[{\"description\":\"A word or phrase that is used to describe something or to express a concept in a particular kind of language or branch of business.\\n\\nExamples: Customer, Person Purchase Count, Loan Amount.\",\"displayNameEnabled\":false,\"finalType\":false,\"id\":\"00000000-0000-0000-0000-000000011001\",\"name\":\"Business Term\",\"product\":\"GLOSSARY\",\"publicId\":\"BusinessTerm\",\"ratingEnabled\":false,\"system\":true}],\"limit\":1,\"offset\":0,\"resultsTruncated\":false,\"scanned\":0,\"status\":\"success\",\"total\":1}"}],"structuredContent":{"assetTypes":[{"description":"A word or phrase that is used to describe something or to express a concept in a particular kind of language or branch of business.\n\nExamples: Customer, Person Purchase Count, Loan Amount.","displayNameEnabled":false,"
2026/11/13 20:11:43 WARN Using a single basic auth header for all requests is not recommended as it will result in all actions being attributed to the same account. Consider setting an appropriate basic auth header for each request.
2026/11/13 20:11:43 INFO Calling tool: list_asset_types tool_name=list_asset_types
>>> POST http://localhost:8091/ headers={"Content-Type": "application/json", "Accept": "application/json, text/event-stream", "Authorization": "Basic cGVzdG8tdmFjLXVzZXIyOmFkbWlu"}
>>> {"jsonrpc": "2.0", "id": 0, "method": "initialize", "params": {"protocolVersion": "2025-06-18", "capabilities": {}, "clientInfo": {"name": "validate-ac", "v …(initialize, truncated)
<<< HTTP 200
<<< event: message
data: {"jsonrpc":"2.0","id":0,"result":{"capabilities":{"logging":{},"tools":{"listChanged":true}},"instructions":"# Collibra MCP Server\n\nThis server connects …(initialize, truncated)
>>> POST http://localhost:8091/ headers={"Content-Type": "application/json", "Accept": "application/json, text/event-stream", "Authorization": "Basic cGVzdG8tdmFjLXVzZXIyOmFkbWlu"}
>>> {"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "list_asset_types", "arguments": {"limit": 1, "name": "Business Term"}}}
<<< HTTP 200
<<< event: message
data: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"{\"assetTypes\":[{\"description\":\"A word or phrase that is used to describe something or to express a concept in a particular kind of language or branch of business.\\n\\nExamples: Customer, Person Purchase Count, Loan Amount.\",\"displayNameEnabled\":false,\"finalType\":false,\"id\":\"00000000-0000-0000-0000-000000011001\",\"name\":\"Business Term\",\"product\":\"GLOSSARY\",\"publicId\":\"BusinessTerm\",\"ratingEnabled\":false,\"system\":true}],\"limit\":1,\"offset\":0,\"resultsTruncated\":false,\"scanned\":0,\"status\":\"success\",\"total\":1}"}],"structuredContent":{"assetTypes":[{"description":"A word or phrase that is used to describe something or to express a concept in a particular kind of language or branch of business.\n\nExamples: Customer, Person Purchase Count, Loan Amount.","displayNameEnabled":false
Logging proxy record (chip -> DGC):
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/users/current -> 200 (25.4ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Accept": "application/json", "Authorization": "Basic QWRtaW46YWRtaW4=", "Content-Type": "application/json", "Accept-Encoding": "gzip"}
resp body: {"id":"00000000-0000-0000-0000-000000900002","createdBy":"00000000-0000-0000-0000-000000900001","createdOn":1794599788313,"lastModifiedBy":"00000000-0000-0000-0000-000000900001","lastModifiedOn":1794600222152,"system":fa
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=1&name=Business+Term -> 200 (22.5ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Authorization": "Basic QWRtaW46YWRtaW4=", "Content-Type": "application/json", "Traceparent": "00-91d27483b4455f305dfac7c28ac0ccba-029c6055c322b6d6-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "X-Mcp-User-Id": "00000000-0000-0000-0000-000000900002", "Accept-Encoding": "gzip"}
resp body: {"total":1,"offset":0,"limit":1,"results":[{"id":"00000000-0000-0000-0000-000000011001","createdBy":"00000000-0000-0000-0000-000000900001","createdOn":1794599788313,"lastModifiedBy":"00000000-0000-0000-0000-000000900001"
GET http://dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400/rest/2.0/assetTypes?excludeMeta=true&limit=1&name=Business+Term -> 200 (21.7ms)
req headers: {"Host": "dgc-gateway.dgc-af3a7b6ebec4.svc.cluster.local:4400", "User-Agent": "Collibra MCP/0.0.0-SNAPSHOT", "Authorization": "Basic cGVzdG8tdmFjLXVzZXIyOmFkbWlu", "Content-Type": "application/json", "Traceparent": "00-40832b3f149a11b148ad4f3454245793-f11d26023e42a226-01", "X-Mcp-Session-Id": "", "X-Mcp-Tool-Name": "list_asset_types", "X-Mcp-User-Id": "01a1d684-7fce-71cd-a1fc-fd153d0ec38b", "Accept-Encoding": "gzip"}
resp body: {"total":1,"offset":0,"limit":1,"results":[{"id":"00000000-0000-0000-0000-000000011001","createdBy":"00000000-0000-0000-0000-000000900001","createdOn":1794599788313,"lastModifiedBy":"00000000-0000-0000-0000-000000900001"
nginx.conf BEFORE (ConfigMap dgc-gateway)
events { worker_connections 1024; }
http {
map $http_host $forwarded_port {
~:(?<port>[0-9]+)$ $port;
default 80;
}
map $upstream_http_content_security_policy $csp_without_upgrade {
'~*^(?<before>(?:.*;)?\s*)upgrade-insecure-requests\s*;\s*(?<after>.*)$' $before$after;
'~*^(?:(?<before>.*?)\s*;)?\s*upgrade-insecure-requests\s*$' $before;
default $upstream_http_content_security_policy;
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' '';
}
client_max_body_size 256m;
proxy_read_timeout 120s;
proxy_send_timeout 120s;
server {
listen 4400;
location = /rest/oauth/v2 {
proxy_pass http://auth.dgc-af3a7b6ebec4.svc.cluster.local:4557;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_hide_header Strict-Transport-Security;
proxy_hide_header Content-Security-Policy;
add_header Content-Security-Policy $csp_without_upgrade always;
}
location /rest/oauth/v2/ {
proxy_pass http://auth.dgc-af3a7b6ebec4.svc.cluster.local:4557;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_hide_header Strict-Transport-Security;
proxy_hide_header Content-Security-Policy;
add_header Content-Security-Policy $csp_without_upgrade always;
}
location / {
proxy_pass http://dgc.dgc-af3a7b6ebec4.svc.cluster.local:4400;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_hide_header Strict-Transport-Security;
proxy_hide_header Content-Security-Policy;
add_header Content-Security-Policy $csp_without_upgrade always;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Port $forwarded_port;
}
}
}
Shorten the current-user lookup timeout to 500ms and cap the response at 1 MiB. Definitive failures (4xx other than 408/429, 200 without an id) stay cached for 10 minutes; transient ones (timeout, transport error, 5xx, 408, 429, undecodable or oversized body, panic) are cached for 30 seconds. 401/403 are logged at debug level. A panic in the lookup is recovered and still releases waiters. A non-2xx/non-4xx status other than 5xx (e.g. 3xx) is treated as transient, since the requirements only name 4xx as definitive. Co-authored-by: betty-pr-factory-app[bot] <316249552+betty-pr-factory-app[bot]@users.noreply.github.com>
🎯 What does this PR do?
Every request chip sends to DGC now carries an
x-mcp-user-idheader. It holds the UUID of the user the request'sAuthorizationvalue belongs to. This lets DGC attribute MCP traffic to a user.The UUID comes from
GET /rest/2.0/users/current, called with the same credential. The result is cached per credential, so each credential costs at most one lookup per cache lifetime.The lookup is abandoned after 500 milliseconds. A failed lookup sends the request without the header. The short 30 second lifetime for transient failures keeps a struggling DGC from getting a lookup on every request. It also lets the header return soon after DGC recovers.
Tracked as DEV-233767.
✅ Checklist