@tambo-ai/react 0.53.2 → 0.54.1

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 (57) hide show
  1. package/dist/mcp/__tests__/tambo-mcp-provider.test.js +115 -0
  2. package/dist/mcp/__tests__/tambo-mcp-provider.test.js.map +1 -1
  3. package/dist/mcp/__tests__/use-mcp-servers.test.d.ts +2 -0
  4. package/dist/mcp/__tests__/use-mcp-servers.test.d.ts.map +1 -0
  5. package/dist/mcp/__tests__/use-mcp-servers.test.js +118 -0
  6. package/dist/mcp/__tests__/use-mcp-servers.test.js.map +1 -0
  7. package/dist/mcp/index.d.ts +1 -1
  8. package/dist/mcp/index.d.ts.map +1 -1
  9. package/dist/mcp/index.js +2 -1
  10. package/dist/mcp/index.js.map +1 -1
  11. package/dist/mcp/tambo-mcp-provider.d.ts +34 -2
  12. package/dist/mcp/tambo-mcp-provider.d.ts.map +1 -1
  13. package/dist/mcp/tambo-mcp-provider.js +125 -14
  14. package/dist/mcp/tambo-mcp-provider.js.map +1 -1
  15. package/dist/providers/__tests__/tambo-interactable-provider-partial-updates.test.js +15 -0
  16. package/dist/providers/__tests__/tambo-interactable-provider-partial-updates.test.js.map +1 -1
  17. package/dist/providers/__tests__/tambo-registry-provider.test.js +44 -9
  18. package/dist/providers/__tests__/tambo-registry-provider.test.js.map +1 -1
  19. package/dist/providers/tambo-interactable-provider.d.ts.map +1 -1
  20. package/dist/providers/tambo-interactable-provider.js +3 -0
  21. package/dist/providers/tambo-interactable-provider.js.map +1 -1
  22. package/dist/providers/tambo-registry-provider.d.ts.map +1 -1
  23. package/dist/providers/tambo-registry-provider.js +12 -1
  24. package/dist/providers/tambo-registry-provider.js.map +1 -1
  25. package/dist/util/validate-component-name.d.ts +7 -0
  26. package/dist/util/validate-component-name.d.ts.map +1 -0
  27. package/dist/util/validate-component-name.js +14 -0
  28. package/dist/util/validate-component-name.js.map +1 -0
  29. package/esm/mcp/__tests__/tambo-mcp-provider.test.js +83 -1
  30. package/esm/mcp/__tests__/tambo-mcp-provider.test.js.map +1 -1
  31. package/esm/mcp/__tests__/use-mcp-servers.test.d.ts +2 -0
  32. package/esm/mcp/__tests__/use-mcp-servers.test.d.ts.map +1 -0
  33. package/esm/mcp/__tests__/use-mcp-servers.test.js +83 -0
  34. package/esm/mcp/__tests__/use-mcp-servers.test.js.map +1 -0
  35. package/esm/mcp/index.d.ts +1 -1
  36. package/esm/mcp/index.d.ts.map +1 -1
  37. package/esm/mcp/index.js +1 -1
  38. package/esm/mcp/index.js.map +1 -1
  39. package/esm/mcp/tambo-mcp-provider.d.ts +34 -2
  40. package/esm/mcp/tambo-mcp-provider.d.ts.map +1 -1
  41. package/esm/mcp/tambo-mcp-provider.js +90 -13
  42. package/esm/mcp/tambo-mcp-provider.js.map +1 -1
  43. package/esm/providers/__tests__/tambo-interactable-provider-partial-updates.test.js +15 -0
  44. package/esm/providers/__tests__/tambo-interactable-provider-partial-updates.test.js.map +1 -1
  45. package/esm/providers/__tests__/tambo-registry-provider.test.js +44 -9
  46. package/esm/providers/__tests__/tambo-registry-provider.test.js.map +1 -1
  47. package/esm/providers/tambo-interactable-provider.d.ts.map +1 -1
  48. package/esm/providers/tambo-interactable-provider.js +3 -0
  49. package/esm/providers/tambo-interactable-provider.js.map +1 -1
  50. package/esm/providers/tambo-registry-provider.d.ts.map +1 -1
  51. package/esm/providers/tambo-registry-provider.js +12 -1
  52. package/esm/providers/tambo-registry-provider.js.map +1 -1
  53. package/esm/util/validate-component-name.d.ts +7 -0
  54. package/esm/util/validate-component-name.d.ts.map +1 -0
  55. package/esm/util/validate-component-name.js +11 -0
  56. package/esm/util/validate-component-name.js.map +1 -0
  57. package/package.json +3 -2
