diff --git a/src/daniel_lightrag_mcp/__init__.py b/src/daniel_lightrag_mcp/__init__.py index a7d0e39..d3401d4 100644 --- a/src/daniel_lightrag_mcp/__init__.py +++ b/src/daniel_lightrag_mcp/__init__.py @@ -56,6 +56,7 @@ "RelationInfo", "GraphResponse", "LabelsResponse", + "PopularEntitiesResponse", "EntityExistsResponse", "EntityUpdateResponse", "RelationUpdateResponse", diff --git a/src/daniel_lightrag_mcp/client.py b/src/daniel_lightrag_mcp/client.py index 46b561c..a11960f 100644 --- a/src/daniel_lightrag_mcp/client.py +++ b/src/daniel_lightrag_mcp/client.py @@ -17,7 +17,7 @@ DeleteDocByIdResponse, ClearDocumentsResponse, PipelineStatusResponse, TrackStatusResponse, StatusCountsResponse, ClearCacheResponse, DeletionResult, QueryResponse, GraphResponse, LabelsResponse, EntityExistsResponse, EntityUpdateResponse, RelationUpdateResponse, - HealthResponse, TextDocument + HealthResponse, TextDocument, PopularEntitiesResponse ) @@ -429,6 +429,13 @@ async def get_graph_labels(self) -> LabelsResponse: response_data = {"labels": response_data} return LabelsResponse(**response_data) + async def get_popular_entities(self, limit: int = 50) -> PopularEntitiesResponse: + """Get the most-connected entities in the knowledge graph, sorted by degree.""" + params = {"limit": min(limit, 1000)} + response_data = await self._make_request("GET", "/graph/label/popular", params=params) + entities = response_data if isinstance(response_data, list) else [] + return PopularEntitiesResponse(entities=entities, limit=limit) + async def check_entity_exists(self, entity_name: str) -> EntityExistsResponse: """Check if an entity exists in the knowledge graph.""" params = {"name": entity_name} diff --git a/src/daniel_lightrag_mcp/models.py b/src/daniel_lightrag_mcp/models.py index 20ba949..d9375a3 100644 --- a/src/daniel_lightrag_mcp/models.py +++ b/src/daniel_lightrag_mcp/models.py @@ -315,6 +315,12 @@ class LabelsResponse(BaseModel): relation_labels: List[str] = Field(default_factory=list) +class PopularEntitiesResponse(BaseModel): + """Response model for popular (high-degree) entities.""" + entities: List[str] = Field(default_factory=list, description="Entity names sorted by degree descending") + limit: int = Field(..., description="The limit applied to this result") + + class EntityExistsResponse(BaseModel): """Response model for entity existence check.""" exists: bool = Field(..., description="Whether entity exists") diff --git a/src/daniel_lightrag_mcp/server.py b/src/daniel_lightrag_mcp/server.py index e9da2bf..821f382 100644 --- a/src/daniel_lightrag_mcp/server.py +++ b/src/daniel_lightrag_mcp/server.py @@ -493,6 +493,21 @@ async def handle_list_tools() -> List[Tool]:#ListToolsResult: "required": [] } ), + Tool( + name="get_popular_entities", + description="Get the most-connected entities in the knowledge graph, sorted by degree (relation count) descending. Useful for session-start orientation, query anchor selection, and post-batch auditing.", + inputSchema={ + "type": "object", + "properties": { + "limit": { + "type": "integer", + "description": "Maximum number of entities to return (default 50, max 1000)", + "default": 50 + } + }, + "required": [] + } + ), Tool( name="check_entity_exists", description="Check if an entity exists in the knowledge graph", @@ -1541,6 +1556,11 @@ async def handle_call_tool(self, request: CallToolRequest) -> dict: logger.error(f" - Full traceback: {traceback.format_exc()}") raise + elif tool_name == "get_popular_entities": + limit = arguments.get("limit", 50) + result = await lightrag_client.get_popular_entities(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}")