Skip to main content
Glama
logs.py4.47 kB
# # MCP Foxxy Bridge - Log Management Commands # # Copyright (C) 2024 Billy Bryant # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <https://www.gnu.org/licenses/>. # """Log management commands for MCP servers.""" import asyncio import logging from pathlib import Path from typing import Any from rich.console import Console from mcp_foxxy_bridge.oauth.utils import _validate_server_name from mcp_foxxy_bridge.utils.config_migration import get_server_logs_dir async def handle_mcp_logs( args: Any, config_path: Path, config_dir: Path, console: Console, logger: logging.Logger ) -> None: """Handle MCP server log viewing and tailing commands. Args: args: Command line arguments containing server_name, follow, and lines options config_path: Path to configuration file (unused) config_dir: Configuration directory (unused) console: Rich console for output logger: Logger for error reporting Displays log entries for the specified MCP server. Supports both static viewing of recent entries and live tailing mode. Uses the system 'tail' command for efficient log following. """ server_name = _validate_server_name(args.server_name) follow = args.follow if hasattr(args, "follow") else False lines = args.lines if hasattr(args, "lines") else 50 # Get the log file path for this server logs_dir = get_server_logs_dir() log_file = logs_dir / f"{server_name}.log" if not log_file.exists(): console.print(f"[red]❌ No log file found for server '[bold]{server_name}[/bold]'[/red]") console.print(f"[dim]Expected: {log_file}[/dim]") console.print("[dim]Note: Server may not have been started yet or may not exist.[/dim]") return if follow: console.print( f"[yellow]📖 Tailing logs for MCP server '[bold]{server_name}[/bold]' (press Ctrl+C to stop)[/yellow]" ) console.print(f"[dim]Reading from: {log_file}[/dim]\n") # Use tail -f to follow the log file try: process = await asyncio.create_subprocess_exec( "tail", "-f", str(log_file), stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE ) while True: if process.stdout is None: break line = await process.stdout.readline() if not line: break console.print(line.decode("utf-8").rstrip()) except KeyboardInterrupt: console.print("\n[yellow]📖 Log tailing stopped.[/yellow]") if process: process.terminate() await process.wait() except Exception as e: console.print(f"[red]❌ Error tailing log file: {e}[/red]") else: console.print( f"[yellow]📖 Showing last {lines} log entries for MCP server '[bold]{server_name}[/bold]'[/yellow]" ) console.print(f"[dim]Reading from: {log_file}[/dim]\n") try: # Use tail to get the last N lines process = await asyncio.create_subprocess_exec( "tail", "-n", str(lines), str(log_file), stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE ) stdout, stderr = await process.communicate() if process.returncode == 0: log_content = stdout.decode("utf-8").strip() if log_content: console.print(log_content) else: console.print(f"[dim]Log file for '{server_name}' is empty.[/dim]") else: error_msg = stderr.decode("utf-8").strip() console.print(f"[red]❌ Error reading log file: {error_msg}[/red]") except Exception as e: console.print(f"[red]❌ Error reading log file: {e}[/red]")

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/billyjbryant/mcp-foxxy-bridge'

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