@postmcp/cli 0.1.26 → 0.1.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin.mjs CHANGED
@@ -569,6 +569,15 @@ function getClientConfigPath(client) {
569
569
  if (client === "cursor") {
570
570
  return path4.join(process.cwd(), ".cursor", "mcp.json");
571
571
  }
572
+ if (client === "opencode") {
573
+ return path4.join(process.cwd(), "opencode.json");
574
+ }
575
+ if (client === "claude-code") {
576
+ return path4.join(process.cwd(), ".mcp.json");
577
+ }
578
+ if (client === "codex") {
579
+ return path4.join(process.cwd(), ".codex", "config.toml");
580
+ }
572
581
  if (client === "claude") {
573
582
  if (process.platform === "darwin") {
574
583
  return path4.join(home, "Library", "Application Support", "Claude", "claude_desktop_config.json");
@@ -586,6 +595,7 @@ function getClientConfigPath(client) {
586
595
  function buildClientConfigSnippet(serverKey, specPath, options) {
587
596
  const env = {};
588
597
  if (options.bearer) {
598
+ env["BEARER_TOKEN"] = options.bearer;
589
599
  env["API_KEY"] = options.bearer;
590
600
  }
591
601
  if (options.baseUrl) {
@@ -612,10 +622,68 @@ function buildClientConfigSnippet(serverKey, specPath, options) {
612
622
  }
613
623
  };
614
624
  }
625
+ function buildOpenCodeConfigSnippet(serverKey, specPath, options) {
626
+ const env = {};
627
+ if (options.bearer) {
628
+ env["BEARER_TOKEN"] = options.bearer;
629
+ }
630
+ if (options.baseUrl) {
631
+ env["BASE_URL"] = options.baseUrl;
632
+ }
633
+ if (options.env) {
634
+ for (const e of options.env) {
635
+ const eqIdx = e.indexOf("=");
636
+ if (eqIdx !== -1) {
637
+ const k = e.slice(0, eqIdx).trim();
638
+ const v = e.slice(eqIdx + 1).trim();
639
+ if (k) env[k] = v;
640
+ }
641
+ }
642
+ }
643
+ const targetSpecPath = specPath.startsWith("http://") || specPath.startsWith("https://") || specPath.startsWith("@") ? specPath : path4.resolve(process.cwd(), specPath);
644
+ return {
645
+ $schema: "https://opencode.ai/config.json",
646
+ mcp: {
647
+ [serverKey]: {
648
+ type: "local",
649
+ enabled: true,
650
+ command: ["npx", "-y", "@postmcp/cli", "run", targetSpecPath],
651
+ environment: Object.keys(env).length > 0 ? env : void 0
652
+ }
653
+ }
654
+ };
655
+ }
656
+ function buildCodexTomlSnippet(serverKey, specPath, options) {
657
+ const env = {};
658
+ if (options.bearer) {
659
+ env["BEARER_TOKEN"] = options.bearer;
660
+ }
661
+ if (options.baseUrl) {
662
+ env["BASE_URL"] = options.baseUrl;
663
+ }
664
+ if (options.env) {
665
+ for (const e of options.env) {
666
+ const eqIdx = e.indexOf("=");
667
+ if (eqIdx !== -1) {
668
+ const k = e.slice(0, eqIdx).trim();
669
+ const v = e.slice(eqIdx + 1).trim();
670
+ if (k) env[k] = v;
671
+ }
672
+ }
673
+ }
674
+ const targetSpecPath = specPath.startsWith("http://") || specPath.startsWith("https://") || specPath.startsWith("@") ? specPath : path4.resolve(process.cwd(), specPath);
675
+ const envEntries = Object.entries(env).map(([k, v]) => `${k} = "${v}"`).join(", ");
676
+ const envLine = envEntries.length > 0 ? `
677
+ env = { ${envEntries} }` : "";
678
+ return `[mcp_servers.${serverKey}]
679
+ command = "npx"
680
+ args = ["-y", "@postmcp/cli", "run", "${targetSpecPath}"]${envLine}`;
681
+ }
682
+ var ALL_CLIENTS = ["cursor", "opencode", "claude-code", "codex", "claude", "windsurf"];
615
683
  async function exportCommand(specArg, options) {
616
684
  let specPath = specArg;
617
685
  if (!specPath) {
618
- console.error(pc4.red("Error: No OpenAPI spec provided. Usage: postmcp export <spec-path-or-url-or-@preset> --target cursor|claude|windsurf|all"));
686
+ console.error(pc4.red("Error: No OpenAPI spec provided. Usage: postmcp export <spec-path-or-url-or-@preset> --target cursor|opencode|claude-code|codex|claude|windsurf|all"));
619
687
  process.exit(1);
620
688
  }
621
689
  let serverKey = "api-server";
@@ -630,39 +698,85 @@ async function exportCommand(specArg, options) {
630
698
  }
631
699
  }
632
700
  const selectedTarget = (options.client || options.target || "all").toLowerCase();
633
- const clientsToExport = selectedTarget === "all" ? ["cursor", "claude", "windsurf"] : [selectedTarget];
701
+ const clientsToExport = selectedTarget === "all" ? ALL_CLIENTS : [selectedTarget];
634
702
  console.log(pc4.bold(pc4.cyan(`PostMCP 1-Click Client Configuration Exporter`)));
635
703
  console.log();
636
704
  for (const c of clientsToExport) {
637
705
  const configPath = getClientConfigPath(c);
638
- const snippet = buildClientConfigSnippet(serverKey, specPath, options);
639
- const formattedSnippet = JSON.stringify(snippet, null, 2);
640
- console.log(pc4.bold(pc4.green(`\u25B6 ${c.toUpperCase()} (${c === "cursor" ? "Project Local" : "Global Client"})`)));
706
+ let formattedSnippet = "";
707
+ if (c === "opencode") {
708
+ const snippet = buildOpenCodeConfigSnippet(serverKey, specPath, options);
709
+ formattedSnippet = JSON.stringify(snippet, null, 2);
710
+ } else if (c === "codex") {
711
+ formattedSnippet = buildCodexTomlSnippet(serverKey, specPath, options);
712
+ } else {
713
+ const snippet = buildClientConfigSnippet(serverKey, specPath, options);
714
+ formattedSnippet = JSON.stringify(snippet, null, 2);
715
+ }
716
+ const isProjectLocal = ["cursor", "opencode", "claude-code", "codex"].includes(c);
717
+ console.log(pc4.bold(pc4.green(`\u25B6 ${c.toUpperCase()} (${isProjectLocal ? "Project Local" : "Global Client"})`)));
641
718
  console.log(pc4.dim(` Config path: ${configPath}`));
642
719
  console.log();
643
720
  console.log(pc4.gray(formattedSnippet));
644
721
  console.log();
645
722
  if (options.write) {
646
723
  try {
647
- let existingConfig = {};
648
- if (fs4.existsSync(configPath)) {
649
- const raw = fs4.readFileSync(configPath, "utf-8");
650
- try {
651
- existingConfig = JSON.parse(raw);
652
- } catch {
653
- existingConfig = {};
654
- }
655
- }
656
- existingConfig.mcpServers = existingConfig.mcpServers || {};
657
- if (snippet.mcpServers?.[serverKey]) {
658
- existingConfig.mcpServers[serverKey] = snippet.mcpServers[serverKey];
659
- }
660
724
  const parentDir = path4.dirname(configPath);
661
725
  if (!fs4.existsSync(parentDir)) {
662
726
  fs4.mkdirSync(parentDir, { recursive: true });
663
727
  }
664
- fs4.writeFileSync(configPath, JSON.stringify(existingConfig, null, 2), "utf-8");
665
- console.log(pc4.green(` Successfully merged and written to ${configPath}`));
728
+ if (c === "codex") {
729
+ let content = "";
730
+ if (fs4.existsSync(configPath)) {
731
+ content = fs4.readFileSync(configPath, "utf-8");
732
+ }
733
+ if (!content.includes(`[mcp_servers.${serverKey}]`)) {
734
+ content = content ? `${content.trim()}
735
+
736
+ ${formattedSnippet}
737
+ ` : `${formattedSnippet}
738
+ `;
739
+ fs4.writeFileSync(configPath, content, "utf-8");
740
+ console.log(pc4.green(` Successfully appended to ${configPath}`));
741
+ } else {
742
+ console.log(pc4.yellow(` Server [mcp_servers.${serverKey}] already exists in ${configPath}`));
743
+ }
744
+ } else if (c === "opencode") {
745
+ let existingConfig = {};
746
+ if (fs4.existsSync(configPath)) {
747
+ try {
748
+ existingConfig = JSON.parse(fs4.readFileSync(configPath, "utf-8"));
749
+ } catch {
750
+ existingConfig = {};
751
+ }
752
+ }
753
+ existingConfig.$schema = existingConfig.$schema || "https://opencode.ai/config.json";
754
+ existingConfig.mcp = existingConfig.mcp || {};
755
+ const openCodeSnippet = buildOpenCodeConfigSnippet(serverKey, specPath, options);
756
+ const newMcp = openCodeSnippet.mcp?.[serverKey];
757
+ if (newMcp) {
758
+ existingConfig.mcp[serverKey] = newMcp;
759
+ }
760
+ fs4.writeFileSync(configPath, JSON.stringify(existingConfig, null, 2), "utf-8");
761
+ console.log(pc4.green(` Successfully merged and written to ${configPath}`));
762
+ } else {
763
+ let existingConfig = {};
764
+ if (fs4.existsSync(configPath)) {
765
+ const raw = fs4.readFileSync(configPath, "utf-8");
766
+ try {
767
+ existingConfig = JSON.parse(raw);
768
+ } catch {
769
+ existingConfig = {};
770
+ }
771
+ }
772
+ existingConfig.mcpServers = existingConfig.mcpServers || {};
773
+ const snippet = buildClientConfigSnippet(serverKey, specPath, options);
774
+ if (snippet.mcpServers?.[serverKey]) {
775
+ existingConfig.mcpServers[serverKey] = snippet.mcpServers[serverKey];
776
+ }
777
+ fs4.writeFileSync(configPath, JSON.stringify(existingConfig, null, 2), "utf-8");
778
+ console.log(pc4.green(` Successfully merged and written to ${configPath}`));
779
+ }
666
780
  } catch (err) {
667
781
  const errMsg = err instanceof Error ? err.message : String(err);
668
782
  console.error(pc4.red(` Failed to write to ${configPath}: ${errMsg}`));
@@ -956,7 +1070,7 @@ import { resolve as resolve5 } from "path";
956
1070
  import pc8 from "picocolors";
957
1071
  function getCliVersion() {
958
1072
  if (true) {
959
- return "0.1.26";
1073
+ return "0.1.28";
960
1074
  }
961
1075
  try {
962
1076
  const dir = typeof __dirname !== "undefined" ? __dirname : process.cwd();
@@ -987,7 +1101,7 @@ function createCli() {
987
1101
  process.exit(1);
988
1102
  });
989
1103
  });
990
- program.command("export <spec>").description("1-Click configuration exporter for Cursor, Claude Desktop, and Windsurf").option("-t, --target <name>", "Target client: cursor, claude, windsurf, or all").option("--client <name>", "Alias for --target").option("-w, --write", "Automatically merge and write configuration directly to the client config file on disk").option("--bearer <token>", "Bearer token for client configuration environment").option("-b, --base-url <url>", "Base URL override for client configuration environment").option("-e, --env <key=val...>", "Environment variables for client configuration", (val, prev = []) => [...prev, val]).action((spec, opts) => {
1104
+ program.command("export <spec>").description("1-Click configuration exporter for OpenCode, Claude Code, Codex, Cursor, Claude Desktop, and Windsurf").option("-t, --target <name>", "Target client: cursor, opencode, claude-code, codex, claude, windsurf, or all").option("--client <name>", "Alias for --target").option("-w, --write", "Automatically merge and write configuration directly to the client config file on disk").option("--bearer <token>", "Bearer token for client configuration environment").option("-b, --base-url <url>", "Base URL override for client configuration environment").option("-e, --env <key=val...>", "Environment variables for client configuration", (val, prev = []) => [...prev, val]).action((spec, opts) => {
991
1105
  const target = opts.target || opts.client || "all";
992
1106
  exportCommand(spec, { ...opts, target, client: target }).catch((err) => {
993
1107
  console.error(pc8.red(`Fatal error: ${err.message}`));