mcp-use 2.0.0-beta.35 → 2.0.0-beta.37

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.
Files changed (44) hide show
  1. package/dist/bin.js +1 -3
  2. package/dist/chunk-5Z6KY5ON.js +2 -0
  3. package/dist/{chunk-PPQL2WHL.js → chunk-GX6PGIEO.js} +32 -142
  4. package/dist/chunk-JMDHTN6N.js +1 -0
  5. package/dist/chunk-OJF6B5EU.js +1 -0
  6. package/dist/chunk-PSKSL567.js +1 -0
  7. package/dist/chunk-WYBJYZJB.js +1 -0
  8. package/dist/chunk-Y26DNVWA.js +3 -0
  9. package/dist/chunk-ZMU5USAZ.js +1 -0
  10. package/dist/index.js +9 -3100
  11. package/dist/internal/resource-completion.js +1 -6
  12. package/dist/internal/usage.js +1 -0
  13. package/dist/landing-handler-TG6LVQBI.js +1 -0
  14. package/dist/landing.js +1 -6
  15. package/dist/mcp-proxy-NETCUGUD.js +2 -0
  16. package/dist/mcp-proxy.d.ts +6 -0
  17. package/dist/next/index.js +1 -171
  18. package/dist/node-bridge.js +1 -150
  19. package/dist/oauth/auth0.js +1 -60
  20. package/dist/oauth/better-auth.js +1 -75
  21. package/dist/oauth/clerk.js +1 -69
  22. package/dist/oauth/index.js +1 -26
  23. package/dist/oauth/keycloak.js +1 -93
  24. package/dist/oauth/supabase.js +1 -100
  25. package/dist/oauth/workos.js +1 -76
  26. package/dist/openapi/index.js +1 -6
  27. package/dist/public-route-DAQJGS6K.js +1 -0
  28. package/dist/react/components/model-context.d.ts +9 -14
  29. package/dist/react/hooks/use-view-state.d.ts +23 -0
  30. package/dist/react/index.d.ts +1 -0
  31. package/dist/react/index.js +215 -81
  32. package/dist/react/runtime/model-context-store.d.ts +34 -68
  33. package/dist/react/runtime/view-runtime.d.ts +2 -2
  34. package/dist/usage.d.ts +11 -0
  35. package/package.json +6 -5
  36. package/dist/chunk-DFFP6QPR.js +0 -37
  37. package/dist/chunk-HDV7K2TE.js +0 -97
  38. package/dist/chunk-HNNQJLD5.js +0 -383
  39. package/dist/chunk-QCIREWRS.js +0 -64
  40. package/dist/chunk-QKJJ6DWK.js +0 -184
  41. package/dist/chunk-YF5X7FYF.js +0 -517
  42. package/dist/landing-handler-QEH2ATIR.js +0 -36
  43. package/dist/mcp-proxy-JK7IC5CR.js +0 -281
  44. package/dist/public-route-BAMZRI4R.js +0 -8
