@remcp/remcp 0.2.22 → 0.2.23
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/package.json +2 -2
- package/src/cli.mjs +22 -2
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remcp/remcp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.23",
|
|
4
4
|
"description": "ReMCP device client: pair a computer with ReMCP and run the outbound-only agent that hosts the local MCP runtime.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
|
-
"homepage": "https://remcp.
|
|
7
|
+
"homepage": "https://remcp.site",
|
|
8
8
|
"bin": {
|
|
9
9
|
"remcp": "bin/remcp.mjs"
|
|
10
10
|
},
|
package/src/cli.mjs
CHANGED
|
@@ -252,7 +252,9 @@ async function pairWithDeviceCode(server, flags) {
|
|
|
252
252
|
console.log(`Approve this computer in your browser: ${approvalUrl}`);
|
|
253
253
|
console.log(`Pairing code: ${grant.user_code} (expires in ${Math.max(1, Math.round(Number(grant.expires_in || 600) / 60))} minutes)`);
|
|
254
254
|
openInBrowser(approvalUrl);
|
|
255
|
+
console.log('Waiting for approval… (Ctrl+C to cancel)');
|
|
255
256
|
const deadline = Date.now() + (Number(grant.expires_in) || 600) * 1000;
|
|
257
|
+
let lastReminder = Date.now();
|
|
256
258
|
const intervalMs = Math.max(1, Number(grant.interval) || 5) * 1000;
|
|
257
259
|
while (Date.now() < deadline) {
|
|
258
260
|
await sleep(intervalMs);
|
|
@@ -262,11 +264,19 @@ async function pairWithDeviceCode(server, flags) {
|
|
|
262
264
|
body: new URLSearchParams({
|
|
263
265
|
grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
|
|
264
266
|
device_code: String(grant.device_code || ''),
|
|
267
|
+
machineId: ensureMachineId(),
|
|
265
268
|
}).toString(),
|
|
266
269
|
});
|
|
267
270
|
const data = await response.json().catch(() => ({}));
|
|
268
271
|
if (response.ok && data.device_token) return data;
|
|
269
|
-
if (data.error === 'authorization_pending' || data.error === 'slow_down')
|
|
272
|
+
if (data.error === 'authorization_pending' || data.error === 'slow_down') {
|
|
273
|
+
if (Date.now() - lastReminder > 60_000) {
|
|
274
|
+
lastReminder = Date.now();
|
|
275
|
+
const left = Math.max(0, Math.round((deadline - Date.now()) / 60_000));
|
|
276
|
+
console.log(`Still waiting — approve at ${approvalUrl} (about ${left} min left)`);
|
|
277
|
+
}
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
270
280
|
if (data.error === 'access_denied') throw new Error('That pairing request was denied in the browser. Run the command again if it was not you.');
|
|
271
281
|
if (data.error === 'expired_token') break;
|
|
272
282
|
throw new Error(`Pairing failed (${response.status}): ${JSON.stringify(data)}`);
|
|
@@ -434,7 +444,8 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
434
444
|
trustRuntime: Boolean(flags['trust-runtime']) || new URL(server).origin === officialOrigin,
|
|
435
445
|
};
|
|
436
446
|
saveConfig(config);
|
|
437
|
-
|
|
447
|
+
const accountEmail = String(paired.account?.email || '');
|
|
448
|
+
console.log(`Paired ${os.hostname()} with ${server}${accountEmail ? ` as ${accountEmail}` : ''}`);
|
|
438
449
|
if (flags.install) {
|
|
439
450
|
installPersistentAgent(config);
|
|
440
451
|
return;
|
|
@@ -443,6 +454,15 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
443
454
|
// a fresh machine expects the connection to be live when the command finishes. A workspace code
|
|
444
455
|
// keeps its old meaning (pair, then `remcp start` or `--install`).
|
|
445
456
|
if (!deviceInitiated) return;
|
|
457
|
+
// One question, and the machine survives a reboot afterwards. Nothing about the credential
|
|
458
|
+
// changes: the same revocable token is used either way.
|
|
459
|
+
if (!flags.install && process.stdin.isTTY) {
|
|
460
|
+
const answer = await new Promise(resolve => {
|
|
461
|
+
process.stdout.write('Install ReMCP as a background service so it stays connected after a reboot? [Y/n] ');
|
|
462
|
+
process.stdin.once('data', chunk => resolve(String(chunk).trim().toLowerCase()));
|
|
463
|
+
});
|
|
464
|
+
if (answer === '' || answer === 'y' || answer === 'yes') { installPersistentAgent(config); return; }
|
|
465
|
+
}
|
|
446
466
|
// Nobody supervises this machine yet, so the agent runs in this window: Ctrl+C disconnects it,
|
|
447
467
|
// which is the behaviour people expect from a command they just ran themselves.
|
|
448
468
|
console.log('ReMCP is connected. Keep this window open, or run `remcp install` for a background service. Press Ctrl+C to stop.');
|