From 38c6f99bce6ca48249b032fa43bac7fc6a868b80 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 6 Dec 2025 02:24:45 +0100 Subject: [PATCH] chore: store oauth vault in credentials.json --- CHANGELOG.md | 2 +- docs/config.md | 2 +- src/oauth-persistence.ts | 2 +- src/oauth-vault.ts | 2 +- tests/oauth-persistence.test.ts | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b15443..3bbec9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ## [0.7.0] - 2025-12-06 ### CLI -- Centralized OAuth credentials in a shared vault (`~/.mcporter/.credentials.json`) while still honoring per-server `tokenCacheDir` when present; legacy per-server caches are migrated automatically. +- Centralized OAuth credentials in a shared vault (`~/.mcporter/credentials.json`) while still honoring per-server `tokenCacheDir` when present; legacy per-server caches are migrated automatically. - `mcporter auth --reset` now clears the vault and legacy caches without crashing on corrupted credential files, making re-auth reliable for servers like Gmail. - StdIO servers that expose a separate auth subcommand (e.g., Gmail MCP) can now declare `oauthCommand.args`; `mcporter auth ` will spawn that helper and wait for browser completion, so Gmail auth now works without running npx manually. - Raw output now prints full strings without Node’s 10k-character truncation (`util.inspect` uses `maxStringLength: null`), so large MCP responses and plans are preserved end-to-end. diff --git a/docs/config.md b/docs/config.md index 683c2ec..22cab40 100644 --- a/docs/config.md +++ b/docs/config.md @@ -147,7 +147,7 @@ Server definition fields (subset of what `RawEntrySchema` accepts): | `env` | Key/value pairs applied when launching stdio commands. Supports `${VAR}` interpolation and `${VAR:-fallback}` defaults. Existing process env values win over fallbacks. | | `headers` | Request headers for HTTP/SSE transports. Values can reference `$env:VAR` or `${VAR}` placeholders, which must be set at runtime or mcporter aborts with a helpful error. | `auth` | Currently only `oauth` is recognized. Any other string is ignored (treated as undefined) to avoid stale state from other clients. | -| `tokenCacheDir` | Directory for OAuth tokens; still honored, but mcporter now keeps a centralized vault in `~/.mcporter/.credentials.json` (legacy per-server caches are auto-migrated). Supports `~` expansion. | +| `tokenCacheDir` | Directory for OAuth tokens; still honored, but mcporter now keeps a centralized vault in `~/.mcporter/credentials.json` (legacy per-server caches are auto-migrated). Supports `~` expansion. | | `clientName` | Optional identifier some servers use for telemetry/audience segmentation. | | `oauthRedirectUrl` | Override the default localhost callback. Useful when tunneling OAuth through Codespaces or remote dev boxes. | | `oauthCommand.args` | For STDIO servers that ship a custom auth subcommand (e.g., Gmail MCP). mcporter will spawn the stdio command with these args when you run `mcporter auth `, so you don’t need to call `npx ... auth` manually. | diff --git a/src/oauth-persistence.ts b/src/oauth-persistence.ts index 9bf6619..9093dad 100644 --- a/src/oauth-persistence.ts +++ b/src/oauth-persistence.ts @@ -122,7 +122,7 @@ class VaultPersistence implements OAuthPersistence { constructor(private readonly definition: ServerDefinition) {} describe(): string { - return '~/.mcporter/.credentials.json (vault)'; + return '~/.mcporter/credentials.json (vault)'; } async readTokens(): Promise { diff --git a/src/oauth-vault.ts b/src/oauth-vault.ts index 50ca0ac..80cb8fa 100644 --- a/src/oauth-vault.ts +++ b/src/oauth-vault.ts @@ -6,7 +6,7 @@ import type { OAuthClientInformationMixed, OAuthTokens } from '@modelcontextprot import type { ServerDefinition } from './config.js'; import { readJsonFile, writeJsonFile } from './fs-json.js'; -const VAULT_PATH = path.join(os.homedir(), '.mcporter', '.credentials.json'); +const VAULT_PATH = path.join(os.homedir(), '.mcporter', 'credentials.json'); type VaultKey = string; diff --git a/tests/oauth-persistence.test.ts b/tests/oauth-persistence.test.ts index c38dd77..687a027 100644 --- a/tests/oauth-persistence.test.ts +++ b/tests/oauth-persistence.test.ts @@ -42,7 +42,7 @@ describe('oauth persistence', () => { ); // Vault also contains a token, but cache dir should win. - const vaultPath = path.join(tmp, '.mcporter', '.credentials.json'); + const vaultPath = path.join(tmp, '.mcporter', 'credentials.json'); await fs.mkdir(path.dirname(vaultPath), { recursive: true }); const definition = mkDef('service', cacheDir); const key = vaultKeyForDefinition(definition); @@ -120,7 +120,7 @@ describe('oauth persistence', () => { await fs.mkdir(path.dirname(gmailLegacyFile), { recursive: true }); await fs.writeFile(gmailLegacyFile, '{}'); - const vaultPath = path.join(tmp, '.mcporter', '.credentials.json'); + const vaultPath = path.join(tmp, '.mcporter', 'credentials.json'); await fs.mkdir(path.dirname(vaultPath), { recursive: true }); const logger = { info: vi.fn(), warn: vi.fn(), error: vi.fn() } as const; const definition = mkDef('gmail', cacheDir);