feat(client): make HTTP User-Agent header configurable - #41
Conversation
There was a problem hiding this comment.
Pull request overview
Adds support for configuring the outbound HTTP User-Agent used by the Phabricator/Phorge client via a new PHABRICATOR_USER_AGENT environment variable, wiring it through config → client construction → httpx.Client headers.
Changes:
- Introduces
DEFAULT_USER_AGENTand auser_agentoverride parameter in client constructors. - Plumbs
PHABRICATOR_USER_AGENTthroughPhabricatorConfigandConduitApp.get_client(stdio + SSE paths). - Adds unit tests and documentation updates for default vs overridden behavior.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Documents PHABRICATOR_USER_AGENT usage. |
| AGENTS.md | Documents PHABRICATOR_USER_AGENT for dev/test workflows. |
| conduit/conduit.py | Reads env var into config and forwards to PhabricatorClient. |
| conduit/client/base.py | Adds DEFAULT_USER_AGENT and user_agent parameter to base client creation. |
| conduit/client/unified.py | Adds user_agent parameter and applies it to basic/enhanced httpx.Client headers. |
| conduit/client/tests/test_enhanced_client.py | Adds tests asserting default and override User-Agent behavior across client variants. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| self.client = httpx.Client( | ||
| headers={ | ||
| "Content-Type": "application/x-www-form-urlencoded", | ||
| "User-Agent": "ModelContextProtocol/1.0 (Autonomous; +https://github.com/modelcontextprotocol/servers)", | ||
| "User-Agent": user_agent or DEFAULT_USER_AGENT, | ||
| }, |
There was a problem hiding this comment.
The new user_agent parameter is only applied when BasePhabricatorClient constructs its own httpx.Client (http_client is None). If a caller provides http_client, user_agent is silently ignored, which can be surprising given the parameter name/docstring; consider either documenting this explicitly, raising when both are provided, or applying the override to the provided client in a controlled way.
Summary:
The Phabricator/Phorge client previously hardcoded two User-Agent strings
("ModelContextProtocol/1.0 (Autonomous; …)" and "… (Enhanced; …)") across
all three HTTP client construction sites. Some Phabricator/Phorge sites
(notably Wikimedia) inspect the User-Agent header for rate-limiting and
require identifying contact information for automated clients, which
made the server unusable against those instances without patching.
This change introduces a new optional PHABRICATOR_USER_AGENT environment
variable that, when set, overrides the default User-Agent sent on every
outbound request. When unset, behavior is unchanged — the existing
default string is preserved verbatim via two new DEFAULT_USER_AGENT
and DEFAULT_ENHANCED_USER_AGENT constants in conduit/client/base.py, so
the change is fully backwards compatible.
The new setting follows the exact same wiring pattern as the existing
PHABRICATOR_PROXY and PHABRICATOR_DISABLE_CERT_VERIFY options:
environment variable → PhabricatorConfig field → PhabricatorClient
kwarg → httpx.Client header. Both stdio and HTTP/SSE transport modes
forward the value.
Changes:
- Added constants in conduit/client/base.py as the single source of
truth for the default header values
- Added user_agent: Optional[str] = None parameter to
BasePhabricatorClient.__init__, EnhancedPhabricatorClient.__init__,
and the backwards-compatible PhabricatorClient.__init__ wrapper
- Added PHABRICATOR_USER_AGENT env var handling to PhabricatorConfig
- Forwarded config.user_agent through ConduitApp.get_client in both
stdio and SSE code paths
- Added unit tests covering default and override behavior across all
three client flavors (basic, enhanced-via-wrapper, direct enhanced)
- Documented the new env var in README.md and AGENTS.md alongside the
existing optional PHABRICATOR_* variables
Key Features:
- Fully backwards compatible: unset env var preserves the original
User-Agent string byte-for-byte
- Works in both stdio and HTTP/SSE transport modes
- Single source of truth for the default value — future changes to the
default touch exactly one line
- Enables use against Phabricator/Phorge instances that require
identifying User-Agent headers (e.g. Wikimedia) without source patches
Test Plan:
- Added test_user_agent_default: asserts DEFAULT_USER_AGENT is applied
on the basic path, DEFAULT_ENHANCED_USER_AGENT on the enhanced path
(triggered via timeout=60.0), and on direct EnhancedPhabricatorClient
construction
- Added test_user_agent_override: asserts a user_agent kwarg overrides
the default on all three of the above paths
- Ran full test suite against phorge_debug Docker container per
AGENTS.md instructions: 299 passed, 1 skipped (was 297 passed before
the two new tests)
- Ran \`pre-commit run -a\`: ruff check, ruff format, and bandit all pass
- Manually verified via MCP client config that setting
PHABRICATOR_USER_AGENT="MyOrg-Phabricator-MCP/1.0 (contact@example.org)"
causes the expected header to be sent on outbound requests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6941102 to
10998c2
Compare
Summary:
The Phabricator/Phorge client previously hardcoded a single User-Agent string ("ModelContextProtocol/1.0 (Autonomous; ...)") across all three HTTP client construction sites. Some Phabricator/Phorge operators (notably Wikimedia) inspect the User-Agent header for rate-limiting and require identifying contact information for automated clients, which made the server unusable against those instances without patching.
This change introduces a new optional PHABRICATOR_USER_AGENT environment variable that, when set, overrides the default User-Agent sent on every outbound request. When unset, behavior is unchanged — the existing default string is preserved verbatim via a new DEFAULT_USER_AGENT constant in conduit/client/base.py, so the change is fully backwards compatible.
The new setting follows the exact same wiring pattern as the existing PHABRICATOR_PROXY and PHABRICATOR_DISABLE_CERT_VERIFY options: environment variable → PhabricatorConfig field → PhabricatorClient kwarg → httpx.Client header. Both stdio and HTTP/SSE transport modes forward the value.
Changes:
Key Features:
Test Plan: