Files
Hermes-ui/packages/server/src/services/hermes/mcp.ts
T
ekko b015e70b9d [codex] fix MCP management lifecycle (#1144)
* feat(mcp): add MCP server management UI

- Server CRUD: add/edit/remove with YAML/JSON Monaco editor
- raw_config passthrough: zero field loss on edit/toggle
- tool_details embedding: single-request card data (1+N → 1)
- Auto-retry exponential backoff (2s→32s, max 5 retries)
- Route safety guards (hasRoute) for dynamic sidebar
- i18n: 9 languages (de/en/es/fr/ja/ko/pt/zh/zh-TW)
- 19 unit tests + 8 UX browser tests
- 35 files, +2933 lines

* fix mcp management lifecycle

---------

Co-authored-by: Crafter-feng <succeed_happu@163.com>
2026-05-30 11:06:08 +08:00

68 lines
2.1 KiB
TypeScript

import { AgentBridgeClient } from './agent-bridge/client'
import type { McpActionResponse } from './mcp-types'
export type { McpServerEntry, McpActionResponse } from './mcp-types'
let bridgeClient: AgentBridgeClient | null = null
export function getBridgeClient(): AgentBridgeClient {
if (!bridgeClient) {
bridgeClient = new AgentBridgeClient()
}
return bridgeClient
}
/**
* Send an MCP action to the AgentBridge using typed client methods.
*/
export async function bridgeMcpAction(
action: string,
payload: Record<string, unknown> = {},
profile?: string
): Promise<McpActionResponse> {
const client = getBridgeClient()
let raw: McpActionResponse
switch (action) {
case 'mcp_list':
raw = await client.mcpList(profile)
break
case 'mcp_server_add': {
const addName = String(payload.name || '')
const addConfig = payload.config as Record<string, unknown> | undefined
if (!addName || !addConfig) throw new Error('name and config are required')
raw = await client.mcpAdd(addName, addConfig, profile)
break
}
case 'mcp_server_update': {
const updName = String(payload.name || '')
const updConfig = payload.config as Record<string, unknown> | undefined
if (!updName || !updConfig) throw new Error('name and config are required')
raw = await client.mcpUpdate(updName, updConfig, profile)
break
}
case 'mcp_server_remove': {
const rmName = String(payload.name || '')
if (!rmName) throw new Error('name is required')
raw = await client.mcpRemove(rmName, profile)
break
}
case 'mcp_server_test': {
const testName = String(payload.name || '')
if (!testName) throw new Error('name is required')
raw = await client.mcpTest(testName, profile)
break
}
case 'mcp_tools_list':
raw = await client.mcpTools(payload.server as string | undefined, profile)
break
case 'mcp_reload':
raw = await client.mcpReload(payload.server as string | undefined, profile)
break
default:
throw new Error(`Unknown MCP action: ${action}`)
}
return raw
}