@mcp-ts/sdk 1.3.9 → 1.4.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/README.md +0 -1
- package/dist/adapters/langchain-adapter.js.map +1 -1
- package/dist/adapters/langchain-adapter.mjs.map +1 -1
- package/dist/client/index.d.mts +3 -189
- package/dist/client/index.d.ts +3 -189
- package/dist/client/index.js +218 -54
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +215 -55
- package/dist/client/index.mjs.map +1 -1
- package/dist/client/react.d.mts +29 -40
- package/dist/client/react.d.ts +29 -40
- package/dist/client/react.js +492 -147
- package/dist/client/react.js.map +1 -1
- package/dist/client/react.mjs +490 -149
- package/dist/client/react.mjs.map +1 -1
- package/dist/client/vue.d.mts +3 -2
- package/dist/client/vue.d.ts +3 -2
- package/dist/client/vue.js +239 -63
- package/dist/client/vue.js.map +1 -1
- package/dist/client/vue.mjs +236 -64
- package/dist/client/vue.mjs.map +1 -1
- package/dist/index-CQr9q0bF.d.mts +295 -0
- package/dist/index-nE_7Io0I.d.ts +295 -0
- package/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +315 -64
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +303 -65
- package/dist/index.mjs.map +1 -1
- package/dist/server/index.js +93 -10
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +88 -10
- package/dist/server/index.mjs.map +1 -1
- package/package.json +13 -11
- package/src/adapters/langchain-adapter.ts +1 -1
- package/src/client/core/app-host.ts +252 -65
- package/src/client/core/constants.ts +30 -0
- package/src/client/index.ts +6 -1
- package/src/client/react/index.ts +6 -1
- package/src/client/react/use-app-host.ts +13 -19
- package/src/client/react/use-mcp-apps.tsx +297 -125
- package/src/client/react/use-mcp.ts +75 -36
- package/src/client/utils/app-host-utils.ts +62 -0
- package/src/client/vue/use-mcp.ts +23 -12
- package/src/server/mcp/oauth-client.ts +31 -8
- package/src/server/storage/crypto.ts +92 -0
- package/src/server/storage/supabase-backend.ts +7 -6
package/dist/server/index.js
CHANGED
|
@@ -8,6 +8,7 @@ var auth_js = require('@modelcontextprotocol/sdk/client/auth.js');
|
|
|
8
8
|
var types_js = require('@modelcontextprotocol/sdk/types.js');
|
|
9
9
|
var fs2 = require('fs');
|
|
10
10
|
var path = require('path');
|
|
11
|
+
var crypto = require('crypto');
|
|
11
12
|
|
|
12
13
|
function _interopNamespace(e) {
|
|
13
14
|
if (e && e.__esModule) return e;
|
|
@@ -765,6 +766,77 @@ var SqliteStorage = class {
|
|
|
765
766
|
|
|
766
767
|
// src/server/storage/supabase-backend.ts
|
|
767
768
|
init_cjs_shims();
|
|
769
|
+
|
|
770
|
+
// src/server/storage/crypto.ts
|
|
771
|
+
init_cjs_shims();
|
|
772
|
+
var ALGORITHM = "aes-256-gcm";
|
|
773
|
+
var IV_LENGTH = 12;
|
|
774
|
+
var ENCRYPTION_PREFIX = "enc:1:";
|
|
775
|
+
var warningLogged = false;
|
|
776
|
+
function getKey() {
|
|
777
|
+
const keyString = process.env.STORAGE_ENCRYPTION_KEY;
|
|
778
|
+
if (!keyString) return null;
|
|
779
|
+
if (keyString.length === 64) {
|
|
780
|
+
return Buffer.from(keyString, "hex");
|
|
781
|
+
} else {
|
|
782
|
+
const keyBuffer = Buffer.alloc(32);
|
|
783
|
+
keyBuffer.write(keyString, 0, 32, "utf-8");
|
|
784
|
+
return keyBuffer;
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
function encryptObject(data) {
|
|
788
|
+
if (data === void 0 || data === null) return data;
|
|
789
|
+
const key = getKey();
|
|
790
|
+
if (!key) {
|
|
791
|
+
if (!warningLogged) {
|
|
792
|
+
console.warn("[mcp-ts][Storage] WARNING: STORAGE_ENCRYPTION_KEY is not set. Saving sensitive data in plain-text.");
|
|
793
|
+
warningLogged = true;
|
|
794
|
+
}
|
|
795
|
+
return data;
|
|
796
|
+
}
|
|
797
|
+
try {
|
|
798
|
+
const text = JSON.stringify(data);
|
|
799
|
+
const iv = crypto.randomBytes(IV_LENGTH);
|
|
800
|
+
const cipher = crypto.createCipheriv(ALGORITHM, key, iv);
|
|
801
|
+
let encrypted = cipher.update(text, "utf-8", "hex");
|
|
802
|
+
encrypted += cipher.final("hex");
|
|
803
|
+
const authTag = cipher.getAuthTag().toString("hex");
|
|
804
|
+
return `${ENCRYPTION_PREFIX}${iv.toString("hex")}:${authTag}:${encrypted}`;
|
|
805
|
+
} catch (e) {
|
|
806
|
+
console.error("[mcp-ts][Storage] Encryption failed, falling back to plain-text.", e);
|
|
807
|
+
return data;
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
function decryptObject(data) {
|
|
811
|
+
if (data === void 0 || data === null) return data;
|
|
812
|
+
if (typeof data !== "string" || !data.startsWith(ENCRYPTION_PREFIX)) {
|
|
813
|
+
return data;
|
|
814
|
+
}
|
|
815
|
+
const key = getKey();
|
|
816
|
+
if (!key) {
|
|
817
|
+
console.warn("[mcp-ts][Storage] WARNING: Found encrypted data but STORAGE_ENCRYPTION_KEY is missing. Returning raw encrypted string.");
|
|
818
|
+
return data;
|
|
819
|
+
}
|
|
820
|
+
try {
|
|
821
|
+
const parts = data.split(":");
|
|
822
|
+
if (parts.length !== 5) {
|
|
823
|
+
return data;
|
|
824
|
+
}
|
|
825
|
+
const iv = Buffer.from(parts[2], "hex");
|
|
826
|
+
const authTag = Buffer.from(parts[3], "hex");
|
|
827
|
+
const encryptedText = parts[4];
|
|
828
|
+
const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);
|
|
829
|
+
decipher.setAuthTag(authTag);
|
|
830
|
+
let decrypted = decipher.update(encryptedText, "hex", "utf-8");
|
|
831
|
+
decrypted += decipher.final("utf-8");
|
|
832
|
+
return JSON.parse(decrypted);
|
|
833
|
+
} catch (e) {
|
|
834
|
+
console.error("[mcp-ts][Storage] Decryption failed.", e);
|
|
835
|
+
return data;
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
// src/server/storage/supabase-backend.ts
|
|
768
840
|
var SupabaseStorageBackend = class {
|
|
769
841
|
constructor(supabase) {
|
|
770
842
|
this.supabase = supabase;
|
|
@@ -795,10 +867,10 @@ var SupabaseStorageBackend = class {
|
|
|
795
867
|
callbackUrl: row.callback_url,
|
|
796
868
|
createdAt: new Date(row.created_at).getTime(),
|
|
797
869
|
identity: row.identity,
|
|
798
|
-
headers: row.headers,
|
|
870
|
+
headers: decryptObject(row.headers),
|
|
799
871
|
active: row.active,
|
|
800
872
|
clientInformation: row.client_information,
|
|
801
|
-
tokens: row.tokens,
|
|
873
|
+
tokens: decryptObject(row.tokens),
|
|
802
874
|
codeVerifier: row.code_verifier,
|
|
803
875
|
clientId: row.client_id
|
|
804
876
|
};
|
|
@@ -819,10 +891,10 @@ var SupabaseStorageBackend = class {
|
|
|
819
891
|
callback_url: session.callbackUrl,
|
|
820
892
|
created_at: new Date(session.createdAt || Date.now()).toISOString(),
|
|
821
893
|
identity,
|
|
822
|
-
headers: session.headers,
|
|
894
|
+
headers: encryptObject(session.headers),
|
|
823
895
|
active: session.active ?? false,
|
|
824
896
|
client_information: session.clientInformation,
|
|
825
|
-
tokens: session.tokens,
|
|
897
|
+
tokens: encryptObject(session.tokens),
|
|
826
898
|
code_verifier: session.codeVerifier,
|
|
827
899
|
client_id: session.clientId,
|
|
828
900
|
expires_at: expiresAt
|
|
@@ -847,9 +919,9 @@ var SupabaseStorageBackend = class {
|
|
|
847
919
|
if ("transportType" in data) updateData.transport_type = data.transportType;
|
|
848
920
|
if ("callbackUrl" in data) updateData.callback_url = data.callbackUrl;
|
|
849
921
|
if ("active" in data) updateData.active = data.active;
|
|
850
|
-
if ("headers" in data) updateData.headers = data.headers;
|
|
922
|
+
if ("headers" in data) updateData.headers = encryptObject(data.headers);
|
|
851
923
|
if ("clientInformation" in data) updateData.client_information = data.clientInformation;
|
|
852
|
-
if ("tokens" in data) updateData.tokens = data.tokens;
|
|
924
|
+
if ("tokens" in data) updateData.tokens = encryptObject(data.tokens);
|
|
853
925
|
if ("codeVerifier" in data) updateData.code_verifier = data.codeVerifier;
|
|
854
926
|
if ("clientId" in data) updateData.client_id = data.clientId;
|
|
855
927
|
const { data: updatedRows, error } = await this.supabase.from("mcp_sessions").update(updateData).eq("identity", identity).eq("session_id", sessionId).select("id");
|
|
@@ -1648,13 +1720,24 @@ var MCPClient = class _MCPClient {
|
|
|
1648
1720
|
}
|
|
1649
1721
|
} catch (error) {
|
|
1650
1722
|
if (error instanceof auth_js.UnauthorizedError || error instanceof Error && error.message.toLowerCase().includes("unauthorized")) {
|
|
1651
|
-
this.emitStateChange("AUTHENTICATING");
|
|
1652
|
-
console.log(`[MCPClient] Saving session ${this.sessionId} with 10min TTL (OAuth pending)`);
|
|
1653
|
-
await this.saveSession(Math.floor(STATE_EXPIRATION_MS / 1e3), false);
|
|
1654
1723
|
let authUrl = "";
|
|
1655
1724
|
if (this.oauthProvider) {
|
|
1656
|
-
authUrl = this.oauthProvider.authUrl || "";
|
|
1725
|
+
authUrl = (this.oauthProvider.authUrl || "").trim();
|
|
1657
1726
|
}
|
|
1727
|
+
if (!authUrl) {
|
|
1728
|
+
const detail = error instanceof Error && error.message.trim().length > 0 ? error.message.trim() : "Unauthorized";
|
|
1729
|
+
const message = detail.toLowerCase() === "unauthorized" ? "OAuth authorization URL not available" : `OAuth authorization URL not available: ${detail}`;
|
|
1730
|
+
this.emitError(message, "auth");
|
|
1731
|
+
this.emitStateChange("FAILED");
|
|
1732
|
+
try {
|
|
1733
|
+
await storage.removeSession(this.identity, this.sessionId);
|
|
1734
|
+
} catch {
|
|
1735
|
+
}
|
|
1736
|
+
throw new Error(message);
|
|
1737
|
+
}
|
|
1738
|
+
this.emitStateChange("AUTHENTICATING");
|
|
1739
|
+
console.log(`[MCPClient] Saving session ${this.sessionId} with 10min TTL (OAuth pending)`);
|
|
1740
|
+
await this.saveSession(Math.floor(STATE_EXPIRATION_MS / 1e3), false);
|
|
1658
1741
|
if (this.serverId) {
|
|
1659
1742
|
this._onConnectionEvent.fire({
|
|
1660
1743
|
type: "auth_required",
|