-
Notifications
You must be signed in to change notification settings - Fork 2.3k
[MCP-UI] Proxy and Better Message Handling #5487
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
a828eac
02b3d7c
8da9d52
be436f7
b49fd9c
8f877fa
0ce5a8a
94d2162
745f2eb
715c09a
c42f12b
72f1ef1
7677e76
5af7c66
949f9b4
fec432d
093bf6c
9084e51
8f2bd7e
4f38d64
2f9c187
ed320d2
5af994a
4d04991
972f95f
6a748ec
6522b1b
927c969
127ba09
80b2c21
b1e8628
5eb9bf3
52304d7
10468bb
d3f5360
72e52e8
bf42719
8c3988d
881eaa5
ee9959a
c444706
913b0bf
c170e4c
f2c66e1
356b409
dfe457e
e1590f0
92d7c3c
8433401
40276bf
a6daeed
b6740fb
273f4de
7aef5a2
e9e18d7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -52,6 +52,8 @@ import { Recipe } from './recipe'; | |
| import './utils/recipeHash'; | ||
| import { Client, createClient, createConfig } from './api/client'; | ||
| import installExtension, { REACT_DEVELOPER_TOOLS } from 'electron-devtools-installer'; | ||
| import express from 'express'; | ||
michaelneale marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| import http from 'node:http'; | ||
|
|
||
| // Updater functions (moved here to keep updates.ts minimal for release replacement) | ||
| function shouldSetupUpdater(): boolean { | ||
|
|
@@ -1024,6 +1026,13 @@ ipcMain.handle('get-secret-key', () => { | |
| return SERVER_SECRET; | ||
| }); | ||
|
|
||
| ipcMain.handle('get-mcp-ui-proxy-url', () => { | ||
| if (mcpUIProxyServerPort) { | ||
| return `http://localhost:${mcpUIProxyServerPort}/mcp-ui-proxy.html`; | ||
| } | ||
| return undefined; | ||
| }); | ||
|
|
||
| ipcMain.handle('get-goosed-host-port', async (event) => { | ||
| const windowId = BrowserWindow.fromWebContents(event.sender)?.id; | ||
| if (!windowId) { | ||
|
|
@@ -1642,10 +1651,51 @@ const registerGlobalHotkey = (accelerator: string) => { | |
| } | ||
| }; | ||
|
|
||
| // HTTP server for serving MCP proxy files | ||
| let mcpUIProxyServerPort: number | null = null; | ||
| let mcpUIProxyServer: http.Server | null = null; | ||
|
|
||
| async function startMcpUIProxyServer(): Promise<number> { | ||
| return new Promise((resolve, reject) => { | ||
| const expressApp = express(); | ||
|
||
| const staticPath = path.join(__dirname, '../../static'); | ||
|
|
||
| // Serve static files from the static directory | ||
| expressApp.use(express.static(staticPath)); | ||
|
|
||
| // Create HTTP server | ||
| mcpUIProxyServer = http.createServer(expressApp); | ||
|
|
||
| // Listen on a dynamic port (0 = let the OS choose an available port) | ||
| mcpUIProxyServer.listen(0, 'localhost', () => { | ||
| const address = mcpUIProxyServer?.address(); | ||
| if (address && typeof address === 'object') { | ||
| mcpUIProxyServerPort = address.port; | ||
| log.info(`MCP UI Proxy server started on port ${mcpUIProxyServerPort}`); | ||
| resolve(mcpUIProxyServerPort); | ||
| } else { | ||
| reject(new Error('Failed to get server address')); | ||
| } | ||
| }); | ||
|
|
||
| mcpUIProxyServer.on('error', (error) => { | ||
| log.error('MCP Proxy server error:', error); | ||
| reject(error); | ||
| }); | ||
| }); | ||
| } | ||
|
|
||
| async function appMain() { | ||
| // Ensure Windows shims are available before any MCP processes are spawned | ||
| await ensureWinShims(); | ||
|
|
||
| // Start MCP proxy server | ||
| try { | ||
| await startMcpUIProxyServer(); | ||
| } catch (error) { | ||
| log.error('Failed to start MCP proxy server:', error); | ||
| } | ||
|
|
||
| registerUpdateIpcHandlers(); | ||
|
|
||
| // Handle microphone permission requests | ||
|
|
@@ -2192,6 +2242,13 @@ app.on('will-quit', async () => { | |
| } | ||
| windowPowerSaveBlockers.clear(); | ||
|
|
||
| // Close MCP proxy server | ||
| if (mcpUIProxyServer) { | ||
| mcpUIProxyServer.close(() => { | ||
| log.info('MCP UI Proxy server closed'); | ||
| }); | ||
| } | ||
aharvard marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| // Unregister all shortcuts when quitting | ||
| globalShortcut.unregisterAll(); | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just a note regarding the deletions in this file: previously we were over-handling messages form the iframe, upgrading @mcp-ui/client and using a proxy takes most of this off our plate.