Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/daniel_lightrag_mcp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@
"RelationInfo",
"GraphResponse",
"LabelsResponse",
"EntitySearchResult",
"EntitySearchResponse",
"EntityExistsResponse",
"EntityUpdateResponse",
"RelationUpdateResponse",
Expand Down
12 changes: 11 additions & 1 deletion src/daniel_lightrag_mcp/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
DeleteDocByIdResponse, ClearDocumentsResponse, PipelineStatusResponse, TrackStatusResponse,
StatusCountsResponse, ClearCacheResponse, DeletionResult, QueryResponse, GraphResponse,
LabelsResponse, EntityExistsResponse, EntityUpdateResponse, RelationUpdateResponse,
HealthResponse, TextDocument
HealthResponse, TextDocument, EntitySearchResponse, EntitySearchResult
)


Expand Down Expand Up @@ -429,6 +429,16 @@ async def get_graph_labels(self) -> LabelsResponse:
response_data = {"labels": response_data}
return LabelsResponse(**response_data)

async def search_entity_labels(self, queries: List[str], limit: int = 10) -> EntitySearchResponse:
"""Search for entity labels matching one or more query strings."""
results = []
for query in queries:
params = {"q": query, "limit": min(limit, 100)}
response_data = await self._make_request("GET", "/graph/label/search", params=params)
matches = response_data if isinstance(response_data, list) else []
results.append(EntitySearchResult(query=query, matches=matches))
return EntitySearchResponse(results=results)

async def check_entity_exists(self, entity_name: str) -> EntityExistsResponse:
"""Check if an entity exists in the knowledge graph."""
params = {"name": entity_name}
Expand Down
11 changes: 11 additions & 0 deletions src/daniel_lightrag_mcp/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,17 @@ class LabelsResponse(BaseModel):
relation_labels: List[str] = Field(default_factory=list)


class EntitySearchResult(BaseModel):
"""Search results for a single query string."""
query: str = Field(..., description="The search query")
matches: List[str] = Field(default_factory=list, description="Matching entity labels")


class EntitySearchResponse(BaseModel):
"""Response model for entity label search (batch)."""
results: List[EntitySearchResult] = Field(default_factory=list)


class EntityExistsResponse(BaseModel):
"""Response model for entity existence check."""
exists: bool = Field(..., description="Whether entity exists")
Expand Down
28 changes: 28 additions & 0 deletions src/daniel_lightrag_mcp/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,26 @@ async def handle_list_tools() -> List[Tool]:#ListToolsResult:
"required": []
}
),
Tool(
name="search_entity_labels",
description="Fuzzy-search entity labels in the knowledge graph. Accepts one or more query strings and returns matching entity names per query. Useful for checking whether a concept is indexed before querying, and for finding the canonical form of an entity name.",
inputSchema={
"type": "object",
"properties": {
"queries": {
"type": "array",
"items": {"type": "string"},
"description": "One or more search terms"
},
"limit": {
"type": "integer",
"description": "Max results per query (default 10, max 100)",
"default": 10
}
},
"required": ["queries"]
}
),
Tool(
name="check_entity_exists",
description="Check if an entity exists in the knowledge graph",
Expand Down Expand Up @@ -1541,6 +1561,14 @@ async def handle_call_tool(self, request: CallToolRequest) -> dict:
logger.error(f" - Full traceback: {traceback.format_exc()}")
raise

elif tool_name == "search_entity_labels":
queries = arguments.get("queries", [])
limit = arguments.get("limit", 10)
if not queries:
raise LightRAGValidationError("queries must be a non-empty list")
result = await lightrag_client.search_entity_labels(queries=queries, limit=limit)
return _create_success_response(result, tool_name)

elif tool_name == "check_entity_exists":
logger.info("EXECUTING CHECK_ENTITY_EXISTS TOOL:")
logger.info(f" - Tool: {tool_name}")
Expand Down