@@ -368,6 +368,215 @@ def late_tool(value: str):
368368 )
369369 assert "Processed: test" in str (result )
370370
371+ @pytest .mark .asyncio
372+ async def test_custom_context_description (self ):
373+ """Test that custom context description is correctly applied in community FastMCP."""
374+ server = create_community_todo_server ()
375+ custom_description = "Explain why you need to use this tool"
376+ options = MCPCatOptions (
377+ enable_tool_call_context = True ,
378+ custom_context_description = custom_description
379+ )
380+ track (server , "test_project" , options )
381+
382+ async with create_community_test_client (server ) as client :
383+ tools_result = await client .list_tools ()
384+
385+ # Check each tool (except get_more_tools)
386+ for tool in tools_result :
387+ if tool .name == "get_more_tools" :
388+ continue
389+
390+ # Verify context parameter has custom description
391+ context_schema = tool .inputSchema ["properties" ]["context" ]
392+ assert context_schema ["description" ] == custom_description
393+
394+ @pytest .mark .asyncio
395+ async def test_custom_context_description_empty_string (self ):
396+ """Test edge case with empty string custom description in community FastMCP."""
397+ server = create_community_todo_server ()
398+ options = MCPCatOptions (
399+ enable_tool_call_context = True ,
400+ custom_context_description = ""
401+ )
402+ track (server , "test_project" , options )
403+
404+ async with create_community_test_client (server ) as client :
405+ tools_result = await client .list_tools ()
406+
407+ # Find a tool to test
408+ add_todo_tool = next (t for t in tools_result if t .name == "add_todo" )
409+
410+ # Verify context exists with empty description
411+ context_schema = add_todo_tool .inputSchema ["properties" ]["context" ]
412+ assert context_schema ["description" ] == ""
413+ assert context_schema ["type" ] == "string"
414+
415+ @pytest .mark .asyncio
416+ async def test_custom_context_description_special_characters (self ):
417+ """Test custom description with special characters and Unicode in community FastMCP."""
418+ server = create_community_todo_server ()
419+ special_description = "Why use this? 🚀 Include: 'quotes', \" double\" , newlines\n , tabs\t ."
420+ options = MCPCatOptions (
421+ enable_tool_call_context = True ,
422+ custom_context_description = special_description
423+ )
424+ track (server , "test_project" , options )
425+
426+ async with create_community_test_client (server ) as client :
427+ tools_result = await client .list_tools ()
428+
429+ # Verify special characters are preserved
430+ add_todo_tool = next (t for t in tools_result if t .name == "add_todo" )
431+ context_schema = add_todo_tool .inputSchema ["properties" ]["context" ]
432+ assert context_schema ["description" ] == special_description
433+
434+ @pytest .mark .asyncio
435+ async def test_custom_context_description_very_long (self ):
436+ """Test with a very long description string in community FastMCP."""
437+ server = create_community_todo_server ()
438+ # Create a very long description
439+ long_description = "This is a very detailed description for the context. " * 50
440+ options = MCPCatOptions (
441+ enable_tool_call_context = True ,
442+ custom_context_description = long_description
443+ )
444+ track (server , "test_project" , options )
445+
446+ async with create_community_test_client (server ) as client :
447+ tools_result = await client .list_tools ()
448+
449+ # Verify long description is preserved
450+ add_todo_tool = next (t for t in tools_result if t .name == "add_todo" )
451+ context_schema = add_todo_tool .inputSchema ["properties" ]["context" ]
452+ assert context_schema ["description" ] == long_description
453+ assert len (context_schema ["description" ]) > 1000
454+
455+ @pytest .mark .asyncio
456+ async def test_default_context_description (self ):
457+ """Verify the default description is used when not specified in community FastMCP."""
458+ server = create_community_todo_server ()
459+ # Don't specify custom_context_description, should use default
460+ options = MCPCatOptions (enable_tool_call_context = True )
461+ track (server , "test_project" , options )
462+
463+ async with create_community_test_client (server ) as client :
464+ tools_result = await client .list_tools ()
465+
466+ # Check for default description
467+ add_todo_tool = next (t for t in tools_result if t .name == "add_todo" )
468+ context_schema = add_todo_tool .inputSchema ["properties" ]["context" ]
469+ assert context_schema ["description" ] == "Describe why you are calling this tool and how it fits into your overall task"
470+
471+ @pytest .mark .asyncio
472+ async def test_custom_context_description_with_multiple_tools (self ):
473+ """Test that custom description is applied to all tools consistently in community FastMCP."""
474+ if not HAS_COMMUNITY_FASTMCP :
475+ pytest .skip ("Community FastMCP not available" )
476+
477+ from fastmcp import FastMCP
478+
479+ server = FastMCP ("test-server" )
480+
481+ @server .tool
482+ def tool1 (param : str ):
483+ """First tool."""
484+ return f"Tool 1: { param } "
485+
486+ @server .tool
487+ def tool2 (value : int ):
488+ """Second tool."""
489+ return f"Tool 2: { value } "
490+
491+ @server .tool
492+ def tool3 ():
493+ """Third tool with no params."""
494+ return "Tool 3"
495+
496+ custom_desc = "Custom community context for all tools"
497+ options = MCPCatOptions (
498+ enable_tool_call_context = True ,
499+ custom_context_description = custom_desc
500+ )
501+ track (server , "test_project" , options )
502+
503+ async with create_community_test_client (server ) as client :
504+ tools_result = await client .list_tools ()
505+
506+ # All tools should have the same custom context description
507+ for tool in tools_result :
508+ if tool .name in ["tool1" , "tool2" , "tool3" ]:
509+ assert "context" in tool .inputSchema ["properties" ]
510+ assert tool .inputSchema ["properties" ]["context" ]["description" ] == custom_desc
511+
512+ @pytest .mark .asyncio
513+ async def test_custom_context_with_tool_call (self ):
514+ """Test tool calls work correctly with custom context description in community FastMCP."""
515+ server = create_community_todo_server ()
516+ custom_desc = "Provide reasoning for this action in the community server"
517+ options = MCPCatOptions (
518+ enable_tool_call_context = True ,
519+ custom_context_description = custom_desc
520+ )
521+ track (server , "test_project" , options )
522+
523+ async with create_community_test_client (server ) as client :
524+ # Verify the custom description is set
525+ tools_result = await client .list_tools ()
526+ add_todo_tool = next (t for t in tools_result if t .name == "add_todo" )
527+ assert add_todo_tool .inputSchema ["properties" ]["context" ]["description" ] == custom_desc
528+
529+ # Call the tool with context
530+ result = await client .call_tool (
531+ "add_todo" ,
532+ {
533+ "text" : "Test with custom description in community" ,
534+ "context" : "Adding todo to test custom context description in community FastMCP"
535+ }
536+ )
537+
538+ # Should succeed
539+ assert "Added todo" in str (result )
540+
541+ @pytest .mark .asyncio
542+ async def test_custom_context_with_dynamically_added_tool (self ):
543+ """Test that dynamically added tools get custom context description in community FastMCP."""
544+ if not HAS_COMMUNITY_FASTMCP :
545+ pytest .skip ("Community FastMCP not available" )
546+
547+ from fastmcp import FastMCP
548+
549+ server = FastMCP ("test-server" )
550+
551+ # Track with custom context description
552+ custom_desc = "Dynamic tool custom context"
553+ options = MCPCatOptions (
554+ enable_tool_call_context = True ,
555+ custom_context_description = custom_desc
556+ )
557+ track (server , "test_project" , options )
558+
559+ # Add tool AFTER tracking
560+ @server .tool
561+ def dynamic_tool (data : str ):
562+ """Tool added after tracking with custom context."""
563+ return f"Dynamic result: { data } "
564+
565+ async with create_community_test_client (server ) as client :
566+ tools_result = await client .list_tools ()
567+ dynamic_tool_def = next (t for t in tools_result if t .name == "dynamic_tool" )
568+
569+ # Should have context parameter with custom description
570+ assert "context" in dynamic_tool_def .inputSchema ["properties" ]
571+ assert dynamic_tool_def .inputSchema ["properties" ]["context" ]["description" ] == custom_desc
572+
573+ # Test calling it
574+ result = await client .call_tool (
575+ "dynamic_tool" ,
576+ {"data" : "test" , "context" : "Using dynamic tool with custom context" }
577+ )
578+ assert "Dynamic result: test" in str (result )
579+
371580
372581if __name__ == "__main__" :
373582 pytest .main ([__file__ , "-v" ])
0 commit comments