This commit is contained in:
nasir@endelospay.com
2025-07-11 20:22:12 +05:00
commit 8c74b0e23f
120 changed files with 206874 additions and 0 deletions

426
http-tools-server.js Normal file
View File

@@ -0,0 +1,426 @@
#!/usr/bin/env node
/**
* HTTP server with MCP tool execution support
*/
import dotenv from "dotenv";
import express from "express";
import cors from "cors";
// Load environment variables from .env file
dotenv.config();
console.log("🔧 Environment variables loaded:");
console.log(
` LARAVEL_API_BASE_URL: ${process.env.LARAVEL_API_BASE_URL || "NOT SET"}`
);
console.log(` MCP_SERVER_PORT: ${process.env.MCP_SERVER_PORT || "NOT SET"}`);
console.log(` MCP_SERVER_HOST: ${process.env.MCP_SERVER_HOST || "NOT SET"}`);
console.log("");
// Set default values if not provided
process.env.LARAVEL_API_BASE_URL =
process.env.LARAVEL_API_BASE_URL || "https://example.com";
console.log("🚀 Starting Laravel Healthcare MCP HTTP Server with Tools...");
const app = express();
const port = process.env.MCP_SERVER_PORT || 3000;
const host = process.env.MCP_SERVER_HOST || "0.0.0.0";
// Middleware
app.use(cors());
app.use(express.json({ limit: "10mb" }));
// Initialize MCP components
let toolGenerator = null;
let authManager = null;
async function initializeMCP() {
try {
console.log("📋 Initializing MCP components...");
const { ConfigManager } = await import("./src/config/ConfigManager.js");
const { AuthManager } = await import("./src/auth/AuthManager.js");
const { ApiClient } = await import("./src/proxy/ApiClient.js");
const { ToolGenerator } = await import("./src/tools/ToolGenerator.js");
const config = new ConfigManager();
authManager = new AuthManager(null, config.getAll(true));
const apiClient = new ApiClient(config.getAll(), authManager);
toolGenerator = new ToolGenerator(apiClient);
console.log("✅ MCP components initialized");
return true;
} catch (error) {
console.error("❌ Failed to initialize MCP:", error.message);
return false;
}
}
// Health endpoint
app.get("/health", (req, res) => {
res.json({
status: "healthy",
timestamp: new Date().toISOString(),
server: "Laravel Healthcare MCP Server",
port: port,
mcpInitialized: toolGenerator !== null,
});
});
// List all tools
app.get("/tools", (req, res) => {
try {
if (!toolGenerator) {
return res.status(500).json({ error: "MCP not initialized" });
}
const tools = toolGenerator.generateAllTools();
const toolsWithDetails = tools.map((tool) => {
const toolDef = toolGenerator.getTool(tool.name);
return {
name: tool.name,
description: tool.description,
authType: toolDef?.authType,
method: toolDef?.endpoint?.method,
path: toolDef?.endpoint?.path,
inputSchema: tool.inputSchema,
};
});
res.json({
total: toolsWithDetails.length,
tools: toolsWithDetails,
});
} catch (error) {
console.error("Failed to list tools:", error);
res.status(500).json({ error: error.message });
}
});
// Get specific tool
app.get("/tools/:toolName", (req, res) => {
try {
if (!toolGenerator) {
return res.status(500).json({ error: "MCP not initialized" });
}
const { toolName } = req.params;
const tool = toolGenerator.getTool(toolName);
if (!tool) {
return res.status(404).json({ error: "Tool not found" });
}
res.json({
name: tool.name,
description: tool.description,
authType: tool.authType,
endpoint: tool.endpoint,
inputSchema: tool.inputSchema,
});
} catch (error) {
console.error("Failed to get tool:", error);
res.status(500).json({ error: error.message });
}
});
// Execute MCP tool
app.post("/tools/:toolName/execute", async (req, res) => {
const { toolName } = req.params;
const parameters = req.body;
try {
if (!toolGenerator) {
return res.status(500).json({ error: "MCP not initialized" });
}
console.log(`🔧 Executing tool: ${toolName}`);
console.log(`📝 Parameters:`, JSON.stringify(parameters, null, 2));
// Get all tools and find the one we want
const allTools = toolGenerator.generateAllTools();
const toolDef = allTools.find((tool) => tool.name === toolName);
if (!toolDef) {
console.log(`❌ Tool ${toolName} not found in generated tools`);
return res.status(404).json({ error: "Tool not found" });
}
console.log(`🔍 Found tool: ${toolDef.name}`);
// Get the actual tool implementation
const tool = toolGenerator.getTool(toolName);
console.log(tool);
if (!tool || !tool.execute) {
console.log(`❌ Tool ${toolName} has no execute method`);
return res
.status(500)
.json({ error: "Tool execution method not available" });
}
console.log(`🚀 Executing tool...`);
const result = await tool.execute(parameters);
console.log(`✅ Tool ${toolName} executed successfully`);
console.log(`📊 Result:`, JSON.stringify(result, null, 2));
// Special handling for login tools - extract and store token
if (toolName === "public_manage_login" && result && authManager) {
try {
let token = null;
let expiresIn = 3600; // Default 1 hour
let userData = null;
// Extract token from different possible response formats
if (result.accessToken || result.access_token || result.token) {
token = result.accessToken || result.access_token || result.token;
expiresIn = result.expiresIn || result.expires_in || 3600;
userData = result.userData || result.user || result.data || null;
} else if (result.data) {
// Token might be nested in data object
token =
result.data.accessToken ||
result.data.access_token ||
result.data.token;
expiresIn = result.data.expiresIn || result.data.expires_in || 3600;
userData = result.data.userData || result.data.user || null;
}
if (token) {
// Store token for provider auth type
authManager.setToken("provider", token, expiresIn, userData);
console.log(
`🔑 Stored bearer token for provider authentication (expires in ${expiresIn}s)`
);
// Add token info to response
result._tokenInfo = {
stored: true,
authType: "provider",
expiresIn: expiresIn,
message: "Token automatically stored for provider endpoints",
};
} else {
console.log(`⚠️ No token found in login response`);
}
} catch (error) {
console.error(
`❌ Failed to store token from login response:`,
error.message
);
}
}
res.json({
success: true,
toolName,
result,
});
} catch (error) {
console.error(`❌ Tool execution failed for ${toolName}:`, error.message);
console.error(`📋 Error stack:`, error.stack);
res.status(error.status || 500).json({
success: false,
toolName,
error: error.message,
details: error.details || null,
stack: error.stack,
});
}
});
// Server stats
app.get("/stats", (req, res) => {
try {
if (!toolGenerator) {
return res.status(500).json({ error: "MCP not initialized" });
}
const tools = toolGenerator.generateAllTools();
const publicTools = tools.filter((tool) => {
const toolDef = toolGenerator.getTool(tool.name);
return toolDef?.authType === "public";
});
const providerTools = tools.filter((tool) => {
const toolDef = toolGenerator.getTool(tool.name);
return toolDef?.authType === "provider";
});
res.json({
server: {
name: "Laravel Healthcare MCP Server",
version: "1.0.0",
uptime: process.uptime(),
memory: process.memoryUsage(),
},
tools: {
total: tools.length,
public: publicTools.length,
provider: providerTools.length,
},
config: {
port: port,
host: host,
apiUrl: process.env.LARAVEL_API_BASE_URL,
},
authentication: {
hasProviderToken: authManager
? authManager.getCacheStats().keys?.includes("token_provider") ||
false
: false,
},
});
} catch (error) {
console.error("Failed to get stats:", error);
res.status(500).json({ error: error.message });
}
});
// Set bearer token manually
app.post("/auth/set-token", (req, res) => {
try {
if (!authManager) {
return res.status(500).json({ error: "Auth manager not initialized" });
}
const {
authType = "provider",
token,
expiresIn = 3600,
userData = null,
} = req.body;
if (!token) {
return res.status(400).json({ error: "Token is required" });
}
authManager.setToken(authType, token, expiresIn, userData);
res.json({
success: true,
message: `Token set for ${authType}`,
authType,
expiresIn,
});
} catch (error) {
console.error("Failed to set token:", error);
res.status(500).json({ error: error.message });
}
});
// Get auth status
app.get("/auth/status", (req, res) => {
try {
if (!authManager) {
return res.status(500).json({ error: "Auth manager not initialized" });
}
const cacheStats = authManager.getCacheStats();
const hasProviderToken =
cacheStats.keys?.includes("token_provider") || false;
res.json({
authManager: "initialized",
cacheStats,
tokens: {
provider: hasProviderToken ? "present" : "missing",
},
});
} catch (error) {
console.error("Failed to get auth status:", error);
res.status(500).json({ error: error.message });
}
});
// 404 handler
app.use("*", (req, res) => {
res.status(404).json({
error: "Endpoint not found",
availableEndpoints: [
"GET /health",
"GET /tools",
"GET /tools/:toolName",
"POST /tools/:toolName/execute",
"GET /stats",
"POST /auth/set-token",
"GET /auth/status",
],
});
});
// Error handler
app.use((error, req, res, next) => {
console.error("HTTP server error:", error);
res.status(500).json({
error: "Internal server error",
message: error.message,
});
});
// Initialize and start server
async function startServer() {
const mcpReady = await initializeMCP();
if (!mcpReady) {
console.error("❌ Cannot start server without MCP initialization");
process.exit(1);
}
const server = app.listen(port, host, () => {
const serverUrl = `http://${
host === "0.0.0.0" ? "localhost" : host
}:${port}`;
console.log("\n" + "=".repeat(60));
console.log("🚀 LARAVEL HEALTHCARE MCP SERVER - HTTP MODE");
console.log("=".repeat(60));
console.log(`📡 Server URL: ${serverUrl}`);
console.log(`🌐 Host: ${host}`);
console.log(`🔌 Port: ${port}`);
console.log(`🔗 API URL: ${process.env.LARAVEL_API_BASE_URL}`);
console.log("=".repeat(60));
console.log("📋 Available Endpoints:");
console.log(` • Health Check: ${serverUrl}/health`);
console.log(` • Tools List: ${serverUrl}/tools`);
console.log(` • Server Stats: ${serverUrl}/stats`);
console.log(
` • Tool Execute: POST ${serverUrl}/tools/{toolName}/execute`
);
console.log("=".repeat(60));
console.log("📊 Server Status: READY");
console.log(`⏰ Started at: ${new Date().toLocaleString()}`);
console.log("=".repeat(60));
console.log("💡 Press Ctrl+C to stop the server");
console.log("");
console.log("🧪 Test login tool:");
console.log(
` curl -X POST ${serverUrl}/tools/public_manage_login/execute \\`
);
console.log(` -H "Content-Type: application/json" \\`);
console.log(
` -d '{"email": "test@example.com", "password": "password"}'`
);
console.log("");
});
// Graceful shutdown
const shutdown = (signal) => {
console.log(`\n🛑 Received ${signal}, shutting down HTTP server...`);
server.close(() => {
console.log("✅ HTTP server stopped");
process.exit(0);
});
};
process.on("SIGINT", () => shutdown("SIGINT"));
process.on("SIGTERM", () => shutdown("SIGTERM"));
}
startServer().catch((error) => {
console.error("❌ Failed to start server:", error);
process.exit(1);
});