@super-hands/connect 0.1.4 → 0.1.6
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/client.mjs +67 -29
- package/package.json +1 -1
package/client.mjs
CHANGED
|
@@ -32,7 +32,7 @@ function codexConfigBlock(args) {
|
|
|
32
32
|
return [
|
|
33
33
|
`[mcp_servers.${MCP_SERVER_KEY}]`,
|
|
34
34
|
`url = "${args.endpoint}"`,
|
|
35
|
-
`
|
|
35
|
+
`http_headers = { "Authorization" = "${mcpAuthorizationHeader(args.token)}" }`
|
|
36
36
|
].join("\n");
|
|
37
37
|
}
|
|
38
38
|
|
|
@@ -94,6 +94,12 @@ function stop(message) {
|
|
|
94
94
|
`);
|
|
95
95
|
process.exit(1);
|
|
96
96
|
}
|
|
97
|
+
function cursorServerEntry(args) {
|
|
98
|
+
return {
|
|
99
|
+
url: args.endpoint,
|
|
100
|
+
headers: { Authorization: mcpAuthorizationHeader(args.token) }
|
|
101
|
+
};
|
|
102
|
+
}
|
|
97
103
|
function mergedCursorConfig(existing, args) {
|
|
98
104
|
let config = {};
|
|
99
105
|
if (existing !== null && existing.trim() !== "") {
|
|
@@ -111,21 +117,28 @@ function mergedCursorConfig(existing, args) {
|
|
|
111
117
|
const serversRaw = config.mcpServers;
|
|
112
118
|
const servers = typeof serversRaw === "object" && serversRaw !== null && !Array.isArray(serversRaw) ? serversRaw : {};
|
|
113
119
|
const replaced = MCP_SERVER_KEY in servers;
|
|
114
|
-
servers[MCP_SERVER_KEY] =
|
|
115
|
-
url: args.endpoint,
|
|
116
|
-
headers: { Authorization: mcpAuthorizationHeader(args.token) }
|
|
117
|
-
};
|
|
120
|
+
servers[MCP_SERVER_KEY] = cursorServerEntry(args);
|
|
118
121
|
config.mcpServers = servers;
|
|
119
122
|
return { text: `${JSON.stringify(config, null, 2)}
|
|
120
123
|
`, replaced };
|
|
121
124
|
}
|
|
122
125
|
function appendedCodexConfig(existing, args) {
|
|
126
|
+
const staleOwnBlock = new RegExp(
|
|
127
|
+
`\\[mcp_servers\\.${MCP_SERVER_KEY}\\]\\nurl = "[^"\\n]*"\\nbearer_token = "[^"\\n]*"`
|
|
128
|
+
);
|
|
129
|
+
if (staleOwnBlock.test(existing)) {
|
|
130
|
+
return {
|
|
131
|
+
text: existing.replace(staleOwnBlock, codexConfigBlock(args)),
|
|
132
|
+
alreadyPresent: false,
|
|
133
|
+
repaired: true
|
|
134
|
+
};
|
|
135
|
+
}
|
|
123
136
|
if (existing.includes(`[mcp_servers.${MCP_SERVER_KEY}]`)) {
|
|
124
|
-
return { text: existing, alreadyPresent: true };
|
|
137
|
+
return { text: existing, alreadyPresent: true, repaired: false };
|
|
125
138
|
}
|
|
126
139
|
const sep = existing === "" || existing.endsWith("\n\n") ? "" : existing.endsWith("\n") ? "\n" : "\n\n";
|
|
127
140
|
return { text: `${existing}${sep}${codexConfigBlock(args)}
|
|
128
|
-
`, alreadyPresent: false };
|
|
141
|
+
`, alreadyPresent: false, repaired: false };
|
|
129
142
|
}
|
|
130
143
|
function writeSkill(clientDir) {
|
|
131
144
|
const skillPath = join(clientDir, "skills", CONNECT_SKILL_DIR, CONNECT_SKILL_FILENAME);
|
|
@@ -188,26 +201,40 @@ async function main() {
|
|
|
188
201
|
} catch {
|
|
189
202
|
existing = null;
|
|
190
203
|
}
|
|
204
|
+
let merged = null;
|
|
191
205
|
try {
|
|
192
|
-
|
|
193
|
-
mkdirSync(dirname(configPath), { recursive: true });
|
|
194
|
-
writeFileSync(configPath, merged.text);
|
|
195
|
-
say(
|
|
196
|
-
merged.replaced ? `Cursor \u2014 updated the ${MCP_SERVER_KEY} server in ${configPath}.` : `Cursor \u2014 added the ${MCP_SERVER_KEY} server to ${configPath}.`
|
|
197
|
-
);
|
|
198
|
-
if (openCursor()) {
|
|
199
|
-
say(
|
|
200
|
-
` Cursor is opening \u2014 enable ${MCP_SERVER_KEY} under Settings \u2192 MCP. If it was already running, restart it first.`
|
|
201
|
-
);
|
|
202
|
-
} else {
|
|
203
|
-
say(` Open Cursor (restart it if it was running), then enable ${MCP_SERVER_KEY} under Settings \u2192 MCP.`);
|
|
204
|
-
}
|
|
205
|
-
writeSkill(cursorDir);
|
|
206
|
-
connected += 1;
|
|
206
|
+
merged = mergedCursorConfig(existing, { endpoint, token });
|
|
207
207
|
} catch {
|
|
208
208
|
say(`Cursor \u2014 ${configPath} is not valid JSON, so it was left untouched.`);
|
|
209
209
|
say(" Fix or remove that file, then run this command again.");
|
|
210
210
|
}
|
|
211
|
+
if (merged) {
|
|
212
|
+
try {
|
|
213
|
+
mkdirSync(dirname(configPath), { recursive: true });
|
|
214
|
+
writeFileSync(configPath, merged.text);
|
|
215
|
+
say(
|
|
216
|
+
merged.replaced ? `Cursor \u2014 updated the ${MCP_SERVER_KEY} server in ${configPath}.` : `Cursor \u2014 added the ${MCP_SERVER_KEY} server to ${configPath}.`
|
|
217
|
+
);
|
|
218
|
+
if (openCursor()) {
|
|
219
|
+
say(
|
|
220
|
+
` Cursor is opening \u2014 enable ${MCP_SERVER_KEY} under Settings \u2192 MCP. If it was already running, restart it first.`
|
|
221
|
+
);
|
|
222
|
+
} else {
|
|
223
|
+
say(` Open Cursor (restart it if it was running), then enable ${MCP_SERVER_KEY} under Settings \u2192 MCP.`);
|
|
224
|
+
}
|
|
225
|
+
writeSkill(cursorDir);
|
|
226
|
+
connected += 1;
|
|
227
|
+
} catch {
|
|
228
|
+
say(`Cursor \u2014 ${configPath} could not be written, so it was left as it was.`);
|
|
229
|
+
say(
|
|
230
|
+
' A sandboxed agent usually cannot write outside its workspace. Run this same command in a regular terminal, or add this under "mcpServers" in that file (or in .cursor/mcp.json inside the project, which connects this project alone):'
|
|
231
|
+
);
|
|
232
|
+
process.stdout.write(
|
|
233
|
+
`${JSON.stringify({ [MCP_SERVER_KEY]: cursorServerEntry({ endpoint, token }) }, null, 2)}
|
|
234
|
+
`
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
211
238
|
}
|
|
212
239
|
if (onlyClaude || autodetect && hasCli("claude")) {
|
|
213
240
|
attempted += 1;
|
|
@@ -255,16 +282,27 @@ async function main() {
|
|
|
255
282
|
const result = appendedCodexConfig(existing, { endpoint, token });
|
|
256
283
|
if (result.alreadyPresent) {
|
|
257
284
|
say(`Codex \u2014 ${configPath} already names a ${MCP_SERVER_KEY} server, so it was left as it is.`);
|
|
258
|
-
say(" If that connection is stale, update
|
|
285
|
+
say(" If that connection is stale, update the http_headers Authorization value there by hand.");
|
|
259
286
|
writeSkill(codexDir);
|
|
260
287
|
connected += 1;
|
|
261
288
|
} else {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
289
|
+
try {
|
|
290
|
+
mkdirSync(dirname(configPath), { recursive: true });
|
|
291
|
+
writeFileSync(configPath, result.text);
|
|
292
|
+
say(
|
|
293
|
+
result.repaired ? `Codex \u2014 replaced the ${MCP_SERVER_KEY} entry in ${configPath}: its old bearer_token spelling makes current Codex reject the whole config.` : `Codex \u2014 added the ${MCP_SERVER_KEY} server to ${configPath}.`
|
|
294
|
+
);
|
|
295
|
+
say(" The app and the CLI both read this config \u2014 open either and it connects when a session starts.");
|
|
296
|
+
writeSkill(codexDir);
|
|
297
|
+
connected += 1;
|
|
298
|
+
} catch {
|
|
299
|
+
say(`Codex \u2014 ${configPath} could not be written, so it was left as it was.`);
|
|
300
|
+
say(
|
|
301
|
+
" A sandboxed agent usually cannot write outside its workspace. Run this same command in a regular terminal, or append this block to that file yourself:"
|
|
302
|
+
);
|
|
303
|
+
process.stdout.write(`${codexConfigBlock({ endpoint, token })}
|
|
304
|
+
`);
|
|
305
|
+
}
|
|
268
306
|
}
|
|
269
307
|
}
|
|
270
308
|
if (connected === 0) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@super-hands/connect",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Connect the coding agents on this machine to your team's Superhands MCP server. Writes each client's own config; reads no repository, uploads nothing.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"superhands-connect": "client.mjs"
|