Move MCP status loading to app-server controller

This commit is contained in:
murashit 2026-05-29 05:50:26 +09:00
parent 390b8b2333
commit 76a1598f04
3 changed files with 47 additions and 10 deletions

View file

@ -13,6 +13,7 @@ import type { SkillMetadata } from "../../generated/app-server/v2/SkillMetadata"
import type { SharedAppServerMetadata } from "../../runtime/shared-app-server-state";
import { requestedOrConfiguredServiceTier, type RuntimeSnapshot } from "../../runtime/state";
import type { ChatAction, ChatState, ChatStateStore } from "./chat-state";
import { mcpStatusLines as buildMcpStatusLines } from "./mcp-status";
import { resumedThreadAction } from "./thread-resume";
export interface ChatAppServerControllerHost {
@ -264,6 +265,19 @@ export class ChatAppServerController {
this.publishAppServerMetadataSnapshot();
}
async mcpStatusLines(): Promise<string[]> {
const client = this.host.currentClient();
if (!client) return ["MCP servers", "Codex app-server is not connected."];
try {
const response = await client.listMcpServerStatus();
return buildMcpStatusLines(response.data, this.state.appServerDiagnostics.mcpServers);
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
return ["MCP servers", `Could not load MCP servers: ${message}`];
}
}
recordMcpStartupStatus(name: string, startupStatus: "starting" | "ready" | "failed" | "cancelled", message: string | null): void {
this.dispatch({
type: "thread/list-applied",

View file

@ -16,7 +16,6 @@ import { ChatController } from "./chat-controller";
import { currentModel, type RuntimeSnapshot } from "../../runtime/state";
import { executeSlashCommand as runSlashCommand, type SlashCommandExecutionResult } from "./slash-commands";
import type { ThreadReferenceInput } from "./slash-commands";
import { mcpStatusLines } from "./mcp-status";
import { ChatAppServerController } from "./chat-app-server-controller";
import { ThreadHistoryLoader } from "./thread-history";
import { ThreadRenameController } from "./thread-rename";
@ -1301,15 +1300,7 @@ export class CodexChatView extends ItemView {
}
private async mcpStatusLines(): Promise<string[]> {
if (!this.client) return ["MCP servers", "Codex app-server is not connected."];
try {
const response = await this.client.listMcpServerStatus();
return mcpStatusLines(response.data, this.state.appServerDiagnostics.mcpServers);
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
return ["MCP servers", `Could not load MCP servers: ${message}`];
}
return this.appServer.mcpStatusLines();
}
private collaborationModeLabel(): string {

View file

@ -4,6 +4,7 @@ import type { AppServerClient } from "../../../src/app-server/client";
import { ChatAppServerController } from "../../../src/features/chat/chat-app-server-controller";
import { createChatState, createChatStateStore } from "../../../src/features/chat/chat-state";
import type { Model } from "../../../src/generated/app-server/v2/Model";
import type { McpServerStatus } from "../../../src/generated/app-server/v2/McpServerStatus";
import type { RateLimitSnapshot } from "../../../src/generated/app-server/v2/RateLimitSnapshot";
import type { SkillMetadata } from "../../../src/generated/app-server/v2/SkillMetadata";
@ -60,4 +61,35 @@ describe("ChatAppServerController", () => {
summary: "available",
});
});
it("loads MCP status lines with cached startup diagnostics", async () => {
const stateStore = createChatStateStore(createChatState());
const client = {
listMcpServerStatus: vi.fn().mockResolvedValue({ data: [mcpServerStatus()] }),
} as unknown as AppServerClient;
const controller = new ChatAppServerController({
stateStore,
vaultPath: "/vault",
currentClient: () => client,
runtimeSnapshot: () => ({}) as never,
forceMessagesToBottom: () => undefined,
publishAppServerMetadata: () => undefined,
});
controller.recordMcpStartupStatus("github", "ready", null);
await expect(controller.mcpStatusLines()).resolves.toEqual(["MCP servers", "github: ready, auth oAuth, 1 tool, 0 resources"]);
});
});
function mcpServerStatus(): McpServerStatus {
return {
name: "github",
tools: {
search_issues: { name: "search_issues", inputSchema: {} },
},
resources: [],
resourceTemplates: [],
authStatus: "oAuth",
} as McpServerStatus;
}