1919
2020# Create cache with appropriate settings for the use case
2121tool_cache = Cache (
22- maxsize = 10000 , # Max 10000 unique requests (fits about 2000 tasks)
23- ttl = CACHE_TTL_HOURS * 60 * 60 , # 48 hours TTL by default (but each item will have some slight variation)
24- enable_stats = True # Track cache performance
22+ maxsize = 10000 , # Max 10000 unique requests (fits about 2000 tasks)
23+ ttl = CACHE_TTL_HOURS
24+ * 60
25+ * 60 , # 48 hours TTL by default (but each item will have some slight variation)
26+ enable_stats = True , # Track cache performance
2527)
2628
2729# Tool name mappings - maps old invalid names to correct names
@@ -126,40 +128,45 @@ def should_cache_tool(tool_name: str) -> bool:
126128 server_name = tool_name .split ("_" , 1 )[0 ]
127129 return server_name in CACHEABLE_SERVERS
128130
131+
129132def generate_cache_key (tool_name : str , tool_args : dict ) -> str :
130133 """Generate consistent cache key from tool call parameters."""
131- cache_data = {
132- "tool_name" : tool_name ,
133- "tool_args" : tool_args
134- }
134+ cache_data = {"tool_name" : tool_name , "tool_args" : tool_args }
135135 cache_str = json .dumps (cache_data , sort_keys = True )
136136 return hashlib .md5 (cache_str .encode ()).hexdigest ()
137137
138+
138139@app .post ("/call-tool" )
139140async def call_tool (
140141 request : CallToolRequest ,
141142) -> list [mcp .types .ContentBlock ]:
142143 """Call a specific tool with the provided arguments."""
143-
144+
144145 mapped_tool_name = TOOL_NAME_MAPPINGS .get (request .tool_name , request .tool_name )
145-
146+
146147 # Generate cache key
147148 cache_key = generate_cache_key (mapped_tool_name , request .tool_args )
148-
149+
149150 # Check cache first
150151 cached_result = tool_cache .get (cache_key )
151- if cached_result is not None and request .use_cache and should_cache_tool (mapped_tool_name ):
152+ if (
153+ cached_result is not None
154+ and request .use_cache
155+ and should_cache_tool (mapped_tool_name )
156+ ):
152157 logger .info (f"Returning cached result for tool '{ request .tool_name } '" )
153158 return cached_result
154-
159+
155160 async with client :
156161 try :
157162 result = await client .call_tool (mapped_tool_name , request .tool_args )
158163
159164 # Check for errors first (FastMCP best practice)
160165 if result .is_error :
161166 error_msg = "Unknown error"
162- if result .content and isinstance (result .content [0 ], mcp .types .TextContent ):
167+ if result .content and isinstance (
168+ result .content [0 ], mcp .types .TextContent
169+ ):
163170 error_msg = result .content [0 ].text
164171 raise HTTPException (
165172 status_code = 500 ,
@@ -172,24 +179,26 @@ async def call_tool(
172179 # TTL is 70-100% of default TTL, to avoid all items expiring at the same time
173180 random_ttl = int (CACHE_TTL_HOURS * 60 * 60 * random .uniform (0.7 , 1.0 ))
174181 tool_cache .set (cache_key , content_blocks , ttl = random_ttl )
175-
182+
176183 return content_blocks
177-
184+
178185 except Exception as e :
179186 raise HTTPException (
180187 status_code = 500 ,
181188 detail = f"Failed to call tool '{ request .tool_name } ': { str (e )} " ,
182189 )
183190
191+
184192@app .get ("/cache-stats" )
185193async def get_cache_stats ():
186194 """Get cache statistics for monitoring."""
187195 return {
188196 "cache_size" : len (tool_cache ),
189197 "max_size" : tool_cache .maxsize ,
190- "ttl_seconds" : tool_cache .ttl
198+ "ttl_seconds" : tool_cache .ttl ,
191199 }
192200
201+
193202@app .post ("/cache-clear" )
194203async def clear_cache ():
195204 """Clear the entire cache."""
@@ -201,7 +210,7 @@ async def clear_cache():
201210async def get_enabled_servers () -> dict [str , Any ]:
202211 """Get list of configured MCP servers with their status (OK or ERROR_NOT_ONLINE)."""
203212 configured = set (config .get ("mcpServers" , {}).keys ())
204-
213+
205214 async with client :
206215 try :
207216 tools = await client .list_tools ()
@@ -211,18 +220,18 @@ async def get_enabled_servers() -> dict[str, Any]:
211220 if "_" in tool .name :
212221 server_name = tool .name .split ("_" , 1 )[0 ]
213222 live_servers .add (server_name )
214-
223+
215224 # Build status list for each configured server
216225 servers = [
217226 (name , "OK" if name in live_servers else "ERROR_NOT_ONLINE" )
218227 for name in sorted (configured )
219228 ]
220-
229+
221230 return {
222231 "servers" : servers ,
223232 "total" : len (configured ),
224233 "online" : len (live_servers ),
225- "offline" : len (configured - live_servers )
234+ "offline" : len (configured - live_servers ),
226235 }
227236 except Exception as e :
228237 raise HTTPException (
@@ -234,6 +243,7 @@ async def get_enabled_servers() -> dict[str, Any]:
234243async def health () -> dict [str , Any ]:
235244 """Simple health check that verifies client is also ok. Timeout is 5 seconds."""
236245 try :
246+
237247 async def _health_check_with_client ():
238248 async with client :
239249 return {
0 commit comments