modality-ai 0.5.3 → 0.5.4

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
@@ -138837,9 +138837,16 @@ import { createHash } from "node:crypto";
138837
138837
  import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
138838
138838
  import { homedir } from "node:os";
138839
138839
  import { join as join8 } from "node:path";
138840
+ var SERVER_IDENTITY_WHITELIST = {
138841
+ "figma.com": {
138842
+ client_name: "Claude Code",
138843
+ client_uri: "https://claude.ai"
138844
+ }
138845
+ };
138840
138846
 
138841
138847
  class CLIBrowserOAuthProvider {
138842
138848
  _clientName;
138849
+ _serverIdentity;
138843
138850
  _noOpen;
138844
138851
  _cachePath;
138845
138852
  _port;
@@ -138854,6 +138861,7 @@ class CLIBrowserOAuthProvider {
138854
138861
  constructor(options = {}) {
138855
138862
  this._clientName = options.clientName ?? "mcp-cli";
138856
138863
  this._noOpen = options.noOpen ?? false;
138864
+ this._serverIdentity = options.serverUrl ? resolveServerIdentity(options.serverUrl) : null;
138857
138865
  if (options.serverUrl === null) {
138858
138866
  this._cachePath = null;
138859
138867
  } else {
@@ -138873,19 +138881,27 @@ class CLIBrowserOAuthProvider {
138873
138881
  this._rejectCode = reject3;
138874
138882
  });
138875
138883
  this._server = Bun.serve({
138876
- port: options.callbackPort ?? 0,
138884
+ port: options.callbackPort ?? 9876,
138877
138885
  fetch: (req) => this._handleCallback(req)
138878
138886
  });
138879
- this._port = this._server.port ?? 0;
138887
+ this._port = this._server.port ?? 9876;
138888
+ if (this._clientInfo) {
138889
+ const uris = this._clientInfo.redirect_uris ?? [];
138890
+ if (!uris.includes(this.redirectUrl)) {
138891
+ this._clientInfo = undefined;
138892
+ }
138893
+ }
138880
138894
  }
138881
138895
  get redirectUrl() {
138882
138896
  return `http://127.0.0.1:${this._port}/callback`;
138883
138897
  }
138884
138898
  get clientMetadata() {
138899
+ const identity7 = this._serverIdentity;
138885
138900
  return {
138886
- client_name: this._clientName,
138901
+ client_name: identity7?.client_name ?? this._clientName,
138902
+ ...identity7?.client_uri ? { client_uri: identity7.client_uri } : {},
138887
138903
  redirect_uris: [this.redirectUrl],
138888
- grant_types: ["authorization_code"],
138904
+ grant_types: ["authorization_code", "refresh_token"],
138889
138905
  response_types: ["code"],
138890
138906
  token_endpoint_auth_method: "none"
138891
138907
  };
@@ -138918,6 +138934,16 @@ class CLIBrowserOAuthProvider {
138918
138934
  throw new Error("No PKCE code verifier saved");
138919
138935
  return this._codeVerifier;
138920
138936
  }
138937
+ addClientAuthentication = (_headers, params) => {
138938
+ const info3 = this._clientInfo;
138939
+ if (!info3)
138940
+ return;
138941
+ params.set("client_id", info3.client_id);
138942
+ const secret3 = info3.client_secret;
138943
+ if (secret3) {
138944
+ params.set("client_secret", secret3);
138945
+ }
138946
+ };
138921
138947
  async redirectToAuthorization(authorizationUrl) {
138922
138948
  const url5 = authorizationUrl.toString();
138923
138949
  if (this._noOpen) {
@@ -138945,13 +138971,8 @@ class CLIBrowserOAuthProvider {
138945
138971
  return this._discoveryState;
138946
138972
  }
138947
138973
  clearCache() {
138948
- this._clientInfo = undefined;
138949
138974
  this._tokens = undefined;
138950
- if (this._cachePath) {
138951
- try {
138952
- writeFileSync(this._cachePath, "{}");
138953
- } catch {}
138954
- }
138975
+ this._persistCache();
138955
138976
  }
138956
138977
  stop() {
138957
138978
  this._server.stop(true);
@@ -139097,6 +139118,20 @@ function openBrowser(url5) {
139097
139118
  function urlStorageKey(url5) {
139098
139119
  return createHash("sha1").update(url5).digest("hex").slice(0, 12);
139099
139120
  }
139121
+ function resolveServerIdentity(serverUrl) {
139122
+ let hostname4;
139123
+ try {
139124
+ hostname4 = new URL(serverUrl).hostname;
139125
+ } catch {
139126
+ return null;
139127
+ }
139128
+ for (const [key, identity7] of Object.entries(SERVER_IDENTITY_WHITELIST)) {
139129
+ if (hostname4 === key || hostname4.endsWith(`.${key}`)) {
139130
+ return identity7;
139131
+ }
139132
+ }
139133
+ return null;
139134
+ }
139100
139135
  export {
139101
139136
  setupStdioToHttpTools,
139102
139137
  mergeToolCallsAndResults,
@@ -1,4 +1,4 @@
1
- import type { OAuthClientProvider, OAuthDiscoveryState } from "@modelcontextprotocol/sdk/client/auth.js";
1
+ import type { OAuthClientProvider, OAuthDiscoveryState, AddClientAuthentication } from "@modelcontextprotocol/sdk/client/auth.js";
2
2
  import type { OAuthClientInformationMixed, OAuthClientMetadata, OAuthTokens } from "@modelcontextprotocol/sdk/shared/auth.js";
3
3
  interface CLIBrowserOAuthProviderOptions {
4
4
  /** Display name registered with the OAuth server. Default: "mcp-cli" */
@@ -10,9 +10,7 @@ interface CLIBrowserOAuthProviderOptions {
10
10
  clientId?: string;
11
11
  /**
12
12
  * Port for the local callback server.
13
- * 0 (default) picks a random available port.
14
- * Use a fixed port when registering an OAuth app manually so the redirect
15
- * URI stays stable across runs (e.g. callbackPort: 9876).
13
+ * Defaults to 9876 for a stable redirect_uri across runs.
16
14
  */
17
15
  callbackPort?: number;
18
16
  /**
@@ -57,6 +55,7 @@ interface CLIBrowserOAuthProviderOptions {
57
55
  */
58
56
  export declare class CLIBrowserOAuthProvider implements OAuthClientProvider {
59
57
  private readonly _clientName;
58
+ private readonly _serverIdentity;
60
59
  private readonly _noOpen;
61
60
  private readonly _cachePath;
62
61
  private _port;
@@ -79,6 +78,17 @@ export declare class CLIBrowserOAuthProvider implements OAuthClientProvider {
79
78
  discoveryState(): OAuthDiscoveryState | undefined;
80
79
  saveCodeVerifier(verifier: string): void;
81
80
  codeVerifier(): string;
81
+ /**
82
+ * Custom client authentication for token exchange.
83
+ *
84
+ * Figma's dynamic registration returns `token_endpoint_auth_method: "none"` yet
85
+ * also issues a `client_secret`. The MCP SDK honours the registered
86
+ * `token_endpoint_auth_method` and therefore sends only `client_id`, which Figma
87
+ * rejects. When a `client_secret` is present we always send it as
88
+ * `client_secret_post` so the credentials reach Figma regardless of whatever
89
+ * auth-method string the registration response contained.
90
+ */
91
+ readonly addClientAuthentication: AddClientAuthentication;
82
92
  redirectToAuthorization(authorizationUrl: URL): Promise<void>;
83
93
  /**
84
94
  * Resolves with the authorization code once the browser redirect completes.
@@ -86,7 +96,7 @@ export declare class CLIBrowserOAuthProvider implements OAuthClientProvider {
86
96
  waitForCode(): Promise<string>;
87
97
  /** Discovery state captured before registration — available even when registration fails. */
88
98
  getDiscoveryState(): OAuthDiscoveryState | undefined;
89
- /** Remove all persisted state for this server (forces re-registration + re-auth on next run). */
99
+ /** Clear cached tokens only forces browser re-auth on next run while keeping client registration. */
90
100
  clearCache(): void;
91
101
  /** Stop the local callback HTTP server. Call once auth is complete. */
92
102
  stop(): void;
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.5.3",
2
+ "version": "0.5.4",
3
3
  "name": "modality-ai",
4
4
  "repository": {
5
5
  "type": "git",