feat: add plugin attribution via operation_context (Phase 2)#56
Open
arorashivam96 wants to merge 6 commits into
Open
feat: add plugin attribution via operation_context (Phase 2)#56arorashivam96 wants to merge 6 commits into
arorashivam96 wants to merge 6 commits into
Conversation
Add get_client() and get_plugin_headers() helpers to auth.py that build
a single operation_context string (app/skill/agent) and pass it to the
Python SDK, which appends it to the User-Agent header on all outbound
requests.
Changes:
- auth.py: new helpers with closed-schema allowlists for skill and agent
- dv-data, dv-query, dv-metadata, dv-solution: migrate Setup blocks to
get_client("<skill>") — simpler 2-line pattern
- dv-connect: write DATAVERSE_PLUGIN_VERSION and DATAVERSE_PLUGIN_AGENT
to .env; include DATAVERSE_OPERATION_CONTEXT in MCP registration env
- Version bump: 1.4.5 -> 1.5.0 (MINOR — new capabilities)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…comments Update auth.py to use the SDK's OperationContext class (not plain string) and the renamed `context` kwarg on DataverseClient. Add regex validation in auth.py matching the SDK's own format check as a defense-in-depth layer. Add inline comments to all skill code blocks warning not to modify the context value and not to include secrets or PII. The context uses a closed schema (app/skill/agent from allowlists) — free-form text, emails, and special characters are rejected by both auth.py and the SDK. Also migrates remaining Level 3 reference files (multi-table-fk-import, sample-data-generation, alternate-keys) from get_credential to get_client for consistency. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add get_client as the preferred auth pattern in CLAUDE.md skill authoring rules, alongside existing get_credential and get_token - Fix dv-connect Step 3: add missing plugin_version = "1.5.0" in the .env writer code block (was referenced but never defined) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The hardcoded plugin_version in dv-connect Step 3 is now a 5th place the version lives. Update: - static_checks.py: EVAL-VERSION-01/02 now check dv-connect SKILL.md plugin_version alongside the 4 JSON manifest fields - CLAUDE.md: Version Bumping section lists all 5 locations Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
saurabhrb
requested changes
May 15, 2026
| ```python | ||
| import os | ||
|
|
||
| plugin_version = "1.5.0" |
Contributor
There was a problem hiding this comment.
anyway, at least in these scripts to extract version from json files? rather than one more set of hard coded versions?
Contributor
Author
There was a problem hiding this comment.
- dv-connect Step 3 now reads version from .claude-plugin/plugin.json (with marketplace.json as fallback), eliminating the hardcoded plugin_version = "1.5.0"
- Reverted CLAUDE.md back to 4 version locations (the 5th no longer exists)
- Reverted static_checks.py — removed the _extract_dv_connect_plugin_version helper and the 5th check
| 5. Register the MCP server (Copilot: write JSON config; Claude: run `claude mcp add` command) | ||
| 6. Handle admin consent and environment allowlist (one-time per tenant/environment) | ||
|
|
||
| **Plugin attribution for MCP:** When registering the stdio MCP server, include `DATAVERSE_OPERATION_CONTEXT` in the env block so the CLI appends it to its User-Agent on all outbound requests. Build the value from `.env`: |
Contributor
There was a problem hiding this comment.
can we confirm if we are using actual mcp server using orgurl/mcp http mcp server or a local stdio mcp server?
based on that this statement might change
Contributor
Author
There was a problem hiding this comment.
- Step 6 now explicitly states "stdio proxy" transport (npx @microsoft/dataverse mcp ) and explains that DATAVERSE_OPERATION_CONTEXT works because the CLI runs as a local subprocess that reads env
vars at startup
Address PR review feedback: - dv-connect Step 3: read plugin_version from .claude-plugin/plugin.json instead of hardcoding it. Falls back to marketplace.json, then "unknown". Eliminates the 5th version location that required manual sync. - dv-connect Step 6: clarify that the plugin uses stdio proxy transport (npx @microsoft/dataverse mcp <url>), not direct HTTP-streamable MCP. Add note about X-Dataverse-Plugin header for future HTTP-streamable agents. - Revert CLAUDE.md and static_checks.py back to 4 version locations since the hardcoded version no longer exists. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove the X-Dataverse-Plugin header note from dv-connect Step 6. Dataverse does not log custom headers in telemetry, so this approach is not viable for HTTP-streamable MCP attribution. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.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
Add plugin attribution to all outbound Dataverse requests via User-Agent tagging. Every SDK call, raw Web API call, and MCP proxy request now carries a closed-schema operation_context identifying the plugin version, skill, and agent — enabling server-side MAU/MAT, skill split, and agent distribution dashboards from existing Dataverse logs.
What changed
scripts/auth.py— Two new helpers centralize attribution:get_client(skill)— returns aDataverseClientwithOperationContextbaked into the UAget_plugin_headers(skill, token)— returns headers dict for raw Web API calls with UA attribution_ALLOWED_SKILLS,_ALLOWED_AGENTS) and a strict regex. Free-form text, PII, emails, and unknown keys are rejected withValueError.Skill Setup blocks — All 4 SDK-using skills (dv-data, dv-query, dv-metadata, dv-solution) migrated from the 4-line
DataverseClient(...)pattern toget_client("<skill>"). Each block includes an inline comment: "Do not modify the context value — it is a closed schema for server-side telemetry. Never include secrets or PII."Level 3 references — multi-table-fk-import.md, sample-data-generation.md, alternate-keys.md also migrated.
dv-connect Step 3 — Writes
DATAVERSE_PLUGIN_VERSIONandDATAVERSE_PLUGIN_AGENTto.env(version hardcoded, agent auto-detected fromCLAUDECODE/VSCODE_PID/CURSOR_TRACE_DIRenv vars).dv-connect Step 6 — Adds
DATAVERSE_OPERATION_CONTEXTguidance for MCP server registration env block.dv-overview — Updated routing hint from
get_credentialtoget_client.CLAUDE.md — Updated auth pattern section to list
get_clientas the preferred import alongside existingget_credentialandget_token.Version — 1.4.5 -> 1.5.0 (MINOR: new backward-compatible capabilities).
Resulting User-Agent per channel
DataverseSvcPythonClient:0.1.0b10 (app=dataverse-skills/1.5.0;skill=dv-data;agent=claude-code)DataverseCli/1.0.0 (app=dataverse-skills/1.5.0;agent=claude-code)Python-urllib (app=dataverse-skills/1.5.0;skill=dv-metadata;agent=claude-code)Depends on
OperationContext+contextkwarg (merged)feat/operation-contexton DataverseCLI —--contextflag +DATAVERSE_OPERATION_CONTEXTenv var (merged)Test plan
python .github/evals/static_checks.py— passes (only pre-existing dv-overview token budget warning)get_clientwith correct skill names and attribution comments in generated scriptsget_credentialandget_tokenstill work for advanced/raw-API cases🤖 Generated with Claude Code