@bigbrain-work/mcp-connect 1.2.2 → 1.3.1

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.
@@ -1,205 +1,186 @@
1
- import { existsSync } from 'node:fs'
2
- import { mkdir, readFile, rename, writeFile } from 'node:fs/promises'
3
- import path from 'node:path'
4
- import { spawnSync } from 'node:child_process'
1
+ import { spawnSync } from "node:child_process";
2
+ import { existsSync } from "node:fs";
3
+ import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
4
+ import path from "node:path";
5
5
 
6
- import { API_KEY_ENV, MCP_URL, SERVER_NAME } from './constants.js'
6
+ import { PACKAGE_NAME, SERVER_NAME } from "./constants.js";
7
7
 
8
- export function codexArguments() {
9
- return [
10
- 'mcp',
11
- 'add',
12
- SERVER_NAME,
13
- '--url',
14
- MCP_URL,
15
- '--bearer-token-env-var',
16
- API_KEY_ENV,
17
- ]
8
+ export function stdioServerDefinition(platform = process.platform) {
9
+ if (platform === "win32") {
10
+ return {
11
+ command: "cmd",
12
+ args: ["/d", "/s", "/c", "npx", "-y", PACKAGE_NAME, "mcp"],
13
+ };
14
+ }
15
+ return {
16
+ command: "npx",
17
+ args: ["-y", PACKAGE_NAME, "mcp"],
18
+ };
18
19
  }
19
20
 
20
- export function claudeServerDefinition() {
21
- return {
22
- type: 'http',
23
- url: MCP_URL,
24
- headers: {
25
- Authorization: `Bearer \${${API_KEY_ENV}}`,
26
- },
27
- }
21
+ export function codexArguments(platform = process.platform) {
22
+ const proxy = stdioServerDefinition(platform);
23
+ return ["mcp", "add", SERVER_NAME, "--", proxy.command, ...proxy.args];
28
24
  }
29
25
 
30
- export function cursorServerDefinition() {
26
+ export function claudeServerDefinition(platform = process.platform) {
31
27
  return {
32
- type: 'http',
33
- url: MCP_URL,
34
- headers: {
35
- Authorization: `Bearer \${env:${API_KEY_ENV}}`,
36
- },
37
- }
28
+ type: "stdio",
29
+ ...stdioServerDefinition(platform),
30
+ };
38
31
  }
39
32
 
33
+ export const cursorServerDefinition = stdioServerDefinition;
34
+
40
35
  function commandText(command, args) {
41
- return [command, ...args].map((value) => (
42
- /[\s"]/u.test(value) ? JSON.stringify(value) : value
43
- )).join(' ')
36
+ return [command, ...args]
37
+ .map((value) => (/\s|"/u.test(value) ? JSON.stringify(value) : value))
38
+ .join(" ");
44
39
  }
45
40
 
46
- export function commandInvocation(command, args, {
47
- platform = process.platform,
48
- env = process.env,
49
- fileExists = existsSync,
50
- nodeExecutable = process.execPath,
51
- } = {}) {
52
- if (platform !== 'win32') {
53
- return { command, args }
54
- }
55
-
56
- const searchPath = env.PATH || env.Path || ''
41
+ export function commandInvocation(
42
+ command,
43
+ args,
44
+ {
45
+ platform = process.platform,
46
+ env = process.env,
47
+ fileExists = existsSync,
48
+ nodeExecutable = process.execPath,
49
+ } = {},
50
+ ) {
51
+ if (platform !== "win32") return { command, args };
52
+
53
+ const searchPath = env.PATH || env.Path || "";
57
54
  const npmDirectory = searchPath
58
- .split(';')
59
- .map((entry) => entry.trim().replace(/^"|"$/gu, ''))
55
+ .split(";")
56
+ .map((entry) => entry.trim().replace(/^"|"$/gu, ""))
60
57
  .filter(Boolean)
61
- .find((entry) => fileExists(path.join(entry, `${command}.cmd`)))
58
+ .find((entry) => fileExists(path.join(entry, `${command}.cmd`)));
62
59
 
63
- if (!npmDirectory) {
64
- return { command, args }
65
- }
66
-
67
- if (command === 'claude') {
60
+ if (!npmDirectory) return { command, args };
61
+ if (command === "claude") {
68
62
  const executable = path.join(
69
63
  npmDirectory,
70
- 'node_modules',
71
- '@anthropic-ai',
72
- 'claude-code',
73
- 'bin',
74
- 'claude.exe',
75
- )
76
- if (fileExists(executable)) {
77
- return { command: executable, args }
78
- }
79
- }
80
- if (command === 'codex') {
64
+ "node_modules",
65
+ "@anthropic-ai",
66
+ "claude-code",
67
+ "bin",
68
+ "claude.exe",
69
+ );
70
+ if (fileExists(executable)) return { command: executable, args };
71
+ }
72
+ if (command === "codex") {
81
73
  const script = path.join(
82
74
  npmDirectory,
83
- 'node_modules',
84
- '@openai',
85
- 'codex',
86
- 'bin',
87
- 'codex.js',
88
- )
89
- if (fileExists(script)) {
90
- return { command: nodeExecutable, args: [script, ...args] }
91
- }
92
- }
93
-
94
- return { command, args }
75
+ "node_modules",
76
+ "@openai",
77
+ "codex",
78
+ "bin",
79
+ "codex.js",
80
+ );
81
+ if (fileExists(script))
82
+ return { command: nodeExecutable, args: [script, ...args] };
83
+ }
84
+ return { command, args };
95
85
  }
96
86
 
97
87
  function execute(command, args, { dryRun = false } = {}) {
98
88
  if (dryRun) {
99
- console.log(`[dry-run] ${commandText(command, args)}`)
100
- return
89
+ console.log(`[dry-run] ${commandText(command, args)}`);
90
+ return;
101
91
  }
102
92
 
103
- const invocation = commandInvocation(command, args)
93
+ const invocation = commandInvocation(command, args);
104
94
  const result = spawnSync(invocation.command, invocation.args, {
105
- encoding: 'utf8',
95
+ encoding: "utf8",
106
96
  windowsHide: true,
107
97
  shell: false,
108
- })
98
+ });
109
99
  if (result.error) {
110
- if (result.error.code === 'ENOENT') {
111
- throw new Error(`未找到 ${command},请先安装对应客户端`)
112
- }
113
- throw result.error
100
+ if (result.error.code === "ENOENT")
101
+ throw new Error(`未找到 ${command},请先安装对应客户端`);
102
+ throw result.error;
114
103
  }
115
104
  if (result.status !== 0) {
116
- const detail = `${result.stderr || ''}\n${result.stdout || ''}`.trim()
117
- const error = new Error(detail || `${command} 返回退出码 ${result.status}`)
118
- error.commandOutput = detail
119
- throw error
105
+ const detail = `${result.stderr || ""}\n${result.stdout || ""}`.trim();
106
+ const error = new Error(detail || `${command} 返回退出码 ${result.status}`);
107
+ error.commandOutput = detail;
108
+ throw error;
120
109
  }
121
110
  }
122
111
 
123
112
  function isDuplicateError(error) {
124
- return /already|exist|duplicate|已存在/iu.test(error.commandOutput || error.message)
113
+ return /already|exist|duplicate|已存在/iu.test(
114
+ error.commandOutput || error.message,
115
+ );
125
116
  }
126
117
 
127
118
  export function configureCodex(options = {}) {
128
119
  try {
129
- execute('codex', codexArguments(), options)
120
+ execute("codex", codexArguments(), options);
130
121
  } catch (error) {
131
- if (!isDuplicateError(error)) {
132
- throw error
133
- }
134
- execute('codex', ['mcp', 'remove', SERVER_NAME], options)
135
- execute('codex', codexArguments(), options)
122
+ if (!isDuplicateError(error)) throw error;
123
+ execute("codex", ["mcp", "remove", SERVER_NAME], options);
124
+ execute("codex", codexArguments(), options);
136
125
  }
137
126
  }
138
127
 
139
128
  export function configureClaude(options = {}) {
140
129
  const addArgs = [
141
- 'mcp',
142
- 'add-json',
143
- '--scope',
144
- 'user',
130
+ "mcp",
131
+ "add-json",
132
+ "--scope",
133
+ "user",
145
134
  SERVER_NAME,
146
135
  JSON.stringify(claudeServerDefinition()),
147
- ]
136
+ ];
148
137
  try {
149
- execute('claude', addArgs, options)
138
+ execute("claude", addArgs, options);
150
139
  } catch (error) {
151
- if (!isDuplicateError(error)) {
152
- throw error
153
- }
154
- execute('claude', ['mcp', 'remove', '--scope', 'user', SERVER_NAME], options)
155
- execute('claude', addArgs, options)
140
+ if (!isDuplicateError(error)) throw error;
141
+ execute(
142
+ "claude",
143
+ ["mcp", "remove", "--scope", "user", SERVER_NAME],
144
+ options,
145
+ );
146
+ execute("claude", addArgs, options);
156
147
  }
157
148
  }
158
149
 
159
150
  export async function configureCursor({ home, dryRun = false } = {}) {
160
- const configPath = path.join(home, '.cursor', 'mcp.json')
151
+ const configPath = path.join(home, ".cursor", "mcp.json");
161
152
  if (dryRun) {
162
- console.log(`[dry-run] 更新 ${configPath} 中的 ${SERVER_NAME},认证头使用 ${API_KEY_ENV} 环境变量`)
163
- return configPath
153
+ console.log(
154
+ `[dry-run] 更新 ${configPath} 中的 ${SERVER_NAME},使用本地 stdio 桥接`,
155
+ );
156
+ return configPath;
164
157
  }
165
158
 
166
- let config = {}
159
+ let config = {};
167
160
  try {
168
- const source = await readFile(configPath, 'utf8')
169
- config = JSON.parse(source)
161
+ config = JSON.parse(await readFile(configPath, "utf8"));
170
162
  } catch (error) {
171
- if (error.code !== 'ENOENT') {
172
- if (error instanceof SyntaxError) {
173
- throw new Error(`${configPath} 不是有效 JSON,未做任何修改`)
174
- }
175
- throw error
163
+ if (error.code !== "ENOENT") {
164
+ if (error instanceof SyntaxError)
165
+ throw new Error(`${configPath} 不是有效 JSON,未做任何修改`);
166
+ throw error;
176
167
  }
177
168
  }
178
169
 
179
170
  config.mcpServers = {
180
171
  ...(config.mcpServers || {}),
181
172
  [SERVER_NAME]: cursorServerDefinition(),
182
- }
183
-
184
- await mkdir(path.dirname(configPath), { recursive: true })
185
- const tempPath = `${configPath}.${process.pid}.tmp`
186
- await writeFile(tempPath, `${JSON.stringify(config, null, 2)}\n`, 'utf8')
187
- await rename(tempPath, configPath)
188
- return configPath
173
+ };
174
+ await mkdir(path.dirname(configPath), { recursive: true });
175
+ const tempPath = `${configPath}.${process.pid}.tmp`;
176
+ await writeFile(tempPath, `${JSON.stringify(config, null, 2)}\n`, "utf8");
177
+ await rename(tempPath, configPath);
178
+ return configPath;
189
179
  }
190
180
 
191
181
  export async function configureAgent(agent, options) {
192
- if (agent === 'codex') {
193
- configureCodex(options)
194
- return
195
- }
196
- if (agent === 'claude') {
197
- configureClaude(options)
198
- return
199
- }
200
- if (agent === 'cursor') {
201
- await configureCursor(options)
202
- return
203
- }
204
- throw new Error(`不支持的客户端:${agent}`)
182
+ if (agent === "codex") return configureCodex(options);
183
+ if (agent === "claude") return configureClaude(options);
184
+ if (agent === "cursor") return configureCursor(options);
185
+ throw new Error(`不支持的客户端:${agent}`);
205
186
  }
package/src/constants.js CHANGED
@@ -1,6 +1,12 @@
1
- export const PACKAGE_NAME = '@bigbrain-work/mcp-connect'
2
- export const PACKAGE_VERSION = '1.2.2'
3
- export const SERVER_NAME = 'shiliu_mcp'
4
- export const MCP_URL = 'https://api.bigbrain.work/shiliu/mcp'
5
- export const API_KEY_ENV = 'SHILIU_AI_API_KEY'
6
- export const SUPPORTED_AGENTS = ['codex', 'claude', 'cursor']
1
+ export const PACKAGE_NAME = "@bigbrain-work/mcp-connect";
2
+ export const PACKAGE_VERSION = "1.3.1";
3
+ export const SERVER_NAME = "shiliu_mcp";
4
+ export const MCP_URL = "https://api.bigbrain.work/shiliu/mcp";
5
+ export const AUTH_URL = "https://api.bigbrain.work/shiliu/auth/device";
6
+ export const API_KEY_ENV = "SHILIU_AI_API_KEY";
7
+ export const KEYRING_SERVICE = "work.bigbrain.shiliu-ai";
8
+ export const KEYRING_ACCOUNT = "default";
9
+ export const PENDING_KEYRING_ACCOUNT = "pending-device-login";
10
+ export const SUPPORTED_AGENTS = ["codex", "claude", "cursor"];
11
+ export const REGISTRY_LATEST_URL =
12
+ "https://registry.npmjs.org/@bigbrain-work%2Fmcp-connect/latest";