16
16
17
17
logger = logging .getLogger (__name__ )
18
18
19
- FULL_TOOL_NAME_MAX_LENGTH = 55
20
-
21
19
22
20
class FastApiMCP :
23
21
def __init__ (
@@ -40,6 +38,7 @@ def __init__(
40
38
exclude_operations : Optional [List [str ]] = None ,
41
39
include_tags : Optional [List [str ]] = None ,
42
40
exclude_tags : Optional [List [str ]] = None ,
41
+ max_tool_name_length : Optional [int ] = None ,
43
42
):
44
43
"""
45
44
Create an MCP server from a FastAPI app.
@@ -54,6 +53,8 @@ def __init__(
54
53
exclude_operations: List of operation IDs to exclude from MCP tools. Cannot be used with include_operations.
55
54
include_tags: List of tags to include as MCP tools. Cannot be used with exclude_tags.
56
55
exclude_tags: List of tags to exclude from MCP tools. Cannot be used with include_tags.
56
+ max_tool_name_length: Maximum length allowed for tools (some vendors prohibit long names).
57
+ Tools breaching this restriction will be filtered out.
57
58
"""
58
59
# Validate operation and tag filtering options
59
60
if include_operations is not None and exclude_operations is not None :
@@ -77,6 +78,7 @@ def __init__(
77
78
self ._exclude_operations = exclude_operations
78
79
self ._include_tags = include_tags
79
80
self ._exclude_tags = exclude_tags
81
+ self ._max_tool_name_length = max_tool_name_length
80
82
81
83
self ._http_client = http_client or httpx .AsyncClient (
82
84
transport = httpx .ASGITransport (app = self .fastapi , raise_app_exceptions = False ),
@@ -322,6 +324,7 @@ def _filter_tools(self, tools: List[types.Tool], openapi_schema: Dict[str, Any])
322
324
and self ._exclude_operations is None
323
325
and self ._include_tags is None
324
326
and self ._exclude_tags is None
327
+ and self ._max_tool_name_length is None
325
328
):
326
329
return tools
327
330
@@ -339,23 +342,6 @@ def _filter_tools(self, tools: List[types.Tool], openapi_schema: Dict[str, Any])
339
342
)
340
343
continue
341
344
342
- operation_full_name = self .get_tool_full_name (operation_id )
343
- if len (operation_full_name ) > FULL_TOOL_NAME_MAX_LENGTH :
344
- logger .warning (f"Skipping operation with exceedingly long operationId: { operation_full_name } " )
345
- continue
346
-
347
- """
348
- if method not in ["get", "post", "put", "delete", "patch"]:
349
- logger.warning(f"Skipping non-HTTP method: {method.upper()} {path}")
350
- continue
351
-
352
- # Get operation metadata
353
- operation_id = operation.get("operationId")
354
- if not operation_id:
355
- logger.warning(f"Skipping operation with no operationId: {method.upper()} {path}, details: {operation}")
356
- continue
357
- """
358
-
359
345
tags = operation .get ("tags" , [])
360
346
for tag in tags :
361
347
if tag not in operations_by_tag :
@@ -364,11 +350,14 @@ def _filter_tools(self, tools: List[types.Tool], openapi_schema: Dict[str, Any])
364
350
365
351
operations_to_include = set ()
366
352
353
+ all_operations = {tool .name for tool in tools }
354
+
367
355
if self ._include_operations is not None :
368
356
operations_to_include .update (self ._include_operations )
369
357
elif self ._exclude_operations is not None :
370
- all_operations = {tool .name for tool in tools }
371
358
operations_to_include .update (all_operations - set (self ._exclude_operations ))
359
+ elif self ._max_tool_name_length is not None :
360
+ operations_to_include .update (all_operations ) # all_operations
372
361
373
362
if self ._include_tags is not None :
374
363
for tag in self ._include_tags :
@@ -378,9 +367,14 @@ def _filter_tools(self, tools: List[types.Tool], openapi_schema: Dict[str, Any])
378
367
for tag in self ._exclude_tags :
379
368
excluded_operations .update (operations_by_tag .get (tag , []))
380
369
381
- all_operations = {tool .name for tool in tools }
382
370
operations_to_include .update (all_operations - excluded_operations )
383
371
372
+ if self ._max_tool_name_length is not None :
373
+ long_operations = {
374
+ tool .name for tool in tools if len (self .get_combined_full_name (tool .name )) > self ._max_tool_name_length
375
+ }
376
+ operations_to_include = operations_to_include - long_operations
377
+
384
378
filtered_tools = [tool for tool in tools if tool .name in operations_to_include ]
385
379
386
380
if filtered_tools :
@@ -391,5 +385,17 @@ def _filter_tools(self, tools: List[types.Tool], openapi_schema: Dict[str, Any])
391
385
392
386
return filtered_tools
393
387
394
- def get_tool_full_name (self , operation_id : str ) -> str :
388
+ def get_combined_full_name (self , operation_id : str ) -> str :
389
+ """
390
+ Combined name consists of server name + operation_id
391
+
392
+ Args:
393
+ operation_id: As defined during creation
394
+
395
+ Returns:
396
+ concatenated string of server name + operation_id
397
+ """
398
+ if not self .name :
399
+ return operation_id
400
+
395
401
return f"{ self .name } \\ { operation_id } "
0 commit comments