inspector/core/client/config.ts
Bob Dickinson 5de4e911e3
feat(web,core): enterprise-managed authorization (EMA) (#1509) (#1512)
Adds enterprise-managed authorization (EMA): browser-side IdP login + RFC 8693 token-exchange and JWT-bearer resource-token mint, per-server EMA opt-in in Server Settings, IdP config in Client Settings, and IdP clientSecret keychain storage. Includes the v2/main merge and review follow-ups (400 on malformed client config; normalizeIdpIssuer import consolidation).
2026-06-24 22:15:12 -04:00

67 lines
1.9 KiB
TypeScript

/**
* Load/save/validate install-level client config (client.json).
*/
import type { SecretStore } from "../auth/node/secret-store.js";
import {
getDefaultStorageDir,
getStoreFilePath,
parseStore,
readStoreFile,
serializeStore,
writeStoreFile,
} from "../storage/store-io.js";
import { parseClientConfig } from "./config-parse.js";
import {
readClientConfigStore,
writeClientConfigStore,
} from "./node-persistence.js";
import type { ClientConfig } from "./types.js";
export { parseClientConfig, serializeClientConfig } from "./config-parse.js";
/** Default path: ~/.mcp-inspector/storage/client.json */
export function getClientConfigFilePath(customPath?: string): string {
return customPath ?? getStoreFilePath(getDefaultStorageDir(), "client");
}
/**
* Read client.json from disk. Returns `{}` when the file is absent.
* When `secretStore` is provided, IdP clientSecret is read from the keychain.
*/
export async function loadClientConfig(options?: {
filePath?: string;
secretStore?: SecretStore;
}): Promise<ClientConfig> {
const filePath = getClientConfigFilePath(options?.filePath);
if (options?.secretStore) {
return readClientConfigStore(filePath, options.secretStore);
}
const raw = await readStoreFile(filePath);
if (raw === null) {
return {};
}
return parseClientConfig(parseStore(raw));
}
/** Write client.json atomically (mode 0o600). */
export async function saveClientConfig(
config: ClientConfig,
options?: { filePath?: string; secretStore?: SecretStore },
): Promise<void> {
const filePath = getClientConfigFilePath(options?.filePath);
if (options?.secretStore) {
await writeClientConfigStore(filePath, config, options.secretStore);
return;
}
const validated = parseClientConfig(config);
await writeStoreFile(filePath, serializeStore(validated));
}
export {
deleteClientConfigStore,
readClientConfigStore,
writeClientConfigStore,
} from "./node-persistence.js";