#!/usr/bin/env node /* Copyright (C) 2026 Moko Consulting * * This file is part of a Moko Consulting project. * * SPDX-License-Identifier: GPL-3.0-or-later * * FILE INFORMATION * DEFGROUP: dolibarr-api-mcp.Scripts * INGROUP: dolibarr-api-mcp * REPO: https://git.mokoconsulting.tech/MokoConsulting/dolibarr-api-mcp * PATH: /scripts/setup.mjs * VERSION: 01.00.00 * BRIEF: Interactive setup — prompts for Dolibarr API connection details and writes config */ import { createInterface } from 'node:readline/promises'; import { readFile, writeFile } from 'node:fs/promises'; import { resolve } from 'node:path'; import { homedir } from 'node:os'; const CONFIG_PATH = resolve(homedir(), '.dolibarr-api-mcp.json'); const rl = createInterface({ input: process.stdin, output: process.stdout }); async function prompt(question, defaultValue) { const suffix = defaultValue ? ` [${defaultValue}]` : ''; const answer = await rl.question(`${question}${suffix}: `); return answer.trim() || defaultValue || ''; } async function promptRequired(question) { let answer = ''; while (!answer) { answer = (await rl.question(`${question}: `)).trim(); if (!answer) { console.log(' This field is required.'); } } return answer; } async function main() { console.log(''); console.log('=== dolibarr-api-mcp Setup ==='); console.log(''); console.log('This will create your configuration file at:'); console.log(` ${CONFIG_PATH}`); console.log(''); // Check for existing config let existing = null; try { const raw = await readFile(CONFIG_PATH, 'utf-8'); existing = JSON.parse(raw); console.log('Existing config found. You can add a new connection or overwrite.'); console.log(` Current connections: ${Object.keys(existing.connections).join(', ')}`); console.log(''); } catch { // No existing config } const connectionName = await prompt('Connection name', 'production'); const baseUrl = await promptRequired('Dolibarr URL (e.g. https://erp.example.com)'); const apiKey = await promptRequired('Dolibarr API key (from user settings or Setup > Security)'); const cleanUrl = baseUrl.replace(/\/+$/, ''); const insecureAnswer = await prompt('Skip TLS verification for self-signed certs? (y/N)', 'N'); const insecure = insecureAnswer.toLowerCase() === 'y'; const connection = { baseUrl: cleanUrl, apiKey }; if (insecure) { connection.insecure = true; } let config; if (existing) { config = existing; config.connections[connectionName] = connection; const setDefault = await prompt(`Set "${connectionName}" as default connection? (y/N)`, 'N'); if (setDefault.toLowerCase() === 'y') { config.defaultConnection = connectionName; } } else { config = { defaultConnection: connectionName, connections: { [connectionName]: connection, }, }; } await writeFile(CONFIG_PATH, JSON.stringify(config, null, '\t') + '\n', 'utf-8'); console.log(''); console.log(`Config written to ${CONFIG_PATH}`); console.log(` Connection "${connectionName}" configured for ${cleanUrl}`); console.log(''); const addAnother = await prompt('Add another connection? (y/N)', 'N'); if (addAnother.toLowerCase() === 'y') { rl.close(); // Re-run to add another const { execFileSync } = await import('node:child_process'); execFileSync('node', [new URL(import.meta.url).pathname], { stdio: 'inherit' }); return; } console.log('Setup complete. You can now use the MCP server.'); console.log(''); rl.close(); } main().catch((err) => { console.error(`Setup failed: ${err.message}`); rl.close(); process.exit(1); });