inspector/core/auth/remote/storage-remote.ts
Cliff Hall 82269e78cb
refactor(core): apply v1.5-port cleanups deferred from #1306 (#1316)
* refactor(core): apply v1.5-port cleanups deferred from #1306

Addresses issue #1309 — five small, mechanical cleanups deferred from the
v1.5 runtime port:

1. Collapse BrowserOAuthStorage / NodeOAuthStorage / RemoteOAuthStorage
   onto a shared OAuthStorageBase. Three ~130-line duplicates become
   thin adapter wrappers; behavior + public API unchanged.
2. Re-enable erasableSyntaxOnly in tsconfig.app.json by rewriting the
   seven (plus two the issue missed in sampling/elicitation create-
   message) parameter-property constructors as explicit field + assign.
3. Route the lone console.error in inspectorClient.ts through this.logger.
4. Replace `${Date.now()}-${Math.random()}` with crypto.randomUUID() at
   the five local-only ID sites (message tracking + sampling/elicit).
5. Pin the remote-server hono app generic at new Hono<Env>() and drop
   the streamSSE cast. Root cause of the cast was an unresolved hono
   subpath: the tsconfig "hono/*" wildcard didn't honor the exports
   map, so hono/streaming leaked to the root-hoisted hono@4.12.12 while
   hono itself resolved to clients/web/hono@4.12.18. Replaced the
   wildcard with an explicit hono/streaming entry in both tsconfig.app
   and tsconfig.test, removing the package-identity mismatch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(core): address #1316 PR review feedback

- Drop the stranded no-op getServerState() read at the top of
  clearClientInformation in OAuthStorageBase (carried over verbatim
  from the three originals).
- Drop the crypto.randomUUID() guard at the task-ID site so all
  six in-scope sites are consistent; the fallback branch was dead
  code on every supported runtime.
- Remove the residual `c as Context` cast at the streamSSE call site
  in core/mcp/remote/node/server.ts — once both hono imports
  resolve to the same package the route-typed Context flows through
  to streamSSE with no cast at all.
- Move the new `options` / `config` field declarations in
  RemoteClientTransport up with the rest of the field block, matching
  the layout used by the other five rewritten classes in this PR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 19:15:48 -04:00

40 lines
1.3 KiB
TypeScript

/**
* Remote HTTP storage implementation for OAuth state.
* Uses Zustand with remote storage adapter (HTTP API).
* For web clients that need to share state with Node apps.
*/
import { OAuthStorageBase } from "../oauth-storage.js";
import { createOAuthStore } from "../store.js";
import { createRemoteStorageAdapter } from "../../storage/adapters/remote-storage.js";
export interface RemoteOAuthStorageOptions {
/** Base URL of the remote server (e.g. http://localhost:3000) */
baseUrl: string;
/** Store ID (default: "oauth") */
storeId?: string;
/** Optional auth token for x-mcp-remote-auth header */
authToken?: string;
/** Fetch function to use (default: globalThis.fetch) */
fetchFn?: typeof fetch;
}
/**
* Remote HTTP storage implementation using Zustand with remote storage adapter.
* Stores OAuth state via HTTP API (GET/POST/DELETE /api/storage/:storeId).
* For web clients that need to share state with Node apps (TUI, CLI).
*/
export class RemoteOAuthStorage extends OAuthStorageBase {
constructor(options: RemoteOAuthStorageOptions) {
super(
createOAuthStore(
createRemoteStorageAdapter({
baseUrl: options.baseUrl,
storeId: options.storeId ?? "oauth",
authToken: options.authToken,
fetchFn: options.fetchFn,
}),
),
);
}
}