Skip to content

Identify the CLI as the caller via X-Shopify-Agent-Source header - #12

Merged
joerj123 merged 3 commits into
mainfrom
add-shop-cli-agent-source-header
Jun 11, 2026
Merged

Identify the CLI as the caller via X-Shopify-Agent-Source header#12
joerj123 merged 3 commits into
mainfrom
add-shop-cli-agent-source-header

Conversation

@joerj123

Copy link
Copy Markdown
Collaborator

What

Send an X-Shopify-Agent-Source: shop-cli header on every outbound MCP request so the catalog / UCP endpoints can attribute Shop CLI traffic server-side.

The header is added in the single callMcp chokepoint in src/shop-client.ts, so it rides on all MCP calls — global-catalog reads (search_catalog, lookup_catalog, get_product) and per-shop UCP checkout calls — for both authenticated and unauthenticated requests. The caller's own headers are spread last so an explicit override always wins.

Why

We're moving the Shop Skill (and other surfaces) to call the Global Catalog MCP endpoint directly instead of going through the Shop Proxy. Today, unauthenticated catalog calls carry no client_id and collapse into a single anonymous bucket keyed only by source IP — so we can't say "X searches came from Shop CLI" and we lose top-of-funnel attribution.

Per the Slack discussion, the agreed approach is a transport header rather than a UCP schema/API change: it's orthogonal to the protocol, invisible to the public UCP contract, trivial for first-party clients to set, and trivial to log into the existing tool-call Monorail event server-side. This PR is the client half of that; the server side picks the header up and adds it to the Monorail event.

Important caveat

The value is self-asserted analytics/funnel metadata only. It is spoofable, so it must never feed trust, fraud, or rate-limiting decisions — those stay keyed on auth tier + IP. Documented as such in references/catalog-mcp.md and the code comments.

Naming note: the thread proposed X-Shopify-Agent-Source with snake_case values (shop_skill, ucp_cli, …). I used the kebab value shop-cli to match the repo/package name and the request. Happy to switch to shop_cli (or another header name) if that's the convention the server-side logging lands on.

Changes

  • src/constants.ts — add AGENT_SOURCE_HEADER (X-Shopify-Agent-Source) and AGENT_SOURCE (shop-cli).
  • src/shop-client.ts — inject the header into callMcp.
  • tests/catalog.test.ts — assert the header is sent on catalog calls.
  • references/catalog-mcp.md — document the header.
  • changeset (minor).

Testing

  • pnpm typecheck
  • pnpm test ✅ (80 passing, including the new case)
  • pnpm build

joerj123 and others added 3 commits June 11, 2026 11:28
Send X-Shopify-Agent-Source: shop-cli on every outbound MCP request from
the single callMcp chokepoint, so the catalog/UCP endpoints can attribute
Shop CLI traffic server-side. This closes the gap where unauthenticated
global-catalog searches otherwise collapse into one anonymous bucket.

The value is self-asserted analytics-only metadata: it is spoofable and
must never be used for trust, fraud, or rate-limiting decisions.
@joerj123
joerj123 merged commit 101c0b8 into main Jun 11, 2026
1 check passed
@joerj123
joerj123 deleted the add-shop-cli-agent-source-header branch June 11, 2026 12:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant