Skip to main content
Glama

f0_make_randomvalues MCP Server

mcp_specification.md25.4 kB
# MCP Server 要件定義・仕様書 ## f0_make_randomvalues Function Block の MCP サーバー実装 ### 1. エグゼクティブサマリー #### 1.1 プロジェクト概要 FGDB(Functional Graph Database)システムで使用される `f0_make_randomvalues` 関数ブロックを、Model Context Protocol (MCP) サーバーとして実装する。これにより、Claude DesktopなどのMCP対応クライアントから、乱数生成機能を直接利用可能にする。 #### 1.2 ビジネス価値 - **相互運用性の向上**: FGDBシステムの機能をLLMアプリケーションに統合 - **開発効率の向上**: 既存の関数ブロックをMCPエコシステムで再利用 - **標準化**: MCP仕様準拠による将来的な拡張性の確保 #### 1.3 主要成果物 - MCPサーバー実装(`mcp_f0_server.py`) - Claude Desktop統合設定 - 自動化テストスイート - 運用ドキュメント --- ## 2. システムアーキテクチャ ### 2.1 全体構成 ``` ┌─────────────────┐ MCP Protocol ┌─────────────────┐ │ MCP Client │◄────────────────────►│ MCP Server │ │ (Claude, etc) │ │ (f0_random) │ └─────────────────┘ └─────────────────┘ │ ▼ ┌─────────────────┐ │ FGDB Function │ │ Block (f0) │ └─────────────────┘ ``` ### 2.2 コンポーネント構成 | コンポーネント | 役割 | 技術スタック | |---------------|------|-------------| | MCPサーバー | プロトコル処理、メッセージ管理 | Python, MCP SDK | | ツールハンドラー | 乱数生成機能の実装 | FastMCP | | リソースプロバイダー | データファイルアクセス | asyncio | | プロンプトテンプレート | ユーザーインタラクション定義 | YAML/JSON | ### 2.3 通信方式 - **プライマリ**: stdio(標準入出力) - **セカンダリ**: Streamable HTTP(将来拡張用) - **プロトコル**: JSON-RPC 2.0 over stdio --- ## 3. 機能要件 ### 3.1 MCPサーバー基本機能 #### 3.1.1 サーバー初期化 ```python @dataclass class ServerCapabilities: tools: bool = True # ツール機能を提供 resources: bool = True # リソース機能を提供 prompts: bool = True # プロンプト機能を提供 logging: bool = True # ロギング機能を有効化 ``` #### 3.1.2 ライフサイクル管理 | フェーズ | 処理内容 | |---------|---------| | 起動 | 環境初期化、デフォルト設定読込 | | 初期化 | クライアント接続、capability交換 | | 実行 | リクエスト処理、レスポンス送信 | | 終了 | リソース解放、ログ保存 | ### 3.2 ツール機能 #### 3.2.1 generate_random_numbers ```python @mcp.tool() def generate_random_numbers( count: int = 5, min_value: int = 0, max_value: int = 999, seed: int | None = None ) -> RandomNumberResult: """Generate random numbers with specified parameters.""" ``` **パラメータ仕様**: | パラメータ | 型 | デフォルト | 説明 | |-----------|-----|-----------|------| | count | int | 5 | 生成する乱数の個数 | | min_value | int | 0 | 乱数の最小値 | | max_value | int | 999 | 乱数の最大値 | | seed | int\|None | None | 乱数シード(再現性用) | **戻り値(構造化出力)**: ```python class RandomNumberResult(BaseModel): numbers: List[int] count: int min_value: int max_value: int timestamp: str seed: Optional[int] = None ``` #### 3.2.2 save_random_data ```python @mcp.tool() def save_random_data( numbers: List[int], filename: str = "data.csv" ) -> SaveResult: """Save random numbers to CSV file.""" ``` #### 3.2.3 analyze_random_data ```python @mcp.tool() def analyze_random_data( numbers: List[int] ) -> StatisticsResult: """Analyze statistical properties of random numbers.""" ``` ### 3.3 リソース機能 #### 3.3.1 動的リソース ```python @mcp.resource("random://current") def get_current_random_data() -> str: """Get the most recently generated random numbers.""" ``` #### 3.3.2 ファイルリソース ```python @mcp.resource("file://data/{filename}") def get_saved_data(filename: str) -> str: """Read saved random data from file.""" ``` #### 3.3.3 メタデータリソース ```python @mcp.resource("meta://statistics") def get_statistics() -> str: """Get statistical metadata about all generated data.""" ``` ### 3.4 プロンプト機能 #### 3.4.1 インタラクティブ生成 ```python @mcp.prompt(title="Generate Random Dataset") def generate_dataset_prompt( purpose: str = "testing", count: int = 10, distribution: str = "uniform" ) -> List[Message]: """Interactive prompt for dataset generation.""" ``` #### 3.4.2 分析レポート生成 ```python @mcp.prompt(title="Analyze Random Data") def analyze_data_prompt( data_source: str ) -> str: """Generate analysis report prompt.""" ``` --- ## 4. 非機能要件 ### 4.1 パフォーマンス要件 | メトリクス | 目標値 | 測定方法 | |-----------|--------|----------| | レスポンスタイム | <100ms | 95パーセンタイル | | 同時接続数 | 10 | 最大同時クライアント | | メモリ使用量 | <200MB | ピーク時使用量 | | CPU使用率 | <20% | アイドル時 | ### 4.2 信頼性要件 - **可用性**: 99.9%(ローカル実行環境) - **エラーハンドリング**: 全例外の適切なキャッチと報告 - **データ整合性**: トランザクショナルな書き込み ### 4.3 セキュリティ要件 - **認証**: OAuth 2.1対応(オプション) - **入力検証**: 全パラメータの型・範囲チェック - **ファイルアクセス**: サンドボックス内のみ ### 4.4 互換性要件 - **MCPバージョン**: 仕様2025-06-18準拠 - **Python**: 3.8以上 - **SDK**: mcp[cli] 最新版 --- ## 5. 実装詳細 ### 5.1 プロジェクト構造 ``` mcp_f0_server/ ├── src/ │ ├── __init__.py │ ├── server.py # MCPサーバーメイン │ ├── tools.py # ツール実装 │ ├── resources.py # リソース実装 │ ├── prompts.py # プロンプト実装 │ └── models.py # Pydanticモデル定義 ├── tests/ │ ├── test_server.py │ ├── test_tools.py │ └── test_integration.py ├── config/ │ └── server_config.yaml ├── pyproject.toml ├── README.md └── requirements.txt ``` ### 5.2 主要実装ファイル #### 5.2.1 server.py - メインサーバー ```python from mcp.server.fastmcp import FastMCP from contextlib import asynccontextmanager from typing import AsyncIterator import logging # ロギング設定 logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # アプリケーションコンテキスト @dataclass class AppContext: data_dir: Path current_data: Optional[List[int]] = None @asynccontextmanager async def lifespan(server: FastMCP) -> AsyncIterator[AppContext]: """サーバーライフサイクル管理""" data_dir = Path("./data") data_dir.mkdir(exist_ok=True) context = AppContext(data_dir=data_dir) logger.info("MCP Server initialized") try: yield context finally: logger.info("MCP Server shutting down") # MCPサーバーインスタンス mcp = FastMCP( name="f0_random_server", version="1.0.0", lifespan=lifespan ) ``` #### 5.2.2 models.py - データモデル定義 ```python from pydantic import BaseModel, Field from typing import List, Optional from datetime import datetime class RandomNumberResult(BaseModel): """乱数生成結果の構造化データ""" numbers: List[int] = Field(description="生成された乱数リスト") count: int = Field(description="乱数の個数") min_value: int = Field(description="最小値") max_value: int = Field(description="最大値") timestamp: str = Field(description="生成日時") seed: Optional[int] = Field(default=None, description="使用シード") class StatisticsResult(BaseModel): """統計分析結果""" mean: float = Field(description="平均値") median: float = Field(description="中央値") std_dev: float = Field(description="標準偏差") min: int = Field(description="最小値") max: int = Field(description="最大値") count: int = Field(description="データ数") ``` ### 5.3 エラーハンドリング ```python class MCPServerError(Exception): """基底例外クラス""" pass class ValidationError(MCPServerError): """入力検証エラー""" pass class ResourceNotFoundError(MCPServerError): """リソース未検出エラー""" pass @mcp.tool() async def safe_operation(ctx: Context, **kwargs): try: # 処理実装 result = await process_data(**kwargs) return result except ValidationError as e: await ctx.error(f"Validation failed: {e}") raise except Exception as e: await ctx.error(f"Unexpected error: {e}") logger.exception("Operation failed") raise MCPServerError("Internal server error") ``` --- ## 6. テスト戦略 ### 6.1 テストレベル | レベル | カバレッジ目標 | テスト内容 | |--------|--------------|-----------| | ユニットテスト | 90% | 個別関数の動作確認 | | 統合テスト | 80% | MCPプロトコル通信 | | E2Eテスト | 主要シナリオ | Claude Desktop統合 | ### 6.2 テストシナリオ #### 6.2.1 正常系テスト 1. **基本的な乱数生成** - デフォルトパラメータでの生成 - カスタムパラメータでの生成 - シード指定での再現性確認 2. **ファイル操作** - CSV保存と読込 - 複数ファイルの管理 - 同時アクセス処理 3. **リソースアクセス** - 動的リソースの取得 - テンプレートパラメータ解決 #### 6.2.2 異常系テスト 1. **入力検証** - 範囲外パラメータ - 型不一致 - 必須パラメータ欠落 2. **エラーリカバリー** - ファイル書込失敗 - メモリ不足 - タイムアウト ### 6.3 テスト実装例 ```python import pytest from unittest.mock import AsyncMock, patch from mcp.client import ClientSession @pytest.mark.asyncio async def test_generate_random_numbers(): """乱数生成ツールのテスト""" async with create_test_client() as session: result = await session.call_tool( "generate_random_numbers", arguments={"count": 10, "seed": 42} ) assert result.structuredContent is not None data = result.structuredContent assert data["count"] == 10 assert len(data["numbers"]) == 10 assert data["seed"] == 42 @pytest.mark.asyncio async def test_resource_access(): """リソースアクセスのテスト""" async with create_test_client() as session: resource = await session.read_resource( "random://current" ) assert resource.contents content = resource.contents[0] assert isinstance(content, TextContent) ``` --- ## 7. デプロイメント ### 7.1 Claude Desktop統合 #### 7.1.1 設定ファイル(claude_desktop_config.json) ```json { "mcpServers": { "f0_random": { "command": "uv", "args": ["run", "mcp_f0_server.py"], "cwd": "/absolute/path/to/mcp_f0_server", "env": { "LOG_LEVEL": "INFO", "DATA_DIR": "./data" } } } } ``` #### 7.1.2 インストール手順 ```bash # 1. プロジェクト作成 uv init mcp_f0_server cd mcp_f0_server # 2. 依存関係インストール uv add "mcp[cli]" # 3. サーバー実装配置 cp mcp_f0_server.py ./ # 4. 権限設定(macOS/Linux) chmod +x mcp_f0_server.py # 5. Claude Desktopへの登録 uv run mcp install mcp_f0_server.py --name "F0 Random Generator" # 6. 動作確認 uv run mcp dev mcp_f0_server.py ``` ### 7.2 環境変数設定 | 変数名 | デフォルト値 | 説明 | |--------|------------|------| | MCP_LOG_LEVEL | INFO | ログレベル | | MCP_DATA_DIR | ./data | データ保存ディレクトリ | | MCP_MAX_NUMBERS | 10000 | 最大生成数制限 | | MCP_ENABLE_STATS | true | 統計機能の有効化 | --- ## 8. 監視と運用 ### 8.1 ログ管理 ```python # ログ設定 LOGGING_CONFIG = { "version": 1, "handlers": { "file": { "class": "logging.handlers.RotatingFileHandler", "filename": "mcp_f0_server.log", "maxBytes": 10485760, # 10MB "backupCount": 5, "formatter": "detailed" }, "console": { "class": "logging.StreamHandler", "formatter": "simple" } }, "formatters": { "detailed": { "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s" }, "simple": { "format": "%(levelname)s - %(message)s" } } } ``` ### 8.2 メトリクス収集 | メトリクス | 収集方法 | アラート閾値 | |-----------|---------|------------| | リクエスト数 | カウンター | - | | レスポンスタイム | ヒストグラム | >500ms | | エラー率 | レート計算 | >5% | | メモリ使用量 | システム監視 | >500MB | ### 8.3 トラブルシューティング #### 8.3.1 一般的な問題と解決策 | 問題 | 症状 | 解決策 | |-----|-----|--------| | 接続失敗 | "Server not found" | パス設定確認、権限チェック | | タイムアウト | レスポンスなし | ログ確認、プロセス再起動 | | データ不整合 | 誤った結果 | キャッシュクリア、再初期化 | #### 8.3.2 デバッグ手順 ```bash # 1. MCPインスペクターで確認 uv run mcp dev mcp_f0_server.py # 2. ログファイル確認(macOS/Linux) tail -f ~/Library/Logs/Claude/mcp-server-f0_random.log # 3. 手動実行テスト uv run mcp_f0_server.py # 4. 設定検証 uv run mcp validate-config ``` --- ## 9. セキュリティ考慮事項 ### 9.1 入力サニタイゼーション ```python def validate_input(value: Any, schema: Type[BaseModel]) -> BaseModel: """入力値の検証とサニタイゼーション""" try: return schema.model_validate(value) except ValidationError as e: logger.warning(f"Invalid input: {e}") raise MCPServerError("Invalid input parameters") ``` ### 9.2 ファイルアクセス制御 ```python ALLOWED_EXTENSIONS = {'.csv', '.json', '.txt'} BASE_DATA_DIR = Path("./data").resolve() def validate_filepath(filepath: str) -> Path: """ファイルパスの安全性検証""" path = Path(filepath).resolve() # ディレクトリトラバーサル防止 if not path.is_relative_to(BASE_DATA_DIR): raise SecurityError("Access denied") # 拡張子チェック if path.suffix not in ALLOWED_EXTENSIONS: raise SecurityError("Invalid file type") return path ``` ### 9.3 レート制限 ```python from asyncio import Semaphore class RateLimiter: def __init__(self, max_requests: int = 100): self.semaphore = Semaphore(max_requests) async def __aenter__(self): await self.semaphore.acquire() async def __aexit__(self, *args): self.semaphore.release() rate_limiter = RateLimiter() @mcp.tool() async def limited_operation(ctx: Context): async with rate_limiter: # 処理実装 pass ``` --- ## 10. 将来の拡張計画 ### 10.1 短期計画(3ヶ月) - [ ] Streamable HTTP transport対応 - [ ] バッチ処理機能の追加 - [ ] 統計分析機能の拡張 - [ ] プロンプトテンプレートの充実 ### 10.2 中期計画(6ヶ月) - [ ] FGDBシステムとの完全統合 - [ ] 他の関数ブロックのMCP化 - [ ] OAuth認証実装 - [ ] WebUIダッシュボード ### 10.3 長期計画(1年) - [ ] マルチテナント対応 - [ ] 分散処理対応 - [ ] MLパイプライン統合 - [ ] エンタープライズ機能 --- ## 11. リスク管理 ### 11.1 技術的リスク | リスク | 発生確率 | 影響度 | 対策 | |--------|---------|--------|------| | MCP仕様変更 | 中 | 高 | 定期的な仕様確認、バージョン管理 | | パフォーマンス劣化 | 低 | 中 | プロファイリング、最適化 | | 依存関係の脆弱性 | 中 | 高 | 定期的な更新、セキュリティ監査 | ### 11.2 運用リスク | リスク | 発生確率 | 影響度 | 対策 | |--------|---------|--------|------| | データ損失 | 低 | 高 | 定期バックアップ、冗長化 | | 設定ミス | 中 | 中 | 設定検証ツール、ドキュメント整備 | | リソース枯渇 | 低 | 中 | リソース監視、自動スケーリング | --- ## 12. 承認と合意事項 ### 12.1 ステークホルダー承認 | 役割 | 氏名 | 承認日 | 署名 | |------|------|--------|------| | プロジェクトマネージャー | - | - | - | | 技術リード | - | - | - | | QAリード | - | - | - | | セキュリティ責任者 | - | - | - | ### 12.2 前提条件 1. Python 3.8以上の実行環境が利用可能 2. MCP SDK最新版へのアクセス権限 3. Claude Desktopがインストール済み 4. 開発・テスト環境の提供 ### 12.3 制約事項 1. ローカル実行環境に限定(初期バージョン) 2. 同期的なファイルI/O処理 3. 単一プロセスでの実行 4. 英語ドキュメントのみ(初期) --- ## 付録A: 用語集 | 用語 | 定義 | |-----|------| | MCP | Model Context Protocol - LLMアプリケーション向け標準プロトコル | | FastMCP | MCPサーバー構築用Pythonフレームワーク | | stdio | Standard Input/Output - プロセス間通信方式 | | Tool | MCPでLLMに公開される実行可能な関数 | | Resource | MCPで提供されるデータアクセスポイント | | Prompt | MCPで定義されるインタラクションテンプレート | | FGDB | Functional Graph Database - 関数実行履歴管理システム | | Claude Desktop | Anthropic社のデスクトップAIアシスタント | --- ## 付録B: 参考資料 ### B.1 公式ドキュメント - [Model Context Protocol Specification](https://spec.modelcontextprotocol.io) - [MCP Python SDK Documentation](https://github.com/modelcontextprotocol/python-sdk) - [FastMCP Framework Guide](https://modelcontextprotocol.io/docs/tools/fastmcp) - [Claude Desktop Integration](https://modelcontextprotocol.io/docs/tools/claude-desktop) ### B.2 関連仕様 - [JSON-RPC 2.0 Specification](https://www.jsonrpc.org/specification) - [OAuth 2.1 Draft](https://datatracker.ietf.org/doc/draft-ietf-oauth-v2-1/) - [RFC 9728 - Protected Resource Metadata](https://datatracker.ietf.org/doc/rfc9728/) ### B.3 内部ドキュメント - FGDB システム仕様書 - f0_make_randomvalues 要件定義書(specification.md) --- ## 付録C: サンプルコード ### C.1 最小実装例 ```python #!/usr/bin/env python3 """ Minimal MCP server implementation for f0_make_randomvalues """ from mcp.server.fastmcp import FastMCP import random from typing import List # Create MCP server instance mcp = FastMCP(name="f0_random_minimal", version="1.0.0") @mcp.tool() def generate_random(count: int = 5) -> List[int]: """Generate random numbers""" return [random.randint(0, 999) for _ in range(count)] if __name__ == "__main__": mcp.run() ``` ### C.2 完全実装例(抜粋) ```python #!/usr/bin/env python3 """ Complete MCP server implementation with all features """ from mcp.server.fastmcp import FastMCP, Context from pydantic import BaseModel, Field from typing import List, Optional from pathlib import Path import random import csv import json from datetime import datetime from contextlib import asynccontextmanager from dataclasses import dataclass import logging # Configure logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) # Data models class RandomNumberResult(BaseModel): """Structured output for random number generation""" numbers: List[int] = Field(description="Generated random numbers") count: int = Field(description="Number of values generated") min_value: int = Field(description="Minimum value") max_value: int = Field(description="Maximum value") timestamp: str = Field(description="Generation timestamp") seed: Optional[int] = Field(default=None, description="Random seed used") # Application context @dataclass class AppContext: data_dir: Path current_data: Optional[List[int]] = None stats_cache: dict = None # Lifespan management @asynccontextmanager async def app_lifespan(server: FastMCP): """Manage server lifecycle""" # Initialize on startup data_dir = Path("./data") data_dir.mkdir(exist_ok=True) context = AppContext( data_dir=data_dir, stats_cache={} ) logger.info(f"MCP Server '{server.name}' initialized") logger.info(f"Data directory: {data_dir.absolute()}") try: yield context finally: # Cleanup on shutdown logger.info(f"MCP Server '{server.name}' shutting down") # Create server with lifespan mcp = FastMCP( name="f0_random_server", version="1.0.0", lifespan=app_lifespan ) # Tool implementations @mcp.tool() async def generate_random_numbers( ctx: Context, count: int = 5, min_value: int = 0, max_value: int = 999, seed: Optional[int] = None ) -> RandomNumberResult: """ Generate random numbers with specified parameters. Args: count: Number of random values to generate (default: 5) min_value: Minimum value (default: 0) max_value: Maximum value (default: 999) seed: Random seed for reproducibility (optional) Returns: Structured result containing generated numbers and metadata """ # Log operation await ctx.info(f"Generating {count} random numbers [{min_value}, {max_value}]") # Validate inputs if count <= 0 or count > 10000: raise ValueError("Count must be between 1 and 10000") if min_value >= max_value: raise ValueError("min_value must be less than max_value") # Set seed if provided if seed is not None: random.seed(seed) await ctx.debug(f"Using seed: {seed}") # Generate numbers numbers = [random.randint(min_value, max_value) for _ in range(count)] # Store in context ctx.request_context.lifespan_context.current_data = numbers # Create result result = RandomNumberResult( numbers=numbers, count=count, min_value=min_value, max_value=max_value, timestamp=datetime.now().isoformat(), seed=seed ) await ctx.info(f"Successfully generated {count} random numbers") return result # Resource implementations @mcp.resource("random://current") async def get_current_data(ctx: Context) -> str: """Get the most recently generated random numbers""" app_ctx = ctx.request_context.lifespan_context if app_ctx.current_data is None: return json.dumps({"error": "No data generated yet"}) return json.dumps({ "numbers": app_ctx.current_data, "count": len(app_ctx.current_data) }, indent=2) # Prompt implementations @mcp.prompt(title="Generate Test Dataset") def generate_test_dataset( purpose: str = "testing", size: str = "small" ) -> str: """Generate a prompt for creating test datasets""" sizes = { "small": 10, "medium": 100, "large": 1000 } count = sizes.get(size, 10) return f""" Please generate a random dataset for {purpose}. Requirements: - Size: {size} ({count} numbers) - Range: 0-999 - Format: CSV Use the generate_random_numbers tool with count={count}, then save the results. """ # Entry point if __name__ == "__main__": import sys # Check for debug mode if "--debug" in sys.argv: logging.getLogger().setLevel(logging.DEBUG) logger.debug("Debug mode enabled") # Run server logger.info("Starting MCP server...") mcp.run() ``` --- ## 改訂履歴 | バージョン | 日付 | 変更内容 | 作成者 | |-----------|------|---------|--------| | 1.0 | 2025-01-26 | 初版作成 | MCP開発チーム | --- *本仕様書は、f0_make_randomvalues関数ブロックのMCPサーバー実装に関する要件定義および詳細仕様を記載したものである。*

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/sengokusal2025/f0_20251002'

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