first commit
This commit is contained in:
113
app/native-server/src/mcp/mcp-server-stdio.ts
Normal file
113
app/native-server/src/mcp/mcp-server-stdio.ts
Normal file
@@ -0,0 +1,113 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
||||
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
||||
import {
|
||||
CallToolRequestSchema,
|
||||
CallToolResult,
|
||||
ListToolsRequestSchema,
|
||||
} from '@modelcontextprotocol/sdk/types.js';
|
||||
import { TOOL_SCHEMAS } from 'chrome-mcp-shared';
|
||||
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
||||
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
let stdioMcpServer: Server | null = null;
|
||||
let mcpClient: Client | null = null;
|
||||
|
||||
// Read configuration from stdio-config.json
|
||||
const loadConfig = () => {
|
||||
try {
|
||||
const configPath = path.join(__dirname, 'stdio-config.json');
|
||||
const configData = fs.readFileSync(configPath, 'utf8');
|
||||
return JSON.parse(configData);
|
||||
} catch (error) {
|
||||
console.error('Failed to load stdio-config.json:', error);
|
||||
throw new Error('Configuration file stdio-config.json not found or invalid');
|
||||
}
|
||||
};
|
||||
|
||||
export const getStdioMcpServer = () => {
|
||||
if (stdioMcpServer) {
|
||||
return stdioMcpServer;
|
||||
}
|
||||
stdioMcpServer = new Server(
|
||||
{
|
||||
name: 'StdioChromeMcpServer',
|
||||
version: '1.0.0',
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
tools: {},
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
setupTools(stdioMcpServer);
|
||||
return stdioMcpServer;
|
||||
};
|
||||
|
||||
export const ensureMcpClient = async () => {
|
||||
try {
|
||||
if (mcpClient) {
|
||||
const pingResult = await mcpClient.ping();
|
||||
if (pingResult) {
|
||||
return mcpClient;
|
||||
}
|
||||
}
|
||||
|
||||
const config = loadConfig();
|
||||
mcpClient = new Client({ name: 'Mcp Chrome Proxy', version: '1.0.0' }, { capabilities: {} });
|
||||
const transport = new StreamableHTTPClientTransport(new URL(config.url), {});
|
||||
await mcpClient.connect(transport);
|
||||
return mcpClient;
|
||||
} catch (error) {
|
||||
mcpClient?.close();
|
||||
mcpClient = null;
|
||||
console.error('Failed to connect to MCP server:', error);
|
||||
}
|
||||
};
|
||||
|
||||
export const setupTools = (server: Server) => {
|
||||
// List tools handler
|
||||
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOL_SCHEMAS }));
|
||||
|
||||
// Call tool handler
|
||||
server.setRequestHandler(CallToolRequestSchema, async (request) =>
|
||||
handleToolCall(request.params.name, request.params.arguments || {}),
|
||||
);
|
||||
};
|
||||
|
||||
const handleToolCall = async (name: string, args: any): Promise<CallToolResult> => {
|
||||
try {
|
||||
const client = await ensureMcpClient();
|
||||
if (!client) {
|
||||
throw new Error('Failed to connect to MCP server');
|
||||
}
|
||||
const result = await client.callTool({ name, arguments: args }, undefined, {
|
||||
timeout: 2 * 6 * 1000, // Default timeout of 2 minute
|
||||
});
|
||||
return result as CallToolResult;
|
||||
} catch (error: any) {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Error calling tool: ${error.message}`,
|
||||
},
|
||||
],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
async function main() {
|
||||
const transport = new StdioServerTransport();
|
||||
await getStdioMcpServer().connect(transport);
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error('Fatal error Chrome MCP Server main():', error);
|
||||
process.exit(1);
|
||||
});
|
24
app/native-server/src/mcp/mcp-server.ts
Normal file
24
app/native-server/src/mcp/mcp-server.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
||||
import { setupTools } from './register-tools';
|
||||
|
||||
export let mcpServer: Server | null = null;
|
||||
|
||||
export const getMcpServer = () => {
|
||||
if (mcpServer) {
|
||||
return mcpServer;
|
||||
}
|
||||
mcpServer = new Server(
|
||||
{
|
||||
name: 'ChromeMcpServer',
|
||||
version: '1.0.0',
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
tools: {},
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
setupTools(mcpServer);
|
||||
return mcpServer;
|
||||
};
|
55
app/native-server/src/mcp/register-tools.ts
Normal file
55
app/native-server/src/mcp/register-tools.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
||||
import {
|
||||
CallToolRequestSchema,
|
||||
CallToolResult,
|
||||
ListToolsRequestSchema,
|
||||
} from '@modelcontextprotocol/sdk/types.js';
|
||||
import nativeMessagingHostInstance from '../native-messaging-host';
|
||||
import { NativeMessageType, TOOL_SCHEMAS } from 'chrome-mcp-shared';
|
||||
|
||||
export const setupTools = (server: Server) => {
|
||||
// List tools handler
|
||||
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOL_SCHEMAS }));
|
||||
|
||||
// Call tool handler
|
||||
server.setRequestHandler(CallToolRequestSchema, async (request) =>
|
||||
handleToolCall(request.params.name, request.params.arguments || {}),
|
||||
);
|
||||
};
|
||||
|
||||
const handleToolCall = async (name: string, args: any): Promise<CallToolResult> => {
|
||||
try {
|
||||
// 发送请求到Chrome扩展并等待响应
|
||||
const response = await nativeMessagingHostInstance.sendRequestToExtensionAndWait(
|
||||
{
|
||||
name,
|
||||
args,
|
||||
},
|
||||
NativeMessageType.CALL_TOOL,
|
||||
30000, // 30秒超时
|
||||
);
|
||||
if (response.status === 'success') {
|
||||
return response.data;
|
||||
} else {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Error calling tool: ${response.error}`,
|
||||
},
|
||||
],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
} catch (error: any) {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Error calling tool: ${error.message}`,
|
||||
},
|
||||
],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
};
|
3
app/native-server/src/mcp/stdio-config.json
Normal file
3
app/native-server/src/mcp/stdio-config.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"url": "http://127.0.0.1:12306/mcp"
|
||||
}
|
Reference in New Issue
Block a user