@nado-language/mcp 0.1.3 → 0.1.5
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 +13 -0
- package/dist/nado-mcp-auth.mjs +63 -11
- package/dist/nado-mcp-cli.mjs +23 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -54,6 +54,8 @@ NADO_MCP_REFRESH_TOKEN='supabase-user-refresh-token'
|
|
|
54
54
|
|
|
55
55
|
By default this uses the existing Azure Static Web Apps production site as a static OAuth relay. It does not require a new Azure Function, App Service, database, or paid runtime. The local helper still receives the final callback on `127.0.0.1`; Azure only serves the static relay page.
|
|
56
56
|
|
|
57
|
+
The installed CLI opens the Nado relay page first. The relay stores the local callback in browser session storage, then sends Supabase a fixed redirect URL. This avoids Supabase rejecting a dynamic `redirect_to` URL with `local_callback` query parameters and falling back to the normal Nado web site.
|
|
58
|
+
|
|
57
59
|
The MCP server refreshes expired access tokens with `NADO_MCP_REFRESH_TOKEN` and updates the auth file when Supabase rotates the refresh token.
|
|
58
60
|
|
|
59
61
|
Supported local browser providers are `google`, `kakao`, and `apple`. Naver login is not available in the local MCP flow yet because the current Naver Edge Function uses fixed web/native redirect URLs.
|
|
@@ -64,6 +66,8 @@ Supabase Auth must allow the Azure relay redirect URL:
|
|
|
64
66
|
https://language.nado.ai.kr/auth/mcp-callback
|
|
65
67
|
```
|
|
66
68
|
|
|
69
|
+
Register the exact URL above. Do not include `local_callback`, `provider`, or other query parameters in the Supabase allow list.
|
|
70
|
+
|
|
67
71
|
For direct local callback mode, run with `--redirect-mode local` and allow:
|
|
68
72
|
|
|
69
73
|
```text
|
|
@@ -73,6 +77,7 @@ http://127.0.0.1:*/callback
|
|
|
73
77
|
You can inspect or clear local MCP auth with:
|
|
74
78
|
|
|
75
79
|
```bash
|
|
80
|
+
nado-mcp --version
|
|
76
81
|
nado-mcp status
|
|
77
82
|
nado-mcp logout
|
|
78
83
|
```
|
|
@@ -84,6 +89,14 @@ npm run mcp:nado:auth -- status
|
|
|
84
89
|
npm run mcp:nado:auth -- logout
|
|
85
90
|
```
|
|
86
91
|
|
|
92
|
+
If the browser shows an error about an old, incomplete, truncated, or invalid PKCE login URL, close every old Nado MCP login tab, upgrade the package, and rerun login. Printed login URLs are single-run URLs and should not be reused:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
npm install --global @nado-language/mcp@latest
|
|
96
|
+
nado-mcp --version
|
|
97
|
+
nado-mcp login --provider google
|
|
98
|
+
```
|
|
99
|
+
|
|
87
100
|
Manual access-token option:
|
|
88
101
|
|
|
89
102
|
```bash
|
package/dist/nado-mcp-auth.mjs
CHANGED
|
@@ -16,12 +16,15 @@ const SUPPORTED_REDIRECT_MODES = new Set(['azure', 'local']);
|
|
|
16
16
|
|
|
17
17
|
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
|
18
18
|
const repoRoot = path.resolve(scriptDir, '..');
|
|
19
|
+
const packageVersion = readPackageVersion();
|
|
19
20
|
|
|
20
21
|
const { command, options } = parseCli(process.argv.slice(2));
|
|
21
22
|
|
|
22
23
|
try {
|
|
23
24
|
if (options.help || command === 'help') {
|
|
24
25
|
printHelp();
|
|
26
|
+
} else if (command === 'version') {
|
|
27
|
+
console.log(packageVersion);
|
|
25
28
|
} else if (command === 'login') {
|
|
26
29
|
await login(options);
|
|
27
30
|
} else if (command === 'status') {
|
|
@@ -39,7 +42,10 @@ try {
|
|
|
39
42
|
function parseCli(argv) {
|
|
40
43
|
let command = 'login';
|
|
41
44
|
let args = argv;
|
|
42
|
-
if (argv[0]
|
|
45
|
+
if (argv[0] === '--version' || argv[0] === '-v') {
|
|
46
|
+
command = 'version';
|
|
47
|
+
args = argv.slice(1);
|
|
48
|
+
} else if (argv[0] && !argv[0].startsWith('-')) {
|
|
43
49
|
command = argv[0];
|
|
44
50
|
args = argv.slice(1);
|
|
45
51
|
}
|
|
@@ -77,6 +83,7 @@ function parseCli(argv) {
|
|
|
77
83
|
else if (flag === '--timeout-ms') options.timeoutMs = Number(readValue());
|
|
78
84
|
else if (flag === '--no-open') options.noOpen = true;
|
|
79
85
|
else if (flag === '--help' || flag === '-h') options.help = true;
|
|
86
|
+
else if (flag === '--version' || flag === '-v') command = 'version';
|
|
80
87
|
else throw new Error(`Unknown option: ${arg}`);
|
|
81
88
|
}
|
|
82
89
|
|
|
@@ -183,19 +190,18 @@ async function login(options) {
|
|
|
183
190
|
|
|
184
191
|
const localCallbackUrl = new URL(`http://127.0.0.1:${address.port}/callback`);
|
|
185
192
|
localCallbackUrl.searchParams.set('state', state);
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
supabaseUrl: options.supabaseUrl,
|
|
193
|
+
const browserUrl = buildBrowserLoginUrl({
|
|
194
|
+
options,
|
|
189
195
|
provider,
|
|
190
|
-
|
|
196
|
+
localCallbackUrl: localCallbackUrl.toString(),
|
|
191
197
|
codeChallenge,
|
|
192
198
|
});
|
|
193
199
|
|
|
194
200
|
console.log(`Opening browser for Nado MCP login (${provider}).`);
|
|
195
201
|
console.log(`Local callback: ${localCallbackUrl.toString()}`);
|
|
196
202
|
if (options.redirectMode === 'azure') console.log(`Azure relay: ${options.relayUrl}`);
|
|
197
|
-
if (!options.noOpen) openBrowser(
|
|
198
|
-
console.log(`If the browser did not open, visit:\n${
|
|
203
|
+
if (!options.noOpen) openBrowser(browserUrl);
|
|
204
|
+
console.log(`If the browser did not open, visit:\n${browserUrl}`);
|
|
199
205
|
|
|
200
206
|
let timeoutId;
|
|
201
207
|
const timeout = new Promise((_, reject) => {
|
|
@@ -217,18 +223,40 @@ function loginTimeoutError(options) {
|
|
|
217
223
|
'Timed out waiting for browser login.',
|
|
218
224
|
`Rerun \`nado-mcp login --provider ${options.provider} --timeout-ms 900000\` and keep the terminal open until the browser says login completed.`,
|
|
219
225
|
'If the browser did not open, copy the printed URL into the same desktop browser where you can sign in.',
|
|
220
|
-
'If
|
|
226
|
+
'If Google login succeeds but the browser lands on the normal Nado site, upgrade @nado-language/mcp and confirm Supabase Auth allows the exact relay URL without query parameters.',
|
|
227
|
+
'If it still times out after the relay page says it is returning to the local helper, check that the browser can reach the printed 127.0.0.1 local callback URL.',
|
|
221
228
|
].join(' '));
|
|
222
229
|
}
|
|
223
230
|
|
|
224
|
-
function
|
|
225
|
-
if (options.redirectMode === 'local')
|
|
231
|
+
function buildBrowserLoginUrl({ options, provider, localCallbackUrl, codeChallenge }) {
|
|
232
|
+
if (options.redirectMode === 'local') {
|
|
233
|
+
return buildAuthorizeUrl({
|
|
234
|
+
supabaseUrl: options.supabaseUrl,
|
|
235
|
+
provider,
|
|
236
|
+
redirectTo: localCallbackUrl,
|
|
237
|
+
codeChallenge,
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return buildRelayStartUrl({
|
|
242
|
+
relayUrl: options.relayUrl,
|
|
243
|
+
localCallbackUrl,
|
|
244
|
+
provider,
|
|
245
|
+
supabaseUrl: options.supabaseUrl,
|
|
246
|
+
codeChallenge,
|
|
247
|
+
});
|
|
248
|
+
}
|
|
226
249
|
|
|
227
|
-
|
|
250
|
+
function buildRelayStartUrl({ relayUrl: value, localCallbackUrl, provider, supabaseUrl, codeChallenge }) {
|
|
251
|
+
const relayUrl = new URL(value);
|
|
228
252
|
if (relayUrl.protocol !== 'https:') {
|
|
229
253
|
throw new Error('--relay-url must be an HTTPS URL when --redirect-mode azure is used.');
|
|
230
254
|
}
|
|
231
255
|
relayUrl.searchParams.set('local_callback', localCallbackUrl);
|
|
256
|
+
relayUrl.searchParams.set('provider', provider);
|
|
257
|
+
relayUrl.searchParams.set('supabase_url', supabaseUrl);
|
|
258
|
+
relayUrl.searchParams.set('code_challenge', codeChallenge);
|
|
259
|
+
relayUrl.searchParams.set('client_version', packageVersion);
|
|
232
260
|
return relayUrl.toString();
|
|
233
261
|
}
|
|
234
262
|
|
|
@@ -436,6 +464,24 @@ function resolvePath(value) {
|
|
|
436
464
|
return path.isAbsolute(value) ? value : path.resolve(process.cwd(), value);
|
|
437
465
|
}
|
|
438
466
|
|
|
467
|
+
function readPackageVersion() {
|
|
468
|
+
const candidates = [
|
|
469
|
+
path.join(repoRoot, 'packages', 'nado-mcp', 'package.json'),
|
|
470
|
+
path.join(scriptDir, '..', 'package.json'),
|
|
471
|
+
];
|
|
472
|
+
for (const filePath of candidates) {
|
|
473
|
+
try {
|
|
474
|
+
const pkg = JSON.parse(readFileSync(filePath, 'utf8'));
|
|
475
|
+
if (pkg?.name === '@nado-language/mcp' && typeof pkg.version === 'string') {
|
|
476
|
+
return pkg.version;
|
|
477
|
+
}
|
|
478
|
+
} catch {
|
|
479
|
+
// Continue to the next candidate.
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
return '0.0.0-dev';
|
|
483
|
+
}
|
|
484
|
+
|
|
439
485
|
function listen(server, port) {
|
|
440
486
|
return new Promise((resolve, reject) => {
|
|
441
487
|
server.once('error', reject);
|
|
@@ -477,6 +523,7 @@ Usage:
|
|
|
477
523
|
nado-mcp login [--provider google|kakao|apple]
|
|
478
524
|
nado-mcp status
|
|
479
525
|
nado-mcp logout
|
|
526
|
+
nado-mcp-auth --version
|
|
480
527
|
|
|
481
528
|
Repo checkout aliases:
|
|
482
529
|
npm run mcp:nado:auth -- [login] [--provider google|kakao|apple]
|
|
@@ -493,11 +540,16 @@ Options:
|
|
|
493
540
|
--timeout-ms <number> Login wait timeout. Default: 300000
|
|
494
541
|
--supabase-url <url> Supabase project URL
|
|
495
542
|
--anon-key <key> Supabase anon key
|
|
543
|
+
--version Print installed Nado MCP version
|
|
496
544
|
|
|
497
545
|
Default mode uses the existing Azure Static Web Apps site as a zero-new-resource
|
|
498
546
|
OAuth relay. Supabase Auth must allow this redirect URL:
|
|
499
547
|
${DEFAULT_RELAY_URL}
|
|
500
548
|
|
|
549
|
+
The relay starts login with local state in browser sessionStorage, then sends
|
|
550
|
+
Supabase the fixed redirect URL above. Do not add local_callback query strings
|
|
551
|
+
to the Supabase allow list.
|
|
552
|
+
|
|
501
553
|
The optional local mode requires Supabase Auth to allow:
|
|
502
554
|
http://127.0.0.1:*/callback
|
|
503
555
|
`);
|
package/dist/nado-mcp-cli.mjs
CHANGED
|
@@ -11,6 +11,7 @@ const sourceRoot = path.resolve(scriptDir, '..');
|
|
|
11
11
|
const packageDistDir = scriptDir;
|
|
12
12
|
const serverName = 'nado-language';
|
|
13
13
|
const opencodeSchema = 'https://opencode.ai/config.json';
|
|
14
|
+
const packageVersion = readPackageVersion();
|
|
14
15
|
|
|
15
16
|
const serverPath = firstExisting([
|
|
16
17
|
path.join(packageDistDir, 'nado-language-server.mjs'),
|
|
@@ -31,6 +32,8 @@ const args = process.argv.slice(3);
|
|
|
31
32
|
try {
|
|
32
33
|
if (command === 'help' || command === '--help' || command === '-h') {
|
|
33
34
|
printHelp();
|
|
35
|
+
} else if (command === 'version' || command === '--version' || command === '-v') {
|
|
36
|
+
console.log(packageVersion);
|
|
34
37
|
} else if (command === 'server') {
|
|
35
38
|
await runNode(serverPath, args, { stdio: 'inherit' });
|
|
36
39
|
} else if (command === 'login') {
|
|
@@ -240,6 +243,7 @@ async function doctor() {
|
|
|
240
243
|
const probe = probeTools();
|
|
241
244
|
|
|
242
245
|
console.log('Nado MCP doctor');
|
|
246
|
+
console.log(`Version: ${packageVersion}`);
|
|
243
247
|
console.log(`Node: ${process.version}`);
|
|
244
248
|
console.log(`Server: ${serverPath}${existsSync(serverPath) ? '' : ' (missing)'}`);
|
|
245
249
|
console.log(`Auth CLI: ${authPath}${existsSync(authPath) ? '' : ' (missing)'}`);
|
|
@@ -789,6 +793,24 @@ function expandHome(value) {
|
|
|
789
793
|
return text;
|
|
790
794
|
}
|
|
791
795
|
|
|
796
|
+
function readPackageVersion() {
|
|
797
|
+
const candidates = [
|
|
798
|
+
path.join(sourceRoot, 'packages', 'nado-mcp', 'package.json'),
|
|
799
|
+
path.join(packageDistDir, '..', 'package.json'),
|
|
800
|
+
];
|
|
801
|
+
for (const filePath of candidates) {
|
|
802
|
+
try {
|
|
803
|
+
const pkg = JSON.parse(readFileSync(filePath, 'utf8'));
|
|
804
|
+
if (pkg?.name === '@nado-language/mcp' && typeof pkg.version === 'string') {
|
|
805
|
+
return pkg.version;
|
|
806
|
+
}
|
|
807
|
+
} catch {
|
|
808
|
+
// Continue to the next candidate.
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
return '0.0.0-dev';
|
|
812
|
+
}
|
|
813
|
+
|
|
792
814
|
function printHelp() {
|
|
793
815
|
console.log(`Nado Language MCP
|
|
794
816
|
|
|
@@ -807,6 +829,7 @@ Usage:
|
|
|
807
829
|
nado-mcp server Start the stdio MCP server
|
|
808
830
|
nado-mcp probe list List exposed MCP tools
|
|
809
831
|
nado-mcp doctor Print local paths and auth status
|
|
832
|
+
nado-mcp --version Print installed Nado MCP version
|
|
810
833
|
|
|
811
834
|
Supported automatic setup clients:
|
|
812
835
|
codex, claude, opencode
|