delete old mcp tests, add docs to tools

This commit is contained in:
phernandez
2024-12-25 14:28:35 -06:00
parent bb47fbd48b
commit 141bcd85b8
11 changed files with 195 additions and 730 deletions
+195 -28
View File
@@ -1,7 +1,7 @@
"""Basic Memory MCP server using fastmcp - proxies to FastAPI endpoints."""
import sys
from typing import Any, List
from typing import Any, List, Optional, Dict
from fastmcp import FastMCP
from loguru import logger
@@ -54,8 +54,24 @@ async def log_api_call(method: str, url: str, data: Any, response: Any):
@mcp.tool()
async def create_entities(entities: list[dict]) -> dict:
"""Create new entities in the knowledge graph."""
async def create_entities(entities: List[dict]) -> dict:
"""Create new entities in the knowledge graph.
Args:
entities: List of entity dictionaries, each containing:
- name: Entity name
- entity_type: Classification (e.g., 'component', 'specification')
- description: Optional description
- observations: Optional list of initial observations
Example:
create_entities([{
"name": "Knowledge Format",
"entity_type": "specification",
"description": "Document format specification",
"observations": ["Uses markdown format", "Supports YAML frontmatter"]
}])
"""
url = "/knowledge/entities"
data = {"entities": entities}
response = await client.post(url, json=data)
@@ -63,8 +79,24 @@ async def create_entities(entities: list[dict]) -> dict:
@mcp.tool()
async def create_relations(relations: list[dict]) -> dict:
"""Create relations between entities."""
async def create_relations(relations: List[dict]) -> dict:
"""Create relations between existing entities.
Args:
relations: List of relation dictionaries, each containing:
- from_id: Source entity path_id
- to_id: Target entity path_id
- relation_type: Type of relationship in active voice
- context: Optional context for the relation
Example:
create_relations([{
"from_id": "test/parser_test",
"to_id": "component/parser",
"relation_type": "validates",
"context": "Unit test coverage"
}])
"""
url = "/knowledge/relations"
data = {"relations": relations}
response = await client.post(url, json=data)
@@ -72,10 +104,32 @@ async def create_relations(relations: list[dict]) -> dict:
@mcp.tool()
async def add_observations(path_id: str, observations: list[str]) -> dict:
"""Add observations to an entity."""
async def add_observations(path_id: str, observations: List[dict], context: Optional[str] = None) -> dict:
"""Add observations to an entity.
Args:
path_id: Entity path ID
observations: List of observations, each containing:
- content: The observation text
- category: Optional category ('tech', 'design', 'feature', 'note', 'issue', 'todo')
context: Optional shared context for all observations
Example:
add_observations(
"specification/knowledge_format",
observations=[
{"content": "Uses markdown format", "category": "tech"},
{"content": "Designed for readability", "category": "design"}
],
context="Initial design"
)
"""
url = "/knowledge/observations"
data = {"path_id": path_id, "observations": observations}
data = {
"path_id": path_id,
"observations": observations,
"context": context
}
response = await client.post(url, json=data)
await log_api_call("POST", url, data, response)
return response.json()
@@ -86,24 +140,59 @@ async def add_observations(path_id: str, observations: list[str]) -> dict:
@mcp.tool()
async def get_entity(path_id: str) -> dict:
"""Get a specific entity by path_id."""
"""Get a specific entity by its path_id.
Args:
path_id: Entity path ID (e.g., 'component/memory_service')
Returns:
Complete entity information including observations and relations.
Example:
get_entity("specification/knowledge_format")
"""
url = f"/knowledge/entities/{path_id}"
response = await client.get(url)
return response.json()
@mcp.tool()
async def search_nodes(query: str) -> dict:
"""Search for entities in the knowledge graph."""
async def search_nodes(query: str, category: Optional[str] = None) -> dict:
"""Search for entities in the knowledge graph.
Args:
query: Search text to match against entities
category: Optional category to filter observations by
Returns:
Matching entities with their observations and relations.
Example:
search_nodes("markdown format", category="tech") # Find tech observations about markdown
search_nodes("implementation") # Search all categories
"""
url = "/knowledge/search"
data = {"query": query}
data = {"query": query, "category": category}
response = await client.post(url, json=data)
return response.json()
@mcp.tool()
async def open_nodes(path_ids: List[str]) -> dict:
"""Search for entities in the knowledge graph."""
"""Load multiple entities by their path_ids.
Args:
path_ids: List of entity path IDs to load
Returns:
Dictionary of loaded entities with their observations and relations.
Example:
open_nodes([
"specification/knowledge_format",
"component/parser"
])
"""
url = "/knowledge/nodes"
data = {"path_ids": path_ids}
response = await client.post(url, json=data)
@@ -115,7 +204,14 @@ async def open_nodes(path_ids: List[str]) -> dict:
@mcp.tool()
async def delete_entities(path_ids: List[str]) -> dict:
"""Search for entities in the knowledge graph."""
"""Delete entities from the knowledge graph.
Args:
path_ids: List of entity path IDs to delete
Example:
delete_entities(["test/obsolete_test", "component/old_component"])
"""
url = "/knowledge/entities/delete"
data = {"path_ids": path_ids}
response = await client.post(url, json=data)
@@ -123,8 +219,19 @@ async def delete_entities(path_ids: List[str]) -> dict:
@mcp.tool()
async def delete_observations(path_id: str, observations: list[str]) -> dict:
"""Delete observations from an entity."""
async def delete_observations(path_id: str, observations: List[str]) -> dict:
"""Delete specific observations from an entity.
Args:
path_id: Entity path ID
observations: List of observation content strings to delete
Example:
delete_observations(
"component/parser",
["Obsolete implementation detail", "Old design note"]
)
"""
url = "/knowledge/observations/delete"
data = {
"path_id": path_id,
@@ -132,18 +239,32 @@ async def delete_observations(path_id: str, observations: list[str]) -> dict:
}
response = await client.post(
url, json=data
)
)
return response.json()
@mcp.tool()
async def delete_relations(relations: list[dict]) -> dict:
"""Delete relations between entities."""
async def delete_relations(relations: List[dict]) -> dict:
"""Delete relations between entities.
Args:
relations: List of relation dictionaries to delete, each containing:
- from_id: Source entity path_id
- to_id: Target entity path_id
- relation_type: Type of relationship
Example:
delete_relations([{
"from_id": "test/old_test",
"to_id": "component/parser",
"relation_type": "validates"
}])
"""
url = "/knowledge/relations/delete"
data = {"relations": relations}
response = await client.post(
url, json=data
)
)
return response.json()
@@ -151,8 +272,21 @@ async def delete_relations(relations: list[dict]) -> dict:
@mcp.tool()
async def create_document(path: str, content: str, metadata: dict = None) -> dict:
"""Create a new document."""
async def create_document(path: str, content: str, metadata: Optional[Dict] = None) -> dict:
"""Create a new document.
Args:
path: Document path (must end in .md)
content: Document content as markdown text
metadata: Optional metadata dictionary
Example:
create_document(
"docs/format.md",
"# Format Specification\n\nDetails here...",
metadata={"author": "AI team"}
)
"""
url = "/documents/create"
data = {"path": path, "content": content, "metadata": metadata}
response = await client.post(url, json=data)
@@ -161,15 +295,35 @@ async def create_document(path: str, content: str, metadata: dict = None) -> dic
@mcp.tool()
async def get_document(path: str) -> dict:
"""Get a document by path_id."""
"""Get a document by its path.
Args:
path: Document path to retrieve
Example:
get_document("docs/format.md")
"""
url = f"/documents/{path}"
response = await client.get(url)
return response.json()
@mcp.tool()
async def update_document(path: str, content: str, metadata: dict = None) -> dict:
"""Update an existing document."""
async def update_document(path: str, content: str, metadata: Optional[Dict] = None) -> dict:
"""Update an existing document.
Args:
path: Document path
content: New document content
metadata: Optional new metadata
Example:
update_document(
"docs/format.md",
"# Updated Format\n\nNew content...",
metadata={"updated_by": "AI team"}
)
"""
url = f"/documents/{path}"
data = {"path": path, "content": content, "metadata": metadata}
response = await client.put(url, json=data)
@@ -178,7 +332,14 @@ async def update_document(path: str, content: str, metadata: dict = None) -> dic
@mcp.tool()
async def list_documents() -> list:
"""List all documents."""
"""List all documents in the system.
Returns:
List of document paths and metadata.
Example:
list_documents() # Get all document paths
"""
url = "/documents/list"
response = await client.get(url)
return response.json()
@@ -186,13 +347,19 @@ async def list_documents() -> list:
@mcp.tool()
async def delete_document(path: str) -> dict:
"""Delete an existing document."""
"""Delete a document.
Args:
path: Path of document to delete
Example:
delete_document("docs/obsolete.md")
"""
url = f"/documents/{path}"
response = await client.delete(url)
if response.status_code == 204:
return {"deleted": True}
if __name__ == "__main__":
setup_logging()
logger.info("Starting Basic Memory MCP server")