get_element_relationships
Retrieve semantic connections, verb-based links, and cross-element references for any persona, skill, template, agent, memory, or ensemble element in DollhouseMCP.
Instructions
Get all relationships for a specific element, including semantic similarities, verb-based connections, and cross-element references.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| element_name | Yes | Name of the element to get relationships for | |
| element_type | No | Type of the element. If not specified, searches all types. | |
| relationship_types | No | Filter by specific relationship types. If not specified, returns all types. |
Implementation Reference
- Core handler function executing the tool logic: validates inputs, normalizes element IDs, fetches relationships from EnhancedIndexManager, filters by type if specified, parses relationships, and formats a rich text response with icons and strength scores.async getElementRelationships(options: { elementName: string; elementType?: string; relationshipTypes?: string[]; }) { try { // FIX: DMCP-SEC-004 - Normalize Unicode in user input const normalized = UnicodeValidator.normalize(options.elementName); if (!normalized.isValid) { throw new Error(`Invalid element name: ${normalized.detectedIssues?.join(', ')}`); } options.elementName = normalized.normalizedContent; if (options.elementType) { const normalizedType = UnicodeValidator.normalize(options.elementType); if (!normalizedType.isValid) { throw new Error(`Invalid element type: ${normalizedType.detectedIssues?.join(', ')}`); } options.elementType = normalizedType.normalizedContent; } // Get the index with error handling await this.enhancedIndexManager.getIndex().catch(async (error) => { logger.error('Failed to get Enhanced Index, attempting rebuild', error); return this.enhancedIndexManager.getIndex({ forceRebuild: true }); }); // FIX: DMCP-SEC-006 - Add security audit logging SecurityMonitor.logSecurityEvent({ type: 'ELEMENT_CREATED', severity: 'LOW', source: 'EnhancedIndexHandler.getElementRelationships', details: `Relationship query performed for element: ${options.elementName}`, additionalData: { elementType: options.elementType, relationshipTypes: options.relationshipTypes } }); // FIX: Use centralized element ID formatting // If no element type provided, use full element name as-is (may already include type) const elementId = options.elementType ? formatElementId(options.elementType, options.elementName) : options.elementName; const relationships = await this.enhancedIndexManager.getElementRelationships(elementId); // Filter by type if requested let filteredRelationships = relationships; if (options.relationshipTypes && options.relationshipTypes.length > 0) { filteredRelationships = {}; for (const type of options.relationshipTypes) { if (relationships[type]) { filteredRelationships[type] = relationships[type]; } } } // Format results let text = `${this.personaIndicator}🔗 **Element Relationships**\n\n`; text += `**Element**: ${options.elementName}\n`; if (options.elementType) { text += `**Type**: ${options.elementType}\n`; } text += '\n'; const relationshipCount = Object.values(filteredRelationships) .reduce((sum, rels) => sum + (Array.isArray(rels) ? rels.length : 0), 0); if (relationshipCount === 0) { text += `No relationships found for this element.\n`; } else { for (const [relType, relations] of Object.entries(filteredRelationships)) { if (Array.isArray(relations) && relations.length > 0) { text += `**${relType.charAt(0).toUpperCase() + relType.slice(1)} (${relations.length})**\n`; for (const rel of relations) { // FIX: Use type-safe relationship parsing const parsedRel = parseRelationship(rel); if (isParsedRelationship(parsedRel)) { const icon = this.getElementIcon(parsedRel.targetType); text += ` ${icon} ${parsedRel.targetName}`; if (parsedRel.strength) { text += ` (strength: ${(parsedRel.strength * 100).toFixed(0)}%)`; } text += '\n'; } else { // Fallback for invalid relationships const parsed = parseElementIdWithFallback(rel.element); const icon = this.getElementIcon(parsed.type); text += ` ${icon} ${parsed.name} ⚠️\n`; } } text += '\n'; } } } return { content: [{ type: "text", text }] }; } catch (error: any) { ErrorHandler.logError('EnhancedIndexHandler.getElementRelationships', error, options); return { content: [{ type: "text", text: `${this.personaIndicator}❌ Failed to get relationships: ${SecureErrorHandler.sanitizeError(error).message}` }] }; } }
- src/server/tools/EnhancedIndexTools.ts:77-109 (registration)Registers the MCP tool 'get_element_relationships' with full input schema, description, and handler that maps args to server.getElementRelationships call.tool: { name: "get_element_relationships", description: "Get all relationships for a specific element, including semantic similarities, verb-based connections, and cross-element references.", inputSchema: { type: "object", properties: { element_name: { type: "string", description: "Name of the element to get relationships for", }, element_type: { type: "string", enum: ["personas", "skills", "templates", "agents", "memories", "ensembles"], description: "Type of the element. If not specified, searches all types.", }, relationship_types: { type: "array", items: { type: "string", enum: ["similar", "uses", "extends", "requires", "complements", "verb-based"] }, description: "Filter by specific relationship types. If not specified, returns all types.", }, }, required: ["element_name"], }, }, handler: (args: GetElementRelationshipsArgs) => server.getElementRelationships({ elementName: args.element_name, elementType: args.element_type, relationshipTypes: args.relationship_types }) },
- JSON schema for tool inputs defining element_name (required), optional element_type enum, and relationship_types array enum.inputSchema: { type: "object", properties: { element_name: { type: "string", description: "Name of the element to get relationships for", }, element_type: { type: "string", enum: ["personas", "skills", "templates", "agents", "memories", "ensembles"], description: "Type of the element. If not specified, searches all types.", }, relationship_types: { type: "array", items: { type: "string", enum: ["similar", "uses", "extends", "requires", "complements", "verb-based"] }, description: "Filter by specific relationship types. If not specified, returns all types.", }, }, required: ["element_name"], },
- Helper method in EnhancedIndexManager that retrieves raw relationships for an element from the in-memory index after parsing the elementId.public async getElementRelationships(elementId: string): Promise<Record<string, Relationship[]>> { const index = await this.getIndex(); // FIX: Use centralized element ID parsing const parsed = parseElementId(elementId); if (!parsed) { return {}; } const element = index.elements[parsed.type]?.[parsed.name]; if (!element) { return {}; } return element.relationships || {}; }