from mcp.types import ToolAnnotations import pytest from artemis.mcp.tool_server import ArtemisFastMCP @pytest.mark.asyncio @pytest.mark.parametrize("registration", ["decorator", "add_tool"]) @pytest.mark.parametrize( ("docstring", "expected"), [ ("Summary.\n\n Details.\n Nested.\n ", "Summary.\n\nDetails.\n Nested.\n"), ("Summary.\n\nDetails.\n Nested.\n", "Summary.\n\nDetails.\n Nested.\n"), ("One line.", "One line."), ], ) async def test_tool_descriptions_match_across_docstring_formats(registration, docstring, expected): server = ArtemisFastMCP("description-test") def probe(count: int = 1) -> str: return str(count) probe.__doc__ = docstring if registration == "decorator": assert server.tool()(probe) is probe else: server.add_tool(probe) (tool,) = await server.list_tools() assert tool.description == expected assert tool.inputSchema["properties"]["count"]["type"] == "integer" assert probe.__doc__ == docstring @pytest.mark.asyncio async def test_explicit_tool_metadata_is_preserved(): server = ArtemisFastMCP("description-test") def probe() -> str: """The fallback docstring.""" return "ok" description = "Explicit description.\n Keep this indentation.\n" server.add_tool( probe, "renamed_probe", "Probe title", description, annotations=ToolAnnotations(readOnlyHint=True), meta={"source": "test"}, structured_output=False, ) (tool,) = await server.list_tools() assert tool.name == "renamed_probe" assert tool.title == "Probe title" assert tool.description == description assert tool.annotations.readOnlyHint is True assert tool.meta == {"source": "test"}