@postmcp/cli 0.1.25 → 0.1.27

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) {
@@ -593,24 +603,87 @@ function buildClientConfigSnippet(serverKey, specPath, options) {
593
603
  }
594
604
  if (options.env) {
595
605
  for (const e of options.env) {
596
- const [k, v] = e.split("=");
597
- if (k && v) env[k] = v;
606
+ const eqIdx = e.indexOf("=");
607
+ if (eqIdx !== -1) {
608
+ const k = e.slice(0, eqIdx).trim();
609
+ const v = e.slice(eqIdx + 1).trim();
610
+ if (k) env[k] = v;
611
+ }
598
612
  }
599
613
  }
614
+ const targetSpecPath = specPath.startsWith("http://") || specPath.startsWith("https://") || specPath.startsWith("@") ? specPath : path4.resolve(process.cwd(), specPath);
600
615
  return {
601
616
  mcpServers: {
602
617
  [serverKey]: {
603
618
  command: "npx",
604
- args: ["-y", "@postmcp/cli", "run", specPath],
619
+ args: ["-y", "@postmcp/cli", "run", targetSpecPath],
605
620
  env: Object.keys(env).length > 0 ? env : void 0
606
621
  }
607
622
  }
608
623
  };
609
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"];
610
683
  async function exportCommand(specArg, options) {
611
684
  let specPath = specArg;
612
685
  if (!specPath) {
613
- 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"));
614
687
  process.exit(1);
615
688
  }
616
689
  let serverKey = "api-server";
@@ -625,39 +698,85 @@ async function exportCommand(specArg, options) {
625
698
  }
626
699
  }
627
700
  const selectedTarget = (options.client || options.target || "all").toLowerCase();
628
- const clientsToExport = selectedTarget === "all" ? ["cursor", "claude", "windsurf"] : [selectedTarget];
701
+ const clientsToExport = selectedTarget === "all" ? ALL_CLIENTS : [selectedTarget];
629
702
  console.log(pc4.bold(pc4.cyan(`PostMCP 1-Click Client Configuration Exporter`)));
630
703
  console.log();
631
704
  for (const c of clientsToExport) {
632
705
  const configPath = getClientConfigPath(c);
633
- const snippet = buildClientConfigSnippet(serverKey, specPath, options);
634
- const formattedSnippet = JSON.stringify(snippet, null, 2);
635
- 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"})`)));
636
718
  console.log(pc4.dim(` Config path: ${configPath}`));
637
719
  console.log();
638
720
  console.log(pc4.gray(formattedSnippet));
639
721
  console.log();
640
722
  if (options.write) {
641
723
  try {
642
- let existingConfig = {};
643
- if (fs4.existsSync(configPath)) {
644
- const raw = fs4.readFileSync(configPath, "utf-8");
645
- try {
646
- existingConfig = JSON.parse(raw);
647
- } catch {
648
- existingConfig = {};
649
- }
650
- }
651
- existingConfig.mcpServers = existingConfig.mcpServers || {};
652
- if (snippet.mcpServers?.[serverKey]) {
653
- existingConfig.mcpServers[serverKey] = snippet.mcpServers[serverKey];
654
- }
655
724
  const parentDir = path4.dirname(configPath);
656
725
  if (!fs4.existsSync(parentDir)) {
657
726
  fs4.mkdirSync(parentDir, { recursive: true });
658
727
  }
659
- fs4.writeFileSync(configPath, JSON.stringify(existingConfig, null, 2), "utf-8");
660
- 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
+ }
661
780
  } catch (err) {
662
781
  const errMsg = err instanceof Error ? err.message : String(err);
663
782
  console.error(pc4.red(` Failed to write to ${configPath}: ${errMsg}`));
@@ -912,8 +1031,8 @@ async function studioCommand(specArg, options = {}) {
912
1031
  }
913
1032
  }
914
1033
  if (child) {
915
- await new Promise((resolve5) => {
916
- child?.on("close", () => resolve5());
1034
+ await new Promise((resolve6) => {
1035
+ child?.on("close", () => resolve6());
917
1036
  });
918
1037
  }
919
1038
  }
@@ -947,15 +1066,15 @@ async function docsCommand(options = {}) {
947
1066
 
948
1067
  // src/bin.ts
949
1068
  import { readFileSync as readFileSync4 } from "fs";
950
- import { resolve as resolve4 } from "path";
1069
+ import { resolve as resolve5 } from "path";
951
1070
  import pc8 from "picocolors";
952
1071
  function getCliVersion() {
953
1072
  if (true) {
954
- return "0.1.25";
1073
+ return "0.1.27";
955
1074
  }
956
1075
  try {
957
1076
  const dir = typeof __dirname !== "undefined" ? __dirname : process.cwd();
958
- const pkg = JSON.parse(readFileSync4(resolve4(dir, "../package.json"), "utf8"));
1077
+ const pkg = JSON.parse(readFileSync4(resolve5(dir, "../package.json"), "utf8"));
959
1078
  return pkg.version || "unknown";
960
1079
  } catch {
961
1080
  return "unknown";
@@ -982,7 +1101,7 @@ function createCli() {
982
1101
  process.exit(1);
983
1102
  });
984
1103
  });
985
- 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) => {
986
1105
  const target = opts.target || opts.client || "all";
987
1106
  exportCommand(spec, { ...opts, target, client: target }).catch((err) => {
988
1107
  console.error(pc8.red(`Fatal error: ${err.message}`));