Skip to main content
Glama
knowall-ai

Neo4j Agent Memory MCP Server

by knowall-ai

get_guidance

Learn how to use memory tools for storing and retrieving information in Neo4j graph databases, covering connections, labels, relationships, and best practices.

Instructions

Get help on using the memory tools effectively

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
topicNoTopic: connections, labels, relationships, best-practices, examples, or leave empty for all

Implementation Reference

  • The core handler function that implements the get_guidance tool logic. It returns markdown-formatted guidance content based on the provided topic or all topics if none specified.
    export function getGuidanceContent(topic?: string): string {
      const sections = {
        connections: `## The Power of Connections
    
    **Why Connections Matter**
    - Isolated memories = limited utility
    - Connected memories = exponential value
    - Each connection adds context and meaning
    - Enables discovery of hidden patterns
    
    **Connection Strategy**
    1. Create the memory first
    2. Immediately ask: "What does this relate to?"
    3. Search for related memories
    4. Create meaningful connections
    5. Add properties to connections for context
    
    **Example Flow**
    1. User: "John works at Google as a software engineer"
    2. **Search for John first** - he might already exist!
    3. If not found, create memory for John (person)
    4. **Search for Google** - it probably already exists
    5. If not found, create Google (organization)
    6. Connect: John -[WORKS_AT]-> Google
    7. Add properties: role="Software Engineer", since="2020"
    
    **Connection Patterns**
    - Person -> Organization (WORKS_AT, FOUNDED, OWNS)
    - Person -> Person (KNOWS, MANAGES, MARRIED_TO)
    - Person -> Skill (HAS_SKILL)
    - Person -> Place (LIVES_IN, FROM)
    - Project -> Person (LED_BY, INVOLVES)
    - Event -> Person (ATTENDED_BY, ORGANIZED_BY)`,
    
        labels: `## Common Memory Labels
    
    Use these labels when creating memories (always use lowercase):
    
    **People & Living Things**
    - person: Individual people
    - animal: Pets, wildlife
    - plant: Trees, flowers, crops
    
    **Places & Locations**  
    - place: General locations
    - organization: Companies, institutions
    - vehicle: Cars, planes, boats
    
    **Concepts & Activities**
    - project: Work or personal projects
    - event: Meetings, conferences, celebrations
    - topic: Subjects of interest
    - activity: Sports, hobbies
    - skill: Abilities and expertise
    
    **Objects & Media**
    - object: Physical items
    - food: Meals, ingredients
    - media: Books, movies, music
    - document: Files, reports
    - tool: Software, hardware
    
    **Abstract Concepts**
    - idea: Thoughts, concepts
    - goal: Objectives, targets
    - task: To-dos, assignments
    - habit: Routines, behaviors
    - health: Medical, wellness`,
    
        relationships: `## Common Relationship Types
    
    Use UPPERCASE for relationship types:
    
    **Personal Relationships**
    - KNOWS: General acquaintance
    - FRIENDS_WITH: Close friendship
    - MARRIED_TO: Spouse relationship
    - FAMILY_OF: Family connection
    
    **Professional Relationships**
    - WORKS_AT: Employment
    - WORKS_ON: Project involvement
    - COLLABORATES_WITH: Working together
    - MANAGES: Leadership role
    - REPORTS_TO: Reporting structure
    - OWNS: Ownership
    
    **Location Relationships**
    - LIVES_IN: Residence
    - LOCATED_IN: Physical location
    - VISITED: Past visits
    - FROM: Origin
    
    **Skill & Knowledge**
    - HAS_SKILL: Possesses ability
    - TEACHES: Instructing others
    - LEARNS_FROM: Student relationship
    
    **Project & Creation**
    - LEADS: Project leadership
    - PARTICIPATES_IN: Involvement
    - CREATED: Authorship
    - USES: Utilization`,
    
        'best-practices': `## Best Practices
    
    **CRITICAL: Always Create Connections**
    - Isolated memories have limited value - ALWAYS look for connections
    - When storing new information, immediately think: "What does this relate to?"
    - A memory without connections is like a book with no catalog entry
    - The graph becomes exponentially more useful with each connection
    
    **Creating Memories - ALWAYS SEARCH FIRST**
    - **CRITICAL: Always search before creating** - memories often already exist
    - Search by name first: search_memories({query: "John Smith"})
    - If multiple matches found, **ASK THE USER TO CONFIRM** which one they mean
    - Show distinguishing details: "I found 3 people named John: John Smith (Engineer at Google), John Smith (Doctor), John Smith (Teacher). Which one did you mean?"
    - If unsure about a match, describe it and ask: "I found John Smith who works at TechCorp. Is this the same person?"
    - Only create new memory after confirming it's not a duplicate
    - Always use lowercase for labels
    - Include a 'name' property for easy identification
    - 'created_at' is automatic if not provided
    - IMMEDIATELY after creating, connect it to related memories
    
    **Building Connections**
    - After creating any memory, ask: "What existing memories relate to this?"
    - Create connections for: people→organizations, people→projects, people→skills
    - Add relationship properties for rich context (since, role, status)
    - One memory can have many connections - don't limit yourself
    
    **Searching**
    - Empty query string returns all memories
    - Use label parameter to filter by type
    - Increase depth to include more relationships (depth=2 or 3 for rich context)
    - Default limit is 10, max is 200
    
    **Managing Relationships**
    - Use UPPERCASE for relationship types
    - Add properties to relationships for context (e.g., since, role)
    - Search for memory IDs before creating connections
    - Use list_memory_labels to see existing labels
    
    **Data Organization**
    - Keep labels simple and consistent
    - Reuse existing labels when possible
    - Add descriptive properties to memories
    - Use relationships instead of complex properties
    - Think in graphs: nodes (memories) + edges (relationships) = knowledge`,
    
        examples: `## Examples
    
    **Creating a Person (WITH SEARCH FIRST)**
    \`\`\`
    // ALWAYS search first to avoid duplicates
    const searchResult = search_memories({ query: "Alice Johnson" })
    
    if (searchResult.length === 0) {
      // Only create if not found
      create_memory({
        label: "person",
        properties: {
          name: "Alice Johnson",
          occupation: "Software Engineer",
          company: "Tech Corp"
        }
      })
    } else {
      // Use existing memory ID: searchResult[0].memory._id
    }
    \`\`\`
    
    **Creating a Relationship**
    \`\`\`
    // First, find the IDs
    search_memories({ query: "Alice Johnson" })
    search_memories({ query: "Tech Corp" })
    
    // Then connect them
    create_connection({
      fromMemoryId: 123,
      toMemoryId: 456,
      type: "WORKS_AT",
      properties: {
        role: "Senior Engineer",
        since: "2020-01-15"
      }
    })
    \`\`\`
    
    **Handling Ambiguous Matches**
    \`\`\`
    // User says: "Add that Sarah works at Microsoft"
    const searchResult = search_memories({ query: "Sarah" })
    
    // Found multiple matches - ASK USER TO CONFIRM
    if (searchResult.length > 1) {
      // Show options to user:
      // "I found 3 people named Sarah:
      // 1. Sarah Johnson (Marketing Manager at TechCorp)
      // 2. Sarah Chen (Data Scientist)
      // 3. Sarah Williams (Designer at StartupXYZ)
      // Which Sarah works at Microsoft?"
    }
    
    // If only one match but uncertain
    if (searchResult.length === 1) {
      // Confirm with user:
      // "I found Sarah Johnson who is a Marketing Manager at TechCorp. 
      // Is this the Sarah who now works at Microsoft?"
    }
    \`\`\`
    
    **Searching with Depth**
    \`\`\`
    // Find all people and their connections
    search_memories({
      query: "",
      label: "person",
      depth: 2,
      limit: 50
    })
    \`\`\`
    
    **Updating a Memory**
    \`\`\`
    update_memory({
      nodeId: 123,
      properties: {
        occupation: "Lead Engineer",
        skills: ["Python", "Neo4j", "MCP"]
      }
    })
    \`\`\``,
      };
    
      if (!topic) {
        // Return all sections
        return `# Neo4j Agent Memory Guidance
    
    ${sections.connections}
    
    ${sections.labels}
    
    ${sections.relationships}
    
    ${sections['best-practices']}
    
    ${sections.examples}`;
      }
    
      const content = sections[topic as keyof typeof sections];
      if (content) {
        return content;
      }
    
      return `Unknown topic: '${topic}'. Available topics: connections, labels, relationships, best-practices, examples, or leave empty for all guidance.`;
    }
  • Tool definition object including the input schema for validating get_guidance arguments.
    export const guidanceTool: Tool = {
      name: 'get_guidance',
      description: 'Get help on using the memory tools effectively',
      inputSchema: {
        type: 'object',
        properties: {
          topic: {
            type: 'string',
            description: 'Topic: connections, labels, relationships, best-practices, examples, or leave empty for all',
          },
        },
        required: [],
      },
    };
  • TypeScript interface and type guard function for input validation of get_guidance arguments.
    export interface GetGuidanceArgs {
      topic?: string;
    }
    
    export function isGetGuidanceArgs(args: unknown): args is GetGuidanceArgs {
      if (typeof args !== 'object' || args === null) return true; // Allow empty args
      const obj = args as Record<string, unknown>;
      return obj.topic === undefined || typeof obj.topic === 'string';
    }
  • The tools array where get_guidance is registered via inclusion of the guidanceTool object.
    export const tools: Tool[] = [
      {
        name: 'search_memories',
        description: 'Search and retrieve memories from the knowledge graph',
        inputSchema: {
          type: 'object',
          properties: {
            query: {
              type: 'string',
              description: 'Search text to find in any property (searches for ANY word - e.g. "Ben Weeks" finds memories containing "Ben" OR "Weeks")',
            },
            label: {
              type: 'string',
              description: 'Filter by memory label',
            },
            depth: {
              type: 'number',
              description: 'Relationship depth to include, defaults to 1',
            },
            order_by: {
              type: 'string',
              description: 'Sort order such as created_at DESC, name ASC',
            },
            limit: {
              type: 'number',
              description: 'Maximum results to return, defaults to 10, max 200',
            },
            since_date: {
              type: 'string',
              description: 'ISO date string to filter memories created after this date (e.g., "2024-01-01" or "2024-01-01T00:00:00Z")',
            },
          },
          required: [],
        },
      },
      {
        name: 'create_memory',
        description: 'Create a new memory in the knowledge graph. Consider that the memory might already exist, so Search → Create → Connect (its important to try and connect memories)',
        inputSchema: {
          type: 'object',
          properties: {
            label: {
              type: 'string',
              description: 'Memory label in lowercase (use list_memory_labels first to check existing labels for consistency) - common: person, place, organization, project, event, topic, object, animal, plant, food, activity, media, skill, document, meeting, task, habit, health, vehicle, tool, idea, goal',
            },
            properties: {
              type: 'object',
              description: 'Information to store about this memory (use "name" as primary identifier, e.g. {name: "John Smith", age: 30, occupation: "Engineer"})',
              additionalProperties: true,
            },
          },
          required: ['label', 'properties'],
        },
      },
      {
        name: 'create_connection',
        description: 'Create a connection between two memories (its good to have connected memories)',
        inputSchema: {
          type: 'object',
          properties: {
            fromMemoryId: {
              type: 'number',
              description: 'ID of the source memory',
            },
            toMemoryId: {
              type: 'number',
              description: 'ID of the target memory',
            },
            type: {
              type: 'string',
              description: 'Relationship type such as KNOWS, WORKS_ON, LIVES_IN, HAS_SKILL, PARTICIPATES_IN',
            },
            properties: {
              type: 'object',
              description: 'Optional relationship metadata (e.g. {since: "2023-01", role: "Manager", status: "active"})',
              additionalProperties: true,
            },
          },
          required: ['fromMemoryId', 'toMemoryId', 'type'],
        },
      },
      {
        name: 'update_memory',
        description: 'Update properties of an existing memory such as adding more detail or make a change when you find out something new',
        inputSchema: {
          type: 'object',
          properties: {
            nodeId: {
              type: 'number',
              description: 'ID of the memory to update',
            },
            properties: {
              type: 'object',
              description: 'Properties to update/add',
              additionalProperties: true,
            },
          },
          required: ['nodeId', 'properties'],
        },
      },
      {
        name: 'update_connection',
        description: 'Update properties of an existing connection between memories',
        inputSchema: {
          type: 'object',
          properties: {
            fromMemoryId: {
              type: 'number',
              description: 'ID of the source memory',
            },
            toMemoryId: {
              type: 'number',
              description: 'ID of the target memory',
            },
            type: {
              type: 'string',
              description: 'Relationship type to identify which connection to update (e.g. WORKS_AT, KNOWS, MANAGES)',
            },
            properties: {
              type: 'object',
              description: 'Properties to update/add (e.g. {status: "completed", end_date: "2024-01"})',
              additionalProperties: true,
            },
          },
          required: ['fromMemoryId', 'toMemoryId', 'type', 'properties'],
        },
      },
      {
        name: 'delete_memory',
        description: 'Delete a memory and all its connections (use with caution - this permanently removes the memory and all its connections)',
        inputSchema: {
          type: 'object',
          properties: {
            nodeId: {
              type: 'number',
              description: 'ID of the memory to delete',
            },
          },
          required: ['nodeId'],
        },
      },
      {
        name: 'delete_connection',
        description: 'Delete a specific connection between two memories (use with caution - this permanently removes the relationship)',
        inputSchema: {
          type: 'object',
          properties: {
            fromMemoryId: {
              type: 'number',
              description: 'ID of the source memory',
            },
            toMemoryId: {
              type: 'number',
              description: 'ID of the target memory',
            },
            type: {
              type: 'string',
              description: 'Exact relationship type to delete (e.g. WORKS_AT, KNOWS, MANAGES)',
            },
          },
          required: ['fromMemoryId', 'toMemoryId', 'type'],
        },
      },
      {
        name: 'list_memory_labels',
        description: 'List all unique memory labels currently in use with their counts (useful for getting an overview of the knowledge graph)',
        inputSchema: {
          type: 'object',
          properties: {},
          required: [],
        },
      },
      guidanceTool,
    ];
  • The switch case dispatcher in the main tool handler that validates arguments and calls the getGuidanceContent function for get_guidance.
    case 'get_guidance': {
      if (!isGetGuidanceArgs(args)) {
        throw new McpError(ErrorCode.InvalidParams, 'Invalid get_guidance arguments');
      }
      
      const content = getGuidanceContent(args.topic);
      
      return {
        content: [
          {
            type: 'text',
            text: content,
          },
        ],
      };
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It states the tool provides 'help' but does not specify what form this help takes (e.g., textual advice, examples, documentation), whether it requires authentication, or any rate limits. This leaves significant gaps in understanding how the tool behaves beyond its basic purpose.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, clear sentence: 'Get help on using the memory tools effectively.' It is front-loaded with the core purpose, has no unnecessary words, and efficiently communicates the tool's intent without redundancy, making it highly concise and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's low complexity (one optional parameter) and high schema coverage, the description is adequate for basic understanding. However, with no annotations and no output schema, it fails to provide details on behavioral aspects (e.g., response format, error handling) or deeper context, which could be important for effective use. It meets minimum viability but has clear gaps in completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 100% description coverage, with the 'topic' parameter well-documented in the schema itself. The description does not add any additional meaning or context beyond what the schema provides (e.g., it doesn't explain the significance of topics like 'best-practices'). Since schema coverage is high, the baseline score of 3 is appropriate, as the description doesn't compensate but also doesn't detract.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Get help on using the memory tools effectively.' It specifies the verb ('Get help') and the resource ('memory tools'), making it understandable. However, it doesn't explicitly differentiate from sibling tools like 'list_memory_labels' or 'search_memories' in terms of its advisory versus operational nature, which prevents a perfect score.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage context ('using the memory tools effectively'), suggesting it should be used for guidance rather than direct operations. However, it lacks explicit guidance on when to use this tool versus alternatives (e.g., when to seek help versus directly using tools like 'create_memory'), and does not mention any exclusions or prerequisites, leaving room for ambiguity.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/knowall-ai/mcp-neo4j-agent-memory'

If you have feedback or need assistance with the MCP directory API, please join our Discord server