Sitemap & Navigation
Configure intelligent navigation so the AI can navigate your application on behalf of users.
Overview
The sitemap tells the AI:
- What pages exist in your application
- How to navigate to them (URL patterns)
- How to resolve dynamic URLs (e.g., converting "John's profile" →
/employees/emp_123/profile)
Why Not Hardcode URLs?
Problem: AI doesn't know valid paths or how to find IDs
User: "Open John's employee profile" ❌ AI: "I don't know John's employee ID or the URL pattern"
Solution: Sitemap + placeholder resolvers
User: "Open John's employee profile" ✅ AI:
- Calls
get_sitemap→ finds/employees/{employeeId}/profile - Sees
{employeeId}needs resolution viasearch_employeestool - Calls
search_employeeswith "John" → getsemp_123 - Constructs
/employees/emp_123/profile - Calls
navigatetool
Core Concepts
Sitemap Entries
Each entry defines a navigable page:
| Field | Description | Example |
|---|---|---|
pathPattern | URL pattern with placeholders | /products/{productId}/details |
displayName | Human-readable name for AI | "Product Details Page" |
category | Group pages | "products", "admin", "reports" |
description | Context for AI | "Shows detailed product information" |
placeholders | How to resolve dynamic parts | See below |
Placeholder Resolvers
For dynamic URLs like /products/{productId}, you define how the AI should find the ID:
{
"name": "productId",
"description": "Unique product identifier",
"resolver": {
"toolName": "search_products",
"inputMapping": { "param": "query" },
"outputPath": "results[0].id"
},
"searchHint": "Search by product name or SKU",
"examples": ["24/7 package", "SKU-12345", "premium hosting"]
}
How it works:
- User: "Open the 24/7 package details"
- AI calls
search_products(query: "24/7 package") - AI gets response:
{ results: [{ id: "prod_abc", name: "24/7 Package" }] } - AI extracts ID using
outputPath:results[0].id→"prod_abc" - AI constructs URL:
/products/prod_abc/details - AI navigates
Hierarchical Structure
Pages can have parent/child relationships:
- Dashboard (/)
- Analytics (/analytics)
- Sales Report (/analytics/sales)
- User Report (/analytics/users)
- Settings (/settings)
Setting Up Navigation
Static Pages (No Placeholders)
Simple pages with fixed URLs:
POST /admin/assistants/{assistantId}/sitemap
Content-Type: application/json
{
"assistantInfoId": "ast_abc123",
"pathPattern": "/dashboard",
"displayName": "Main Dashboard",
"category": "navigation",
"description": "Overview of key metrics and recent activity"
}
Dynamic Pages (With Placeholders)
Pages with variable URL segments:
POST /admin/assistants/{assistantId}/sitemap
Content-Type: application/json
{
"assistantInfoId": "ast_abc123",
"pathPattern": "/employees/{employeeId}/profile",
"displayName": "Employee Profile",
"category": "employees",
"description": "Detailed employee information and history",
"placeholders": [
{
"name": "employeeId",
"description": "Unique employee identifier",
"resolver": {
"toolName": "search_employees",
"inputMapping": { "param": "query" },
"outputPath": "results[0].id"
},
"searchHint": "Search by name, email, or employee ID",
"examples": ["John Doe", "john@company.com", "EMP-12345"]
}
]
}
Via MCP Admin Server (Natural Language)
With Claude Desktop + MCP Admin Server:
Add static page:
Add a sitemap entry for the dashboard at path /dashboard
Create a sitemap entry for the settings page at /settings with category "admin"
Add dynamic page:
Add a sitemap entry for employee profiles at /employees/{employeeId}/profile
Configure the employeeId placeholder to use the search_employees tool with parameter "query" and extract the ID from results[0].id
List sitemap:
Show me all sitemap entries
What navigation paths are configured for products?
Navigation Flow
How AI Navigates
User: "Open John's profile"
↓
AI calls get_sitemap(search: "profile")
↓
Finds: /employees/{employeeId}/profile
↓
Sees placeholder needs resolution
↓
Resolver says: call search_employees(query: "John")
↓
Gets results: [{ id: "emp_123", name: "John Doe" }]
↓
Extracts ID using outputPath: results[0].id → "emp_123"
↓
Constructs URL: /employees/emp_123/profile
↓
Calls navigate("/employees/emp_123/profile")
↓
User is taken to John's profile
Disambiguation
When search returns multiple results:
User: "Open John's profile"
AI calls search_employees("John")
Results: [
{ id: "emp_123", name: "John Doe", dept: "Engineering" },
{ id: "emp_456", name: "John Smith", dept: "Sales" }
]
AI asks user:
"I found multiple employees named John. Which one would you like?
1. John Doe (Engineering)
2. John Smith (Sales)"
User selects: 1
AI uses emp_123 and navigates to /employees/emp_123/profile
Categories & Hierarchy
Categories
Group related pages for better organization:
# Products category
POST /admin/assistants/{assistantId}/sitemap
{
"pathPattern": "/products",
"displayName": "Product List",
"category": "products"
}
{
"pathPattern": "/products/{productId}/details",
"displayName": "Product Details",
"category": "products"
}
# Admin category
{
"pathPattern": "/admin/users",
"displayName": "User Management",
"category": "admin"
}
Query by category:
GET /admin/assistants/{assistantId}/sitemap?category=products
Parent/Child Hierarchy
Build navigation trees:
# Parent: Dashboard
POST /admin/assistants/{assistantId}/sitemap
{
"pathPattern": "/",
"displayName": "Dashboard",
"sortOrder": 0
}
# Returns: { "id": "entry_dashboard_123" }
# Child: Analytics
{
"pathPattern": "/analytics",
"displayName": "Analytics",
"parentId": "entry_dashboard_123", # Link to parent
"sortOrder": 1
}
# Grandchild: Sales Report
{
"pathPattern": "/analytics/sales",
"displayName": "Sales Report",
"parentId": "entry_analytics_456", # Link to Analytics
"sortOrder": 0
}
Get hierarchical view:
GET /admin/assistants/{assistantId}/sitemap?hierarchical=true
Validating Configuration
Extract Placeholders from Path
Before configuring resolvers, see what placeholders exist:
POST /admin/assistants/{assistantId}/sitemap/extract-placeholders
{
"pathPattern": "/products/{productId}/reviews/{reviewId}"
}
# Response
{
"placeholders": ["productId", "reviewId"],
"pathPattern": "/products/{productId}/reviews/{reviewId}",
"count": 2
}
Validate Placeholder Configurations
Check if resolver tools exist and are configured correctly:
POST /admin/assistants/{assistantId}/sitemap/validate-placeholders
{
"assistantId": "ast_abc123",
"placeholders": [
{
"name": "productId",
"resolver": {
"toolName": "search_products",
"inputMapping": { "param": "query" },
"outputPath": "results[0].id"
}
}
]
}
# Response
{
"valid": true,
"errors": [],
"warnings": [
{
"placeholderName": "productId",
"field": "outputPath",
"message": "Cannot verify outputPath without test data. Ensure search_products returns results with id field.",
"severity": "warning"
}
]
}
Get Available Tools
See which MCP tools you can use in resolvers:
GET /admin/assistants/{assistantId}/sitemap/available-tools
# Response
{
"tools": [
{
"name": "search_employees",
"description": "Search for employees by name, email, or ID",
"serverName": "hr-system-mcp",
"inputSchema": {
"type": "object",
"properties": {
"query": { "type": "string" }
}
}
},
{
"name": "search_products",
"description": "Search products by name, SKU, or category",
"serverName": "product-mcp",
"inputSchema": {
"type": "object",
"properties": {
"query": { "type": "string" },
"category": { "type": "string" }
}
}
}
]
}
Configuration Examples
Product Catalog
{
"pathPattern": "/products/{productId}/details",
"displayName": "Product Details",
"category": "products",
"description": "View detailed product information, pricing, and specifications",
"placeholders": [
{
"name": "productId",
"description": "Product ID or SKU",
"resolver": {
"toolName": "search_products",
"inputMapping": { "param": "query" },
"outputPath": "results[0].id"
},
"searchHint": "Search by product name, SKU, or category",
"examples": ["24/7 hosting", "SKU-12345", "premium package"]
}
]
}
Customer Support
{
"pathPattern": "/support/tickets/{ticketId}",
"displayName": "Support Ticket",
"category": "support",
"description": "View and manage customer support tickets",
"placeholders": [
{
"name": "ticketId",
"description": "Support ticket number",
"resolver": {
"toolName": "search_tickets",
"inputMapping": { "param": "query" },
"outputPath": "tickets[0].ticketId"
},
"searchHint": "Search by ticket number, customer name, or issue description",
"examples": ["TKT-12345", "John's refund request", "login issue"]
}
]
}
Multi-Level Navigation
{
"pathPattern": "/projects/{projectId}/tasks/{taskId}",
"displayName": "Project Task",
"category": "projects",
"description": "View and edit project task details",
"placeholders": [
{
"name": "projectId",
"description": "Project identifier",
"resolver": {
"toolName": "search_projects",
"inputMapping": { "param": "projectName" },
"outputPath": "projects[0].id"
},
"searchHint": "Search by project name or code"
},
{
"name": "taskId",
"description": "Task identifier within the project",
"resolver": {
"toolName": "search_tasks",
"inputMapping": { "param": "taskQuery" },
"outputPath": "tasks[0].id"
},
"searchHint": "Search by task title or ID"
}
]
}
Best Practices
1. Use Descriptive Display Names
AI reads these to understand where it can navigate:
Good:
- "Employee Profile Page"
- "Product Details and Reviews"
- "Customer Order History"
Bad:
- "Page 1"
- "Employee"
- "Details"
2. Add Search Hints
Help AI understand how to query the resolver tool:
{
"searchHint": "Search by name, email, or employee ID number"
}
3. Provide Examples
Show AI what good queries look like:
{
"examples": [
"John Doe",
"john@company.com",
"EMP-12345",
"engineering department"
]
}
4. Group with Categories
Organize by functional area:
products- Product catalog pagescustomers- Customer managementadmin- Administrative functionsreports- Analytics and reportingsettings- Configuration pages
5. Keep Path Patterns RESTful
Follow REST conventions:
Good:
/products/{productId}/users/{userId}/orders/{orderId}/reports/sales
Bad:
/product?id={productId}(query params not supported)/getProduct/{id}(not RESTful)
6. Test End-to-End
After configuring:
- Ask AI: "What pages can you navigate to?"
- Try: "Open [specific item]'s page"
- Verify AI calls correct resolver
- Check final URL is correct
- Confirm navigation works
7. Handle Ambiguity
If your resolver might return multiple results:
- Return enough metadata for disambiguation
- AI will ask user to choose
- User selects, then AI navigates
Example resolver output:
{
"results": [
{ "id": "emp_123", "name": "John Doe", "dept": "Engineering", "email": "john.doe@company.com" },
{ "id": "emp_456", "name": "John Smith", "dept": "Sales", "email": "john.smith@company.com" }
]
}
AI can show: "Which John? 1. John Doe (Engineering) or 2. John Smith (Sales)"
Troubleshooting
AI Shows "UNKNOWN_PATH" Error
Symptoms: AI says "I don't know how to navigate to that page"
Cause: AI didn't call get_sitemap to discover paths
Solutions:
- Check AI system prompt includes navigation instructions
- Verify sitemap entries exist (
GET /sitemap) - Check
displayNamematches what user is asking for - Add more specific
descriptionto help AI understand
AI Shows "UNRESOLVED_PLACEHOLDER" Error
Symptoms: AI finds the path but can't fill in the placeholder
Cause: AI skipped calling the resolver tool
Solutions:
- Verify resolver
toolNamematches actual MCP tool - Check
searchHintprovides clear guidance - Ensure
inputMapping.parammatches tool's parameter name - Test resolver tool directly to confirm it works
Wrong Page Opened
Symptoms: AI navigates to wrong item (wrong ID)
Cause: outputPath extraction is incorrect
Solutions:
- Check resolver tool's actual response structure
- Verify
outputPathJSONPath is correct - Test:
results[0].idvsdata.idvsitems[0].productId - Call resolver tool manually to see response format
AI Can't Find Page Even Though It Exists
Symptoms: User asks for a page, AI says it doesn't exist
Cause: displayName or description doesn't match user's language
Solutions:
- Add more descriptive
displayName: "Employee Profile" → "Employee Profile and Information Page" - Add helpful
description: "View employee details, contact info, and employment history" - Use common terminology: If users say "customer" not "client", use "customer" in display names
- Add multiple sitemap entries for the same path with different display names (if needed)
API Reference
| Method | Endpoint | Description |
|---|---|---|
POST | /admin/assistants/{id}/sitemap | Create sitemap entry |
GET | /admin/assistants/{id}/sitemap | List entries (supports filters) |
GET | /admin/assistants/{id}/sitemap/{entryId} | Get specific entry |
PATCH | /admin/assistants/{id}/sitemap/{entryId} | Update entry |
DELETE | /admin/assistants/{id}/sitemap/{entryId} | Delete entry |
POST | /admin/assistants/{id}/sitemap/extract-placeholders | Extract placeholders from path |
POST | /admin/assistants/{id}/sitemap/validate-placeholders | Validate resolver configs |
GET | /admin/assistants/{id}/sitemap/available-tools | List available MCP tools |
Sitemap Entry Fields
| Field | Type | Required | Description |
|---|---|---|---|
pathPattern | string | Yes | URL pattern with {placeholders} |
displayName | string | Yes | Human-readable page name |
description | string | No | Context about the page |
category | string | No | Group pages (products, admin, etc.) |
placeholders | array | No | Resolver configs for dynamic segments |
parentId | string | No | Parent entry ID for hierarchy |
sortOrder | number | No | Display order (default: 0) |
isActive | boolean | No | Enable/disable entry (default: true) |
Placeholder Config Fields
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Placeholder name (matches {name} in path) |
description | string | No | What this placeholder represents |
resolver.toolName | string | Yes | MCP tool to call |
resolver.inputMapping.param | string | Yes | Tool parameter name |
resolver.outputPath | string | Yes | JSONPath to extract ID from response |
searchHint | string | No | Guide for AI on how to query |
examples | string[] | No | Example search queries |
Previous: Approval Policies
Next: Administrator Guides Index