@ai-sdk/mcp 2.0.12 → 2.0.14
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/CHANGELOG.md +19 -0
- package/dist/index.d.ts +16 -1
- package/dist/index.js +54 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +4 -0
- package/src/tool/mcp-app-fingerprint.ts +70 -0
- package/src/tool/mcp-apps.ts +33 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @ai-sdk/mcp
|
|
2
2
|
|
|
3
|
+
## 2.0.14
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 48e7e78: Harden MCP Apps handling of server-supplied resource metadata and the host/iframe bridge:
|
|
8
|
+
|
|
9
|
+
- Runtime-validate `_meta.ui` and drop malformed or non-string fields.
|
|
10
|
+
- Gate iframe permissions deny-by-default via a new `sandbox.allowedPermissions` allowlist.
|
|
11
|
+
- Derive a concrete `postMessage` target origin and validate inbound message origins.
|
|
12
|
+
- Validate inbound bridge params: limit `resources/read` to `ui://` resources and allow only `https`/`http`/`mailto` in `ui/open-link`.
|
|
13
|
+
- Add `fingerprintMCPAppResource` / `detectMCPAppResourceDrift` for pinning and comparing app resources.
|
|
14
|
+
|
|
15
|
+
## 2.0.13
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- Updated dependencies [31c7be8]
|
|
20
|
+
- @ai-sdk/provider-utils@5.0.10
|
|
21
|
+
|
|
3
22
|
## 2.0.12
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -762,4 +762,19 @@ declare function readMCPAppResource({ client, uri, options, }: {
|
|
|
762
762
|
options?: RequestOptions;
|
|
763
763
|
}): Promise<MCPAppResource>;
|
|
764
764
|
|
|
765
|
-
|
|
765
|
+
/**
|
|
766
|
+
* Stable SHA-256 digest (base64url) over an MCP App resource's `html`, `csp`,
|
|
767
|
+
* and `permissions`.
|
|
768
|
+
*
|
|
769
|
+
* Capture a baseline on first load and compare later reads with
|
|
770
|
+
* {@link detectMCPAppResourceDrift} to detect a changed resource. Baseline
|
|
771
|
+
* storage and the response are the host's concern, mirroring `fingerprintTools`.
|
|
772
|
+
*/
|
|
773
|
+
declare function fingerprintMCPAppResource(resource: MCPAppResource): Promise<string>;
|
|
774
|
+
/**
|
|
775
|
+
* Compares two fingerprints from {@link fingerprintMCPAppResource}. Returns
|
|
776
|
+
* `true` when the current resource differs from its baseline.
|
|
777
|
+
*/
|
|
778
|
+
declare function detectMCPAppResourceDrift(current: string, baseline: string): boolean;
|
|
779
|
+
|
|
780
|
+
export { type CallToolResult, type CompleteRequestParams, type CompleteResult, type Configuration, type ElicitResult, ElicitResultSchema, type ElicitationRequest, ElicitationRequestSchema, type InitializeResult, type JSONRPCError, type JSONRPCMessage, type JSONRPCNotification, type JSONRPCRequest, type JSONRPCResponse, type ListToolsResult, type MCPAppResource, type MCPAppResourceCSP, type MCPAppResourceMeta, type MCPClient, type ClientCapabilities as MCPClientCapabilities, type MCPClientConfig, type MCPTransport, MCP_APP_MIME_TYPE, type McpProviderMetadata, type OAuthAuthorizationServerInformation, type OAuthClientInformation, type OAuthClientMetadata, type OAuthClientProvider, type OAuthTokens, UnauthorizedError, auth, createMCPClient, detectMCPAppResourceDrift, type MCPClient as experimental_MCPClient, type ClientCapabilities as experimental_MCPClientCapabilities, type MCPClientConfig as experimental_MCPClientConfig, createMCPClient as experimental_createMCPClient, fingerprintMCPAppResource, mcpAppClientCapabilities, readMCPAppResource, splitMCPAppTools, validateJSONRPCMessage };
|
package/dist/index.js
CHANGED
|
@@ -1971,6 +1971,7 @@ function isCustomMcpTransport(transport) {
|
|
|
1971
1971
|
// src/tool/mcp-apps.ts
|
|
1972
1972
|
import { isJSONObject } from "@ai-sdk/provider";
|
|
1973
1973
|
import { convertBase64ToUint8Array } from "@ai-sdk/provider-utils";
|
|
1974
|
+
import * as z4 from "zod/v4";
|
|
1974
1975
|
var MCP_APP_EXTENSION_NAME = "io.modelcontextprotocol/ui";
|
|
1975
1976
|
var MCP_APP_MIME_TYPE = "text/html;profile=mcp-app";
|
|
1976
1977
|
var MCP_APP_LEGACY_RESOURCE_URI_META_KEY = "ui/resourceUri";
|
|
@@ -1985,11 +1986,25 @@ function getToolUiMeta(meta) {
|
|
|
1985
1986
|
const uiMeta = meta == null ? void 0 : meta.ui;
|
|
1986
1987
|
return isJSONObject(uiMeta) ? uiMeta : void 0;
|
|
1987
1988
|
}
|
|
1989
|
+
var optionalStringArray = z4.array(z4.unknown()).transform((items) => items.filter((v) => typeof v === "string")).optional().catch(void 0);
|
|
1990
|
+
var MCPAppResourceCSPSchema = z4.looseObject({
|
|
1991
|
+
connectDomains: optionalStringArray,
|
|
1992
|
+
resourceDomains: optionalStringArray,
|
|
1993
|
+
frameDomains: optionalStringArray
|
|
1994
|
+
});
|
|
1995
|
+
var MCPAppResourceMetaSchema = z4.looseObject({
|
|
1996
|
+
prefersBorder: z4.boolean().optional().catch(void 0),
|
|
1997
|
+
csp: MCPAppResourceCSPSchema.optional().catch(void 0),
|
|
1998
|
+
permissions: z4.record(z4.string(), z4.unknown()).optional().catch(void 0)
|
|
1999
|
+
});
|
|
1988
2000
|
function getResourceUiMeta(meta) {
|
|
1989
2001
|
const resourceMeta = isJSONObject(meta) ? meta : void 0;
|
|
1990
2002
|
const rawUiMeta = resourceMeta == null ? void 0 : resourceMeta.ui;
|
|
1991
|
-
|
|
1992
|
-
|
|
2003
|
+
if (!isJSONObject(rawUiMeta)) {
|
|
2004
|
+
return void 0;
|
|
2005
|
+
}
|
|
2006
|
+
const parsed = MCPAppResourceMetaSchema.safeParse(rawUiMeta);
|
|
2007
|
+
return parsed.success ? parsed.data : void 0;
|
|
1993
2008
|
}
|
|
1994
2009
|
function parseVisibility(value) {
|
|
1995
2010
|
return Array.isArray(value) ? value.filter(
|
|
@@ -2790,6 +2805,41 @@ var DefaultMCPClient = class {
|
|
|
2790
2805
|
);
|
|
2791
2806
|
}
|
|
2792
2807
|
};
|
|
2808
|
+
|
|
2809
|
+
// src/tool/mcp-app-fingerprint.ts
|
|
2810
|
+
import { convertUint8ArrayToBase64 } from "@ai-sdk/provider-utils";
|
|
2811
|
+
var encoder = new TextEncoder();
|
|
2812
|
+
function canonicalJSON(value) {
|
|
2813
|
+
if (value == null || typeof value !== "object") {
|
|
2814
|
+
return JSON.stringify(value != null ? value : null);
|
|
2815
|
+
}
|
|
2816
|
+
if (Array.isArray(value)) {
|
|
2817
|
+
return `[${value.map(canonicalJSON).join(",")}]`;
|
|
2818
|
+
}
|
|
2819
|
+
const record2 = value;
|
|
2820
|
+
const entries = Object.keys(record2).sort().map((k) => `${JSON.stringify(k)}:${canonicalJSON(record2[k])}`);
|
|
2821
|
+
return `{${entries.join(",")}}`;
|
|
2822
|
+
}
|
|
2823
|
+
function toBase64url(bytes) {
|
|
2824
|
+
return convertUint8ArrayToBase64(bytes).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
2825
|
+
}
|
|
2826
|
+
async function fingerprintMCPAppResource(resource) {
|
|
2827
|
+
var _a3, _b3, _c, _d;
|
|
2828
|
+
const digest = await crypto.subtle.digest(
|
|
2829
|
+
"SHA-256",
|
|
2830
|
+
encoder.encode(
|
|
2831
|
+
canonicalJSON({
|
|
2832
|
+
html: resource.html,
|
|
2833
|
+
csp: (_b3 = (_a3 = resource.meta) == null ? void 0 : _a3.csp) != null ? _b3 : null,
|
|
2834
|
+
permissions: (_d = (_c = resource.meta) == null ? void 0 : _c.permissions) != null ? _d : null
|
|
2835
|
+
})
|
|
2836
|
+
)
|
|
2837
|
+
);
|
|
2838
|
+
return toBase64url(new Uint8Array(digest));
|
|
2839
|
+
}
|
|
2840
|
+
function detectMCPAppResourceDrift(current, baseline) {
|
|
2841
|
+
return current !== baseline;
|
|
2842
|
+
}
|
|
2793
2843
|
export {
|
|
2794
2844
|
ElicitResultSchema,
|
|
2795
2845
|
ElicitationRequestSchema,
|
|
@@ -2797,7 +2847,9 @@ export {
|
|
|
2797
2847
|
UnauthorizedError,
|
|
2798
2848
|
auth,
|
|
2799
2849
|
createMCPClient,
|
|
2850
|
+
detectMCPAppResourceDrift,
|
|
2800
2851
|
createMCPClient as experimental_createMCPClient,
|
|
2852
|
+
fingerprintMCPAppResource,
|
|
2801
2853
|
mcpAppClientCapabilities,
|
|
2802
2854
|
readMCPAppResource,
|
|
2803
2855
|
splitMCPAppTools,
|