Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
- ADD_CHAIN138_TO_LEDGER_LIVE: Ledger form done; public code review repo bis-innovations/LedgerLive; init/push commands - CONTRACT_DEPLOYMENT_RUNBOOK: Chain 138 gas price 1 gwei, 36-addr check, TransactionMirror workaround - CONTRACT_*: AddressMapper, MirrorManager deployed 2026-02-12; 36-address on-chain check - NEXT_STEPS_FOR_YOU: Ledger done; steps completable now (no LAN); run-completable-tasks-from-anywhere - MASTER_INDEX, OPERATOR_OPTIONAL, SMART_CONTRACTS_INVENTORY_SIMPLE: updates - LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE: bis-innovations/LedgerLive reference Co-authored-by: Cursor <cursoragent@cursor.com>
111 lines
3.0 KiB
JavaScript
111 lines
3.0 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* MCP Server for UniFi Controller
|
|
*
|
|
* Entry point for the Model Context Protocol server that provides
|
|
* tools for managing Ubiquiti UniFi/UDM Pro devices
|
|
*/
|
|
|
|
import { readFileSync } from 'fs';
|
|
import { join, dirname } from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
import { homedir } from 'os';
|
|
import { UnifiServer } from './server/UnifiServer.js';
|
|
import { ApiMode } from 'unifi-api';
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = dirname(__filename);
|
|
|
|
// Load environment variables from ~/.env file (standardized location)
|
|
const envPath = join(homedir(), '.env');
|
|
const envPathFallback = join(__dirname, '../.env');
|
|
|
|
function loadEnvFile(filePath: string): boolean {
|
|
try {
|
|
const envFile = readFileSync(filePath, 'utf8');
|
|
const envVars = envFile.split('\n').filter(
|
|
(line) => line.includes('=') && !line.trim().startsWith('#')
|
|
);
|
|
for (const line of envVars) {
|
|
const [key, ...values] = line.split('=');
|
|
// Validate key is a valid environment variable name
|
|
if (key && values.length > 0 && /^[A-Z_][A-Z0-9_]*$/.test(key.trim())) {
|
|
// Remove surrounding quotes if present and trim
|
|
let value = values.join('=').trim();
|
|
if (
|
|
(value.startsWith('"') && value.endsWith('"')) ||
|
|
(value.startsWith("'") && value.endsWith("'"))
|
|
) {
|
|
value = value.slice(1, -1);
|
|
}
|
|
process.env[key.trim()] = value;
|
|
}
|
|
}
|
|
return true;
|
|
} catch (error) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Try ~/.env first, then fallback to relative path
|
|
if (!loadEnvFile(envPath)) {
|
|
if (!loadEnvFile(envPathFallback)) {
|
|
console.error('Warning: Could not load .env file from ~/.env or ../.env');
|
|
}
|
|
}
|
|
|
|
// Get configuration from environment variables
|
|
const baseUrl = process.env.UNIFI_UDM_URL || 'https://192.168.1.1';
|
|
const apiMode = (process.env.UNIFI_API_MODE || 'private') as ApiMode;
|
|
const siteId = process.env.UNIFI_SITE_ID;
|
|
const verifySSL = process.env.UNIFI_VERIFY_SSL !== 'false';
|
|
|
|
let config: {
|
|
baseUrl: string;
|
|
apiMode: ApiMode;
|
|
siteId?: string;
|
|
verifySSL: boolean;
|
|
apiKey?: string;
|
|
username?: string;
|
|
password?: string;
|
|
};
|
|
|
|
if (apiMode === ApiMode.OFFICIAL) {
|
|
const apiKey = process.env.UNIFI_API_KEY;
|
|
if (!apiKey) {
|
|
console.error('Error: UNIFI_API_KEY must be set in environment variables for Official API mode');
|
|
process.exit(1);
|
|
}
|
|
config = {
|
|
baseUrl,
|
|
apiMode,
|
|
apiKey,
|
|
siteId,
|
|
verifySSL,
|
|
};
|
|
} else {
|
|
const username = process.env.UNIFI_USERNAME;
|
|
const password = process.env.UNIFI_PASSWORD;
|
|
if (!username || !password) {
|
|
console.error('Error: UNIFI_USERNAME and UNIFI_PASSWORD must be set in environment variables for Private API mode');
|
|
process.exit(1);
|
|
}
|
|
config = {
|
|
baseUrl,
|
|
apiMode,
|
|
username,
|
|
password,
|
|
siteId,
|
|
verifySSL,
|
|
};
|
|
}
|
|
|
|
// Create and run the server
|
|
const server = new UnifiServer(config);
|
|
|
|
server.run().catch((error) => {
|
|
console.error('Fatal error:', error);
|
|
process.exit(1);
|
|
});
|