Skip to main content
Glama

update_location

Modify location details in the MemoryMesh knowledge graph, including name, type, description, status, atmosphere, accessibility, danger level, and associated entities like characters, quests, and artifacts.

Instructions

Update an existing location in the knowledge graph

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
update_locationYes

Implementation Reference

  • Core handler executing the logic for 'update_location' tool: validates node, processes updates to metadata and edges, manages transactions via ApplicationManager.
    export async function handleSchemaUpdate(
        updates: NodeData,
        schema: SchemaConfig,
        nodeType: string,
        applicationManager: ApplicationManager
    ): Promise<ToolResponse> {
        try {
            // Start a transaction to ensure atomic updates
            await applicationManager.beginTransaction();
    
            // Get the complete current state
            const fullGraph = await applicationManager.readGraph();
            const node = fullGraph.nodes.find((n: Node) => n.nodeType === nodeType && n.name === updates.name);
    
            if (!node) {
                await applicationManager.rollback();
                return formatToolError({
                    operation: 'updateSchema',
                    error: `${nodeType} "${updates.name}" not found`,
                    context: {updates, nodeType},
                    suggestions: ["Verify the node exists", "Check node type matches"]
                });
            }
    
            try {
                // Process updates
                const {metadata, edgeChanges} = await updateSchemaNode(
                    updates,
                    node,
                    schema,
                    fullGraph
                );
    
                // Update the node first
                const updatedNode: Node = {
                    ...node,
                    metadata
                };
                await applicationManager.updateNodes([updatedNode]);
    
                // Then handle edges if there are any changes
                if (edgeChanges.remove.length > 0) {
                    await applicationManager.deleteEdges(edgeChanges.remove);
                }
    
                if (edgeChanges.add.length > 0) {
                    await applicationManager.addEdges(edgeChanges.add);
                }
    
                // If everything succeeded, commit the transaction
                await applicationManager.commit();
    
                return formatToolResponse({
                    data: {
                        updatedNode,
                        edgeChanges
                    },
                    actionTaken: `Updated ${nodeType}: ${updatedNode.name}`
                });
    
            } catch (error) {
                // If anything fails, rollback all changes
                await applicationManager.rollback();
                throw error;
            }
    
        } catch (error) {
            if (applicationManager.isInTransaction()) {
                await applicationManager.rollback();
            }
    
            return formatToolError({
                operation: 'updateSchema',
                error: error instanceof Error ? error.message : 'Unknown error occurred',
                context: {updates, schema, nodeType},
                suggestions: [
                    "Check all required fields are provided",
                    "Verify relationship targets exist"
                ],
                recoverySteps: [
                    "Review schema requirements",
                    "Ensure node exists before updating"
                ]
            });
        }
    }
  • Generates the input schema/JSON Schema for the update tool (e.g., update_location), defining properties, relationships, and validation rules based on the base schema.
    createUpdateSchema(excludeFields: Set<string> = new Set()): SchemaConfig {
        const schemaName = this.schema.name!.replace('add_', 'update_');
        const updateSchemaBuilder = new SchemaBuilder(
            schemaName,
            `Update an existing ${schemaName.replace('update_', '')} in the knowledge graph`
        );
    
        const baseProperties = this.schema.inputSchema!.properties[this.schema.name!.replace('add_', '')].properties;
    
        // Copy properties except excluded ones
        Object.entries(baseProperties).forEach(([propName, propValue]) => {
            if (!excludeFields.has(propName)) {
                if (propValue.type === 'array') {
                    updateSchemaBuilder.addArrayProperty(
                        propName,
                        propValue.description,
                        false,
                        propValue.items?.enum
                    );
                } else {
                    updateSchemaBuilder.addStringProperty(
                        propName,
                        propValue.description,
                        false,
                        propValue.enum
                    );
                }
            }
        });
    
        // Copy relationships
        this.relationships.forEach((config, propName) => {
            if (!excludeFields.has(propName)) {
                updateSchemaBuilder.addRelationship(
                    propName,
                    config.edgeType,
                    config.description || 'Relationship property',
                    config.nodeType || null
                );
            }
        });
    
        // Add metadata array
        updateSchemaBuilder.addArrayProperty(
            'metadata',
            'An array of metadata contents to replace the existing metadata'
        );
    
        return updateSchemaBuilder.build();
    }
  • Registers the dynamic tools for a schema, including creating the 'update_location' tool definition from location schema using createUpdateSchema.
    private async generateToolsForSchema(schemaName: string, schema: SchemaBuilder): Promise<Tool[]> {
        const tools: Tool[] = [];
        const baseSchema = schema.build();
    
        // Add tool
        tools.push(baseSchema as unknown as Tool);
    
        // Update tool
        const updateSchema = schema.createUpdateSchema();
        tools.push(updateSchema as unknown as Tool);
    
        // Delete tool
        const deleteSchema: Tool = {
            name: `delete_${schemaName}`,
            description: `Delete
            an existing
            ${schemaName}
            from
            the
            knowledge
            graph`,
            inputSchema: {
                type: "object",
                properties: {
                    [`delete_${schemaName}`]: {
                        type: "object",
                        description: `Delete parameters for ${schemaName}`,
                        properties: {
                            name: {
                                type: "string",
                                description: `The name of the ${schemaName} to delete`
                            }
                        },
                        required: ["name"]
                    }
                },
                required: [`delete_${schemaName}`]
            }
        };
    
        tools.push(deleteSchema);
        return tools;
    }
  • Helper function that computes metadata updates and edge changes (add/remove) for schema node updates, used by handleSchemaUpdate.
    export async function updateSchemaNode(
        updates: NodeData,
        currentNode: Node,
        schema: SchemaConfig,
        currentGraph: Graph
    ): Promise<SchemaUpdateResult> {
        const {metadataConfig, relationships} = schema;
        const metadata = new Map<string, string>();
        const edgeChanges = {
            remove: [] as Edge[],
            add: [] as Edge[]
        };
    
        // Create a set of all schema-defined fields
        const schemaFields = new Set<string>([
            ...metadataConfig.requiredFields,
            ...metadataConfig.optionalFields,
            ...(metadataConfig.excludeFields || []),
            'name',
            'metadata'
        ]);
    
        // Add relationship fields to schema fields
        if (relationships) {
            Object.keys(relationships).forEach(field => schemaFields.add(field));
        }
    
        // Process existing metadata into the Map
        currentNode.metadata.forEach(meta => {
            const colonIndex = meta.indexOf(':');
            if (colonIndex !== -1) {
                const key = meta.substring(0, colonIndex).trim().toLowerCase();
                const value = meta.substring(colonIndex + 1).trim();
                metadata.set(key, value);
            }
        });
    
        const updateMetadataEntry = (key: string, value: unknown) => {
            const formattedValue = Array.isArray(value) ? value.join(', ') : String(value);
            metadata.set(key.toLowerCase(), formattedValue);
        };
    
        // Process standard metadata fields
        const allSchemaFields = [...metadataConfig.requiredFields, ...metadataConfig.optionalFields];
        for (const field of allSchemaFields) {
            if (updates[field] !== undefined && (!relationships || !relationships[field])) {
                updateMetadataEntry(field, updates[field]);
            }
        }
    
        // Process relationships if they exist in the schema
        if (relationships) {
            for (const [field, config] of Object.entries(relationships)) {
                // Only process relationship if it's being updated
                if (updates[field] !== undefined) {
                    // Get all existing edges for this relationship type from this node
                    const existingEdges = currentGraph.edges.filter(edge =>
                        edge.from === currentNode.name &&
                        edge.edgeType === config.edgeType
                    );
    
                    // Only mark edges for removal if they're part of this relationship type
                    edgeChanges.remove.push(...existingEdges);
    
                    // Add new edges
                    const value = updates[field];
                    if (Array.isArray(value)) {
                        value.forEach((target: string) => {
                            edgeChanges.add.push({
                                type: 'edge',
                                from: currentNode.name,
                                to: target,
                                edgeType: config.edgeType
                            });
                        });
                    } else if (value) {
                        edgeChanges.add.push({
                            type: 'edge',
                            from: currentNode.name,
                            to: value as string,
                            edgeType: config.edgeType
                        });
                    }
    
                    updateMetadataEntry(field, value);
                }
            }
        }
    
        // Process additional fields not defined in schema
        for (const [key, value] of Object.entries(updates)) {
            if (!schemaFields.has(key) && value !== undefined) {
                updateMetadataEntry(key, value);
            }
        }
    
        const updatedMetadata = Array.from(metadata).map(([key, value]) => {
            const capitalizedKey = key.charAt(0).toUpperCase() + key.slice(1);
            return `${capitalizedKey}: ${value}`;
        });
    
        return {
            metadata: updatedMetadata,
            edgeChanges
        };
    }
  • Top-level tool registry initialization that includes dynamic tools like update_location by adding them to the central tools map.
    async initialize(knowledgeGraphManager: ApplicationManager): Promise<void> {
        if (this.initialized) {
            return;
        }
    
        try {
            this.knowledgeGraphManager = knowledgeGraphManager;
    
            // Register static tools
            allStaticTools.forEach(tool => {
                this.tools.set(tool.name, tool);
            });
    
            // Initialize and register dynamic tools
            await dynamicToolManager.initialize();
            dynamicToolManager.getTools().forEach(tool => {
                this.tools.set(tool.name, tool);
            });
    
            this.initialized = true;
            console.error(`[ToolsRegistry] Initialized with ${this.tools.size} tools`);
        } catch (error) {
            console.error('[ToolsRegistry] Initialization error:', error);
            throw error;
        }
    }

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/CheMiguel23/MemoryMesh'

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