Harden MCP schema and wire Claude OAuth/token handling
This commit is contained in:
36
src/mcp.ts
36
src/mcp.ts
@@ -20,12 +20,9 @@ import type {
|
||||
McpLoadContext,
|
||||
SharedMcpConfigFile,
|
||||
} from "./mcp/types.js";
|
||||
import { parseMcpConfig } from "./mcp/types.js";
|
||||
import type { ToolClearancePolicy } from "./security/schemas.js";
|
||||
|
||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
return typeof value === "object" && value !== null && !Array.isArray(value);
|
||||
}
|
||||
|
||||
function readConfigFile(configPath: string): {
|
||||
config?: SharedMcpConfigFile;
|
||||
sourcePath?: string;
|
||||
@@ -41,17 +38,32 @@ function readConfigFile(configPath: string): {
|
||||
}
|
||||
|
||||
const rawText = readFileSync(resolvedPath, "utf8");
|
||||
const parsed = JSON.parse(rawText) as unknown;
|
||||
if (!isRecord(parsed)) {
|
||||
throw new Error(`MCP config file must contain a JSON object: ${resolvedPath}`);
|
||||
}
|
||||
const parsed = parseMcpConfig(JSON.parse(rawText) as unknown);
|
||||
|
||||
return {
|
||||
config: normalizeSharedMcpConfigFile(parsed as SharedMcpConfigFile),
|
||||
config: normalizeSharedMcpConfigFile(parsed),
|
||||
sourcePath: resolvedPath,
|
||||
};
|
||||
}
|
||||
|
||||
function warnClaudeUnsupportedSharedFields(
|
||||
config: SharedMcpConfigFile,
|
||||
warn: (message: string) => void,
|
||||
): void {
|
||||
for (const [serverName, server] of Object.entries(config.servers ?? {})) {
|
||||
if (server.enabled_tools) {
|
||||
warn(
|
||||
`[WARN] MCP field 'enabled_tools' is not supported by the Claude adapter and will be ignored (server: "${serverName}").`,
|
||||
);
|
||||
}
|
||||
if (server.startup_timeout_sec !== undefined || server.tool_timeout_sec !== undefined) {
|
||||
warn(
|
||||
`[WARN] MCP field 'timeouts' is not supported by the Claude adapter and will be ignored (server: "${serverName}").`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const defaultMcpRegistry = createDefaultMcpRegistry();
|
||||
|
||||
export function getDefaultMcpRegistry(): McpRegistry {
|
||||
@@ -64,16 +76,22 @@ export function loadMcpConfigFromEnv(
|
||||
config?: Readonly<AppConfig>;
|
||||
registry?: McpRegistry;
|
||||
toolClearance?: ToolClearancePolicy;
|
||||
warn?: (message: string) => void;
|
||||
},
|
||||
): LoadedMcpConfig {
|
||||
const runtimeConfig = options?.config ?? getConfig();
|
||||
const registry = options?.registry ?? defaultMcpRegistry;
|
||||
const warn = options?.warn ?? ((message: string) => console.warn(message));
|
||||
|
||||
const { config, sourcePath } = readConfigFile(runtimeConfig.mcp.configPath);
|
||||
if (!config) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (context.providerHint === "claude" || context.providerHint === "both") {
|
||||
warnClaudeUnsupportedSharedFields(config, warn);
|
||||
}
|
||||
|
||||
const codexServers: NonNullable<CodexOptions["config"]> = {};
|
||||
const claudeServers: NonNullable<LoadedMcpConfig["claudeMcpServers"]> = {};
|
||||
const resolvedHandlers: Record<string, string> = {};
|
||||
|
||||
Reference in New Issue
Block a user