fix: replace undefined with null in ACP MCP tool responses

Replace all undefined values with null in agent MCP tool responses to prevent JSON serialization issues that break the MCP client.

Changes:
- Update AgentInfo interface to use `| null` instead of optional `?` syntax
- Convert undefined to null in listAgents(), getCurrentMode(), getAvailableModes()
- Update all Zod schemas from .optional() to .nullable()
- Fix tool responses in create_coding_agent and set_agent_mode

This ensures all MCP tool responses properly serialize optional fields as null instead of undefined, preventing client-side errors.

🤖 Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
This commit is contained in:
Mohamed Boudra
2025-10-21 16:34:11 +02:00
parent cf977968c6
commit d883436395
3 changed files with 26 additions and 26 deletions

View File

@@ -315,10 +315,10 @@ export class AgentManager {
status: agent.status,
createdAt: agent.createdAt,
type: "claude" as const,
sessionId: agent.sessionId,
error: agent.error,
currentModeId: agent.currentModeId,
availableModes: agent.availableModes,
sessionId: agent.sessionId ?? null,
error: agent.error ?? null,
currentModeId: agent.currentModeId ?? null,
availableModes: agent.availableModes ?? null,
}));
}
@@ -356,23 +356,23 @@ export class AgentManager {
/**
* Get the current session mode for an agent
*/
getCurrentMode(agentId: string): string | undefined {
getCurrentMode(agentId: string): string | null {
const agent = this.agents.get(agentId);
if (!agent) {
throw new Error(`Agent ${agentId} not found`);
}
return agent.currentModeId;
return agent.currentModeId ?? null;
}
/**
* Get available session modes for an agent
*/
getAvailableModes(agentId: string): SessionMode[] {
getAvailableModes(agentId: string): SessionMode[] | null {
const agent = this.agents.get(agentId);
if (!agent) {
throw new Error(`Agent ${agentId} not found`);
}
return agent.availableModes || [];
return agent.availableModes ?? null;
}
/**

View File

@@ -74,12 +74,12 @@ export async function createAgentMcpServer(
"Current agent status: 'initializing', 'ready', 'processing', etc."
),
cwd: z.string().describe("The resolved absolute working directory the agent is running in"),
currentModeId: z.string().optional().describe("The agent's current session mode"),
currentModeId: z.string().nullable().describe("The agent's current session mode"),
availableModes: z.array(z.object({
id: z.string(),
name: z.string(),
description: z.string().optional(),
})).optional().describe("Available session modes for this agent"),
})).nullable().describe("Available session modes for this agent"),
},
},
async ({ cwd, initialPrompt, initialMode }) => {
@@ -100,8 +100,8 @@ export async function createAgentMcpServer(
agentId,
status,
cwd: resolvedCwd,
currentModeId,
availableModes,
currentModeId: currentModeId ?? null,
availableModes: availableModes ?? null,
};
return {
@@ -162,14 +162,14 @@ export async function createAgentMcpServer(
status: z.string(),
createdAt: z.date(),
type: z.literal("claude"),
sessionId: z.string().optional(),
error: z.string().optional(),
currentModeId: z.string().optional(),
sessionId: z.string().nullable(),
error: z.string().nullable(),
currentModeId: z.string().nullable(),
availableModes: z.array(z.object({
id: z.string(),
name: z.string(),
description: z.string().optional(),
})).optional(),
})).nullable(),
})
.describe("Detailed agent information"),
},
@@ -210,14 +210,14 @@ export async function createAgentMcpServer(
status: z.string(),
createdAt: z.date(),
type: z.literal("claude"),
sessionId: z.string().optional(),
error: z.string().optional(),
currentModeId: z.string().optional(),
sessionId: z.string().nullable(),
error: z.string().nullable(),
currentModeId: z.string().nullable(),
availableModes: z.array(z.object({
id: z.string(),
name: z.string(),
description: z.string().optional(),
})).optional(),
})).nullable(),
})
),
},
@@ -362,7 +362,7 @@ export async function createAgentMcpServer(
},
outputSchema: {
success: z.boolean().describe("Whether the mode change succeeded"),
previousMode: z.string().optional().describe("The previous session mode"),
previousMode: z.string().nullable().describe("The previous session mode"),
newMode: z.string().describe("The new session mode"),
},
},
@@ -372,7 +372,7 @@ export async function createAgentMcpServer(
const result = {
success: true,
previousMode,
previousMode: previousMode ?? null,
newMode: modeId,
};

View File

@@ -19,10 +19,10 @@ export interface AgentInfo {
status: AgentStatus;
createdAt: Date;
type: "claude";
sessionId?: string;
error?: string;
currentModeId?: string;
availableModes?: SessionMode[];
sessionId: string | null;
error: string | null;
currentModeId: string | null;
availableModes: SessionMode[] | null;
}
/**