@myea/aem-mcp-handler
Version:
Advanced AEM MCP request handler with intelligent search, multi-locale support, and comprehensive content management capabilities
241 lines (240 loc) ⢠8.97 kB
JavaScript
#!/usr/bin/env node
import express from 'express';
import cors from 'cors';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
import { AEMConnector } from './aem-connector.js';
import { MCPRequestHandler } from './mcp-handler.js';
import llmRouter from './llm-integration.js';
import telegramIntegration from './telegram-integration.js';
import dotenv from 'dotenv';
dotenv.config();
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const app = express();
const MCP_PORT = parseInt(process.env.MCP_PORT || '8080', 10);
const GATEWAY_PORT = parseInt(process.env.GATEWAY_PORT || '3000', 10);
// Middleware
app.use(cors());
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true }));
// Serve static files from public directory
app.use(express.static(join(__dirname, '../public')));
// Basic auth middleware for MCP endpoints if credentials are configured
const basicAuth = (req, res, next) => {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Basic ')) {
res.status(401).json({ error: 'Authentication required' });
return;
}
const credentials = Buffer.from(authHeader.slice(6), 'base64').toString();
const [username, password] = credentials.split(':');
const validUsername = process.env.MCP_USERNAME || 'admin';
const validPassword = process.env.MCP_PASSWORD || 'admin';
if (username !== validUsername || password !== validPassword) {
res.status(401).json({ error: 'Invalid credentials' });
return;
}
next();
};
// Apply auth to MCP endpoints if credentials are configured
if (process.env.MCP_USERNAME && process.env.MCP_PASSWORD) {
app.use('/mcp', basicAuth);
}
// Initialize AEM connector and MCP handler
const aemConnector = new AEMConnector();
const mcpHandler = new MCPRequestHandler(aemConnector);
// Health check endpoint
app.get('/health', async (req, res) => {
try {
const aemConnected = await aemConnector.testConnection();
res.json({
status: 'healthy',
aem: aemConnected ? 'connected' : 'disconnected',
mcp: 'ready',
chatgpt: !!process.env.OPENAI_API_KEY,
timestamp: new Date().toISOString(),
version: process.env.npm_package_version || '1.0.0',
ports: {
gateway: GATEWAY_PORT,
mcp: MCP_PORT
}
});
}
catch (error) {
res.status(500).json({
status: 'unhealthy',
error: error.message,
timestamp: new Date().toISOString()
});
}
});
// MCP JSON-RPC endpoint
app.post('/mcp', async (req, res) => {
try {
const { jsonrpc, id, method, params } = req.body;
// Validate JSON-RPC format
if (jsonrpc !== '2.0' || !method) {
res.status(400).json({
jsonrpc: '2.0',
id: id || null,
error: {
code: -32600,
message: 'Invalid Request',
data: 'Must be valid JSON-RPC 2.0'
}
});
return;
}
console.error(`[MCP] ${method}:`, params ? JSON.stringify(params).substring(0, 100) + '...' : 'no params');
const result = await mcpHandler.handleRequest(method, params || {});
res.json({
jsonrpc: '2.0',
id: id || null,
result
});
}
catch (error) {
console.error(`[MCP] Error:`, error);
res.json({
jsonrpc: '2.0',
id: req.body?.id || null,
error: {
code: -32000,
message: error.message || 'Internal error',
data: error.stack
}
});
}
});
// List available MCP methods
app.get('/mcp/methods', async (req, res) => {
try {
const methods = mcpHandler.getAvailableMethods();
res.json({
methods,
total: methods.length,
timestamp: new Date().toISOString()
});
}
catch (error) {
res.status(500).json({ error: error.message });
}
});
// LLM Integration endpoints
app.use('/api', llmRouter);
// Telegram Integration endpoints
app.use('/webhook', telegramIntegration);
// Root endpoint with API documentation
app.get('/', (req, res) => {
res.json({
name: 'AEM MCP Gateway Server',
description: 'A Model Context Protocol server for Adobe Experience Manager with ChatGPT and Telegram Bot integration',
version: process.env.npm_package_version || '1.0.0',
endpoints: {
health: {
method: 'GET',
path: '/health',
description: 'Health check for all services'
},
mcp: {
method: 'POST',
path: '/mcp',
description: 'JSON-RPC endpoint for MCP calls',
example: {
jsonrpc: '2.0',
id: 1,
method: 'fetchSites',
params: {}
}
},
mcpMethods: {
method: 'GET',
path: '/mcp/methods',
description: 'List all available MCP methods'
},
chatgpt: {
method: 'POST',
path: '/api/chat',
description: 'Natural language interface to AEM via ChatGPT',
example: {
message: 'What sites are available in AEM?',
conversationHistory: []
}
},
chatgptHealth: {
method: 'GET',
path: '/api/health',
description: 'Health check for ChatGPT integration'
},
telegram: {
method: 'POST',
path: '/webhook/telegram',
description: 'Telegram bot webhook endpoint'
},
telegramStatus: {
method: 'GET',
path: '/webhook/telegram/status',
description: 'Telegram bot status endpoint'
},
telegramWebhook: {
method: 'POST',
path: '/webhook/telegram/webhook',
description: 'Setup Telegram webhook'
}
},
architecture: 'Telegram Bot + ChatGPT + MCP integration',
timestamp: new Date().toISOString()
});
});
// Start server
async function startGateway() {
console.error('š Starting AEM MCP Gateway Server...');
console.error('Architecture: Telegram Bot + ChatGPT + MCP integration');
console.error('================================');
// Test AEM connection first
console.error('š Testing AEM connectivity...');
// const isConnected = await aemConnector.testConnection();
// if (!isConnected) {
// console.error('ā AEM connection failed! Server will start but AEM operations may not work.');
// console.error(' Check your AEM instance and credentials.');
// } else {
// console.error('ā
AEM connection successful!');
// }
// Check ChatGPT configuration
if (process.env.OPENAI_API_KEY) {
console.error('ā
OpenAI API key configured');
}
else {
console.error('ā ļø OpenAI API key not configured - ChatGPT features disabled');
}
app.listen(GATEWAY_PORT, () => {
console.error('š AEM MCP Gateway Server');
console.error('================================');
console.error(`š Gateway Server: http://localhost:${GATEWAY_PORT}`);
console.error(`š Health Check: http://localhost:${GATEWAY_PORT}/health`);
console.error(`š” MCP Endpoint: http://localhost:${GATEWAY_PORT}/mcp`);
console.error(`š§ MCP Methods: http://localhost:${GATEWAY_PORT}/mcp/methods`);
console.error(`š¬ ChatGPT API: http://localhost:${GATEWAY_PORT}/api/chat`);
console.error(`š¤ Telegram Webhook: http://localhost:${GATEWAY_PORT}/webhook/telegram`);
console.error(`šÆ API Health: http://localhost:${GATEWAY_PORT}/api/health`);
console.error(`š Telegram Status: http://localhost:${GATEWAY_PORT}/webhook/telegram/status`);
console.error('================================');
console.error(`š API Documentation: http://localhost:${GATEWAY_PORT}`);
console.error('�� Ready for ChatGPT, Telegram Bot and MCP clients!');
});
}
// Handle graceful shutdown
process.on('SIGINT', () => {
console.error('\nš Shutting down AEM MCP Gateway...');
process.exit(0);
});
process.on('SIGTERM', () => {
console.error('\nš Shutting down AEM MCP Gateway...');
process.exit(0);
});
// Start the gateway
startGateway().catch((error) => {
console.error('Failed to start gateway:', error);
process.exit(1);
});