@assistant-ui/react-mcp 0.0.6 → 0.0.7

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 (54) hide show
  1. package/dist/auth/createOAuthProvider.js.map +1 -1
  2. package/dist/context/McpConnectorByIndexProvider.js.map +1 -1
  3. package/dist/context/McpCustomServerByIndexProvider.js.map +1 -1
  4. package/dist/context/McpServerByIdProvider.js.map +1 -1
  5. package/dist/hooks/useMcpOAuthCallback.js +1 -1
  6. package/dist/hooks/useMcpOAuthCallback.js.map +1 -1
  7. package/dist/primitives/addForm/McpAddFormAuthSelect.js +1 -1
  8. package/dist/primitives/addForm/McpAddFormCancel.js +1 -1
  9. package/dist/primitives/addForm/McpAddFormError.js +1 -1
  10. package/dist/primitives/addForm/McpAddFormNameField.js +1 -1
  11. package/dist/primitives/addForm/McpAddFormRoot.js +1 -1
  12. package/dist/primitives/addForm/McpAddFormRoot.js.map +1 -1
  13. package/dist/primitives/addForm/McpAddFormSubmit.js +1 -1
  14. package/dist/primitives/addForm/McpAddFormUrlField.js +1 -1
  15. package/dist/primitives/addForm/context.js +1 -1
  16. package/dist/primitives/manager/McpManagerAddCustomTrigger.js +1 -1
  17. package/dist/primitives/manager/McpManagerConnectors.js +1 -1
  18. package/dist/primitives/manager/McpManagerConnectors.js.map +1 -1
  19. package/dist/primitives/manager/McpManagerCustomServers.js +1 -1
  20. package/dist/primitives/manager/McpManagerCustomServers.js.map +1 -1
  21. package/dist/primitives/manager/McpManagerRoot.js +1 -1
  22. package/dist/primitives/server/McpServerConnectButton.js +1 -1
  23. package/dist/primitives/server/McpServerConnectButton.js.map +1 -1
  24. package/dist/primitives/server/McpServerDisconnectButton.js +1 -1
  25. package/dist/primitives/server/McpServerDisconnectButton.js.map +1 -1
  26. package/dist/primitives/server/McpServerError.js +1 -1
  27. package/dist/primitives/server/McpServerIcon.js +1 -1
  28. package/dist/primitives/server/McpServerName.js +1 -1
  29. package/dist/primitives/server/McpServerOAuthLink.js +1 -1
  30. package/dist/primitives/server/McpServerRemoveButton.js +1 -1
  31. package/dist/primitives/server/McpServerRemoveButton.js.map +1 -1
  32. package/dist/primitives/server/McpServerRoot.js +1 -1
  33. package/dist/primitives/server/McpServerStatus.js +1 -1
  34. package/dist/primitives/server/McpServerToolName.js +1 -1
  35. package/dist/primitives/server/McpServerTools.js +1 -1
  36. package/dist/resources/McpManagerResource.d.ts.map +1 -1
  37. package/dist/resources/McpManagerResource.js +20 -18
  38. package/dist/resources/McpManagerResource.js.map +1 -1
  39. package/dist/resources/McpServerResource.d.ts.map +1 -1
  40. package/dist/resources/McpServerResource.js +17 -16
  41. package/dist/resources/McpServerResource.js.map +1 -1
  42. package/dist/resources/storage/McpCustomStorage.js +3 -1
  43. package/dist/resources/storage/McpCustomStorage.js.map +1 -1
  44. package/dist/resources/storage/McpLocalStorage.js +1 -1
  45. package/dist/resources/storage/McpLocalStorage.js.map +1 -1
  46. package/dist/resources/storage/McpMemoryStorage.js +1 -1
  47. package/dist/resources/storage/McpMemoryStorage.js.map +1 -1
  48. package/package.json +9 -9
  49. package/src/resources/McpManagerResource.ts +196 -203
  50. package/src/resources/McpServerResource.ts +228 -239
  51. package/src/resources/storage/McpCustomStorage.ts +5 -3
  52. package/src/resources/storage/McpLocalStorage.ts +49 -49
  53. package/src/resources/storage/McpMemoryStorage.ts +19 -17
  54. package/src/resources/storage/types.ts +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"createOAuthProvider.js","names":[],"sources":["../../src/auth/createOAuthProvider.ts"],"sourcesContent":["import type { OAuthClientProvider } from \"@modelcontextprotocol/sdk/client/auth.js\";\nimport type {\n OAuthClientInformationFull,\n OAuthClientMetadata,\n OAuthTokens,\n} from \"@modelcontextprotocol/sdk/shared/auth.js\";\nimport type { MCPStorage } from \"../resources/storage/types\";\nimport type { MCPAuthConfig } from \"../mcp-scope\";\n\nconst STATE_PREFIX = \"aui-mcp:\";\n\nfunction bytesToBase64Url(bytes: Uint8Array): string {\n let s = \"\";\n for (const b of bytes) s += String.fromCharCode(b);\n return btoa(s).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\nfunction base64UrlToBytes(b64url: string): Uint8Array {\n const padded =\n b64url.replace(/-/g, \"+\").replace(/_/g, \"/\") +\n \"=\".repeat((4 - (b64url.length % 4)) % 4);\n const bin = atob(padded);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\nfunction encodeServerIdInState(serverId: string): string {\n const bytes = new TextEncoder().encode(serverId);\n return `${STATE_PREFIX}${bytesToBase64Url(bytes)}`;\n}\n\nexport function decodeServerIdFromState(state: string): string | null {\n if (!state.startsWith(STATE_PREFIX)) return null;\n const dot = state.indexOf(\".\", STATE_PREFIX.length);\n const encoded =\n dot === -1\n ? state.slice(STATE_PREFIX.length)\n : state.slice(STATE_PREFIX.length, dot);\n try {\n return new TextDecoder(\"utf-8\", { fatal: true }).decode(\n base64UrlToBytes(encoded),\n );\n } catch {\n return null;\n }\n}\n\nexport type CreateOAuthProviderOptions = {\n serverId: string;\n /** Must be `auth.type === \"oauth\"`. */\n config: Extract<MCPAuthConfig, { type: \"oauth\" }>;\n storage: MCPStorage;\n redirectUri: string;\n /** Called by the SDK to start the authorization redirect. */\n onAuthorizationUrl: (url: URL) => void;\n};\n\n/**\n * Builds an OAuthClientProvider for the MCP SDK, backed by MCPStorage.\n * Token refresh and DCR are handled by the SDK; this provider only mediates\n * load/save and the redirect step.\n */\nexport function createOAuthProvider(\n opts: CreateOAuthProviderOptions,\n): OAuthClientProvider {\n const { serverId, config, storage, redirectUri, onAuthorizationUrl } = opts;\n\n type Cache = {\n tokens?: OAuthTokens | undefined;\n clientInformation?: OAuthClientInformationFull | undefined;\n codeVerifier?: string | undefined;\n };\n let cached: Cache | null = null;\n\n const loadCache = async (): Promise<Cache> => {\n if (cached) return cached;\n const persisted = await storage.loadAuthState(serverId);\n const initial: Cache = {};\n if (persisted?.tokens) initial.tokens = persisted.tokens;\n if (config.clientId) {\n const ci: OAuthClientInformationFull = {\n client_id: config.clientId,\n redirect_uris: [redirectUri],\n };\n if (config.clientSecret) ci.client_secret = config.clientSecret;\n initial.clientInformation = ci;\n } else if (persisted?.clientInformation) {\n initial.clientInformation = persisted.clientInformation;\n }\n if (persisted?.codeVerifier) initial.codeVerifier = persisted.codeVerifier;\n cached = initial;\n return cached;\n };\n\n const persist = async () => {\n const c = cached;\n if (!c) return;\n const next: Parameters<typeof storage.saveAuthState>[1] = {};\n if (c.tokens) next.tokens = c.tokens;\n if (c.clientInformation) next.clientInformation = c.clientInformation;\n if (c.codeVerifier) next.codeVerifier = c.codeVerifier;\n await storage.saveAuthState(serverId, next);\n };\n\n const clientMetadata: OAuthClientMetadata = {\n client_name: \"assistant-ui\",\n redirect_uris: [redirectUri],\n grant_types: [\"authorization_code\", \"refresh_token\"],\n response_types: [\"code\"],\n token_endpoint_auth_method: \"none\",\n scope: config.scopes?.join(\" \"),\n };\n\n return {\n get redirectUrl() {\n return redirectUri;\n },\n get clientMetadata() {\n return clientMetadata;\n },\n state() {\n // Embed the server id so the callback handler can route it back to the\n // right MCPServerResource without app-level wiring.\n const nonce =\n typeof crypto !== \"undefined\" && \"randomUUID\" in crypto\n ? crypto.randomUUID()\n : `${Date.now()}.${Math.random()}`;\n return `${encodeServerIdInState(serverId)}.${nonce}`;\n },\n async clientInformation() {\n const c = await loadCache();\n return c.clientInformation;\n },\n async saveClientInformation(info) {\n const c = await loadCache();\n c.clientInformation = info as OAuthClientInformationFull;\n await persist();\n },\n async tokens() {\n const c = await loadCache();\n return c.tokens;\n },\n async saveTokens(tokens) {\n const c = await loadCache();\n c.tokens = tokens;\n await persist();\n },\n async redirectToAuthorization(url) {\n onAuthorizationUrl(url);\n },\n async saveCodeVerifier(codeVerifier) {\n const c = await loadCache();\n c.codeVerifier = codeVerifier;\n await persist();\n },\n async codeVerifier() {\n const c = await loadCache();\n if (!c.codeVerifier) {\n throw new Error(\"No code verifier saved for this OAuth flow\");\n }\n return c.codeVerifier;\n },\n async invalidateCredentials(scope) {\n const c = await loadCache();\n if (scope === \"all\" || scope === \"tokens\") delete c.tokens;\n if (scope === \"all\" || scope === \"client\") delete c.clientInformation;\n if (scope === \"all\" || scope === \"verifier\") delete c.codeVerifier;\n await persist();\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"createOAuthProvider.js","names":[],"sources":["../../src/auth/createOAuthProvider.ts"],"sourcesContent":["import type { OAuthClientProvider } from \"@modelcontextprotocol/sdk/client/auth.js\";\nimport type {\n OAuthClientInformationFull,\n OAuthClientMetadata,\n OAuthTokens,\n} from \"@modelcontextprotocol/sdk/shared/auth.js\";\nimport type { MCPStorage } from \"../resources/storage/types\";\nimport type { MCPAuthConfig } from \"../mcp-scope\";\n\nconst STATE_PREFIX = \"aui-mcp:\";\n\nfunction bytesToBase64Url(bytes: Uint8Array): string {\n let s = \"\";\n for (const b of bytes) s += String.fromCharCode(b);\n return btoa(s).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\nfunction base64UrlToBytes(b64url: string): Uint8Array {\n const padded =\n b64url.replace(/-/g, \"+\").replace(/_/g, \"/\") +\n \"=\".repeat((4 - (b64url.length % 4)) % 4);\n const bin = atob(padded);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\nfunction encodeServerIdInState(serverId: string): string {\n const bytes = new TextEncoder().encode(serverId);\n return `${STATE_PREFIX}${bytesToBase64Url(bytes)}`;\n}\n\nexport function decodeServerIdFromState(state: string): string | null {\n if (!state.startsWith(STATE_PREFIX)) return null;\n const dot = state.indexOf(\".\", STATE_PREFIX.length);\n const encoded =\n dot === -1\n ? state.slice(STATE_PREFIX.length)\n : state.slice(STATE_PREFIX.length, dot);\n try {\n return new TextDecoder(\"utf-8\", { fatal: true }).decode(\n base64UrlToBytes(encoded),\n );\n } catch {\n return null;\n }\n}\n\nexport type CreateOAuthProviderOptions = {\n serverId: string;\n /** Must be `auth.type === \"oauth\"`. */\n config: Extract<MCPAuthConfig, { type: \"oauth\" }>;\n storage: MCPStorage;\n redirectUri: string;\n /** Called by the SDK to start the authorization redirect. */\n onAuthorizationUrl: (url: URL) => void;\n};\n\n/**\n * Builds an OAuthClientProvider for the MCP SDK, backed by MCPStorage.\n * Token refresh and DCR are handled by the SDK; this provider only mediates\n * load/save and the redirect step.\n */\nexport function createOAuthProvider(\n opts: CreateOAuthProviderOptions,\n): OAuthClientProvider {\n const { serverId, config, storage, redirectUri, onAuthorizationUrl } = opts;\n\n type Cache = {\n tokens?: OAuthTokens | undefined;\n clientInformation?: OAuthClientInformationFull | undefined;\n codeVerifier?: string | undefined;\n };\n let cached: Cache | null = null;\n\n const loadCache = async (): Promise<Cache> => {\n if (cached) return cached;\n const persisted = await storage.loadAuthState(serverId);\n const initial: Cache = {};\n if (persisted?.tokens) initial.tokens = persisted.tokens;\n if (config.clientId) {\n const ci: OAuthClientInformationFull = {\n client_id: config.clientId,\n redirect_uris: [redirectUri],\n };\n if (config.clientSecret) ci.client_secret = config.clientSecret;\n initial.clientInformation = ci;\n } else if (persisted?.clientInformation) {\n initial.clientInformation = persisted.clientInformation;\n }\n if (persisted?.codeVerifier) initial.codeVerifier = persisted.codeVerifier;\n cached = initial;\n return cached;\n };\n\n const persist = async () => {\n const c = cached;\n if (!c) return;\n const next: Parameters<typeof storage.saveAuthState>[1] = {};\n if (c.tokens) next.tokens = c.tokens;\n if (c.clientInformation) next.clientInformation = c.clientInformation;\n if (c.codeVerifier) next.codeVerifier = c.codeVerifier;\n await storage.saveAuthState(serverId, next);\n };\n\n const clientMetadata: OAuthClientMetadata = {\n client_name: \"assistant-ui\",\n redirect_uris: [redirectUri],\n grant_types: [\"authorization_code\", \"refresh_token\"],\n response_types: [\"code\"],\n token_endpoint_auth_method: \"none\",\n scope: config.scopes?.join(\" \"),\n };\n\n return {\n get redirectUrl() {\n return redirectUri;\n },\n get clientMetadata() {\n return clientMetadata;\n },\n state() {\n // Embed the server id so the callback handler can route it back to the\n // right MCPServerResource without app-level wiring.\n const nonce =\n typeof crypto !== \"undefined\" && \"randomUUID\" in crypto\n ? crypto.randomUUID()\n : `${Date.now()}.${Math.random()}`;\n return `${encodeServerIdInState(serverId)}.${nonce}`;\n },\n async clientInformation() {\n const c = await loadCache();\n return c.clientInformation;\n },\n async saveClientInformation(info) {\n const c = await loadCache();\n c.clientInformation = info as OAuthClientInformationFull;\n await persist();\n },\n async tokens() {\n const c = await loadCache();\n return c.tokens;\n },\n async saveTokens(tokens) {\n const c = await loadCache();\n c.tokens = tokens;\n await persist();\n },\n async redirectToAuthorization(url) {\n onAuthorizationUrl(url);\n },\n async saveCodeVerifier(codeVerifier) {\n const c = await loadCache();\n c.codeVerifier = codeVerifier;\n await persist();\n },\n async codeVerifier() {\n const c = await loadCache();\n if (!c.codeVerifier) {\n throw new Error(\"No code verifier saved for this OAuth flow\");\n }\n return c.codeVerifier;\n },\n async invalidateCredentials(scope) {\n const c = await loadCache();\n if (scope === \"all\" || scope === \"tokens\") delete c.tokens;\n if (scope === \"all\" || scope === \"client\") delete c.clientInformation;\n if (scope === \"all\" || scope === \"verifier\") delete c.codeVerifier;\n await persist();\n },\n };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"McpConnectorByIndexProvider.js","names":[],"sources":["../../src/context/McpConnectorByIndexProvider.tsx"],"sourcesContent":["import type { FC, PropsWithChildren } from \"react\";\nimport { useAui, AuiProvider, Derived } from \"@assistant-ui/store\";\n\nexport const McpConnectorByIndexProvider: FC<\n PropsWithChildren<{ index: number }>\n> = ({ index, children }) => {\n const aui = useAui({\n mcpServer: Derived({\n source: \"mcp\",\n query: { kind: \"connector\", index },\n get: (parent) => parent.mcp().connector({ index }),\n }),\n });\n\n return <AuiProvider value={aui}>{children}</AuiProvider>;\n};\n"],"mappings":";;;AAGA,MAAa,+BAER,EAAE,OAAO,eAAe;CAS3B,OAAO,oBAAC,aAAD;EAAa,OARR,OAAO,EACjB,WAAW,QAAQ;GACjB,QAAQ;GACR,OAAO;IAAE,MAAM;IAAa;GAAM;GAClC,MAAM,WAAW,OAAO,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC;EACnD,CAAC,EACH,CAE6B;EAAI;CAAsB,CAAA;AACzD"}
