(wsId: string, wsLabel: string, origin?: InboxOrigin)
| 89 | * Each WorkspaceToolFactory is invoked with the URL's wsId so its |
| 90 | * tools' execute() closes over that identity. */ |
| 91 | const createWorkspaceMcpServer = (wsId: string, wsLabel: string, origin?: InboxOrigin) => { |
| 92 | // GLOBAL issue-board reader, backed by the live WorkspaceService — parity |
| 93 | // with the CLI gateway so issue_list / issue_show read EVERY workspace's |
| 94 | // issues here too. Absent when the service isn't up → tools self-read. |
| 95 | const svc = getWorkspaceService() |
| 96 | const tools = workspaceToolCenter.build({ |
| 97 | workspaceId: wsId, |
| 98 | workspaceLabel: wsLabel, |
| 99 | inboxStore, |
| 100 | entityStore, |
| 101 | // Parity with the CLI gateway so external MCP consumers get the same |
| 102 | // workspace_path resolution — shared helper, so the two can't drift. |
| 103 | resolveWorkspace: makeWorkspaceResolver(getWorkspaceService), |
| 104 | ...(svc |
| 105 | ? { |
| 106 | board: { |
| 107 | snapshot: () => svc.issuesSnapshot(), |
| 108 | detail: (w: string, i: string) => svc.issueDetail(w, i), |
| 109 | resolveByName: (n: string) => svc.resolveIssuesByName(n), |
| 110 | }, |
| 111 | } |
| 112 | : {}), |
| 113 | // Agent-invisible run provenance from the out-of-band header (resolved |
| 114 | // server-side from the authoritative registry). Absent → undefined. |
| 115 | ...(origin ? { origin } : {}), |
| 116 | }) |
| 117 | const mcp = new McpServer({ name: 'open-alice-workspace', version: '1.0.0' }) |
| 118 | for (const [name, t] of Object.entries(tools)) { |
| 119 | if (!t.execute) continue |
| 120 | mcp.registerTool(name, { |
| 121 | description: t.description, |
| 122 | inputSchema: extractMcpShape(t), |
| 123 | }, wrapToolExecute(t)) |
| 124 | } |
| 125 | return mcp |
| 126 | } |
| 127 | |
| 128 | const app = new Hono() |
| 129 |
nothing calls this directly
no test coverage detected