Download src/utils/computerUse/mcpServer.ts from chenbhao/codev: direct link, hf CLI and curl.
- Browser
- Download file 4.12 kB
-
https://huggingface.co/chenbhao/codev/resolve/714ab7d15ffd78992a4c3d4e2bf153c2f62f4841/src/utils/computerUse/mcpServer.ts
- Command line
-
hf download hf://chenbhao/codev@714ab7d15ffd78992a4c3d4e2bf153c2f62f4841/src/utils/computerUse/mcpServer.ts
-
curl -L -o mcpServer.ts https://huggingface.co/chenbhao/codev/resolve/714ab7d15ffd78992a4c3d4e2bf153c2f62f4841/src/utils/computerUse/mcpServer.ts
4.12 kB
| import { | |
| buildComputerUseTools, | |
| createComputerUseMcpServer, | |
| } from '@ant/computer-use-mcp' | |
| import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js' | |
| import { ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js' | |
| import { homedir } from 'os' | |
| import { shutdownDatadog } from '../../services/analytics/datadog.js' | |
| import { shutdown1PEventLogging } from '../../services/analytics/firstPartyEventLogger.js' | |
| import { initializeAnalyticsSink } from '../../services/analytics/sink.js' | |
| import { enableConfigs } from '../config.js' | |
| import { logForDebugging } from '../debug.js' | |
| import { filterAppsForDescription } from './appNames.js' | |
| import { getChicagoCoordinateMode } from './gates.js' | |
| import { getComputerUseHostAdapter } from './hostAdapter.js' | |
| const APP_ENUM_TIMEOUT_MS = 1000 | |
| /** | |
| * Enumerate installed apps, timed. Fails soft — if Spotlight is slow or | |
| * claude-swift throws, the tool description just omits the list. Resolution | |
| * happens at call time regardless; the model just doesn't get hints. | |
| */ | |
| async function tryGetInstalledAppNames(): Promise<string[] | undefined> { | |
| const adapter = getComputerUseHostAdapter() | |
| const enumP = adapter.executor.listInstalledApps() | |
| let timer: ReturnType<typeof setTimeout> | undefined | |
| const timeoutP = new Promise<undefined>(resolve => { | |
| timer = setTimeout(resolve, APP_ENUM_TIMEOUT_MS, undefined) | |
| }) | |
| const installed = await Promise.race([enumP, timeoutP]) | |
| .catch(() => undefined) | |
| .finally(() => clearTimeout(timer)) | |
| if (!installed) { | |
| // The enumeration continues in the background — swallow late rejections. | |
| void enumP.catch(() => {}) | |
| logForDebugging( | |
| `[Computer Use MCP] app enumeration exceeded ${APP_ENUM_TIMEOUT_MS}ms or failed; tool description omits list`, | |
| ) | |
| return undefined | |
| } | |
| return filterAppsForDescription(installed, homedir()) | |
| } | |
| /** | |
| * Construct the in-process server. Delegates to the package's | |
| * `createComputerUseMcpServer` for the Server object + stub CallTool handler, | |
| * then REPLACES the ListTools handler with one that includes installed-app | |
| * names in the `request_access` description (the package's factory doesn't | |
| * take `installedAppNames`, and Cowork builds its own tool array in | |
| * serverDef.ts for the same reason). | |
| * | |
| * Async so the 1s app-enumeration timeout doesn't block startup — called from | |
| * an `await import()` in `client.ts` on first CU connection, not `main.tsx`. | |
| * | |
| * Real dispatch still goes through `wrapper.tsx`'s `.call()` override; this | |
| * server exists only to answer ListTools. | |
| */ | |
| export async function createComputerUseMcpServerForCli(): Promise< | |
| ReturnType<typeof createComputerUseMcpServer> | |
| > { | |
| const adapter = getComputerUseHostAdapter() | |
| const coordinateMode = getChicagoCoordinateMode() | |
| const server = createComputerUseMcpServer(adapter, coordinateMode) | |
| const installedAppNames = await tryGetInstalledAppNames() | |
| const tools = buildComputerUseTools( | |
| adapter.executor.capabilities, | |
| coordinateMode, | |
| installedAppNames, | |
| ) | |
| server.setRequestHandler(ListToolsRequestSchema, async () => | |
| adapter.isDisabled() ? { tools: [] } : { tools }, | |
| ) | |
| return server | |
| } | |
| /** | |
| * Subprocess entrypoint for `--computer-use-mcp`. Mirror of | |
| * `runClaudeInChromeMcpServer` — stdio transport, exit on stdin close, | |
| * flush analytics before exit. | |
| */ | |
| export async function runComputerUseMcpServer(): Promise<void> { | |
| enableConfigs() | |
| initializeAnalyticsSink() | |
| const server = await createComputerUseMcpServerForCli() | |
| const transport = new StdioServerTransport() | |
| let exiting = false | |
| const shutdownAndExit = async (): Promise<void> => { | |
| if (exiting) return | |
| exiting = true | |
| await Promise.all([shutdown1PEventLogging(), shutdownDatadog()]) | |
| // eslint-disable-next-line custom-rules/no-process-exit | |
| process.exit(0) | |
| } | |
| process.stdin.on('end', () => void shutdownAndExit()) | |
| process.stdin.on('error', () => void shutdownAndExit()) | |
| logForDebugging('[Computer Use MCP] Starting MCP server') | |
| await server.connect(transport) | |
| logForDebugging('[Computer Use MCP] MCP server started') | |
| } | |