1
+ {"version":3,"file":"McpConnectorByIndexProvider.js","names":[],"sources":["../../src/context/McpConnectorByIndexProvider.tsx"],"sourcesContent":["import type { FC, PropsWithChildren } from \"react\";\nimport { useAui, AuiProvider, Derived } from \"@assistant-ui/store\";\n\nexport const McpConnectorByIndexProvider: FC<\n PropsWithChildren<{ index: number }>\n> = ({ index, children }) => {\n const aui = useAui({\n mcpServer: Derived({\n source: \"mcp\",\n query: { kind: \"connector\", index },\n get: (parent) => parent.mcp().connector({ index }),\n }),\n });\n\n return <AuiProvider value={aui}>{children}</AuiProvider>;\n};\n"],"mappings":";;;AAGA,MAAa,+BAER,EAAE,OAAO,eAAe;CAS3B,OAAO,oBAAC,aAAD;EAAa,OARR,OAAO,EACjB,WAAW,QAAQ;GACjB,QAAQ;GACR,OAAO;IAAE,MAAM;IAAa;GAAM;GAClC,MAAM,WAAW,OAAO,IAAI,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC;EACnD,CAAC,EACH,CAE6B;EAAI;CAAsB,CAAA;AACzD"}
@@ -1 +1 @@
1
- {"version":3,"file":"McpCustomServerByIndexProvider.js","names":[],"sources":["../../src/context/McpCustomServerByIndexProvider.tsx"],"sourcesContent":["import type { FC, PropsWithChildren } from \"react\";\nimport { useAui, AuiProvider, Derived } from \"@assistant-ui/store\";\n\nexport const McpCustomServerByIndexProvider: FC<\n PropsWithChildren<{ index: number }>\n> = ({ index, children }) => {\n const aui = useAui({\n mcpServer: Derived({\n source: \"mcp\",\n query: { kind: \"custom\", index },\n get: (parent) => parent.mcp().customServer({ index }),\n }),\n });\n\n return <AuiProvider value={aui}>{children}</AuiProvider>;\n};\n"],"mappings":";;;AAGA,MAAa,kCAER,EAAE,OAAO,eAAe;CAS3B,OAAO,oBAAC,aAAD;EAAa,OARR,OAAO,EACjB,WAAW,QAAQ;GACjB,QAAQ;GACR,OAAO;IAAE,MAAM;IAAU;GAAM;GAC/B,MAAM,WAAW,OAAO,IAAI,EAAE,aAAa,EAAE,MAAM,CAAC;EACtD,CAAC,EACH,CAE6B;EAAI;CAAsB,CAAA;AACzD"}
1
+ {"version":3,"file":"McpCustomServerByIndexProvider.js","names":[],"sources":["../../src/context/McpCustomServerByIndexProvider.tsx"],"sourcesContent":["import type { FC, PropsWithChildren } from \"react\";\nimport { useAui, AuiProvider, Derived } from \"@assistant-ui/store\";\n\nexport const McpCustomServerByIndexProvider: FC<\n PropsWithChildren<{ index: number }>\n> = ({ index, children }) => {\n const aui = useAui({\n mcpServer: Derived({\n source: \"mcp\",\n query: { kind: \"custom\", index },\n get: (parent) => parent.mcp().customServer({ index }),\n }),\n });\n\n return <AuiProvider value={aui}>{children}</AuiProvider>;\n};\n"],"mappings":";;;AAGA,MAAa,kCAER,EAAE,OAAO,eAAe;CAS3B,OAAO,oBAAC,aAAD;EAAa,OARR,OAAO,EACjB,WAAW,QAAQ;GACjB,QAAQ;GACR,OAAO;IAAE,MAAM;IAAU;GAAM;GAC/B,MAAM,WAAW,OAAO,IAAI,CAAC,CAAC,aAAa,EAAE,MAAM,CAAC;EACtD,CAAC,EACH,CAE6B;EAAI;CAAsB,CAAA;AACzD"}
@@ -1 +1 @@
1
- {"version":3,"file":"McpServerByIdProvider.js","names":[],"sources":["../../src/context/McpServerByIdProvider.tsx"],"sourcesContent":["import type { FC, PropsWithChildren } from \"react\";\nimport { useAui, AuiProvider, Derived } from \"@assistant-ui/store\";\n\nexport const McpServerByIdProvider: FC<PropsWithChildren<{ id: string }>> = ({\n id,\n children,\n}) => {\n const aui = useAui({\n mcpServer: Derived({\n source: \"mcp\",\n query: { id },\n get: (parent) => parent.mcp().server({ id }),\n }),\n });\n\n return <AuiProvider value={aui}>{children}</AuiProvider>;\n};\n"],"mappings":";;;AAGA,MAAa,yBAAgE,EAC3E,IACA,eACI;CASJ,OAAO,oBAAC,aAAD;EAAa,OARR,OAAO,EACjB,WAAW,QAAQ;GACjB,QAAQ;GACR,OAAO,EAAE,GAAG;GACZ,MAAM,WAAW,OAAO,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC;EAC7C,CAAC,EACH,CAE6B;EAAI;CAAsB,CAAA;AACzD"}
1
+ {"version":3,"file":"McpServerByIdProvider.js","names":[],"sources":["../../src/context/McpServerByIdProvider.tsx"],"sourcesContent":["import type { FC, PropsWithChildren } from \"react\";\nimport { useAui, AuiProvider, Derived } from \"@assistant-ui/store\";\n\nexport const McpServerByIdProvider: FC<PropsWithChildren<{ id: string }>> = ({\n id,\n children,\n}) => {\n const aui = useAui({\n mcpServer: Derived({\n source: \"mcp\",\n query: { id },\n get: (parent) => parent.mcp().server({ id }),\n }),\n });\n\n return <AuiProvider value={aui}>{children}</AuiProvider>;\n};\n"],"mappings":";;;AAGA,MAAa,yBAAgE,EAC3E,IACA,eACI;CASJ,OAAO,oBAAC,aAAD;EAAa,OARR,OAAO,EACjB,WAAW,QAAQ;GACjB,QAAQ;GACR,OAAO,EAAE,GAAG;GACZ,MAAM,WAAW,OAAO,IAAI,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC;EAC7C,CAAC,EACH,CAE6B;EAAI;CAAsB,CAAA;AACzD"}
@@ -1,6 +1,6 @@
1
1
  import { decodeServerIdFromState } from "../auth/createOAuthProvider.js";
2
2
  import { useAui } from "@assistant-ui/store";
3
- import { useEffect, useRef, useState } from "react";
3
+ import { useEffect, useRef, useState } from "@assistant-ui/tap/react-shim";
4
4
  import { Fragment, jsx } from "react/jsx-runtime";
5
5
  //#region src/hooks/useMcpOAuthCallback.tsx
