@hhoangphuoc/escape-room-cli
Version:
A CLI for playing AI-generated escape room games. Install globally with: npm install -g @hhoangphuoc/escape-room-cli
127 lines (126 loc) • 5.96 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
//--------------------------------------------------------------------------------------------------------
// CODEBASE FOR MCP CLIENT
//--------------------------------------------------------------------------------------------------------
import { useState, useEffect } from 'react';
import { Box, Text } from 'ink';
import Spinner from 'ink-spinner';
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
const McpClientUI = ({ onMessage }) => {
const [mcpClient, setMcpClient] = useState(null);
const [isConnected, setIsConnected] = useState(false);
const [isConnecting, setIsConnecting] = useState(false);
const [tools, setTools] = useState([]);
const [error, setError] = useState(null);
// Transport
const transport = new StdioClientTransport({
command: "mcp",
args: ["--port", "3001"],
});
// Connect to MCP server
const connectToMcp = async () => {
setIsConnecting(true);
setError(null);
try {
// Create MCP client
const client = new Client({
name: "escape-room-cli",
version: "0.1.0",
url: "http://localhost:3001/mcp"
});
// Connect to server
await client.connect(transport);
// Get available tools
const availableTools = await client.listTools();
// Check if availableTools is an array before trying to map it
if (Array.isArray(availableTools)) {
setTools(availableTools.map((tool) => tool.name));
}
else {
console.error("Expected availableTools to be an array but got:", availableTools);
setTools([]);
}
setMcpClient(client);
setIsConnected(true);
onMessage("Connected to MCP server successfully!");
}
catch (error) {
console.error("Error connecting to MCP server:", error);
setError(`Failed to connect to MCP server: ${error instanceof Error ? error.message : "Unknown error"}`);
onMessage("Failed to connect to MCP server. Make sure the backend is running.");
}
finally {
setIsConnecting(false);
}
};
// Call MCP tool
// const callTool = async (toolName: string, args: any = {}) => {
// if (!mcpClient || !isConnected) {
// return { error: "Not connected to MCP server" };
// }
// try {
// const result = await mcpClient.callTool(toolName, args);
// return result;
// } catch (error) {
// console.error(`Error calling tool ${toolName}:`, error);
// return {
// error: `Error calling tool ${toolName}: ${error instanceof Error ? error.message : "Unknown error"}`
// };
// }
// };
// Process MCP command (parse command and call appropriate tool) -----------------------------------
// FIXME: NOT IMPLEMENTED YET
// const processMcpCommand = async (command: string) => {
// if (!command.startsWith('/')) {
// return { error: "MCP commands must start with /" };
// }
// // Parse command
// const parts = command.substring(1).split(' ');
// const toolName = parts[0]; //TOOL NAME (get from MCP SERVER TOOLS)
// // Check if tool exists
// if (!toolName) {
// return { error: "No tool specified. Please provide a valid MCP tool." };
// }
// if (!tools.includes(toolName)) {
// return {
// error: `Unknown MCP tool: ${toolName}. Available tools: ${tools.join(', ')}`
// };
// }
// // Parse arguments
// let args = {};
// switch (toolName) {
// case 'analyse_object':
// if (parts.length > 1) {
// const objectName = parts.slice(1).join(' ');
// args = { object_name: objectName };
// } else {
// return { error: "Usage: /analyse_object [object_name]" };
// }
// break;
// case 'submit_password':
// if (parts.length > 1) {
// const passwordGuess = parts.slice(1).join(' ');
// args = { password_guess: passwordGuess };
// } else {
// return { error: "Usage: /submit_password [password]" };
// }
// break;
// }
// // Call tool
// return await callTool(toolName, args);
// };
//--------------------------------------------------------------------------------------------------------
// Connect to MCP server on component mount
useEffect(() => {
connectToMcp();
// Cleanup on unmount
return () => {
if (mcpClient && isConnected) {
mcpClient.disconnect();
}
};
}, []);
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [isConnecting ? (_jsxs(Box, { children: [_jsx(Text, { color: "green", children: _jsx(Spinner, { type: "dots" }) }), _jsx(Text, { children: " Connecting to MCP server..." })] })) : isConnected ? (_jsxs(Box, { children: [_jsx(Text, { color: "green", children: "\u2713 " }), _jsx(Text, { children: "Connected to MCP server" })] })) : (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { color: "red", children: "\u2717 " }), _jsx(Text, { children: "Not connected to MCP server" })] }), error && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "red", children: error }) }))] })), isConnected && tools.length > 0 && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { bold: true, children: "Available MCP tools:" }), tools.map(tool => (_jsxs(Text, { children: [" - /", tool] }, tool)))] }))] }));
};
export default McpClientUI;