refactor: use --json flag alias instead of --format json throughout CLI

This commit is contained in:
Mohamed Boudra
2026-02-01 12:33:18 +07:00
parent dac1538d1f
commit a473302a9f
22 changed files with 313 additions and 167 deletions
@@ -4,6 +4,44 @@ export type AgentProvider = string;
export type AgentMetadata = { [key: string]: unknown };
/**
* Stdio-based MCP server (spawns a subprocess).
*/
export interface McpStdioServerConfig {
type: "stdio";
command: string;
args?: string[];
env?: Record<string, string>;
}
/**
* HTTP-based MCP server.
*/
export interface McpHttpServerConfig {
type: "http";
url: string;
headers?: Record<string, string>;
}
/**
* SSE-based MCP server (Server-Sent Events over HTTP).
*/
export interface McpSseServerConfig {
type: "sse";
url: string;
headers?: Record<string, string>;
}
/**
* Canonical MCP server configuration.
* Discriminated union by `type` field.
* Each provider normalizes this to their expected format.
*/
export type McpServerConfig =
| McpStdioServerConfig
| McpHttpServerConfig
| McpSseServerConfig;
export type AgentMode = {
id: string;
label: string;
@@ -208,7 +246,7 @@ export type AgentSessionConfig = {
codex?: AgentMetadata;
claude?: Partial<ClaudeAgentOptions>;
};
mcpServers?: AgentMetadata;
mcpServers?: Record<string, McpServerConfig>;
/**
* Internal agents are hidden from listings and don't trigger notifications.
* They are used for ephemeral system tasks like commit/PR generation.
@@ -7,7 +7,7 @@ import {
query,
type AgentDefinition,
type CanUseTool,
type McpServerConfig,
type McpServerConfig as ClaudeSdkMcpServerConfig,
type ModelInfo,
type Options,
type PermissionMode,
@@ -45,6 +45,7 @@ import type {
AgentRuntimeInfo,
ListModelsOptions,
ListPersistedAgentsOptions,
McpServerConfig,
PersistedAgentDescriptor,
} from "../agent-sdk-types.js";
import { getOrchestratorModeInstructions } from "../orchestrator-instructions.js";
@@ -102,7 +103,6 @@ type ClaudeAgentConfig = AgentSessionConfig & { provider: "claude" };
export type ClaudeContentChunk = { type: string; [key: string]: any };
type ClaudeMcpServerConfig = McpServerConfig;
type ClaudeOptions = Options;
type ClaudeAgentClientOptions = {
@@ -178,6 +178,32 @@ function isMetadata(value: unknown): value is AgentMetadata {
return typeof value === "object" && value !== null;
}
function isMcpServerConfig(value: unknown): value is McpServerConfig {
if (!isMetadata(value)) {
return false;
}
const type = value.type;
if (type === "stdio") {
return typeof value.command === "string";
}
if (type === "http" || type === "sse") {
return typeof value.url === "string";
}
return false;
}
function isMcpServersRecord(value: unknown): value is Record<string, McpServerConfig> {
if (!isMetadata(value)) {
return false;
}
for (const config of Object.values(value)) {
if (!isMcpServerConfig(config)) {
return false;
}
}
return true;
}
function isPermissionMode(value: string | undefined): value is PermissionMode {
return typeof value === "string" && VALID_CLAUDE_MODES.has(value);
}
@@ -230,18 +256,37 @@ function coerceSessionMetadata(metadata: AgentMetadata | undefined): Partial<Age
result.extra = extra;
}
}
if (isMetadata(metadata.mcpServers)) {
if (isMcpServersRecord(metadata.mcpServers)) {
result.mcpServers = metadata.mcpServers;
}
return result;
}
function isClaudeMcpServerConfig(value: unknown): value is ClaudeMcpServerConfig {
if (!isMetadata(value)) {
return false;
function toClaudeSdkMcpConfig(
config: McpServerConfig
): ClaudeSdkMcpServerConfig {
switch (config.type) {
case "stdio":
return {
type: "stdio",
command: config.command,
args: config.args,
env: config.env,
};
case "http":
return {
type: "http",
url: config.url,
headers: config.headers,
};
case "sse":
return {
type: "sse",
url: config.url,
headers: config.headers,
};
}
return typeof value.type === "string" || typeof value.command === "string" || typeof value.url === "string";
}
function isClaudeContentChunk(value: unknown): value is ClaudeContentChunk {
@@ -783,10 +828,7 @@ class ClaudeAgentSession implements AgentSession {
};
if (this.config.mcpServers) {
const normalizedUserServers = this.normalizeMcpServers(this.config.mcpServers);
if (normalizedUserServers) {
base.mcpServers = normalizedUserServers;
}
base.mcpServers = this.normalizeMcpServers(this.config.mcpServers);
}
if (this.config.model) {
@@ -800,18 +842,13 @@ class ClaudeAgentSession implements AgentSession {
}
private normalizeMcpServers(
servers: ClaudeAgentConfig["mcpServers"]
): Record<string, ClaudeMcpServerConfig> | undefined {
if (!servers) {
return undefined;
}
const result: Record<string, ClaudeMcpServerConfig> = {};
servers: Record<string, McpServerConfig>
): Record<string, ClaudeSdkMcpServerConfig> {
const result: Record<string, ClaudeSdkMcpServerConfig> = {};
for (const [name, config] of Object.entries(servers)) {
if (isClaudeMcpServerConfig(config)) {
result[name] = config;
}
result[name] = toClaudeSdkMcpConfig(config);
}
return Object.keys(result).length ? result : undefined;
return result;
}
private toSdkUserMessage(prompt: AgentPromptInput): SDKUserMessage {
@@ -37,6 +37,7 @@ import type {
AgentRuntimeInfo,
ListModelsOptions,
ListPersistedAgentsOptions,
McpServerConfig,
PersistedAgentDescriptor,
} from "../agent-sdk-types.js";
import { curateAgentActivity } from "../activity-curator.js";
@@ -1866,6 +1867,31 @@ const AgentSessionExtraSchema = z.object({
claude: z.custom<AgentSessionExtra["claude"]>().optional(),
});
const McpStdioServerConfigSchema = z.object({
type: z.literal("stdio"),
command: z.string(),
args: z.array(z.string()).optional(),
env: z.record(z.string()).optional(),
});
const McpHttpServerConfigSchema = z.object({
type: z.literal("http"),
url: z.string(),
headers: z.record(z.string()).optional(),
});
const McpSseServerConfigSchema = z.object({
type: z.literal("sse"),
url: z.string(),
headers: z.record(z.string()).optional(),
});
const McpServerConfigSchema = z.discriminatedUnion("type", [
McpStdioServerConfigSchema,
McpHttpServerConfigSchema,
McpSseServerConfigSchema,
]);
const AgentSessionConfigSchema = z
.object({
provider: z.string(),
@@ -1879,7 +1905,7 @@ const AgentSessionConfigSchema = z
webSearch: z.boolean().optional(),
reasoningEffort: z.string().optional(),
extra: AgentSessionExtraSchema.optional(),
mcpServers: z.record(z.unknown()).optional(),
mcpServers: z.record(McpServerConfigSchema).optional(),
})
.passthrough();
@@ -2693,14 +2719,35 @@ function getCodexMcpCommand(): string {
}
}
type CodexMcpServerConfig = {
interface CodexMcpServerConfig {
url?: string;
http_headers?: Record<string, string>; // Static HTTP headers for HTTP servers
http_headers?: Record<string, string>;
command?: string;
args?: string[];
env?: Record<string, string>;
tool_timeout_sec?: number; // Override the default 60s per-tool timeout
};
tool_timeout_sec?: number;
}
function toCodexMcpConfig(config: McpServerConfig): CodexMcpServerConfig {
switch (config.type) {
case "stdio":
return {
command: config.command,
args: config.args,
env: config.env,
};
case "http":
return {
url: config.url,
http_headers: config.headers,
};
case "sse":
return {
url: config.url,
http_headers: config.headers,
};
}
}
type CodexConfigPayload = {
mcp_servers?: Record<string, CodexMcpServerConfig>;
@@ -2754,22 +2801,10 @@ function buildCodexMcpConfig(
// Build MCP servers configuration
const mcpServers: Record<string, CodexMcpServerConfig> = {};
// Merge MCP servers from extra.codex.mcp_servers (legacy location)
const extraCodex = config.extra?.codex as Record<string, unknown> | undefined;
if (extraCodex?.mcp_servers && typeof extraCodex.mcp_servers === "object") {
for (const [name, serverConfig] of Object.entries(extraCodex.mcp_servers as Record<string, unknown>)) {
if (typeof serverConfig === "object" && serverConfig !== null) {
mcpServers[name] = serverConfig as CodexMcpServerConfig;
}
}
}
// Merge user-provided MCP servers (they take highest precedence)
// Merge user-provided MCP servers
if (config.mcpServers) {
for (const [name, serverConfig] of Object.entries(config.mcpServers)) {
if (typeof serverConfig === "object" && serverConfig !== null) {
mcpServers[name] = serverConfig as CodexMcpServerConfig;
}
mcpServers[name] = toCodexMcpConfig(serverConfig);
}
}
+26 -1
View File
@@ -46,6 +46,31 @@ const AgentUsageSchema: z.ZodType<AgentUsage> = z.object({
totalCostUsd: z.number().optional(),
});
const McpStdioServerConfigSchema = z.object({
type: z.literal("stdio"),
command: z.string(),
args: z.array(z.string()).optional(),
env: z.record(z.string()).optional(),
});
const McpHttpServerConfigSchema = z.object({
type: z.literal("http"),
url: z.string(),
headers: z.record(z.string()).optional(),
});
const McpSseServerConfigSchema = z.object({
type: z.literal("sse"),
url: z.string(),
headers: z.record(z.string()).optional(),
});
const McpServerConfigSchema = z.discriminatedUnion("type", [
McpStdioServerConfigSchema,
McpHttpServerConfigSchema,
McpSseServerConfigSchema,
]);
const AgentSessionConfigSchema = z.object({
provider: AgentProviderSchema,
cwd: z.string(),
@@ -70,7 +95,7 @@ const AgentSessionConfigSchema = z.object({
})
.partial()
.optional(),
mcpServers: z.record(z.unknown()).optional(),
mcpServers: z.record(McpServerConfigSchema).optional(),
});
const AgentPermissionUpdateSchema = z.record(z.unknown());