mirror of
https://github.com/wu736139669/hapi.git
synced 2026-10-30 23:27:57 +00:00
feat(codex): support user-configured MCP servers in remote sessions (#1789)
* feat(codex): load user MCP servers in HAPI sessions * feat(codex): proxy Windows MCP command shims * fix(codex): address MCP review feedback * fix(codex): use HAPI-owned MCP proxy * fix(codex): preserve Windows MCP argv boundaries * fix(codex): keep remote MCP placement unchanged
This commit is contained in:
@@ -21,6 +21,12 @@ import {
|
||||
buildTurnStartParams,
|
||||
type CodexContextManagementConfig
|
||||
} from './utils/appServerConfig';
|
||||
import {
|
||||
extractCodexMcpServers,
|
||||
mergeCodexMcpServers,
|
||||
type CodexMcpServersConfig
|
||||
} from './utils/codexMcpServers';
|
||||
import { prepareCodexMcpServers } from './utils/codexMcpProxy';
|
||||
import type { SkillMetadata, ThreadGoal, ThreadGoalStatus } from './appServerTypes';
|
||||
import { shouldIgnoreTerminalEvent } from './utils/terminalEventGuard';
|
||||
import { parseCodexSpecialCommand } from './codexSpecialCommands';
|
||||
@@ -232,6 +238,7 @@ class CodexRemoteLauncher extends RemoteLauncherBase {
|
||||
private reasoningProcessor: ReasoningProcessor | null = null;
|
||||
private diffProcessor: DiffProcessor | null = null;
|
||||
private happyServer: HappyServer | null = null;
|
||||
private mcpProxyCleanup: (() => Promise<void>) | null = null;
|
||||
private abortController: AbortController = new AbortController();
|
||||
/** Invalidates queued-message steer handlers after abort or cleanup. */
|
||||
private steerEpoch = 0;
|
||||
@@ -3528,7 +3535,7 @@ class CodexRemoteLauncher extends RemoteLauncherBase {
|
||||
failPendingAgentStartsForSpawnArgumentError(spawnAgentError);
|
||||
});
|
||||
|
||||
const { server: happyServer, mcpServers } = await buildHapiMcpBridge(session.client, {
|
||||
const { server: happyServer, mcpServers: hapiMcpServers } = await buildHapiMcpBridge(session.client, {
|
||||
// In app-server/collab mode, child agents share this MCP bridge.
|
||||
// If the MCP handler writes the title directly, child title calls
|
||||
// leak into the parent HAPI session. Defer the side effect until
|
||||
@@ -3537,6 +3544,7 @@ class CodexRemoteLauncher extends RemoteLauncherBase {
|
||||
emitTitleSummary: false
|
||||
});
|
||||
this.happyServer = happyServer;
|
||||
let mcpServers: CodexMcpServersConfig = hapiMcpServers;
|
||||
|
||||
this.setupAbortHandlers(session.client.rpcHandlerManager, {
|
||||
onAbort: () => this.handleAbort(),
|
||||
@@ -3576,6 +3584,22 @@ class CodexRemoteLauncher extends RemoteLauncherBase {
|
||||
cwd: session.path,
|
||||
includeLayers: false
|
||||
})).config;
|
||||
try {
|
||||
const userMcpServers = extractCodexMcpServers(effectiveConfig);
|
||||
const preparedMcpServers = await prepareCodexMcpServers(userMcpServers);
|
||||
this.mcpProxyCleanup = preparedMcpServers.cleanup;
|
||||
mcpServers = mergeCodexMcpServers(preparedMcpServers.servers, hapiMcpServers);
|
||||
if (Object.keys(userMcpServers).length > 0) {
|
||||
logger.debug(`[Codex] Loaded ${Object.keys(userMcpServers).length} user MCP server(s)`);
|
||||
}
|
||||
if (preparedMcpServers.proxiedServerNames.length > 0) {
|
||||
logger.debug(
|
||||
`[Codex] Added stdio compatibility proxy for ${preparedMcpServers.proxiedServerNames.length} Windows MCP server(s)`
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.warn(`[Codex] Failed to merge user MCP servers; using HAPI bridge only: ${errorMessage(error)}`);
|
||||
}
|
||||
const modelContextWindow = effectiveConfig.model_context_window;
|
||||
const modelAutoCompactTokenLimit = effectiveConfig.model_auto_compact_token_limit;
|
||||
contextManagementConfig = {
|
||||
@@ -4332,6 +4356,15 @@ class CodexRemoteLauncher extends RemoteLauncherBase {
|
||||
this.happyServer = null;
|
||||
}
|
||||
|
||||
if (this.mcpProxyCleanup) {
|
||||
try {
|
||||
await this.mcpProxyCleanup();
|
||||
} catch (error) {
|
||||
logger.debug('[codex-remote]: Error cleaning MCP proxy specs', error);
|
||||
}
|
||||
this.mcpProxyCleanup = null;
|
||||
}
|
||||
|
||||
this.permissionHandler?.reset();
|
||||
this.reasoningProcessor?.abort();
|
||||
this.diffProcessor?.reset();
|
||||
|
||||
Reference in New Issue
Block a user