feat(mcp): make mcp navigated faster (#671)

This commit is contained in:
2025-04-29 13:14:03 +08:00 committed by GitHub
parent 061ff92c69
commit 81bcc5ec1a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 29 additions and 40 deletions

View File

@ -33,7 +33,9 @@
"@midscene/core": "workspace:*",
"@midscene/shared": "workspace:*",
"@modelcontextprotocol/sdk": "1.10.1",
"zod": "3.24.3"
"zod": "3.24.3",
"kill-port": "2.0.1",
"@types/kill-port": "2.0.3"
},
"dependencies": {
"puppeteer": "24.2.0"

View File

@ -5,6 +5,7 @@ import {
} from '@midscene/shared/env';
import {
AgentOverChromeBridge,
DefaultBridgeServerPort,
allConfigFromEnv,
overrideAIConfig,
} from '@midscene/web/bridge-mode';
@ -15,6 +16,7 @@ import type {
ImageContent,
TextContent,
} from '@modelcontextprotocol/sdk/types.js';
import killPort from 'kill-port';
import { z } from 'zod';
import { PuppeteerBrowserAgent, ensureBrowser } from './puppeteer';
@ -33,10 +35,12 @@ export class MidsceneManager {
private mcpServer: McpServer; // Add server instance
private agent?: AgentOverChromeBridge | PuppeteerBrowserAgent;
private puppeteerMode = getAIConfigInBoolean(MIDSCENE_MCP_USE_PUPPETEER_MODE);
private initKillPort: Promise<void>;
constructor(server: McpServer) {
this.mcpServer = server;
this.initEnv();
this.registerTools();
this.initKillPort = this.killPort();
}
private initEnv() {
@ -51,6 +55,14 @@ export class MidsceneManager {
overrideAIConfig(envOverrides);
}
private async killPort() {
// Avoid existing bridge-mode servers that haven't exited occupying ports, which would cause new mcp server connections to take a long time
// And the killPort operation may take a long time
try {
await killPort(DefaultBridgeServerPort, 'tcp');
} catch (e) {}
}
// Asynchronously initializes or re-initializes the browser agent.
// Accepts an optional 'reInit' flag (default: false). If true, forces re-creation of the agent.
private async initAgent(openNewTabWithUrl?: string) {
@ -80,6 +92,7 @@ export class MidsceneManager {
private async initAgentByBridgeMode(
openNewTabWithUrl?: string,
): Promise<AgentOverChromeBridge> {
await this.initKillPort;
let agent: AgentOverChromeBridge;
try {
// Create a new agent instance designed for bridge mode.

View File

@ -135,7 +135,6 @@
"inquirer": "10.1.5",
"js-sha256": "0.11.0",
"js-yaml": "4.1.0",
"kill-port": "2.0.1",
"openai": "4.81.0",
"socket.io": "^4.8.1",
"socket.io-client": "4.8.1"
@ -148,7 +147,6 @@
"@types/express": "^4.17.21",
"@types/fs-extra": "11.0.4",
"@types/js-yaml": "4.0.9",
"@types/kill-port": "2.0.3",
"@types/node": "^18.0.0",
"playwright": "1.44.1",
"puppeteer": "24.2.0",

View File

@ -20,13 +20,11 @@ const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
// actually, this is a proxy to the page in browser side
export const getBridgePageInCliSide = (
forceCloseServer?: boolean,
timeout?: number | false,
): ChromeExtensionPageCliSide => {
const server = new BridgeServer(DefaultBridgeServerPort);
server.listen({
timeout,
forceCloseServer,
});
const bridgeCaller = (method: string) => {
return async (...args: any[]) => {
@ -109,10 +107,7 @@ export class AgentOverChromeBridge extends PageAgent<ChromeExtensionPageCliSide>
serverListeningTimeout?: number | false;
},
) {
const page = getBridgePageInCliSide(
opts?.forceCloseServer,
opts?.serverListeningTimeout,
);
const page = getBridgePageInCliSide(opts?.serverListeningTimeout);
super(
page,
Object.assign(opts || {}, {

View File

@ -3,3 +3,5 @@ import { AgentOverChromeBridge } from './agent-cli-side';
export { AgentOverChromeBridge };
export { overrideAIConfig, allConfigFromEnv } from '@midscene/shared/env';
export { DefaultBridgeServerPort } from './common';

View File

@ -1,5 +1,4 @@
import { logMsg } from '@midscene/shared/utils';
import killPort from 'kill-port';
import { Server, type Socket as ServerSocket } from 'socket.io';
import {
type BridgeCall,
@ -34,13 +33,9 @@ export class BridgeServer {
async listen(
opts: {
timeout?: number | false;
forceCloseServer?: boolean;
} = {},
): Promise<void> {
const { timeout = 30000, forceCloseServer = false } = opts;
if (forceCloseServer) {
await this.killPort();
}
const { timeout = 30000 } = opts;
return new Promise((resolve, reject) => {
if (this.listeningTimerFlag) {
@ -166,15 +161,6 @@ export class BridgeServer {
});
}
async killPort() {
if (!this.listeningTimerFlag) {
// kill the port if it is already occupied
try {
await killPort(this.port, 'tcp');
} catch (e) {}
}
}
private connectionLostErrorMsg = () => {
return `Connection lost, reason: ${this.connectionLostReason}`;
};

25
pnpm-lock.yaml generated
View File

@ -555,12 +555,18 @@ importers:
'@rslib/core':
specifier: ^0.6.2
version: 0.6.3(typescript@5.8.3)
'@types/kill-port':
specifier: 2.0.3
version: 2.0.3
'@types/node':
specifier: ^18.0.0
version: 18.19.62
dotenv:
specifier: 16.4.5
version: 16.4.5
kill-port:
specifier: 2.0.1
version: 2.0.1
typescript:
specifier: ^5.8.2
version: 5.8.3
@ -740,9 +746,6 @@ importers:
js-yaml:
specifier: 4.1.0
version: 4.1.0
kill-port:
specifier: 2.0.1
version: 2.0.1
openai:
specifier: 4.81.0
version: 4.81.0(ws@8.18.1)(zod@3.24.3)
@ -774,9 +777,6 @@ importers:
'@types/js-yaml':
specifier: 4.0.9
version: 4.0.9
'@types/kill-port':
specifier: 2.0.3
version: 2.0.3
'@types/node':
specifier: ^18.0.0
version: 18.19.62
@ -5090,9 +5090,6 @@ packages:
'@types/node@18.19.62':
resolution: {integrity: sha512-UOGhw+yZV/icyM0qohQVh3ktpY40Sp7tdTW7HxG3pTd7AiMrlFlAJNUrGK9t5mdW0+ViQcFV74zCSIx9ZJpncA==}
'@types/node@18.19.86':
resolution: {integrity: sha512-fifKayi175wLyKyc5qUfyENhQ1dCNI1UNjp653d8kuYcPQN5JhX3dGuP/XmvPTg/xRBn1VTLpbmi+H/Mr7tLfQ==}
'@types/node@18.19.87':
resolution: {integrity: sha512-OIAAu6ypnVZHmsHCeJ+7CCSub38QNBS9uceMQeg7K5Ur0Jr+wG9wEOEvvMbhp09pxD5czIUy/jND7s7Tb6Nw7A==}
@ -18946,7 +18943,7 @@ snapshots:
'@types/connect@3.4.38':
dependencies:
'@types/node': 18.19.86
'@types/node': 18.19.87
'@types/conventional-commits-parser@5.0.1':
dependencies:
@ -19086,7 +19083,7 @@ snapshots:
'@types/mute-stream@0.0.4':
dependencies:
'@types/node': 18.19.62
'@types/node': 18.19.87
'@types/node-fetch@2.6.11':
dependencies:
@ -19101,10 +19098,6 @@ snapshots:
dependencies:
undici-types: 5.26.5
'@types/node@18.19.86':
dependencies:
undici-types: 5.26.5
'@types/node@18.19.87':
dependencies:
undici-types: 5.26.5
@ -19154,7 +19147,7 @@ snapshots:
'@types/send@0.17.4':
dependencies:
'@types/mime': 1.3.5
'@types/node': 18.19.62
'@types/node': 18.19.87
'@types/serve-static@1.15.7':
dependencies: