modality-ai 0.7.5 → 0.8.0

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/dist/index.js CHANGED
@@ -129458,7 +129458,7 @@ var setupStdioToHttpTools = async (client, mcpServer) => {
129458
129458
  return setupAITools(aiTools, mcpServer);
129459
129459
  };
129460
129460
  // src/mcp-oauth-provider.ts
129461
- import { createHash } from "node:crypto";
129461
+ import { createHash, randomBytes } from "node:crypto";
129462
129462
  import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
129463
129463
  import { homedir } from "node:os";
129464
129464
  import { join as join9 } from "node:path";
@@ -129474,6 +129474,10 @@ class CLIBrowserOAuthProvider {
129474
129474
  _serverIdentity;
129475
129475
  _noOpen;
129476
129476
  _cachePath;
129477
+ _callbackPath;
129478
+ _callbackHost;
129479
+ _state;
129480
+ _onAuthorizationUrl;
129477
129481
  _port;
129478
129482
  _server;
129479
129483
  _resolveCode;
@@ -129486,6 +129490,10 @@ class CLIBrowserOAuthProvider {
129486
129490
  constructor(options = {}) {
129487
129491
  this._clientName = options.clientName ?? "mcp-cli";
129488
129492
  this._noOpen = options.noOpen ?? false;
129493
+ this._onAuthorizationUrl = options.onAuthorizationUrl;
129494
+ this._state = randomBytes(16).toString("hex");
129495
+ this._callbackPath = options.externalCallback?.path ?? "/callback";
129496
+ this._callbackHost = options.externalCallback?.host ?? "127.0.0.1";
129489
129497
  this._serverIdentity = options.serverUrl ? resolveServerIdentity(options.serverUrl) : null;
129490
129498
  if (options.serverUrl === null) {
129491
129499
  this._cachePath = null;
@@ -129505,11 +129513,15 @@ class CLIBrowserOAuthProvider {
129505
129513
  this._resolveCode = resolve2;
129506
129514
  this._rejectCode = reject3;
129507
129515
  });
129508
- this._server = Bun.serve({
129509
- port: options.callbackPort ?? 9876,
129510
- fetch: (req) => this._handleCallback(req)
129511
- });
129512
- this._port = this._server.port ?? 9876;
129516
+ if (options.externalCallback) {
129517
+ this._port = options.externalCallback.port;
129518
+ } else {
129519
+ this._server = Bun.serve({
129520
+ port: options.callbackPort ?? 9876,
129521
+ fetch: (req) => this._handleCallback(req)
129522
+ });
129523
+ this._port = this._server.port ?? 9876;
129524
+ }
129513
129525
  if (this._clientInfo) {
129514
129526
  const uris = this._clientInfo.redirect_uris ?? [];
129515
129527
  if (!uris.includes(this.redirectUrl)) {
@@ -129518,7 +129530,7 @@ class CLIBrowserOAuthProvider {
129518
129530
  }
129519
129531
  }
129520
129532
  get redirectUrl() {
129521
- return `http://127.0.0.1:${this._port}/callback`;
129533
+ return `http://${this._callbackHost}:${this._port}${this._callbackPath}`;
129522
129534
  }
129523
129535
  get clientMetadata() {
129524
129536
  const identity7 = this._serverIdentity;
@@ -129569,7 +129581,11 @@ class CLIBrowserOAuthProvider {
129569
129581
  params.set("client_secret", secret3);
129570
129582
  }
129571
129583
  };
129584
+ state() {
129585
+ return this._state;
129586
+ }
129572
129587
  async redirectToAuthorization(authorizationUrl) {
129588
+ this._onAuthorizationUrl?.(authorizationUrl);
129573
129589
  const url5 = authorizationUrl.toString();
129574
129590
  if (this._noOpen) {
129575
129591
  console.error(`
@@ -129592,6 +129608,15 @@ class CLIBrowserOAuthProvider {
129592
129608
  waitForCode() {
129593
129609
  return this._pendingCode;
129594
129610
  }
129611
+ get oauthState() {
129612
+ return this._state;
129613
+ }
129614
+ get callbackPath() {
129615
+ return this._callbackPath;
129616
+ }
129617
+ handleCallback(req) {
129618
+ return this._handleCallback(req);
129619
+ }
129595
129620
  getDiscoveryState() {
129596
129621
  return this._discoveryState;
129597
129622
  }
@@ -129600,7 +129625,7 @@ class CLIBrowserOAuthProvider {
129600
129625
  this._persistCache();
129601
129626
  }
129602
129627
  stop() {
129603
- this._server.stop(true);
129628
+ this._server?.stop(true);
129604
129629
  }
129605
129630
  _loadCache() {
129606
129631
  if (!this._cachePath)
@@ -129626,9 +129651,14 @@ class CLIBrowserOAuthProvider {
129626
129651
  }
129627
129652
  _handleCallback(req) {
129628
129653
  const url5 = new URL(req.url);
129629
- if (url5.pathname !== "/callback") {
129654
+ if (url5.pathname !== this._callbackPath) {
129630
129655
  return new Response("Not found", { status: 404 });
129631
129656
  }
129657
+ const returnedState = url5.searchParams.get("state");
129658
+ if (returnedState !== null && returnedState !== this._state) {
129659
+ this._rejectCode?.(new Error("OAuth state mismatch"));
129660
+ return errorPage("state_mismatch", "State parameter did not match.");
129661
+ }
129632
129662
  const error54 = url5.searchParams.get("error");
129633
129663
  if (error54) {
129634
129664
  const description = url5.searchParams.get("error_description") ?? "";
@@ -11,8 +11,28 @@ interface CLIBrowserOAuthProviderOptions {
11
11
  /**
12
12
  * Port for the local callback server.
13
13
  * Defaults to 9876 for a stable redirect_uri across runs.
14
+ * Ignored when `externalCallback` is set.
14
15
  */
15
16
  callbackPort?: number;
17
+ /**
18
+ * Route the OAuth redirect through an existing HTTP server instead of
19
+ * starting a local Bun.serve. When set, the provider binds no port of its
20
+ * own — the host app must forward the redirect request to `handleCallback()`.
21
+ * `port`/`path`/`host` define the advertised redirect_uri and must match the
22
+ * host server (defaults: host "127.0.0.1", path "/callback").
23
+ * Correlate the inbound callback to this provider via `oauthState`.
24
+ */
25
+ externalCallback?: {
26
+ port: number;
27
+ path?: string;
28
+ host?: string;
29
+ };
30
+ /**
31
+ * Invoked with the full authorization URL just before the browser opens.
32
+ * Lets the host correlate the later callback to this provider (e.g. by
33
+ * reading the `state` query param, which equals `oauthState`).
34
+ */
35
+ onAuthorizationUrl?: (url: URL) => void;
16
36
  /**
17
37
  * Skip opening the system browser automatically.
18
38
  * When true the authorization URL is printed but not launched.
@@ -58,8 +78,12 @@ export declare class CLIBrowserOAuthProvider implements OAuthClientProvider {
58
78
  private readonly _serverIdentity;
59
79
  private readonly _noOpen;
60
80
  private readonly _cachePath;
81
+ private readonly _callbackPath;
82
+ private readonly _callbackHost;
83
+ private readonly _state;
84
+ private readonly _onAuthorizationUrl?;
61
85
  private _port;
62
- private _server;
86
+ private _server?;
63
87
  private _resolveCode?;
64
88
  private _rejectCode?;
65
89
  private _pendingCode;
@@ -89,16 +113,36 @@ export declare class CLIBrowserOAuthProvider implements OAuthClientProvider {
89
113
  * auth-method string the registration response contained.
90
114
  */
91
115
  readonly addClientAuthentication: AddClientAuthentication;
116
+ /**
117
+ * CSRF `state` echoed back on the redirect. The SDK reads this via the
118
+ * optional `state()` hook and appends it to the authorization request; the
119
+ * callback validates it. Also used by host apps to correlate an external
120
+ * callback to this provider instance.
121
+ */
122
+ state(): string;
92
123
  redirectToAuthorization(authorizationUrl: URL): Promise<void>;
93
124
  /**
94
125
  * Resolves with the authorization code once the browser redirect completes.
95
126
  */
96
127
  waitForCode(): Promise<string>;
128
+ /** CSRF state for this flow — key an external callback route by this value. */
129
+ get oauthState(): string;
130
+ /** Advertised redirect path — the route an external host server must expose. */
131
+ get callbackPath(): string;
132
+ /**
133
+ * Handle an OAuth redirect request forwarded from an external host server
134
+ * (externalCallback mode). Resolves waitForCode() and returns the page to
135
+ * render in the browser tab.
136
+ */
137
+ handleCallback(req: Request): Response;
97
138
  /** Discovery state captured before registration — available even when registration fails. */
98
139
  getDiscoveryState(): OAuthDiscoveryState | undefined;
99
140
  /** Clear cached tokens only — forces browser re-auth on next run while keeping client registration. */
100
141
  clearCache(): void;
101
- /** Stop the local callback HTTP server. Call once auth is complete. */
142
+ /**
143
+ * Stop the local callback HTTP server. Call once auth is complete.
144
+ * No-op in externalCallback mode, where the host owns the server.
145
+ */
102
146
  stop(): void;
103
147
  private _loadCache;
104
148
  private _persistCache;
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.7.5",
2
+ "version": "0.8.0",
3
3
  "name": "modality-ai",
4
4
  "repository": {
5
5
  "type": "git",