@myea/aem-mcp-handler
Version:
Advanced AEM MCP request handler with intelligent search, multi-locale support, and comprehensive content management capabilities
146 lines (145 loc) ⢠4.98 kB
JavaScript
#!/usr/bin/env node
import express from 'express';
import cors from 'cors';
import { AEMConnector } from './aem-connector.js';
import { MCPRequestHandler } from './mcp-handler.js';
import dotenv from 'dotenv';
dotenv.config();
const app = express();
const PORT = parseInt(process.env.MCP_PORT || '8080', 10);
// Middleware
app.use(cors());
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true }));
// Basic auth middleware for security
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',
timestamp: new Date().toISOString(),
version: process.env.npm_package_version || '1.0.0'
});
}
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 });
}
});
// Start server
async function startServer() {
console.error('š Starting AEM MCP HTTP Server...');
// Test AEM connection first
console.log('š Testing AEM connectivity...');
const isConnected = await aemConnector.testConnection();
if (!isConnected) {
console.log('ā AEM connection failed! Server will start but AEM operations may not work.');
console.log(' Check your AEM instance and credentials.');
}
else {
console.log('ā
AEM connection successful!');
}
app.listen(PORT, () => {
console.error('š AEM MCP HTTP Server');
console.error('================================');
console.error(`š Server running at: http://localhost:${PORT}`);
console.error(`š Health check: http://localhost:${PORT}/health`);
console.error(`š§ MCP Methods: http://localhost:${PORT}/mcp/methods`);
console.error(`š” MCP Endpoint: http://localhost:${PORT}/mcp`);
console.error('================================');
});
}
// Handle graceful shutdown
process.on('SIGINT', () => {
console.error('\nš Shutting down AEM MCP server...');
process.exit(0);
});
process.on('SIGTERM', () => {
console.error('\nš Shutting down AEM MCP server...');
process.exit(0);
});
// Start the server
startServer().catch((error) => {
console.error('Failed to start server:', error);
process.exit(1);
});