Skip to main content
Glama

MCP Todoist

by kentaroh7777
phase2_mcp-tester-base-component.md14.1 kB
# Task 2: MCPTester基本コンポーネント構造実装 ## 概要 現在のMCPTester.tsxを拡張し、5つのセクション構造とExtendedConvexMCPClientを統合したコンポーネントを実装する。テストケースが期待するdata-testid要素を段階的に追加する。 ## 依存関係 - **前提タスク**: Task 1 (ExtendedConvexMCPClient実装) - **依存成果物**: `packages/web-ui/lib/mcp/extended-convex-client.ts` ### 前提条件 - ExtendedConvexMCPClient実装済み - `packages/web-ui/components/MCPTester.tsx`: 既存のファイル(大幅書き換えが必要) ### 成果物 - **修正**: `packages/web-ui/components/MCPTester.tsx` - 5つのセクション構造への書き換え ### 影響範囲 - MCPTesterコンポーネントの全面的な構造変更 - 既存テストケースとの段階的互換性確保 ## 実装要件 ### 【必須制約】セクション構造の実装 5つの主要セクションを持つコンポーネント構造: 1. **接続セクション** - MCPサーバー接続管理 2. **ツールセクション** - MCPツール一覧と実行 3. **リソースセクション** - MCPリソース管理 4. **プロンプトセクション** - MCPプロンプト管理 5. **デバッグセクション** - メッセージログとJSON表示 ### 【必須制約】data-testidの段階的実装 テストケースが期待する要素を段階的に追加: ```typescript // Phase 2で実装すべきdata-testid要素 const REQUIRED_TEST_IDS = [ // セクション要素 'connection-section', 'tools-section', 'resources-section', 'prompts-section', 'debug-section', // 基本要素 'server-url-input', 'connect-button', 'disconnect-button', 'connection-status' ]; ``` ### 技術仕様 ```typescript // コンポーネント状態管理 interface MCPTesterState { connectionState: 'disconnected' | 'connecting' | 'connected' | 'error'; serverUrl: string; client?: ExtendedConvexMCPClient; tools: MCPTool[]; resources: MCPResource[]; prompts: MCPPrompt[]; messages: MCPMessage[]; } // Props定義 interface MCPTesterProps { skipAuthentication?: boolean; testUserId?: string; defaultServerUrl?: string; } ``` ## 実装ガイド ### ステップ1: 基本構造の実装 ```typescript 'use client'; import { useState, useEffect, useCallback } from 'react'; import Layout from 'antd/es/layout'; import Card from 'antd/es/card'; import Tabs from 'antd/es/tabs'; import { useExtendedConvexMCPClient } from '@/lib/mcp/extended-convex-client'; const { Content } = Layout; interface MCPTesterState { connectionState: 'disconnected' | 'connecting' | 'connected' | 'error'; serverUrl: string; client?: ExtendedConvexMCPClient; tools: any[]; resources: any[]; prompts: any[]; messages: any[]; } export default function MCPTester({ skipAuthentication = true, testUserId = 'test-user', defaultServerUrl = 'http://localhost:3001' }: MCPTesterProps) { const [state, setState] = useState<MCPTesterState>({ connectionState: 'disconnected', serverUrl: defaultServerUrl, tools: [], resources: [], prompts: [], messages: [] }); const client = useExtendedConvexMCPClient({ skipAuthentication, testUserId }); return ( <Content className="p-6"> <div className="max-w-6xl mx-auto"> <Card title="MCP Todoist テスター"> <Tabs defaultActiveKey="connection" items={tabItems} /> </Card> </div> </Content> ); } ``` ### ステップ2: セクション別Tabsアイテムの実装 ```typescript const tabItems = [ { key: 'connection', label: '接続', children: <ConnectionSection />, }, { key: 'tools', label: 'ツール', children: <ToolsSection />, }, { key: 'resources', label: 'リソース', children: <ResourcesSection />, }, { key: 'prompts', label: 'プロンプト', children: <PromptsSection />, }, { key: 'debug', label: 'デバッグ', children: <DebugSection />, } ]; ``` ### ステップ3: 接続セクションの基本実装 ```typescript function ConnectionSection({ state, setState, client }: SectionProps) { const handleConnect = useCallback(async () => { setState(prev => ({ ...prev, connectionState: 'connecting' })); try { await client.connect(state.serverUrl); setState(prev => ({ ...prev, connectionState: 'connected', client })); } catch (error) { setState(prev => ({ ...prev, connectionState: 'error' })); } }, [state.serverUrl, client, setState]); return ( <div data-testid="connection-section"> <Input data-testid="server-url-input" value={state.serverUrl} onChange={e => setState(prev => ({ ...prev, serverUrl: e.target.value }))} placeholder="MCPサーバーURL" /> <Button data-testid="connect-button" onClick={handleConnect} loading={state.connectionState === 'connecting'} disabled={state.connectionState === 'connected'} > 接続 </Button> <Button data-testid="disconnect-button" onClick={() => setState(prev => ({ ...prev, connectionState: 'disconnected' }))} disabled={state.connectionState !== 'connected'} > 切断 </Button> <div data-testid="connection-status"> 状態: {state.connectionState} </div> </div> ); } ``` ### ステップ4: 他セクションの基本構造実装 ```typescript function ToolsSection({ state }: SectionProps) { return ( <div data-testid="tools-section"> <div>ツール機能を実装予定</div> </div> ); } function ResourcesSection({ state }: SectionProps) { return ( <div data-testid="resources-section"> <div>リソース機能を実装予定</div> </div> ); } function PromptsSection({ state }: SectionProps) { return ( <div data-testid="prompts-section"> <div>プロンプト機能を実装予定</div> </div> ); } function DebugSection({ state }: SectionProps) { return ( <div data-testid="debug-section"> <div>デバッグ機能を実装予定</div> </div> ); } ``` ## 検証基準 ### 機能検証 - [ ] 5つのセクションがTabsで切り替え可能 - [ ] ExtendedConvexMCPClientとの正常な統合 - [ ] 接続/切断ボタンの基本動作 ### テスト互換性検証 - [ ] 以下のdata-testid要素が存在する: - [ ] connection-section - [ ] tools-section - [ ] resources-section - [ ] prompts-section - [ ] debug-section - [ ] server-url-input - [ ] connect-button - [ ] disconnect-button - [ ] connection-status ### 技術検証 - [ ] TypeScript strict modeでコンパイル成功 - [ ] ESLintエラー0件 - [ ] 既存の認証無効化が正常に動作 ## 完全実装例 ```typescript 'use client'; import { useState, useEffect, useCallback } from 'react'; import Layout from 'antd/es/layout'; import Card from 'antd/es/card'; import Tabs from 'antd/es/tabs'; import Input from 'antd/es/input'; import Button from 'antd/es/button'; import Alert from 'antd/es/alert'; import { useExtendedConvexMCPClient } from '@/lib/mcp/extended-convex-client'; const { Content } = Layout; interface MCPTesterState { connectionState: 'disconnected' | 'connecting' | 'connected' | 'error'; serverUrl: string; client?: any; tools: any[]; resources: any[]; prompts: any[]; messages: any[]; } interface MCPTesterProps { skipAuthentication?: boolean; testUserId?: string; defaultServerUrl?: string; } interface SectionProps { state: MCPTesterState; setState: React.Dispatch<React.SetStateAction<MCPTesterState>>; client: any; } function ConnectionSection({ state, setState, client }: SectionProps) { const handleConnect = useCallback(async () => { setState(prev => ({ ...prev, connectionState: 'connecting' })); try { // ExtendedConvexMCPClientでの接続 await client.connect(state.serverUrl); setState(prev => ({ ...prev, connectionState: 'connected', client })); } catch (error) { setState(prev => ({ ...prev, connectionState: 'error' })); } }, [state.serverUrl, client, setState]); const handleDisconnect = useCallback(async () => { try { await client.disconnect(); setState(prev => ({ ...prev, connectionState: 'disconnected', tools: [], resources: [], prompts: [], messages: [] })); } catch (error) { console.error('切断エラー:', error); } }, [client, setState]); return ( <div data-testid="connection-section" className="space-y-4"> <div> <label className="block mb-2">MCPサーバーURL:</label> <Input data-testid="server-url-input" value={state.serverUrl} onChange={e => setState(prev => ({ ...prev, serverUrl: e.target.value }))} placeholder="http://localhost:3001" disabled={state.connectionState === 'connected'} /> </div> <div className="space-x-2"> <Button data-testid="connect-button" type="primary" onClick={handleConnect} loading={state.connectionState === 'connecting'} disabled={state.connectionState === 'connected'} > 接続 </Button> <Button data-testid="disconnect-button" onClick={handleDisconnect} disabled={state.connectionState !== 'connected'} > 切断 </Button> </div> <Alert data-testid="connection-status" message={`接続状態: ${state.connectionState}`} type={ state.connectionState === 'connected' ? 'success' : state.connectionState === 'error' ? 'error' : 'info' } showIcon /> </div> ); } function ToolsSection({ state }: SectionProps) { return ( <div data-testid="tools-section"> <Alert message="ツール機能" description="MCPツールの実行機能を実装予定です。" type="info" showIcon /> </div> ); } function ResourcesSection({ state }: SectionProps) { return ( <div data-testid="resources-section"> <Alert message="リソース機能" description="MCPリソースの管理機能を実装予定です。" type="info" showIcon /> </div> ); } function PromptsSection({ state }: SectionProps) { return ( <div data-testid="prompts-section"> <Alert message="プロンプト機能" description="MCPプロンプトの実行機能を実装予定です。" type="info" showIcon /> </div> ); } function DebugSection({ state }: SectionProps) { return ( <div data-testid="debug-section"> <Alert message="デバッグ機能" description="MCP通信ログの表示・管理機能を実装予定です。" type="info" showIcon /> </div> ); } export default function MCPTester({ skipAuthentication = true, testUserId = 'test-user', defaultServerUrl = 'http://localhost:3001' }: MCPTesterProps) { const [state, setState] = useState<MCPTesterState>({ connectionState: 'disconnected', serverUrl: defaultServerUrl, tools: [], resources: [], prompts: [], messages: [] }); const client = useExtendedConvexMCPClient({ skipAuthentication, testUserId }); useEffect(() => { setState(prev => ({ ...prev, client })); }, [client]); const tabItems = [ { key: 'connection', label: '接続', children: <ConnectionSection state={state} setState={setState} client={client} />, }, { key: 'tools', label: 'ツール', children: <ToolsSection state={state} setState={setState} client={client} />, }, { key: 'resources', label: 'リソース', children: <ResourcesSection state={state} setState={setState} client={client} />, }, { key: 'prompts', label: 'プロンプト', children: <PromptsSection state={state} setState={setState} client={client} />, }, { key: 'debug', label: 'デバッグ', children: <DebugSection state={state} setState={setState} client={client} />, } ]; return ( <Content className="p-6"> <div className="max-w-6xl mx-auto"> <Card title="MCP Todoist テスター (Convex統合版)"> <Alert message="認証無効化モード" description="テスト用にFirebase認証をスキップしています。" type="warning" showIcon className="mb-4" /> <Tabs defaultActiveKey="connection" items={tabItems} type="card" /> </Card> </div> </Content> ); } ``` ## 注意事項 ### 【厳守事項】 - ExtendedConvexMCPClientとの統合を必須とする - 既存のMCPTester.tsxファイルの完全書き換え - data-testid要素の段階的追加(Phase 2では基本要素のみ) ### 【推奨事項】 - TypeScript strict modeでの型安全な実装 - Ant Designコンポーネントの適切な使用 - 将来の機能追加を考慮した拡張性確保 ### 【禁止事項】 - 既存のExtendedConvexMCPClientの変更 - Phase 2で高度な機能の実装(Phase 3以降で実装) - Firebase認証の再有効化 ## 参考情報 - `packages/web-ui/lib/mcp/extended-convex-client.ts`: 使用するクライアント - `packages/web-ui/test/components/mcp-tester.test.tsx`: 対応すべきテストケース - Ant Design Tabs: https://ant.design/components/tabs

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/kentaroh7777/mcp-todoist'

If you have feedback or need assistance with the MCP directory API, please join our Discord server