@cgaspard/webappmcp
Version:
WebApp MCP - Model Context Protocol integration for web applications with server-side debugging tools
136 lines • 4.84 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.WebAppMCPServer = void 0;
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
const websocket_manager_js_1 = require("./websocket-manager.js");
const index_js_2 = require("./tools/index.js");
class WebAppMCPServer {
constructor(config) {
this.connections = new Map();
this.server = new index_js_1.Server({
name: 'webapp-mcp',
version: '0.1.0',
}, {
capabilities: {
tools: {},
},
});
this.wsManager = new websocket_manager_js_1.WebSocketManager({
port: config.wsPort,
authToken: config.authToken,
onConnection: this.handleClientConnection.bind(this),
onDisconnection: this.handleClientDisconnection.bind(this),
onMessage: this.handleClientMessage.bind(this),
});
this.setupHandlers();
}
setupHandlers() {
this.server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
return {
tools: (0, index_js_2.registerTools)(),
};
});
this.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
const activeConnection = this.getActiveConnection();
if (!activeConnection) {
throw new Error('No active client connection');
}
try {
const result = await this.executeToolOnClient(activeConnection, name, args);
return result;
}
catch (error) {
return {
content: [
{
type: 'text',
text: `Error executing tool: ${error instanceof Error ? error.message : 'Unknown error'}`,
},
],
};
}
});
}
handleClientConnection(clientId, ws) {
this.connections.set(clientId, {
id: clientId,
ws,
url: '',
isActive: true,
});
}
handleClientDisconnection(clientId) {
this.connections.delete(clientId);
}
handleClientMessage(clientId, message) {
const connection = this.connections.get(clientId);
if (connection && message.type === 'init') {
connection.url = message.url || '';
}
}
getActiveConnection() {
for (const connection of this.connections.values()) {
if (connection.isActive) {
return connection;
}
}
return null;
}
async executeToolOnClient(connection, toolName, args) {
return new Promise((resolve, reject) => {
const requestId = Math.random().toString(36).substring(7);
const timeout = setTimeout(() => {
reject(new Error('Tool execution timeout'));
}, 30000);
const messageHandler = (data) => {
if (data.requestId === requestId) {
clearTimeout(timeout);
connection.ws.off('message', messageHandler);
if (data.error) {
reject(new Error(data.error));
}
else {
resolve({
content: [
{
type: 'text',
text: JSON.stringify(data.result, null, 2),
},
],
});
}
}
};
connection.ws.on('message', messageHandler);
connection.ws.send(JSON.stringify({
type: 'execute_tool',
requestId,
tool: toolName,
args,
}));
});
}
async start() {
const transport = new stdio_js_1.StdioServerTransport();
await this.server.connect(transport);
await this.wsManager.start();
console.error('WebApp MCP Server started');
}
}
exports.WebAppMCPServer = WebAppMCPServer;
async function main() {
const wsPort = parseInt(process.env.WS_PORT || '4835');
const authToken = process.env.MCP_AUTH_TOKEN;
const server = new WebAppMCPServer({
wsPort,
authToken,
});
await server.start();
}
if (require.main === module) {
main().catch(console.error);
}
//# sourceMappingURL=index.js.map