Skip to main content
Glama

Panther MCP Server

Official
Apache 2.0
31
  • Apple
server.py4.69 kB
import logging import os import signal import sys from importlib.metadata import version import click from fastmcp import FastMCP # Server name MCP_SERVER_NAME = "mcp-panther" # Get log level from environment variable, default to WARNING if not set log_level_name = os.environ.get("LOG_LEVEL", "WARNING") # Convert string log level to logging constant log_level = getattr(logging, log_level_name.upper(), logging.DEBUG) # Configure logging def configure_logging(log_file: str | None = None, *, force: bool = False) -> None: """Configure logging to stderr or the specified file. This also reconfigures the ``FastMCP`` logger so that all FastMCP output uses the same handler as the rest of the application. """ handler: logging.Handler if log_file: handler = logging.FileHandler(os.path.expanduser(log_file)) else: handler = logging.StreamHandler(sys.stderr) logging.basicConfig( level=log_level, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", handlers=[handler], force=force, ) # Ensure FastMCP logs propagate to the root logger fastmcp_logger = logging.getLogger("FastMCP") for hdlr in list(fastmcp_logger.handlers): fastmcp_logger.removeHandler(hdlr) fastmcp_logger.propagate = True fastmcp_logger.setLevel(log_level) configure_logging(os.environ.get("MCP_LOG_FILE")) logger = logging.getLogger(MCP_SERVER_NAME) # Support multiple import paths to accommodate different execution contexts: # 1. When running as a binary, uvx expects relative imports # 2. When running with MCP inspector: `uv run mcp dev src/mcp_panther/server.py` # 3. When installing: `uv run mcp install src/mcp_panther/server.py` try: from panther_mcp_core.prompts.registry import register_all_prompts from panther_mcp_core.resources.registry import register_all_resources from panther_mcp_core.tools.registry import register_all_tools except ImportError: from .panther_mcp_core.prompts.registry import register_all_prompts from .panther_mcp_core.resources.registry import register_all_resources from .panther_mcp_core.tools.registry import register_all_tools # Server dependencies deps = [ "gql[aiohttp]", "aiohttp", ] # Create the MCP server mcp = FastMCP(MCP_SERVER_NAME, dependencies=deps) # Register all tools with MCP using the registry register_all_tools(mcp) # Register all prompts with MCP using the registry register_all_prompts(mcp) # Register all resources with MCP using the registry register_all_resources(mcp) def handle_signals(): def signal_handler(sig, frame): logger.info(f"Received signal {sig}, shutting down...") sys.exit(0) signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) # SIGHUP is not available on Windows if hasattr(signal, "SIGHUP"): signal.signal(signal.SIGHUP, signal_handler) @click.command() @click.version_option(version("mcp-panther"), "--version", "-v") @click.option( "--transport", type=click.Choice(["stdio", "streamable-http"]), default=os.environ.get("MCP_TRANSPORT", default="stdio"), help="Transport type (stdio or streamable-http)", ) @click.option( "--port", default=int(os.environ.get("MCP_PORT", default="3000")), help="Port to use for streamable HTTP transport", ) @click.option( "--host", default=os.environ.get("MCP_HOST", default="127.0.0.1"), help="Host to bind to for streamable HTTP transport", ) @click.option( "--log-file", type=click.Path(), default=os.environ.get("MCP_LOG_FILE"), help="Write logs to this file instead of stderr", ) def main(transport: str, port: int, host: str, log_file: str | None): """Run the Panther MCP server with the specified transport""" # Set up signal handling handle_signals() # Reconfigure logging if a log file is provided if log_file: configure_logging(log_file, force=True) major = sys.version_info.major minor = sys.version_info.minor micro = sys.version_info.micro logger.info(f"Python {major}.{minor}.{micro}") if transport == "streamable-http": logger.info( f"Starting Panther MCP Server with streamable HTTP transport on {host}:{port}" ) try: mcp.run(transport="streamable-http", host=host, port=port) except KeyboardInterrupt: logger.info("Keyboard interrupt received, forcing immediate exit") sys.exit(0) else: logger.info("Starting Panther MCP Server with stdio transport") # Let FastMCP handle all the asyncio details internally mcp.run()

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/panther-labs/mcp-panther'

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