@ainecto/mcp 0.8.0 → 0.8.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 CHANGED
@@ -174,7 +174,7 @@ This is the entry `setup` and `init --mcp` write — you normally do not add it
174
174
  "mcpServers": {
175
175
  "ainecto": {
176
176
  "command": "npx",
177
- "args": ["-y", "@ainecto/mcp@0.8.0"]
177
+ "args": ["-y", "@ainecto/mcp@0.8.1"]
178
178
  }
179
179
  }
180
180
  }
@@ -185,6 +185,15 @@ var OAuthLoginError = class extends Error {
185
185
  }
186
186
  code;
187
187
  };
188
+ var OAuthReauthRequiredError = class extends Error {
189
+ constructor(oauthError, status) {
190
+ super(`The stored sign-in was rejected by the server (${oauthError}, HTTP ${status}). Sign in again.`);
191
+ this.oauthError = oauthError;
192
+ this.name = "OAuthReauthRequiredError";
193
+ }
194
+ oauthError;
195
+ };
196
+ var REAUTH_REQUIRED_ERRORS = /* @__PURE__ */ new Set(["invalid_grant", "invalid_client", "unauthorized_client"]);
188
197
  var OAuthClient = class {
189
198
  constructor(options) {
190
199
  this.options = options;
@@ -380,10 +389,32 @@ async function exchangeToken(tokenEndpoint, params, fetchImpl) {
380
389
  body: new URLSearchParams(params)
381
390
  });
382
391
  if (!response.ok) {
383
- throw new Error(`OAuth token exchange failed with HTTP ${response.status}.`);
392
+ const oauthError = await readOAuthErrorCode(response);
393
+ if (params.grant_type === "refresh_token" && oauthError !== void 0 && REAUTH_REQUIRED_ERRORS.has(oauthError)) {
394
+ throw new OAuthReauthRequiredError(oauthError, response.status);
395
+ }
396
+ throw new Error(`OAuth token exchange failed with HTTP ${response.status}${oauthError ? ` (${oauthError})` : ""}.`);
384
397
  }
385
398
  return response.json();
386
399
  }
400
+ async function readOAuthErrorCode(response) {
401
+ try {
402
+ const body = await response.json();
403
+ return typeof body.error === "string" ? body.error : void 0;
404
+ } catch {
405
+ return void 0;
406
+ }
407
+ }
408
+ async function usableAccessToken(auth) {
409
+ try {
410
+ return await auth.getAccessToken();
411
+ } catch (error) {
412
+ if (error instanceof OAuthReauthRequiredError) {
413
+ return void 0;
414
+ }
415
+ throw error;
416
+ }
417
+ }
387
418
  function toStoredToken(endpoint, token, metadata, previous) {
388
419
  if (typeof token.access_token !== "string") {
389
420
  throw new Error("OAuth token response did not include access_token.");
@@ -592,7 +623,7 @@ function legacyRoleInput(flag, envVars = process.env) {
592
623
 
593
624
  // src/core/version.ts
594
625
  var UNBUNDLED_VERSION = "dev";
595
- var CLI_VERSION = true ? "0.8.0" : UNBUNDLED_VERSION;
626
+ var CLI_VERSION = true ? "0.8.1" : UNBUNDLED_VERSION;
596
627
  var PACKAGE_NAME = "@ainecto/mcp";
597
628
  var CLI_USER_AGENT = `${PACKAGE_NAME} ${CLI_VERSION}`;
598
629
  function bridgePackageSpec(version = CLI_VERSION) {
@@ -4200,7 +4231,7 @@ async function executeSetupCommand(options) {
4200
4231
  }, { json: options.json }));
4201
4232
  return failed2 ? 1 : 0;
4202
4233
  }
4203
- let signedIn = Boolean(await options.auth.getAccessToken());
4234
+ let signedIn = Boolean(await usableAccessToken(options.auth));
4204
4235
  if (!signedIn && !args.dryRun) {
4205
4236
  await options.auth.login();
4206
4237
  options.io.stderr.write("Signed in.\n");
@@ -4616,18 +4647,9 @@ async function runAinectoCli(argv, io) {
4616
4647
  argv: parsed.positionals.slice(1),
4617
4648
  // 문서는 인증 후에 받는다 — 토큰이 없으면 패키지 기본값으로 가고, 그 사실을 보고한다.
4618
4649
  // ★«필요할 때» 가져온다. --undo 는 로컬 작업이라 토큰을 건드리지 않는다(S1).
4619
- // ★갱신 실패는 «토큰 없음»(→ 로그인)이지만, AINECTO_TOKEN 을 못 쓰는 주소라는 거절은 삼키지 않는다 —
4620
- // 삼키면 그 설정 오류가 브라우저 로그인으로 둔갑한다.
4621
- accessToken: async () => {
4622
- try {
4623
- return await auth.getAccessToken();
4624
- } catch (error) {
4625
- if (process.env.AINECTO_TOKEN) {
4626
- throw error;
4627
- }
4628
- return void 0;
4629
- }
4630
- },
4650
+ // ★판정은 setup 과 같은 {@link usableAccessToken} 하나 — 서버가 저장 로그인을 거절했으면 «없음»(→ 로그인),
4651
+ // 네트워크 장애·AINECTO_TOKEN 을 못 쓰는 주소라는 거절은 삼키지 않는다(브라우저 로그인으로 둔갑하지 않게).
4652
+ accessToken: () => usableAccessToken(auth),
4631
4653
  // 로그인한다 — `ainecto auth login` 과 같은 함수다. 서버마다 한 번이다.
4632
4654
  login: async () => {
4633
4655
  await auth.login();