2424import httpx
2525from fastmcp import FastMCP
2626from fastmcp .server .dependencies import get_http_request
27+ from fastmcp .server .middleware import Middleware , MiddlewareContext , CallNext
28+ from fastmcp .server .middleware .logging import LoggingMiddleware
29+ from fastmcp .tools .tool import Tool
2730from starlette .requests import Request
31+ from typing import Sequence
32+ import mcp .types
2833import os
2934import argparse
3035import json
@@ -41,10 +46,6 @@ def get_logger():
4146 logger = configure_logging ("WARNING" )
4247 return logger
4348
44- # Initialize FastMCP server
45- # The name "nps" is how this server will be identified by clients
46- mcp = FastMCP ("nps" )
47-
4849# Constants for the National Park Service API
4950NPS_API_BASE = "https://developer.nps.gov/api/v1"
5051USER_AGENT = "nps-mcp-server/1.0 (contact@example.com)"
@@ -107,6 +108,28 @@ def get_api_key() -> str:
107108 return "DEMO_KEY" # NPS allows limited use with DEMO_KEY
108109 return api_key
109110
111+ class ListToolsLoggerMiddleware (Middleware ):
112+ """Custom middleware to log when list-tools is called."""
113+
114+ async def on_list_tools (
115+ self ,
116+ context : MiddlewareContext [mcp .types .ListToolsRequest ],
117+ call_next : CallNext [mcp .types .ListToolsRequest , Sequence [Tool ]],
118+ ) -> Sequence [Tool ]:
119+ # Log before processing
120+ get_logger ().debug (f"list-tools called at { context .timestamp } (method: { context .method } )" )
121+
122+ # Call the next middleware or core handler
123+ tools = await call_next (context )
124+
125+ # Log after processing
126+ get_logger ().debug (f"list-tools returned { len (tools )} tools" )
127+ return tools
128+
129+ # Initialize FastMCP server
130+ # The name "nps" is how this server will be identified by clients
131+ mcp = FastMCP (name = "nps" , middleware = [LoggingMiddleware (logger = get_logger ()), ListToolsLoggerMiddleware ()])
132+
110133@mcp .tool ()
111134async def search_parks (
112135 state_code : Optional [str ] = None ,
0 commit comments