6
6
  function useMcpOAuthCallback(opts = {}) {
@@ -1 +1 @@
1
- {"version":3,"file":"useMcpOAuthCallback.js","names":[],"sources":["../../src/hooks/useMcpOAuthCallback.tsx"],"sourcesContent":["import { type FC, type ReactNode, useEffect, useRef, useState } from \"react\";\nimport { useAui } from \"@assistant-ui/store\";\nimport { decodeServerIdFromState } from \"../auth/createOAuthProvider\";\n\nexport type UseMcpOAuthCallbackOptions = {\n /** Defaults to `window.location.href`. */\n url?: string;\n onComplete?: (serverId: string) => void;\n onError?: (err: Error) => void;\n};\n\nexport type UseMcpOAuthCallbackResult = {\n status: \"idle\" | \"running\" | \"done\" | \"error\";\n serverId: string | null;\n error: Error | null;\n};\n\nexport function useMcpOAuthCallback(\n opts: UseMcpOAuthCallbackOptions = {},\n): UseMcpOAuthCallbackResult {\n const aui = useAui();\n const [result, setResult] = useState<UseMcpOAuthCallbackResult>({\n status: \"idle\",\n serverId: null,\n error: null,\n });\n // Guard against React 18 Strict Mode's mount-unmount-remount: the effect\n // body must not run completeAuth twice for the same URL, otherwise the\n // single-use OAuth code is double-redeemed and the second attempt 4xxs.\n const startedRef = useRef<string | null>(null);\n const optsRef = useRef(opts);\n optsRef.current = opts;\n\n useEffect(() => {\n const url =\n opts.url ?? (typeof window !== \"undefined\" ? window.location.href : null);\n if (!url) return;\n if (startedRef.current === url) return;\n startedRef.current = url;\n\n (async () => {\n try {\n const parsed = new URL(url);\n const state = parsed.searchParams.get(\"state\");\n const error = parsed.searchParams.get(\"error\");\n if (error) {\n throw new Error(\n parsed.searchParams.get(\"error_description\") ?? error,\n );\n }\n if (!state) throw new Error(\"missing state parameter in callback URL\");\n const serverId = decodeServerIdFromState(state);\n if (!serverId) {\n throw new Error(\"callback state does not match an MCP server\");\n }\n setResult({ status: \"running\", serverId, error: null });\n await aui.mcp().server({ id: serverId }).completeAuth(url);\n setResult({ status: \"done\", serverId, error: null });\n optsRef.current.onComplete?.(serverId);\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n setResult((prev) => ({ ...prev, status: \"error\", error: e }));\n optsRef.current.onError?.(e);\n }\n })();\n }, [aui, opts.url]);\n\n return result;\n}\n\nexport const McpOAuthCallback: FC<\n UseMcpOAuthCallbackOptions & {\n children?: (result: UseMcpOAuthCallbackResult) => ReactNode;\n }\n> = ({ children, ...opts }) => {\n const result = useMcpOAuthCallback(opts);\n if (children) return <>{children(result)}</>;\n return null;\n};\n"],"mappings":";;;;;AAiBA,SAAgB,oBACd,OAAmC,CAAC,GACT;CAC3B,MAAM,MAAM,OAAO;CACnB,MAAM,CAAC,QAAQ,aAAa,SAAoC;EAC9D,QAAQ;EACR,UAAU;EACV,OAAO;CACT,CAAC;CAID,MAAM,aAAa,OAAsB,IAAI;CAC7C,MAAM,UAAU,OAAO,IAAI;CAC3B,QAAQ,UAAU;CAElB,gBAAgB;EACd,MAAM,MACJ,KAAK,QAAQ,OAAO,WAAW,cAAc,OAAO,SAAS,OAAO;EACtE,IAAI,CAAC,KAAK;EACV,IAAI,WAAW,YAAY,KAAK;EAChC,WAAW,UAAU;EAErB,CAAC,YAAY;GACX,IAAI;IACF,MAAM,SAAS,IAAI,IAAI,GAAG;IAC1B,MAAM,QAAQ,OAAO,aAAa,IAAI,OAAO;IAC7C,MAAM,QAAQ,OAAO,aAAa,IAAI,OAAO;IAC7C,IAAI,OACF,MAAM,IAAI,MACR,OAAO,aAAa,IAAI,mBAAmB,KAAK,KAClD;IAEF,IAAI,CAAC,OAAO,MAAM,IAAI,MAAM,yCAAyC;IACrE,MAAM,WAAW,wBAAwB,KAAK;IAC9C,IAAI,CAAC,UACH,MAAM,IAAI,MAAM,6CAA6C;IAE/D,UAAU;KAAE,QAAQ;KAAW;KAAU,OAAO;IAAK,CAAC;IACtD,MAAM,IAAI,IAAI,EAAE,OAAO,EAAE,IAAI,SAAS,CAAC,EAAE,aAAa,GAAG;IACzD,UAAU;KAAE,QAAQ;KAAQ;KAAU,OAAO;IAAK,CAAC;IACnD,QAAQ,QAAQ,aAAa,QAAQ;GACvC,SAAS,KAAK;IACZ,MAAM,IAAI,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;IAC5D,WAAW,UAAU;KAAE,GAAG;KAAM,QAAQ;KAAS,OAAO;IAAE,EAAE;IAC5D,QAAQ,QAAQ,UAAU,CAAC;GAC7B;EACF,GAAG;CACL,GAAG,CAAC,KAAK,KAAK,GAAG,CAAC;CAElB,OAAO;AACT;AAEA,MAAa,oBAIR,EAAE,UAAU,GAAG,WAAW;CAC7B,MAAM,SAAS,oBAAoB,IAAI;CACvC,IAAI,UAAU,OAAO,oBAAA,UAAA,EAAA,UAAG,SAAS,MAAM,EAAI,CAAA;CAC3C,OAAO;AACT"}
1
+ {"version":3,"file":"useMcpOAuthCallback.js","names":[],"sources":["../../src/hooks/useMcpOAuthCallback.tsx"],"sourcesContent":["import { type FC, type ReactNode, useEffect, useRef, useState } from \"react\";\nimport { useAui } from \"@assistant-ui/store\";\nimport { decodeServerIdFromState } from \"../auth/createOAuthProvider\";\n\nexport type UseMcpOAuthCallbackOptions = {\n /** Defaults to `window.location.href`. */\n url?: string;\n onComplete?: (serverId: string) => void;\n onError?: (err: Error) => void;\n};\n\nexport type UseMcpOAuthCallbackResult = {\n status: \"idle\" | \"running\" | \"done\" | \"error\";\n serverId: string | null;\n error: Error | null;\n};\n\nexport function useMcpOAuthCallback(\n opts: UseMcpOAuthCallbackOptions = {},\n): UseMcpOAuthCallbackResult {\n const aui = useAui();\n const [result, setResult] = useState<UseMcpOAuthCallbackResult>({\n status: \"idle\",\n serverId: null,\n error: null,\n });\n // Guard against React 18 Strict Mode's mount-unmount-remount: the effect\n // body must not run completeAuth twice for the same URL, otherwise the\n // single-use OAuth code is double-redeemed and the second attempt 4xxs.\n const startedRef = useRef<string | null>(null);\n const optsRef = useRef(opts);\n optsRef.current = opts;\n\n useEffect(() => {\n const url =\n opts.url ?? (typeof window !== \"undefined\" ? window.location.href : null);\n if (!url) return;\n if (startedRef.current === url) return;\n startedRef.current = url;\n\n (async () => {\n try {\n const parsed = new URL(url);\n const state = parsed.searchParams.get(\"state\");\n const error = parsed.searchParams.get(\"error\");\n if (error) {\n throw new Error(\n parsed.searchParams.get(\"error_description\") ?? error,\n );\n }\n if (!state) throw new Error(\"missing state parameter in callback URL\");\n const serverId = decodeServerIdFromState(state);\n if (!serverId) {\n throw new Error(\"callback state does not match an MCP server\");\n }\n setResult({ status: \"running\", serverId, error: null });\n await aui.mcp().server({ id: serverId }).completeAuth(url);\n setResult({ status: \"done\", serverId, error: null });\n optsRef.current.onComplete?.(serverId);\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n setResult((prev) => ({ ...prev, status: \"error\", error: e }));\n optsRef.current.onError?.(e);\n }\n })();\n }, [aui, opts.url]);\n\n return result;\n}\n\nexport const McpOAuthCallback: FC<\n UseMcpOAuthCallbackOptions & {\n children?: (result: UseMcpOAuthCallbackResult) => ReactNode;\n }\n> = ({ children, ...opts }) => {\n const result = useMcpOAuthCallback(opts);\n if (children) return <>{children(result)}</>;\n return null;\n};\n"],"mappings":";;;;;AAiBA,SAAgB,oBACd,OAAmC,CAAC,GACT;CAC3B,MAAM,MAAM,OAAO;CACnB,MAAM,CAAC,QAAQ,aAAa,SAAoC;EAC9D,QAAQ;EACR,UAAU;EACV,OAAO;CACT,CAAC;CAID,MAAM,aAAa,OAAsB,IAAI;CAC7C,MAAM,UAAU,OAAO,IAAI;CAC3B,QAAQ,UAAU;CAElB,gBAAgB;EACd,MAAM,MACJ,KAAK,QAAQ,OAAO,WAAW,cAAc,OAAO,SAAS,OAAO;EACtE,IAAI,CAAC,KAAK;EACV,IAAI,WAAW,YAAY,KAAK;EAChC,WAAW,UAAU;EAErB,CAAC,YAAY;GACX,IAAI;IACF,MAAM,SAAS,IAAI,IAAI,GAAG;IAC1B,MAAM,QAAQ,OAAO,aAAa,IAAI,OAAO;IAC7C,MAAM,QAAQ,OAAO,aAAa,IAAI,OAAO;IAC7C,IAAI,OACF,MAAM,IAAI,MACR,OAAO,aAAa,IAAI,mBAAmB,KAAK,KAClD;IAEF,IAAI,CAAC,OAAO,MAAM,IAAI,MAAM,yCAAyC;IACrE,MAAM,WAAW,wBAAwB,KAAK;IAC9C,IAAI,CAAC,UACH,MAAM,IAAI,MAAM,6CAA6C;IAE/D,UAAU;KAAE,QAAQ;KAAW;KAAU,OAAO;IAAK,CAAC;IACtD,MAAM,IAAI,IAAI,CAAC,CAAC,OAAO,EAAE,IAAI,SAAS,CAAC,CAAC,CAAC,aAAa,GAAG;IACzD,UAAU;KAAE,QAAQ;KAAQ;KAAU,OAAO;IAAK,CAAC;IACnD,QAAQ,QAAQ,aAAa,QAAQ;GACvC,SAAS,KAAK;IACZ,MAAM,IAAI,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;IAC5D,WAAW,UAAU;KAAE,GAAG;KAAM,QAAQ;KAAS,OAAO;IAAE,EAAE;IAC5D,QAAQ,QAAQ,UAAU,CAAC;GAC7B;EACF,EAAA,CAAG;CACL,GAAG,CAAC,KAAK,KAAK,GAAG,CAAC;CAElB,OAAO;AACT;AAEA,MAAa,oBAIR,EAAE,UAAU,GAAG,WAAW;CAC7B,MAAM,SAAS,oBAAoB,IAAI;CACvC,IAAI,UAAU,OAAO,oBAAA,UAAA,EAAA,UAAG,SAAS,MAAM,EAAI,CAAA;CAC3C,OAAO;AACT"}
@@ -1,5 +1,5 @@
1
1
  import { useAddForm } from "./context.js";
2
- import { forwardRef } from "react";
2
+ import { forwardRef } from "@assistant-ui/tap/react-shim";
3
3
  import { Primitive } from "@radix-ui/react-primitive";
4
4
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
5
  //#region src/primitives/addForm/McpAddFormAuthSelect.tsx
@@ -1,5 +1,5 @@
1
1
  import { useAddForm } from "./context.js";
2
- import { forwardRef } from "react";
2
+ import { forwardRef } from "@assistant-ui/tap/react-shim";
3
3
  import { Primitive } from "@radix-ui/react-primitive";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  //#region src/primitives/addForm/McpAddFormCancel.tsx
@@ -1,5 +1,5 @@
1
1
  import { useAddForm } from "./context.js";
2
- import { forwardRef } from "react";
2
+ import { forwardRef } from "@assistant-ui/tap/react-shim";
3
3
  import { Primitive } from "@radix-ui/react-primitive";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  //#region src/primitives/addForm/McpAddFormError.tsx
@@ -1,5 +1,5 @@
1
1
  import { useAddForm } from "./context.js";
2
- import { forwardRef } from "react";
2
+ import { forwardRef } from "@assistant-ui/tap/react-shim";
3
3
  import { Primitive } from "@radix-ui/react-primitive";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  //#region src/primitives/addForm/McpAddFormNameField.tsx
@@ -1,6 +1,6 @@
1
1
  import { AddFormContext } from "./context.js";
2
2
  import { useAui } from "@assistant-ui/store";
3
- import { forwardRef, useCallback, useMemo, useState } from "react";
3
+ import { forwardRef, useCallback, useMemo, useState } from "@assistant-ui/tap/react-shim";
4
4
  import { Primitive } from "@radix-ui/react-primitive";
5
5
  import { jsx } from "react/jsx-runtime";
6
6
  //#region src/primitives/addForm/McpAddFormRoot.tsx
@@ -1 +1 @@
1
- {"version":3,"file":"McpAddFormRoot.js","names":[],"sources":["../../../src/primitives/addForm/McpAddFormRoot.tsx"],"sourcesContent":["import {\n type ComponentPropsWithoutRef,\n type ComponentRef,\n type FormEventHandler,\n forwardRef,\n useCallback,\n useMemo,\n useState,\n} from \"react\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport { useAui } from \"@assistant-ui/store\";\nimport { AddFormContext, type AddFormState } from \"./context\";\nimport type { MCPAuthConfig } from \"../../mcp-scope\";\n\nconst INITIAL: AddFormState = {\n name: \"\",\n url: \"\",\n authType: \"oauth\",\n bearerToken: \"\",\n scopes: \"\",\n submitting: false,\n error: null,\n};\n\nfunction validateUrl(raw: string): { url: string } | { error: string } {\n const trimmed = raw.trim();\n if (!trimmed) return { error: \"URL is required\" };\n let parsed: URL;\n try {\n parsed = new URL(trimmed);\n } catch {\n return { error: \"Invalid URL\" };\n }\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n return { error: \"URL must be http(s)\" };\n }\n return { url: trimmed };\n}\n\nexport namespace McpAddFormPrimitiveRoot {\n export type Element = ComponentRef<typeof Primitive.form>;\n export type Props = Omit<\n ComponentPropsWithoutRef<typeof Primitive.form>,\n \"onSubmit\"\n > & {\n onSubmitted?: (id: string) => void;\n onCancel?: () => void;\n };\n}\n\nexport const McpAddFormPrimitiveRoot = forwardRef<\n McpAddFormPrimitiveRoot.Element,\n McpAddFormPrimitiveRoot.Props\n>(({ onSubmitted, onCancel, ...props }, ref) => {\n const aui = useAui();\n const [state, setState] = useState<AddFormState>(INITIAL);\n\n const setField = useCallback(\n <K extends keyof AddFormState>(key: K, value: AddFormState[K]) => {\n setState((prev) => ({ ...prev, [key]: value }));\n },\n [],\n );\n\n const reset = useCallback(() => setState(INITIAL), []);\n\n const buildAuth = useCallback((): MCPAuthConfig => {\n switch (state.authType) {\n case \"none\":\n return { type: \"none\" };\n case \"bearer\":\n return { type: \"bearer\", token: state.bearerToken || undefined };\n case \"oauth\": {\n const scopeList = state.scopes\n .split(/[\\s,]+/)\n .map((s) => s.trim())\n .filter(Boolean);\n return {\n type: \"oauth\",\n scopes: scopeList.length > 0 ? scopeList : undefined,\n };\n }\n }\n }, [state.authType, state.bearerToken, state.scopes]);\n\n const submit = useCallback(async () => {\n if (state.submitting) return;\n if (!state.name.trim()) {\n setState((p) => ({ ...p, error: \"Name is required\" }));\n return;\n }\n if (state.authType === \"bearer\" && !state.bearerToken.trim()) {\n setState((p) => ({ ...p, error: \"Bearer token is required\" }));\n return;\n }\n const urlResult = validateUrl(state.url);\n if (\"error\" in urlResult) {\n setState((p) => ({ ...p, error: urlResult.error }));\n return;\n }\n setState((p) => ({ ...p, submitting: true, error: null }));\n try {\n const id = await aui.mcp().addCustomServer({\n name: state.name.trim(),\n url: urlResult.url,\n auth: buildAuth(),\n });\n setState(INITIAL);\n onSubmitted?.(id);\n } catch (err) {\n setState((p) => ({\n ...p,\n submitting: false,\n error: err instanceof Error ? err.message : String(err),\n }));\n }\n }, [aui, buildAuth, onSubmitted, state]);\n\n const cancel = useCallback(() => {\n setState(INITIAL);\n onCancel?.();\n }, [onCancel]);\n\n const value = useMemo(\n () => ({ state, setField, reset, submit, cancel }),\n [state, setField, reset, submit, cancel],\n );\n\n const onFormSubmit: FormEventHandler<HTMLFormElement> = (e) => {\n e.preventDefault();\n void submit();\n };\n\n return (\n <AddFormContext.Provider value={value}>\n <Primitive.form {...props} ref={ref} onSubmit={onFormSubmit} />\n </AddFormContext.Provider>\n );\n});\n\nMcpAddFormPrimitiveRoot.displayName = \"McpAddFormPrimitive.Root\";\n"],"mappings":"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"}
1
+ {"version":3,"file":"McpAddFormRoot.js","names":[],"sources":["../../../src/primitives/addForm/McpAddFormRoot.tsx"],"sourcesContent":["import {\n type ComponentPropsWithoutRef,\n type ComponentRef,\n type FormEventHandler,\n forwardRef,\n useCallback,\n useMemo,\n useState,\n} from \"react\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport { useAui } from \"@assistant-ui/store\";\nimport { AddFormContext, type AddFormState } from \"./context\";\nimport type { MCPAuthConfig } from \"../../mcp-scope\";\n\nconst INITIAL: AddFormState = {\n name: \"\",\n url: \"\",\n authType: \"oauth\",\n bearerToken: \"\",\n scopes: \"\",\n submitting: false,\n error: null,\n};\n\nfunction validateUrl(raw: string): { url: string } | { error: string } {\n const trimmed = raw.trim();\n if (!trimmed) return { error: \"URL is required\" };\n let parsed: URL;\n try {\n parsed = new URL(trimmed);\n } catch {\n return { error: \"Invalid URL\" };\n }\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n return { error: \"URL must be http(s)\" };\n }\n return { url: trimmed };\n}\n\nexport namespace McpAddFormPrimitiveRoot {\n export type Element = ComponentRef<typeof Primitive.form>;\n export type Props = Omit<\n ComponentPropsWithoutRef<typeof Primitive.form>,\n \"onSubmit\"\n > & {\n onSubmitted?: (id: string) => void;\n onCancel?: () => void;\n };\n}\n\nexport const McpAddFormPrimitiveRoot = forwardRef<\n McpAddFormPrimitiveRoot.Element,\n McpAddFormPrimitiveRoot.Props\n>(({ onSubmitted, onCancel, ...props }, ref) => {\n const aui = useAui();\n const [state, setState] = useState<AddFormState>(INITIAL);\n\n const setField = useCallback(\n <K extends keyof AddFormState>(key: K, value: AddFormState[K]) => {\n setState((prev) => ({ ...prev, [key]: value }));\n },\n [],\n );\n\n const reset = useCallback(() => setState(INITIAL), []);\n\n const buildAuth = useCallback((): MCPAuthConfig => {\n switch (state.authType) {\n case \"none\":\n return { type: \"none\" };\n case \"bearer\":\n return { type: \"bearer\", token: state.bearerToken || undefined };\n case \"oauth\": {\n const scopeList = state.scopes\n .split(/[\\s,]+/)\n .map((s) => s.trim())\n .filter(Boolean);\n return {\n type: \"oauth\",\n scopes: scopeList.length > 0 ? scopeList : undefined,\n };\n }\n }\n }, [state.authType, state.bearerToken, state.scopes]);\n\n const submit = useCallback(async () => {\n if (state.submitting) return;\n if (!state.name.trim()) {\n setState((p) => ({ ...p, error: \"Name is required\" }));\n return;\n }\n if (state.authType === \"bearer\" && !state.bearerToken.trim()) {\n setState((p) => ({ ...p, error: \"Bearer token is required\" }));\n return;\n }\n const urlResult = validateUrl(state.url);\n if (\"error\" in urlResult) {\n setState((p) => ({ ...p, error: urlResult.error }));\n return;\n }\n setState((p) => ({ ...p, submitting: true, error: null }));\n try {\n const id = await aui.mcp().addCustomServer({\n name: state.name.trim(),\n url: urlResult.url,\n auth: buildAuth(),\n });\n setState(INITIAL);\n onSubmitted?.(id);\n } catch (err) {\n setState((p) => ({\n ...p,\n submitting: false,\n error: err instanceof Error ? err.message : String(err),\n }));\n }\n }, [aui, buildAuth, onSubmitted, state]);\n\n const cancel = useCallback(() => {\n setState(INITIAL);\n onCancel?.();\n }, [onCancel]);\n\n const value = useMemo(\n () => ({ state, setField, reset, submit, cancel }),\n [state, setField, reset, submit, cancel],\n );\n\n const onFormSubmit: FormEventHandler<HTMLFormElement> = (e) => {\n e.preventDefault();\n void submit();\n };\n\n return (\n <AddFormContext.Provider value={value}>\n <Primitive.form {...props} ref={ref} onSubmit={onFormSubmit} />\n </AddFormContext.Provider>\n );\n});\n\nMcpAddFormPrimitiveRoot.displayName = \"McpAddFormPrimitive.Root\";\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { useAddForm } from "./context.js";
2
- import { forwardRef } from "react";
2
+ import { forwardRef } from "@assistant-ui/tap/react-shim";
3
3
  import { Primitive } from "@radix-ui/react-primitive";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  //#region src/primitives/addForm/McpAddFormSubmit.tsx
@@ -1,5 +1,5 @@
1
1
  import { useAddForm } from "./context.js";
2
- import { forwardRef } from "react";
2
+ import { forwardRef } from "@assistant-ui/tap/react-shim";
3
3
  import { Primitive } from "@radix-ui/react-primitive";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  //#region src/primitives/addForm/McpAddFormUrlField.tsx
@@ -1,4 +1,4 @@
1
- import { createContext, useContext } from "react";
1
+ import { createContext, useContext } from "@assistant-ui/tap/react-shim";
2
2
  //#region src/primitives/addForm/context.tsx
3
3
  const AddFormContext = createContext(null);
4
4
  const useAddForm = () => {
@@ -1,4 +1,4 @@
1
- import { forwardRef } from "react";
1
+ import { forwardRef } from "@assistant-ui/tap/react-shim";
2
2
  import { Primitive } from "@radix-ui/react-primitive";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  //#region src/primitives/manager/McpManagerAddCustomTrigger.tsx
@@ -1,6 +1,6 @@
1
1
  import { McpConnectorByIndexProvider } from "../../context/McpConnectorByIndexProvider.js";
2
2
  import { RenderChildrenWithAccessor, useAuiState } from "@assistant-ui/store";
3
- import { memo, useMemo } from "react";
3
+ import { memo, useMemo } from "@assistant-ui/tap/react-shim";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  //#region src/primitives/manager/McpManagerConnectors.tsx
6
6
  const SEP = "";
@@ -1 +1 @@
1
- {"version":3,"file":"McpManagerConnectors.js","names":[],"sources":["../../../src/primitives/manager/McpManagerConnectors.tsx"],"sourcesContent":["import { type FC, type ReactNode, memo, useMemo } from \"react\";\nimport { RenderChildrenWithAccessor, useAuiState } from \"@assistant-ui/store\";\nimport { McpConnectorByIndexProvider } from \"../../context/McpConnectorByIndexProvider\";\nimport type { MCPServerState } from \"../../mcp-scope\";\n\n// ASCII Unit Separator — never appears in MCP connector ids (uuids, urls,\n// app-provided strings).\nconst SEP = \"\\x1f\";\n\nexport namespace McpManagerPrimitiveConnectors {\n export type Props = {\n /**\n * Render function called once per connector. Receives a lazy `server`\n * accessor — reading it inside the render function subscribes to that\n * connector's state.\n */\n children: (value: { server: MCPServerState }) => ReactNode;\n };\n}\n\nconst McpManagerPrimitiveConnectorsInner: FC<{\n children: (value: { server: MCPServerState }) => ReactNode;\n}> = ({ children }) => {\n // Subscribe to the connector id list, joined to a primitive so identity\n // is stable when the list hasn't changed. Re-renders on add/remove/reorder\n // but not on per-item state changes.\n const idsJoined = useAuiState((s) =>\n s.mcp.connectors.map((c) => c.id).join(SEP),\n );\n const ids = useMemo(\n () => (idsJoined ? idsJoined.split(SEP) : []),\n [idsJoined],\n );\n\n return useMemo(() => {\n if (ids.length === 0) return null;\n return ids.map((id, index) => (\n <McpConnectorByIndexProvider key={id} index={index}>\n <RenderChildrenWithAccessor\n getItemState={(aui) => aui.mcp().connector({ index }).getState()}\n >\n {(getItem) =>\n children({\n get server() {\n return getItem();\n },\n })\n }\n </RenderChildrenWithAccessor>\n </McpConnectorByIndexProvider>\n ));\n }, [ids, children]);\n};\n\n/**\n * Renders all connectors declared on `McpManagerResource`.\n *\n * @example\n * ```tsx\n * <McpManagerPrimitive.Connectors>\n * {({ server }) => (\n * <McpServerPrimitive.Root>\n * <McpServerPrimitive.Name />\n * {server.connectionState === \"error\" && <p>{server.lastError?.message}</p>}\n * </McpServerPrimitive.Root>\n * )}\n * </McpManagerPrimitive.Connectors>\n * ```\n */\nexport const McpManagerPrimitiveConnectors: FC<McpManagerPrimitiveConnectors.Props> =\n memo(\n McpManagerPrimitiveConnectorsInner,\n (prev, next) => prev.children === next.children,\n );\n\nMcpManagerPrimitiveConnectors.displayName = \"McpManagerPrimitive.Connectors\";\n"],"mappings":";;;;;AAOA,MAAM,MAAM;AAaZ,MAAM,sCAEA,EAAE,eAAe;CAIrB,MAAM,YAAY,aAAa,MAC7B,EAAE,IAAI,WAAW,KAAK,MAAM,EAAE,EAAE,EAAE,KAAK,GAAG,CAC5C;CACA,MAAM,MAAM,cACH,YAAY,UAAU,MAAM,GAAG,IAAI,CAAC,GAC3C,CAAC,SAAS,CACZ;CAEA,OAAO,cAAc;EACnB,IAAI,IAAI,WAAW,GAAG,OAAO;EAC7B,OAAO,IAAI,KAAK,IAAI,UAClB,oBAAC,6BAAD;GAA6C;aAC3C,oBAAC,4BAAD;IACE,eAAe,QAAQ,IAAI,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,SAAS;eAE7D,YACA,SAAS,EACP,IAAI,SAAS;KACX,OAAO,QAAQ;IACjB,EACF,CAAC;GAEuB,CAAA;EACD,GAZK,EAYL,CAC9B;CACH,GAAG,CAAC,KAAK,QAAQ,CAAC;AACpB;;;;;;;;;;;;;;;;AAiBA,MAAa,gCACX,KACE,qCACC,MAAM,SAAS,KAAK,aAAa,KAAK,QACzC;AAEF,8BAA8B,cAAc"}
1
+ {"version":3,"file":"McpManagerConnectors.js","names":[],"sources":["../../../src/primitives/manager/McpManagerConnectors.tsx"],"sourcesContent":["import { type FC, type ReactNode, memo, useMemo } from \"react\";\nimport { RenderChildrenWithAccessor, useAuiState } from \"@assistant-ui/store\";\nimport { McpConnectorByIndexProvider } from \"../../context/McpConnectorByIndexProvider\";\nimport type { MCPServerState } from \"../../mcp-scope\";\n\n// ASCII Unit Separator — never appears in MCP connector ids (uuids, urls,\n// app-provided strings).\nconst SEP = \"\\x1f\";\n\nexport namespace McpManagerPrimitiveConnectors {\n export type Props = {\n /**\n * Render function called once per connector. Receives a lazy `server`\n * accessor — reading it inside the render function subscribes to that\n * connector's state.\n */\n children: (value: { server: MCPServerState }) => ReactNode;\n };\n}\n\nconst McpManagerPrimitiveConnectorsInner: FC<{\n children: (value: { server: MCPServerState }) => ReactNode;\n}> = ({ children }) => {\n // Subscribe to the connector id list, joined to a primitive so identity\n // is stable when the list hasn't changed. Re-renders on add/remove/reorder\n // but not on per-item state changes.\n const idsJoined = useAuiState((s) =>\n s.mcp.connectors.map((c) => c.id).join(SEP),\n );\n const ids = useMemo(\n () => (idsJoined ? idsJoined.split(SEP) : []),\n [idsJoined],\n );\n\n return useMemo(() => {\n if (ids.length === 0) return null;\n return ids.map((id, index) => (\n <McpConnectorByIndexProvider key={id} index={index}>\n <RenderChildrenWithAccessor\n getItemState={(aui) => aui.mcp().connector({ index }).getState()}\n >\n {(getItem) =>\n children({\n get server() {\n return getItem();\n },\n })\n }\n </RenderChildrenWithAccessor>\n </McpConnectorByIndexProvider>\n ));\n }, [ids, children]);\n};\n\n/**\n * Renders all connectors declared on `McpManagerResource`.\n *\n * @example\n * ```tsx\n * <McpManagerPrimitive.Connectors>\n * {({ server }) => (\n * <McpServerPrimitive.Root>\n * <McpServerPrimitive.Name />\n * {server.connectionState === \"error\" && <p>{server.lastError?.message}</p>}\n * </McpServerPrimitive.Root>\n * )}\n * </McpManagerPrimitive.Connectors>\n * ```\n */\nexport const McpManagerPrimitiveConnectors: FC<McpManagerPrimitiveConnectors.Props> =\n memo(\n McpManagerPrimitiveConnectorsInner,\n (prev, next) => prev.children === next.children,\n );\n\nMcpManagerPrimitiveConnectors.displayName = \"McpManagerPrimitive.Connectors\";\n"],"mappings":";;;;;AAOA,MAAM,MAAM;AAaZ,MAAM,sCAEA,EAAE,eAAe;CAIrB,MAAM,YAAY,aAAa,MAC7B,EAAE,IAAI,WAAW,KAAK,MAAM,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,CAC5C;CACA,MAAM,MAAM,cACH,YAAY,UAAU,MAAM,GAAG,IAAI,CAAC,GAC3C,CAAC,SAAS,CACZ;CAEA,OAAO,cAAc;EACnB,IAAI,IAAI,WAAW,GAAG,OAAO;EAC7B,OAAO,IAAI,KAAK,IAAI,UAClB,oBAAC,6BAAD;GAA6C;aAC3C,oBAAC,4BAAD;IACE,eAAe,QAAQ,IAAI,IAAI,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS;eAE7D,YACA,SAAS,EACP,IAAI,SAAS;KACX,OAAO,QAAQ;IACjB,EACF,CAAC;GAEuB,CAAA;EACD,GAZK,EAYL,CAC9B;CACH,GAAG,CAAC,KAAK,QAAQ,CAAC;AACpB;;;;;;;;;;;;;;;;AAiBA,MAAa,gCACX,KACE,qCACC,MAAM,SAAS,KAAK,aAAa,KAAK,QACzC;AAEF,8BAA8B,cAAc"}
@@ -1,6 +1,6 @@
1
1
  import { McpCustomServerByIndexProvider } from "../../context/McpCustomServerByIndexProvider.js";
2
2
  import { RenderChildrenWithAccessor, useAuiState } from "@assistant-ui/store";
3
- import { memo, useMemo } from "react";
3
+ import { memo, useMemo } from "@assistant-ui/tap/react-shim";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  //#region src/primitives/manager/McpManagerCustomServers.tsx
6
6
  const SEP = "";
@@ -1 +1 @@
1
- {"version":3,"file":"McpManagerCustomServers.js","names":[],"sources":["../../../src/primitives/manager/McpManagerCustomServers.tsx"],"sourcesContent":["import { type FC, type ReactNode, memo, useMemo } from \"react\";\nimport { RenderChildrenWithAccessor, useAuiState } from \"@assistant-ui/store\";\nimport { McpCustomServerByIndexProvider } from \"../../context/McpCustomServerByIndexProvider\";\nimport type { MCPServerState } from \"../../mcp-scope\";\n\nconst SEP = \"\\x1f\";\n\nexport namespace McpManagerPrimitiveCustomServers {\n export type Props = {\n /**\n * Render function called once per custom server. Receives a lazy\n * `server` accessor — reading it inside the render function subscribes\n * to that server's state.\n */\n children: (value: { server: MCPServerState }) => ReactNode;\n };\n}\n\nconst McpManagerPrimitiveCustomServersInner: FC<{\n children: (value: { server: MCPServerState }) => ReactNode;\n}> = ({ children }) => {\n const idsJoined = useAuiState((s) =>\n s.mcp.customServers.map((c) => c.id).join(SEP),\n );\n const ids = useMemo(\n () => (idsJoined ? idsJoined.split(SEP) : []),\n [idsJoined],\n );\n\n return useMemo(() => {\n if (ids.length === 0) return null;\n return ids.map((id, index) => (\n <McpCustomServerByIndexProvider key={id} index={index}>\n <RenderChildrenWithAccessor\n getItemState={(aui) => aui.mcp().customServer({ index }).getState()}\n >\n {(getItem) =>\n children({\n get server() {\n return getItem();\n },\n })\n }\n </RenderChildrenWithAccessor>\n </McpCustomServerByIndexProvider>\n ));\n }, [ids, children]);\n};\n\n/**\n * Renders all user-added custom servers persisted in storage.\n *\n * @example\n * ```tsx\n * <McpManagerPrimitive.CustomServers>\n * {() => (\n * <McpServerPrimitive.Root>\n * <McpServerPrimitive.Name />\n * <McpServerPrimitive.RemoveButton>Remove</McpServerPrimitive.RemoveButton>\n * </McpServerPrimitive.Root>\n * )}\n * </McpManagerPrimitive.CustomServers>\n * ```\n */\nexport const McpManagerPrimitiveCustomServers: FC<McpManagerPrimitiveCustomServers.Props> =\n memo(\n McpManagerPrimitiveCustomServersInner,\n (prev, next) => prev.children === next.children,\n );\n\nMcpManagerPrimitiveCustomServers.displayName =\n \"McpManagerPrimitive.CustomServers\";\n"],"mappings":";;;;;AAKA,MAAM,MAAM;AAaZ,MAAM,yCAEA,EAAE,eAAe;CACrB,MAAM,YAAY,aAAa,MAC7B,EAAE,IAAI,cAAc,KAAK,MAAM,EAAE,EAAE,EAAE,KAAK,GAAG,CAC/C;CACA,MAAM,MAAM,cACH,YAAY,UAAU,MAAM,GAAG,IAAI,CAAC,GAC3C,CAAC,SAAS,CACZ;CAEA,OAAO,cAAc;EACnB,IAAI,IAAI,WAAW,GAAG,OAAO;EAC7B,OAAO,IAAI,KAAK,IAAI,UAClB,oBAAC,gCAAD;GAAgD;aAC9C,oBAAC,4BAAD;IACE,eAAe,QAAQ,IAAI,IAAI,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,SAAS;eAEhE,YACA,SAAS,EACP,IAAI,SAAS;KACX,OAAO,QAAQ;IACjB,EACF,CAAC;GAEuB,CAAA;EACE,GAZK,EAYL,CACjC;CACH,GAAG,CAAC,KAAK,QAAQ,CAAC;AACpB;;;;;;;;;;;;;;;;AAiBA,MAAa,mCACX,KACE,wCACC,MAAM,SAAS,KAAK,aAAa,KAAK,QACzC;AAEF,iCAAiC,cAC/B"}
1
+ {"version":3,"file":"McpManagerCustomServers.js","names":[],"sources":["../../../src/primitives/manager/McpManagerCustomServers.tsx"],"sourcesContent":["import { type FC, type ReactNode, memo, useMemo } from \"react\";\nimport { RenderChildrenWithAccessor, useAuiState } from \"@assistant-ui/store\";\nimport { McpCustomServerByIndexProvider } from \"../../context/McpCustomServerByIndexProvider\";\nimport type { MCPServerState } from \"../../mcp-scope\";\n\nconst SEP = \"\\x1f\";\n\nexport namespace McpManagerPrimitiveCustomServers {\n export type Props = {\n /**\n * Render function called once per custom server. Receives a lazy\n * `server` accessor — reading it inside the render function subscribes\n * to that server's state.\n */\n children: (value: { server: MCPServerState }) => ReactNode;\n };\n}\n\nconst McpManagerPrimitiveCustomServersInner: FC<{\n children: (value: { server: MCPServerState }) => ReactNode;\n}> = ({ children }) => {\n const idsJoined = useAuiState((s) =>\n s.mcp.customServers.map((c) => c.id).join(SEP),\n );\n const ids = useMemo(\n () => (idsJoined ? idsJoined.split(SEP) : []),\n [idsJoined],\n );\n\n return useMemo(() => {\n if (ids.length === 0) return null;\n return ids.map((id, index) => (\n <McpCustomServerByIndexProvider key={id} index={index}>\n <RenderChildrenWithAccessor\n getItemState={(aui) => aui.mcp().customServer({ index }).getState()}\n >\n {(getItem) =>\n children({\n get server() {\n return getItem();\n },\n })\n }\n </RenderChildrenWithAccessor>\n </McpCustomServerByIndexProvider>\n ));\n }, [ids, children]);\n};\n\n/**\n * Renders all user-added custom servers persisted in storage.\n *\n * @example\n * ```tsx\n * <McpManagerPrimitive.CustomServers>\n * {() => (\n * <McpServerPrimitive.Root>\n * <McpServerPrimitive.Name />\n * <McpServerPrimitive.RemoveButton>Remove</McpServerPrimitive.RemoveButton>\n * </McpServerPrimitive.Root>\n * )}\n * </McpManagerPrimitive.CustomServers>\n * ```\n */\nexport const McpManagerPrimitiveCustomServers: FC<McpManagerPrimitiveCustomServers.Props> =\n memo(\n McpManagerPrimitiveCustomServersInner,\n (prev, next) => prev.children === next.children,\n );\n\nMcpManagerPrimitiveCustomServers.displayName =\n \"McpManagerPrimitive.CustomServers\";\n"],"mappings":";;;;;AAKA,MAAM,MAAM;AAaZ,MAAM,yCAEA,EAAE,eAAe;CACrB,MAAM,YAAY,aAAa,MAC7B,EAAE,IAAI,cAAc,KAAK,MAAM,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,CAC/C;CACA,MAAM,MAAM,cACH,YAAY,UAAU,MAAM,GAAG,IAAI,CAAC,GAC3C,CAAC,SAAS,CACZ;CAEA,OAAO,cAAc;EACnB,IAAI,IAAI,WAAW,GAAG,OAAO;EAC7B,OAAO,IAAI,KAAK,IAAI,UAClB,oBAAC,gCAAD;GAAgD;aAC9C,oBAAC,4BAAD;IACE,eAAe,QAAQ,IAAI,IAAI,CAAC,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS;eAEhE,YACA,SAAS,EACP,IAAI,SAAS;KACX,OAAO,QAAQ;IACjB,EACF,CAAC;GAEuB,CAAA;EACE,GAZK,EAYL,CACjC;CACH,GAAG,CAAC,KAAK,QAAQ,CAAC;AACpB;;;;;;;;;;;;;;;;AAiBA,MAAa,mCACX,KACE,wCACC,MAAM,SAAS,KAAK,aAAa,KAAK,QACzC;AAEF,iCAAiC,cAC/B"}
@@ -1,5 +1,5 @@
1
1
  import { useAuiState } from "@assistant-ui/store";
2
- import { forwardRef } from "react";
2
+ import { forwardRef } from "@assistant-ui/tap/react-shim";
3
3
  import { Primitive } from "@radix-ui/react-primitive";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  //#region src/primitives/manager/McpManagerRoot.tsx
@@ -1,5 +1,5 @@
1
1
  import { useAui, useAuiState } from "@assistant-ui/store";
2
- import { forwardRef } from "react";
2
+ import { forwardRef } from "@assistant-ui/tap/react-shim";
3
3
  import { Primitive } from "@radix-ui/react-primitive";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  //#region src/primitives/server/McpServerConnectButton.tsx
@@ -1 +1 @@
1
- {"version":3,"file":"McpServerConnectButton.js","names":[],"sources":["../../../src/primitives/server/McpServerConnectButton.tsx"],"sourcesContent":["import {\n type ComponentPropsWithoutRef,\n type ComponentRef,\n forwardRef,\n} from \"react\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport { useAui, useAuiState } from \"@assistant-ui/store\";\n\nexport namespace McpServerPrimitiveConnectButton {\n export type Element = ComponentRef<typeof Primitive.button>;\n export type Props = ComponentPropsWithoutRef<typeof Primitive.button>;\n}\n\nconst CONNECTABLE = new Set([\"disconnected\", \"error\", \"authRequired\"]);\n\nexport const McpServerPrimitiveConnectButton = forwardRef<\n McpServerPrimitiveConnectButton.Element,\n McpServerPrimitiveConnectButton.Props\n>((props, ref) => {\n const state = useAuiState((s) => s.mcpServer.connectionState);\n const aui = useAui();\n if (!CONNECTABLE.has(state)) return null;\n return (\n <Primitive.button\n {...props}\n type=\"button\"\n ref={ref}\n data-state-hint={state === \"authRequired\" ? \"auth-required\" : undefined}\n onClick={(e) => {\n props.onClick?.(e);\n if (e.defaultPrevented) return;\n void aui.mcpServer().connect();\n }}\n />\n );\n});\n\nMcpServerPrimitiveConnectButton.displayName =\n \"McpServerPrimitive.ConnectButton\";\n"],"mappings":";;;;;AAaA,MAAM,cAAc,IAAI,IAAI;CAAC;CAAgB;CAAS;AAAc,CAAC;AAErE,MAAa,kCAAkC,YAG5C,OAAO,QAAQ;CAChB,MAAM,QAAQ,aAAa,MAAM,EAAE,UAAU,eAAe;CAC5D,MAAM,MAAM,OAAO;CACnB,IAAI,CAAC,YAAY,IAAI,KAAK,GAAG,OAAO;CACpC,OACE,oBAAC,UAAU,QAAX;EACE,GAAI;EACJ,MAAK;EACA;EACL,mBAAiB,UAAU,iBAAiB,kBAAkB,KAAA;EAC9D,UAAU,MAAM;GACd,MAAM,UAAU,CAAC;GACjB,IAAI,EAAE,kBAAkB;GACxB,IAAS,UAAU,EAAE,QAAQ;EAC/B;CACD,CAAA;AAEL,CAAC;AAED,gCAAgC,cAC9B"}
1
+ {"version":3,"file":"McpServerConnectButton.js","names":[],"sources":["../../../src/primitives/server/McpServerConnectButton.tsx"],"sourcesContent":["import {\n type ComponentPropsWithoutRef,\n type ComponentRef,\n forwardRef,\n} from \"react\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport { useAui, useAuiState } from \"@assistant-ui/store\";\n\nexport namespace McpServerPrimitiveConnectButton {\n export type Element = ComponentRef<typeof Primitive.button>;\n export type Props = ComponentPropsWithoutRef<typeof Primitive.button>;\n}\n\nconst CONNECTABLE = new Set([\"disconnected\", \"error\", \"authRequired\"]);\n\nexport const McpServerPrimitiveConnectButton = forwardRef<\n McpServerPrimitiveConnectButton.Element,\n McpServerPrimitiveConnectButton.Props\n>((props, ref) => {\n const state = useAuiState((s) => s.mcpServer.connectionState);\n const aui = useAui();\n if (!CONNECTABLE.has(state)) return null;\n return (\n <Primitive.button\n {...props}\n type=\"button\"\n ref={ref}\n data-state-hint={state === \"authRequired\" ? \"auth-required\" : undefined}\n onClick={(e) => {\n props.onClick?.(e);\n if (e.defaultPrevented) return;\n void aui.mcpServer().connect();\n }}\n />\n );\n});\n\nMcpServerPrimitiveConnectButton.displayName =\n \"McpServerPrimitive.ConnectButton\";\n"],"mappings":";;;;;AAaA,MAAM,cAAc,IAAI,IAAI;CAAC;CAAgB;CAAS;AAAc,CAAC;AAErE,MAAa,kCAAkC,YAG5C,OAAO,QAAQ;CAChB,MAAM,QAAQ,aAAa,MAAM,EAAE,UAAU,eAAe;CAC5D,MAAM,MAAM,OAAO;CACnB,IAAI,CAAC,YAAY,IAAI,KAAK,GAAG,OAAO;CACpC,OACE,oBAAC,UAAU,QAAX;EACE,GAAI;EACJ,MAAK;EACA;EACL,mBAAiB,UAAU,iBAAiB,kBAAkB,KAAA;EAC9D,UAAU,MAAM;GACd,MAAM,UAAU,CAAC;GACjB,IAAI,EAAE,kBAAkB;GACxB,IAAS,UAAU,CAAC,CAAC,QAAQ;EAC/B;CACD,CAAA;AAEL,CAAC;AAED,gCAAgC,cAC9B"}
@@ -1,5 +1,5 @@
1
1
  import { useAui, useAuiState } from "@assistant-ui/store";
2
- import { forwardRef } from "react";
2
+ import { forwardRef } from "@assistant-ui/tap/react-shim";
3
3
  import { Primitive } from "@radix-ui/react-primitive";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  //#region src/primitives/server/McpServerDisconnectButton.tsx
@@ -1 +1 @@
1
- {"version":3,"file":"McpServerDisconnectButton.js","names":[],"sources":["../../../src/primitives/server/McpServerDisconnectButton.tsx"],"sourcesContent":["import {\n type ComponentPropsWithoutRef,\n type ComponentRef,\n forwardRef,\n} from \"react\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport { useAui, useAuiState } from \"@assistant-ui/store\";\n\nexport namespace McpServerPrimitiveDisconnectButton {\n export type Element = ComponentRef<typeof Primitive.button>;\n export type Props = ComponentPropsWithoutRef<typeof Primitive.button>;\n}\n\nconst DISCONNECTABLE = new Set([\"connected\", \"connecting\", \"authPending\"]);\n\nexport const McpServerPrimitiveDisconnectButton = forwardRef<\n McpServerPrimitiveDisconnectButton.Element,\n McpServerPrimitiveDisconnectButton.Props\n>((props, ref) => {\n const state = useAuiState((s) => s.mcpServer.connectionState);\n const aui = useAui();\n if (!DISCONNECTABLE.has(state)) return null;\n return (\n <Primitive.button\n {...props}\n type=\"button\"\n ref={ref}\n onClick={(e) => {\n props.onClick?.(e);\n if (e.defaultPrevented) return;\n void aui.mcpServer().disconnect();\n }}\n />\n );\n});\n\nMcpServerPrimitiveDisconnectButton.displayName =\n \"McpServerPrimitive.DisconnectButton\";\n"],"mappings":";;;;;AAaA,MAAM,iBAAiB,IAAI,IAAI;CAAC;CAAa;CAAc;AAAa,CAAC;AAEzE,MAAa,qCAAqC,YAG/C,OAAO,QAAQ;CAChB,MAAM,QAAQ,aAAa,MAAM,EAAE,UAAU,eAAe;CAC5D,MAAM,MAAM,OAAO;CACnB,IAAI,CAAC,eAAe,IAAI,KAAK,GAAG,OAAO;CACvC,OACE,oBAAC,UAAU,QAAX;EACE,GAAI;EACJ,MAAK;EACA;EACL,UAAU,MAAM;GACd,MAAM,UAAU,CAAC;GACjB,IAAI,EAAE,kBAAkB;GACxB,IAAS,UAAU,EAAE,WAAW;EAClC;CACD,CAAA;AAEL,CAAC;AAED,mCAAmC,cACjC"}
1
+ {"version":3,"file":"McpServerDisconnectButton.js","names":[],"sources":["../../../src/primitives/server/McpServerDisconnectButton.tsx"],"sourcesContent":["import {\n type ComponentPropsWithoutRef,\n type ComponentRef,\n forwardRef,\n} from \"react\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport { useAui, useAuiState } from \"@assistant-ui/store\";\n\nexport namespace McpServerPrimitiveDisconnectButton {\n export type Element = ComponentRef<typeof Primitive.button>;\n export type Props = ComponentPropsWithoutRef<typeof Primitive.button>;\n}\n\nconst DISCONNECTABLE = new Set([\"connected\", \"connecting\", \"authPending\"]);\n\nexport const McpServerPrimitiveDisconnectButton = forwardRef<\n McpServerPrimitiveDisconnectButton.Element,\n McpServerPrimitiveDisconnectButton.Props\n>((props, ref) => {\n const state = useAuiState((s) => s.mcpServer.connectionState);\n const aui = useAui();\n if (!DISCONNECTABLE.has(state)) return null;\n return (\n <Primitive.button\n {...props}\n type=\"button\"\n ref={ref}\n onClick={(e) => {\n props.onClick?.(e);\n if (e.defaultPrevented) return;\n void aui.mcpServer().disconnect();\n }}\n />\n );\n});\n\nMcpServerPrimitiveDisconnectButton.displayName =\n \"McpServerPrimitive.DisconnectButton\";\n"],"mappings":";;;;;AAaA,MAAM,iBAAiB,IAAI,IAAI;CAAC;CAAa;CAAc;AAAa,CAAC;AAEzE,MAAa,qCAAqC,YAG/C,OAAO,QAAQ;CAChB,MAAM,QAAQ,aAAa,MAAM,EAAE,UAAU,eAAe;CAC5D,MAAM,MAAM,OAAO;CACnB,IAAI,CAAC,eAAe,IAAI,KAAK,GAAG,OAAO;CACvC,OACE,oBAAC,UAAU,QAAX;EACE,GAAI;EACJ,MAAK;EACA;EACL,UAAU,MAAM;GACd,MAAM,UAAU,CAAC;GACjB,IAAI,EAAE,kBAAkB;GACxB,IAAS,UAAU,CAAC,CAAC,WAAW;EAClC;CACD,CAAA;AAEL,CAAC;AAED,mCAAmC,cACjC"}
@@ -1,5 +1,5 @@
1
1
  import { useAuiState } from "@assistant-ui/store";
2
- import { forwardRef } from "react";
2
+ import { forwardRef } from "@assistant-ui/tap/react-shim";
3
3
  import { Primitive } from "@radix-ui/react-primitive";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  //#region src/primitives/server/McpServerError.tsx
@@ -1,5 +1,5 @@
1
1
  import { useAuiState } from "@assistant-ui/store";
2
- import { forwardRef } from "react";
2
+ import { forwardRef } from "@assistant-ui/tap/react-shim";
3
3
  import { Primitive } from "@radix-ui/react-primitive";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  //#region src/primitives/server/McpServerIcon.tsx
@@ -1,5 +1,5 @@
1
1
  import { useAuiState } from "@assistant-ui/store";
2
- import { forwardRef } from "react";
2
+ import { forwardRef } from "@assistant-ui/tap/react-shim";
3
3
  import { Primitive } from "@radix-ui/react-primitive";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  //#region src/primitives/server/McpServerName.tsx
@@ -1,5 +1,5 @@
1
1
  import { useAuiState } from "@assistant-ui/store";
2
- import { forwardRef } from "react";
2
+ import { forwardRef } from "@assistant-ui/tap/react-shim";
3
3
  import { Primitive } from "@radix-ui/react-primitive";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  //#region src/primitives/server/McpServerOAuthLink.tsx
@@ -1,5 +1,5 @@
1
1
  import { useAui, useAuiState } from "@assistant-ui/store";
2
- import { forwardRef } from "react";
2
+ import { forwardRef } from "@assistant-ui/tap/react-shim";
3
3
  import { Primitive } from "@radix-ui/react-primitive";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  //#region src/primitives/server/McpServerRemoveButton.tsx
@@ -1 +1 @@
1
- {"version":3,"file":"McpServerRemoveButton.js","names":[],"sources":["../../../src/primitives/server/McpServerRemoveButton.tsx"],"sourcesContent":["import {\n type ComponentPropsWithoutRef,\n type ComponentRef,\n forwardRef,\n} from \"react\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport { useAui, useAuiState } from \"@assistant-ui/store\";\n\nexport namespace McpServerPrimitiveRemoveButton {\n export type Element = ComponentRef<typeof Primitive.button>;\n export type Props = ComponentPropsWithoutRef<typeof Primitive.button>;\n}\n\nexport const McpServerPrimitiveRemoveButton = forwardRef<\n McpServerPrimitiveRemoveButton.Element,\n McpServerPrimitiveRemoveButton.Props\n>((props, ref) => {\n const kind = useAuiState((s) => s.mcpServer.kind);\n const aui = useAui();\n if (kind !== \"custom\") return null;\n return (\n <Primitive.button\n {...props}\n type=\"button\"\n ref={ref}\n onClick={(e) => {\n props.onClick?.(e);\n if (e.defaultPrevented) return;\n void aui.mcpServer().remove();\n }}\n />\n );\n});\n\nMcpServerPrimitiveRemoveButton.displayName = \"McpServerPrimitive.RemoveButton\";\n"],"mappings":";;;;;AAaA,MAAa,iCAAiC,YAG3C,OAAO,QAAQ;CAChB,MAAM,OAAO,aAAa,MAAM,EAAE,UAAU,IAAI;CAChD,MAAM,MAAM,OAAO;CACnB,IAAI,SAAS,UAAU,OAAO;CAC9B,OACE,oBAAC,UAAU,QAAX;EACE,GAAI;EACJ,MAAK;EACA;EACL,UAAU,MAAM;GACd,MAAM,UAAU,CAAC;GACjB,IAAI,EAAE,kBAAkB;GACxB,IAAS,UAAU,EAAE,OAAO;EAC9B;CACD,CAAA;AAEL,CAAC;AAED,+BAA+B,cAAc"}
1
+ {"version":3,"file":"McpServerRemoveButton.js","names":[],"sources":["../../../src/primitives/server/McpServerRemoveButton.tsx"],"sourcesContent":["import {\n type ComponentPropsWithoutRef,\n type ComponentRef,\n forwardRef,\n} from \"react\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport { useAui, useAuiState } from \"@assistant-ui/store\";\n\nexport namespace McpServerPrimitiveRemoveButton {\n export type Element = ComponentRef<typeof Primitive.button>;\n export type Props = ComponentPropsWithoutRef<typeof Primitive.button>;\n}\n\nexport const McpServerPrimitiveRemoveButton = forwardRef<\n McpServerPrimitiveRemoveButton.Element,\n McpServerPrimitiveRemoveButton.Props\n>((props, ref) => {\n const kind = useAuiState((s) => s.mcpServer.kind);\n const aui = useAui();\n if (kind !== \"custom\") return null;\n return (\n <Primitive.button\n {...props}\n type=\"button\"\n ref={ref}\n onClick={(e) => {\n props.onClick?.(e);\n if (e.defaultPrevented) return;\n void aui.mcpServer().remove();\n }}\n />\n );\n});\n\nMcpServerPrimitiveRemoveButton.displayName = \"McpServerPrimitive.RemoveButton\";\n"],"mappings":";;;;;AAaA,MAAa,iCAAiC,YAG3C,OAAO,QAAQ;CAChB,MAAM,OAAO,aAAa,MAAM,EAAE,UAAU,IAAI;CAChD,MAAM,MAAM,OAAO;CACnB,IAAI,SAAS,UAAU,OAAO;CAC9B,OACE,oBAAC,UAAU,QAAX;EACE,GAAI;EACJ,MAAK;EACA;EACL,UAAU,MAAM;GACd,MAAM,UAAU,CAAC;GACjB,IAAI,EAAE,kBAAkB;GACxB,IAAS,UAAU,CAAC,CAAC,OAAO;EAC9B;CACD,CAAA;AAEL,CAAC;AAED,+BAA+B,cAAc"}
@@ -1,5 +1,5 @@
1
1
  import { useAuiState } from "@assistant-ui/store";
2
- import { forwardRef } from "react";
2
+ import { forwardRef } from "@assistant-ui/tap/react-shim";
3
3
  import { Primitive } from "@radix-ui/react-primitive";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  //#region src/primitives/server/McpServerRoot.tsx
@@ -1,5 +1,5 @@
1
1
  import { useAuiState } from "@assistant-ui/store";
2
- import { forwardRef } from "react";
2
+ import { forwardRef } from "@assistant-ui/tap/react-shim";
3
3
  import { Primitive } from "@radix-ui/react-primitive";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  //#region src/primitives/server/McpServerStatus.tsx
@@ -1,5 +1,5 @@
1
1
  import { useMcpServerTool } from "./McpServerTools.js";
2
- import { forwardRef } from "react";
2
+ import { forwardRef } from "@assistant-ui/tap/react-shim";
3
3
  import { Primitive } from "@radix-ui/react-primitive";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  //#region src/primitives/server/McpServerToolName.tsx
@@ -1,5 +1,5 @@
1
1
  import { useAuiState } from "@assistant-ui/store";
2
- import { createContext, useContext } from "react";
2
+ import { createContext, useContext } from "@assistant-ui/tap/react-shim";
3
3
  import { Fragment, jsx } from "react/jsx-runtime";
4
4
  //#region src/primitives/server/McpServerTools.tsx
5
5
  const ToolContext = createContext(null);
@@ -1 +1 @@
1
- {"version":3,"file":"McpManagerResource.d.ts","names":[],"sources":["../../src/resources/McpManagerResource.ts"],"mappings":";;;;;KA4BY,uBAAA;EACV,UAAA,GAAa,YAAA;EACb,OAAA,GAAU,iBAAiB,cAFM;EAIjC,gBAAA,uBAF2B;EAI3B,WAAA;AAAA;AAAA,cAQW,kBAAA,GAAkB,KAAA,EAAA,uBAAA,iCAAA,eAAA,CAAA,YAAA,SAAA,uBAAA"}
1
+ {"version":3,"file":"McpManagerResource.d.ts","names":[],"sources":["../../src/resources/McpManagerResource.ts"],"mappings":";;;;;KAoBY,uBAAA;EACV,UAAA,GAAa,YAAA;EACb,OAAA,GAAU,iBAAiB,cAFM;EAIjC,gBAAA,uBAF2B;EAI3B,WAAA;AAAA;AAAA,cAYW,kBAAA,GAAkB,KAAA,EAAA,uBAAA,iCAAA,eAAA,CAAA,YAAA,SAAA,uBAAA"}
@@ -1,22 +1,24 @@
1
1
  import { McpServerResource } from "./McpServerResource.js";
2
2
  import { McpLocalStorage } from "./storage/McpLocalStorage.js";
3
- import { attachTransformScopes, tapAssistantClientRef, tapClientLookup } from "@assistant-ui/store";
4
- import { resource, tapEffect, tapEffectEvent, tapMemo, tapRef, tapResource, tapState, withKey } from "@assistant-ui/tap";
3
+ import { attachTransformScopes, useAssistantClientRef, useClientLookup } from "@assistant-ui/store";
4
+ import { useEffect, useEffectEvent, useMemo, useRef, useState } from "@assistant-ui/tap/react-shim";
5
+ import { resource, useResource, withKey } from "@assistant-ui/tap";
5
6
  import { ModelContext } from "@assistant-ui/core/store";
6
7
  //#region src/resources/McpManagerResource.ts
7
8
  function defaultRedirectUri() {
8
9
  if (typeof window === "undefined") return "";
9
10
  return `${window.location.origin}/mcp/callback`;
10
11
  }
11
- const McpManagerResource = resource((props) => {
12
- const connectors = props.connectors ?? [];
12
+ const NO_CONNECTORS = [];
13
+ const McpManagerResource = resource(function McpManagerResource(props) {
14
+ const connectors = props.connectors ?? NO_CONNECTORS;
13
15
  const autoConnect = props.autoConnect ?? true;
14
16
  const redirectUri = props.oauthRedirectUri ?? defaultRedirectUri();
15
- const storage = tapResource(props.storage ?? McpLocalStorage());
16
- const [customServers, setCustomServers] = tapState([]);
17
- const [isHydrated, setIsHydrated] = tapState(false);
18
- const hydratedRef = tapRef(false);
19
- const hydrate = tapEffectEvent(async (signal) => {
17
+ const storage = useResource(props.storage ?? McpLocalStorage());
18
+ const [customServers, setCustomServers] = useState([]);
19
+ const [isHydrated, setIsHydrated] = useState(false);
20
+ const hydratedRef = useRef(false);
21
+ const hydrate = useEffectEvent(async (signal) => {
20
22
  try {
21
23
  const records = await storage.loadCustomServers();
22
24
  if (signal.cancelled) return;
@@ -32,21 +34,21 @@ const McpManagerResource = resource((props) => {
32
34
  }
33
35
  }
34
36
  });
35
- tapEffect(() => {
37
+ useEffect(() => {
36
38
  const signal = { cancelled: false };
37
39
  hydrate(signal);
38
40
  return () => {
39
41
  signal.cancelled = true;
40
42
  };
41
43
  }, []);
42
- const persistCustomServers = tapEffectEvent(async (records) => {
44
+ const persistCustomServers = useEffectEvent(async (records) => {
43
45
  if (!hydratedRef.current) return;
44
46
  await storage.saveCustomServers(records);
45
47
  });
46
- tapEffect(() => {
48
+ useEffect(() => {
47
49
  persistCustomServers(customServers);
48
50
  }, [customServers]);
49
- const serverElements = tapMemo(() => {
51
+ const serverElements = useMemo(() => {
50
52
  const connectorElements = connectors.map((c) => withKey(c.id, McpServerResource({
51
53
  id: c.id,
52
54
  kind: "connector",
@@ -80,8 +82,8 @@ const McpManagerResource = resource((props) => {
80
82
  redirectUri,
81
83
  autoConnect
82
84
  ]);
83
- const lookup = tapClientLookup(() => serverElements, [serverElements]);
84
- const state = tapMemo(() => {
85
+ const lookup = useClientLookup(() => serverElements, [serverElements]);
86
+ const state = useMemo(() => {
85
87
  const all = lookup.state;
86
88
  return {
87
89
  servers: all,
@@ -90,7 +92,7 @@ const McpManagerResource = resource((props) => {
90
92
  isHydrated
91
93
  };
92
94
  }, [lookup.state, isHydrated]);
93
- const toolkit = tapMemo(() => {
95
+ const toolkit = useMemo(() => {
94
96
  const out = {};
95
97
  for (const server of state.servers) {
96
98
  if (server.connectionState !== "connected") continue;
@@ -106,8 +108,8 @@ const McpManagerResource = resource((props) => {
106
108
  }
107
109
  return out;
108
110
  }, [state, lookup]);
109
- const clientRef = tapAssistantClientRef();
110
- tapEffect(() => {
111
+ const clientRef = useAssistantClientRef();
112
+ useEffect(() => {
111
113
  const client = clientRef.current;
112
114
  if (!client) return;
113
115
  return client.modelContext().register({ getModelContext: () => ({ tools: toolkit }) });
@@ -1 +1 @@
1
- {"version":3,"file":"McpManagerResource.js","names":[],"sources":["../../src/resources/McpManagerResource.ts"],"sourcesContent":["import {\n resource,\n tapState,\n tapResource,\n tapEffect,\n tapMemo,\n tapEffectEvent,\n tapRef,\n withKey,\n} from \"@assistant-ui/tap\";\nimport {\n tapClientLookup,\n tapAssistantClientRef,\n attachTransformScopes,\n type ClientOutput,\n} from \"@assistant-ui/store\";\nimport { ModelContext } from \"@assistant-ui/core/store\";\nimport type { Tool } from \"assistant-stream\";\nimport { McpServerResource } from \"./McpServerResource\";\nimport { McpLocalStorage } from \"./storage/McpLocalStorage\";\nimport type { MCPStorageElement } from \"./storage/types\";\nimport type {\n MCPAuthConfig,\n MCPConnector,\n MCPCustomServerRecord,\n MCPManagerState,\n} from \"../mcp-scope\";\n\nexport type McpManagerResourceProps = {\n connectors?: MCPConnector[] | undefined;\n storage?: MCPStorageElement | undefined;\n /** OAuth redirect target. Defaults to `${origin}/mcp/callback`. */\n oauthRedirectUri?: string | undefined;\n /** Connect on mount when usable auth exists. Default true. */\n autoConnect?: boolean | undefined;\n};\n\nfunction defaultRedirectUri(): string {\n if (typeof window === \"undefined\") return \"\";\n return `${window.location.origin}/mcp/callback`;\n}\n\nexport const McpManagerResource = resource(\n (props: McpManagerResourceProps): ClientOutput<\"mcp\"> => {\n const connectors = props.connectors ?? [];\n const autoConnect = props.autoConnect ?? true;\n const redirectUri = props.oauthRedirectUri ?? defaultRedirectUri();\n\n const storageElement = props.storage ?? McpLocalStorage();\n const storage = tapResource(storageElement);\n\n const [customServers, setCustomServers] = tapState<MCPCustomServerRecord[]>(\n [],\n );\n const [isHydrated, setIsHydrated] = tapState(false);\n\n const hydratedRef = tapRef(false);\n\n const hydrate = tapEffectEvent(async (signal: { cancelled: boolean }) => {\n try {\n const records = await storage.loadCustomServers();\n if (signal.cancelled) return;\n // Merge rather than replace so any addCustomServer calls that\n // happened before hydration resolved aren't silently overwritten.\n // Persisted order wins; pre-hydration locals append.\n setCustomServers((prev) => {\n if (prev.length === 0) return records;\n const persistedIds = new Set(records.map((r) => r.id));\n return [...records, ...prev.filter((r) => !persistedIds.has(r.id))];\n });\n } finally {\n if (!signal.cancelled) {\n hydratedRef.current = true;\n setIsHydrated(true);\n }\n }\n });\n\n tapEffect(() => {\n const signal = { cancelled: false };\n void hydrate(signal);\n return () => {\n signal.cancelled = true;\n };\n }, []);\n\n const persistCustomServers = tapEffectEvent(\n async (records: MCPCustomServerRecord[]) => {\n if (!hydratedRef.current) return;\n await storage.saveCustomServers(records);\n },\n );\n\n tapEffect(() => {\n void persistCustomServers(customServers);\n }, [customServers]);\n\n const serverElements = tapMemo(() => {\n const connectorElements = connectors.map((c) =>\n withKey(\n c.id,\n McpServerResource({\n id: c.id,\n kind: \"connector\",\n name: c.name,\n url: c.url,\n icon: c.icon,\n auth: c.auth,\n storage,\n redirectUri,\n autoConnect,\n onRemove: async () => {\n // connectors cannot be removed\n },\n }),\n ),\n );\n const customElements = customServers.map((s) =>\n withKey(\n s.id,\n McpServerResource({\n id: s.id,\n kind: \"custom\",\n name: s.name,\n url: s.url,\n auth: s.auth,\n storage,\n redirectUri,\n autoConnect,\n onRemove: async () => {\n setCustomServers((prev) => prev.filter((x) => x.id !== s.id));\n },\n }),\n ),\n );\n return [...connectorElements, ...customElements];\n }, [connectors, customServers, storage, redirectUri, autoConnect]);\n\n const lookup = tapClientLookup(() => serverElements, [serverElements]);\n\n const state = tapMemo<MCPManagerState>(() => {\n const all = lookup.state;\n return {\n servers: all,\n connectors: all.filter((s) => s.kind === \"connector\"),\n customServers: all.filter((s) => s.kind === \"custom\"),\n isHydrated,\n };\n }, [lookup.state, isHydrated]);\n\n // ─── Auto-register MCP tools as frontend tools in modelContext ─────\n // Build the toolkit from connected servers; re-register when the visible\n // tool surface changes. Tool names are prefixed with the server id to\n // avoid collisions across connected servers — connector ids must not\n // contain `__` (enforced by `defineConnector`); `addCustomServer`\n // generates UUIDs that satisfy the constraint by construction.\n const toolkit = tapMemo<Record<string, Tool<any, any>>>(() => {\n const out: Record<string, Tool<any, any>> = {};\n for (const server of state.servers) {\n if (server.connectionState !== \"connected\") continue;\n for (const tool of server.tools) {\n const fullName = `${server.id}__${tool.name}`;\n out[fullName] = {\n type: \"frontend\",\n ...(tool.description !== undefined\n ? { description: tool.description }\n : {}),\n parameters: tool.inputSchema as never,\n execute: (args) =>\n lookup\n .get({ key: server.id })\n .callTool(tool.name, args as unknown),\n };\n }\n }\n return out;\n }, [state, lookup]);\n\n const clientRef = tapAssistantClientRef();\n\n tapEffect(() => {\n const client = clientRef.current;\n if (!client) return;\n return client.modelContext().register({\n getModelContext: () => ({ tools: toolkit }),\n });\n }, [toolkit, clientRef]);\n\n const serverByKind = (kind: \"connector\" | \"custom\", index: number) => {\n const list =\n kind === \"connector\" ? state.connectors : state.customServers;\n const entry = list[index];\n if (!entry) {\n throw new Error(\n `McpManagerResource: no ${kind} at index ${index} (length ${list.length})`,\n );\n }\n return lookup.get({ key: entry.id });\n };\n\n return {\n getState: () => state,\n server: (query) => {\n if (\"id\" in query) return lookup.get({ key: query.id });\n return serverByKind(query.kind, query.index);\n },\n connector: ({ index }) => serverByKind(\"connector\", index),\n customServer: ({ index }) => serverByKind(\"custom\", index),\n addCustomServer: async ({ name, url, auth }) => {\n const record: MCPCustomServerRecord = {\n id:\n typeof crypto !== \"undefined\" && \"randomUUID\" in crypto\n ? crypto.randomUUID()\n : `mcp-${Date.now()}-${Math.random().toString(36).slice(2)}`,\n name,\n url,\n auth: auth as MCPAuthConfig,\n createdAt: Date.now(),\n };\n setCustomServers((prev) => [...prev, record]);\n return record.id;\n },\n removeServer: async (id) => {\n // removeServer is custom-server only — connectors are app-defined\n // and not user-removable. Refuse rather than silently no-op.\n if (state.connectors.some((c) => c.id === id)) {\n throw new Error(\n `Cannot remove connector \"${id}\" — connectors are app-defined and not removable. Use a custom server id instead.`,\n );\n }\n // Delegate to McpServerResource.remove() which disconnects,\n // clears auth state, and unregisters from customServers in one\n // place. Fallback to manual cleanup if the lookup is empty\n // (server already gone).\n try {\n await lookup.get({ key: id }).remove();\n } catch {\n await storage.clearAuthState(id);\n setCustomServers((prev) => prev.filter((s) => s.id !== id));\n }\n },\n };\n },\n);\n\n// Ensure modelContext exists as a sibling when the manager mounts. If an\n// ancestor (e.g. a chat runtime) already provides modelContext, this is a\n// no-op; otherwise it's auto-mounted alongside `mcp`.\nattachTransformScopes(McpManagerResource, (scopes, parent) => {\n if (!scopes.modelContext && parent.modelContext.source === null) {\n scopes.modelContext = ModelContext();\n }\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"McpManagerResource.js","names":[],"sources":["../../src/resources/McpManagerResource.ts"],"sourcesContent":["import { useState, useEffect, useMemo, useEffectEvent, useRef } from \"react\";\nimport { useResource, resource, withKey } from \"@assistant-ui/tap\";\nimport {\n useClientLookup,\n useAssistantClientRef,\n attachTransformScopes,\n type ClientOutput,\n} from \"@assistant-ui/store\";\nimport { ModelContext } from \"@assistant-ui/core/store\";\nimport type { Tool } from \"assistant-stream\";\nimport { McpServerResource } from \"./McpServerResource\";\nimport { McpLocalStorage } from \"./storage/McpLocalStorage\";\nimport type { MCPStorageElement } from \"./storage/types\";\nimport type {\n MCPAuthConfig,\n MCPConnector,\n MCPCustomServerRecord,\n MCPManagerState,\n} from \"../mcp-scope\";\n\nexport type McpManagerResourceProps = {\n connectors?: MCPConnector[] | undefined;\n storage?: MCPStorageElement | undefined;\n /** OAuth redirect target. Defaults to `${origin}/mcp/callback`. */\n oauthRedirectUri?: string | undefined;\n /** Connect on mount when usable auth exists. Default true. */\n autoConnect?: boolean | undefined;\n};\n\nfunction defaultRedirectUri(): string {\n if (typeof window === \"undefined\") return \"\";\n return `${window.location.origin}/mcp/callback`;\n}\n\n// Stable empty fallback so an absent `connectors` prop doesn't produce a fresh\n// array each render (which would invalidate the serverElements memo below).\nconst NO_CONNECTORS: MCPConnector[] = [];\n\nexport const McpManagerResource = resource(function McpManagerResource(\n props: McpManagerResourceProps,\n): ClientOutput<\"mcp\"> {\n const connectors = props.connectors ?? NO_CONNECTORS;\n const autoConnect = props.autoConnect ?? true;\n const redirectUri = props.oauthRedirectUri ?? defaultRedirectUri();\n\n const storageElement = props.storage ?? McpLocalStorage();\n const storage = useResource(storageElement);\n\n const [customServers, setCustomServers] = useState<MCPCustomServerRecord[]>(\n [],\n );\n const [isHydrated, setIsHydrated] = useState(false);\n\n const hydratedRef = useRef(false);\n\n const hydrate = useEffectEvent(async (signal: { cancelled: boolean }) => {\n try {\n const records = await storage.loadCustomServers();\n if (signal.cancelled) return;\n // Merge rather than replace so any addCustomServer calls that\n // happened before hydration resolved aren't silently overwritten.\n // Persisted order wins; pre-hydration locals append.\n setCustomServers((prev) => {\n if (prev.length === 0) return records;\n const persistedIds = new Set(records.map((r) => r.id));\n return [...records, ...prev.filter((r) => !persistedIds.has(r.id))];\n });\n } finally {\n if (!signal.cancelled) {\n hydratedRef.current = true;\n setIsHydrated(true);\n }\n }\n });\n\n useEffect(() => {\n const signal = { cancelled: false };\n void hydrate(signal);\n return () => {\n signal.cancelled = true;\n };\n }, []);\n\n const persistCustomServers = useEffectEvent(\n async (records: MCPCustomServerRecord[]) => {\n if (!hydratedRef.current) return;\n await storage.saveCustomServers(records);\n },\n );\n\n useEffect(() => {\n void persistCustomServers(customServers);\n }, [customServers]);\n\n const serverElements = useMemo(() => {\n const connectorElements = connectors.map((c) =>\n withKey(\n c.id,\n McpServerResource({\n id: c.id,\n kind: \"connector\",\n name: c.name,\n url: c.url,\n icon: c.icon,\n auth: c.auth,\n storage,\n redirectUri,\n autoConnect,\n onRemove: async () => {\n // connectors cannot be removed\n },\n }),\n ),\n );\n const customElements = customServers.map((s) =>\n withKey(\n s.id,\n McpServerResource({\n id: s.id,\n kind: \"custom\",\n name: s.name,\n url: s.url,\n auth: s.auth,\n storage,\n redirectUri,\n autoConnect,\n onRemove: async () => {\n setCustomServers((prev) => prev.filter((x) => x.id !== s.id));\n },\n }),\n ),\n );\n return [...connectorElements, ...customElements];\n }, [connectors, customServers, storage, redirectUri, autoConnect]);\n\n const lookup = useClientLookup(() => serverElements, [serverElements]);\n\n const state = useMemo<MCPManagerState>(() => {\n const all = lookup.state;\n return {\n servers: all,\n connectors: all.filter((s) => s.kind === \"connector\"),\n customServers: all.filter((s) => s.kind === \"custom\"),\n isHydrated,\n };\n }, [lookup.state, isHydrated]);\n\n // ─── Auto-register MCP tools as frontend tools in modelContext ─────\n // Build the toolkit from connected servers; re-register when the visible\n // tool surface changes. Tool names are prefixed with the server id to\n // avoid collisions across connected servers — connector ids must not\n // contain `__` (enforced by `defineConnector`); `addCustomServer`\n // generates UUIDs that satisfy the constraint by construction.\n const toolkit = useMemo<Record<string, Tool<any, any>>>(() => {\n const out: Record<string, Tool<any, any>> = {};\n for (const server of state.servers) {\n if (server.connectionState !== \"connected\") continue;\n for (const tool of server.tools) {\n const fullName = `${server.id}__${tool.name}`;\n out[fullName] = {\n type: \"frontend\",\n ...(tool.description !== undefined\n ? { description: tool.description }\n : {}),\n parameters: tool.inputSchema as never,\n execute: (args) =>\n lookup.get({ key: server.id }).callTool(tool.name, args as unknown),\n };\n }\n }\n return out;\n }, [state, lookup]);\n\n const clientRef = useAssistantClientRef();\n\n useEffect(() => {\n const client = clientRef.current;\n if (!client) return;\n return client.modelContext().register({\n getModelContext: () => ({ tools: toolkit }),\n });\n }, [toolkit, clientRef]);\n\n const serverByKind = (kind: \"connector\" | \"custom\", index: number) => {\n const list = kind === \"connector\" ? state.connectors : state.customServers;\n const entry = list[index];\n if (!entry) {\n throw new Error(\n `McpManagerResource: no ${kind} at index ${index} (length ${list.length})`,\n );\n }\n return lookup.get({ key: entry.id });\n };\n\n return {\n getState: () => state,\n server: (query) => {\n if (\"id\" in query) return lookup.get({ key: query.id });\n return serverByKind(query.kind, query.index);\n },\n connector: ({ index }) => serverByKind(\"connector\", index),\n customServer: ({ index }) => serverByKind(\"custom\", index),\n addCustomServer: async ({ name, url, auth }) => {\n const record: MCPCustomServerRecord = {\n id:\n typeof crypto !== \"undefined\" && \"randomUUID\" in crypto\n ? crypto.randomUUID()\n : `mcp-${Date.now()}-${Math.random().toString(36).slice(2)}`,\n name,\n url,\n auth: auth as MCPAuthConfig,\n createdAt: Date.now(),\n };\n setCustomServers((prev) => [...prev, record]);\n return record.id;\n },\n removeServer: async (id) => {\n // removeServer is custom-server only — connectors are app-defined\n // and not user-removable. Refuse rather than silently no-op.\n if (state.connectors.some((c) => c.id === id)) {\n throw new Error(\n `Cannot remove connector \"${id}\" — connectors are app-defined and not removable. Use a custom server id instead.`,\n );\n }\n // Delegate to McpServerResource.remove() which disconnects,\n // clears auth state, and unregisters from customServers in one\n // place. Fallback to manual cleanup if the lookup is empty\n // (server already gone).\n try {\n await lookup.get({ key: id }).remove();\n } catch {\n await storage.clearAuthState(id);\n setCustomServers((prev) => prev.filter((s) => s.id !== id));\n }\n },\n };\n});\n\n// Ensure modelContext exists as a sibling when the manager mounts. If an\n// ancestor (e.g. a chat runtime) already provides modelContext, this is a\n// no-op; otherwise it's auto-mounted alongside `mcp`.\nattachTransformScopes(McpManagerResource, (scopes, parent) => {\n if (!scopes.modelContext && parent.modelContext.source === null) {\n scopes.modelContext = ModelContext();\n }\n});\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"McpServerResource.d.ts","names":[],"sources":["../../src/resources/McpServerResource.ts"],"mappings":";;;;;KA4BY,sBAAA;EACV,EAAA;EACA,IAAA,EAAM,aAAA;EACN,IAAA;EACA,GAAA;EACA,IAAA;EACA,IAAA,EAAM,aAAA;EACN,OAAA,EAAS,UAAA;EACT,WAAA;EACA,WAAA;EACA,QAAA,QAAgB,OAAA;AAAA;AAAA,cAGL,iBAAA,GAAiB,KAAA,EAAA,sBAAA,iCAAA,eAAA,CAAA,YAAA,eAAA,sBAAA"}
1
+ {"version":3,"file":"McpServerResource.d.ts","names":[],"sources":["../../src/resources/McpServerResource.ts"],"mappings":";;;;;KAsBY,sBAAA;EACV,EAAA;EACA,IAAA,EAAM,aAAA;EACN,IAAA;EACA,GAAA;EACA,IAAA;EACA,IAAA,EAAM,aAAA;EACN,OAAA,EAAS,UAAA;EACT,WAAA;EACA,WAAA;EACA,QAAA,QAAgB,OAAA;AAAA;AAAA,cAGL,iBAAA,GAAiB,KAAA,EAAA,sBAAA,iCAAA,eAAA,CAAA,YAAA,eAAA,sBAAA"}