Ink-based TUI that shows exactly what an LLM sees through MCP. Browse tools/resources/prompts, execute them, and see raw JSON-RPC traffic in a protocol log. Supports gated session flow with begin_session, raw JSON-RPC input, and session reconnect. - McpSession class wrapping HTTP transport with typed methods - 12 React/Ink components (header, protocol-log, menu, tool/resource/prompt views, etc.) - 21 unit tests for McpSession against a mock MCP server - Fish + Bash completions with project name argument - bun compile with --external react-devtools-core Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
72 lines
1.8 KiB
TypeScript
72 lines
1.8 KiB
TypeScript
import { useState } from 'react';
|
|
import { Box, Text } from 'ink';
|
|
import { TextInput, Spinner } from '@inkjs/ui';
|
|
import type { McpSession } from '../mcp-session.js';
|
|
|
|
interface RawJsonRpcViewProps {
|
|
session: McpSession;
|
|
onBack: () => void;
|
|
}
|
|
|
|
export function RawJsonRpcView({ session }: RawJsonRpcViewProps) {
|
|
const [loading, setLoading] = useState(false);
|
|
const [result, setResult] = useState<string | null>(null);
|
|
const [error, setError] = useState<string | null>(null);
|
|
const [input, setInput] = useState('');
|
|
|
|
const handleSubmit = async () => {
|
|
if (!input.trim()) return;
|
|
setLoading(true);
|
|
setResult(null);
|
|
setError(null);
|
|
|
|
try {
|
|
const response = await session.sendRaw(input);
|
|
try {
|
|
setResult(JSON.stringify(JSON.parse(response), null, 2));
|
|
} catch {
|
|
setResult(response);
|
|
}
|
|
} catch (err) {
|
|
setError(err instanceof Error ? err.message : String(err));
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Box flexDirection="column">
|
|
<Text bold>Raw JSON-RPC</Text>
|
|
<Text dimColor>Enter a full JSON-RPC message and press Enter to send:</Text>
|
|
|
|
<Box marginTop={1}>
|
|
<Text color="cyan">> </Text>
|
|
<TextInput
|
|
placeholder='{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
|
|
onChange={setInput}
|
|
onSubmit={handleSubmit}
|
|
/>
|
|
</Box>
|
|
|
|
{loading && (
|
|
<Box marginTop={1}>
|
|
<Spinner label="Sending..." />
|
|
</Box>
|
|
)}
|
|
|
|
{error && (
|
|
<Box marginTop={1}>
|
|
<Text color="red">Error: {error}</Text>
|
|
</Box>
|
|
)}
|
|
|
|
{result && (
|
|
<Box flexDirection="column" marginTop={1}>
|
|
<Text bold>Response:</Text>
|
|
<Text>{result}</Text>
|
|
</Box>
|
|
)}
|
|
</Box>
|
|
);
|
|
}
|