Skip to content

Add device sweep to resolve Claude connector UUIDs#217

Closed
zeus-12 wants to merge 2 commits into
stagingfrom
vv/backfill-uuid-mcp-connectors
Closed

Add device sweep to resolve Claude connector UUIDs#217
zeus-12 wants to merge 2 commits into
stagingfrom
vv/backfill-uuid-mcp-connectors

Conversation

@zeus-12

@zeus-12 zeus-12 commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

What

Adds a device-side sweep that resolves bare Claude connector UUIDs to their real names so the control plane can group/policy them. Companion backend change: ai-gateway-data PR (vv/backfill-uuid-mcp-connectors).

Claude desktop OAuth remote connectors are named by a per-registration UUID at runtime. The real display name only exists in the local Claude session files on the device — the backend can't resolve it alone.

How (sweep_connectors.py)

  1. GET /api/v1/ai-tools/unresolved-connector-uuids/ — the opaque list of UUIDs the backend still needs resolved.
  2. Read the local session files in both folders (claude-code-sessions = Claude Code, local-agent-mode-sessions = CoWork) → remoteMcpServersConfig{uuid, name, tools}, de-duped across folders.
  3. For each UUID the backend asked for and we can resolve locally, POST the real name + tools + originating connector_uuid to /api/v1/ai-tools/mcp-server-scan/.

Only UUIDs the backend explicitly requested ever leave the device — nothing else from the session files is sent. HTTP uses curl per the Zscaler constraint (no urllib).

Notes

  • Standalone script for now; wiring it into the tool's existing scan cycle is a follow-up.
  • Validated against a real machine: resolves Gmail / Google Calendar / Notion / Linear, dedupes the two Google Calendar UUIDs.
  • Automated test coverage not included in this PR.

🤖 Generated with Claude Code


Note

Medium Risk
The script reads local Claude session data and posts connector metadata to the control plane using a bearer API key; scope is limited to backend-requested UUIDs and omits session URLs.

Overview
Adds a standalone sweep_connectors.py script so devices can backfill bare Claude OAuth connector UUIDs with human-readable names and tool lists the control plane cannot infer from gateway traffic alone.

The sweep GETs /api/v1/ai-tools/unresolved-connector-uuids/, parses remoteMcpServersConfig from Claude Code and CoWork session JSON (newest files first, tools merged only when the UUID shares the same name), then POSTs each backend-requested match to /api/v1/ai-tools/mcp-server-scan/ with connector_uuid, display name, claude-connector scope, and scan tools. Session url is not included in the payload. HTTP is done via curl --config (aligned with scan_single_mcp_server.py and Zscaler constraints), with UNBOUND_API_KEY / --api-key auth.

Not wired into the main discovery scan cycle yet; intended as a companion to the ai-gateway-data backfill work.

Reviewed by Cursor Bugbot for commit cb932fd. Bugbot is set up for automated code reviews on this repo. Configure here.

Greptile Summary

This PR adds a standalone sweep for resolving Claude connector UUIDs. The main changes are:

  • Reads local Claude Code and CoWork session files for connector names and tools.
  • Fetches unresolved connector UUIDs from the control plane.
  • Reports only locally matched connector UUIDs back to the scan endpoint.
  • Handles duplicate connector entries and curl transport failures.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
scripts/coding_discovery_tools/sweep_connectors.py Adds the Claude connector UUID sweep and follow-up handling for URL omission, duplicate UUID conflicts, and curl errors.

Reviews (2): Last reviewed commit: "Address review feedback in connector swe..." | Re-trigger Greptile

Fetch the backend's unresolved-UUID list, match each against the local Claude
session files (Claude Code + CoWork folders), and report the resolved name +
tools back via the single-server scan endpoint with the originating UUID. Only
UUIDs the backend asked for are sent; HTTP via curl per the Zscaler constraint.
@zeus-12 zeus-12 requested a review from a team June 26, 2026 21:21
Comment thread scripts/coding_discovery_tools/sweep_connectors.py Outdated
Comment thread scripts/coding_discovery_tools/sweep_connectors.py Outdated
Comment thread scripts/coding_discovery_tools/sweep_connectors.py

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 23ea63a. Configure here.

Comment thread scripts/coding_discovery_tools/sweep_connectors.py
Comment thread scripts/coding_discovery_tools/sweep_connectors.py Outdated

@vigneshsubbiah16 vigneshsubbiah16 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛡️ Automated Security Review (consensus)

2 findings — 1 high-confidence, 1 to triage. Reviewers: Cursor, Claude, Semgrep, Gitleaks.

🔴 HIGH — Local connector url sent beyond documented device scope

scripts/coding_discovery_tools/sweep_connectors.py:154-155 (also report_connector ~143-165)

Impact: Resolved sweeps POST the session file's url to the control plane even though the PR contract and module doc state only {name, tools, connector_uuid} leave the device — expanding disclosure of private MCP endpoint metadata the backend never requested.

Fix: Remove url from the report payload to match the documented contract, or explicitly extend the PR/backend scope and treat url as sensitive data end-to-end.

Flagged by: Greptile, Claude, Lead


🟡 TRIAGE — Conflicting duplicate UUIDs merged without identity checks

scripts/coding_discovery_tools/sweep_connectors.py:86-95

Impact: When the same UUID appears in multiple session files, merge logic keeps the first name/URL and unions tools from later entries — a stale or conflicting file can report connector A's identity with connector B's tools, folding the UUID into the wrong grouped fingerprint on the control plane.

Fix: Skip or split on name/URL mismatches before unioning tools (e.g., only merge when name and URL agree, or prefer the newest session file).

Flagged by: Greptile, Cursor


🤖 consensus review · reviewers: Cursor,Claude,Semgrep,Gitleaks · head 23ea63a2 · 2026-06-26T21:32Z

- don't send the session url (not needed; keeps name-based grouping)
- read session files newest-first; union tools only across same-name entries
- raise on curl failure so DNS/TLS/timeout reasons surface
- normalize UUIDs (lower+strip) on both the needed list and local entries
@vigneshsubbiah16

Copy link
Copy Markdown
Contributor

🛡️ Automated Security Review (consensus)

0 findings — 0 high-confidence, 0 to triage. Reviewers: Cursor, Claude, Semgrep, Gitleaks.

✅ Security consensus: no issues found. (reviewers: Cursor, Claude, Semgrep, Gitleaks)

Previously acknowledged (not re-flagged)

  • Session url leaving the device (sweep_connectors.py) — Addressed by design: read_local_connectors intentionally omits url; only backend-requested UUIDs plus name/tools are posted to the control plane.

🤖 consensus review · reviewers: Cursor,Claude,Semgrep,Gitleaks · head cb932fdd · 2026-06-29T09:35Z

@zeus-12 zeus-12 closed this Jun 29, 2026
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.

2 participants