Package Exports
- @myea/aem-mcp-handler
- @myea/aem-mcp-handler/aem-connector
Readme
AEM MCP Handler
Advanced Adobe Experience Manager (AEM) request handler with intelligent search, multi-locale support, and comprehensive content management capabilities for AI integrations.
๐ Features
- Intelligent Search: Advanced fuzzy matching and cross-section path generation
- Multi-Locale Support: Automatic discovery and search across language variants
- Comprehensive AEM Operations: Full CRUD operations for pages, components, and assets
- Smart Path Resolution: Automatic site structure discovery and path suggestions
- Validation & Feedback Loops: Built-in result validation and search optimization
- Enterprise Ready: Supports complex AEM architectures and workflows
๐ Quick Setup for Claude Desktop
Connect Claude AI directly to your AEM instance!
Step 1: Install the Handler
npm install -g @myea/aem-mcp-handlerStep 2: Configure Claude Desktop
On Mac:
- Open Claude Desktop
- Go to Settings (Claude Desktop โ Settings)
- Click Developer tab
- Edit the MCP servers configuration file, or create it at:
~/Library/Application Support/Claude/claude_desktop_config.json
On Windows:
- Open Claude Desktop
- Go to Settings (File โ Settings or Ctrl+Comma)
- Click Developer tab
- Edit the MCP servers configuration file, or create it at:
%APPDATA%\Claude\claude_desktop_config.json
Step 3: Add Configuration
Add this configuration to your claude_desktop_config.json:
{
"mcpServers": {
"aem-mcp-handler": {
"command": "aem-mcp-server",
"env": {
"AEM_HOST": "http://localhost:4502",
"AEM_SERVICE_USER": "admin",
"AEM_SERVICE_PASSWORD": "admin",
"AEM_TIMEOUT": "30000"
}
}
}
}Step 4: Restart Claude Desktop
Important: Completely quit and restart Claude Desktop for the changes to take effect.
Step 5: Test the Connection
Ask Claude: "Can you search for pages in my AEM instance?"
Claude should now be able to:
- ๐ Search your AEM content
- ๐ List pages and components
- ๐ Get page properties and content
- ๐ง Update component properties
- ๐ Provide detailed content analysis
๐ Troubleshooting & Logs
Where to Find Logs
Mac Logs Location:
~/Library/Logs/Claude/mcp.logWindows Logs Location:
%LOCALAPPDATA%\Claude\logs\mcp.logView Live Logs
Mac:
tail -f ~/Library/Logs/Claude/mcp.logWindows (PowerShell):
Get-Content "$env:LOCALAPPDATA\Claude\logs\mcp.log" -Wait -Tail 10Common Issues
โ "Cannot connect to AEM"
- Check if your AEM instance is running at the specified host
- Verify credentials are correct
- Ensure firewall/network allows connection
โ "Command not found: aem-mcp-server"
# Reinstall globally
npm uninstall -g @myea/aem-mcp-handler
npm install -g @myea/aem-mcp-handlerโ "Environment variables not working"
- Restart Claude Desktop completely
- Check JSON syntax in config file
- Verify file permissions
โ "No results found"
- Check AEM content exists at specified paths
- Try broader search terms
- Verify user permissions in AEM
Test AEM Connection Manually
# Test if AEM is accessible
curl -u admin:admin http://localhost:4502/libs/granite/core/content/login.html -I
# Test content access
curl -u admin:admin "http://localhost:4502/content.1.json"๐ฆ Installation
npm install @venkatesh/aem-mcp-handler๐ง Quick Setup
1. Environment Configuration
Create a .env file in your project:
# AEM Instance Configuration
AEM_HOST=http://localhost:4502
AEM_USERNAME=admin
AEM_PASSWORD=admin
# Optional: Timeout settings
AEM_TIMEOUT=300002. Basic Usage
import { MCPRequestHandler } from '@venkatesh/aem-mcp-handler';
import { AEMConnector } from '@venkatesh/aem-mcp-handler/aem-connector';
// Initialize the connector
const aemConnector = new AEMConnector({
host: process.env.AEM_HOST || 'http://localhost:4502',
username: process.env.AEM_USERNAME,
password: process.env.AEM_PASSWORD,
timeout: parseInt(process.env.AEM_TIMEOUT || '30000')
});
// Initialize the MCP handler
const mcpHandler = new MCPRequestHandler(aemConnector);
// Example: Search for content
const searchResults = await mcpHandler.handleRequest('search', {
searchTerm: 'homepage',
basePath: '/content/mysite'
});
console.log('Search Results:', searchResults);๐ Available Methods
Content Search & Discovery
// Comprehensive content search with intelligent path discovery
await mcpHandler.handleRequest('search', {
searchTerm: 'product page',
basePath: '/content/mysite',
limit: 10
});
// Enhanced page search with fuzzy matching
await mcpHandler.handleRequest('searchPages', {
searchTerm: 'about us',
basePath: '/content/mysite'
});
// List all pages in a site
await mcpHandler.handleRequest('listPages', {
siteRoot: '/content/mysite',
depth: 2,
limit: 50
});Content Management
// Get page or component content
await mcpHandler.handleRequest('getContent', {
path: '/content/mysite/en/homepage',
depth: 2
});
// Update component properties
await mcpHandler.handleRequest('updateComponent', {
path: '/content/mysite/en/homepage/jcr:content/hero',
properties: {
title: 'New Hero Title',
description: 'Updated description'
}
});
// Validate component before update
await mcpHandler.handleRequest('validateComponent', {
path: '/content/mysite/en/homepage/jcr:content/hero',
properties: {
title: 'New Title'
}
});Asset Management
// Search for assets
await mcpHandler.handleRequest('searchAssets', {
searchTerm: 'logo',
basePath: '/content/dam'
});
// Get asset metadata
await mcpHandler.handleRequest('getAssetMetadata', {
assetPath: '/content/dam/images/logo.png'
});Workflow & Publishing
// Get workflow status
await mcpHandler.handleRequest('getWorkflowStatus', {
workflowId: 'workflow-123'
});
// Check page activation status
await mcpHandler.handleRequest('getActivationStatus', {
pagePath: '/content/mysite/en/homepage'
});๐ฏ Use Cases
1. Chatbot Integration
import { MCPRequestHandler } from '@venkatesh/aem-mcp-handler';
class AEMChatbot {
constructor(private mcpHandler: MCPRequestHandler) {}
async handleUserQuery(userMessage: string) {
// Extract intent and parameters from user message
const intent = this.extractIntent(userMessage);
switch (intent.type) {
case 'search':
return await this.mcpHandler.handleRequest('search', {
searchTerm: intent.searchTerm,
basePath: intent.basePath || '/content'
});
case 'update':
return await this.mcpHandler.handleRequest('updateComponent', {
path: intent.componentPath,
properties: intent.properties
});
default:
return { error: 'Intent not recognized' };
}
}
}2. Content Migration Tool
async function migrateContent(sourceInstance: MCPRequestHandler, targetInstance: MCPRequestHandler) {
// Get all pages from source
const pages = await sourceInstance.handleRequest('listPages', {
siteRoot: '/content/oldsite',
depth: 5
});
for (const page of pages.results) {
// Get content from source
const content = await sourceInstance.handleRequest('getContent', {
path: page.path,
depth: 3
});
// Create/update in target
await targetInstance.handleRequest('updateComponent', {
path: page.path.replace('/oldsite/', '/newsite/'),
properties: content.properties
});
}
}3. Multi-Locale Content Sync
async function syncContentAcrossLocales(handler: MCPRequestHandler) {
const masterContent = await handler.handleRequest('getContent', {
path: '/content/mysite/language-masters/en/homepage'
});
const locales = ['de', 'fr', 'es', 'it'];
for (const locale of locales) {
await handler.handleRequest('updateComponent', {
path: `/content/mysite/language-masters/${locale}/homepage`,
properties: {
...masterContent.properties,
// Keep locale-specific fields
title: await translateTitle(masterContent.properties.title, locale)
}
});
}
}๐ Advanced Search Features
The handler includes sophisticated search capabilities:
Cross-Section Path Generation
Automatically discovers and searches across:
- Language masters (
/language-masters/en,/language-masters/de) - Country/locale combinations (
/us/en,/de/de,/ca/fr) - Direct locale paths (
/en,/fr,/es)
Fuzzy Matching
- Levenshtein distance calculation
- Term variation generation (camelCase, kebab-case, etc.)
- Similarity scoring and ranking
Validation & Feedback
- Result validation with confidence scoring
- Automatic retry logic for low-confidence results
- Comprehensive search reporting
๐ ๏ธ Configuration Options
AEM Connector Options
const connector = new AEMConnector({
host: 'https://author.mysite.com',
username: 'service-user',
password: 'secure-password',
timeout: 30000,
retryAttempts: 3,
retryDelay: 1000
});Search Configuration
await mcpHandler.handleRequest('search', {
searchTerm: 'product',
basePath: '/content/mysite',
limit: 20,
includeInactive: false,
searchDepth: 5,
fuzzyThreshold: 0.7
});๐ Response Formats
Search Response
{
success: true,
results: [
{
path: '/content/mysite/en/products',
title: 'Products Page',
lastModified: '2024-01-15T10:30:00Z',
score: 0.95
}
],
searchReport: {
strategiesUsed: ['enhanced', 'fuzzy', 'cross-section'],
pathsExplored: ['/content/mysite/en', '/content/mysite/de'],
totalAttempts: 3,
confidence: 0.89,
coverage: 'comprehensive'
},
total: 1
}Content Response
{
success: true,
content: {
'jcr:primaryType': 'cq:Page',
'jcr:content': {
'jcr:title': 'Homepage',
'sling:resourceType': 'mysite/components/page',
// ... other properties
}
},
metadata: {
lastModified: '2024-01-15T10:30:00Z',
lastModifiedBy: 'admin'
}
}๐ Security Considerations
- Use service users with minimal required permissions
- Store credentials securely (environment variables, vault systems)
- Implement proper authentication for production instances
- Validate all input parameters to prevent injection attacks
๐งช Testing
# Run all tests
npm test
# Run with coverage
npm run test:coverage
# Run specific test suites
npm run test:unit
npm run test:integration๐ Performance Tips
- Use specific base paths: Narrow down search scope for better performance
- Set appropriate limits: Avoid large result sets that may timeout
- Cache frequently accessed content: Implement caching layer for repeated queries
- Use batch operations: Group multiple updates when possible
๐ค Contributing
- Fork the repository
- Create a feature branch:
git checkout -b feature/new-feature - Commit changes:
git commit -am 'Add new feature' - Push to branch:
git push origin feature/new-feature - Submit a Pull Request
๐ License
MIT License - see LICENSE file for details.
๐ Support
- Issues: GitHub Issues
- Documentation: Full API Documentation
- Examples: Code Examples
๐ Migration Guide
From Direct AEM API Calls
Replace direct axios calls:
// Before
const response = await axios.get(`${aemHost}/content/mysite.2.json`);
// After
const response = await mcpHandler.handleRequest('getContent', {
path: '/content/mysite',
depth: 2
});From Other AEM Libraries
The MCP Handler provides enhanced search and multi-locale support not available in basic AEM connectors, making it ideal for AI-powered applications and complex content management scenarios.