Skip to main content
Glama

Sitecore MCP Server

by GaryWenneker
build-relationship-graph.ps19.41 kB
# Relationship Graph Builder # Recursively follows item references to build complete relationship graph param( [string]$Output = (Join-Path $PSScriptRoot "..\\..\\.schema-analysis\\relationship-graph.json") ) # Load environment variables from .env file (canonical) . "$PSScriptRoot\Load-DotEnv.ps1" Load-DotEnv -EnvFile "$PSScriptRoot\..\..\.env" # Load field reference parser (from tools folder) . "$PSScriptRoot\parse-field-references.ps1" Write-Host "" Write-Host "========================================" -ForegroundColor Cyan Write-Host " Relationship Graph Builder" -ForegroundColor Cyan Write-Host "========================================" -ForegroundColor Cyan Write-Host "" # Global tracking $script:visitedItems = @{} $script:relationshipGraph = @{ Nodes = @() Edges = @() } $script:circularReferences = @() function Get-ItemByPath { param( [string]$Path, [string]$Language = "en" ) Write-Host "[QUERY] Getting item: $Path" -ForegroundColor Yellow $headers = @{ "sc_apikey" = $env:SITECORE_API_KEY "Content-Type" = "application/json" } $endpoint = "$($env:SITECORE_HOST)/sitecore/api/graph/items/master" $query = @{ query = @" { item(path: "$Path", language: "$Language") { id name displayName path template { id name path } language { name } } } "@ } | ConvertTo-Json try { $response = Invoke-RestMethod -Uri $endpoint -Method Post -Body $query -Headers $headers return $response.data.item } catch { Write-Host "[ERROR] Failed to get item: $($_.Exception.Message)" -ForegroundColor Red return $null } } function Get-ItemFields { param( [string]$Path, [string]$Language = "en" ) Write-Host "[QUERY] Getting fields for: $Path" -ForegroundColor Yellow $headers = @{ "sc_apikey" = $env:SITECORE_API_KEY "Content-Type" = "application/json" } $endpoint = "$($env:SITECORE_HOST)/sitecore/api/graph/items/master" $query = @{ query = @" { item(path: "$Path", language: "$Language") { fields(ownFields: false) { name value } } } "@ } | ConvertTo-Json try { $response = Invoke-RestMethod -Uri $endpoint -Method Post -Body $query -Headers $headers if ($response.data.item) { return $response.data.item.fields } return @() } catch { Write-Host "[ERROR] Failed to get fields: $($_.Exception.Message)" -ForegroundColor Red return @() } } function Build-RelationshipGraph { param( [Parameter(Mandatory=$true)] [string]$RootPath, [string]$Language = "en", [int]$MaxDepth = 3, [int]$CurrentDepth = 0 ) Write-Host "" Write-Host "$([string]::new("`t", $CurrentDepth))[DEPTH $CurrentDepth] Processing: $RootPath" -ForegroundColor Cyan # Check depth limit if ($CurrentDepth -ge $MaxDepth) { Write-Host "$([string]::new("`t", $CurrentDepth))[LIMIT] Max depth reached" -ForegroundColor Yellow return } # Get item details $item = Get-ItemByPath -Path $RootPath -Language $Language if (-not $item) { Write-Host "$([string]::new("`t", $CurrentDepth))[SKIP] Item not found or inaccessible" -ForegroundColor Red return } $itemId = $item.id # Check if already visited (circular reference detection) if ($script:visitedItems.ContainsKey($itemId)) { Write-Host "$([string]::new("`t", $CurrentDepth))[CIRCULAR] Already visited: $($item.name)" -ForegroundColor Magenta $script:circularReferences += @{ From = $RootPath To = $item.path ItemId = $itemId } return } # Mark as visited $script:visitedItems[$itemId] = $true Write-Host "$([string]::new("`t", $CurrentDepth))[OK] Found: $($item.name)" -ForegroundColor Green # Add to graph nodes $script:relationshipGraph.Nodes += @{ Id = $itemId Name = $item.name DisplayName = $item.displayName Path = $item.path Template = $item.template.name TemplatePath = $item.template.path Language = $item.language.name Depth = $CurrentDepth } # Get fields $fields = Get-ItemFields -Path $RootPath -Language $Language if ($fields.Count -eq 0) { Write-Host "$([string]::new("`t", $CurrentDepth))[INFO] No fields found" -ForegroundColor Gray return } Write-Host "$([string]::new("`t", $CurrentDepth))[INFO] Found $($fields.Count) fields" -ForegroundColor Gray # Parse field references $refs = Parse-FieldReferences -Fields $fields # Process GUID references foreach ($guidRef in $refs.GuidReferences) { Write-Host "$([string]::new("`t", $CurrentDepth))[REF] Following GUID from field: $($guidRef.Field)" -ForegroundColor Yellow # Add edge to graph $script:relationshipGraph.Edges += @{ From = $itemId To = $guidRef.Guid Field = $guidRef.Field Type = "GUID" } # Note: Cannot follow GUID without search/lookup mechanism Write-Host "$([string]::new("`t", $CurrentDepth))[TODO] GUID lookup requires search (not implemented in raw GraphQL)" -ForegroundColor Yellow } # Process path references foreach ($pathRef in $refs.PathReferences) { Write-Host "$([string]::new("`t", $CurrentDepth))[REF] Following path from field: $($pathRef.Field)" -ForegroundColor Yellow # Recursively process referenced item Build-RelationshipGraph -RootPath $pathRef.Path -Language $Language -MaxDepth $MaxDepth -CurrentDepth ($CurrentDepth + 1) # Add edge to graph $script:relationshipGraph.Edges += @{ From = $itemId To = $pathRef.Path Field = $pathRef.Field Type = "PATH" } } } function Show-RelationshipGraph { Write-Host "" Write-Host "========================================" -ForegroundColor Cyan Write-Host " Relationship Graph Summary" -ForegroundColor Cyan Write-Host "========================================" -ForegroundColor Cyan Write-Host "" Write-Host "Nodes: $($script:relationshipGraph.Nodes.Count)" -ForegroundColor Yellow Write-Host "Edges: $($script:relationshipGraph.Edges.Count)" -ForegroundColor Yellow Write-Host "Circular References: $($script:circularReferences.Count)" -ForegroundColor Yellow Write-Host "" if ($script:relationshipGraph.Nodes.Count -gt 0) { Write-Host "Nodes by Depth:" -ForegroundColor Cyan $nodesByDepth = $script:relationshipGraph.Nodes | Group-Object Depth | Sort-Object Name foreach ($group in $nodesByDepth) { Write-Host " Depth $($group.Name): $($group.Count) items" -ForegroundColor Gray foreach ($node in $group.Group) { Write-Host " - $($node.Name) ($($node.Template))" -ForegroundColor Gray Write-Host " $($node.Path)" -ForegroundColor DarkGray } } Write-Host "" } if ($script:relationshipGraph.Edges.Count -gt 0) { Write-Host "Relationships:" -ForegroundColor Cyan foreach ($edge in $script:relationshipGraph.Edges) { Write-Host " [$($edge.Type)] $($edge.Field)" -ForegroundColor Yellow Write-Host " From: $($edge.From)" -ForegroundColor Gray Write-Host " To: $($edge.To)" -ForegroundColor Gray } Write-Host "" } if ($script:circularReferences.Count -gt 0) { Write-Host "Circular References:" -ForegroundColor Magenta foreach ($circular in $script:circularReferences) { Write-Host " [LOOP] $($circular.From) -> $($circular.To)" -ForegroundColor Magenta } Write-Host "" } } function Export-RelationshipGraph { param( [string]$OutputPath = (Join-Path $PSScriptRoot "..\\..\\graph.json") ) $export = @{ Nodes = $script:relationshipGraph.Nodes Edges = $script:relationshipGraph.Edges CircularReferences = $script:circularReferences GeneratedAt = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss") } $export | ConvertTo-Json -Depth 10 | Out-File -FilePath $OutputPath -Encoding UTF8 Write-Host "[EXPORT] Graph saved to: $OutputPath" -ForegroundColor Green } Write-Host "[INFO] This script builds a relationship graph by following references" -ForegroundColor Yellow Write-Host "" Write-Host "Usage Example:" -ForegroundColor Cyan Write-Host " Build-RelationshipGraph -RootPath '/sitecore/content/Home' -Language 'en' -MaxDepth 3" -ForegroundColor Gray Write-Host " Show-RelationshipGraph" -ForegroundColor Gray Write-Host " Export-RelationshipGraph -OutputPath (Join-Path $PSScriptRoot '..\\..\\graph.json')" -ForegroundColor Gray Write-Host "" Write-Host "[NOTE] This is a DEMONSTRATION script" -ForegroundColor Yellow Write-Host "[NOTE] For production use, integrate with MCP tools" -ForegroundColor Yellow Write-Host "[NOTE] GUID resolution requires search functionality" -ForegroundColor Yellow

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/GaryWenneker/SitecoreMCP'

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