#!/usr/bin/env node
/**
* LiteFarm MCP Server
* Main entry point for the MCP server
*/
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import express from "express";
import dotenv from "dotenv";
import { LiteFarmClient, formatApiError } from "./litefarm-client.js";
import { registerFarmTools } from "./tools/farm-tools.js";
import { registerTaskTools } from "./tools/task-tools.js";
import { registerCropTools } from "./tools/crop-tools.js";
import { registerLocationTools } from "./tools/location-tools.js";
import { registerAnimalTools } from "./tools/animal-tools.js";
import { registerFinanceTools } from "./tools/finance-tools.js";
import { registerDbTools, closeDbPool } from "./tools/db-tools.js";
// Load environment variables
dotenv.config();
// Validate required environment variables
const requiredEnvVars = ["LITEFARM_EMAIL", "LITEFARM_PASSWORD"];
const missingVars = requiredEnvVars.filter(varName => !process.env[varName]);
if (missingVars.length > 0) {
console.error(`❌ Missing required environment variables: ${missingVars.join(", ")}`);
console.error("Please create a .env file based on .env.example");
process.exit(1);
}
// Initialize LiteFarm client
const client = new LiteFarmClient(
process.env.LITEFARM_EMAIL!,
process.env.LITEFARM_PASSWORD!
);
// Create MCP server
const server = new McpServer({
name: "litefarm-mcp-server",
version: "1.0.0"
});
// Register all tools
console.error("Registering LiteFarm tools...");
try {
registerFarmTools(server, client);
registerTaskTools(server, client);
registerCropTools(server, client);
registerLocationTools(server, client);
registerAnimalTools(server, client);
registerFinanceTools(server, client);
registerDbTools(server);
console.error("✅ All tools registered successfully");
console.error("✅ Animal & Finance tools enabled");
console.error("✅ Database tools (SQL Logic Sandbox) enabled");
} catch (error) {
console.error("❌ Error registering tools:", error);
process.exit(1);
}
// Verify LiteFarm connection on startup
async function verifyConnection(): Promise<void> {
try {
console.error("Verifying LiteFarm API connection...");
await client.login();
const user = await client.getCurrentUser();
console.error(`✅ Connected to LiteFarm as ${user.first_name} ${user.last_name} (${user.email})`);
} catch (error) {
console.error("❌ Failed to connect to LiteFarm API:");
console.error(formatApiError(error));
console.error("\nPlease check:");
console.error("1. LiteFarm API is running (http://localhost:5000)");
console.error("2. Your credentials in .env are correct");
console.error("3. Your account exists and is active");
process.exit(1);
}
}
/**
* Run server with stdio transport (for Claude Desktop)
*/
async function runStdio(): Promise<void> {
await verifyConnection();
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("🚀 LiteFarm MCP Server running on stdio transport");
console.error("Ready for connections from Claude Desktop");
}
/**
* Run server with HTTP transport (for remote access)
*/
async function runHTTP(): Promise<void> {
await verifyConnection();
const app = express();
app.use(express.json());
// Health check endpoint
app.get('/health', (_req, res) => {
res.json({ status: 'healthy', service: 'litefarm-mcp-server', version: '1.0.0' });
});
// MCP endpoint
app.post('/mcp', async (req, res) => {
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: undefined,
enableJsonResponse: true
});
res.on('close', () => transport.close());
await server.connect(transport);
await transport.handleRequest(req, res, req.body);
});
const port = parseInt(process.env.PORT || '3000');
app.listen(port, () => {
console.error(`🚀 LiteFarm MCP Server running on http://localhost:${port}/mcp`);
console.error(`Health check available at http://localhost:${port}/health`);
});
}
// Determine transport based on environment
const transport = process.env.TRANSPORT || 'stdio';
if (transport === 'http') {
runHTTP().catch(error => {
console.error("❌ Server error:", error);
process.exit(1);
});
} else {
runStdio().catch(error => {
console.error("❌ Server error:", error);
process.exit(1);
});
}
// Graceful shutdown
process.on('SIGINT', async () => {
console.error("\n👋 Shutting down LiteFarm MCP Server...");
await closeDbPool();
process.exit(0);
});
process.on('SIGTERM', async () => {
console.error("\n👋 Shutting down LiteFarm MCP Server...");
await closeDbPool();
process.exit(0);
});