Skip to main content
Glama
fusion_client.py5.82 kB
import logging from dataclasses import dataclass from typing import Any import httpx # ログ設定 logging.basicConfig(level=logging.INFO) logger = logging.getLogger("Fusion MCP Server") # 定数 DEFAULT_HOST = "localhost" DEFAULT_PORT = 3600 DEFAULT_TIMEOUT = 10.0 ADDIN_CONNECTION_ERROR = { "type": "FusionServerConnectionError", "message": "Cannot connect to 'mcp-addin', Fusion Add-in. Instruct the user to run 'mcp-addin'.", } ADDIN_TIMEOUT_ERROR = { "type": "FusionServerTimeoutError", "message": "Fusion took too long to respond. The operation may be complex or Fusion may be busy. Break complex operations into smaller steps.", } RESPONSE_PARSE_ERROR = { "type": "FusionServerResponseError", "message": "Received invalid response from Fusion. This may indicate a compatibility issue. Instruct the user to check 'Fusion MCP' is up to date.", } UNKNOWN_ERROR = { "type": "UnknownError", "message": "An unexpected error occurred in the MCP server. Check the server logs for details.", } def format_error( error_type: str | None = None, message: str | None = None, ) -> str: if error_type is None: error_type = UNKNOWN_ERROR["type"] if message is None: message = UNKNOWN_ERROR["message"] return f"{error_type}: {message}" @dataclass class FusionAddinClient: """Fusionアドインのサーバーと接続するクライアント""" host: str = DEFAULT_HOST port: int = DEFAULT_PORT @property def base_url(self) -> str: """サーバーのベースURL""" return f"http://{self.host}:{self.port}" async def call_action( self, action_name: str, params: dict[str, Any] | None = None, ) -> dict[str, Any]: """アドインサーバーのアクションを呼び出す Args: action_name (str): 呼び出すアクション名 params (dict, optional): アクションのパラメータ Returns: dict: アクションの実行結果 """ url = f"{self.base_url}/{action_name}" params = params or {} logger.info(f"Calling action '{action_name}' at {url}") try: async with httpx.AsyncClient(timeout=DEFAULT_TIMEOUT) as client: response = await client.post(url, json=params) # JSONレスポンスをデコード try: response_data = response.json() except Exception: logger.exception(f"Failed to decode JSON response from {url}: {response.text}") return self._create_error_response( RESPONSE_PARSE_ERROR["type"], RESPONSE_PARSE_ERROR["message"], ) # レスポンス処理 if response.is_success: return self._handle_ok_response(response_data, action_name) return self._handle_error_response(response_data, response.status_code, action_name) except httpx.ConnectError: logger.exception(f"Connection to {url} failed. Is the server running?") return self._create_error_response( ADDIN_CONNECTION_ERROR["type"], ADDIN_CONNECTION_ERROR["message"], ) except httpx.TimeoutException: logger.exception(f"Request to {url} timed out.") return self._create_error_response( ADDIN_TIMEOUT_ERROR["type"], ADDIN_TIMEOUT_ERROR["message"], ) except httpx.RequestError as e: logger.exception(f"Request failed: {e!s}") return self._create_error_response( "FusionServerRequestError", f"Network error while communicating with Fusion Add-in: {e!s}. Please ask the user to check their network connection and ensure Fusion is accessible.", ) except Exception as e: logger.exception(f"Unexpected error while calling action '{action_name}': {e!s}") return self._create_error_response( UNKNOWN_ERROR["type"], f"{UNKNOWN_ERROR['message']} Details: {e!s}", ) def _handle_ok_response( self, response_data: dict[str, Any], action_name: str, ) -> dict[str, Any]: """HTTPステータスが正常な場合のレスポンス処理""" is_success = response_data.get("success", False) if is_success: return response_data # サーバーからの論理エラー logger.error(f"Action '{action_name}' failed with error: {response_data.get('error', {})}") error_info = response_data.get("error", {}) return self._create_error_response( error_info.get("type", "FusionServerError"), error_info.get("message", "An unknown error occurred"), ) def _handle_error_response( self, response_data: dict[str, Any], status_code: int, action_name: str, ) -> dict[str, Any]: """HTTPエラーステータスの場合のレスポンス処理""" logger.error( f"Action '{action_name}' failed with HTTP status {status_code}: {response_data}", ) error_info = response_data.get("error", {}) return self._create_error_response( error_info.get("type", "ServerError"), error_info.get("message", f"Server returned status {status_code}"), ) def _create_error_response(self, error_type: str, message: str) -> dict[str, Any]: """エラーレスポンスを作成する""" return { "success": False, "error": { "type": error_type, "message": message, }, }

Latest Blog Posts

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/shiguri-01/fusion-mcp'

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