From d308d8375ef99cea53435780c4b12eabb641dbde Mon Sep 17 00:00:00 2001 From: bea Date: Mon, 11 May 2026 02:38:22 +0200 Subject: [PATCH] Add ncmcp.mjs CLI wrapper --- ncmcp.mjs | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100755 ncmcp.mjs diff --git a/ncmcp.mjs b/ncmcp.mjs new file mode 100755 index 0000000..cc94b88 --- /dev/null +++ b/ncmcp.mjs @@ -0,0 +1,71 @@ +#!/usr/bin/env node +// ncmcp.mjs - CLI wrapper for nextcloud-mcp (read .env automatically) +// Usage: ncmcp [key=value ...] + +import { spawn } from "child_process"; +import { dirname, join } from "path"; +import { fileURLToPath } from "url"; +import { readFileSync, existsSync } from "fs"; +import { createInterface } from "readline"; + +const __dir = dirname(fileURLToPath(import.meta.url)); +const serverPath = join(__dir, "build/index.js"); + +// Load .env +const envFile = join(__dir, ".env"); +const env = { ...process.env }; +if (existsSync(envFile)) { + for (const line of readFileSync(envFile, "utf8").split("\n")) { + const m = line.match(/^([^#=]+)=(.*)$/); + if (m) env[m[1].trim()] = m[2].trim(); + } +} + +const [,, tool, ...rawArgs] = process.argv; + +if (!tool) { + console.log("Usage: ncmcp [key=value ...]"); + console.log("Tools: list_calendars, get_calendar_events, create_calendar_event,"); + console.log(" get_tasks, create_task, update_task,"); + console.log(" get_notes, create_note, get_note_content, get_emails"); + process.exit(0); +} + +// Parse key=value args; values that look like JSON arrays/objects get parsed +const args = {}; +for (const a of rawArgs) { + const sep = a.indexOf("="); + if (sep > 0) { + const k = a.slice(0, sep); + const v = a.slice(sep + 1); + try { args[k] = JSON.parse(v); } catch { args[k] = v; } + } +} + +const child = spawn("node", [serverPath], { env, stdio: ["pipe", "pipe", "inherit"] }); +const rl = createInterface({ input: child.stdout }); + +const send = (msg) => child.stdin.write(JSON.stringify(msg) + "\n"); + +rl.on("line", (line) => { + try { + const msg = JSON.parse(line); + if (msg.id === 1) { + send({ jsonrpc: "2.0", id: 2, method: "tools/call", params: { name: tool, arguments: args } }); + } else if (msg.id === 2) { + const content = msg.result?.content?.[0]?.text; + if (content) { + try { console.log(JSON.stringify(JSON.parse(content), null, 2)); } + catch { console.log(content); } + } else if (msg.error) { + console.error("Error:", msg.error.message); + process.exit(1); + } + child.stdin.end(); + process.exit(0); + } + } catch {} +}); + +send({ jsonrpc: "2.0", id: 1, method: "initialize", params: { protocolVersion: "2024-11-05", capabilities: {}, clientInfo: { name: "ncmcp", version: "1.0" } } }); +setTimeout(() => { console.error("Timeout"); process.exit(1); }, 15000);