Skip to main content
Glama

SuzieQ MCP Server

MIT License
3
  • Apple
  • Linux
server.py7.15 kB
# server.py # Implements the MCP server logic and SuzieQ tools. import httpx # Using httpx for asynchronous HTTP requests import os import json from typing import Any, Dict, Optional from mcp.server.fastmcp import FastMCP from dotenv import load_dotenv # Import dotenv # Load environment variables from .env file if it exists load_dotenv() # --- Configuration --- # Get SuzieQ API endpoint and key from environment variables SUZIEQ_API_ENDPOINT = os.getenv("SUZIEQ_API_ENDPOINT", None) # Default to None if not set SUZIEQ_API_KEY = os.getenv("SUZIEQ_API_KEY", None) # Default to None if not set # --- MCP Server Setup --- # Initialize FastMCP server with a name mcp = FastMCP("SuzieQ MCP Server") # --- SuzieQ API Interaction Helper (Generalized) --- async def _query_suzieq_api(verb: str, table: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: """ Asynchronously queries the SuzieQ REST API for a given verb and table. Args: verb: The SuzieQ verb to execute (e.g., 'show', 'summarize'). table: The SuzieQ table name (e.g., 'device', 'bgp', 'interface'). params: A dictionary of query parameters for filtering (e.g., {'hostname': 'leaf01', 'vrf': 'default'}). Returns: A dictionary containing the API response or an error message. """ # Check if configuration is missing if not SUZIEQ_API_ENDPOINT or not SUZIEQ_API_KEY: error_msg = "SuzieQ API endpoint or key not configured. Set SUZIEQ_API_ENDPOINT and SUZIEQ_API_KEY environment variables or in .env file." print(f"[ERROR] {error_msg}") # Log configuration error return {"error": error_msg} # Construct the API URL using the provided verb and table api_endpoint_clean = SUZIEQ_API_ENDPOINT.rstrip('/') # Assuming the API structure follows /{table}/{verb} pattern api_url = f"{api_endpoint_clean}/{table}/{verb}" # --- Authentication --- # Prepare parameters, adding the API key as 'access_token' query parameter query_params = params if params else {} query_params["access_token"] = SUZIEQ_API_KEY # Add key as query param query_params["format"] = "json" # Ensure response is JSON headers = {} # No custom headers needed now for auth # --------------------------- async with httpx.AsyncClient() as client: try: # Use headers={}, params=query_params print(f"[INFO] Querying SuzieQ API: {api_url} with params: {query_params}") # Debug print response = await client.get(api_url, headers=headers, params=query_params, timeout=30.0) print(f"[INFO] SuzieQ API Response Status: {response.status_code}") # Debug print response.raise_for_status() # Raise an exception for bad status codes (4xx or 5xx) if response.status_code == 204: return {"warning": f"Received empty response (204 No Content) from SuzieQ API for {verb} {table}"} content_type = response.headers.get('content-type', '') if 'application/json' in content_type: return response.json() else: error_detail = f"Unexpected content type received: {content_type}. Response text: {response.text}" print(f"[ERROR] {error_detail}") return {"error": error_detail} except httpx.HTTPStatusError as e: error_detail = f"HTTP error occurred: {e.response.status_code} - {e.response.text}" print(f"[ERROR] {error_detail}") # Debug print return {"error": error_detail} except httpx.RequestError as e: error_detail = f"An error occurred while requesting {e.request.url!r}: {e}" print(f"[ERROR] {error_detail}") # Debug print return {"error": error_detail} except json.JSONDecodeError as e: error_detail = f"Failed to decode JSON response from SuzieQ API: {e}. Response text: {response.text}" print(f"[ERROR] {error_detail}") return {"error": error_detail} except Exception as e: error_detail = f"An unexpected error occurred: {str(e)}" print(f"[ERROR] {error_detail}") # Debug print return {"error": error_detail} # --- MCP Tool Definitions --- @mcp.tool() async def run_suzieq_show(table: str, filters: Optional[Dict[str, Any]] = None) -> str: """ Runs a SuzieQ 'show' query via its REST API. Args: table: The name of the SuzieQ table to query (e.g., 'device', 'bgp', 'interface', 'route'). filters: An optional dictionary of filter parameters for the SuzieQ query (e.g., {"hostname": "leaf01", "vrf": "default", "state": "Established"}). Keys should match SuzieQ filter names. Values can be strings or lists of strings. If no filters are needed, this can be None, null, or an empty dictionary. Returns: A JSON string representing the result from the SuzieQ API, or a JSON string with an error message. """ actual_filters = filters if isinstance(filters, dict) else None # Call the generalized helper function with verb='show' result = await _query_suzieq_api(verb="show", table=table, params=actual_filters) try: # Serialize the result dictionary to a JSON string return json.dumps(result, indent=2, ensure_ascii=False) except TypeError as e: error_message = f"Error serializing SuzieQ 'show' response to JSON: {str(e)}" print(f"[ERROR] {error_message}") # Debug print return json.dumps({"error": error_message}) @mcp.tool() async def run_suzieq_summarize(table: str, filters: Optional[Dict[str, Any]] = None) -> str: """ Runs a SuzieQ 'summarize' query via its REST API. Args: table: The name of the SuzieQ table to summarize (e.g., 'device', 'bgp', 'interface', 'route'). filters: An optional dictionary of filter parameters for the SuzieQ query (e.g., {"hostname": "leaf01", "vrf": "default"}). Keys should match SuzieQ filter names. Values can be strings or lists of strings. If no filters are needed, this can be None, null, or an empty dictionary. Returns: A JSON string representing the summarized result from the SuzieQ API, or a JSON string with an error message. """ actual_filters = filters if isinstance(filters, dict) else None # Call the generalized helper function with verb='summarize' result = await _query_suzieq_api(verb="summarize", table=table, params=actual_filters) try: # Serialize the result dictionary to a JSON string return json.dumps(result, indent=2, ensure_ascii=False) except TypeError as e: error_message = f"Error serializing SuzieQ 'summarize' response to JSON: {str(e)}" print(f"[ERROR] {error_message}") # Debug print return json.dumps({"error": error_message}) # --- Main Execution (Example) --- # You would typically run this server using an ASGI server like uvicorn: # uvicorn server:mcp --reload # Or integrate it into a larger application framework.

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/PovedaAqui/suzieq-mcp'

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