@m2canvas/connect 0.3.0 → 0.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.
- package/README.md +1 -1
- package/dist/clients.js +8 -8
- package/dist/config-files.js +10 -0
- package/dist/system.js +8 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ It finds the supported clients you have installed, shows what it will change, an
|
|
|
15
15
|
| Client | How it is set up | Sign-in |
|
|
16
16
|
|---|---|---|
|
|
17
17
|
| Claude Code | `claude mcp add --transport http --scope user m2 …` | `claude mcp login m2` |
|
|
18
|
-
| Codex (CLI or the desktop app's bundled CLI) | `
|
|
18
|
+
| Codex (CLI or the desktop app's bundled CLI) | appends `[mcp_servers.m2]` to `~/.codex/config.toml` | `codex mcp login m2` |
|
|
19
19
|
| Cursor | merges `m2` into `~/.cursor/mcp.json`, then `cursor-agent mcp enable m2` | `cursor-agent mcp login m2` |
|
|
20
20
|
| OpenCode | merges `m2` into `~/.config/opencode/opencode.json`, keeping the file's existing format | `opencode mcp auth m2` |
|
|
21
21
|
| Qoder (CLI + desktop app) | `qodercli mcp add -s user -t http m2 …` | in Qoder: Extensions → Connectors → m2 → Authorize |
|
package/dist/clients.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
// 各客户端的探测 / 写入 / 登录。每家的命令与坑位都经本机逐一实测,见 README。
|
|
2
|
-
import { mkdirSync } from 'node:fs';
|
|
3
2
|
import { join } from 'node:path';
|
|
4
|
-
import { M2_MCP_URL, SERVER_NAME, findInClaudeConfig, findInCodexToml, findInQoderSettings, mergeCursorConfig, mergeOpencodeConfig, } from './config-files.js';
|
|
5
|
-
import { existsSync, firstExecutable, firstRunnable, home, readJson, readText, run, which, writeJsonWithBackup } from './system.js';
|
|
3
|
+
import { M2_MCP_URL, SERVER_NAME, findInClaudeConfig, findInCodexToml, findInQoderSettings, appendCodexServer, mergeCursorConfig, mergeOpencodeConfig, } from './config-files.js';
|
|
4
|
+
import { existsSync, firstExecutable, firstRunnable, home, readJson, readText, run, which, writeJsonWithBackup, writeTextWithBackup, } from './system.js';
|
|
6
5
|
function jsonExisting(path, find) {
|
|
7
6
|
const read = readJson(path);
|
|
8
7
|
return read.kind === 'ok' ? find(read.value) : null;
|
|
@@ -34,19 +33,20 @@ function codex() {
|
|
|
34
33
|
if (!bin)
|
|
35
34
|
return null;
|
|
36
35
|
const codexHome = process.env.CODEX_HOME ?? join(home, '.codex');
|
|
37
|
-
const
|
|
36
|
+
const path = join(codexHome, 'config.toml');
|
|
37
|
+
const toml = readText(path);
|
|
38
38
|
return {
|
|
39
39
|
label: 'Codex',
|
|
40
40
|
existing: toml ? findInCodexToml(toml) : null,
|
|
41
41
|
blocked: null,
|
|
42
|
-
actions: [`
|
|
42
|
+
actions: [`add [mcp_servers.${SERVER_NAME}] to ${path}`],
|
|
43
43
|
// 顺序敏感:login 的本地回调端口挂在 login 进程上,必须授权完成后再重启 Codex。
|
|
44
44
|
restart: 'Fully quit and reopen Codex (after signing in).',
|
|
45
45
|
signIn: (_interactive, name) => ({ login: { command: bin, args: ['mcp', 'login', name] }, manual: null }),
|
|
46
46
|
add() {
|
|
47
|
-
//
|
|
48
|
-
|
|
49
|
-
return
|
|
47
|
+
// 直接追加 config.toml,不用 `codex mcp add`(会自己拉起 OAuth 并阻塞,见 appendCodexServer)。
|
|
48
|
+
writeTextWithBackup(path, appendCodexServer(toml));
|
|
49
|
+
return { ok: true };
|
|
50
50
|
},
|
|
51
51
|
};
|
|
52
52
|
}
|
package/dist/config-files.js
CHANGED
|
@@ -88,3 +88,13 @@ export function mergeOpencodeConfig(config) {
|
|
|
88
88
|
: { ...mcp, [SERVER_NAME]: { type: 'remote', url: M2_MCP_URL, enabled: true } };
|
|
89
89
|
return { existing: null, config: { ...base, mcp: nextMcp } };
|
|
90
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Codex `config.toml` 追加 m2 段。不走 `codex mcp add`:它在没有已存 token 时会顺手启动 OAuth
|
|
93
|
+
* 并阻塞等浏览器回调(实测),agent 代跑时输出被捕获、链接不可见,命令永远不返回。
|
|
94
|
+
* 只做追加、不解析重写,用户原有内容与注释逐字保留;调用方先用 findInCodexToml 判重。
|
|
95
|
+
*/
|
|
96
|
+
export function appendCodexServer(toml) {
|
|
97
|
+
const base = toml ?? '';
|
|
98
|
+
const separator = base === '' || base.endsWith('\n\n') ? '' : base.endsWith('\n') ? '\n' : '\n\n';
|
|
99
|
+
return `${base}${separator}[mcp_servers.${SERVER_NAME}]\nurl = "${M2_MCP_URL}"\n`;
|
|
100
|
+
}
|
package/dist/system.js
CHANGED
|
@@ -57,16 +57,19 @@ export function readText(path) {
|
|
|
57
57
|
return existsSync(path) ? readFileSync(path, 'utf8') : null;
|
|
58
58
|
}
|
|
59
59
|
/** 覆写前先备份到同目录 `<file>.bak-m2canvas`,返回备份路径(新建文件时为 null)。 */
|
|
60
|
-
export function
|
|
60
|
+
export function writeTextWithBackup(path, text) {
|
|
61
61
|
mkdirSync(dirname(path), { recursive: true });
|
|
62
62
|
let backup = null;
|
|
63
63
|
if (existsSync(path)) {
|
|
64
64
|
backup = `${path}.bak-m2canvas`;
|
|
65
65
|
copyFileSync(path, backup);
|
|
66
66
|
}
|
|
67
|
-
writeFileSync(path,
|
|
67
|
+
writeFileSync(path, text);
|
|
68
68
|
return backup;
|
|
69
69
|
}
|
|
70
|
+
export function writeJsonWithBackup(path, value) {
|
|
71
|
+
return writeTextWithBackup(path, `${JSON.stringify(value, null, 2)}\n`);
|
|
72
|
+
}
|
|
70
73
|
/**
|
|
71
74
|
* 跑子进程。`interactive` 时继承当前终端 —— login / auth 要开浏览器并等回调,
|
|
72
75
|
* Claude Code 的 `mcp login` 还硬性要求 TTY(stdin 不是终端时直接失败),所以必须 inherit。
|
|
@@ -75,6 +78,9 @@ export function run(command, args, interactive = false) {
|
|
|
75
78
|
const result = spawnSync(command, args, {
|
|
76
79
|
stdio: interactive ? 'inherit' : 'pipe',
|
|
77
80
|
encoding: 'utf8',
|
|
81
|
+
// 非交互命令给上限:客户端 CLI 可能在写配置时自己拉起 OAuth 并阻塞等回调(实测 codex mcp add),
|
|
82
|
+
// 输出被 pipe 吞掉时用户看不到链接,没有上限就会永远挂住。交互 login 等用户操作,不设上限。
|
|
83
|
+
timeout: interactive ? undefined : 60_000,
|
|
78
84
|
});
|
|
79
85
|
const output = interactive ? '' : `${result.stdout ?? ''}${result.stderr ?? ''}`.trim();
|
|
80
86
|
return { status: result.error ? null : result.status, output: result.error ? result.error.message : output };
|
package/package.json
CHANGED