@@ -1 +1 @@
1
- {"version":3,"file":"tambo-interactable-provider.js","sourceRoot":"","sources":["../../src/providers/tambo-interactable-provider.tsx"],"names":[],"mappings":"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","sourcesContent":["// react-sdk/src/providers/tambo-interactable-provider.tsx\n\"use client\";\nimport React, {\n createContext,\n PropsWithChildren,\n useCallback,\n useContext,\n useEffect,\n useState,\n} from \"react\";\nimport { z } from \"zod\";\nimport { createInteractablesContextHelper } from \"../context-helpers/current-interactables-context-helper\";\nimport {\n TamboInteractableComponent,\n type TamboInteractableContext,\n} from \"../model/tambo-interactable\";\nimport { useTamboComponent } from \"./tambo-component-provider\";\nimport { useTamboContextHelpers } from \"./tambo-context-helpers-provider\";\n\nconst TamboInteractableContext = createContext<TamboInteractableContext>({\n interactableComponents: [],\n addInteractableComponent: () => \"\",\n removeInteractableComponent: () => {},\n updateInteractableComponentProps: () => \"\",\n getInteractableComponent: () => undefined,\n getInteractableComponentsByName: () => [],\n clearAllInteractableComponents: () => {},\n});\n\n/**\n * The TamboInteractableProvider manages a list of components that are currently\n * interactable, allowing tambo to interact with them by updating their props. It also registers tools\n * for Tambo to perform CRUD operations on the components list.\n * @param props - The props for the TamboInteractableProvider\n * @param props.children - The children to wrap\n * @returns The TamboInteractableProvider component\n */\nexport const TamboInteractableProvider: React.FC<PropsWithChildren> = ({\n children,\n}) => {\n const [interactableComponents, setInteractableComponents] = useState<\n TamboInteractableComponent[]\n >([]);\n const { registerTool } = useTamboComponent();\n const { addContextHelper, removeContextHelper } = useTamboContextHelpers();\n\n // Create a stable context helper function\n const contextHelper = useCallback(() => {\n return createInteractablesContextHelper(() => interactableComponents)();\n }, [interactableComponents]);\n\n // Register the default interactables context helper\n useEffect(() => {\n addContextHelper(\"interactables\", contextHelper);\n\n return () => {\n removeContextHelper(\"interactables\");\n };\n }, [contextHelper, addContextHelper, removeContextHelper]);\n\n useEffect(() => {\n if (interactableComponents.length > 0) {\n registerTool({\n name: \"get_all_interactable_components\",\n description:\n \"Only use this tool if the user is asking about interactable components.Get all currently interactable components with their details including their current props. These are components that you can interact with on behalf of the user.\",\n tool: () => {\n return {\n components: interactableComponents,\n };\n },\n toolSchema: z.function().returns(\n z.object({\n components: z.array(\n z.object({\n id: z.string(),\n componentName: z.string(),\n props: z.record(z.any()),\n propsSchema: z.object({}).optional(),\n }),\n ),\n }),\n ),\n });\n\n registerTool({\n name: \"get_interactable_component_by_id\",\n description: \"Get a specific interactable component by its ID\",\n tool: (componentId: string) => {\n const component = interactableComponents.find(\n (c) => c.id === componentId,\n );\n\n if (!component) {\n return {\n success: false,\n error: `Component with ID ${componentId} not found`,\n };\n }\n\n return {\n success: true,\n component: {\n id: component.id,\n componentName: component.name,\n props: component.props,\n },\n };\n },\n toolSchema: z\n .function()\n .args(z.string())\n .returns(\n z.object({\n success: z.boolean(),\n component: z\n .object({\n id: z.string(),\n componentName: z.string(),\n props: z.record(z.any()),\n })\n .optional(),\n error: z.string().optional(),\n }),\n ),\n });\n\n registerTool({\n name: \"remove_interactable_component\",\n description: \"Remove an interactable component from the system\",\n tool: (componentId: string) => {\n const component = interactableComponents.find(\n (c) => c.id === componentId,\n );\n\n if (!component) {\n return {\n success: false,\n error: `Component with ID ${componentId} not found`,\n };\n }\n\n setInteractableComponents((prev) =>\n prev.filter((c) => c.id !== componentId),\n );\n\n return {\n success: true,\n componentId,\n removedComponent: {\n id: component.id,\n componentName: component.name,\n props: component.props,\n },\n };\n },\n toolSchema: z\n .function()\n .args(z.string())\n .returns(\n z.object({\n success: z.boolean(),\n componentId: z.string(),\n removedComponent: z.object({\n id: z.string(),\n componentName: z.string(),\n props: z.record(z.any()),\n }),\n error: z.string().optional(),\n }),\n ),\n });\n }\n }, [interactableComponents, registerTool]);\n\n const updateInteractableComponentProps = useCallback(\n (id: string, newProps: Record<string, any>): string => {\n if (!newProps || Object.keys(newProps).length === 0) {\n return `Warning: No props provided for component with ID ${id}.`;\n }\n\n setInteractableComponents((prev) => {\n const component = prev.find((c) => c.id === id);\n if (!component) {\n return prev;\n }\n\n // Compare props shallowly\n const propsChanged = Object.entries(newProps).some(([key, value]) => {\n return component.props[key] !== value;\n });\n\n if (!propsChanged) {\n return prev; // unchanged\n }\n\n // Apply partial update\n const updated = {\n ...component,\n props: { ...component.props, ...newProps },\n };\n\n const updatedComponents = [...prev];\n const idx = prev.findIndex((c) => c.id === id);\n updatedComponents[idx] = updated;\n\n return updatedComponents;\n });\n\n return \"Updated successfully\";\n },\n [],\n );\n\n const registerInteractableComponentUpdateTool = useCallback(\n (component: TamboInteractableComponent) => {\n const schemaForArgs =\n typeof component.propsSchema === \"object\" &&\n \"describe\" in component.propsSchema &&\n \"partial\" in component.propsSchema\n ? (component.propsSchema as any).partial()\n : z.object({});\n\n registerTool({\n name: `update_interactable_component_${component.id}`,\n description: `Update the props of interactable component ${component.id} (${component.name}). You can provide partial props (only the props you want to change) or complete props (all props). Only the props you specify will be updated.`,\n tool: (componentId: string, newProps: any) => {\n return updateInteractableComponentProps(componentId, newProps);\n },\n toolSchema: z\n .function()\n .args(\n z\n .string()\n .describe(\"The ID of the interactable component to update\"),\n schemaForArgs.describe(\n \"The props to update the component with. You can provide partial props (only the props you want to change) or complete props (all props). Only the props you specify will be updated.\",\n ),\n )\n .returns(z.string()),\n });\n },\n [registerTool, updateInteractableComponentProps],\n );\n\n const addInteractableComponent = useCallback(\n (\n component: Omit<TamboInteractableComponent, \"id\" | \"createdAt\">,\n ): string => {\n const id = `${component.name}-${Math.random().toString(36).slice(2, 11)}`;\n const newComponent: TamboInteractableComponent = {\n ...component,\n id,\n };\n\n registerInteractableComponentUpdateTool(newComponent);\n\n setInteractableComponents((prev) => {\n return [...prev, newComponent];\n });\n\n return id;\n },\n [registerInteractableComponentUpdateTool],\n );\n\n const removeInteractableComponent = useCallback((id: string) => {\n setInteractableComponents((prev) => prev.filter((c) => c.id !== id));\n }, []);\n\n const getInteractableComponent = useCallback(\n (id: string) => {\n return interactableComponents.find((c) => c.id === id);\n },\n [interactableComponents],\n );\n\n const getInteractableComponentsByName = useCallback(\n (componentName: string) => {\n return interactableComponents.filter((c) => c.name === componentName);\n },\n [interactableComponents],\n );\n\n const clearAllInteractableComponents = useCallback(() => {\n setInteractableComponents([]);\n }, []);\n\n const value: TamboInteractableContext = {\n interactableComponents,\n addInteractableComponent,\n removeInteractableComponent,\n updateInteractableComponentProps,\n getInteractableComponent,\n getInteractableComponentsByName,\n clearAllInteractableComponents,\n };\n\n return (\n <TamboInteractableContext.Provider value={value}>\n {children}\n </TamboInteractableContext.Provider>\n );\n};\n\n/**\n * The useTamboInteractable hook provides access to the interactable component\n * management functions.\n * @returns The interactable component management functions\n */\nexport const useTamboInteractable = () => {\n return useContext(TamboInteractableContext);\n};\n\n/**\n * Hook to get a cloned snapshot of the current interactables.\n * Returns a shallow copy of the array with cloned items and props to prevent\n * external mutation from affecting internal state.\n * @returns The current interactables snapshot (cloned).\n */\nexport const useCurrentInteractablesSnapshot = () => {\n const { interactableComponents } = useTamboInteractable();\n // Clone the array and each item/props to prevent mutation\n const copy = interactableComponents.map((c) => ({\n ...c,\n props: { ...c.props },\n }));\n\n return copy;\n};\n"]}
1
+ {"version":3,"file":"tambo-interactable-provider.js","sourceRoot":"","sources":["../../src/providers/tambo-interactable-provider.tsx"],"names":[],"mappings":";AAAA,0DAA0D;AAC1D,YAAY,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACb,+CAOe;AACf,6BAAwB;AACxB,kHAA2G;AAK3G,yEAA+D;AAC/D,qFAA0E;AAC1E,6EAAkE;AAElE,MAAM,wBAAwB,GAAG,IAAA,qBAAa,EAA2B;IACvE,sBAAsB,EAAE,EAAE;IAC1B,wBAAwB,EAAE,GAAG,EAAE,CAAC,EAAE;IAClC,2BAA2B,EAAE,GAAG,EAAE,GAAE,CAAC;IACrC,gCAAgC,EAAE,GAAG,EAAE,CAAC,EAAE;IAC1C,wBAAwB,EAAE,GAAG,EAAE,CAAC,SAAS;IACzC,+BAA+B,EAAE,GAAG,EAAE,CAAC,EAAE;IACzC,8BAA8B,EAAE,GAAG,EAAE,GAAE,CAAC;CACzC,CAAC,CAAC;AAEH;;;;;;;GAOG;AACI,MAAM,yBAAyB,GAAgC,CAAC,EACrE,QAAQ,GACT,EAAE,EAAE;IACH,MAAM,CAAC,sBAAsB,EAAE,yBAAyB,CAAC,GAAG,IAAA,gBAAQ,EAElE,EAAE,CAAC,CAAC;IACN,MAAM,EAAE,YAAY,EAAE,GAAG,IAAA,4CAAiB,GAAE,CAAC;IAC7C,MAAM,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,GAAG,IAAA,uDAAsB,GAAE,CAAC;IAE3E,0CAA0C;IAC1C,MAAM,aAAa,GAAG,IAAA,mBAAW,EAAC,GAAG,EAAE;QACrC,OAAO,IAAA,uEAAgC,EAAC,GAAG,EAAE,CAAC,sBAAsB,CAAC,EAAE,CAAC;IAC1E,CAAC,EAAE,CAAC,sBAAsB,CAAC,CAAC,CAAC;IAE7B,oDAAoD;IACpD,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,gBAAgB,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;QAEjD,OAAO,GAAG,EAAE;YACV,mBAAmB,CAAC,eAAe,CAAC,CAAC;QACvC,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,aAAa,EAAE,gBAAgB,EAAE,mBAAmB,CAAC,CAAC,CAAC;IAE3D,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,IAAI,sBAAsB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtC,YAAY,CAAC;gBACX,IAAI,EAAE,iCAAiC;gBACvC,WAAW,EACT,2OAA2O;gBAC7O,IAAI,EAAE,GAAG,EAAE;oBACT,OAAO;wBACL,UAAU,EAAE,sBAAsB;qBACnC,CAAC;gBACJ,CAAC;gBACD,UAAU,EAAE,OAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAC9B,OAAC,CAAC,MAAM,CAAC;oBACP,UAAU,EAAE,OAAC,CAAC,KAAK,CACjB,OAAC,CAAC,MAAM,CAAC;wBACP,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE;wBACd,aAAa,EAAE,OAAC,CAAC,MAAM,EAAE;wBACzB,KAAK,EAAE,OAAC,CAAC,MAAM,CAAC,OAAC,CAAC,GAAG,EAAE,CAAC;wBACxB,WAAW,EAAE,OAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;qBACrC,CAAC,CACH;iBACF,CAAC,CACH;aACF,CAAC,CAAC;YAEH,YAAY,CAAC;gBACX,IAAI,EAAE,kCAAkC;gBACxC,WAAW,EAAE,iDAAiD;gBAC9D,IAAI,EAAE,CAAC,WAAmB,EAAE,EAAE;oBAC5B,MAAM,SAAS,GAAG,sBAAsB,CAAC,IAAI,CAC3C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,WAAW,CAC5B,CAAC;oBAEF,IAAI,CAAC,SAAS,EAAE,CAAC;wBACf,OAAO;4BACL,OAAO,EAAE,KAAK;4BACd,KAAK,EAAE,qBAAqB,WAAW,YAAY;yBACpD,CAAC;oBACJ,CAAC;oBAED,OAAO;wBACL,OAAO,EAAE,IAAI;wBACb,SAAS,EAAE;4BACT,EAAE,EAAE,SAAS,CAAC,EAAE;4BAChB,aAAa,EAAE,SAAS,CAAC,IAAI;4BAC7B,KAAK,EAAE,SAAS,CAAC,KAAK;yBACvB;qBACF,CAAC;gBACJ,CAAC;gBACD,UAAU,EAAE,OAAC;qBACV,QAAQ,EAAE;qBACV,IAAI,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC;qBAChB,OAAO,CACN,OAAC,CAAC,MAAM,CAAC;oBACP,OAAO,EAAE,OAAC,CAAC,OAAO,EAAE;oBACpB,SAAS,EAAE,OAAC;yBACT,MAAM,CAAC;wBACN,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE;wBACd,aAAa,EAAE,OAAC,CAAC,MAAM,EAAE;wBACzB,KAAK,EAAE,OAAC,CAAC,MAAM,CAAC,OAAC,CAAC,GAAG,EAAE,CAAC;qBACzB,CAAC;yBACD,QAAQ,EAAE;oBACb,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;iBAC7B,CAAC,CACH;aACJ,CAAC,CAAC;YAEH,YAAY,CAAC;gBACX,IAAI,EAAE,+BAA+B;gBACrC,WAAW,EAAE,kDAAkD;gBAC/D,IAAI,EAAE,CAAC,WAAmB,EAAE,EAAE;oBAC5B,MAAM,SAAS,GAAG,sBAAsB,CAAC,IAAI,CAC3C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,WAAW,CAC5B,CAAC;oBAEF,IAAI,CAAC,SAAS,EAAE,CAAC;wBACf,OAAO;4BACL,OAAO,EAAE,KAAK;4BACd,KAAK,EAAE,qBAAqB,WAAW,YAAY;yBACpD,CAAC;oBACJ,CAAC;oBAED,yBAAyB,CAAC,CAAC,IAAI,EAAE,EAAE,CACjC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,WAAW,CAAC,CACzC,CAAC;oBAEF,OAAO;wBACL,OAAO,EAAE,IAAI;wBACb,WAAW;wBACX,gBAAgB,EAAE;4BAChB,EAAE,EAAE,SAAS,CAAC,EAAE;4BAChB,aAAa,EAAE,SAAS,CAAC,IAAI;4BAC7B,KAAK,EAAE,SAAS,CAAC,KAAK;yBACvB;qBACF,CAAC;gBACJ,CAAC;gBACD,UAAU,EAAE,OAAC;qBACV,QAAQ,EAAE;qBACV,IAAI,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC;qBAChB,OAAO,CACN,OAAC,CAAC,MAAM,CAAC;oBACP,OAAO,EAAE,OAAC,CAAC,OAAO,EAAE;oBACpB,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE;oBACvB,gBAAgB,EAAE,OAAC,CAAC,MAAM,CAAC;wBACzB,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE;wBACd,aAAa,EAAE,OAAC,CAAC,MAAM,EAAE;wBACzB,KAAK,EAAE,OAAC,CAAC,MAAM,CAAC,OAAC,CAAC,GAAG,EAAE,CAAC;qBACzB,CAAC;oBACF,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;iBAC7B,CAAC,CACH;aACJ,CAAC,CAAC;QACL,CAAC;IACH,CAAC,EAAE,CAAC,sBAAsB,EAAE,YAAY,CAAC,CAAC,CAAC;IAE3C,MAAM,gCAAgC,GAAG,IAAA,mBAAW,EAClD,CAAC,EAAU,EAAE,QAA6B,EAAU,EAAE;QACpD,IAAI,CAAC,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACpD,OAAO,oDAAoD,EAAE,GAAG,CAAC;QACnE,CAAC;QAED,yBAAyB,CAAC,CAAC,IAAI,EAAE,EAAE;YACjC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;YAChD,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,OAAO,IAAI,CAAC;YACd,CAAC;YAED,0BAA0B;YAC1B,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;gBAClE,OAAO,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC;YACxC,CAAC,CAAC,CAAC;YAEH,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,OAAO,IAAI,CAAC,CAAC,YAAY;YAC3B,CAAC;YAED,uBAAuB;YACvB,MAAM,OAAO,GAAG;gBACd,GAAG,SAAS;gBACZ,KAAK,EAAE,EAAE,GAAG,SAAS,CAAC,KAAK,EAAE,GAAG,QAAQ,EAAE;aAC3C,CAAC;YAEF,MAAM,iBAAiB,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;YACpC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;YAC/C,iBAAiB,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC;YAEjC,OAAO,iBAAiB,CAAC;QAC3B,CAAC,CAAC,CAAC;QAEH,OAAO,sBAAsB,CAAC;IAChC,CAAC,EACD,EAAE,CACH,CAAC;IAEF,MAAM,uCAAuC,GAAG,IAAA,mBAAW,EACzD,CAAC,SAAqC,EAAE,EAAE;QACxC,MAAM,aAAa,GACjB,OAAO,SAAS,CAAC,WAAW,KAAK,QAAQ;YACzC,UAAU,IAAI,SAAS,CAAC,WAAW;YACnC,SAAS,IAAI,SAAS,CAAC,WAAW;YAChC,CAAC,CAAE,SAAS,CAAC,WAAmB,CAAC,OAAO,EAAE;YAC1C,CAAC,CAAC,OAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAEnB,YAAY,CAAC;YACX,IAAI,EAAE,iCAAiC,SAAS,CAAC,EAAE,EAAE;YACrD,WAAW,EAAE,8CAA8C,SAAS,CAAC,EAAE,KAAK,SAAS,CAAC,IAAI,iJAAiJ;YAC3O,IAAI,EAAE,CAAC,WAAmB,EAAE,QAAa,EAAE,EAAE;gBAC3C,OAAO,gCAAgC,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;YACjE,CAAC;YACD,UAAU,EAAE,OAAC;iBACV,QAAQ,EAAE;iBACV,IAAI,CACH,OAAC;iBACE,MAAM,EAAE;iBACR,QAAQ,CAAC,gDAAgD,CAAC,EAC7D,aAAa,CAAC,QAAQ,CACpB,sLAAsL,CACvL,CACF;iBACA,OAAO,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC;SACvB,CAAC,CAAC;IACL,CAAC,EACD,CAAC,YAAY,EAAE,gCAAgC,CAAC,CACjD,CAAC;IAEF,MAAM,wBAAwB,GAAG,IAAA,mBAAW,EAC1C,CACE,SAA+D,EACvD,EAAE;QACV,0BAA0B;QAC1B,IAAA,yCAAe,EAAC,SAAS,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAE7C,MAAM,EAAE,GAAG,GAAG,SAAS,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;QAC1E,MAAM,YAAY,GAA+B;YAC/C,GAAG,SAAS;YACZ,EAAE;SACH,CAAC;QAEF,uCAAuC,CAAC,YAAY,CAAC,CAAC;QAEtD,yBAAyB,CAAC,CAAC,IAAI,EAAE,EAAE;YACjC,OAAO,CAAC,GAAG,IAAI,EAAE,YAAY,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,OAAO,EAAE,CAAC;IACZ,CAAC,EACD,CAAC,uCAAuC,CAAC,CAC1C,CAAC;IAEF,MAAM,2BAA2B,GAAG,IAAA,mBAAW,EAAC,CAAC,EAAU,EAAE,EAAE;QAC7D,yBAAyB,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IACvE,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,wBAAwB,GAAG,IAAA,mBAAW,EAC1C,CAAC,EAAU,EAAE,EAAE;QACb,OAAO,sBAAsB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACzD,CAAC,EACD,CAAC,sBAAsB,CAAC,CACzB,CAAC;IAEF,MAAM,+BAA+B,GAAG,IAAA,mBAAW,EACjD,CAAC,aAAqB,EAAE,EAAE;QACxB,OAAO,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC;IACxE,CAAC,EACD,CAAC,sBAAsB,CAAC,CACzB,CAAC;IAEF,MAAM,8BAA8B,GAAG,IAAA,mBAAW,EAAC,GAAG,EAAE;QACtD,yBAAyB,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,KAAK,GAA6B;QACtC,sBAAsB;QACtB,wBAAwB;QACxB,2BAA2B;QAC3B,gCAAgC;QAChC,wBAAwB;QACxB,+BAA+B;QAC/B,8BAA8B;KAC/B,CAAC;IAEF,OAAO,CACL,8BAAC,wBAAwB,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,IAC5C,QAAQ,CACyB,CACrC,CAAC;AACJ,CAAC,CAAC;AA7QW,QAAA,yBAAyB,6BA6QpC;AAEF;;;;GAIG;AACI,MAAM,oBAAoB,GAAG,GAAG,EAAE;IACvC,OAAO,IAAA,kBAAU,EAAC,wBAAwB,CAAC,CAAC;AAC9C,CAAC,CAAC;AAFW,QAAA,oBAAoB,wBAE/B;AAEF;;;;;GAKG;AACI,MAAM,+BAA+B,GAAG,GAAG,EAAE;IAClD,MAAM,EAAE,sBAAsB,EAAE,GAAG,IAAA,4BAAoB,GAAE,CAAC;IAC1D,0DAA0D;IAC1D,MAAM,IAAI,GAAG,sBAAsB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC9C,GAAG,CAAC;QACJ,KAAK,EAAE,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE;KACtB,CAAC,CAAC,CAAC;IAEJ,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AATW,QAAA,+BAA+B,mCAS1C","sourcesContent":["// react-sdk/src/providers/tambo-interactable-provider.tsx\n\"use client\";\nimport React, {\n createContext,\n PropsWithChildren,\n useCallback,\n useContext,\n useEffect,\n useState,\n} from \"react\";\nimport { z } from \"zod\";\nimport { createInteractablesContextHelper } from \"../context-helpers/current-interactables-context-helper\";\nimport {\n TamboInteractableComponent,\n type TamboInteractableContext,\n} from \"../model/tambo-interactable\";\nimport { useTamboComponent } from \"./tambo-component-provider\";\nimport { useTamboContextHelpers } from \"./tambo-context-helpers-provider\";\nimport { assertValidName } from \"../util/validate-component-name\";\n\nconst TamboInteractableContext = createContext<TamboInteractableContext>({\n interactableComponents: [],\n addInteractableComponent: () => \"\",\n removeInteractableComponent: () => {},\n updateInteractableComponentProps: () => \"\",\n getInteractableComponent: () => undefined,\n getInteractableComponentsByName: () => [],\n clearAllInteractableComponents: () => {},\n});\n\n/**\n * The TamboInteractableProvider manages a list of components that are currently\n * interactable, allowing tambo to interact with them by updating their props. It also registers tools\n * for Tambo to perform CRUD operations on the components list.\n * @param props - The props for the TamboInteractableProvider\n * @param props.children - The children to wrap\n * @returns The TamboInteractableProvider component\n */\nexport const TamboInteractableProvider: React.FC<PropsWithChildren> = ({\n children,\n}) => {\n const [interactableComponents, setInteractableComponents] = useState<\n TamboInteractableComponent[]\n >([]);\n const { registerTool } = useTamboComponent();\n const { addContextHelper, removeContextHelper } = useTamboContextHelpers();\n\n // Create a stable context helper function\n const contextHelper = useCallback(() => {\n return createInteractablesContextHelper(() => interactableComponents)();\n }, [interactableComponents]);\n\n // Register the default interactables context helper\n useEffect(() => {\n addContextHelper(\"interactables\", contextHelper);\n\n return () => {\n removeContextHelper(\"interactables\");\n };\n }, [contextHelper, addContextHelper, removeContextHelper]);\n\n useEffect(() => {\n if (interactableComponents.length > 0) {\n registerTool({\n name: \"get_all_interactable_components\",\n description:\n \"Only use this tool if the user is asking about interactable components.Get all currently interactable components with their details including their current props. These are components that you can interact with on behalf of the user.\",\n tool: () => {\n return {\n components: interactableComponents,\n };\n },\n toolSchema: z.function().returns(\n z.object({\n components: z.array(\n z.object({\n id: z.string(),\n componentName: z.string(),\n props: z.record(z.any()),\n propsSchema: z.object({}).optional(),\n }),\n ),\n }),\n ),\n });\n\n registerTool({\n name: \"get_interactable_component_by_id\",\n description: \"Get a specific interactable component by its ID\",\n tool: (componentId: string) => {\n const component = interactableComponents.find(\n (c) => c.id === componentId,\n );\n\n if (!component) {\n return {\n success: false,\n error: `Component with ID ${componentId} not found`,\n };\n }\n\n return {\n success: true,\n component: {\n id: component.id,\n componentName: component.name,\n props: component.props,\n },\n };\n },\n toolSchema: z\n .function()\n .args(z.string())\n .returns(\n z.object({\n success: z.boolean(),\n component: z\n .object({\n id: z.string(),\n componentName: z.string(),\n props: z.record(z.any()),\n })\n .optional(),\n error: z.string().optional(),\n }),\n ),\n });\n\n registerTool({\n name: \"remove_interactable_component\",\n description: \"Remove an interactable component from the system\",\n tool: (componentId: string) => {\n const component = interactableComponents.find(\n (c) => c.id === componentId,\n );\n\n if (!component) {\n return {\n success: false,\n error: `Component with ID ${componentId} not found`,\n };\n }\n\n setInteractableComponents((prev) =>\n prev.filter((c) => c.id !== componentId),\n );\n\n return {\n success: true,\n componentId,\n removedComponent: {\n id: component.id,\n componentName: component.name,\n props: component.props,\n },\n };\n },\n toolSchema: z\n .function()\n .args(z.string())\n .returns(\n z.object({\n success: z.boolean(),\n componentId: z.string(),\n removedComponent: z.object({\n id: z.string(),\n componentName: z.string(),\n props: z.record(z.any()),\n }),\n error: z.string().optional(),\n }),\n ),\n });\n }\n }, [interactableComponents, registerTool]);\n\n const updateInteractableComponentProps = useCallback(\n (id: string, newProps: Record<string, any>): string => {\n if (!newProps || Object.keys(newProps).length === 0) {\n return `Warning: No props provided for component with ID ${id}.`;\n }\n\n setInteractableComponents((prev) => {\n const component = prev.find((c) => c.id === id);\n if (!component) {\n return prev;\n }\n\n // Compare props shallowly\n const propsChanged = Object.entries(newProps).some(([key, value]) => {\n return component.props[key] !== value;\n });\n\n if (!propsChanged) {\n return prev; // unchanged\n }\n\n // Apply partial update\n const updated = {\n ...component,\n props: { ...component.props, ...newProps },\n };\n\n const updatedComponents = [...prev];\n const idx = prev.findIndex((c) => c.id === id);\n updatedComponents[idx] = updated;\n\n return updatedComponents;\n });\n\n return \"Updated successfully\";\n },\n [],\n );\n\n const registerInteractableComponentUpdateTool = useCallback(\n (component: TamboInteractableComponent) => {\n const schemaForArgs =\n typeof component.propsSchema === \"object\" &&\n \"describe\" in component.propsSchema &&\n \"partial\" in component.propsSchema\n ? (component.propsSchema as any).partial()\n : z.object({});\n\n registerTool({\n name: `update_interactable_component_${component.id}`,\n description: `Update the props of interactable component ${component.id} (${component.name}). You can provide partial props (only the props you want to change) or complete props (all props). Only the props you specify will be updated.`,\n tool: (componentId: string, newProps: any) => {\n return updateInteractableComponentProps(componentId, newProps);\n },\n toolSchema: z\n .function()\n .args(\n z\n .string()\n .describe(\"The ID of the interactable component to update\"),\n schemaForArgs.describe(\n \"The props to update the component with. You can provide partial props (only the props you want to change) or complete props (all props). Only the props you specify will be updated.\",\n ),\n )\n .returns(z.string()),\n });\n },\n [registerTool, updateInteractableComponentProps],\n );\n\n const addInteractableComponent = useCallback(\n (\n component: Omit<TamboInteractableComponent, \"id\" | \"createdAt\">,\n ): string => {\n // Validate component name\n assertValidName(component.name, \"component\");\n\n const id = `${component.name}-${Math.random().toString(36).slice(2, 11)}`;\n const newComponent: TamboInteractableComponent = {\n ...component,\n id,\n };\n\n registerInteractableComponentUpdateTool(newComponent);\n\n setInteractableComponents((prev) => {\n return [...prev, newComponent];\n });\n\n return id;\n },\n [registerInteractableComponentUpdateTool],\n );\n\n const removeInteractableComponent = useCallback((id: string) => {\n setInteractableComponents((prev) => prev.filter((c) => c.id !== id));\n }, []);\n\n const getInteractableComponent = useCallback(\n (id: string) => {\n return interactableComponents.find((c) => c.id === id);\n },\n [interactableComponents],\n );\n\n const getInteractableComponentsByName = useCallback(\n (componentName: string) => {\n return interactableComponents.filter((c) => c.name === componentName);\n },\n [interactableComponents],\n );\n\n const clearAllInteractableComponents = useCallback(() => {\n setInteractableComponents([]);\n }, []);\n\n const value: TamboInteractableContext = {\n interactableComponents,\n addInteractableComponent,\n removeInteractableComponent,\n updateInteractableComponentProps,\n getInteractableComponent,\n getInteractableComponentsByName,\n clearAllInteractableComponents,\n };\n\n return (\n <TamboInteractableContext.Provider value={value}>\n {children}\n </TamboInteractableContext.Provider>\n );\n};\n\n/**\n * The useTamboInteractable hook provides access to the interactable component\n * management functions.\n * @returns The interactable component management functions\n */\nexport const useTamboInteractable = () => {\n return useContext(TamboInteractableContext);\n};\n\n/**\n * Hook to get a cloned snapshot of the current interactables.\n * Returns a shallow copy of the array with cloned items and props to prevent\n * external mutation from affecting internal state.\n * @returns The current interactables snapshot (cloned).\n */\nexport const useCurrentInteractablesSnapshot = () => {\n const { interactableComponents } = useTamboInteractable();\n // Clone the array and each item/props to prevent mutation\n const copy = interactableComponents.map((c) => ({\n ...c,\n props: { ...c.props },\n }));\n\n return copy;\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"tambo-registry-provider.d.ts","sourceRoot":"","sources":["../../src/providers/tambo-registry-provider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,OAAO,MAAM,0BAA0B,CAAC;AACpD,OAAO,KAAK,EAAE,EAEZ,iBAAiB,EAKlB,MAAM,OAAO,CAAC;AAGf,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,SAAS,EACV,MAAM,6BAA6B,CAAC;AAGrC,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,iBAAiB,CAAC;IACjC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACxC,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACpD,iBAAiB,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;IACrD,YAAY,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IACxC,aAAa,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;IAC5C,kBAAkB,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IACrE,sBAAsB,CAAC,EAAE,CACvB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,CAAC,iBAAiB,EAAE,KAC9B,OAAO,CAAC,MAAM,CAAC,CAAC;CACtB;AAED,eAAO,MAAM,oBAAoB,qCAoB/B,CAAC;AAEH,MAAM,WAAW,0BAA0B;IACzC,iCAAiC;IACjC,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAC9B,4BAA4B;IAC5B,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC;IAEpB;;;;;;;OAOG;IACH,sBAAsB,CAAC,EAAE,CACvB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,CAAC,iBAAiB,EAAE,KAC9B,OAAO,CAAC,MAAM,CAAC,CAAC;CACtB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAC1C,iBAAiB,CAAC,0BAA0B,CAAC,CAgJ9C,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,4BAE5B,CAAC"}
1
+ {"version":3,"file":"tambo-registry-provider.d.ts","sourceRoot":"","sources":["../../src/providers/tambo-registry-provider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,OAAO,MAAM,0BAA0B,CAAC;AACpD,OAAO,KAAK,EAAE,EAEZ,iBAAiB,EAKlB,MAAM,OAAO,CAAC;AAGf,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,SAAS,EACV,MAAM,6BAA6B,CAAC;AAIrC,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,iBAAiB,CAAC;IACjC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACxC,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACpD,iBAAiB,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;IACrD,YAAY,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IACxC,aAAa,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;IAC5C,kBAAkB,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IACrE,sBAAsB,CAAC,EAAE,CACvB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,CAAC,iBAAiB,EAAE,KAC9B,OAAO,CAAC,MAAM,CAAC,CAAC;CACtB;AAED,eAAO,MAAM,oBAAoB,qCAoB/B,CAAC;AAEH,MAAM,WAAW,0BAA0B;IACzC,iCAAiC;IACjC,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAC9B,4BAA4B;IAC5B,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC;IAEpB;;;;;;;OAOG;IACH,sBAAsB,CAAC,EAAE,CACvB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,CAAC,iBAAiB,EAAE,KAC9B,OAAO,CAAC,MAAM,CAAC,CAAC;CACtB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAC1C,iBAAiB,CAAC,0BAA0B,CAAC,CA8J9C,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,4BAE5B,CAAC"}
@@ -41,6 +41,7 @@ exports.useTamboRegistry = exports.TamboRegistryProvider = exports.TamboRegistry
41
41
  const react_1 = __importStar(require("react"));
42
42
  const zod_1 = require("zod");
43
43
  const zod_to_json_schema_1 = __importDefault(require("zod-to-json-schema"));
44
+ const validate_component_name_1 = require("../util/validate-component-name");
44
45
  const validate_zod_schema_1 = require("../util/validate-zod-schema");
45
46
  exports.TamboRegistryContext = (0, react_1.createContext)({
46
47
  componentList: {},
@@ -78,6 +79,8 @@ const TamboRegistryProvider = ({ children, components: userComponents, tools: us
78
79
  const [toolRegistry, setToolRegistry] = (0, react_1.useState)({});
79
80
  const [componentToolAssociations, setComponentToolAssociations] = (0, react_1.useState)({});
80
81
  const registerTool = (0, react_1.useCallback)((tool, warnOnOverwrite = true) => {
82
+ // Validate tool name
83
+ (0, validate_component_name_1.assertValidName)(tool.name, "tool");
81
84
  // Validate tool schemas
82
85
  if (tool.toolSchema && isZodSchema(tool.toolSchema)) {
83
86
  (0, validate_zod_schema_1.assertNoZodRecord)(tool.toolSchema, `toolSchema of tool "${tool.name}"`);
@@ -96,16 +99,24 @@ const TamboRegistryProvider = ({ children, components: userComponents, tools: us
96
99
  tools.forEach((tool) => registerTool(tool, warnOnOverwrite));
97
100
  }, [registerTool]);
98
101
  const addToolAssociation = (0, react_1.useCallback)((componentName, tool) => {
102
+ // Validate component and tool names
103
+ (0, validate_component_name_1.assertValidName)(componentName, "component");
104
+ (0, validate_component_name_1.assertValidName)(tool.name, "tool");
99
105
  if (!componentList[componentName]) {
100
106
  throw new Error(`Component ${componentName} not found in registry`);
101
107
  }
108
+ if (!toolRegistry[tool.name]) {
109
+ throw new Error(`Tool ${tool.name} not found in registry`);
110
+ }
102
111
  setComponentToolAssociations((prev) => ({
103
112
  ...prev,
104
113
  [componentName]: [...(prev[componentName] || []), tool.name],
105
114
  }));
106
- }, [componentList]);
115
+ }, [componentList, toolRegistry]);
107
116
  const registerComponent = (0, react_1.useCallback)((options, warnOnOverwrite = true) => {
108
117
  const { name, description, component, propsSchema, propsDefinition, loadingComponent, associatedTools, } = options;
118
+ // Validate component name
119
+ (0, validate_component_name_1.assertValidName)(name, "component");
109
120
  // Validate that at least one props definition is provided
110
121
  if (!propsSchema && !propsDefinition) {
111
122
  throw new Error(`Component ${name} must have either propsSchema (recommended) or propsDefinition defined`);
@@ -1 +1 @@
1
- {"version":3,"file":"tambo-registry-provider.js","sourceRoot":"","sources":["../../src/providers/tambo-registry-provider.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\nimport type TamboAI from \"@tambo-ai/typescript-sdk\";\nimport React, {\n createContext,\n PropsWithChildren,\n useCallback,\n useContext,\n useEffect,\n useState,\n} from \"react\";\nimport { ZodSchema } from \"zod\";\nimport zodToJsonSchema from \"zod-to-json-schema\";\nimport {\n ComponentRegistry,\n TamboComponent,\n TamboTool,\n} from \"../model/component-metadata\";\nimport { assertNoZodRecord } from \"../util/validate-zod-schema\";\n\nexport interface TamboRegistryContext {\n componentList: ComponentRegistry;\n toolRegistry: Record<string, TamboTool>;\n componentToolAssociations: Record<string, string[]>;\n registerComponent: (options: TamboComponent) => void;\n registerTool: (tool: TamboTool) => void;\n registerTools: (tools: TamboTool[]) => void;\n addToolAssociation: (componentName: string, tool: TamboTool) => void;\n onCallUnregisteredTool?: (\n toolName: string,\n args: TamboAI.ToolCallParameter[],\n ) => Promise<string>;\n}\n\nexport const TamboRegistryContext = createContext<TamboRegistryContext>({\n componentList: {},\n toolRegistry: {},\n componentToolAssociations: {},\n /**\n *\n */\n registerComponent: () => {},\n /**\n *\n */\n registerTool: () => {},\n /**\n *\n */\n registerTools: () => {},\n /**\n *\n */\n addToolAssociation: () => {},\n});\n\nexport interface TamboRegistryProviderProps {\n /** The components to register */\n components?: TamboComponent[];\n /** The tools to register */\n tools?: TamboTool[];\n\n /**\n * A function to call when an unknown tool is called. If this function is not\n * provided, an error will be thrown when a tool call is requested by the\n * server.\n *\n * Note that this is generally only for agents, where the agent code may\n * request tool calls that are not registered in the tool registry.\n */\n onCallUnregisteredTool?: (\n toolName: string,\n args: TamboAI.ToolCallParameter[],\n ) => Promise<string>;\n}\n\n/**\n * The TamboRegistryProvider is a React provider that provides a component\n * registry to the descendants of the provider.\n * @param props - The props for the TamboRegistryProvider\n * @param props.children - The children to wrap\n * @param props.components - The components to register\n * @param props.tools - The tools to register\n * @param props.onCallUnregisteredTool - The function to call when an unknown tool is called (optional)\n * @returns The TamboRegistryProvider component\n */\nexport const TamboRegistryProvider: React.FC<\n PropsWithChildren<TamboRegistryProviderProps>\n> = ({\n children,\n components: userComponents,\n tools: userTools,\n onCallUnregisteredTool,\n}) => {\n const [componentList, setComponentList] = useState<ComponentRegistry>({});\n const [toolRegistry, setToolRegistry] = useState<Record<string, TamboTool>>(\n {},\n );\n const [componentToolAssociations, setComponentToolAssociations] = useState<\n Record<string, string[]>\n >({});\n\n const registerTool = useCallback(\n (tool: TamboTool, warnOnOverwrite = true) => {\n // Validate tool schemas\n if (tool.toolSchema && isZodSchema(tool.toolSchema)) {\n assertNoZodRecord(tool.toolSchema, `toolSchema of tool \"${tool.name}\"`);\n }\n setToolRegistry((prev) => {\n if (prev[tool.name] && warnOnOverwrite) {\n console.warn(`Overwriting tool ${tool.name}`);\n }\n return {\n ...prev,\n [tool.name]: tool,\n };\n });\n },\n [],\n );\n\n const registerTools = useCallback(\n (tools: TamboTool[], warnOnOverwrite = true) => {\n tools.forEach((tool) => registerTool(tool, warnOnOverwrite));\n },\n [registerTool],\n );\n\n const addToolAssociation = useCallback(\n (componentName: string, tool: TamboTool) => {\n if (!componentList[componentName]) {\n throw new Error(`Component ${componentName} not found in registry`);\n }\n setComponentToolAssociations((prev) => ({\n ...prev,\n [componentName]: [...(prev[componentName] || []), tool.name],\n }));\n },\n [componentList],\n );\n\n const registerComponent = useCallback(\n (options: TamboComponent, warnOnOverwrite = true) => {\n const {\n name,\n description,\n component,\n propsSchema,\n propsDefinition,\n loadingComponent,\n associatedTools,\n } = options;\n\n // Validate that at least one props definition is provided\n if (!propsSchema && !propsDefinition) {\n throw new Error(\n `Component ${name} must have either propsSchema (recommended) or propsDefinition defined`,\n );\n }\n\n // Validate that only one props definition is provided\n if (propsSchema && propsDefinition) {\n throw new Error(\n `Component ${name} cannot have both propsSchema and propsDefinition defined. Use only one. We recommend using propsSchema.`,\n );\n }\n\n // Validate that the propsSchema does not include z.record()\n if (propsSchema && isZodSchema(propsSchema)) {\n assertNoZodRecord(propsSchema, `propsSchema of component \"${name}\"`);\n }\n\n // Convert propsSchema to JSON Schema if it exists\n const props = getSerializedProps(propsDefinition, propsSchema, name);\n\n setComponentList((prev) => {\n if (prev[name] && warnOnOverwrite) {\n console.warn(`overwriting component ${name}`);\n }\n return {\n ...prev,\n [name]: {\n component,\n loadingComponent,\n name,\n description,\n props,\n contextTools: [],\n },\n };\n });\n if (associatedTools) {\n registerTools(associatedTools);\n setComponentToolAssociations((prev) => ({\n ...prev,\n [name]: associatedTools.map((tool) => tool.name),\n }));\n }\n },\n [registerTools],\n );\n useEffect(() => {\n if (userComponents) {\n userComponents.forEach((component) => {\n registerComponent(component, false);\n });\n }\n }, [registerComponent, userComponents]);\n\n useEffect(() => {\n if (userTools) {\n registerTools(userTools, false);\n }\n }, [registerTools, userTools]);\n\n const value = {\n componentList,\n toolRegistry,\n componentToolAssociations,\n registerComponent,\n registerTool,\n registerTools,\n addToolAssociation,\n onCallUnregisteredTool,\n };\n\n return (\n <TamboRegistryContext.Provider value={value}>\n {children}\n </TamboRegistryContext.Provider>\n );\n};\n\n/**\n * The useTamboRegistry hook provides access to the component registry\n * to the descendants of the TamboRegistryProvider.\n * @returns The component registry\n */\nexport const useTamboRegistry = () => {\n return useContext(TamboRegistryContext);\n};\nfunction getSerializedProps(\n propsDefinition: any,\n propsSchema: any,\n name: string,\n) {\n if (propsDefinition) {\n console.warn(`propsDefinition is deprecated. Use propsSchema instead.`);\n return propsDefinition;\n }\n\n if (isZodSchema(propsSchema)) {\n try {\n return zodToJsonSchema(propsSchema);\n } catch (error) {\n console.error(\n `Error converting ${name} props schema to JSON Schema:`,\n error,\n );\n }\n }\n // try to roughly detect JSONSchema, should always be an object with a properties key\n if (isJSONSchema(propsSchema)) {\n return propsSchema;\n }\n\n throw new Error(`Invalid props schema for ${name}`);\n}\n\n/**\n * Checks if the propsSchema is a JSON Schema. This is a rough check, and the\n * server will provide the definitive check.\n * @param propsSchema - The props schema to check\n * @returns True if the props schema is a JSON Schema, false otherwise\n */\nfunction isJSONSchema(propsSchema: any) {\n return (\n propsSchema &&\n typeof propsSchema === \"object\" &&\n propsSchema.type === \"object\" &&\n propsSchema.properties\n );\n}\n\n/**\n * Since we require a certain zod version, we need to check if the object is a ZodSchema\n * @param obj - The object to check\n * @returns True if the object is a ZodSchema, false otherwise\n */\nfunction isZodSchema(obj: unknown): obj is ZodSchema {\n if (obj instanceof ZodSchema) {\n return true;\n }\n // try to detect if the object is a ZodSchema\n return (\n typeof obj === \"object\" &&\n obj !== null &&\n typeof (obj as any).safeParse === \"function\" &&\n typeof (obj as any)._def === \"object\"\n );\n}\n"]}
1
+ {"version":3,"file":"tambo-registry-provider.js","sourceRoot":"","sources":["../../src/providers/tambo-registry-provider.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\nimport type TamboAI from \"@tambo-ai/typescript-sdk\";\nimport React, {\n createContext,\n PropsWithChildren,\n useCallback,\n useContext,\n useEffect,\n useState,\n} from \"react\";\nimport { ZodSchema } from \"zod\";\nimport zodToJsonSchema from \"zod-to-json-schema\";\nimport {\n ComponentRegistry,\n TamboComponent,\n TamboTool,\n} from \"../model/component-metadata\";\nimport { assertValidName } from \"../util/validate-component-name\";\nimport { assertNoZodRecord } from \"../util/validate-zod-schema\";\n\nexport interface TamboRegistryContext {\n componentList: ComponentRegistry;\n toolRegistry: Record<string, TamboTool>;\n componentToolAssociations: Record<string, string[]>;\n registerComponent: (options: TamboComponent) => void;\n registerTool: (tool: TamboTool) => void;\n registerTools: (tools: TamboTool[]) => void;\n addToolAssociation: (componentName: string, tool: TamboTool) => void;\n onCallUnregisteredTool?: (\n toolName: string,\n args: TamboAI.ToolCallParameter[],\n ) => Promise<string>;\n}\n\nexport const TamboRegistryContext = createContext<TamboRegistryContext>({\n componentList: {},\n toolRegistry: {},\n componentToolAssociations: {},\n /**\n *\n */\n registerComponent: () => {},\n /**\n *\n */\n registerTool: () => {},\n /**\n *\n */\n registerTools: () => {},\n /**\n *\n */\n addToolAssociation: () => {},\n});\n\nexport interface TamboRegistryProviderProps {\n /** The components to register */\n components?: TamboComponent[];\n /** The tools to register */\n tools?: TamboTool[];\n\n /**\n * A function to call when an unknown tool is called. If this function is not\n * provided, an error will be thrown when a tool call is requested by the\n * server.\n *\n * Note that this is generally only for agents, where the agent code may\n * request tool calls that are not registered in the tool registry.\n */\n onCallUnregisteredTool?: (\n toolName: string,\n args: TamboAI.ToolCallParameter[],\n ) => Promise<string>;\n}\n\n/**\n * The TamboRegistryProvider is a React provider that provides a component\n * registry to the descendants of the provider.\n * @param props - The props for the TamboRegistryProvider\n * @param props.children - The children to wrap\n * @param props.components - The components to register\n * @param props.tools - The tools to register\n * @param props.onCallUnregisteredTool - The function to call when an unknown tool is called (optional)\n * @returns The TamboRegistryProvider component\n */\nexport const TamboRegistryProvider: React.FC<\n PropsWithChildren<TamboRegistryProviderProps>\n> = ({\n children,\n components: userComponents,\n tools: userTools,\n onCallUnregisteredTool,\n}) => {\n const [componentList, setComponentList] = useState<ComponentRegistry>({});\n const [toolRegistry, setToolRegistry] = useState<Record<string, TamboTool>>(\n {},\n );\n const [componentToolAssociations, setComponentToolAssociations] = useState<\n Record<string, string[]>\n >({});\n\n const registerTool = useCallback(\n (tool: TamboTool, warnOnOverwrite = true) => {\n // Validate tool name\n assertValidName(tool.name, \"tool\");\n\n // Validate tool schemas\n if (tool.toolSchema && isZodSchema(tool.toolSchema)) {\n assertNoZodRecord(tool.toolSchema, `toolSchema of tool \"${tool.name}\"`);\n }\n setToolRegistry((prev) => {\n if (prev[tool.name] && warnOnOverwrite) {\n console.warn(`Overwriting tool ${tool.name}`);\n }\n return {\n ...prev,\n [tool.name]: tool,\n };\n });\n },\n [],\n );\n\n const registerTools = useCallback(\n (tools: TamboTool[], warnOnOverwrite = true) => {\n tools.forEach((tool) => registerTool(tool, warnOnOverwrite));\n },\n [registerTool],\n );\n\n const addToolAssociation = useCallback(\n (componentName: string, tool: TamboTool) => {\n // Validate component and tool names\n assertValidName(componentName, \"component\");\n assertValidName(tool.name, \"tool\");\n\n if (!componentList[componentName]) {\n throw new Error(`Component ${componentName} not found in registry`);\n }\n if (!toolRegistry[tool.name]) {\n throw new Error(`Tool ${tool.name} not found in registry`);\n }\n\n setComponentToolAssociations((prev) => ({\n ...prev,\n [componentName]: [...(prev[componentName] || []), tool.name],\n }));\n },\n [componentList, toolRegistry],\n );\n\n const registerComponent = useCallback(\n (options: TamboComponent, warnOnOverwrite = true) => {\n const {\n name,\n description,\n component,\n propsSchema,\n propsDefinition,\n loadingComponent,\n associatedTools,\n } = options;\n\n // Validate component name\n assertValidName(name, \"component\");\n\n // Validate that at least one props definition is provided\n if (!propsSchema && !propsDefinition) {\n throw new Error(\n `Component ${name} must have either propsSchema (recommended) or propsDefinition defined`,\n );\n }\n\n // Validate that only one props definition is provided\n if (propsSchema && propsDefinition) {\n throw new Error(\n `Component ${name} cannot have both propsSchema and propsDefinition defined. Use only one. We recommend using propsSchema.`,\n );\n }\n\n // Validate that the propsSchema does not include z.record()\n if (propsSchema && isZodSchema(propsSchema)) {\n assertNoZodRecord(propsSchema, `propsSchema of component \"${name}\"`);\n }\n\n // Convert propsSchema to JSON Schema if it exists\n const props = getSerializedProps(propsDefinition, propsSchema, name);\n\n setComponentList((prev) => {\n if (prev[name] && warnOnOverwrite) {\n console.warn(`overwriting component ${name}`);\n }\n return {\n ...prev,\n [name]: {\n component,\n loadingComponent,\n name,\n description,\n props,\n contextTools: [],\n },\n };\n });\n if (associatedTools) {\n registerTools(associatedTools);\n setComponentToolAssociations((prev) => ({\n ...prev,\n [name]: associatedTools.map((tool) => tool.name),\n }));\n }\n },\n [registerTools],\n );\n useEffect(() => {\n if (userComponents) {\n userComponents.forEach((component) => {\n registerComponent(component, false);\n });\n }\n }, [registerComponent, userComponents]);\n\n useEffect(() => {\n if (userTools) {\n registerTools(userTools, false);\n }\n }, [registerTools, userTools]);\n\n const value = {\n componentList,\n toolRegistry,\n componentToolAssociations,\n registerComponent,\n registerTool,\n registerTools,\n addToolAssociation,\n onCallUnregisteredTool,\n };\n\n return (\n <TamboRegistryContext.Provider value={value}>\n {children}\n </TamboRegistryContext.Provider>\n );\n};\n\n/**\n * The useTamboRegistry hook provides access to the component registry\n * to the descendants of the TamboRegistryProvider.\n * @returns The component registry\n */\nexport const useTamboRegistry = () => {\n return useContext(TamboRegistryContext);\n};\nfunction getSerializedProps(\n propsDefinition: any,\n propsSchema: any,\n name: string,\n) {\n if (propsDefinition) {\n console.warn(`propsDefinition is deprecated. Use propsSchema instead.`);\n return propsDefinition;\n }\n\n if (isZodSchema(propsSchema)) {\n try {\n return zodToJsonSchema(propsSchema);\n } catch (error) {\n console.error(\n `Error converting ${name} props schema to JSON Schema:`,\n error,\n );\n }\n }\n // try to roughly detect JSONSchema, should always be an object with a properties key\n if (isJSONSchema(propsSchema)) {\n return propsSchema;\n }\n\n throw new Error(`Invalid props schema for ${name}`);\n}\n\n/**\n * Checks if the propsSchema is a JSON Schema. This is a rough check, and the\n * server will provide the definitive check.\n * @param propsSchema - The props schema to check\n * @returns True if the props schema is a JSON Schema, false otherwise\n */\nfunction isJSONSchema(propsSchema: any) {\n return (\n propsSchema &&\n typeof propsSchema === \"object\" &&\n propsSchema.type === \"object\" &&\n propsSchema.properties\n );\n}\n\n/**\n * Since we require a certain zod version, we need to check if the object is a ZodSchema\n * @param obj - The object to check\n * @returns True if the object is a ZodSchema, false otherwise\n */\nfunction isZodSchema(obj: unknown): obj is ZodSchema {\n if (obj instanceof ZodSchema) {\n return true;\n }\n // try to detect if the object is a ZodSchema\n return (\n typeof obj === \"object\" &&\n obj !== null &&\n typeof (obj as any).safeParse === \"function\" &&\n typeof (obj as any)._def === \"object\"\n );\n}\n"]}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Validates that a name matches OpenAI function name requirements
3
+ * @param name The name to validate
4
+ * @param contextName The context name (e.g., "component", "tool")
5
+ */
6
+ export declare function assertValidName(name: string, contextName: string): void;
7
+ //# sourceMappingURL=validate-component-name.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-component-name.d.ts","sourceRoot":"","sources":["../../src/util/validate-component-name.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAMvE"}
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assertValidName = assertValidName;
4
+ /**
5
+ * Validates that a name matches OpenAI function name requirements
6
+ * @param name The name to validate
7
+ * @param contextName The context name (e.g., "component", "tool")
8
+ */
9
+ function assertValidName(name, contextName) {
10
+ if (!/^[a-zA-Z0-9_-]+$/.test(name)) {
11
+ throw new Error(`${contextName} "${name}" must only contain letters, numbers, underscores, and hyphens.`);
12
+ }
13
+ }
14
+ //# sourceMappingURL=validate-component-name.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-component-name.js","sourceRoot":"","sources":["../../src/util/validate-component-name.ts"],"names":[],"mappings":";;AAKA,0CAMC;AAXD;;;;GAIG;AACH,SAAgB,eAAe,CAAC,IAAY,EAAE,WAAmB;IAC/D,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CACb,GAAG,WAAW,KAAK,IAAI,iEAAiE,CACzF,CAAC;IACJ,CAAC;AACH,CAAC","sourcesContent":["/**\n * Validates that a name matches OpenAI function name requirements\n * @param name The name to validate\n * @param contextName The context name (e.g., \"component\", \"tool\")\n */\nexport function assertValidName(name: string, contextName: string): void {\n if (!/^[a-zA-Z0-9_-]+$/.test(name)) {\n throw new Error(\n `${contextName} \"${name}\" must only contain letters, numbers, underscores, and hyphens.`,\n );\n }\n}\n"]}
@@ -1,4 +1,8 @@
1
- import { extractErrorMessage } from "../tambo-mcp-provider";
1
+ import { render, waitFor } from "@testing-library/react";
2
+ import React, { useEffect } from "react";
3
+ import { useTamboRegistry } from "../../providers/tambo-registry-provider";
4
+ import { MCPClient, MCPTransport } from "../mcp-client";
5
+ import { extractErrorMessage, TamboMcpProvider, useTamboMcpServers, } from "../tambo-mcp-provider";
2
6
  // Mock the MCP client to avoid ES module issues
3
7
  jest.mock("../mcp-client", () => ({
4
8
  MCPClient: jest.fn(),
@@ -110,4 +114,82 @@ describe("extractErrorMessage", () => {
110
114
  });
111
115
  });
112
116
  });
117
+ describe("TamboMcpProvider server list changes", () => {
118
+ beforeEach(() => {
119
+ // Mock registry so tool registration is a no-op
120
+ useTamboRegistry.mockReturnValue({
121
+ registerTool: jest.fn(),
122
+ });
123
+ // Ensure MCPClient.create exists and returns a fake client with listTools
124
+ MCPClient.create = jest
125
+ .fn()
126
+ .mockResolvedValue({ listTools: jest.fn().mockResolvedValue([]) });
127
+ });
128
+ const Capture = ({ onUpdate, }) => {
129
+ const servers = useTamboMcpServers();
130
+ useEffect(() => {
131
+ onUpdate(servers);
132
+ }, [servers, onUpdate]);
133
+ return React.createElement("div", { "data-testid": "urls" }, servers.map((s) => s.url).join(","));
134
+ };
135
+ it("adds a new server when the list grows", async () => {
136
+ let latest = [];
137
+ const { rerender, getByTestId } = render(React.createElement(TamboMcpProvider, { mcpServers: ["https://a.example"] },
138
+ React.createElement(Capture, { onUpdate: (s) => (latest = s) })));
139
+ // Wait for initial connection
140
+ await waitFor(() => {
141
+ expect(latest.length).toBe(1);
142
+ });
143
+ // Add new server
144
+ rerender(React.createElement(TamboMcpProvider, { mcpServers: ["https://a.example", "https://b.example"] },
145
+ React.createElement(Capture, { onUpdate: (s) => (latest = s) })));
146
+ await waitFor(() => {
147
+ expect(latest.length).toBe(2);
148
+ const urls = getByTestId("urls").textContent || "";
149
+ expect(urls).toContain("https://a.example");
150
+ expect(urls).toContain("https://b.example");
151
+ });
152
+ });
153
+ it("removes a server when the list shrinks", async () => {
154
+ let latest = [];
155
+ const { rerender, getByTestId } = render(React.createElement(TamboMcpProvider, { mcpServers: ["https://a.example", "https://b.example"] },
156
+ React.createElement(Capture, { onUpdate: (s) => (latest = s) })));
157
+ await waitFor(() => {
158
+ expect(latest.length).toBe(2);
159
+ });
160
+ // Remove one server
161
+ rerender(React.createElement(TamboMcpProvider, { mcpServers: ["https://a.example"] },
162
+ React.createElement(Capture, { onUpdate: (s) => (latest = s) })));
163
+ await waitFor(() => {
164
+ expect(latest.length).toBe(1);
165
+ const urls = getByTestId("urls").textContent || "";
166
+ expect(urls).toContain("https://a.example");
167
+ expect(urls).not.toContain("https://b.example");
168
+ });
169
+ });
170
+ it("does not duplicate when a new copy of the same list is passed", async () => {
171
+ let latest = [];
172
+ const initial = [
173
+ { url: "https://a.example", transport: MCPTransport.SSE },
174
+ { url: "https://b.example", transport: MCPTransport.SSE },
175
+ ];
176
+ const { rerender } = render(React.createElement(TamboMcpProvider, { mcpServers: initial },
177
+ React.createElement(Capture, { onUpdate: (s) => (latest = s) })));
178
+ await waitFor(() => {
179
+ expect(latest.length).toBe(2);
180
+ });
181
+ // Pass a new array instance with the same logical servers
182
+ const same = [
183
+ { url: "https://a.example", transport: MCPTransport.SSE },
184
+ { url: "https://b.example", transport: MCPTransport.SSE },
185
+ ];
186
+ rerender(React.createElement(TamboMcpProvider, { mcpServers: same },
187
+ React.createElement(Capture, { onUpdate: (s) => (latest = s) })));
188
+ await waitFor(() => {
189
+ expect(latest.length).toBe(2);
190
+ const urls = latest.map((s) => s.url).sort();
191
+ expect(urls).toEqual(["https://a.example", "https://b.example"].sort());
192
+ });
193
+ });
194
+ });
113
195
  //# sourceMappingURL=tambo-mcp-provider.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tambo-mcp-provider.test.js","sourceRoot":"","sources":["../../../src/mcp/__tests__/tambo-mcp-provider.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import { extractErrorMessage } from \"../tambo-mcp-provider\";\n\n// Mock the MCP client to avoid ES module issues\njest.mock(\"../mcp-client\", () => ({\n MCPClient: jest.fn(),\n MCPTransport: {\n SSE: \"sse\",\n HTTP: \"http\",\n },\n}));\n\n// Mock the registry provider to avoid dependency issues\njest.mock(\"../../providers/tambo-registry-provider\", () => ({\n useTamboRegistry: jest.fn(),\n}));\n\ndescribe(\"extractErrorMessage\", () => {\n describe(\"Array content handling\", () => {\n it(\"should extract text from array content with multiple text items\", () => {\n const content = [\n { type: \"text\", text: \"Error:\" },\n { type: \"text\", text: \"Tool execution failed\" },\n { type: \"image\", url: \"http://example.com/error.png\" }, // Should be filtered out\n ];\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Error: Tool execution failed\");\n });\n\n it(\"should extract text from array content with single text item\", () => {\n const content = [{ type: \"text\", text: \"Simple error message\" }];\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Simple error message\");\n });\n\n it(\"should return fallback message for array content with no text items\", () => {\n const content = [\n { type: \"image\", url: \"http://example.com/error.png\" },\n { type: \"resource\", uri: \"file://error.log\" },\n ];\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Error occurred but no details provided\");\n });\n\n it(\"should return fallback message for empty array content\", () => {\n const content: any[] = [];\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Error occurred but no details provided\");\n });\n\n it(\"should handle array content with mixed types correctly\", () => {\n const content = [\n { type: \"resource\", uri: \"file://log.txt\" },\n { type: \"text\", text: \"First error\" },\n { type: \"image\", url: \"http://example.com/img.png\" },\n { type: \"text\", text: \"Second error\" },\n { type: \"unknown\", data: \"something\" },\n ];\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"First error Second error\");\n });\n\n it(\"should handle array content with malformed items\", () => {\n const content = [\n null,\n { type: \"text\", text: \"Valid error\" },\n { type: \"text\" }, // Missing text property\n { type: \"text\", text: null }, // Invalid text type\n { type: \"text\", text: \"Another valid error\" },\n ];\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Valid error Another valid error\");\n });\n });\n\n describe(\"Non-array content handling\", () => {\n it(\"should return string content as-is\", () => {\n const content = \"Direct error message\";\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Direct error message\");\n });\n\n it(\"should handle null content\", () => {\n const content = null;\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Unknown error occurred\");\n });\n\n it(\"should handle undefined content\", () => {\n const content = undefined;\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Unknown error occurred\");\n });\n\n it(\"should handle number content\", () => {\n const content = 42;\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"42\");\n });\n\n it(\"should handle boolean content\", () => {\n const content = false;\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"false\");\n });\n\n it(\"should handle object content\", () => {\n const content = { error: \"Something went wrong\" };\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe('{\"error\":\"Something went wrong\"}');\n });\n\n it(\"should handle complex object content\", () => {\n const content = {\n error: \"Something went wrong\",\n code: 500,\n details: { message: \"Internal server error\" },\n };\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\n '{\"error\":\"Something went wrong\",\"code\":500,\"details\":{\"message\":\"Internal server error\"}}',\n );\n });\n\n it(\"should handle empty object content\", () => {\n const content = {};\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"{}\");\n });\n });\n});\n"]}
1
+ {"version":3,"file":"tambo-mcp-provider.test.js","sourceRoot":"","sources":["../../../src/mcp/__tests__/tambo-mcp-provider.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import { render, waitFor } from \"@testing-library/react\";\nimport React, { useEffect } from \"react\";\nimport { useTamboRegistry } from \"../../providers/tambo-registry-provider\";\nimport { MCPClient, MCPTransport } from \"../mcp-client\";\nimport {\n extractErrorMessage,\n TamboMcpProvider,\n useTamboMcpServers,\n type McpServer,\n} from \"../tambo-mcp-provider\";\n\n// Mock the MCP client to avoid ES module issues\njest.mock(\"../mcp-client\", () => ({\n MCPClient: jest.fn(),\n MCPTransport: {\n SSE: \"sse\",\n HTTP: \"http\",\n },\n}));\n\n// Mock the registry provider to avoid dependency issues\njest.mock(\"../../providers/tambo-registry-provider\", () => ({\n useTamboRegistry: jest.fn(),\n}));\n\ndescribe(\"extractErrorMessage\", () => {\n describe(\"Array content handling\", () => {\n it(\"should extract text from array content with multiple text items\", () => {\n const content = [\n { type: \"text\", text: \"Error:\" },\n { type: \"text\", text: \"Tool execution failed\" },\n { type: \"image\", url: \"http://example.com/error.png\" }, // Should be filtered out\n ];\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Error: Tool execution failed\");\n });\n\n it(\"should extract text from array content with single text item\", () => {\n const content = [{ type: \"text\", text: \"Simple error message\" }];\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Simple error message\");\n });\n\n it(\"should return fallback message for array content with no text items\", () => {\n const content = [\n { type: \"image\", url: \"http://example.com/error.png\" },\n { type: \"resource\", uri: \"file://error.log\" },\n ];\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Error occurred but no details provided\");\n });\n\n it(\"should return fallback message for empty array content\", () => {\n const content: any[] = [];\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Error occurred but no details provided\");\n });\n\n it(\"should handle array content with mixed types correctly\", () => {\n const content = [\n { type: \"resource\", uri: \"file://log.txt\" },\n { type: \"text\", text: \"First error\" },\n { type: \"image\", url: \"http://example.com/img.png\" },\n { type: \"text\", text: \"Second error\" },\n { type: \"unknown\", data: \"something\" },\n ];\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"First error Second error\");\n });\n\n it(\"should handle array content with malformed items\", () => {\n const content = [\n null,\n { type: \"text\", text: \"Valid error\" },\n { type: \"text\" }, // Missing text property\n { type: \"text\", text: null }, // Invalid text type\n { type: \"text\", text: \"Another valid error\" },\n ];\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Valid error Another valid error\");\n });\n });\n\n describe(\"Non-array content handling\", () => {\n it(\"should return string content as-is\", () => {\n const content = \"Direct error message\";\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Direct error message\");\n });\n\n it(\"should handle null content\", () => {\n const content = null;\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Unknown error occurred\");\n });\n\n it(\"should handle undefined content\", () => {\n const content = undefined;\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"Unknown error occurred\");\n });\n\n it(\"should handle number content\", () => {\n const content = 42;\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"42\");\n });\n\n it(\"should handle boolean content\", () => {\n const content = false;\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"false\");\n });\n\n it(\"should handle object content\", () => {\n const content = { error: \"Something went wrong\" };\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe('{\"error\":\"Something went wrong\"}');\n });\n\n it(\"should handle complex object content\", () => {\n const content = {\n error: \"Something went wrong\",\n code: 500,\n details: { message: \"Internal server error\" },\n };\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\n '{\"error\":\"Something went wrong\",\"code\":500,\"details\":{\"message\":\"Internal server error\"}}',\n );\n });\n\n it(\"should handle empty object content\", () => {\n const content = {};\n\n const result = extractErrorMessage(content);\n\n expect(result).toBe(\"{}\");\n });\n });\n});\n\ndescribe(\"TamboMcpProvider server list changes\", () => {\n beforeEach(() => {\n // Mock registry so tool registration is a no-op\n (useTamboRegistry as unknown as jest.Mock).mockReturnValue({\n registerTool: jest.fn(),\n });\n\n // Ensure MCPClient.create exists and returns a fake client with listTools\n (MCPClient as unknown as any).create = jest\n .fn()\n .mockResolvedValue({ listTools: jest.fn().mockResolvedValue([]) });\n });\n\n const Capture: React.FC<{ onUpdate: (servers: McpServer[]) => void }> = ({\n onUpdate,\n }) => {\n const servers = useTamboMcpServers();\n useEffect(() => {\n onUpdate(servers);\n }, [servers, onUpdate]);\n return <div data-testid=\"urls\">{servers.map((s) => s.url).join(\",\")}</div>;\n };\n\n it(\"adds a new server when the list grows\", async () => {\n let latest: McpServer[] = [];\n const { rerender, getByTestId } = render(\n <TamboMcpProvider mcpServers={[\"https://a.example\"]}>\n <Capture onUpdate={(s) => (latest = s)} />\n </TamboMcpProvider>,\n );\n\n // Wait for initial connection\n await waitFor(() => {\n expect(latest.length).toBe(1);\n });\n\n // Add new server\n rerender(\n <TamboMcpProvider mcpServers={[\"https://a.example\", \"https://b.example\"]}>\n <Capture onUpdate={(s) => (latest = s)} />\n </TamboMcpProvider>,\n );\n\n await waitFor(() => {\n expect(latest.length).toBe(2);\n const urls = getByTestId(\"urls\").textContent || \"\";\n expect(urls).toContain(\"https://a.example\");\n expect(urls).toContain(\"https://b.example\");\n });\n });\n\n it(\"removes a server when the list shrinks\", async () => {\n let latest: McpServer[] = [];\n const { rerender, getByTestId } = render(\n <TamboMcpProvider mcpServers={[\"https://a.example\", \"https://b.example\"]}>\n <Capture onUpdate={(s) => (latest = s)} />\n </TamboMcpProvider>,\n );\n\n await waitFor(() => {\n expect(latest.length).toBe(2);\n });\n\n // Remove one server\n rerender(\n <TamboMcpProvider mcpServers={[\"https://a.example\"]}>\n <Capture onUpdate={(s) => (latest = s)} />\n </TamboMcpProvider>,\n );\n\n await waitFor(() => {\n expect(latest.length).toBe(1);\n const urls = getByTestId(\"urls\").textContent || \"\";\n expect(urls).toContain(\"https://a.example\");\n expect(urls).not.toContain(\"https://b.example\");\n });\n });\n\n it(\"does not duplicate when a new copy of the same list is passed\", async () => {\n let latest: McpServer[] = [];\n const initial = [\n { url: \"https://a.example\", transport: MCPTransport.SSE },\n { url: \"https://b.example\", transport: MCPTransport.SSE },\n ];\n\n const { rerender } = render(\n <TamboMcpProvider mcpServers={initial}>\n <Capture onUpdate={(s) => (latest = s)} />\n </TamboMcpProvider>,\n );\n\n await waitFor(() => {\n expect(latest.length).toBe(2);\n });\n\n // Pass a new array instance with the same logical servers\n const same = [\n { url: \"https://a.example\", transport: MCPTransport.SSE },\n { url: \"https://b.example\", transport: MCPTransport.SSE },\n ];\n rerender(\n <TamboMcpProvider mcpServers={same}>\n <Capture onUpdate={(s) => (latest = s)} />\n </TamboMcpProvider>,\n );\n\n await waitFor(() => {\n expect(latest.length).toBe(2);\n const urls = latest.map((s) => s.url).sort();\n expect(urls).toEqual([\"https://a.example\", \"https://b.example\"].sort());\n });\n });\n});\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=use-mcp-servers.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-mcp-servers.test.d.ts","sourceRoot":"","sources":["../../../src/mcp/__tests__/use-mcp-servers.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,83 @@
1
+ import { render, waitFor } from "@testing-library/react";
2
+ import React, { useEffect } from "react";
3
+ import { TamboRegistryProvider } from "../../providers/tambo-registry-provider";
4
+ import { TamboMcpProvider, useTamboMcpServers, } from "../tambo-mcp-provider";
5
+ // Mock the registry to provide a no-op registerTool
6
+ // Do not mock the registry; use the real provider in render
7
+ // Mock the MCP client; use a mutable implementation to avoid TDZ issues
8
+ let createImpl = jest.fn();
9
+ jest.mock("../mcp-client", () => ({
10
+ MCPClient: { create: (...args) => createImpl(...args) },
11
+ MCPTransport: { SSE: "sse", HTTP: "http" },
12
+ }));
13
+ // Import after mocks note: jest.mock calls are hoisted, so standard imports are fine
14
+ describe("useTamboMcpServers + TamboMcpProvider", () => {
15
+ beforeEach(() => {
16
+ createImpl = jest.fn();
17
+ });
18
+ it("provides normalized MCP server entries to inner components", async () => {
19
+ const fakeClient = { listTools: jest.fn().mockResolvedValue([]) };
20
+ createImpl.mockResolvedValue(fakeClient);
21
+ const Inner = () => {
22
+ const servers = useTamboMcpServers();
23
+ return (React.createElement("div", null,
24
+ React.createElement("div", { "data-testid": "count" }, servers.length),
25
+ React.createElement("div", { "data-testid": "urls" }, servers.map((s) => s.url).join(","))));
26
+ };
27
+ const { getByTestId } = render(React.createElement(TamboRegistryProvider, null,
28
+ React.createElement(TamboMcpProvider, { mcpServers: [{ url: "https://one.example" }, "https://two.example"] },
29
+ React.createElement(Inner, null))));
30
+ await waitFor(() => {
31
+ expect(getByTestId("count").textContent).toBe("2");
32
+ const urls = getByTestId("urls").textContent || "";
33
+ expect(urls).toContain("https://one.example");
34
+ expect(urls).toContain("https://two.example");
35
+ });
36
+ });
37
+ it("marks a successfully connected server with a client instance", async () => {
38
+ const fakeClient = { listTools: jest.fn().mockResolvedValue([]) };
39
+ createImpl.mockResolvedValue(fakeClient);
40
+ let latest = [];
41
+ const Capture = () => {
42
+ const servers = useTamboMcpServers();
43
+ useEffect(() => {
44
+ latest = servers;
45
+ }, [servers]);
46
+ return null;
47
+ };
48
+ render(React.createElement(TamboRegistryProvider, null,
49
+ React.createElement(TamboMcpProvider, { mcpServers: [{ url: "https://ok.example" }] },
50
+ React.createElement(Capture, null))));
51
+ await waitFor(() => {
52
+ expect(latest.length).toBe(1);
53
+ expect("client" in latest[0]).toBe(true);
54
+ expect(latest[0].client).toBe(fakeClient);
55
+ // no connectionError on connected server
56
+ expect(latest[0].connectionError).toBeUndefined();
57
+ });
58
+ });
59
+ it("marks a failed server with a connectionError and no client", async () => {
60
+ const boom = new Error("boom");
61
+ createImpl.mockRejectedValue(boom);
62
+ let latest = [];
63
+ const Capture = () => {
64
+ const servers = useTamboMcpServers();
65
+ useEffect(() => {
66
+ latest = servers;
67
+ }, [servers]);
68
+ return null;
69
+ };
70
+ render(React.createElement(TamboRegistryProvider, null,
71
+ React.createElement(TamboMcpProvider, { mcpServers: [{ url: "https://fail.example" }] },
72
+ React.createElement(Capture, null))));
73
+ await waitFor(() => {
74
+ expect(latest.length).toBe(1);
75
+ expect("client" in latest[0]).toBe(false);
76
+ // @ts-expect-error narrowing at runtime
77
+ expect(latest[0].connectionError).toBeInstanceOf(Error);
78
+ // @ts-expect-error narrowing at runtime
79
+ expect(latest[0].connectionError?.message).toBe("boom");
80
+ });
81
+ });
82
+ });
83
+ //# sourceMappingURL=use-mcp-servers.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-mcp-servers.test.js","sourceRoot":"","sources":["../../../src/mcp/__tests__/use-mcp-servers.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import { render, waitFor } from \"@testing-library/react\";\nimport React, { useEffect } from \"react\";\nimport { TamboRegistryProvider } from \"../../providers/tambo-registry-provider\";\nimport {\n TamboMcpProvider,\n useTamboMcpServers,\n type McpServer,\n} from \"../tambo-mcp-provider\";\n\n// Mock the registry to provide a no-op registerTool\n// Do not mock the registry; use the real provider in render\n\n// Mock the MCP client; use a mutable implementation to avoid TDZ issues\nlet createImpl: jest.Mock<any, any> = jest.fn();\njest.mock(\"../mcp-client\", () => ({\n MCPClient: { create: (...args: any[]) => createImpl(...args) },\n MCPTransport: { SSE: \"sse\", HTTP: \"http\" },\n}));\n\n// Import after mocks note: jest.mock calls are hoisted, so standard imports are fine\n\ndescribe(\"useTamboMcpServers + TamboMcpProvider\", () => {\n beforeEach(() => {\n createImpl = jest.fn();\n });\n\n it(\"provides normalized MCP server entries to inner components\", async () => {\n const fakeClient = { listTools: jest.fn().mockResolvedValue([]) } as any;\n createImpl.mockResolvedValue(fakeClient);\n\n const Inner: React.FC = () => {\n const servers = useTamboMcpServers();\n return (\n <div>\n <div data-testid=\"count\">{servers.length}</div>\n <div data-testid=\"urls\">{servers.map((s) => s.url).join(\",\")}</div>\n </div>\n );\n };\n\n const { getByTestId } = render(\n <TamboRegistryProvider>\n <TamboMcpProvider\n mcpServers={[{ url: \"https://one.example\" }, \"https://two.example\"]}\n >\n <Inner />\n </TamboMcpProvider>\n </TamboRegistryProvider>,\n );\n\n await waitFor(() => {\n expect(getByTestId(\"count\").textContent).toBe(\"2\");\n const urls = getByTestId(\"urls\").textContent || \"\";\n expect(urls).toContain(\"https://one.example\");\n expect(urls).toContain(\"https://two.example\");\n });\n });\n\n it(\"marks a successfully connected server with a client instance\", async () => {\n const fakeClient = { listTools: jest.fn().mockResolvedValue([]) } as any;\n createImpl.mockResolvedValue(fakeClient);\n\n let latest: McpServer[] = [];\n const Capture: React.FC = () => {\n const servers = useTamboMcpServers();\n useEffect(() => {\n latest = servers;\n }, [servers]);\n return null;\n };\n\n render(\n <TamboRegistryProvider>\n <TamboMcpProvider mcpServers={[{ url: \"https://ok.example\" }]}>\n <Capture />\n </TamboMcpProvider>\n </TamboRegistryProvider>,\n );\n\n await waitFor(() => {\n expect(latest.length).toBe(1);\n expect(\"client\" in latest[0]).toBe(true);\n expect((latest[0] as any).client).toBe(fakeClient);\n // no connectionError on connected server\n expect((latest[0] as any).connectionError).toBeUndefined();\n });\n });\n\n it(\"marks a failed server with a connectionError and no client\", async () => {\n const boom = new Error(\"boom\");\n createImpl.mockRejectedValue(boom);\n\n let latest: McpServer[] = [];\n const Capture: React.FC = () => {\n const servers = useTamboMcpServers();\n useEffect(() => {\n latest = servers;\n }, [servers]);\n return null;\n };\n\n render(\n <TamboRegistryProvider>\n <TamboMcpProvider mcpServers={[{ url: \"https://fail.example\" }]}>\n <Capture />\n </TamboMcpProvider>\n </TamboRegistryProvider>,\n );\n\n await waitFor(() => {\n expect(latest.length).toBe(1);\n expect(\"client\" in latest[0]).toBe(false);\n // @ts-expect-error narrowing at runtime\n expect(latest[0].connectionError).toBeInstanceOf(Error);\n // @ts-expect-error narrowing at runtime\n expect(latest[0].connectionError?.message).toBe(\"boom\");\n });\n });\n});\n"]}
@@ -1,3 +1,3 @@
1
1
  export { MCPTransport } from "./mcp-client";
2
- export { TamboMcpProvider, type McpServerInfo } from "./tambo-mcp-provider";
2
+ export { TamboMcpProvider, useTamboMcpServers, type ConnectedMcpServer, type FailedMcpServer, type McpServer, type McpServerInfo, } from "./tambo-mcp-provider";
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,SAAS,EACd,KAAK,aAAa,GACnB,MAAM,sBAAsB,CAAC"}
package/esm/mcp/index.js CHANGED
@@ -1,3 +1,3 @@
1
1
  export { MCPTransport } from "./mcp-client";
2
- export { TamboMcpProvider } from "./tambo-mcp-provider";
2
+ export { TamboMcpProvider, useTamboMcpServers, } from "./tambo-mcp-provider";
3
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAsB,MAAM,sBAAsB,CAAC","sourcesContent":["export { MCPTransport } from \"./mcp-client\";\nexport { TamboMcpProvider, type McpServerInfo } from \"./tambo-mcp-provider\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EACL,gBAAgB,EAChB,kBAAkB,GAKnB,MAAM,sBAAsB,CAAC","sourcesContent":["export { MCPTransport } from \"./mcp-client\";\nexport {\n TamboMcpProvider,\n useTamboMcpServers,\n type ConnectedMcpServer,\n type FailedMcpServer,\n type McpServer,\n type McpServerInfo,\n} from \"./tambo-mcp-provider\";\n"]}
@@ -1,5 +1,5 @@
1
- import { FC } from "react";
2
- import { MCPTransport } from "./mcp-client";
1
+ import React, { FC } from "react";
2
+ import { MCPClient, MCPTransport } from "./mcp-client";
3
3
  /**
4
4
  * Extracts error message from MCP tool result content.
5
5
  * Handles both array and string content formats.
@@ -14,6 +14,14 @@ export interface McpServerInfo {
14
14
  transport?: MCPTransport;
15
15
  customHeaders?: Record<string, string>;
16
16
  }
17
+ export interface ConnectedMcpServer extends McpServerInfo {
18
+ client: MCPClient;
19
+ }
20
+ export interface FailedMcpServer extends McpServerInfo {
21
+ client?: never;
22
+ connectionError: Error;
23
+ }
24
+ export type McpServer = ConnectedMcpServer | FailedMcpServer;
17
25
  /**
18
26
  * This provider is used to register tools from MCP servers.
19
27
  * @returns the wrapped children
@@ -22,4 +30,28 @@ export declare const TamboMcpProvider: FC<{
22
30
  mcpServers: (McpServerInfo | string)[];
23
31
  children: React.ReactNode;
24
32
  }>;
33
+ /**
34
+ * Hook to access the actual MCP servers, as they are connected (or fail to
35
+ * connect).
36
+ *
37
+ * You can call methods on the MCP client that is included in the MCP server
38
+ * object.
39
+ *
40
+ * If the server fails to connect, the `client` property will be `undefined` and
41
+ * the `connectionError` property will be set.
42
+ *
43
+ * For example, to forcibly disconnect and reconnect all MCP servers:
44
+ *
45
+ * ```tsx
46
+ * const mcpServers = useTamboMcpServers();
47
+ * mcpServers.forEach((mcpServer) => {
48
+ * mcpServer.client?.reconnect();
49
+ * });
50
+ * ```
51
+ *
52
+ * Note that the MCP servers are not guaranteed to be in the same order as the
53
+ * input array, because they are added as they are connected.
54
+ * @returns The MCP servers
55
+ */
56
+ export declare const useTamboMcpServers: () => McpServer[];
25
57
  //# sourceMappingURL=tambo-mcp-provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tambo-mcp-provider.d.ts","sourceRoot":"","sources":["../../src/mcp/tambo-mcp-provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAa,MAAM,OAAO,CAAC;AAGtC,OAAO,EAAa,YAAY,EAAE,MAAM,cAAc,CAAC;AAEvD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAsB5D;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,YAAY,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACxC;AACD;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,EAAE,CAAC;IAChC,UAAU,EAAE,CAAC,aAAa,GAAG,MAAM,CAAC,EAAE,CAAC;IACvC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAkEA,CAAC"}
1
+ {"version":3,"file":"tambo-mcp-provider.d.ts","sourceRoot":"","sources":["../../src/mcp/tambo-mcp-provider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAEZ,EAAE,EAIH,MAAM,OAAO,CAAC;AAGf,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEvD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAsB5D;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,YAAY,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACxC;AAED,MAAM,WAAW,kBAAmB,SAAQ,aAAa;IACvD,MAAM,EAAE,SAAS,CAAC;CACnB;AAED,MAAM,WAAW,eAAgB,SAAQ,aAAa;IACpD,MAAM,CAAC,EAAE,KAAK,CAAC;IACf,eAAe,EAAE,KAAK,CAAC;CACxB;AAED,MAAM,MAAM,SAAS,GAAG,kBAAkB,GAAG,eAAe,CAAC;AAG7D;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,EAAE,CAAC;IAChC,UAAU,EAAE,CAAC,aAAa,GAAG,MAAM,CAAC,EAAE,CAAC;IACvC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAsIA,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,kBAAkB,mBAE9B,CAAC"}