Skip to main content
Glama

createPage

Generate a new Adobe Experience Manager (AEM) page by specifying parent path, title, and template via AEM MCP Server's REST/JSON-RPC APIs for streamlined content management.

Instructions

Create a new page in AEM

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
nameNo
parentPathYes
propertiesNo
templateYes
titleYes

Implementation Reference

  • MCP tool registration defining the createPage tool with description and input schema validation.
    name: 'createPage', description: 'Create a new page in AEM', inputSchema: { type: 'object', properties: { parentPath: { type: 'string' }, title: { type: 'string' }, template: { type: 'string' }, name: { type: 'string' }, properties: { type: 'object' }, }, required: ['parentPath', 'title', 'template'], }, },
  • MCP server CallToolRequestSchema handler for createPage, delegates execution to AEMConnector.
    case 'createPage': { const result = await aemConnector.createPage(args); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
  • AEMConnector.createPage wrapper method that invokes the detailed template-aware implementation.
    async createPage(request) { // Use the enhanced createPageWithTemplate method return this.createPageWithTemplate(request); }
  • Core handler implementation: validates input, auto-selects template if missing, creates cq:Page and jcr:content nodes, sets template and properties, verifies creation and accessibility.
    async createPageWithTemplate(request) { return safeExecute(async () => { const { parentPath, title, template, name, properties = {} } = request; if (!isValidContentPath(parentPath, this.aemConfig)) { throw createAEMError(AEM_ERROR_CODES.INVALID_PARAMETERS, `Invalid parent path: ${String(parentPath)}`, { parentPath }); } // If no template provided, get available templates and prompt user let selectedTemplate = template; if (!selectedTemplate) { const templatesResponse = await this.getAvailableTemplates(parentPath); const availableTemplates = templatesResponse.data.availableTemplates; if (availableTemplates.length === 0) { throw createAEMError(AEM_ERROR_CODES.INVALID_PARAMETERS, 'No templates available for this path', { parentPath }); } // For now, select the first available template // In a real implementation, this would prompt the user selectedTemplate = availableTemplates[0].path; console.log(`🎯 Auto-selected template: ${selectedTemplate} (${availableTemplates[0].title})`); } // Validate template exists const client = this.createAxiosInstance(); try { await client.get(`${selectedTemplate}.json`); } catch (error) { if (error.response?.status === 404) { throw createAEMError(AEM_ERROR_CODES.INVALID_PARAMETERS, `Template not found: ${selectedTemplate}`, { template: selectedTemplate }); } throw handleAEMHttpError(error, 'createPageWithTemplate'); } const pageName = name || title.replace(/[^a-zA-Z0-9-_]/g, '-').toLowerCase(); const newPagePath = `${parentPath}/${pageName}`; // Create page with proper structure const pageData = { 'jcr:primaryType': 'cq:Page', 'jcr:content': { 'jcr:primaryType': 'cq:PageContent', 'jcr:title': title, 'cq:template': selectedTemplate, 'sling:resourceType': 'foundation/components/page', // Remove protected properties that are managed by the repository // 'jcr:createdBy': 'mcp-server', // 'jcr:created': new Date().toISOString(), 'cq:lastModified': new Date().toISOString(), 'cq:lastModifiedBy': 'admin', // Use the authenticated user instead ...properties } }; // Create the page using Sling POST servlet const formData = new URLSearchParams(); formData.append('jcr:primaryType', 'cq:Page'); // Create page first await client.post(newPagePath, formData, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }); // Then create jcr:content node const contentFormData = new URLSearchParams(); Object.entries(pageData['jcr:content']).forEach(([key, value]) => { // Skip protected JCR properties if (key === 'jcr:created' || key === 'jcr:createdBy') { return; } if (typeof value === 'object') { contentFormData.append(key, JSON.stringify(value)); } else { contentFormData.append(key, String(value)); } }); await client.post(`${newPagePath}/jcr:content`, contentFormData, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }); // Verify page creation const verificationResponse = await client.get(`${newPagePath}.json`); const hasJcrContent = verificationResponse.data['jcr:content'] !== undefined; // Check if page is accessible in author mode let pageAccessible = false; try { const authorResponse = await client.get(`${newPagePath}.html`, { validateStatus: (status) => status < 500 }); pageAccessible = authorResponse.status === 200; } catch (error) { pageAccessible = false; } // Check AEM error logs (simplified check) const errorLogCheck = { hasErrors: false, errors: [] }; return createSuccessResponse({ success: true, pagePath: newPagePath, title, templateUsed: selectedTemplate, jcrContentCreated: hasJcrContent, pageAccessible, errorLogCheck, creationDetails: { timestamp: new Date().toISOString(), steps: [ 'Template validation completed', 'Page node created', 'jcr:content node created', 'Page structure verified', 'Accessibility check completed' ] }, pageStructure: verificationResponse.data }, 'createPageWithTemplate'); }, 'createPageWithTemplate'); }

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/indrasishbanerjee/aem-mcp-server'

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