modality-ai 0.7.5 → 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/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,11 +129474,16 @@ 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;
|
|
129480
129484
|
_rejectCode;
|
|
129481
129485
|
_pendingCode;
|
|
129486
|
+
_codeSettled = false;
|
|
129482
129487
|
_codeVerifier;
|
|
129483
129488
|
_clientInfo;
|
|
129484
129489
|
_tokens;
|
|
@@ -129486,6 +129491,10 @@ class CLIBrowserOAuthProvider {
|
|
|
129486
129491
|
constructor(options = {}) {
|
|
129487
129492
|
this._clientName = options.clientName ?? "mcp-cli";
|
|
129488
129493
|
this._noOpen = options.noOpen ?? false;
|
|
129494
|
+
this._onAuthorizationUrl = options.onAuthorizationUrl;
|
|
129495
|
+
this._state = randomBytes(16).toString("hex");
|
|
129496
|
+
this._callbackPath = options.externalCallback?.path ?? "/callback";
|
|
129497
|
+
this._callbackHost = options.externalCallback?.host ?? "127.0.0.1";
|
|
129489
129498
|
this._serverIdentity = options.serverUrl ? resolveServerIdentity(options.serverUrl) : null;
|
|
129490
129499
|
if (options.serverUrl === null) {
|
|
129491
129500
|
this._cachePath = null;
|
|
@@ -129505,11 +129514,15 @@ class CLIBrowserOAuthProvider {
|
|
|
129505
129514
|
this._resolveCode = resolve2;
|
|
129506
129515
|
this._rejectCode = reject3;
|
|
129507
129516
|
});
|
|
129508
|
-
|
|
129509
|
-
|
|
129510
|
-
|
|
129511
|
-
|
|
129512
|
-
|
|
129517
|
+
if (options.externalCallback) {
|
|
129518
|
+
this._port = options.externalCallback.port;
|
|
129519
|
+
} else {
|
|
129520
|
+
this._server = Bun.serve({
|
|
129521
|
+
port: options.callbackPort ?? 9876,
|
|
129522
|
+
fetch: (req) => this._handleCallback(req)
|
|
129523
|
+
});
|
|
129524
|
+
this._port = this._server.port ?? 9876;
|
|
129525
|
+
}
|
|
129513
129526
|
if (this._clientInfo) {
|
|
129514
129527
|
const uris = this._clientInfo.redirect_uris ?? [];
|
|
129515
129528
|
if (!uris.includes(this.redirectUrl)) {
|
|
@@ -129518,7 +129531,7 @@ class CLIBrowserOAuthProvider {
|
|
|
129518
129531
|
}
|
|
129519
129532
|
}
|
|
129520
129533
|
get redirectUrl() {
|
|
129521
|
-
return `http
|
|
129534
|
+
return `http://${this._callbackHost}:${this._port}${this._callbackPath}`;
|
|
129522
129535
|
}
|
|
129523
129536
|
get clientMetadata() {
|
|
129524
129537
|
const identity7 = this._serverIdentity;
|
|
@@ -129569,7 +129582,11 @@ class CLIBrowserOAuthProvider {
|
|
|
129569
129582
|
params.set("client_secret", secret3);
|
|
129570
129583
|
}
|
|
129571
129584
|
};
|
|
129585
|
+
state() {
|
|
129586
|
+
return this._state;
|
|
129587
|
+
}
|
|
129572
129588
|
async redirectToAuthorization(authorizationUrl) {
|
|
129589
|
+
this._onAuthorizationUrl?.(authorizationUrl);
|
|
129573
129590
|
const url5 = authorizationUrl.toString();
|
|
129574
129591
|
if (this._noOpen) {
|
|
129575
129592
|
console.error(`
|
|
@@ -129592,6 +129609,15 @@ class CLIBrowserOAuthProvider {
|
|
|
129592
129609
|
waitForCode() {
|
|
129593
129610
|
return this._pendingCode;
|
|
129594
129611
|
}
|
|
129612
|
+
get oauthState() {
|
|
129613
|
+
return this.state();
|
|
129614
|
+
}
|
|
129615
|
+
get callbackPath() {
|
|
129616
|
+
return this._callbackPath;
|
|
129617
|
+
}
|
|
129618
|
+
handleCallback(req) {
|
|
129619
|
+
return this._handleCallback(req);
|
|
129620
|
+
}
|
|
129595
129621
|
getDiscoveryState() {
|
|
129596
129622
|
return this._discoveryState;
|
|
129597
129623
|
}
|
|
@@ -129600,7 +129626,7 @@ class CLIBrowserOAuthProvider {
|
|
|
129600
129626
|
this._persistCache();
|
|
129601
129627
|
}
|
|
129602
129628
|
stop() {
|
|
129603
|
-
this._server
|
|
129629
|
+
this._server?.stop(true);
|
|
129604
129630
|
}
|
|
129605
129631
|
_loadCache() {
|
|
129606
129632
|
if (!this._cachePath)
|
|
@@ -129626,20 +129652,32 @@ class CLIBrowserOAuthProvider {
|
|
|
129626
129652
|
}
|
|
129627
129653
|
_handleCallback(req) {
|
|
129628
129654
|
const url5 = new URL(req.url);
|
|
129629
|
-
if (url5.pathname !==
|
|
129655
|
+
if (url5.pathname !== this._callbackPath) {
|
|
129630
129656
|
return new Response("Not found", { status: 404 });
|
|
129631
129657
|
}
|
|
129658
|
+
if (this._codeSettled) {
|
|
129659
|
+
return errorPage("already_completed", "Authorization code was already received.");
|
|
129660
|
+
}
|
|
129661
|
+
const returnedState = url5.searchParams.get("state");
|
|
129662
|
+
if (returnedState !== null && returnedState !== this._state) {
|
|
129663
|
+
this._codeSettled = true;
|
|
129664
|
+
this._rejectCode?.(new Error("OAuth state mismatch"));
|
|
129665
|
+
return errorPage("state_mismatch", "State parameter did not match.");
|
|
129666
|
+
}
|
|
129632
129667
|
const error54 = url5.searchParams.get("error");
|
|
129633
129668
|
if (error54) {
|
|
129634
129669
|
const description = url5.searchParams.get("error_description") ?? "";
|
|
129670
|
+
this._codeSettled = true;
|
|
129635
129671
|
this._rejectCode?.(new Error(`OAuth error: ${error54} — ${description}`));
|
|
129636
129672
|
return errorPage(error54, description);
|
|
129637
129673
|
}
|
|
129638
129674
|
const code = url5.searchParams.get("code");
|
|
129639
129675
|
if (!code) {
|
|
129676
|
+
this._codeSettled = true;
|
|
129640
129677
|
this._rejectCode?.(new Error("OAuth callback missing authorization code"));
|
|
129641
129678
|
return errorPage("no_code", "No authorization code received.");
|
|
129642
129679
|
}
|
|
129680
|
+
this._codeSettled = true;
|
|
129643
129681
|
this._resolveCode?.(code);
|
|
129644
129682
|
return successPage();
|
|
129645
129683
|
}
|
|
@@ -129686,6 +129724,9 @@ function successPage() {
|
|
|
129686
129724
|
</html>`;
|
|
129687
129725
|
return new Response(body, { status: 200, headers: { "Content-Type": "text/html" } });
|
|
129688
129726
|
}
|
|
129727
|
+
function escapeHtml2(s) {
|
|
129728
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
129729
|
+
}
|
|
129689
129730
|
function errorPage(error54, description) {
|
|
129690
129731
|
const body = `<!DOCTYPE html>
|
|
129691
129732
|
<html lang="en">
|
|
@@ -129723,7 +129764,7 @@ function errorPage(error54, description) {
|
|
|
129723
129764
|
<div class="card">
|
|
129724
129765
|
<span class="icon">❌</span>
|
|
129725
129766
|
<h1>Authentication failed</h1>
|
|
129726
|
-
<p><code>${error54}</code>${description ? `: ${description}` : ""}</p>
|
|
129767
|
+
<p><code>${escapeHtml2(error54)}</code>${description ? `: ${escapeHtml2(description)}` : ""}</p>
|
|
129727
129768
|
</div>
|
|
129728
129769
|
</body>
|
|
129729
129770
|
</html>`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -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,11 +78,16 @@ 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;
|
|
90
|
+
private _codeSettled;
|
|
66
91
|
private _codeVerifier?;
|
|
67
92
|
private _clientInfo?;
|
|
68
93
|
private _tokens?;
|
|
@@ -89,16 +114,36 @@ export declare class CLIBrowserOAuthProvider implements OAuthClientProvider {
|
|
|
89
114
|
* auth-method string the registration response contained.
|
|
90
115
|
*/
|
|
91
116
|
readonly addClientAuthentication: AddClientAuthentication;
|
|
117
|
+
/**
|
|
118
|
+
* CSRF `state` echoed back on the redirect. The SDK reads this via the
|
|
119
|
+
* optional `state()` hook and appends it to the authorization request; the
|
|
120
|
+
* callback validates it. Also used by host apps to correlate an external
|
|
121
|
+
* callback to this provider instance.
|
|
122
|
+
*/
|
|
123
|
+
state(): string;
|
|
92
124
|
redirectToAuthorization(authorizationUrl: URL): Promise<void>;
|
|
93
125
|
/**
|
|
94
126
|
* Resolves with the authorization code once the browser redirect completes.
|
|
95
127
|
*/
|
|
96
128
|
waitForCode(): Promise<string>;
|
|
129
|
+
/** CSRF state for this flow — key an external callback route by this value. */
|
|
130
|
+
get oauthState(): string;
|
|
131
|
+
/** Advertised redirect path — the route an external host server must expose. */
|
|
132
|
+
get callbackPath(): string;
|
|
133
|
+
/**
|
|
134
|
+
* Handle an OAuth redirect request forwarded from an external host server
|
|
135
|
+
* (externalCallback mode). Resolves waitForCode() and returns the page to
|
|
136
|
+
* render in the browser tab.
|
|
137
|
+
*/
|
|
138
|
+
handleCallback(req: Request): Response;
|
|
97
139
|
/** Discovery state captured before registration — available even when registration fails. */
|
|
98
140
|
getDiscoveryState(): OAuthDiscoveryState | undefined;
|
|
99
141
|
/** Clear cached tokens only — forces browser re-auth on next run while keeping client registration. */
|
|
100
142
|
clearCache(): void;
|
|
101
|
-
/**
|
|
143
|
+
/**
|
|
144
|
+
* Stop the local callback HTTP server. Call once auth is complete.
|
|
145
|
+
* No-op in externalCallback mode, where the host owns the server.
|
|
146
|
+
*/
|
|
102
147
|
stop(): void;
|
|
103
148
|
private _loadCache;
|
|
104
149
|
private _persistCache;
|
package/package.json
CHANGED