UNPKG

@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
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;