Skip to main content
Glama
toolcall_log_tail.py2.08 kB
from __future__ import annotations import os, json from typing import Any, Dict from pathlib import Path from mcp.types import TextContent from tools.shared.base_tool import BaseTool class ToolcallLogTail(BaseTool): def get_name(self) -> str: return "toolcall_log_tail" def get_description(self) -> str: return ( "Return the last N tool-call events from EX_TOOLCALL_LOG_PATH JSONL file (sanitized)." ) def get_input_schema(self) -> Dict[str, Any]: return { "type": "object", "properties": { "n": {"type": "integer", "default": 20, "minimum": 1, "maximum": 200}, "path": {"type": "string", "description": "Optional override path"}, }, } async def prepare_prompt(self, request) -> str: return "" async def execute(self, arguments: dict[str, Any]) -> list[TextContent]: n = int(arguments.get("n") or 20) p = arguments.get("path") or os.getenv("EX_TOOLCALL_LOG_PATH", "") if not p: return [TextContent(type="text", text=json.dumps({ "status": "disabled", "reason": "EX_TOOLCALL_LOG_PATH not set", }))] try: lines: list[str] = [] with open(p, "r", encoding="utf-8") as f: for line in f: lines.append(line.rstrip("\n")) tail = lines[-n:] events = [json.loads(x) for x in tail if x.strip()] return [TextContent(type="text", text=json.dumps({ "status": "ok", "count": len(events), "events": events, }, ensure_ascii=False))] except FileNotFoundError: return [TextContent(type="text", text=json.dumps({ "status": "not_found", "path": p, }))] except Exception as e: return [TextContent(type="text", text=json.dumps({ "status": "error", "error": str(e), }))]

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/Zazzles2908/EX_AI-mcp-server'

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