diff --git a/src/basic_memory/mcp/server.py b/src/basic_memory/mcp/server.py index 67352786..2c2d3c8a 100644 --- a/src/basic_memory/mcp/server.py +++ b/src/basic_memory/mcp/server.py @@ -23,17 +23,17 @@ server = Server("basic-memory") # Simple map of tool names to endpoints TOOLS = { # Knowledge endpoints - "create_entities": {"endpoint": "/knowledge/entities/", "method": "post"}, - "search_nodes": {"endpoint": "/knowledge/search/", "method": "post"}, - "open_nodes": {"endpoint": "/knowledge/nodes/", "method": "post"}, - "add_observations": {"endpoint": "/knowledge/observations/", "method": "post"}, - "create_relations": {"endpoint": "/knowledge/relations/", "method": "post"}, - "delete_entities": {"endpoint": "/knowledge/entities/delete/", "method": "post"}, - "delete_observations": {"endpoint": "/knowledge/observations/delete/", "method": "post"}, - "delete_relations": {"endpoint": "/knowledge/relations/delete/", "method": "post"}, + "create_entities": {"endpoint": "/knowledge/entities", "method": "post"}, + "search_nodes": {"endpoint": "/knowledge/search", "method": "post"}, + "open_nodes": {"endpoint": "/knowledge/nodes", "method": "post"}, + "add_observations": {"endpoint": "/knowledge/observations", "method": "post"}, + "create_relations": {"endpoint": "/knowledge/relations", "method": "post"}, + "delete_entities": {"endpoint": "/knowledge/entities/delete", "method": "post"}, + "delete_observations": {"endpoint": "/knowledge/observations/delete", "method": "post"}, + "delete_relations": {"endpoint": "/knowledge/relations/delete", "method": "post"}, # Document endpoints - "create_document": {"endpoint": "/documents/", "method": "post"}, - "list_documents": {"endpoint": "/documents/", "method": "get"}, + "create_document": {"endpoint": "/documents", "method": "post"}, + "list_documents": {"endpoint": "/documents", "method": "get"}, "get_document": {"endpoint": "/documents/{id}", "method": "get"}, "update_document": {"endpoint": "/documents/{id}", "method": "put"}, "delete_document": {"endpoint": "/documents/{id}", "method": "delete"}, @@ -60,23 +60,18 @@ async def handle_call_tool(name: str, arguments: dict): if "{id}" in endpoint: endpoint = endpoint.format(id=arguments.get("id")) - # Ensure non-string arguments are properly JSON serialized - processed_args = {} - for key, value in arguments.items(): - if key == "doc_metadata" and isinstance(value, str): - try: - processed_args[key] = json.loads(value) - except json.JSONDecodeError: - processed_args[key] = None - else: - processed_args[key] = value + # Make request to FastAPI async with AsyncClient( transport=ASGITransport(app=fastapi_app), base_url="http://test" ) as client: - response = await getattr(client, method)(endpoint, json=processed_args) - + logger.info(f"{method} {endpoint} arguments: {arguments}") + response = await getattr(client, method)(endpoint, json=arguments) + + data = response.json() + logger.info(f"Response status:{response.status_code} content: {data} ") + # Return wrapped response return [ EmbeddedResource( @@ -84,7 +79,7 @@ async def handle_call_tool(name: str, arguments: dict): resource=TextResourceContents( uri="basic-memory://response", mimeType="application/json", - text=json.dumps(response.json() if response.content else {"status": "success"}), + text=json.dumps(data), ), ) ] diff --git a/tests/mcp/test_list_tools.py b/tests/mcp/test_list_tools.py index a7827e16..f78d422a 100644 --- a/tests/mcp/test_list_tools.py +++ b/tests/mcp/test_list_tools.py @@ -1,49 +1,49 @@ -# """Tests for the MCP server implementation using FastAPI TestClient.""" -# -# import pytest -# -# from basic_memory.mcp.server import handle_list_tools -# -# -# @pytest.mark.asyncio -# async def test_list_tools(app): -# """Test that server exposes expected tools.""" -# -# tools = await handle_list_tools() -# -# # Check each expected tool is present -# expected_tools = { -# # Knowledge graph tools -# "create_entities", -# "search_nodes", -# "open_nodes", -# "add_observations", -# "create_relations", -# "delete_entities", -# "delete_observations", -# "delete_relations", -# # Document tools -# "create_document", -# "list_documents", -# "get_document", -# "update_document", -# "delete_document", -# } -# -# found_tools = {t.name: t for t in tools} -# assert found_tools.keys() == expected_tools -# -# # Verify schemas include required fields -# search_schema = found_tools["search_nodes"].inputSchema -# assert "query" in search_schema["properties"] -# assert search_schema["required"] == ["query"] -# -# # Verify document tool schemas -# create_doc_schema = found_tools["create_document"].inputSchema -# assert "path" in create_doc_schema["properties"] -# assert "content" in create_doc_schema["properties"] -# assert set(create_doc_schema["required"]) == {"path", "content"} -# -# get_doc_schema = found_tools["get_document"].inputSchema -# assert "id" in get_doc_schema["properties"] -# assert get_doc_schema["required"] == ["id"] +"""Tests for the MCP server implementation using FastAPI TestClient.""" + +import pytest + +from basic_memory.mcp.server import handle_list_tools + + +@pytest.mark.asyncio +async def test_list_tools(app): + """Test that server exposes expected tools.""" + + tools = await handle_list_tools() + + # Check each expected tool is present + expected_tools = { + # Knowledge graph tools + "create_entities", + "search_nodes", + "open_nodes", + "add_observations", + "create_relations", + "delete_entities", + "delete_observations", + "delete_relations", + # Document tools + "create_document", + "list_documents", + "get_document", + "update_document", + "delete_document", + } + + found_tools = {t.name: t for t in tools} + assert found_tools.keys() == expected_tools + + # Verify schemas include required fields + search_schema = found_tools["search_nodes"].inputSchema + assert "query" in search_schema["properties"] + assert search_schema["required"] == ["query"] + + # Verify document tool schemas + create_doc_schema = found_tools["create_document"].inputSchema + assert "path" in create_doc_schema["properties"] + assert "content" in create_doc_schema["properties"] + assert set(create_doc_schema["required"]) == {"path", "content"} + + get_doc_schema = found_tools["get_document"].inputSchema + assert "id" in get_doc_schema["properties"] + assert get_doc_schema["required"] == ["id"]