@assistant-ui/react-mcp 0.1.17 → 0.1.19
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/auth/buildHeaders.d.ts +1 -2
- package/dist/auth/buildHeaders.d.ts.map +1 -1
- package/dist/auth/createOAuthProvider.d.ts +5 -6
- package/dist/auth/createOAuthProvider.d.ts.map +1 -1
- package/dist/auth/types.d.ts +1 -2
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/connector.d.ts +1 -2
- package/dist/connector.d.ts.map +1 -1
- package/dist/context/McpConnectorByIndexProvider.d.ts +1 -2
- package/dist/context/McpConnectorByIndexProvider.d.ts.map +1 -1
- package/dist/context/McpCustomServerByIndexProvider.d.ts +1 -2
- package/dist/context/McpCustomServerByIndexProvider.d.ts.map +1 -1
- package/dist/context/McpServerByIdProvider.d.ts +1 -2
- package/dist/context/McpServerByIdProvider.d.ts.map +1 -1
- package/dist/hooks/useMcpOAuthCallback.d.ts +5 -6
- package/dist/hooks/useMcpOAuthCallback.d.ts.map +1 -1
- package/dist/hooks/useMcpOAuthCallback.js +4 -0
- package/dist/hooks/useMcpOAuthCallback.js.map +1 -1
- package/dist/mcp-scope.d.ts +14 -15
- package/dist/mcp-scope.d.ts.map +1 -1
- package/dist/primitives/addForm/McpAddFormAuthFields.d.ts +4 -4
- package/dist/primitives/addForm/McpAddFormAuthFields.d.ts.map +1 -1
- package/dist/primitives/addForm/McpAddFormAuthFields.js +28 -38
- package/dist/primitives/addForm/McpAddFormAuthFields.js.map +1 -1
- package/dist/primitives/addForm/McpAddFormAuthSelect.d.ts +2 -3
- package/dist/primitives/addForm/McpAddFormAuthSelect.d.ts.map +1 -1
- package/dist/primitives/addForm/McpAddFormBearerTokenField.d.ts +10 -0
- package/dist/primitives/addForm/McpAddFormBearerTokenField.d.ts.map +1 -0
- package/dist/primitives/addForm/McpAddFormBearerTokenField.js +50 -0
- package/dist/primitives/addForm/McpAddFormBearerTokenField.js.map +1 -0
- package/dist/primitives/addForm/McpAddFormCancel.d.ts +2 -3
- package/dist/primitives/addForm/McpAddFormCancel.d.ts.map +1 -1
- package/dist/primitives/addForm/McpAddFormError.d.ts +2 -3
- package/dist/primitives/addForm/McpAddFormError.d.ts.map +1 -1
- package/dist/primitives/addForm/McpAddFormError.js +30 -10
- package/dist/primitives/addForm/McpAddFormError.js.map +1 -1
- package/dist/primitives/addForm/McpAddFormNameField.d.ts +2 -3
- package/dist/primitives/addForm/McpAddFormNameField.d.ts.map +1 -1
- package/dist/primitives/addForm/McpAddFormNameField.js +31 -18
- package/dist/primitives/addForm/McpAddFormNameField.js.map +1 -1
- package/dist/primitives/addForm/McpAddFormRoot.d.ts +2 -3
- package/dist/primitives/addForm/McpAddFormRoot.d.ts.map +1 -1
- package/dist/primitives/addForm/McpAddFormRoot.js +32 -11
- package/dist/primitives/addForm/McpAddFormRoot.js.map +1 -1
- package/dist/primitives/addForm/McpAddFormScopesField.d.ts +10 -0
- package/dist/primitives/addForm/McpAddFormScopesField.d.ts.map +1 -0
- package/dist/primitives/addForm/McpAddFormScopesField.js +38 -0
- package/dist/primitives/addForm/McpAddFormScopesField.js.map +1 -0
- package/dist/primitives/addForm/McpAddFormSubmit.d.ts +2 -3
- package/dist/primitives/addForm/McpAddFormSubmit.d.ts.map +1 -1
- package/dist/primitives/addForm/McpAddFormUrlField.d.ts +2 -3
- package/dist/primitives/addForm/McpAddFormUrlField.d.ts.map +1 -1
- package/dist/primitives/addForm/McpAddFormUrlField.js +31 -18
- package/dist/primitives/addForm/McpAddFormUrlField.js.map +1 -1
- package/dist/primitives/addForm/context.d.ts +13 -6
- package/dist/primitives/addForm/context.d.ts.map +1 -1
- package/dist/primitives/addForm/context.js.map +1 -1
- package/dist/primitives/addForm.d.ts +4 -2
- package/dist/primitives/addForm.js +5 -1
- package/dist/primitives/addForm.js.map +1 -1
- package/dist/primitives/elicitation/McpElicitationPrimitiveAccept.d.ts +2 -3
- package/dist/primitives/elicitation/McpElicitationPrimitiveAccept.d.ts.map +1 -1
- package/dist/primitives/elicitation/McpElicitationPrimitiveCancel.d.ts +2 -3
- package/dist/primitives/elicitation/McpElicitationPrimitiveCancel.d.ts.map +1 -1
- package/dist/primitives/elicitation/McpElicitationPrimitiveDecline.d.ts +2 -3
- package/dist/primitives/elicitation/McpElicitationPrimitiveDecline.d.ts.map +1 -1
- package/dist/primitives/elicitation/McpElicitationPrimitiveError.d.ts +2 -3
- package/dist/primitives/elicitation/McpElicitationPrimitiveError.d.ts.map +1 -1
- package/dist/primitives/elicitation/McpElicitationPrimitiveFields.d.ts +3 -3
- package/dist/primitives/elicitation/McpElicitationPrimitiveFields.d.ts.map +1 -1
- package/dist/primitives/elicitation/McpElicitationPrimitiveItems.d.ts +3 -3
- package/dist/primitives/elicitation/McpElicitationPrimitiveItems.d.ts.map +1 -1
- package/dist/primitives/elicitation/McpElicitationPrimitiveMessage.d.ts +2 -3
- package/dist/primitives/elicitation/McpElicitationPrimitiveMessage.d.ts.map +1 -1
- package/dist/primitives/elicitation/McpElicitationPrimitiveRoot.d.ts +2 -3
- package/dist/primitives/elicitation/McpElicitationPrimitiveRoot.d.ts.map +1 -1
- package/dist/primitives/elicitation/context.d.ts +7 -8
- package/dist/primitives/elicitation/context.d.ts.map +1 -1
- package/dist/primitives/elicitation/initialElicitationDraft.d.ts +1 -2
- package/dist/primitives/elicitation/initialElicitationDraft.d.ts.map +1 -1
- package/dist/primitives/elicitation/prepareElicitationContent.d.ts +1 -2
- package/dist/primitives/elicitation/prepareElicitationContent.d.ts.map +1 -1
- package/dist/primitives/elicitation/prepareElicitationContent.js +5 -1
- package/dist/primitives/elicitation/prepareElicitationContent.js.map +1 -1
- package/dist/primitives/manager/McpManagerAddCustomTrigger.d.ts +2 -3
- package/dist/primitives/manager/McpManagerAddCustomTrigger.d.ts.map +1 -1
- package/dist/primitives/manager/McpManagerConnectors.d.ts +2 -3
- package/dist/primitives/manager/McpManagerConnectors.d.ts.map +1 -1
- package/dist/primitives/manager/McpManagerCustomServers.d.ts +2 -3
- package/dist/primitives/manager/McpManagerCustomServers.d.ts.map +1 -1
- package/dist/primitives/manager/McpManagerRoot.d.ts +2 -3
- package/dist/primitives/manager/McpManagerRoot.d.ts.map +1 -1
- package/dist/primitives/server/McpServerConnectButton.d.ts +2 -3
- package/dist/primitives/server/McpServerConnectButton.d.ts.map +1 -1
- package/dist/primitives/server/McpServerDisconnectButton.d.ts +2 -3
- package/dist/primitives/server/McpServerDisconnectButton.d.ts.map +1 -1
- package/dist/primitives/server/McpServerError.d.ts +2 -3
- package/dist/primitives/server/McpServerError.d.ts.map +1 -1
- package/dist/primitives/server/McpServerIcon.d.ts +2 -3
- package/dist/primitives/server/McpServerIcon.d.ts.map +1 -1
- package/dist/primitives/server/McpServerName.d.ts +2 -3
- package/dist/primitives/server/McpServerName.d.ts.map +1 -1
- package/dist/primitives/server/McpServerOAuthLink.d.ts +2 -3
- package/dist/primitives/server/McpServerOAuthLink.d.ts.map +1 -1
- package/dist/primitives/server/McpServerRemoveButton.d.ts +2 -3
- package/dist/primitives/server/McpServerRemoveButton.d.ts.map +1 -1
- package/dist/primitives/server/McpServerRoot.d.ts +2 -3
- package/dist/primitives/server/McpServerRoot.d.ts.map +1 -1
- package/dist/primitives/server/McpServerStatus.d.ts +2 -3
- package/dist/primitives/server/McpServerStatus.d.ts.map +1 -1
- package/dist/primitives/server/McpServerToolName.d.ts +2 -3
- package/dist/primitives/server/McpServerToolName.d.ts.map +1 -1
- package/dist/primitives/server/McpServerTools.d.ts +3 -4
- package/dist/primitives/server/McpServerTools.d.ts.map +1 -1
- package/dist/resources/McpManagerResource.d.ts +2 -3
- package/dist/resources/McpManagerResource.d.ts.map +1 -1
- package/dist/resources/McpManagerResource.js +358 -244
- package/dist/resources/McpManagerResource.js.map +1 -1
- package/dist/resources/McpServerRemovalFence.d.ts +6 -0
- package/dist/resources/McpServerRemovalFence.d.ts.map +1 -0
- package/dist/resources/McpServerRemovalFence.js +11 -0
- package/dist/resources/McpServerRemovalFence.js.map +1 -0
- package/dist/resources/McpServerResource.d.ts +3 -4
- package/dist/resources/McpServerResource.d.ts.map +1 -1
- package/dist/resources/McpServerResource.js +9 -5
- package/dist/resources/McpServerResource.js.map +1 -1
- package/dist/resources/storage/McpCustomStorage.d.ts +1 -2
- package/dist/resources/storage/McpCustomStorage.d.ts.map +1 -1
- package/dist/resources/storage/McpLocalStorage.d.ts +4 -5
- package/dist/resources/storage/McpLocalStorage.d.ts.map +1 -1
- package/dist/resources/storage/McpLocalStorage.js +2 -1
- package/dist/resources/storage/McpLocalStorage.js.map +1 -1
- package/dist/resources/storage/McpMemoryStorage.d.ts +1 -2
- package/dist/resources/storage/McpMemoryStorage.d.ts.map +1 -1
- package/dist/resources/storage/types.d.ts +12 -11
- package/dist/resources/storage/types.d.ts.map +1 -1
- package/dist/resources/validateElicitationContent.d.ts +1 -2
- package/dist/resources/validateElicitationContent.d.ts.map +1 -1
- package/dist/utils/createMcpId.d.ts +1 -2
- package/dist/utils/createMcpId.d.ts.map +1 -1
- package/dist/utils/invokeMcpCallback.d.ts +1 -2
- package/dist/utils/invokeMcpCallback.d.ts.map +1 -1
- package/dist/utils/serverId.d.ts +2 -3
- package/dist/utils/serverId.d.ts.map +1 -1
- package/dist/utils/serverUrl.d.ts +3 -4
- package/dist/utils/serverUrl.d.ts.map +1 -1
- package/package.json +11 -10
- package/src/hooks/useMcpOAuthCallback.test.ts +53 -0
- package/src/hooks/useMcpOAuthCallback.tsx +12 -0
- package/src/index.ts +2 -1
- package/src/primitives/addForm/McpAddFormAccessibility.test.tsx +310 -0
- package/src/primitives/addForm/McpAddFormAuthFields.tsx +26 -16
- package/src/primitives/addForm/McpAddFormBearerTokenField.tsx +46 -0
- package/src/primitives/addForm/McpAddFormError.tsx +17 -3
- package/src/primitives/addForm/McpAddFormNameField.tsx +13 -1
- package/src/primitives/addForm/McpAddFormRoot.test.tsx +65 -0
- package/src/primitives/addForm/McpAddFormRoot.tsx +51 -8
- package/src/primitives/addForm/McpAddFormScopesField.tsx +34 -0
- package/src/primitives/addForm/McpAddFormUrlField.tsx +12 -1
- package/src/primitives/addForm/context.tsx +10 -0
- package/src/primitives/addForm.ts +2 -0
- package/src/primitives/elicitation/prepareElicitationContent.ts +8 -6
- package/src/resources/McpManagerResource.test.ts +797 -9
- package/src/resources/McpManagerResource.ts +242 -60
- package/src/resources/McpServerRemovalFence.ts +21 -0
- package/src/resources/McpServerResource.test.ts +9 -6
- package/src/resources/McpServerResource.ts +11 -6
- package/src/resources/storage/McpLocalStorage.test.ts +2 -0
- package/src/resources/storage/McpLocalStorage.ts +2 -1
- package/src/resources/storage/types.ts +10 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McpLocalStorage.js","names":["resource","useMemo","OAuthMetadataSchema","OAuthClientInformationFullSchema","OAuthProtectedResourceMetadataSchema","OAuthTokensSchema","normalizeMcpServerUrl","MCPAuthConfig","MCPCustomServerRecord","MCPPersistedAuthState","assertValidServerId","MCPStorage","McpLocalStorageOptions","keyPrefix","storage","Storage","scopeId","resolveStorage","opts","globalThis","localStorage","isRecord","value","Record","Array","isArray","isOptionalString","undefined","isNonEmptyString","trim","length","isOptionalNonEmptyString","isOptionalStringArray","every","item","isOptionalConnectionTimeout","Number","isFinite","isValidServerId","id","isMCPAuthConfig","auth","type","token","scopes","authorizationEndpoint","tokenEndpoint","registrationEndpoint","clientId","clientSecret","isCustomServerRecord","name","url","createdAt","connectionTimeout","normalizeCustomServerRecord","record","normalizeCustomServerRecords","flatMap","normalizeOAuthTokens","result","safeParse","success","data","normalizeClientInformation","isSecureNetworkUrl","URL","protocol","hostname","endsWith","startsWith","isMcpServerUrl","normalizeDiscoveryState","authorizationServerUrl","state","NonNullable","resourceMetadataUrl","metadata","authorizationServerMetadata","resourceMetadata","normalizePersistedAuthState","serverUrl","tokensClientId","codeVerifier","tokens","clientInformation","clientInformationSource","discoveryState","Object","keys","useMcpLocalStorage","t0","$","_c","t1","prefix","t2","customServersKey","t3","authKey","t4","key","fallback","raw","getItem","JSON","parse","T","read","t5","key_0","setItem","stringify","write","t6","key_1","removeItem","remove","t7","t8","t9","records","t10","id_0","t11","id_1","t12","id_2","t13","loadCustomServers","saveCustomServers","loadAuthState","saveAuthState","clearAuthState","McpLocalStorage"],"sources":["../../../src/resources/storage/McpLocalStorage.ts"],"sourcesContent":["import { resource } from \"@assistant-ui/tap\";\nimport { useMemo } from \"react\";\nimport {\n OAuthMetadataSchema,\n OAuthClientInformationFullSchema,\n OAuthProtectedResourceMetadataSchema,\n OAuthTokensSchema,\n} from \"@modelcontextprotocol/core\";\nimport { normalizeMcpServerUrl } from \"../../utils/serverUrl\";\nimport type { MCPAuthConfig, MCPCustomServerRecord } from \"../../mcp-scope\";\nimport type { MCPPersistedAuthState } from \"../../auth/types\";\nimport { assertValidServerId } from \"../../utils/serverId\";\nimport type { MCPStorage } from \"./types\";\n\nexport type McpLocalStorageOptions = {\n /** Namespace prefix for keys. Default \"aui-mcp\". */\n keyPrefix?: string;\n /** Override the underlying Storage. Defaults to globalThis.localStorage. */\n storage?: Storage;\n /**\n * Stable identity for the backing data, used to key server reconnects.\n * Required to get reconnect-on-swap behavior when `storage` is overridden;\n * without it a custom backing store declares no scope, since a prefix\n * alone cannot distinguish two different stores.\n */\n scopeId?: string;\n};\n\nfunction resolveStorage(opts: McpLocalStorageOptions): Storage | null {\n if (opts.storage) return opts.storage;\n if (typeof globalThis !== \"undefined\" && \"localStorage\" in globalThis) {\n try {\n return (globalThis as { localStorage: Storage }).localStorage;\n } catch {\n return null;\n }\n }\n return null;\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst isOptionalString = (value: unknown): value is string | undefined =>\n value === undefined || typeof value === \"string\";\n\nconst isNonEmptyString = (value: unknown): value is string =>\n typeof value === \"string\" && value.trim().length > 0;\n\nconst isOptionalNonEmptyString = (\n value: unknown,\n): value is string | undefined =>\n value === undefined || isNonEmptyString(value);\n\nconst isOptionalStringArray = (value: unknown): value is string[] | undefined =>\n value === undefined ||\n (Array.isArray(value) && value.every((item) => typeof item === \"string\"));\n\nconst isOptionalConnectionTimeout = (\n value: unknown,\n): value is number | undefined =>\n value === undefined ||\n (typeof value === \"number\" && Number.isFinite(value) && value >= 0);\n\nconst isValidServerId = (id: string): boolean => {\n try {\n assertValidServerId(id);\n return true;\n } catch {\n return false;\n }\n};\n\nconst isMCPAuthConfig = (auth: unknown): auth is MCPAuthConfig => {\n if (!isRecord(auth)) return false;\n\n switch (auth.type) {\n case \"none\":\n return true;\n case \"bearer\":\n return isOptionalNonEmptyString(auth.token);\n case \"oauth\":\n return (\n isOptionalStringArray(auth.scopes) &&\n isOptionalString(auth.authorizationEndpoint) &&\n isOptionalString(auth.tokenEndpoint) &&\n isOptionalString(auth.registrationEndpoint) &&\n isOptionalString(auth.clientId) &&\n isOptionalString(auth.clientSecret)\n );\n default:\n return false;\n }\n};\n\nconst isCustomServerRecord = (\n value: unknown,\n): value is MCPCustomServerRecord => {\n if (!isRecord(value)) return false;\n if (typeof value.id !== \"string\" || !isValidServerId(value.id)) {\n return false;\n }\n return (\n isNonEmptyString(value.name) &&\n isNonEmptyString(value.url) &&\n Number.isFinite(value.createdAt) &&\n isMCPAuthConfig(value.auth) &&\n isOptionalConnectionTimeout(value.connectionTimeout)\n );\n};\n\nconst normalizeCustomServerRecord = (\n value: unknown,\n): MCPCustomServerRecord | null => {\n if (isCustomServerRecord(value)) return value;\n if (!isRecord(value)) return null;\n\n const record = { ...value };\n delete record.connectionTimeout;\n return isCustomServerRecord(record) ? record : null;\n};\n\nexport const normalizeCustomServerRecords = (\n value: unknown,\n): MCPCustomServerRecord[] => {\n if (!Array.isArray(value)) return [];\n return value.flatMap((item) => {\n const record = normalizeCustomServerRecord(item);\n return record === null ? [] : [record];\n });\n};\n\nconst normalizeOAuthTokens = (\n value: unknown,\n): MCPPersistedAuthState[\"tokens\"] | undefined => {\n const result = OAuthTokensSchema.safeParse(value);\n return result.success ? result.data : undefined;\n};\n\nconst normalizeClientInformation = (\n value: unknown,\n): MCPPersistedAuthState[\"clientInformation\"] | undefined => {\n const result = OAuthClientInformationFullSchema.safeParse(value);\n return result.success ? result.data : undefined;\n};\n\nconst isSecureNetworkUrl = (value: unknown): value is string => {\n if (!isNonEmptyString(value)) return false;\n try {\n const url = new URL(value);\n return (\n url.protocol === \"https:\" ||\n (url.protocol === \"http:\" &&\n (url.hostname === \"localhost\" ||\n url.hostname.endsWith(\".localhost\") ||\n url.hostname.startsWith(\"127.\") ||\n url.hostname === \"[::1]\"))\n );\n } catch {\n return false;\n }\n};\n\nconst isMcpServerUrl = (value: unknown): value is string => {\n if (typeof value !== \"string\") return false;\n try {\n const url = new URL(value);\n return url.protocol === \"https:\" || url.protocol === \"http:\";\n } catch {\n return false;\n }\n};\n\nconst normalizeDiscoveryState = (\n value: unknown,\n): MCPPersistedAuthState[\"discoveryState\"] | undefined => {\n if (!isRecord(value) || !isSecureNetworkUrl(value.authorizationServerUrl)) {\n return undefined;\n }\n\n // A malformed optional field is dropped alone: keeping the validated\n // authorization server URL preserves the redirect-time binding, and the SDK\n // re-discovers whatever metadata is missing.\n const state: NonNullable<MCPPersistedAuthState[\"discoveryState\"]> = {\n authorizationServerUrl: value.authorizationServerUrl,\n };\n\n if (isSecureNetworkUrl(value.resourceMetadataUrl)) {\n state.resourceMetadataUrl = value.resourceMetadataUrl;\n }\n\n const metadata = OAuthMetadataSchema.safeParse(\n value.authorizationServerMetadata,\n );\n if (metadata.success) state.authorizationServerMetadata = metadata.data;\n\n const resourceMetadata = OAuthProtectedResourceMetadataSchema.safeParse(\n value.resourceMetadata,\n );\n if (resourceMetadata.success) state.resourceMetadata = resourceMetadata.data;\n\n return state;\n};\n\nexport const normalizePersistedAuthState = (\n value: unknown,\n): MCPPersistedAuthState | null => {\n if (!isRecord(value)) return null;\n if (\"serverUrl\" in value && !isMcpServerUrl(value.serverUrl)) return null;\n\n const state: MCPPersistedAuthState = {};\n if (isMcpServerUrl(value.serverUrl)) {\n state.serverUrl = normalizeMcpServerUrl(value.serverUrl);\n }\n if (isNonEmptyString(value.token)) state.token = value.token;\n if (isNonEmptyString(value.tokensClientId)) {\n state.tokensClientId = value.tokensClientId;\n }\n if (isNonEmptyString(value.codeVerifier)) {\n state.codeVerifier = value.codeVerifier;\n }\n if (isNonEmptyString(value.state)) state.state = value.state;\n\n const tokens = normalizeOAuthTokens(value.tokens);\n if (tokens) state.tokens = tokens;\n\n const clientInformation = normalizeClientInformation(value.clientInformation);\n if (clientInformation) state.clientInformation = clientInformation;\n if (value.clientInformationSource === \"registered\") {\n state.clientInformationSource = value.clientInformationSource;\n }\n\n const discoveryState = normalizeDiscoveryState(value.discoveryState);\n if (discoveryState) state.discoveryState = discoveryState;\n\n return Object.keys(state).length > 0 ? state : null;\n};\n\nconst useMcpLocalStorage = (opts: McpLocalStorageOptions = {}): MCPStorage => {\n const prefix = opts.keyPrefix ?? \"aui-mcp\";\n const storage = resolveStorage(opts);\n // Deriving a scope from the prefix is only honest for the shared\n // globalThis.localStorage; two custom backing stores under one prefix hold\n // different data, so an overridden backing declares no scope unless the\n // caller names one.\n const scopeId =\n opts.scopeId ??\n (opts.storage === undefined ? `local-storage:${prefix}` : undefined);\n\n // Callers key per-server coordination state on this instance, so it has to\n // stay referentially stable for as long as the underlying store does.\n return useMemo(() => {\n const customServersKey = `${prefix}:custom-servers`;\n const authKey = (id: string) => `${prefix}:auth:${id}`;\n\n const read = <T>(key: string, fallback: T): T => {\n if (!storage) return fallback;\n try {\n const raw = storage.getItem(key);\n if (raw == null) return fallback;\n return JSON.parse(raw) as T;\n } catch {\n return fallback;\n }\n };\n\n const write = (key: string, value: unknown): void => {\n if (!storage) return;\n try {\n storage.setItem(key, JSON.stringify(value));\n } catch {\n // quota or serialization failure — silently drop\n }\n };\n\n const remove = (key: string): void => {\n if (!storage) return;\n try {\n storage.removeItem(key);\n } catch {\n // ignore\n }\n };\n\n return {\n ...(scopeId !== undefined ? { scopeId } : {}),\n loadCustomServers: async () =>\n normalizeCustomServerRecords(read<unknown>(customServersKey, [])),\n saveCustomServers: async (records) => {\n write(customServersKey, records);\n },\n loadAuthState: async (id) =>\n normalizePersistedAuthState(read<unknown>(authKey(id), null)),\n saveAuthState: async (id, state) => {\n write(authKey(id), state);\n },\n clearAuthState: async (id) => {\n remove(authKey(id));\n },\n };\n }, [prefix, storage, scopeId]);\n};\n\nexport const McpLocalStorage = resource(useMcpLocalStorage);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"McpLocalStorage.js","names":["resource","useMemo","OAuthMetadataSchema","OAuthClientInformationFullSchema","OAuthProtectedResourceMetadataSchema","OAuthTokensSchema","normalizeMcpServerUrl","MCPAuthConfig","MCPCustomServerRecord","MCPPersistedAuthState","assertValidServerId","MCPStorage","McpLocalStorageOptions","keyPrefix","storage","Storage","scopeId","resolveStorage","opts","globalThis","localStorage","isRecord","value","Record","Array","isArray","isOptionalString","undefined","isNonEmptyString","trim","length","isOptionalNonEmptyString","isOptionalStringArray","every","item","isOptionalConnectionTimeout","Number","isFinite","isValidServerId","id","isMCPAuthConfig","auth","type","token","scopes","authorizationEndpoint","tokenEndpoint","registrationEndpoint","clientId","clientSecret","isCustomServerRecord","name","url","createdAt","connectionTimeout","normalizeCustomServerRecord","record","normalizeCustomServerRecords","flatMap","normalizeOAuthTokens","result","safeParse","success","data","normalizeClientInformation","isSecureNetworkUrl","URL","isIpv4Loopback","test","hostname","protocol","endsWith","isMcpServerUrl","normalizeDiscoveryState","authorizationServerUrl","state","NonNullable","resourceMetadataUrl","metadata","authorizationServerMetadata","resourceMetadata","normalizePersistedAuthState","serverUrl","tokensClientId","codeVerifier","tokens","clientInformation","clientInformationSource","discoveryState","Object","keys","useMcpLocalStorage","t0","$","_c","t1","prefix","t2","customServersKey","t3","authKey","t4","key","fallback","raw","getItem","JSON","parse","T","read","t5","key_0","setItem","stringify","write","t6","key_1","removeItem","remove","t7","t8","t9","records","t10","id_0","t11","id_1","t12","id_2","t13","loadCustomServers","saveCustomServers","loadAuthState","saveAuthState","clearAuthState","McpLocalStorage"],"sources":["../../../src/resources/storage/McpLocalStorage.ts"],"sourcesContent":["import { resource } from \"@assistant-ui/tap\";\nimport { useMemo } from \"react\";\nimport {\n OAuthMetadataSchema,\n OAuthClientInformationFullSchema,\n OAuthProtectedResourceMetadataSchema,\n OAuthTokensSchema,\n} from \"@modelcontextprotocol/core\";\nimport { normalizeMcpServerUrl } from \"../../utils/serverUrl\";\nimport type { MCPAuthConfig, MCPCustomServerRecord } from \"../../mcp-scope\";\nimport type { MCPPersistedAuthState } from \"../../auth/types\";\nimport { assertValidServerId } from \"../../utils/serverId\";\nimport type { MCPStorage } from \"./types\";\n\nexport type McpLocalStorageOptions = {\n /** Namespace prefix for keys. Default \"aui-mcp\". */\n keyPrefix?: string;\n /** Override the underlying Storage. Defaults to globalThis.localStorage. */\n storage?: Storage;\n /**\n * Stable identity for the backing data, used to key server reconnects.\n * Required to get reconnect-on-swap behavior when `storage` is overridden;\n * without it a custom backing store declares no scope, since a prefix\n * alone cannot distinguish two different stores.\n */\n scopeId?: string;\n};\n\nfunction resolveStorage(opts: McpLocalStorageOptions): Storage | null {\n if (opts.storage) return opts.storage;\n if (typeof globalThis !== \"undefined\" && \"localStorage\" in globalThis) {\n try {\n return (globalThis as { localStorage: Storage }).localStorage;\n } catch {\n return null;\n }\n }\n return null;\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst isOptionalString = (value: unknown): value is string | undefined =>\n value === undefined || typeof value === \"string\";\n\nconst isNonEmptyString = (value: unknown): value is string =>\n typeof value === \"string\" && value.trim().length > 0;\n\nconst isOptionalNonEmptyString = (\n value: unknown,\n): value is string | undefined =>\n value === undefined || isNonEmptyString(value);\n\nconst isOptionalStringArray = (value: unknown): value is string[] | undefined =>\n value === undefined ||\n (Array.isArray(value) && value.every((item) => typeof item === \"string\"));\n\nconst isOptionalConnectionTimeout = (\n value: unknown,\n): value is number | undefined =>\n value === undefined ||\n (typeof value === \"number\" && Number.isFinite(value) && value >= 0);\n\nconst isValidServerId = (id: string): boolean => {\n try {\n assertValidServerId(id);\n return true;\n } catch {\n return false;\n }\n};\n\nconst isMCPAuthConfig = (auth: unknown): auth is MCPAuthConfig => {\n if (!isRecord(auth)) return false;\n\n switch (auth.type) {\n case \"none\":\n return true;\n case \"bearer\":\n return isOptionalNonEmptyString(auth.token);\n case \"oauth\":\n return (\n isOptionalStringArray(auth.scopes) &&\n isOptionalString(auth.authorizationEndpoint) &&\n isOptionalString(auth.tokenEndpoint) &&\n isOptionalString(auth.registrationEndpoint) &&\n isOptionalString(auth.clientId) &&\n isOptionalString(auth.clientSecret)\n );\n default:\n return false;\n }\n};\n\nconst isCustomServerRecord = (\n value: unknown,\n): value is MCPCustomServerRecord => {\n if (!isRecord(value)) return false;\n if (typeof value.id !== \"string\" || !isValidServerId(value.id)) {\n return false;\n }\n return (\n isNonEmptyString(value.name) &&\n isNonEmptyString(value.url) &&\n Number.isFinite(value.createdAt) &&\n isMCPAuthConfig(value.auth) &&\n isOptionalConnectionTimeout(value.connectionTimeout)\n );\n};\n\nconst normalizeCustomServerRecord = (\n value: unknown,\n): MCPCustomServerRecord | null => {\n if (isCustomServerRecord(value)) return value;\n if (!isRecord(value)) return null;\n\n const record = { ...value };\n delete record.connectionTimeout;\n return isCustomServerRecord(record) ? record : null;\n};\n\nexport const normalizeCustomServerRecords = (\n value: unknown,\n): MCPCustomServerRecord[] => {\n if (!Array.isArray(value)) return [];\n return value.flatMap((item) => {\n const record = normalizeCustomServerRecord(item);\n return record === null ? [] : [record];\n });\n};\n\nconst normalizeOAuthTokens = (\n value: unknown,\n): MCPPersistedAuthState[\"tokens\"] | undefined => {\n const result = OAuthTokensSchema.safeParse(value);\n return result.success ? result.data : undefined;\n};\n\nconst normalizeClientInformation = (\n value: unknown,\n): MCPPersistedAuthState[\"clientInformation\"] | undefined => {\n const result = OAuthClientInformationFullSchema.safeParse(value);\n return result.success ? result.data : undefined;\n};\n\nconst isSecureNetworkUrl = (value: unknown): value is string => {\n if (!isNonEmptyString(value)) return false;\n try {\n const url = new URL(value);\n const isIpv4Loopback = /^127(?:\\.\\d{1,3}){3}$/.test(url.hostname);\n return (\n url.protocol === \"https:\" ||\n (url.protocol === \"http:\" &&\n (url.hostname === \"localhost\" ||\n url.hostname.endsWith(\".localhost\") ||\n isIpv4Loopback ||\n url.hostname === \"[::1]\"))\n );\n } catch {\n return false;\n }\n};\n\nconst isMcpServerUrl = (value: unknown): value is string => {\n if (typeof value !== \"string\") return false;\n try {\n const url = new URL(value);\n return url.protocol === \"https:\" || url.protocol === \"http:\";\n } catch {\n return false;\n }\n};\n\nconst normalizeDiscoveryState = (\n value: unknown,\n): MCPPersistedAuthState[\"discoveryState\"] | undefined => {\n if (!isRecord(value) || !isSecureNetworkUrl(value.authorizationServerUrl)) {\n return undefined;\n }\n\n // A malformed optional field is dropped alone: keeping the validated\n // authorization server URL preserves the redirect-time binding, and the SDK\n // re-discovers whatever metadata is missing.\n const state: NonNullable<MCPPersistedAuthState[\"discoveryState\"]> = {\n authorizationServerUrl: value.authorizationServerUrl,\n };\n\n if (isSecureNetworkUrl(value.resourceMetadataUrl)) {\n state.resourceMetadataUrl = value.resourceMetadataUrl;\n }\n\n const metadata = OAuthMetadataSchema.safeParse(\n value.authorizationServerMetadata,\n );\n if (metadata.success) state.authorizationServerMetadata = metadata.data;\n\n const resourceMetadata = OAuthProtectedResourceMetadataSchema.safeParse(\n value.resourceMetadata,\n );\n if (resourceMetadata.success) state.resourceMetadata = resourceMetadata.data;\n\n return state;\n};\n\nexport const normalizePersistedAuthState = (\n value: unknown,\n): MCPPersistedAuthState | null => {\n if (!isRecord(value)) return null;\n if (\"serverUrl\" in value && !isMcpServerUrl(value.serverUrl)) return null;\n\n const state: MCPPersistedAuthState = {};\n if (isMcpServerUrl(value.serverUrl)) {\n state.serverUrl = normalizeMcpServerUrl(value.serverUrl);\n }\n if (isNonEmptyString(value.token)) state.token = value.token;\n if (isNonEmptyString(value.tokensClientId)) {\n state.tokensClientId = value.tokensClientId;\n }\n if (isNonEmptyString(value.codeVerifier)) {\n state.codeVerifier = value.codeVerifier;\n }\n if (isNonEmptyString(value.state)) state.state = value.state;\n\n const tokens = normalizeOAuthTokens(value.tokens);\n if (tokens) state.tokens = tokens;\n\n const clientInformation = normalizeClientInformation(value.clientInformation);\n if (clientInformation) state.clientInformation = clientInformation;\n if (value.clientInformationSource === \"registered\") {\n state.clientInformationSource = value.clientInformationSource;\n }\n\n const discoveryState = normalizeDiscoveryState(value.discoveryState);\n if (discoveryState) state.discoveryState = discoveryState;\n\n return Object.keys(state).length > 0 ? state : null;\n};\n\nconst useMcpLocalStorage = (opts: McpLocalStorageOptions = {}): MCPStorage => {\n const prefix = opts.keyPrefix ?? \"aui-mcp\";\n const storage = resolveStorage(opts);\n // Deriving a scope from the prefix is only honest for the shared\n // globalThis.localStorage; two custom backing stores under one prefix hold\n // different data, so an overridden backing declares no scope unless the\n // caller names one.\n const scopeId =\n opts.scopeId ??\n (opts.storage === undefined ? `local-storage:${prefix}` : undefined);\n\n // Callers key per-server coordination state on this instance, so it has to\n // stay referentially stable for as long as the underlying store does.\n return useMemo(() => {\n const customServersKey = `${prefix}:custom-servers`;\n const authKey = (id: string) => `${prefix}:auth:${id}`;\n\n const read = <T>(key: string, fallback: T): T => {\n if (!storage) return fallback;\n try {\n const raw = storage.getItem(key);\n if (raw == null) return fallback;\n return JSON.parse(raw) as T;\n } catch {\n return fallback;\n }\n };\n\n const write = (key: string, value: unknown): void => {\n if (!storage) return;\n try {\n storage.setItem(key, JSON.stringify(value));\n } catch {\n // quota or serialization failure — silently drop\n }\n };\n\n const remove = (key: string): void => {\n if (!storage) return;\n try {\n storage.removeItem(key);\n } catch {\n // ignore\n }\n };\n\n return {\n ...(scopeId !== undefined ? { scopeId } : {}),\n loadCustomServers: async () =>\n normalizeCustomServerRecords(read<unknown>(customServersKey, [])),\n saveCustomServers: async (records) => {\n write(customServersKey, records);\n },\n loadAuthState: async (id) =>\n normalizePersistedAuthState(read<unknown>(authKey(id), null)),\n saveAuthState: async (id, state) => {\n write(authKey(id), state);\n },\n clearAuthState: async (id) => {\n remove(authKey(id));\n },\n };\n }, [prefix, storage, scopeId]);\n};\n\nexport const McpLocalStorage = resource(useMcpLocalStorage);\n"],"mappings":"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"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { MCPStorage } from "./types.js";
|
|
2
2
|
//#region src/resources/storage/McpMemoryStorage.d.ts
|
|
3
|
-
declare const McpMemoryStorage: import("@assistant-ui/tap").Resource<MCPStorage, []>;
|
|
3
|
+
export declare const McpMemoryStorage: import("@assistant-ui/tap").Resource<MCPStorage, []>;
|
|
4
4
|
//#endregion
|
|
5
|
-
export { McpMemoryStorage };
|
|
6
5
|
//# sourceMappingURL=McpMemoryStorage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McpMemoryStorage.d.ts","names":[],"sources":["../../../src/resources/storage/McpMemoryStorage.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"McpMemoryStorage.d.ts","names":[],"sources":["../../../src/resources/storage/McpMemoryStorage.ts"],"mappings":";;qBA6Ba,8CAAgB,SAAA"}
|
|
@@ -2,17 +2,19 @@ import { MCPCustomServerRecord } from "../../mcp-scope.js";
|
|
|
2
2
|
import { MCPPersistedAuthState } from "../../auth/types.js";
|
|
3
3
|
import { ResourceElement } from "@assistant-ui/tap";
|
|
4
4
|
//#region src/resources/storage/types.d.ts
|
|
5
|
-
type MCPStorage = {
|
|
5
|
+
export type MCPStorage = {
|
|
6
6
|
/**
|
|
7
7
|
* Stable identity of the backing store. Two storages with the same scopeId
|
|
8
|
-
* must read and write the same persisted data. When present,
|
|
9
|
-
* connections and the OAuth write fence key on it
|
|
10
|
-
* differently-scoped storage
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
8
|
+
* must read and write the same persisted data. When present, custom servers,
|
|
9
|
+
* server connections, and the OAuth write fence key on it. Swapping to a
|
|
10
|
+
* differently-scoped storage rehydrates its custom servers and reconnects
|
|
11
|
+
* authenticated servers instead of retaining data or a live OAuth flow from
|
|
12
|
+
* the replaced store. Clearing through a same-scoped replacement still waits
|
|
13
|
+
* for writes queued against the storage it replaced. When absent, the fence
|
|
14
|
+
* falls back to object identity while custom servers and connections never
|
|
15
|
+
* re-key. Replacing an unscoped storage can therefore persist the previous
|
|
16
|
+
* store's custom servers into the replacement, and a clear runs unfenced
|
|
17
|
+
* against writes queued by the object it replaced.
|
|
16
18
|
*/
|
|
17
19
|
scopeId?: string;
|
|
18
20
|
loadCustomServers: () => Promise<MCPCustomServerRecord[]>;
|
|
@@ -21,7 +23,6 @@ type MCPStorage = {
|
|
|
21
23
|
saveAuthState: (serverId: string, state: MCPPersistedAuthState) => Promise<void>;
|
|
22
24
|
clearAuthState: (serverId: string) => Promise<void>;
|
|
23
25
|
};
|
|
24
|
-
type MCPStorageElement = ResourceElement<MCPStorage>;
|
|
26
|
+
export type MCPStorageElement = ResourceElement<MCPStorage>;
|
|
25
27
|
//#endregion
|
|
26
|
-
export { MCPStorage, MCPStorageElement };
|
|
27
28
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/resources/storage/types.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/resources/storage/types.ts"],"mappings":";;;;YAIY;;;;;;;;;;;;;;EAcV;EACA,yBAAyB,QAAQ;EACjC,oBAAoB,SAAS,4BAA4B;EACzD,gBAAgB,qBAAqB,QAAQ;EAC7C,gBACE,kBACA,OAAO,0BACJ;EACL,iBAAiB,qBAAqB;;YAG5B,oBAAoB,gBAAgB"}
|
|
@@ -3,7 +3,6 @@ type ValidationError = {
|
|
|
3
3
|
property: string;
|
|
4
4
|
message: string;
|
|
5
5
|
};
|
|
6
|
-
declare const validateElicitationContent: (requestedSchema: unknown, content: Record<string, unknown>) => readonly ValidationError[];
|
|
6
|
+
export declare const validateElicitationContent: (requestedSchema: unknown, content: Record<string, unknown>) => readonly ValidationError[];
|
|
7
7
|
//#endregion
|
|
8
|
-
export { validateElicitationContent };
|
|
9
8
|
//# sourceMappingURL=validateElicitationContent.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validateElicitationContent.d.ts","names":[],"sources":["../../src/resources/validateElicitationContent.ts"],"mappings":";KAAK;EACH;EACA;;
|
|
1
|
+
{"version":3,"file":"validateElicitationContent.d.ts","names":[],"sources":["../../src/resources/validateElicitationContent.ts"],"mappings":";KAAK;EACH;EACA;;qBA+BW,6BACX,0BACA,SAAS,qCACC"}
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
* Both forms are alphanumeric or hyphenated, so neither can contain the
|
|
4
4
|
* separators `assertValidServerId` reserves.
|
|
5
5
|
*/
|
|
6
|
-
declare const createMcpId: () => string;
|
|
6
|
+
export declare const createMcpId: () => string;
|
|
7
7
|
//#endregion
|
|
8
|
-
export { createMcpId };
|
|
9
8
|
//# sourceMappingURL=createMcpId.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createMcpId.d.ts","names":[],"sources":["../../src/utils/createMcpId.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"createMcpId.d.ts","names":[],"sources":["../../src/utils/createMcpId.ts"],"mappings":";;;;;qBAMa"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
//#region src/utils/invokeMcpCallback.d.ts
|
|
2
|
-
declare const invokeMcpCallback: <TArgs extends unknown[]>(name: string, callback: ((...args: TArgs) => void) | undefined, ...args: TArgs) => void;
|
|
2
|
+
export declare const invokeMcpCallback: <TArgs extends unknown[]>(name: string, callback: ((...args: TArgs) => void) | undefined, ...args: TArgs) => void;
|
|
3
3
|
//#endregion
|
|
4
|
-
export { invokeMcpCallback };
|
|
5
4
|
//# sourceMappingURL=invokeMcpCallback.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"invokeMcpCallback.d.ts","names":[],"sources":["../../src/utils/invokeMcpCallback.ts"],"mappings":";
|
|
1
|
+
{"version":3,"file":"invokeMcpCallback.d.ts","names":[],"sources":["../../src/utils/invokeMcpCallback.ts"],"mappings":";qBAEa,oBAAqB,yBAChC,cACA,eAAe,MAAM,gCAClB,MAAM"}
|
package/dist/utils/serverId.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
//#region src/utils/serverId.d.ts
|
|
2
|
-
declare function assertValidServerId(id: string): void;
|
|
3
|
-
declare function assertUniqueServerIds(ids: Iterable<string>): void;
|
|
2
|
+
export declare function assertValidServerId(id: string): void;
|
|
3
|
+
export declare function assertUniqueServerIds(ids: Iterable<string>): void;
|
|
4
4
|
//#endregion
|
|
5
|
-
export { assertUniqueServerIds, assertValidServerId };
|
|
6
5
|
//# sourceMappingURL=serverId.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serverId.d.ts","names":[],"sources":["../../src/utils/serverId.ts"],"mappings":";
|
|
1
|
+
{"version":3,"file":"serverId.d.ts","names":[],"sources":["../../src/utils/serverId.ts"],"mappings":";wBAIgB,oBAAoB;wBAgBpB,sBAAsB,KAAK"}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { MCPPersistedAuthState } from "../auth/types.js";
|
|
2
2
|
//#region src/utils/serverUrl.d.ts
|
|
3
|
-
declare const normalizeMcpServerUrl: (serverUrl: string) => string;
|
|
4
|
-
declare const isAuthStateForServerUrl: (state: MCPPersistedAuthState | null, serverUrl: string) => boolean;
|
|
5
|
-
declare const hasPersistedCredentials: (state: MCPPersistedAuthState | null) => boolean;
|
|
3
|
+
export declare const normalizeMcpServerUrl: (serverUrl: string) => string;
|
|
4
|
+
export declare const isAuthStateForServerUrl: (state: MCPPersistedAuthState | null, serverUrl: string) => boolean;
|
|
5
|
+
export declare const hasPersistedCredentials: (state: MCPPersistedAuthState | null) => boolean;
|
|
6
6
|
//#endregion
|
|
7
|
-
export { hasPersistedCredentials, isAuthStateForServerUrl, normalizeMcpServerUrl };
|
|
8
7
|
//# sourceMappingURL=serverUrl.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serverUrl.d.ts","names":[],"sources":["../../src/utils/serverUrl.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"serverUrl.d.ts","names":[],"sources":["../../src/utils/serverUrl.ts"],"mappings":";;qBAEa,wBAAyB;qBAGzB,0BACX,OAAO,8BACP;qBAaW,0BACX,OAAO"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@assistant-ui/react-mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.19",
|
|
4
4
|
"description": "MCP server configuration and connection primitives for @assistant-ui",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|
|
@@ -27,13 +27,13 @@
|
|
|
27
27
|
],
|
|
28
28
|
"sideEffects": false,
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@assistant-ui/core": "^0.3.
|
|
31
|
-
"@assistant-ui/store": "^0.3.
|
|
32
|
-
"@assistant-ui/tap": "^0.9.
|
|
30
|
+
"@assistant-ui/core": "^0.3.20",
|
|
31
|
+
"@assistant-ui/store": "^0.3.14",
|
|
32
|
+
"@assistant-ui/tap": "^0.9.18",
|
|
33
33
|
"@modelcontextprotocol/client": "^2.0.0",
|
|
34
34
|
"@modelcontextprotocol/core": "^2.0.0",
|
|
35
35
|
"@radix-ui/react-primitive": "^2.1.10",
|
|
36
|
-
"assistant-stream": "^0.3.
|
|
36
|
+
"assistant-stream": "^0.3.44"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@types/react": "*",
|
|
@@ -45,13 +45,13 @@
|
|
|
45
45
|
}
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@assistant-ui/x-buildutils": "0.0.
|
|
49
|
-
"@testing-library/dom": "^10.4.
|
|
48
|
+
"@assistant-ui/x-buildutils": "0.0.28",
|
|
49
|
+
"@testing-library/dom": "^10.4.2",
|
|
50
50
|
"@testing-library/react": "^16.3.3",
|
|
51
|
-
"@types/react": "^19.
|
|
51
|
+
"@types/react": "^19.3.0",
|
|
52
52
|
"jsdom": "^30.0.1",
|
|
53
|
-
"react": "^19.
|
|
54
|
-
"vitest": "^
|
|
53
|
+
"react": "^19.3.0",
|
|
54
|
+
"vitest": "^5.0.1"
|
|
55
55
|
},
|
|
56
56
|
"publishConfig": {
|
|
57
57
|
"access": "public",
|
|
@@ -69,6 +69,7 @@
|
|
|
69
69
|
"scripts": {
|
|
70
70
|
"build": "aui-build",
|
|
71
71
|
"test": "vitest run",
|
|
72
|
+
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.test.json",
|
|
72
73
|
"test:watch": "vitest"
|
|
73
74
|
}
|
|
74
75
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
createElement,
|
|
5
|
+
StrictMode,
|
|
5
6
|
Suspense,
|
|
6
7
|
startTransition,
|
|
7
8
|
type PropsWithChildren,
|
|
@@ -171,6 +172,58 @@ describe("useMcpOAuthCallback", () => {
|
|
|
171
172
|
expect(onCompleteB).not.toHaveBeenCalled();
|
|
172
173
|
expect(onCompleteA).toHaveBeenCalledWith("docs");
|
|
173
174
|
});
|
|
175
|
+
|
|
176
|
+
it("keeps the newer callback's result when an older attempt settles late", async () => {
|
|
177
|
+
const secondUrl =
|
|
178
|
+
"https://app.example.com/oauth/callback?state=aui-mcp%3AZG9jcw.second";
|
|
179
|
+
let rejectFirst!: (err: Error) => void;
|
|
180
|
+
mocks.completeAuth.mockReturnValueOnce(
|
|
181
|
+
new Promise<void>((_resolve, reject) => {
|
|
182
|
+
rejectFirst = reject;
|
|
183
|
+
}),
|
|
184
|
+
);
|
|
185
|
+
mocks.completeAuth.mockResolvedValueOnce();
|
|
186
|
+
const onComplete = vi.fn();
|
|
187
|
+
const onError = vi.fn();
|
|
188
|
+
|
|
189
|
+
const { result, rerender } = renderHook(
|
|
190
|
+
({ url }) => useMcpOAuthCallback({ url, onComplete, onError }),
|
|
191
|
+
{ initialProps: { url: callbackUrl } },
|
|
192
|
+
);
|
|
193
|
+
await waitFor(() => expect(mocks.completeAuth).toHaveBeenCalledOnce());
|
|
194
|
+
|
|
195
|
+
rerender({ url: secondUrl });
|
|
196
|
+
await waitFor(() => expect(result.current.status).toBe("done"));
|
|
197
|
+
|
|
198
|
+
// The first attempt only fails once the second has already succeeded.
|
|
199
|
+
await act(async () => {
|
|
200
|
+
rejectFirst(new Error("authorization code expired"));
|
|
201
|
+
await Promise.resolve();
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
expect(result.current).toMatchObject({ status: "done", error: null });
|
|
205
|
+
expect(onError).not.toHaveBeenCalled();
|
|
206
|
+
expect(onComplete).toHaveBeenCalledExactlyOnceWith("docs");
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// Strict Mode tears the effect down and remounts it without starting a new
|
|
210
|
+
// attempt, so the one already running must still publish its result.
|
|
211
|
+
it("publishes the result under Strict Mode's remount", async () => {
|
|
212
|
+
mocks.completeAuth.mockResolvedValueOnce();
|
|
213
|
+
const onComplete = vi.fn();
|
|
214
|
+
|
|
215
|
+
const { result } = renderHook(
|
|
216
|
+
() => useMcpOAuthCallback({ url: callbackUrl, onComplete }),
|
|
217
|
+
{
|
|
218
|
+
wrapper: ({ children }: PropsWithChildren) =>
|
|
219
|
+
createElement(StrictMode, null, children),
|
|
220
|
+
},
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
await waitFor(() => expect(result.current.status).toBe("done"));
|
|
224
|
+
expect(mocks.completeAuth).toHaveBeenCalledOnce();
|
|
225
|
+
expect(onComplete).toHaveBeenCalledExactlyOnceWith("docs");
|
|
226
|
+
});
|
|
174
227
|
});
|
|
175
228
|
|
|
176
229
|
describe("createMcpOAuthCallbackError", () => {
|
|
@@ -62,6 +62,15 @@ export function useMcpOAuthCallback(
|
|
|
62
62
|
if (startedRef.current === url) return;
|
|
63
63
|
startedRef.current = url;
|
|
64
64
|
|
|
65
|
+
// A callback page can be handed a second login URL while the first
|
|
66
|
+
// completeAuth is still in flight. That attempt keeps running, so it
|
|
67
|
+
// publishes only while its own URL is still the one being attempted;
|
|
68
|
+
// otherwise an older failure would overwrite the newer attempt's success.
|
|
69
|
+
// The check is against `startedRef` rather than a teardown flag so that
|
|
70
|
+
// Strict Mode's unmount-remount, which starts no new attempt, still
|
|
71
|
+
// publishes the result of the one already running.
|
|
72
|
+
const superseded = () => startedRef.current !== url;
|
|
73
|
+
|
|
65
74
|
void (async () => {
|
|
66
75
|
let serverId: string | null = null;
|
|
67
76
|
try {
|
|
@@ -72,10 +81,13 @@ export function useMcpOAuthCallback(
|
|
|
72
81
|
if (!serverId) {
|
|
73
82
|
throw new Error("state was not created by assistant-ui MCP");
|
|
74
83
|
}
|
|
84
|
+
if (superseded()) return;
|
|
75
85
|
setResult({ status: "running", serverId, error: null });
|
|
76
86
|
await aui.mcp.server({ id: serverId }).completeAuth(url);
|
|
87
|
+
if (superseded()) return;
|
|
77
88
|
setResult({ status: "done", serverId, error: null });
|
|
78
89
|
} catch (err) {
|
|
90
|
+
if (superseded()) return;
|
|
79
91
|
const error = createMcpOAuthCallbackError(err, serverId);
|
|
80
92
|
setResult({ status: "error", serverId, error });
|
|
81
93
|
invokeMcpCallback("onError", optsRef.current.onError, error);
|
package/src/index.ts
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
import "./mcp-scope";
|
|
3
3
|
|
|
4
4
|
// Resource — the entry point. Mount via:
|
|
5
|
-
//
|
|
5
|
+
// const config = AuiConfig({ mcp: McpManagerResource({ connectors }) })
|
|
6
|
+
// <AssistantRuntimeProvider runtime={runtime} config={config}>…</AssistantRuntimeProvider>
|
|
6
7
|
export {
|
|
7
8
|
McpManagerResource,
|
|
8
9
|
type McpManagerResourceProps,
|