Skip to content

Client/CLI lacks support for extra request headers (e.g. x-adcp-tenant) #583

Description

@bokelley

Problem

Neither AgentConfig (Python SDK) nor uvx adcp (CLI) exposes a way to send arbitrary request headers alongside auth_token. This blocks any caller that needs to pass routing/context headers in addition to the bearer token.

Concrete use case

In salesagent (PSA reference impl), the verify scripts target a localhost server that resolves tenant via the 4-strategy chain in src/core/resolved_identity.py:

  1. Host header → virtual host / subdomain
  2. x-adcp-tenant header
  3. Apx-Incoming-Host header
  4. localhost fallback → \"default\" tenant

When a verify script provisions a fresh test tenant on http://localhost:8000, strategy 1 fails (Host is localhost), so it must send x-adcp-tenant: <provisioned_id> to route to the right tenant. The SDK has no way to do this:

# Today (custom transport works because fastmcp.client accepts a `headers` dict):
from fastmcp.client import Client
from fastmcp.client.transports import StreamableHttpTransport
transport = StreamableHttpTransport(
    url=\"http://localhost:8000/mcp/\",
    headers={\"x-adcp-auth\": token, \"x-adcp-tenant\": tenant_id},
)

# Migrating to the adcp SDK — no equivalent:
from adcp.client import ADCPClient, AgentConfig
config = AgentConfig(
    id=\"verify\",
    agent_uri=\"http://localhost:8000/mcp/\",
    protocol=Protocol.MCP,
    auth_token=token,
    auth_header=\"x-adcp-auth\",
    # ❌ No `headers={\"x-adcp-tenant\": tenant_id}` parameter
)

CLI side has the same gap

$ uvx adcp http://localhost:8000/mcp/ get_products '{...}' --auth TOKEN
# ❌ No --header / -H flag to add x-adcp-tenant

Why this matters for adopters

  • Multi-tenant decisioning platforms behind nginx commonly use a tenant header for path-based routing.
  • Reverse-proxy setups (Cloudflare Workers / Apx-Incoming-Host) need pass-through headers.
  • Test/verify scripts can't migrate from fastmcp.client to the SDK without losing functionality.

Proposed fix

SDK

Add headers: Mapping[str, str] | None = None to AgentConfig. Merge into the request headers after auth_header/auth_token are set, so the SDK retains control of auth but adopters can layer routing/context headers.

config = AgentConfig(
    ...,
    auth_token=token,
    headers={\"x-adcp-tenant\": tenant_id},
)

CLI

Add --header KEY=VALUE (repeatable) to uvx adcp and the --save-auth agent config schema:

adcp <agent> get_products '{...}' --auth TOKEN --header x-adcp-tenant=acme --header x-foo=bar

Persist via --save-auth:

{
  \"agents\": {
    \"local\": {
      \"url\": \"http://localhost:8000/mcp\",
      \"protocol\": \"mcp\",
      \"auth_token\": \"...\",
      \"headers\": {\"x-adcp-tenant\": \"acme\"}
    }
  }
}

Acceptance criteria

  • AgentConfig(headers=...) is plumbed through both the MCP and A2A adapters.
  • uvx adcp --header K=V ... works for ad-hoc invocations.
  • ~/.adcp/config.json per-agent headers field is honored on saved agents.
  • Headers do NOT clobber the auth header; auth wins on conflict (with a warning).

Related

  • Companion issue filed against the JS/TS CLI in adcontextprotocol/adcp-client (same gap).
  • salesagent migration tracking: replacing fastmcp.client direct calls with the SDK — currently blocked on this for verify scripts that hit localhost with x-adcp-tenant.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions