@bdmarvin/mcp-server-memory
Version:
MCP Server for LLM Long-Term Memory using KG and Google Drive
111 lines • 11.3 kB
JavaScript
import { z } from 'zod';
// --- Knowledge Graph Tool Schemas (Existing) ---
export const UpdateKgNodeInputSchema = z.object({
project_id: z.string().min(1, { message: "Project ID is required." }).describe("The ID of the project."),
node_id: z.string().min(1, { message: "Node ID is required." }).describe("The unique ID of the node to create/update."),
attributes: z.record(z.any()).describe("A dictionary of attributes for the node.").refine(val => typeof val === 'object' && !Array.isArray(val) && val !== null, {
message: "Attributes must be an object.",
}),
}).describe("Input schema for creating or updating a KG node.");
export const AddKgRelationshipInputSchema = z.object({
project_id: z.string().min(1, { message: "Project ID is required." }).describe("The ID of the project."),
source_node_id: z.string().min(1, { message: "Source Node ID is required." }).describe("The ID of the source node for the relationship."),
relationship_type: z.string().min(1, { message: "Relationship type is required." }).describe("The type of the relationship (e.g., 'depends_on', 'created_by')."),
target_node_id: z.string().min(1, { message: "Target Node ID is required." }).describe("The ID of the target node for the relationship."),
attributes: z.record(z.any()).optional().describe("Optional attributes for the relationship.").refine(val => val === undefined || (typeof val === 'object' && !Array.isArray(val) && val !== null), {
message: "Attributes, if provided, must be an object.",
}),
}).describe("Input schema for adding a relationship between KG nodes.");
export const LogDecisionInputSchema = z.object({
project_id: z.string().min(1, { message: "Project ID is required." }).describe("The ID of the project."),
decision_summary: z.string().min(1, { message: "Decision summary is required." }).describe("A concise summary of the decision made."),
entities_involved: z.array(z.string()).min(1, { message: "At least one entity must be involved." }).describe("List of node IDs or entity names involved in the decision."),
rationale: z.string().optional().describe("Optional rationale or detailed explanation for the decision."),
status: z.enum(["pending", "confirmed", "rejected", "superseded"]).default("confirmed").describe("The current status of the decision."),
}).describe("Input schema for logging a project decision.");
export const GetKgNodeDetailsInputSchema = z.object({
project_id: z.string().min(1, { message: "Project ID is required." }).describe("The ID of the project where the node resides."),
node_id: z.string().min(1, { message: "Node ID is required." }).describe("The unique ID of the KG node to retrieve."),
}).describe("Input schema for retrieving details of a specific KG node.");
export const GetProjectSummaryFromKgInputSchema = z.object({
project_id: z.string().min(1, { message: "Project ID is required." }).describe("The ID of the project to summarize."),
}).describe("Input schema for retrieving a summary of a project from the KG.");
export const SearchKgInputSchema = z.object({
project_id: z.string().optional().describe("Optional: The ID of the project to search within. If omitted, may search across all accessible projects (behavior depends on implementation)."),
query_description: z.string().min(1, { message: "Query description is required." }).describe("Natural language description of what to search for (e.g., 'tasks assigned to John Doe related to feature X')."),
entity_types: z.array(z.string()).optional().describe("Optional: Filter by specific entity types (e.g., ['task', 'feature'])."),
relationship_types: z.array(z.string()).optional().describe("Optional: Filter by specific relationship types (e.g., ['assigned_to', 'depends_on'])."),
max_depth: z.number().int().positive().optional().default(2).describe("Optional: Maximum depth for graph traversal in search (default: 2)."),
max_results: z.number().int().positive().optional().default(10).describe("Optional: Maximum number of results to return (default: 10)."),
}).describe("Input schema for performing a flexible search in the KG.");
export const RetrieveKgInputSchema = z.object({
project_id: z.string().min(1, { message: "Project ID is required." }).describe("The ID of the project whose complete KG is to be retrieved."),
}).describe("Input schema for retrieving the entire Knowledge Graph for a project. Warning: Response can be very large.");
export const TraverseKgInputSchema = z.object({
project_id: z.string().min(1, { message: "Project ID is required." }).describe("The ID of the project whose KG is being traversed."),
start_node_id: z.string().min(1, { message: "Start Node ID is required." }).describe("The ID of the node to begin traversal from."),
relationship_types: z.array(z.string()).optional().describe("Optional: A list of relationship types to follow. If empty or omitted, follows all types."),
direction: z.enum(['outgoing', 'incoming', 'both']).default('outgoing').describe("Specifies the direction of relationships to follow relative to the current node."),
max_depth: z.number().int().min(1).max(5).default(1).describe("Maximum number of steps (relationships) to traverse (1-5, default 1)."),
include_intermediate_nodes: z.boolean().default(false).describe("If true, results include all nodes and relationships in paths; if false, only terminal nodes of paths."),
filter_target_node_types: z.array(z.string()).optional().describe("Optional: Filter terminal nodes by these types."),
max_results: z.number().int().positive().optional().default(25).describe("Maximum number of paths or terminal nodes to return (default 25)."),
}).describe("Input schema for traversing the Knowledge Graph from a starting node.");
const AttributeFilterSchema = z.object({
attribute_name: z.string().min(1).describe("The name of the node attribute to filter on (e.g., 'status', 'version', 'tags'). Use dot notation for nested attributes (e.g., 'details.info')."),
operator: z.enum([
'equals', 'not_equals',
'contains', 'not_contains',
'startswith', 'endswith',
'gt', 'lt', 'gte', 'lte',
'exists', 'not_exists',
'in_array', 'not_in_array'
]).describe("The comparison operator."),
value: z.any().describe("The value to compare against. Type should be appropriate for the operator. For 'exists'/'not_exists', this can be omitted or null. For 'in_array'/'not_in_array', this should be an array if checking attribute against multiple values, or a single value if checking if an array attribute contains the value."),
case_sensitive: z.boolean().optional().default(false).describe("Case sensitivity for string comparisons (default false)."),
});
export const QueryKgByAttributesInputSchema = z.object({
project_id: z.string().min(1, { message: "Project ID is required to scope the search." }).describe("The ID of the project to search within."),
node_type_filter: z.string().optional().describe("Optional: Filter results to only include nodes of this specific type (e.g., 'Issue', 'Decision')."),
attribute_filters: z.array(AttributeFilterSchema).min(1, { message: "At least one attribute filter is required." }).describe("A list of filter conditions to apply to node attributes."),
logical_operator_for_filters: z.enum(['AND', 'OR']).default('AND').describe("How to combine multiple attribute_filters (default AND)."),
max_results: z.number().int().positive().optional().default(50).describe("Maximum number of matching nodes to return (default 50)."),
}).describe("Input schema for finding nodes based on a structured query of their attributes.");
// --- KG Deletion Tool Schemas ---
export const DeleteKgNodeInputSchema = z.object({
project_id: z.string().min(1, { message: "Project ID is required." }).describe("The ID of the project from which to delete the node."),
node_id: z.string().min(1, { message: "Node ID is required." }).describe("The unique ID of the KG node to delete."),
// cascade_delete_relationships: z.boolean().default(false).describe("If true, also deletes all relationships connected to this node. Default is false (node deletion fails if relationships exist or leaves them dangling based on implementation).")
}).describe("Input schema for deleting a specific KG node. Note: This tool, by default, only deletes the node itself. Connected relationships are NOT automatically deleted and might be left dangling or prevent deletion if not handled separately.");
export const DeleteKgRelationshipInputSchema = z.object({
project_id: z.string().min(1, { message: "Project ID is required." }).describe("The ID of the project from which to delete the relationship."),
relationship_id: z.string().min(1, { message: "Relationship ID is required." }).describe("The unique ID of the KG relationship to delete (usually a UUID)."),
// Alternative: identify by source, target, and type if IDs are not always known/used for deletion
// source_node_id: z.string().optional().describe("The ID of the source node of the relationship to delete."),
// target_node_id: z.string().optional().describe("The ID of the target node of the relationship to delete."),
// relationship_type: z.string().optional().describe("The type of the relationship to delete."),
}).describe("Input schema for deleting a specific KG relationship by its ID.");
// --- Google Drive Tool Schemas (Existing) ---
export const StoreDocumentInProjectDriveInputSchema = z.object({
project_id: z.string().min(1, { message: "Project ID is required." }),
document_name: z.string().min(1, { message: "Document name is required." }),
document_content: z.union([z.string(), z.instanceof(Uint8Array)]).describe("Content of the document (string or bytes)."),
document_description: z.string().optional(),
tags: z.array(z.string()).optional(),
}).describe("Input schema for storing a document in Google Drive and linking it in the KG.");
export const FindRelevantDocumentsInKgInputSchema = z.object({
project_id: z.string().min(1, { message: "Project ID is required." }),
keywords: z.array(z.string()).min(1, { message: "At least one keyword is required." }),
date_after: z.string().datetime({ message: "Invalid date format for date_after. Use ISO 8601." }).optional(),
date_before: z.string().datetime({ message: "Invalid date format for date_before. Use ISO 8601." }).optional(),
content_type: z.string().optional().describe("e.g., 'text/plain', 'application/pdf'"),
max_results: z.number().int().positive().optional().default(5),
}).describe("Input schema for finding relevant documents in the KG based on metadata.");
export const GetDocumentContentFromDriveInputSchema = z.object({
drive_file_id: z.string().min(1, { message: "Google Drive File ID is required." }),
}).describe("Input schema for fetching document content from Google Drive.");
export const GetDocumentSummaryFromDriveInputSchema = z.object({
drive_file_id: z.string().min(1, { message: "Google Drive File ID is required." }),
summary_length: z.enum(["short", "medium", "long"]).optional().default("medium"),
}).describe("Input schema for generating and retrieving a summary of a document from Drive.");
//# sourceMappingURL=toolSchemas.js.map