feat(sdk): emit X-DevHelm-Surface telemetry headers#19
Merged
Conversation
Adds optional surface identification to every authenticated API call so the API can attribute usage to the right devtool. Wire contract documented at https://devhelm.io/telemetry; the matching API-side handler shipped in mono#332. Headers emitted by default (every request): - X-DevHelm-Surface: sdk-py - X-DevHelm-Surface-Version: <package version> - X-DevHelm-Sdk-Name: sdk-py Wrappers (e.g. devhelm-mcp-server) override `surface` / `surface_version` at construction time so their traffic is attributed correctly: Devhelm(token=..., surface="mcp", surface_version="0.5.0", surface_metadata={"Mcp-Client": "cursor"}) The SDK identity (`X-DevHelm-Sdk-Name`) is preserved alongside the wrapper surface so the API can still distinguish "wrapper on top of a v0.5 SDK" from "wrapper on top of a v0.6 SDK" when debugging client- version skew. Opt-out is intentionally a single env var, not per-call: `DEVHELM_TELEMETRY=0` drops every X-DevHelm-Surface* header at the client level. Auth + tenant headers are unaffected. Zero callsite changes — surface is set once when the Devhelm client is constructed, every existing tool/test using `Devhelm(...)` keeps working unchanged. Tests: 3 new tests in test_http.py covering defaults, wrapper override, and opt-out. Full suite (716) green; ruff + mypy clean. Co-authored-by: Cursor <cursoragent@cursor.com>
The new `surface` / `surface_version` / `surface_metadata` constructor kwargs are an additive feature; downstream wrappers (e.g. devhelm-mcp-server) need to pin `devhelm>=0.6.0` to use them, so cutting a minor bump. Co-authored-by: Cursor <cursoragent@cursor.com>
This was referenced May 1, 2026
caballeto
added a commit
to devhelmhq/mcp-server
that referenced
this pull request
May 2, 2026
Constructs the underlying devhelm.Devhelm SDK with surface="mcp" so the API attributes traffic to the MCP server rather than to bare-SDK use. The SDK's X-DevHelm-Sdk-Name header is preserved alongside, so the API can still see which devhelm SDK version this MCP build is on for client-version skew debugging. Surface version comes from importlib.metadata; reports the installed devhelm-mcp-server release. Falls back to "unknown" for source-tree installs. Detecting the host MCP client (Cursor vs Claude Desktop vs ...) is deferred — fastmcp's Context.session.client_params.clientInfo carries that info, but threading Context through every tool would be a wide surgery against this PR's "no callsite changes" goal. The wire contract already supports X-DevHelm-Mcp-Client via surface_metadata so we can layer it in later without an API change. Depends on devhelm>=0.6.0 (which ships the surface=/surface_version=/ surface_metadata= constructor kwargs). pyproject pin bumped accordingly. Tests: 1 new test in test_client.py asserting the SDK is built with the mcp surface override. Full suite (58) green; ruff + mypy clean. Wire contract docs: https://devhelm.io/telemetry API-side handler: devhelmhq/mono#332 SDK-side change: devhelmhq/sdk-python#19 Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Reports the SDK's identity to the DevHelm API on every authenticated request so the API can attribute usage to the right devtool. Wire contract documented at https://devhelm.io/telemetry; the matching API-side handler shipped in devhelmhq/mono#332.
What lands on the wire (defaults)
Wrapper override (e.g. MCP server)
```python
Devhelm(
token=...,
surface="mcp",
surface_version="0.5.0",
surface_metadata={"Mcp-Client": "cursor"},
)
```
The SDK identity (`X-DevHelm-Sdk-Name: sdk-py`) is preserved alongside the wrapper surface so the API can distinguish "wrapper on top of v0.5 SDK" from "wrapper on top of v0.6 SDK" when debugging client-version skew.
Opt-out
`DEVHELM_TELEMETRY=0` drops every `X-DevHelm-Surface*` header at the client level. Single env var, not per-call. Auth and tenant headers are unaffected.
Zero callsite changes
Surface is set once when `Devhelm(...)` is constructed. Every existing tool/test using the SDK keeps working unchanged.
Tests
Test plan
Made with Cursor