Repository navigation
Simplify the extension's daemon client boundary across HTTP and MCP operations #4225
Description
Priority: P2 · Type: proposal
Problem
The ChatGPT extension constructs and maintains two daemon-facing client mechanisms for one code-exploration workflow. Some operations use an authenticated HTTP application endpoint; others require an MCP tracedecay serve session. This leaks transport choices into project acquisition, registry access, lifecycle management, and error adaptation.
The registry client is instantiated with baseUrl: "http://127.0.0.1", projectId: "registry", and token: "unused-registry-reads-use-mcp" solely to satisfy a client configuration shape while supplying an MCP adapter. Project acquisition pairs a serve session with an HTTP SDK client. The documented operation split includes MCP registry/search/node/impact/status operations alongside HTTP symbol-search/caller/callee/declaration operations.
Each MCP session uses a spawned stdio transport. The SDK selects transport and changes result handling, while the bridge handles session acquisition and daemon authority separately. These are observable source responsibilities, not merely different names for the same helper.
Proposed change
Define one coherent daemon-client admission boundary for the extension. Reuse the existing canonical operation catalog and generated contracts to determine operation identity, accepted inputs, result semantics, and execution policy. The client should express registry versus project scope directly and should not need fictitious endpoints or credentials to invoke a valid operation.
Choose the underlying transport arrangement after inventorying authority requirements. A unified client may expose legitimate separate registry and project capabilities internally; it need not flatten every operation onto one public HTTP route or permission scope. The audited catalog includes 90 MCP-backed SDK operations with potentially different admission needs, so migrating them wholesale without reviewing those needs is out of scope.
Consolidate connection/session ownership and error translation where possible, remove unnecessary per-project process plumbing once an equivalent daemon path exists, and preserve compatibility for remaining MCP hosts. If HTTP and MCP remain intentionally distinct, isolate that choice beneath one typed facade with accurate configuration types rather than placeholder values.
Relationship to native SDK work
A napi-rs wrapper around the existing Rust SDK still inherits its HTTP/MCP split and caller-owned MCP transport. Native bindings alone do not remove this bridge complexity. This proposal is a separate transport/admission cleanup and must preserve the existing daemon as the authority.
Acceptance criteria
- Registry operations have an explicit projectless or profile-scoped client capability with no fake project ID, URL, or token.
- Project operations retain authenticated, validated project scope; unavailable or unauthorized projects do not fall through to a different authority.
- The extension has one documented client/session ownership path with deterministic shutdown and daemon-restart handling.
- Canonical deadlines, request identities, cancellation, typed failures, and result contracts survive any transport migration.
- Existing MCP consumers retain required callability; no operation gains broader HTTP exposure merely to simplify the extension.
- Conformance exercises registry discovery, project selection, code reads, denied/unavailable states, cancellation, and concurrent session acquisition.
- Remove the superseded bridge/process/error code after migration; do not add a facade while leaving all duplicate ownership active.
Audit provenance
Source evidence is pinned to 30c23baa. Relevant implementation was rechecked against master at 5daa37d1; the finding remains applicable. Verification performed and its limits are stated above.
Activity
ScriptedAlchemy commentedon Oct 19, 2026
Full-backlog implementation: own the shared client workstream for #4225 and #4226, reading both issues and current code/merged prerequisites before editing. First remove fictitious registry project/URL/token inputs with an explicit typed registry/project admission boundary, centralizing connection/session ownership while preserving legitimate HTTP/MCP authority differences. Then implement the owner-selected generated TypeScript facade -> thin napi-rs -> shared Rust client -> existing daemon path. Keep I/O independently cancellable and off Node's event loop; iterator disposal must not cancel a server operation. Preserve request identity, deadlines, typed failures, numeric boundaries, callbacks/customization or an explicit compatible migration. Use the existing Bazel authority and canonical generators; platform native artifacts and offline plugin packaging must be real, not a fallback to the complete old TS runtime. Verify #4209/#4210/#4211/#4224 dispositions rather than rebuilding closed work. Run installed-consumer, transport/concurrency/shutdown/backpressure and event-loop responsiveness tests with actual counts. No broader HTTP exposure, new engine/storage authority, speculative package-size claims, timeout increases or skipped tests. Coordinate settings-generated outputs with #4275 and manifest cleanup #4339. Deliver reviewable implementation/evidence; keep incomplete platform validation explicit.