Something went wrong. Try again.
source dump of claude code forked from oppi.li/claude-code
Something went wrong. Try again.
4.1 kB · 106 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107import { 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')}