Skip to content

Commit 53e1067

Browse files
authored
add tests (#15)
1 parent 9f6a906 commit 53e1067

File tree

3 files changed

+794
-0
lines changed

3 files changed

+794
-0
lines changed

tests/community/test_community_tool_context.py

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

372581
if __name__ == "__main__":
373582
pytest.main([__file__, "-v"])

0 commit comments

Comments
 (0)