@@ -1,93 +1 @@
1
- import {
2
- booleanValue,
3
- createJwtVerifier,
4
- invalidToken,
5
- isRecord,
6
- normalizedProviderUrl,
7
- normalizedStrings,
8
- oauthCustomProvider,
9
- payloadFromAuthInfo,
10
- providerEndpoint,
11
- recordValue,
12
- requiredString,
13
- stringValue
14
- } from "../chunk-YF5X7FYF.js";
15
-
16
- // src/oauth/keycloak.ts
17
- function oauthKeycloakProvider(options) {
18
- if (typeof options.realm !== "string" || options.realm.trim().length === 0 || /[/?#]/.test(options.realm)) {
19
- throw new TypeError("Keycloak realm is invalid");
20
- }
21
- const serverUrl = normalizedProviderUrl(
22
- options.serverUrl,
23
- "Keycloak serverUrl"
24
- );
25
- const issuer = providerEndpoint(
26
- serverUrl,
27
- `realms/${encodeURIComponent(options.realm)}`
28
- ).replace(/\/$/, "");
29
- return oauthCustomProvider({
30
- ...options,
31
- createTokenVerifier: (resource) => createJwtVerifier({
32
- issuer,
33
- jwksUrl: new URL(
34
- providerEndpoint(issuer, "protocol/openid-connect/certs")
35
- ),
36
- resource
37
- }),
38
- oauthMetadata: {
39
- issuer,
40
- authorization_endpoint: providerEndpoint(
41
- issuer,
42
- "protocol/openid-connect/auth"
43
- ),
44
- token_endpoint: providerEndpoint(issuer, "protocol/openid-connect/token"),
45
- registration_endpoint: providerEndpoint(
46
- issuer,
47
- "clients-registrations/openid-connect"
48
- ),
49
- response_types_supported: ["code"],
50
- grant_types_supported: ["authorization_code", "refresh_token"],
51
- code_challenge_methods_supported: ["S256"]
52
- },
53
- mapAuthInfo: mapUser
54
- });
55
- }
56
- function mapUser(authInfo) {
57
- const payload = payloadFromAuthInfo(authInfo);
58
- const id = requiredString(payload, "sub");
59
- if (id === void 0) throw invalidToken("Missing Keycloak subject");
60
- const realmAccess = recordValue(payload, "realm_access");
61
- const resourceAccess = recordValue(payload, "resource_access");
62
- return {
63
- user: {
64
- id,
65
- ...optional("email", stringValue(payload, "email")),
66
- ...optional("name", stringValue(payload, "name")),
67
- ...optional(
68
- "preferredUsername",
69
- stringValue(payload, "preferred_username")
70
- ),
71
- ...optional("givenName", stringValue(payload, "given_name")),
72
- ...optional("familyName", stringValue(payload, "family_name")),
73
- ...optional("emailVerified", booleanValue(payload, "email_verified")),
74
- roles: realmAccess === void 0 ? [] : normalizedStrings(realmAccess["roles"]),
75
- ...realmAccess !== void 0 && { realmAccess },
76
- ...resourceAccess !== void 0 && { resourceAccess }
77
- },
78
- payload,
79
- permissions: resourcePermissions(resourceAccess)
80
- };
81
- }
82
- function optional(key, value) {
83
- return value === void 0 ? {} : { [key]: value };
84
- }
85
- function resourcePermissions(resourceAccess) {
86
- if (resourceAccess === void 0) return [];
87
- return Object.entries(resourceAccess).flatMap(
88
- ([resource, value]) => isRecord(value) ? normalizedStrings(value["roles"]).map((role) => `${resource}:${role}`) : []
89
- );
90
- }
91
- export {
92
- oauthKeycloakProvider
93
- };
1
+ import{booleanValue,createJwtVerifier,invalidToken,isRecord,normalizedProviderUrl,normalizedStrings,oauthCustomProvider,payloadFromAuthInfo,providerEndpoint,recordValue,requiredString,stringValue}from"../chunk-JMDHTN6N.js";function oauthKeycloakProvider(options){if(typeof options.realm!="string"||options.realm.trim().length===0||/[/?#]/.test(options.realm))throw new TypeError("Keycloak realm is invalid");let serverUrl=normalizedProviderUrl(options.serverUrl,"Keycloak serverUrl"),issuer=providerEndpoint(serverUrl,`realms/${encodeURIComponent(options.realm)}`).replace(/\/$/,"");return oauthCustomProvider({...options,createTokenVerifier:resource=>createJwtVerifier({issuer,jwksUrl:new URL(providerEndpoint(issuer,"protocol/openid-connect/certs")),resource}),oauthMetadata:{issuer,authorization_endpoint:providerEndpoint(issuer,"protocol/openid-connect/auth"),token_endpoint:providerEndpoint(issuer,"protocol/openid-connect/token"),registration_endpoint:providerEndpoint(issuer,"clients-registrations/openid-connect"),response_types_supported:["code"],grant_types_supported:["authorization_code","refresh_token"],code_challenge_methods_supported:["S256"]},mapAuthInfo:mapUser})}function mapUser(authInfo){let payload=payloadFromAuthInfo(authInfo),id=requiredString(payload,"sub");if(id===void 0)throw invalidToken("Missing Keycloak subject");let realmAccess=recordValue(payload,"realm_access"),resourceAccess=recordValue(payload,"resource_access");return{user:{id,...optional("email",stringValue(payload,"email")),...optional("name",stringValue(payload,"name")),...optional("preferredUsername",stringValue(payload,"preferred_username")),...optional("givenName",stringValue(payload,"given_name")),...optional("familyName",stringValue(payload,"family_name")),...optional("emailVerified",booleanValue(payload,"email_verified")),roles:realmAccess===void 0?[]:normalizedStrings(realmAccess.roles),...realmAccess!==void 0&&{realmAccess},...resourceAccess!==void 0&&{resourceAccess}},payload,permissions:resourcePermissions(resourceAccess)}}function optional(key,value){return value===void 0?{}:{[key]:value}}function resourcePermissions(resourceAccess){return resourceAccess===void 0?[]:Object.entries(resourceAccess).flatMap(([resource,value])=>isRecord(value)?normalizedStrings(value.roles).map(role=>`${resource}:${role}`):[])}export{oauthKeycloakProvider};
@@ -1,100 +1 @@
1
- import {
2
- createJwtVerifier,
3
- invalidToken,
4
- isRecord,
5
- normalizedProviderUrl,
6
- oauthCustomProvider,
7
- payloadFromAuthInfo,
8
- providerEndpoint,
9
- recordValue,
10
- requiredString,
11
- stringValue
12
- } from "../chunk-YF5X7FYF.js";
13
-
14
- // src/oauth/supabase.ts
15
- function oauthSupabaseProvider(options) {
16
- const supabaseUrl = resolveSupabaseUrl(options);
17
- const issuer = providerEndpoint(supabaseUrl, "auth/v1").replace(/\/$/, "");
18
- const secret = options.jwtSecret;
19
- if (secret !== void 0 && new TextEncoder().encode(secret).length < 32) {
20
- throw new TypeError("Supabase jwtSecret must be at least 32 bytes");
21
- }
22
- return oauthCustomProvider({
23
- ...options,
24
- createTokenVerifier: (resource) => createJwtVerifier({
25
- issuer,
26
- jwksUrl: new URL(
27
- providerEndpoint(supabaseUrl, "auth/v1/.well-known/jwks.json")
28
- ),
29
- ...secret !== void 0 ? { key: new TextEncoder().encode(secret), algorithms: ["HS256"] } : { algorithms: ["ES256"] },
30
- resource
31
- }),
32
- oauthMetadata: {
33
- issuer,
34
- authorization_endpoint: providerEndpoint(
35
- supabaseUrl,
36
- "auth/v1/oauth/authorize"
37
- ),
38
- token_endpoint: providerEndpoint(supabaseUrl, "auth/v1/oauth/token"),
39
- registration_endpoint: providerEndpoint(
40
- supabaseUrl,
41
- "auth/v1/oauth/clients/register"
42
- ),
43
- response_types_supported: ["code"],
44
- grant_types_supported: ["authorization_code", "refresh_token"],
45
- code_challenge_methods_supported: ["S256"]
46
- },
47
- mapAuthInfo: mapUser
48
- });
49
- }
50
- function mapUser(authInfo) {
51
- const payload = payloadFromAuthInfo(authInfo);
52
- const id = requiredString(payload, "sub") ?? requiredString(payload, "user_id");
53
- if (id === void 0) throw invalidToken("Missing Supabase subject");
54
- const userMetadata = recordValue(payload, "user_metadata") ?? {};
55
- const aal = stringValue(payload, "aal");
56
- return {
57
- user: {
58
- id,
59
- ...optional("email", stringValue(payload, "email")),
60
- ...optional("name", stringValue(userMetadata, "name")),
61
- ...optional("fullName", stringValue(userMetadata, "full_name")),
62
- ...optional("username", stringValue(userMetadata, "username")),
63
- ...optional("avatarUrl", stringValue(userMetadata, "avatar_url")),
64
- ...optional("role", stringValue(payload, "role")),
65
- ...optional("aal", aal),
66
- amr: supabaseAmr(payload["amr"]),
67
- ...optional("sessionId", stringValue(payload, "session_id"))
68
- },
69
- payload,
70
- permissions: aal === void 0 ? [] : [`aal:${aal}`]
71
- };
72
- }
73
- function optional(key, value) {
74
- return value === void 0 ? {} : { [key]: value };
75
- }
76
- function resolveSupabaseUrl(options) {
77
- if (options.supabaseUrl !== void 0) {
78
- return normalizedProviderUrl(options.supabaseUrl, "supabaseUrl");
79
- }
80
- if (options.projectId === void 0 || !/^[a-z0-9-]+$/i.test(options.projectId)) {
81
- throw new TypeError("Supabase requires projectId or supabaseUrl");
82
- }
83
- return new URL(`https://${options.projectId}.supabase.co`);
84
- }
85
- function supabaseAmr(value) {
86
- if (!Array.isArray(value)) return [];
87
- return value.flatMap((item) => {
88
- if (!isRecord(item)) return [];
89
- const method = item["method"];
90
- const timestamp = item["timestamp"];
91
- if (typeof method !== "string" || method.length === 0) return [];
92
- if (timestamp !== void 0 && (typeof timestamp !== "number" || !Number.isFinite(timestamp))) {
93
- return [];
94
- }
95
- return [timestamp === void 0 ? { method } : { method, timestamp }];
96
- });
97
- }
98
- export {
99
- oauthSupabaseProvider
100
- };
1
+ import{createJwtVerifier,invalidToken,isRecord,normalizedProviderUrl,oauthCustomProvider,payloadFromAuthInfo,providerEndpoint,recordValue,requiredString,stringValue}from"../chunk-JMDHTN6N.js";function oauthSupabaseProvider(options){let supabaseUrl=resolveSupabaseUrl(options),issuer=providerEndpoint(supabaseUrl,"auth/v1").replace(/\/$/,""),secret=options.jwtSecret;if(secret!==void 0&&new TextEncoder().encode(secret).length<32)throw new TypeError("Supabase jwtSecret must be at least 32 bytes");return oauthCustomProvider({...options,createTokenVerifier:resource=>createJwtVerifier({issuer,jwksUrl:new URL(providerEndpoint(supabaseUrl,"auth/v1/.well-known/jwks.json")),...secret!==void 0?{key:new TextEncoder().encode(secret),algorithms:["HS256"]}:{algorithms:["ES256"]},resource}),oauthMetadata:{issuer,authorization_endpoint:providerEndpoint(supabaseUrl,"auth/v1/oauth/authorize"),token_endpoint:providerEndpoint(supabaseUrl,"auth/v1/oauth/token"),registration_endpoint:providerEndpoint(supabaseUrl,"auth/v1/oauth/clients/register"),response_types_supported:["code"],grant_types_supported:["authorization_code","refresh_token"],code_challenge_methods_supported:["S256"]},mapAuthInfo:mapUser})}function mapUser(authInfo){let payload=payloadFromAuthInfo(authInfo),id=requiredString(payload,"sub")??requiredString(payload,"user_id");if(id===void 0)throw invalidToken("Missing Supabase subject");let userMetadata=recordValue(payload,"user_metadata")??{},aal=stringValue(payload,"aal");return{user:{id,...optional("email",stringValue(payload,"email")),...optional("name",stringValue(userMetadata,"name")),...optional("fullName",stringValue(userMetadata,"full_name")),...optional("username",stringValue(userMetadata,"username")),...optional("avatarUrl",stringValue(userMetadata,"avatar_url")),...optional("role",stringValue(payload,"role")),...optional("aal",aal),amr:supabaseAmr(payload.amr),...optional("sessionId",stringValue(payload,"session_id"))},payload,permissions:aal===void 0?[]:[`aal:${aal}`]}}function optional(key,value){return value===void 0?{}:{[key]:value}}function resolveSupabaseUrl(options){if(options.supabaseUrl!==void 0)return normalizedProviderUrl(options.supabaseUrl,"supabaseUrl");if(options.projectId===void 0||!/^[a-z0-9-]+$/i.test(options.projectId))throw new TypeError("Supabase requires projectId or supabaseUrl");return new URL(`https://${options.projectId}.supabase.co`)}function supabaseAmr(value){return Array.isArray(value)?value.flatMap(item=>{if(!isRecord(item))return[];let method=item.method,timestamp=item.timestamp;return typeof method!="string"||method.length===0?[]:timestamp!==void 0&&(typeof timestamp!="number"||!Number.isFinite(timestamp))?[]:[timestamp===void 0?{method}:{method,timestamp}]}):[]}export{oauthSupabaseProvider};
@@ -1,76 +1 @@
1
- import {
2
- booleanValue,
3
- createJwtVerifier,
4
- invalidToken,
5
- normalizedProviderUrl,
6
- normalizedStrings,
7
- oauthCustomProvider,
8
- payloadFromAuthInfo,
9
- providerEndpoint,
10
- requiredString,
11
- stringValue
12
- } from "../chunk-YF5X7FYF.js";
13
-
14
- // src/oauth/workos.ts
15
- function oauthWorkOSProvider(options) {
16
- const issuer = workosIssuer(options.subdomain);
17
- return oauthCustomProvider({
18
- ...options,
19
- createTokenVerifier: (resource) => createJwtVerifier({
20
- issuer,
21
- jwksUrl: new URL(providerEndpoint(issuer, "oauth2/jwks")),
22
- resource
23
- }),
24
- oauthMetadata: {
25
- issuer,
26
- authorization_endpoint: providerEndpoint(issuer, "oauth2/authorize"),
27
- token_endpoint: providerEndpoint(issuer, "oauth2/token"),
28
- registration_endpoint: providerEndpoint(issuer, "oauth2/register"),
29
- response_types_supported: ["code"],
30
- grant_types_supported: ["authorization_code", "refresh_token"],
31
- code_challenge_methods_supported: ["S256"]
32
- },
33
- mapAuthInfo: mapUser
34
- });
35
- }
36
- function mapUser(authInfo) {
37
- const payload = payloadFromAuthInfo(authInfo);
38
- const id = requiredString(payload, "sub");
39
- if (id === void 0) throw invalidToken("Missing WorkOS subject");
40
- return {
41
- user: {
42
- id,
43
- ...optional("email", stringValue(payload, "email")),
44
- ...optional("emailVerified", booleanValue(payload, "email_verified")),
45
- ...optional("name", stringValue(payload, "name")),
46
- ...optional(
47
- "preferredUsername",
48
- stringValue(payload, "preferred_username")
49
- ),
50
- ...optional("firstName", stringValue(payload, "first_name")),
51
- ...optional("lastName", stringValue(payload, "last_name")),
52
- ...optional("picture", stringValue(payload, "picture")),
53
- roles: normalizedStrings(payload["roles"]),
54
- ...optional("organizationId", stringValue(payload, "org_id")),
55
- ...optional("sessionId", stringValue(payload, "sid"))
56
- },
57
- payload,
58
- permissions: normalizedStrings(payload["permissions"])
59
- };
60
- }
61
- function optional(key, value) {
62
- return value === void 0 ? {} : { [key]: value };
63
- }
64
- function workosIssuer(value) {
65
- if (typeof value !== "string" || value.trim().length === 0) {
66
- throw new TypeError("WorkOS subdomain is required");
67
- }
68
- const url = normalizedProviderUrl(value, "WorkOS subdomain");
69
- if (url.pathname !== "/") {
70
- throw new TypeError("WorkOS subdomain must be a hostname or HTTPS origin");
71
- }
72
- return url.href.replace(/\/$/, "");
73
- }
74
- export {
75
- oauthWorkOSProvider
76
- };
1
+ import{booleanValue,createJwtVerifier,invalidToken,normalizedProviderUrl,normalizedStrings,oauthCustomProvider,payloadFromAuthInfo,providerEndpoint,requiredString,stringValue}from"../chunk-JMDHTN6N.js";function oauthWorkOSProvider(options){let issuer=workosIssuer(options.subdomain);return oauthCustomProvider({...options,createTokenVerifier:resource=>createJwtVerifier({issuer,jwksUrl:new URL(providerEndpoint(issuer,"oauth2/jwks")),resource}),oauthMetadata:{issuer,authorization_endpoint:providerEndpoint(issuer,"oauth2/authorize"),token_endpoint:providerEndpoint(issuer,"oauth2/token"),registration_endpoint:providerEndpoint(issuer,"oauth2/register"),response_types_supported:["code"],grant_types_supported:["authorization_code","refresh_token"],code_challenge_methods_supported:["S256"]},mapAuthInfo:mapUser})}function mapUser(authInfo){let payload=payloadFromAuthInfo(authInfo),id=requiredString(payload,"sub");if(id===void 0)throw invalidToken("Missing WorkOS subject");return{user:{id,...optional("email",stringValue(payload,"email")),...optional("emailVerified",booleanValue(payload,"email_verified")),...optional("name",stringValue(payload,"name")),...optional("preferredUsername",stringValue(payload,"preferred_username")),...optional("firstName",stringValue(payload,"first_name")),...optional("lastName",stringValue(payload,"last_name")),...optional("picture",stringValue(payload,"picture")),roles:normalizedStrings(payload.roles),...optional("organizationId",stringValue(payload,"org_id")),...optional("sessionId",stringValue(payload,"sid"))},payload,permissions:normalizedStrings(payload.permissions)}}function optional(key,value){return value===void 0?{}:{[key]:value}}function workosIssuer(value){if(typeof value!="string"||value.trim().length===0)throw new TypeError("WorkOS subdomain is required");let url=normalizedProviderUrl(value,"WorkOS subdomain");if(url.pathname!=="/")throw new TypeError("WorkOS subdomain must be a hostname or HTTPS origin");return url.href.replace(/\/$/,"")}export{oauthWorkOSProvider};
@@ -1,6 +1 @@
1
- import {
2
- registerOpenAPITools
3
- } from "../chunk-HNNQJLD5.js";
4
- export {
5
- registerOpenAPITools
6
- };
1
+ import{registerOpenAPITools}from"../chunk-Y26DNVWA.js";export{registerOpenAPITools};
@@ -0,0 +1 @@
1
+ import{resolvePublicFilePath,servePublicFile}from"./chunk-ZMU5USAZ.js";export{resolvePublicFilePath,servePublicFile};
@@ -14,20 +14,17 @@ interface ModelContextProps {
14
14
  * Annotate a portion of the view UI with a description the model can see.
15
15
  *
16
16
  * Registers `content` in a hierarchical tree that serializes into an indented
17
- * markdown list and is pushed to the host via `ui/update-model-context`
18
- * (ext-apps `App.updateModelContext`). Updates batch per microtask. An async
19
- * flush pump acknowledges a payload only after a successful send; failed
20
- * update requests and missing host capability stay dirty and retry on the next
21
- * mutation. Each push carries the complete current context — the spec's
22
- * overwrite semantics (the host may defer delivery until the next model turn).
17
+ * markdown list under `_uiContext`. The store merges that field with
18
+ * `useViewState` and sends the complete snapshot through ChatGPT widget state
19
+ * or MCP Apps `ui/update-model-context`. Updates batch per microtask. Failed
20
+ * requests stay dirty and retry after the next mutation.
23
21
  *
24
22
  * An empty `content` (trimmed) does not register a node and does not orphan
25
23
  * children — nested {@link ModelContext} nodes re-parent to the nearest
26
24
  * registered ancestor (or root).
27
25
  *
28
- * When the host does not declare the `updateModelContext` capability, pushes
29
- * are skipped (payload stays dirty) and a one-time `console.warn` names the
30
- * gap.
26
+ * On the MCP Apps path, a host without the `updateModelContext` capability
27
+ * skips pushes and receives a one-time `console.warn`.
31
28
  *
32
29
  * @param props - Component props.
33
30
  * @param props.content - Text describing what the user is currently seeing.
@@ -51,11 +48,9 @@ export declare function ModelContext({ content, children }: ModelContextProps):
51
48
  *
52
49
  * Delegates to the active document runtime's {@link ModelContextStore}.
53
50
  * Strings register as root-level nodes in the same tree {@link ModelContext}
54
- * builds; each push overwrites the previous context on the host (the host may
55
- * defer delivery until the next model turn). Updates batch per microtask and
56
- * use the same async flush pump (ack only on success). When the host lacks the
57
- * `updateModelContext` capability, pushes stay dirty with a one-time
58
- * `console.warn`.
51
+ * builds. Every push merges the complete tree under `_uiContext` beside the
52
+ * current `useViewState` object. Updates batch per microtask and use the same
53
+ * async flush pump as the component API.
59
54
  *
60
55
  * @throws When no view runtime is mounted (`bootstrapView` has not activated a
61
56
  * runtime, or it has been disposed).
@@ -0,0 +1,23 @@
1
+ import { type SetStateAction } from "react";
2
+ /**
3
+ * Persist model-visible state for the current mounted view.
4
+ *
5
+ * Every component in one view runtime reads and updates the same state object.
6
+ * ChatGPT restores the object from `window.openai.widgetState.modelContent`.
7
+ * Other MCP Apps hosts keep it for the iframe lifetime and receive it through
8
+ * `ui/update-model-context`.
9
+ *
10
+ * The state must be a JSON-serializable object and cannot contain the reserved
11
+ * `_uiContext` key used by {@link ModelContext}.
12
+ *
13
+ * @param defaultState - Initial object, or a lazy initializer evaluated once
14
+ * for this hook instance. Restored ChatGPT state takes precedence.
15
+ * @returns A readonly `[state, setState]` tuple with `useState` ergonomics.
16
+ *
17
+ * @example
18
+ * ```tsx
19
+ * const [state, setState] = useViewState({ count: 0 });
20
+ * setState((previous) => ({ ...previous, count: previous.count + 1 }));
21
+ * ```
22
+ */
23
+ export declare function useViewState<T extends Record<string, unknown>>(defaultState: T | (() => T)): readonly [T, (state: SetStateAction<T>) => void];
@@ -22,6 +22,7 @@ export { useOpenExternal } from "./hooks/use-open-external.js";
22
22
  export { useSendFollowUp } from "./hooks/use-send-follow-up.js";
23
23
  export { useSendSizeChanged } from "./hooks/use-send-size-changed.js";
24
24
  export { useViewTheme } from "./hooks/use-view-theme.js";
25
+ export { useViewState } from "./hooks/use-view-state.js";
25
26
  export { useToolContext, type ToolContextHandle, } from "./hooks/use-tool-context.js";
26
27
  export { useViewTool, type ViewToolDefinition } from "./hooks/use-view-tool.js";
27
28
  export { type DeepPartial, type Register, type RegisteredTools, } from "./types/register.js";