UNPKG

@mseep/atlas-mcp-server

Version:

A Model Context Protocol (MCP) server for ATLAS, a Neo4j-powered task management system for LLM Agents - implementing a three-tier architecture (Projects, Tasks, Knowledge) to manage complex workflows.

228 lines (223 loc) 11 kB
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; import { ResponseFormat, createResponseFormatEnum, createToolResponse } from "../../../types/mcp.js"; import { createToolExample, createToolMetadata, registerTool } from "../../../types/tool.js"; import { formatUnifiedSearchResponse } from "./responseFormat.js"; import { UnifiedSearchRequestInput } from "./types.js"; // Corrected type import import { atlasUnifiedSearch } from "./unifiedSearch.js"; export const registerAtlasUnifiedSearchTool = (server: McpServer) => { registerTool( server, "atlas_unified_search", "Performs a unified search across specified entity types (node labels) with relevance scoring and flexible filtering options", // Updated description { property: z.string().optional().describe( "Specific property to search within (e.g., name, description, text)" ), value: z.string().describe( "Search term or phrase to find across the knowledge base (required)" ), entityTypes: z.array( z.string() // Allow any string label ).optional().describe( "Array of entity types (node labels) to include in search (Default: project, task, knowledge if omitted)" // Updated description ), caseInsensitive: z.boolean().optional().default(true).describe( "Boolean flag to ignore case sensitivity when searching for better recall (Default: true)" ), fuzzy: z.boolean().optional().default(false).describe( "Boolean flag to enable approximate matching for typos, spelling variations, and similar terms (Default: false)" ), taskType: z.string().optional().describe( "Optional filter by project/task classification type for more targeted results (applies only if searching Project or Task types)" // Clarified description ), page: z.number().optional().describe( "Page number for paginated results (Default: 1)" ), limit: z.number().optional().describe( "Number of results per page, maximum 100 (Default: 20)" ), responseFormat: createResponseFormatEnum().optional().default(ResponseFormat.FORMATTED).describe( "Desired response format: 'formatted' (default string) or 'json' (raw object)" ), }, async (input, context) => { // Process unified search request const validatedInput = input as unknown as UnifiedSearchRequestInput & { responseFormat?: ResponseFormat }; // Provide default entityTypes if not specified const searchInputWithDefaults = { ...validatedInput, entityTypes: validatedInput.entityTypes && validatedInput.entityTypes.length > 0 ? validatedInput.entityTypes : ['project', 'task', 'knowledge'] // Default if empty or undefined }; const result = await atlasUnifiedSearch(searchInputWithDefaults, context); // Conditionally format response if (validatedInput.responseFormat === ResponseFormat.JSON) { return createToolResponse(JSON.stringify(result, null, 2)); } else { // Return the result using the formatter for rich display return formatUnifiedSearchResponse(result, false); } }, createToolMetadata({ examples: [ createToolExample( { value: "authentication", entityTypes: ["project", "task"], // Example still uses specific types fuzzy: true }, `{ "results": [ { "id": "task_auth123", "type": "task", // Example still uses specific types "entityType": "implementation", "title": "Implement OAuth Authentication", "description": "Create secure authentication system using OAuth 2.0 protocol", "matchedProperty": "title", "matchedValue": "Implement OAuth Authentication", "createdAt": "2025-03-15T10:22:44.123Z", "updatedAt": "2025-03-15T10:22:44.123Z", "projectId": "proj_backend42", "projectName": "API Platform Modernization", "score": 9.5 }, { "id": "proj_auth456", "type": "project", // Example still uses specific types "entityType": "security", "title": "Authentication Microservice", "description": "Build standalone authentication microservice with JWT, refresh tokens and multi-factor support", "matchedProperty": "name", "matchedValue": "Authentication Microservice", "createdAt": "2025-03-10T08:30:12.456Z", "updatedAt": "2025-03-10T08:30:12.456Z", "score": 10 } // ... potentially other types if they match ], "total": 2, // Example total might change if other types match "page": 1, "limit": 20, "totalPages": 1 }`, "Search for authentication-related projects and tasks with fuzzy matching" ), createToolExample( { value: "performance", property: "description", entityTypes: ["knowledge"] // Example still uses specific types }, `{ "results": [ { "id": "know_perf123", "type": "knowledge", // Example still uses specific types "entityType": "technical", "title": "React Performance Optimiz...", "description": "Techniques for optimizing React component performance including memoization, virtualization, and code splitting", "matchedProperty": "text", "matchedValue": "Techniques for optimizing React component performance including memoization, virtualization, and code splitting", "createdAt": "2025-03-18T14:05:33.789Z", "updatedAt": "2025-03-18T14:05:33.789Z", "projectId": "proj_frontend42", "projectName": "Frontend Modernization", "score": 8.2 } // ... potentially other types if they match ], "total": 1, // Example total might change if other types match "page": 1, "limit": 20, "totalPages": 1 }`, "Search knowledge items containing 'performance' in the description" ), createToolExample( { value: "api" // No entityTypes specified, defaults to project, task, knowledge }, `{ "results": [ { "id": "proj_api789", "type": "project", // Example still uses specific types "entityType": "integration", "title": "API Gateway Implementation", "description": "Create centralized API gateway for service integration with rate limiting, monitoring and authentication", "matchedProperty": "name", "matchedValue": "API Gateway Implementation", "createdAt": "2025-03-01T09:45:22.321Z", "updatedAt": "2025-03-05T15:12:44.456Z", "score": 10 }, { "id": "task_api456", "type": "task", // Example still uses specific types "entityType": "development", "title": "Document REST API Endpoints", "description": "Create comprehensive documentation for all REST API endpoints using OpenAPI specification", "matchedProperty": "title", "matchedValue": "Document REST API Endpoints", "createdAt": "2025-03-08T11:20:15.654Z", "updatedAt": "2025-03-08T11:20:15.654Z", "projectId": "proj_api789", "projectName": "API Gateway Implementation", "score": 9.8 }, { "id": "know_api321", "type": "knowledge", // Example still uses specific types "entityType": "technical", "title": "API Design Best Practices...", "description": "Best practices for RESTful API design including versioning, error handling, and resource naming conventions", "matchedProperty": "text", "matchedValue": "Best practices for RESTful API design including versioning, error handling, and resource naming conventions", "createdAt": "2025-03-12T16:30:45.987Z", "updatedAt": "2025-03-12T16:30:45.987Z", "projectId": "proj_api789", "projectName": "API Gateway Implementation", "score": 8.5 } // ... potentially other types if they match ], "total": 8, // Example total might change if other types match "page": 1, "limit": 10, "totalPages": 1 }`, "Search for 'api' across default entity types (project, task, knowledge) with pagination" ) ], requiredPermission: "search:read", returnSchema: z.object({ results: z.array(z.object({ id: z.string().describe("Unique identifier"), type: z.string().describe("Entity type (node label)"), // Allow any string entityType: z.string().optional().describe("Specific classification of the entity (e.g., taskType, domain)"), // Made optional as it might not apply to all types title: z.string().describe("Entity title or name (might be generated for some types)"), description: z.string().optional().describe("Entity description text (might be primary text for some types)"), // Made optional matchedProperty: z.string().describe("Property where the match was found"), matchedValue: z.string().describe("Value containing the match (potentially truncated)"), createdAt: z.string().optional().describe("Creation timestamp (if available)"), // Made optional updatedAt: z.string().optional().describe("Last update timestamp (if available)"), // Made optional projectId: z.string().optional().describe("Associated Project ID (if applicable)"), projectName: z.string().optional().describe("Associated Project name (if applicable)"), score: z.number().describe("Relevance score") })), total: z.number().int().describe("Total number of matching results"), page: z.number().int().describe("Current page number"), limit: z.number().int().describe("Results per page"), totalPages: z.number().int().describe("Total number of pages") }), rateLimit: { windowMs: 60 * 1000, // 1 minute maxRequests: 20 // 20 requests per minute } }) ); };