#!/usr/bin/env node /** * stdio -> streamable-HTTP MCP proxy for the OpenViking Agent Plugins 1.0 package. * * VENDORED (adapted) from examples/claude-code-memory-plugin/servers/mcp-proxy.mjs — * keep in sync with that file. Only the import paths and doc comments differ; * the proxy behavior is identical. The shared modules under ./shared/ are * generated by `node examples/memory-plugin-shared/sync.mjs` (this directory is * one of its TARGETS) — edit them in examples/memory-plugin-shared/lib, never here. * * A conforming Agent Plugins client starts this process as a local stdio MCP * server (see ../mcp.json). The proxy reads the same OpenViking credential * sources as the ov CLI (OPENVIKING_* env → ~/.openviking/ovcli.conf → * ~/.openviking/ov.conf), forwards JSON-RPC requests to the server's /mcp * endpoint, and keeps stdout protocol-clean. */ import { homedir } from "node:os"; import { join, resolve as resolvePath } from "node:path"; import { fileURLToPath } from "node:url"; import { loadConfig } from "./config.mjs"; import { createLogger } from "./debug-log.mjs"; import { createOpenVikingMcpProxy } from "./shared/mcp-proxy-core.mjs"; import { resolveEffectivePeerId } from "./shared/workspace-peer.mjs"; const DEFAULT_TIMEOUT_MS = 15000; function trimSlash(value) { return String(value || "").replace(/\/+$/, ""); } function normalizePath(value) { const raw = String(value || "").trim(); if (!raw) return ""; if (raw === "~") return homedir(); if (raw.startsWith("~/")) return resolvePath(join(homedir(), raw.slice(2))); return resolvePath(raw); } function uniq(values) { return [...new Set(values.filter(Boolean))]; } function readProxyConfig() { const cfg = loadConfig(); const effectivePeer = resolveEffectivePeerId({ cfg, cwd: process.cwd() }); return { mcpUrl: `${trimSlash(cfg.baseUrl)}/mcp`, apiKey: cfg.apiKey || "", account: cfg.accountId || "", user: cfg.userId || "", peerId: effectivePeer.peerId, userAgent: cfg.userAgent || "", timeoutMs: Math.max(1000, Number(cfg.timeoutMs) || DEFAULT_TIMEOUT_MS), debug: cfg.debug === true, debugLogPath: cfg.debugLogPath, credentialSource: cfg.configPath?.endsWith("ovcli.conf") ? "ovcli" : "auto", credentialPath: cfg.configPath || "", watchedPaths: uniq([ cfg.configPath, normalizePath(process.env.OPENVIKING_CLI_CONFIG_FILE), normalizePath(process.env.OPENVIKING_CONFIG_FILE), join(homedir(), ".openviking", "ovcli.conf"), join(homedir(), ".openviking", "ov.conf"), ]), }; } if (process.argv[1] && fileURLToPath(import.meta.url) === resolvePath(process.argv[1])) { createOpenVikingMcpProxy({ readConfig: readProxyConfig, loggerFactory: createLogger }).start(); }