@tambo-ai/react 0.65.3 → 0.66.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +120 -20
- package/dist/{providers/hoc → hoc}/with-tambo-interactable.d.ts +2 -2
- package/dist/hoc/with-tambo-interactable.d.ts.map +1 -0
- package/dist/{providers/hoc → hoc}/with-tambo-interactable.js +29 -2
- package/dist/hoc/with-tambo-interactable.js.map +1 -0
- package/dist/hoc/with-tambo-interactable.test.d.ts +2 -0
- package/dist/hoc/with-tambo-interactable.test.d.ts.map +1 -0
- package/dist/hoc/with-tambo-interactable.test.js +192 -0
- package/dist/hoc/with-tambo-interactable.test.js.map +1 -0
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +2 -1
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/use-current-message.d.ts +51 -7
- package/dist/hooks/use-current-message.d.ts.map +1 -1
- package/dist/hooks/use-current-message.js +50 -6
- package/dist/hooks/use-current-message.js.map +1 -1
- package/dist/hooks/use-current-message.test.d.ts +2 -0
- package/dist/hooks/use-current-message.test.d.ts.map +1 -0
- package/dist/hooks/use-current-message.test.js +264 -0
- package/dist/hooks/use-current-message.test.js.map +1 -0
- package/dist/index.d.ts +10 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +2 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/mcp-hooks.d.ts +77 -6
- package/dist/mcp/mcp-hooks.d.ts.map +1 -1
- package/dist/mcp/mcp-hooks.js +104 -40
- package/dist/mcp/mcp-hooks.js.map +1 -1
- package/dist/mcp/mcp-hooks.test.js +83 -18
- package/dist/mcp/mcp-hooks.test.js.map +1 -1
- package/dist/mcp/tambo-mcp-provider.d.ts.map +1 -1
- package/dist/mcp/tambo-mcp-provider.js +2 -1
- package/dist/mcp/tambo-mcp-provider.js.map +1 -1
- package/dist/model/component-metadata.d.ts +444 -14
- package/dist/model/component-metadata.d.ts.map +1 -1
- package/dist/model/component-metadata.js.map +1 -1
- package/dist/model/generate-component-response.d.ts +12 -1
- package/dist/model/generate-component-response.d.ts.map +1 -1
- package/dist/model/generate-component-response.js.map +1 -1
- package/dist/model/resource-info.d.ts +55 -0
- package/dist/model/resource-info.d.ts.map +1 -0
- package/dist/model/resource-info.js +3 -0
- package/dist/model/resource-info.js.map +1 -0
- package/dist/providers/index.d.ts +1 -1
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/tambo-component-provider.d.ts +4 -4
- package/dist/providers/tambo-component-provider.d.ts.map +1 -1
- package/dist/providers/tambo-component-provider.js.map +1 -1
- package/dist/providers/tambo-interactable-provider-partial-updates.test.js +87 -87
- package/dist/providers/tambo-interactable-provider-partial-updates.test.js.map +1 -1
- package/dist/providers/tambo-interactable-provider.d.ts +2 -3
- package/dist/providers/tambo-interactable-provider.d.ts.map +1 -1
- package/dist/providers/tambo-interactable-provider.js +47 -41
- package/dist/providers/tambo-interactable-provider.js.map +1 -1
- package/dist/providers/tambo-interactables-additional-context-edge-cases.test.js +9 -9
- package/dist/providers/tambo-interactables-additional-context-edge-cases.test.js.map +1 -1
- package/dist/providers/tambo-interactables-additional-context.test.js +11 -11
- package/dist/providers/tambo-interactables-additional-context.test.js.map +1 -1
- package/dist/providers/tambo-registry-provider.d.ts +28 -7
- package/dist/providers/tambo-registry-provider.d.ts.map +1 -1
- package/dist/providers/tambo-registry-provider.js +70 -181
- package/dist/providers/tambo-registry-provider.js.map +1 -1
- package/dist/providers/tambo-registry-provider.test.js +152 -30
- package/dist/providers/tambo-registry-provider.test.js.map +1 -1
- package/dist/providers/tambo-registry-schema-compat.test.d.ts +2 -0
- package/dist/providers/tambo-registry-schema-compat.test.d.ts.map +1 -0
- package/dist/providers/tambo-registry-schema-compat.test.js +616 -0
- package/dist/providers/tambo-registry-schema-compat.test.js.map +1 -0
- package/dist/providers/tambo-stubs.d.ts +2 -2
- package/dist/providers/tambo-stubs.d.ts.map +1 -1
- package/dist/providers/tambo-stubs.js +5 -0
- package/dist/providers/tambo-stubs.js.map +1 -1
- package/dist/providers/tambo-thread-input-provider.d.ts +1 -0
- package/dist/providers/tambo-thread-input-provider.d.ts.map +1 -1
- package/dist/providers/tambo-thread-input-provider.js +3 -3
- package/dist/providers/tambo-thread-input-provider.js.map +1 -1
- package/dist/providers/tambo-thread-provider.d.ts.map +1 -1
- package/dist/providers/tambo-thread-provider.js.map +1 -1
- package/dist/providers/tambo-thread-provider.test.js +32 -36
- package/dist/providers/tambo-thread-provider.test.js.map +1 -1
- package/dist/schema/index.d.ts +6 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +18 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/json-schema.d.ts +35 -0
- package/dist/schema/json-schema.d.ts.map +1 -0
- package/dist/schema/json-schema.js +103 -0
- package/dist/schema/json-schema.js.map +1 -0
- package/dist/schema/schema.d.ts +66 -0
- package/dist/schema/schema.d.ts.map +1 -0
- package/dist/schema/schema.js +192 -0
- package/dist/schema/schema.js.map +1 -0
- package/dist/schema/schema.test.d.ts +2 -0
- package/dist/schema/schema.test.d.ts.map +1 -0
- package/dist/schema/schema.test.js +41 -0
- package/dist/schema/schema.test.js.map +1 -0
- package/dist/schema/standard-schema.d.ts +21 -0
- package/dist/schema/standard-schema.d.ts.map +1 -0
- package/dist/schema/standard-schema.js +37 -0
- package/dist/schema/standard-schema.js.map +1 -0
- package/dist/schema/validate.d.ts +14 -0
- package/dist/schema/validate.d.ts.map +1 -0
- package/dist/schema/validate.js +148 -0
- package/dist/schema/validate.js.map +1 -0
- package/dist/schema/validate.test.d.ts +2 -0
- package/dist/schema/validate.test.d.ts.map +1 -0
- package/dist/schema/validate.test.js +128 -0
- package/dist/schema/validate.test.js.map +1 -0
- package/dist/schema/zod.d.ts +54 -0
- package/dist/schema/zod.d.ts.map +1 -0
- package/dist/schema/zod.js +135 -0
- package/dist/schema/zod.js.map +1 -0
- package/dist/testing/tools.d.ts +29 -15
- package/dist/testing/tools.d.ts.map +1 -1
- package/dist/testing/tools.js +64 -19
- package/dist/testing/tools.js.map +1 -1
- package/dist/util/generate-component.d.ts.map +1 -1
- package/dist/util/generate-component.js +3 -3
- package/dist/util/generate-component.js.map +1 -1
- package/dist/util/mcp-server-utils.d.ts +23 -0
- package/dist/util/mcp-server-utils.d.ts.map +1 -0
- package/dist/util/mcp-server-utils.js +107 -0
- package/dist/util/mcp-server-utils.js.map +1 -0
- package/dist/util/mcp-server-utils.test.d.ts +2 -0
- package/dist/util/mcp-server-utils.test.d.ts.map +1 -0
- package/dist/util/mcp-server-utils.test.js +287 -0
- package/dist/util/mcp-server-utils.test.js.map +1 -0
- package/dist/util/message-builder.d.ts +2 -1
- package/dist/util/message-builder.d.ts.map +1 -1
- package/dist/util/message-builder.js +54 -36
- package/dist/util/message-builder.js.map +1 -1
- package/dist/util/message-builder.test.js +500 -13
- package/dist/util/message-builder.test.js.map +1 -1
- package/dist/util/registry-validators.d.ts +26 -0
- package/dist/util/registry-validators.d.ts.map +1 -0
- package/dist/util/registry-validators.js +105 -0
- package/dist/util/registry-validators.js.map +1 -0
- package/dist/util/registry-validators.test.d.ts +2 -0
- package/dist/util/registry-validators.test.d.ts.map +1 -0
- package/dist/util/registry-validators.test.js +235 -0
- package/dist/util/registry-validators.test.js.map +1 -0
- package/dist/util/registry.d.ts +35 -7
- package/dist/util/registry.d.ts.map +1 -1
- package/dist/util/registry.js +60 -77
- package/dist/util/registry.js.map +1 -1
- package/dist/util/registry.test.d.ts +2 -0
- package/dist/util/registry.test.d.ts.map +1 -0
- package/dist/util/registry.test.js +204 -0
- package/dist/util/registry.test.js.map +1 -0
- package/dist/util/resource-validators.d.ts +16 -0
- package/dist/util/resource-validators.d.ts.map +1 -0
- package/dist/util/resource-validators.js +34 -0
- package/dist/util/resource-validators.js.map +1 -0
- package/dist/util/tool-caller.d.ts +2 -2
- package/dist/util/tool-caller.d.ts.map +1 -1
- package/dist/util/tool-caller.js +12 -4
- package/dist/util/tool-caller.js.map +1 -1
- package/esm/{providers/hoc → hoc}/with-tambo-interactable.d.ts +2 -2
- package/esm/hoc/with-tambo-interactable.d.ts.map +1 -0
- package/esm/{providers/hoc → hoc}/with-tambo-interactable.js +29 -2
- package/esm/hoc/with-tambo-interactable.js.map +1 -0
- package/esm/hoc/with-tambo-interactable.test.d.ts +2 -0
- package/esm/hoc/with-tambo-interactable.test.d.ts.map +1 -0
- package/esm/hoc/with-tambo-interactable.test.js +187 -0
- package/esm/hoc/with-tambo-interactable.test.js.map +1 -0
- package/esm/hooks/index.d.ts +1 -1
- package/esm/hooks/index.d.ts.map +1 -1
- package/esm/hooks/index.js +1 -1
- package/esm/hooks/index.js.map +1 -1
- package/esm/hooks/use-current-message.d.ts +51 -7
- package/esm/hooks/use-current-message.d.ts.map +1 -1
- package/esm/hooks/use-current-message.js +48 -5
- package/esm/hooks/use-current-message.js.map +1 -1
- package/esm/hooks/use-current-message.test.d.ts +2 -0
- package/esm/hooks/use-current-message.test.d.ts.map +1 -0
- package/esm/hooks/use-current-message.test.js +259 -0
- package/esm/hooks/use-current-message.test.js.map +1 -0
- package/esm/index.d.ts +10 -8
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +4 -2
- package/esm/index.js.map +1 -1
- package/esm/mcp/index.d.ts +1 -1
- package/esm/mcp/index.d.ts.map +1 -1
- package/esm/mcp/index.js +1 -1
- package/esm/mcp/index.js.map +1 -1
- package/esm/mcp/mcp-hooks.d.ts +77 -6
- package/esm/mcp/mcp-hooks.d.ts.map +1 -1
- package/esm/mcp/mcp-hooks.js +103 -40
- package/esm/mcp/mcp-hooks.js.map +1 -1
- package/esm/mcp/mcp-hooks.test.js +84 -19
- package/esm/mcp/mcp-hooks.test.js.map +1 -1
- package/esm/mcp/tambo-mcp-provider.d.ts.map +1 -1
- package/esm/mcp/tambo-mcp-provider.js +2 -1
- package/esm/mcp/tambo-mcp-provider.js.map +1 -1
- package/esm/model/component-metadata.d.ts +444 -14
- package/esm/model/component-metadata.d.ts.map +1 -1
- package/esm/model/component-metadata.js.map +1 -1
- package/esm/model/generate-component-response.d.ts +12 -1
- package/esm/model/generate-component-response.d.ts.map +1 -1
- package/esm/model/generate-component-response.js.map +1 -1
- package/esm/model/resource-info.d.ts +55 -0
- package/esm/model/resource-info.d.ts.map +1 -0
- package/esm/model/resource-info.js +2 -0
- package/esm/model/resource-info.js.map +1 -0
- package/esm/providers/index.d.ts +1 -1
- package/esm/providers/index.d.ts.map +1 -1
- package/esm/providers/index.js.map +1 -1
- package/esm/providers/tambo-component-provider.d.ts +4 -4
- package/esm/providers/tambo-component-provider.d.ts.map +1 -1
- package/esm/providers/tambo-component-provider.js.map +1 -1
- package/esm/providers/tambo-interactable-provider-partial-updates.test.js +1 -1
- package/esm/providers/tambo-interactable-provider-partial-updates.test.js.map +1 -1
- package/esm/providers/tambo-interactable-provider.d.ts +2 -3
- package/esm/providers/tambo-interactable-provider.d.ts.map +1 -1
- package/esm/providers/tambo-interactable-provider.js +44 -38
- package/esm/providers/tambo-interactable-provider.js.map +1 -1
- package/esm/providers/tambo-interactables-additional-context-edge-cases.test.js +3 -3
- package/esm/providers/tambo-interactables-additional-context-edge-cases.test.js.map +1 -1
- package/esm/providers/tambo-interactables-additional-context.test.js +3 -3
- package/esm/providers/tambo-interactables-additional-context.test.js.map +1 -1
- package/esm/providers/tambo-registry-provider.d.ts +28 -7
- package/esm/providers/tambo-registry-provider.d.ts.map +1 -1
- package/esm/providers/tambo-registry-provider.js +67 -175
- package/esm/providers/tambo-registry-provider.js.map +1 -1
- package/esm/providers/tambo-registry-provider.test.js +148 -26
- package/esm/providers/tambo-registry-provider.test.js.map +1 -1
- package/esm/providers/tambo-registry-schema-compat.test.d.ts +2 -0
- package/esm/providers/tambo-registry-schema-compat.test.d.ts.map +1 -0
- package/esm/providers/tambo-registry-schema-compat.test.js +578 -0
- package/esm/providers/tambo-registry-schema-compat.test.js.map +1 -0
- package/esm/providers/tambo-stubs.d.ts +2 -2
- package/esm/providers/tambo-stubs.d.ts.map +1 -1
- package/esm/providers/tambo-stubs.js +5 -0
- package/esm/providers/tambo-stubs.js.map +1 -1
- package/esm/providers/tambo-thread-input-provider.d.ts +1 -0
- package/esm/providers/tambo-thread-input-provider.d.ts.map +1 -1
- package/esm/providers/tambo-thread-input-provider.js +3 -3
- package/esm/providers/tambo-thread-input-provider.js.map +1 -1
- package/esm/providers/tambo-thread-provider.d.ts.map +1 -1
- package/esm/providers/tambo-thread-provider.js.map +1 -1
- package/esm/providers/tambo-thread-provider.test.js +24 -28
- package/esm/providers/tambo-thread-provider.test.js.map +1 -1
- package/esm/schema/index.d.ts +6 -0
- package/esm/schema/index.d.ts.map +1 -0
- package/esm/schema/index.js +6 -0
- package/esm/schema/index.js.map +1 -0
- package/esm/schema/json-schema.d.ts +35 -0
- package/esm/schema/json-schema.d.ts.map +1 -0
- package/esm/schema/json-schema.js +98 -0
- package/esm/schema/json-schema.js.map +1 -0
- package/esm/schema/schema.d.ts +66 -0
- package/esm/schema/schema.d.ts.map +1 -0
- package/esm/schema/schema.js +185 -0
- package/esm/schema/schema.js.map +1 -0
- package/esm/schema/schema.test.d.ts +2 -0
- package/esm/schema/schema.test.d.ts.map +1 -0
- package/esm/schema/schema.test.js +39 -0
- package/esm/schema/schema.test.js.map +1 -0
- package/esm/schema/standard-schema.d.ts +21 -0
- package/esm/schema/standard-schema.d.ts.map +1 -0
- package/esm/schema/standard-schema.js +34 -0
- package/esm/schema/standard-schema.js.map +1 -0
- package/esm/schema/validate.d.ts +14 -0
- package/esm/schema/validate.d.ts.map +1 -0
- package/esm/schema/validate.js +145 -0
- package/esm/schema/validate.js.map +1 -0
- package/esm/schema/validate.test.d.ts +2 -0
- package/esm/schema/validate.test.d.ts.map +1 -0
- package/esm/schema/validate.test.js +126 -0
- package/esm/schema/validate.test.js.map +1 -0
- package/esm/schema/zod.d.ts +54 -0
- package/esm/schema/zod.d.ts.map +1 -0
- package/esm/schema/zod.js +124 -0
- package/esm/schema/zod.js.map +1 -0
- package/esm/testing/tools.d.ts +29 -15
- package/esm/testing/tools.d.ts.map +1 -1
- package/esm/testing/tools.js +62 -16
- package/esm/testing/tools.js.map +1 -1
- package/esm/util/generate-component.d.ts.map +1 -1
- package/esm/util/generate-component.js +3 -3
- package/esm/util/generate-component.js.map +1 -1
- package/esm/util/mcp-server-utils.d.ts +23 -0
- package/esm/util/mcp-server-utils.d.ts.map +1 -0
- package/esm/util/mcp-server-utils.js +102 -0
- package/esm/util/mcp-server-utils.js.map +1 -0
- package/esm/util/mcp-server-utils.test.d.ts +2 -0
- package/esm/util/mcp-server-utils.test.d.ts.map +1 -0
- package/esm/util/mcp-server-utils.test.js +285 -0
- package/esm/util/mcp-server-utils.test.js.map +1 -0
- package/esm/util/message-builder.d.ts +2 -1
- package/esm/util/message-builder.d.ts.map +1 -1
- package/esm/util/message-builder.js +54 -36
- package/esm/util/message-builder.js.map +1 -1
- package/esm/util/message-builder.test.js +500 -13
- package/esm/util/message-builder.test.js.map +1 -1
- package/esm/util/registry-validators.d.ts +26 -0
- package/esm/util/registry-validators.d.ts.map +1 -0
- package/esm/util/registry-validators.js +100 -0
- package/esm/util/registry-validators.js.map +1 -0
- package/esm/util/registry-validators.test.d.ts +2 -0
- package/esm/util/registry-validators.test.d.ts.map +1 -0
- package/esm/util/registry-validators.test.js +233 -0
- package/esm/util/registry-validators.test.js.map +1 -0
- package/esm/util/registry.d.ts +35 -7
- package/esm/util/registry.d.ts.map +1 -1
- package/esm/util/registry.js +57 -73
- package/esm/util/registry.js.map +1 -1
- package/esm/util/registry.test.d.ts +2 -0
- package/esm/util/registry.test.d.ts.map +1 -0
- package/esm/util/registry.test.js +169 -0
- package/esm/util/registry.test.js.map +1 -0
- package/esm/util/resource-validators.d.ts +16 -0
- package/esm/util/resource-validators.d.ts.map +1 -0
- package/esm/util/resource-validators.js +30 -0
- package/esm/util/resource-validators.js.map +1 -0
- package/esm/util/tool-caller.d.ts +2 -2
- package/esm/util/tool-caller.d.ts.map +1 -1
- package/esm/util/tool-caller.js +12 -4
- package/esm/util/tool-caller.js.map +1 -1
- package/package.json +13 -8
- package/dist/providers/hoc/with-tambo-interactable.d.ts.map +0 -1
- package/dist/providers/hoc/with-tambo-interactable.js.map +0 -1
- package/dist/util/validate-zod-schema.d.ts +0 -10
- package/dist/util/validate-zod-schema.d.ts.map +0 -1
- package/dist/util/validate-zod-schema.js +0 -100
- package/dist/util/validate-zod-schema.js.map +0 -1
- package/dist/util/validate-zod-schema.test.d.ts +0 -2
- package/dist/util/validate-zod-schema.test.d.ts.map +0 -1
- package/dist/util/validate-zod-schema.test.js +0 -96
- package/dist/util/validate-zod-schema.test.js.map +0 -1
- package/esm/providers/hoc/with-tambo-interactable.d.ts.map +0 -1
- package/esm/providers/hoc/with-tambo-interactable.js.map +0 -1
- package/esm/util/validate-zod-schema.d.ts +0 -10
- package/esm/util/validate-zod-schema.d.ts.map +0 -1
- package/esm/util/validate-zod-schema.js +0 -97
- package/esm/util/validate-zod-schema.js.map +0 -1
- package/esm/util/validate-zod-schema.test.d.ts +0 -2
- package/esm/util/validate-zod-schema.test.d.ts.map +0 -1
- package/esm/util/validate-zod-schema.test.js +0 -94
- package/esm/util/validate-zod-schema.test.js.map +0 -1
package/dist/mcp/mcp-hooks.d.ts
CHANGED
|
@@ -7,16 +7,65 @@ export interface ListPromptEntry {
|
|
|
7
7
|
prompt: ListPromptItem;
|
|
8
8
|
}
|
|
9
9
|
export type ListResourceItem = ListResourcesResult["resources"][number];
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Registry resource entry - resources from the local registry (not MCP servers).
|
|
12
|
+
*
|
|
13
|
+
* These entries always have `server === null` and represent resources that
|
|
14
|
+
* are registered locally via `TamboRegistryProvider` (static `resources`
|
|
15
|
+
* props or dynamic `ResourceSource` functions).
|
|
16
|
+
*/
|
|
17
|
+
export interface RegistryResourceEntry {
|
|
18
|
+
server: null;
|
|
19
|
+
resource: ListResourceItem;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* MCP server resource entry - resources from connected MCP servers.
|
|
23
|
+
*
|
|
24
|
+
* These entries always have a non-null `server` with connection metadata and
|
|
25
|
+
* are produced by the active MCP clients managed by `TamboMcpProvider`.
|
|
26
|
+
*/
|
|
27
|
+
export interface McpResourceEntry {
|
|
11
28
|
server: ConnectedMcpServer;
|
|
12
29
|
resource: ListResourceItem;
|
|
13
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Union type for all resource entries returned by `useTamboMcpResourceList`.
|
|
33
|
+
*
|
|
34
|
+
* - Registry resources have `server === null`.
|
|
35
|
+
* - MCP-backed resources have a non-null `server` with connection metadata.
|
|
36
|
+
*/
|
|
37
|
+
export type ListResourceEntry = RegistryResourceEntry | McpResourceEntry;
|
|
38
|
+
/**
|
|
39
|
+
* Type guard for narrowing a `ListResourceEntry` to an MCP-backed resource
|
|
40
|
+
* (entries where `server` is non-null).
|
|
41
|
+
*/
|
|
42
|
+
export declare function isMcpResourceEntry(entry: ListResourceEntry): entry is McpResourceEntry;
|
|
14
43
|
/**
|
|
15
44
|
* Hook to get the prompts for all the registered MCP servers.
|
|
16
45
|
* @returns The prompts for the MCP servers, including the server that the prompt was found on.
|
|
17
46
|
*/
|
|
18
47
|
export declare function useTamboMcpPromptList(): {
|
|
19
|
-
data:
|
|
48
|
+
data: {
|
|
49
|
+
prompt: {
|
|
50
|
+
name: string;
|
|
51
|
+
description?: string | undefined;
|
|
52
|
+
arguments?: {
|
|
53
|
+
name: string;
|
|
54
|
+
description?: string | undefined;
|
|
55
|
+
required?: boolean | undefined;
|
|
56
|
+
}[] | undefined;
|
|
57
|
+
_meta?: {
|
|
58
|
+
[x: string]: unknown;
|
|
59
|
+
} | undefined;
|
|
60
|
+
icons?: {
|
|
61
|
+
src: string;
|
|
62
|
+
mimeType?: string | undefined;
|
|
63
|
+
sizes?: string[] | undefined;
|
|
64
|
+
}[] | undefined;
|
|
65
|
+
title?: string | undefined;
|
|
66
|
+
};
|
|
67
|
+
server: ConnectedMcpServer;
|
|
68
|
+
}[];
|
|
20
69
|
error: Error | null;
|
|
21
70
|
errors: Error[];
|
|
22
71
|
isPending: boolean;
|
|
@@ -130,11 +179,33 @@ export declare function useTamboMcpPrompt(promptName: string | undefined, args?:
|
|
|
130
179
|
description?: string | undefined;
|
|
131
180
|
} | null, Error>;
|
|
132
181
|
/**
|
|
133
|
-
* Hook to get the resources for all the registered MCP servers.
|
|
134
|
-
* @returns The resources
|
|
182
|
+
* Hook to get the resources for all the registered MCP servers and registry.
|
|
183
|
+
* @returns The resources from MCP servers and the local registry, including the server that the resource was found on (null for registry resources).
|
|
135
184
|
*/
|
|
136
185
|
export declare function useTamboMcpResourceList(): {
|
|
137
|
-
data:
|
|
186
|
+
data: (RegistryResourceEntry | {
|
|
187
|
+
resource: {
|
|
188
|
+
uri: string;
|
|
189
|
+
name: string;
|
|
190
|
+
description?: string | undefined;
|
|
191
|
+
mimeType?: string | undefined;
|
|
192
|
+
annotations?: {
|
|
193
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
194
|
+
priority?: number | undefined;
|
|
195
|
+
lastModified?: string | undefined;
|
|
196
|
+
} | undefined;
|
|
197
|
+
_meta?: {
|
|
198
|
+
[x: string]: unknown;
|
|
199
|
+
} | undefined;
|
|
200
|
+
icons?: {
|
|
201
|
+
src: string;
|
|
202
|
+
mimeType?: string | undefined;
|
|
203
|
+
sizes?: string[] | undefined;
|
|
204
|
+
}[] | undefined;
|
|
205
|
+
title?: string | undefined;
|
|
206
|
+
};
|
|
207
|
+
server: ConnectedMcpServer;
|
|
208
|
+
})[];
|
|
138
209
|
error: Error | null;
|
|
139
210
|
errors: Error[];
|
|
140
211
|
isPending: boolean;
|
|
@@ -148,7 +219,7 @@ export declare function useTamboMcpResourceList(): {
|
|
|
148
219
|
};
|
|
149
220
|
/**
|
|
150
221
|
* Hook to get the resource for the specified URI.
|
|
151
|
-
* @param resourceUri - The URI of the resource to get. Can be prefixed with serverKey (e.g., "linear:file://foo") or unprefixed.
|
|
222
|
+
* @param resourceUri - The URI of the resource to get. Can be prefixed with serverKey (e.g., "linear:file://foo") for MCP resources, or unprefixed for registry resources.
|
|
152
223
|
* @returns The resource for the specified URI.
|
|
153
224
|
*/
|
|
154
225
|
export declare function useTamboMcpResource(resourceUri: string | undefined): UseQueryResult<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-hooks.d.ts","sourceRoot":"","sources":["../../src/mcp/mcp-hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EAEzB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"mcp-hooks.d.ts","sourceRoot":"","sources":["../../src/mcp/mcp-hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EAEzB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGvD,OAAO,EACL,KAAK,kBAAkB,EAGxB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,MAAM,cAAc,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;AAClE,MAAM,WAAW,eAAe;IAE9B,MAAM,EAAE,kBAAkB,CAAC;IAC3B,MAAM,EAAE,cAAc,CAAC;CACxB;AAED,MAAM,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAExE;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,IAAI,CAAC;IACb,QAAQ,EAAE,gBAAgB,CAAC;CAC5B;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,kBAAkB,CAAC;IAC3B,QAAQ,EAAE,gBAAgB,CAAC;CAC5B;AAED;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG,qBAAqB,GAAG,gBAAgB,CAAC;AAEzE;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,iBAAiB,GACvB,KAAK,IAAI,gBAAgB,CAE3B;AAED;;;GAGG;AACH,wBAAgB,qBAAqB;;;;;;;;;;;;;;;;;;;;gBAnD3B,kBAAkB;;WAgGnB,KAAK,GAAG,IAAI;YACX,KAAK,EAAE;eACJ,OAAO;eACP,OAAO;aACT,OAAO;cACN,OAAO;kBACH,OAAO;gBACT,OAAO;eACR,OAAO;aACT,MAAM,OAAO,CAAC,IAAI,CAAC;EAb7B;AAwDD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA0ClC;AAED;;;GAGG;AACH,wBAAgB,uBAAuB;;;;;;;;;;;;;;;;;;;;;;gBAnL7B,kBAAkB;;WAuEnB,KAAK,GAAG,IAAI;YACX,KAAK,EAAE;eACJ,OAAO;eACP,OAAO;aACT,OAAO;cACN,OAAO;kBACH,OAAO;gBACT,OAAO;eACR,OAAO;aACT,MAAM,OAAO,CAAC,IAAI,CAAC;EA6L7B;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS;;;;;;;;;;;;;;;;;;;;;;;;iBAmElE"}
|
package/dist/mcp/mcp-hooks.js
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isMcpResourceEntry = isMcpResourceEntry;
|
|
3
4
|
exports.useTamboMcpPromptList = useTamboMcpPromptList;
|
|
4
5
|
exports.useTamboMcpPrompt = useTamboMcpPrompt;
|
|
5
6
|
exports.useTamboMcpResourceList = useTamboMcpResourceList;
|
|
6
7
|
exports.useTamboMcpResource = useTamboMcpResource;
|
|
7
8
|
const hooks_1 = require("../hooks");
|
|
9
|
+
const tambo_registry_provider_1 = require("../providers/tambo-registry-provider");
|
|
8
10
|
const tambo_mcp_provider_1 = require("./tambo-mcp-provider");
|
|
11
|
+
/**
|
|
12
|
+
* Type guard for narrowing a `ListResourceEntry` to an MCP-backed resource
|
|
13
|
+
* (entries where `server` is non-null).
|
|
14
|
+
*/
|
|
15
|
+
function isMcpResourceEntry(entry) {
|
|
16
|
+
return entry.server !== null && isConnectedMcpServer(entry.server);
|
|
17
|
+
}
|
|
9
18
|
/**
|
|
10
19
|
* Hook to get the prompts for all the registered MCP servers.
|
|
11
20
|
* @returns The prompts for the MCP servers, including the server that the prompt was found on.
|
|
@@ -33,12 +42,8 @@ function useTamboMcpPromptList() {
|
|
|
33
42
|
})),
|
|
34
43
|
combine: (results) => {
|
|
35
44
|
const combined = combineArrayResults(results);
|
|
36
|
-
//
|
|
37
|
-
|
|
38
|
-
if (!shouldPrefix) {
|
|
39
|
-
return combined;
|
|
40
|
-
}
|
|
41
|
-
// Apply prefixes to all prompts
|
|
45
|
+
// Always apply serverKey prefix to MCP prompts (breaking change for consistency with resources)
|
|
46
|
+
// This ensures clear separation between local and remote prompts
|
|
42
47
|
return {
|
|
43
48
|
...combined,
|
|
44
49
|
data: combined.data.map((entry) => ({
|
|
@@ -126,13 +131,16 @@ function useTamboMcpPrompt(promptName, args = {}) {
|
|
|
126
131
|
});
|
|
127
132
|
}
|
|
128
133
|
/**
|
|
129
|
-
* Hook to get the resources for all the registered MCP servers.
|
|
130
|
-
* @returns The resources
|
|
134
|
+
* Hook to get the resources for all the registered MCP servers and registry.
|
|
135
|
+
* @returns The resources from MCP servers and the local registry, including the server that the resource was found on (null for registry resources).
|
|
131
136
|
*/
|
|
132
137
|
function useTamboMcpResourceList() {
|
|
133
138
|
const mcpServers = (0, tambo_mcp_provider_1.useTamboMcpServers)();
|
|
134
|
-
const
|
|
135
|
-
|
|
139
|
+
const { resources: staticResources, resourceSource } = (0, tambo_registry_provider_1.useTamboRegistry)();
|
|
140
|
+
// Build list of queries: MCP servers + optional dynamic resource source
|
|
141
|
+
const queriesToRun = [
|
|
142
|
+
// MCP server queries
|
|
143
|
+
...mcpServers.map((mcpServer) => ({
|
|
136
144
|
queryKey: ["mcp-resources", mcpServer.key],
|
|
137
145
|
// Only run for connected servers that have a client
|
|
138
146
|
enabled: isConnectedMcpServer(mcpServer),
|
|
@@ -150,23 +158,56 @@ function useTamboMcpResourceList() {
|
|
|
150
158
|
return resourceEntries;
|
|
151
159
|
},
|
|
152
160
|
})),
|
|
161
|
+
// Dynamic resource source query (if exists)
|
|
162
|
+
...(resourceSource
|
|
163
|
+
? [
|
|
164
|
+
{
|
|
165
|
+
queryKey: ["registry-resources", "dynamic"],
|
|
166
|
+
enabled: true,
|
|
167
|
+
queryFn: async () => {
|
|
168
|
+
if (!resourceSource)
|
|
169
|
+
return [];
|
|
170
|
+
const resources = await resourceSource.listResources();
|
|
171
|
+
return resources.map((resource) => ({
|
|
172
|
+
server: null,
|
|
173
|
+
resource,
|
|
174
|
+
}));
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
]
|
|
178
|
+
: []),
|
|
179
|
+
];
|
|
180
|
+
const queries = (0, hooks_1.useTamboQueries)({
|
|
181
|
+
queries: queriesToRun,
|
|
153
182
|
combine: (results) => {
|
|
183
|
+
// Type assertion needed because queries can return different entry types
|
|
154
184
|
const combined = combineArrayResults(results);
|
|
155
|
-
//
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
160
|
-
//
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
185
|
+
// Add static registry resources (no query needed)
|
|
186
|
+
const staticEntries = staticResources.map((resource) => ({
|
|
187
|
+
server: null,
|
|
188
|
+
resource,
|
|
189
|
+
}));
|
|
190
|
+
// Merge static resources with query results (registry resources first)
|
|
191
|
+
const allData = [...staticEntries, ...combined.data];
|
|
192
|
+
// Apply serverKey prefix to ALL MCP resources (breaking change)
|
|
193
|
+
// Registry resources (server: null) are never prefixed
|
|
194
|
+
const prefixedData = allData.map((entry) => {
|
|
195
|
+
if (entry.server === null) {
|
|
196
|
+
// Registry resource - no prefix
|
|
197
|
+
return entry;
|
|
198
|
+
}
|
|
199
|
+
// MCP resource - always prefix with serverKey
|
|
200
|
+
return {
|
|
164
201
|
...entry,
|
|
165
202
|
resource: {
|
|
166
203
|
...entry.resource,
|
|
167
204
|
uri: `${entry.server.serverKey}:${entry.resource.uri}`,
|
|
168
205
|
},
|
|
169
|
-
}
|
|
206
|
+
};
|
|
207
|
+
});
|
|
208
|
+
return {
|
|
209
|
+
...combined,
|
|
210
|
+
data: prefixedData,
|
|
170
211
|
};
|
|
171
212
|
},
|
|
172
213
|
});
|
|
@@ -174,36 +215,59 @@ function useTamboMcpResourceList() {
|
|
|
174
215
|
}
|
|
175
216
|
/**
|
|
176
217
|
* Hook to get the resource for the specified URI.
|
|
177
|
-
* @param resourceUri - The URI of the resource to get. Can be prefixed with serverKey (e.g., "linear:file://foo") or unprefixed.
|
|
218
|
+
* @param resourceUri - The URI of the resource to get. Can be prefixed with serverKey (e.g., "linear:file://foo") for MCP resources, or unprefixed for registry resources.
|
|
178
219
|
* @returns The resource for the specified URI.
|
|
179
220
|
*/
|
|
180
221
|
function useTamboMcpResource(resourceUri) {
|
|
181
|
-
|
|
222
|
+
const { resourceSource } = (0, tambo_registry_provider_1.useTamboRegistry)();
|
|
182
223
|
const { data: resourceEntries } = useTamboMcpResourceList();
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
//
|
|
186
|
-
const
|
|
224
|
+
// Find which server/source has the resource
|
|
225
|
+
const resourceEntry = resourceEntries?.find((entry) => entry.resource.uri === resourceUri);
|
|
226
|
+
// Determine if this is a known registry resource or MCP resource
|
|
227
|
+
const isKnownEntry = resourceEntry != null;
|
|
228
|
+
const isRegistryResource = isKnownEntry && resourceEntry.server === null;
|
|
229
|
+
const mcpServer = isKnownEntry && resourceEntry.server != null ? resourceEntry.server : null;
|
|
187
230
|
// Strip the prefix to get the original resource URI for the MCP server call
|
|
188
|
-
// Only strip if we found a matching resource entry with
|
|
189
|
-
const originalResourceUri =
|
|
190
|
-
? resourceUri?.replace(`${
|
|
231
|
+
// Only strip if we found a matching resource entry with an MCP server
|
|
232
|
+
const originalResourceUri = isKnownEntry && mcpServer
|
|
233
|
+
? resourceUri?.replace(`${mcpServer.serverKey}:`, "")
|
|
191
234
|
: resourceUri;
|
|
235
|
+
// Check if we can fetch this resource. Registry resources can always be
|
|
236
|
+
// fetched when a resourceSource exists, even if they haven't appeared in a
|
|
237
|
+
// previous listResources result.
|
|
238
|
+
const hasRegistrySource = resourceSource != null;
|
|
239
|
+
const hasConnectedMcpServer = isKnownEntry && mcpServer != null && isConnectedMcpServer(mcpServer);
|
|
240
|
+
const canFetchResource = Boolean(resourceUri && (hasRegistrySource || hasConnectedMcpServer));
|
|
241
|
+
let locationKey;
|
|
242
|
+
if (isRegistryResource || (!isKnownEntry && hasRegistrySource)) {
|
|
243
|
+
locationKey = "registry";
|
|
244
|
+
}
|
|
245
|
+
else if (mcpServer) {
|
|
246
|
+
locationKey = mcpServer.key;
|
|
247
|
+
}
|
|
192
248
|
return (0, hooks_1.useTamboQuery)({
|
|
193
|
-
// Include server identity to prevent stale cache hits
|
|
194
|
-
queryKey: ["
|
|
195
|
-
|
|
196
|
-
enabled: Boolean(resourceUri && mcpServer && isConnectedMcpServer(mcpServer)),
|
|
249
|
+
// Include server identity or "registry" to prevent stale cache hits
|
|
250
|
+
queryKey: ["resource", resourceUri, locationKey],
|
|
251
|
+
enabled: canFetchResource,
|
|
197
252
|
queryFn: async () => {
|
|
198
|
-
if (!originalResourceUri
|
|
199
|
-
!mcpServer ||
|
|
200
|
-
!isConnectedMcpServer(mcpServer)) {
|
|
253
|
+
if (!originalResourceUri) {
|
|
201
254
|
return null;
|
|
202
255
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
256
|
+
// Registry resource: use resourceSource.getResource
|
|
257
|
+
// If this is not a known entry but we have a resourceSource, treat it as
|
|
258
|
+
// a registry resource by default.
|
|
259
|
+
if (resourceSource && (!isKnownEntry || isRegistryResource)) {
|
|
260
|
+
const result = await resourceSource.getResource(originalResourceUri);
|
|
261
|
+
return result ?? null;
|
|
262
|
+
}
|
|
263
|
+
// MCP resource: use MCP client
|
|
264
|
+
if (mcpServer && isConnectedMcpServer(mcpServer)) {
|
|
265
|
+
const result = await mcpServer.client.client.readResource({
|
|
266
|
+
uri: originalResourceUri,
|
|
267
|
+
});
|
|
268
|
+
return result ?? null;
|
|
269
|
+
}
|
|
270
|
+
return null;
|
|
207
271
|
},
|
|
208
272
|
});
|
|
209
273
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-hooks.js","sourceRoot":"","sources":["../../src/mcp/mcp-hooks.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n GetPromptResult,\n type ListPromptsResult,\n type ListResourcesResult,\n type ReadResourceResult,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { UseQueryResult } from \"@tanstack/react-query\";\nimport { useTamboQueries, useTamboQuery } from \"../hooks\";\nimport {\n type ConnectedMcpServer,\n type McpServer,\n useTamboMcpServers,\n} from \"./tambo-mcp-provider\";\n\nexport type ListPromptItem = ListPromptsResult[\"prompts\"][number];\nexport interface ListPromptEntry {\n // Only connected servers produce prompt entries, so expose the connected type\n server: ConnectedMcpServer;\n prompt: ListPromptItem;\n}\n\nexport type ListResourceItem = ListResourcesResult[\"resources\"][number];\nexport interface ListResourceEntry {\n // Only connected servers produce resource entries, so expose the connected type\n server: ConnectedMcpServer;\n resource: ListResourceItem;\n}\n\n/**\n * Hook to get the prompts for all the registered MCP servers.\n * @returns The prompts for the MCP servers, including the server that the prompt was found on.\n */\nexport function useTamboMcpPromptList() {\n const mcpServers = useTamboMcpServers();\n\n const queries = useTamboQueries({\n queries: mcpServers.map((mcpServer) => ({\n queryKey: [\"mcp-prompts\", mcpServer.key],\n // Only run for connected servers that have a client\n enabled: isConnectedMcpServer(mcpServer),\n queryFn: async (): Promise<ListPromptEntry[]> => {\n // Fast path: if this server doesn't have a client, skip work\n if (!isConnectedMcpServer(mcpServer)) return [];\n\n const result = await mcpServer.client.client.listPrompts();\n const prompts: ListPromptItem[] = result?.prompts ?? [];\n // Return prompts without prefixes - we'll apply prefixing in combine\n const promptsEntries = prompts.map((prompt) => ({\n server: mcpServer,\n prompt,\n }));\n return promptsEntries;\n },\n })),\n combine: (results) => {\n const combined = combineArrayResults(results);\n // Apply prefixing based on current server count\n const shouldPrefix = mcpServers.length > 1;\n if (!shouldPrefix) {\n return combined;\n }\n\n // Apply prefixes to all prompts\n return {\n ...combined,\n data: combined.data.map((entry) => ({\n ...entry,\n prompt: {\n ...entry.prompt,\n name: `${entry.server.serverKey}:${entry.prompt.name}`,\n },\n })),\n };\n },\n });\n\n return queries;\n}\n// TODO: find a more general place for this\nfunction combineArrayResults<T>(results: UseQueryResult<T[]>[]): {\n data: T[];\n error: Error | null;\n errors: Error[];\n isPending: boolean;\n isSuccess: boolean;\n isError: boolean;\n isPaused: boolean;\n isRefetching: boolean;\n isFetching: boolean;\n isLoading: boolean;\n refetch: () => Promise<void>;\n} {\n const errors = results\n .filter((result) => result.isError)\n .map((result) => result.error);\n\n // Treat queries that are idle (disabled) as non-blocking for aggregate status\n const enabledish = results.filter(\n (r) => r.fetchStatus !== \"idle\" || r.isSuccess || r.isError,\n );\n\n return {\n // Prefer flatMap to avoid extra intermediate arrays\n data: results.flatMap((result) =>\n result.isSuccess && Array.isArray(result.data) ? result.data : [],\n ),\n // Preserve a single error for compatibility and expose the full list for diagnostics\n error: errors[0] ?? null,\n errors,\n isPending: enabledish.some((result) => result.isPending),\n isSuccess:\n enabledish.length > 0 && enabledish.every((result) => result.isSuccess),\n isError: errors.length > 0,\n isPaused: enabledish.some((result) => result.isPaused),\n isRefetching: enabledish.some((result) => result.isRefetching),\n isFetching: enabledish.some((result) => result.isFetching),\n isLoading: enabledish.some((result) => result.isLoading),\n // Aggregate refetch to trigger all underlying queries\n refetch: async () => {\n await Promise.all(\n results.map(async (r) => {\n await r.refetch();\n }),\n );\n },\n };\n}\n\n// Type guard for narrowing to connected servers\nfunction isConnectedMcpServer(server: McpServer): server is ConnectedMcpServer {\n return \"client\" in server && server.client != null;\n}\n\n/**\n * Hook to get the prompt for the specified name.\n * @param promptName - The name of the prompt to get. Can be prefixed with serverKey (e.g., \"linear:issue\") or unprefixed.\n * @param args - The arguments to pass to the prompt.\n * @returns The prompt for the specified name.\n */\nexport function useTamboMcpPrompt(\n promptName: string | undefined,\n args: Record<string, string> = {},\n) {\n // figure out which server has the prompt\n const { data: promptEntries } = useTamboMcpPromptList();\n const promptEntry = promptEntries?.find(\n (prompt) => prompt.prompt.name === promptName,\n );\n // Use the stable server key (and the server instance itself) instead of brittle\n // name/url/transport matching.\n const mcpServer = promptEntry?.server;\n\n // Strip the prefix to get the original prompt name for the MCP server call\n const originalPromptName = promptName?.includes(\":\")\n ? promptName.split(\":\").slice(1).join(\":\")\n : promptName;\n\n // Canonicalize args to avoid unstable cache keys from object identity/order\n const sortedArgsEntries = Object.keys(args)\n .sort()\n .map((k) => [k, args[k]] as const);\n return useTamboQuery({\n // Include server identity and sorted args to prevent stale cache hits\n queryKey: [\"mcp-prompt\", promptName, mcpServer?.key, sortedArgsEntries],\n // Only run when we have a prompt name and a connected server\n enabled: Boolean(\n promptName && mcpServer && isConnectedMcpServer(mcpServer),\n ),\n queryFn: async (): Promise<GetPromptResult | null> => {\n if (\n !originalPromptName ||\n !mcpServer ||\n !isConnectedMcpServer(mcpServer)\n ) {\n return null;\n }\n const result = await mcpServer.client.client.getPrompt({\n name: originalPromptName,\n arguments: args,\n });\n return result ?? null; // return null because react-query doesn't like undefined results\n },\n });\n}\n\n/**\n * Hook to get the resources for all the registered MCP servers.\n * @returns The resources for the MCP servers, including the server that the resource was found on.\n */\nexport function useTamboMcpResourceList() {\n const mcpServers = useTamboMcpServers();\n\n const queries = useTamboQueries({\n queries: mcpServers.map((mcpServer) => ({\n queryKey: [\"mcp-resources\", mcpServer.key],\n // Only run for connected servers that have a client\n enabled: isConnectedMcpServer(mcpServer),\n queryFn: async (): Promise<ListResourceEntry[]> => {\n // Fast path: if this server doesn't have a client, skip work\n if (!isConnectedMcpServer(mcpServer)) return [];\n\n const result = await mcpServer.client.client.listResources();\n const resources: ListResourceItem[] = result?.resources ?? [];\n // Return resources without prefixes - we'll apply prefixing in combine\n const resourceEntries = resources.map((resource) => ({\n server: mcpServer,\n resource,\n }));\n return resourceEntries;\n },\n })),\n combine: (results) => {\n const combined = combineArrayResults(results);\n // Apply prefixing based on current server count\n const shouldPrefix = mcpServers.length > 1;\n if (!shouldPrefix) {\n return combined;\n }\n\n // Apply prefixes to all resources\n return {\n ...combined,\n data: combined.data.map((entry) => ({\n ...entry,\n resource: {\n ...entry.resource,\n uri: `${entry.server.serverKey}:${entry.resource.uri}`,\n },\n })),\n };\n },\n });\n\n return queries;\n}\n\n/**\n * Hook to get the resource for the specified URI.\n * @param resourceUri - The URI of the resource to get. Can be prefixed with serverKey (e.g., \"linear:file://foo\") or unprefixed.\n * @returns The resource for the specified URI.\n */\nexport function useTamboMcpResource(resourceUri: string | undefined) {\n // figure out which server has the resource\n const { data: resourceEntries } = useTamboMcpResourceList();\n const resourceEntry = resourceEntries?.find(\n (resource) => resource.resource.uri === resourceUri,\n );\n // Use the stable server key (and the server instance itself) instead of brittle\n // name/url/transport matching.\n const mcpServer = resourceEntry?.server;\n\n // Strip the prefix to get the original resource URI for the MCP server call\n // Only strip if we found a matching resource entry with a server\n const originalResourceUri = resourceEntry\n ? resourceUri?.replace(`${resourceEntry.server.serverKey}:`, \"\")\n : resourceUri;\n\n return useTamboQuery({\n // Include server identity to prevent stale cache hits\n queryKey: [\"mcp-resource\", resourceUri, mcpServer?.key],\n // Only run when we have a resource URI and a connected server\n enabled: Boolean(\n resourceUri && mcpServer && isConnectedMcpServer(mcpServer),\n ),\n queryFn: async (): Promise<ReadResourceResult | null> => {\n if (\n !originalResourceUri ||\n !mcpServer ||\n !isConnectedMcpServer(mcpServer)\n ) {\n return null;\n }\n const result = await mcpServer.client.client.readResource({\n uri: originalResourceUri,\n });\n return result ?? null; // return null because react-query doesn't like undefined results\n },\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"mcp-hooks.js","sourceRoot":"","sources":["../../src/mcp/mcp-hooks.ts"],"names":[],"mappings":";;AA2DA,gDAIC;AAMD,sDAyCC;AA8DD,8CA4CC;AAMD,0DA0FC;AAOD,kDAmEC;AA3XD,oCAA0D;AAC1D,kFAAwE;AACxE,6DAI8B;AA0C9B;;;GAGG;AACH,SAAgB,kBAAkB,CAChC,KAAwB;IAExB,OAAO,KAAK,CAAC,MAAM,KAAK,IAAI,IAAI,oBAAoB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AACrE,CAAC;AAED;;;GAGG;AACH,SAAgB,qBAAqB;IACnC,MAAM,UAAU,GAAG,IAAA,uCAAkB,GAAE,CAAC;IAExC,MAAM,OAAO,GAAG,IAAA,uBAAe,EAAC;QAC9B,OAAO,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YACtC,QAAQ,EAAE,CAAC,aAAa,EAAE,SAAS,CAAC,GAAG,CAAC;YACxC,oDAAoD;YACpD,OAAO,EAAE,oBAAoB,CAAC,SAAS,CAAC;YACxC,OAAO,EAAE,KAAK,IAAgC,EAAE;gBAC9C,6DAA6D;gBAC7D,IAAI,CAAC,oBAAoB,CAAC,SAAS,CAAC;oBAAE,OAAO,EAAE,CAAC;gBAEhD,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;gBAC3D,MAAM,OAAO,GAAqB,MAAM,EAAE,OAAO,IAAI,EAAE,CAAC;gBACxD,qEAAqE;gBACrE,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;oBAC9C,MAAM,EAAE,SAAS;oBACjB,MAAM;iBACP,CAAC,CAAC,CAAC;gBACJ,OAAO,cAAc,CAAC;YACxB,CAAC;SACF,CAAC,CAAC;QACH,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE;YACnB,MAAM,QAAQ,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;YAE9C,gGAAgG;YAChG,iEAAiE;YACjE,OAAO;gBACL,GAAG,QAAQ;gBACX,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;oBAClC,GAAG,KAAK;oBACR,MAAM,EAAE;wBACN,GAAG,KAAK,CAAC,MAAM;wBACf,IAAI,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,SAAS,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE;qBACvD;iBACF,CAAC,CAAC;aACJ,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC;AACjB,CAAC;AACD,2CAA2C;AAC3C,SAAS,mBAAmB,CAAI,OAA8B;IAa5D,MAAM,MAAM,GAAG,OAAO;SACnB,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC;SAClC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAEjC,8EAA8E;IAC9E,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAC/B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,MAAM,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,OAAO,CAC5D,CAAC;IAEF,OAAO;QACL,oDAAoD;QACpD,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAC/B,MAAM,CAAC,SAAS,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAClE;QACD,qFAAqF;QACrF,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI;QACxB,MAAM;QACN,SAAS,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC;QACxD,SAAS,EACP,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC;QACzE,OAAO,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC;QAC1B,QAAQ,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC;QACtD,YAAY,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC;QAC9D,UAAU,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC;QAC1D,SAAS,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC;QACxD,sDAAsD;QACtD,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,MAAM,OAAO,CAAC,GAAG,CACf,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;gBACtB,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC;YACpB,CAAC,CAAC,CACH,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AAED,gDAAgD;AAChD,SAAS,oBAAoB,CAAC,MAAiB;IAC7C,OAAO,QAAQ,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC;AACrD,CAAC;AAED;;;;;GAKG;AACH,SAAgB,iBAAiB,CAC/B,UAA8B,EAC9B,OAA+B,EAAE;IAEjC,yCAAyC;IACzC,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,qBAAqB,EAAE,CAAC;IACxD,MAAM,WAAW,GAAG,aAAa,EAAE,IAAI,CACrC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,UAAU,CAC9C,CAAC;IACF,gFAAgF;IAChF,+BAA+B;IAC/B,MAAM,SAAS,GAAG,WAAW,EAAE,MAAM,CAAC;IAEtC,2EAA2E;IAC3E,MAAM,kBAAkB,GAAG,UAAU,EAAE,QAAQ,CAAC,GAAG,CAAC;QAClD,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QAC1C,CAAC,CAAC,UAAU,CAAC;IAEf,4EAA4E;IAC5E,MAAM,iBAAiB,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;SACxC,IAAI,EAAE;SACN,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAU,CAAC,CAAC;IACrC,OAAO,IAAA,qBAAa,EAAC;QACnB,sEAAsE;QACtE,QAAQ,EAAE,CAAC,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,EAAE,iBAAiB,CAAC;QACvE,6DAA6D;QAC7D,OAAO,EAAE,OAAO,CACd,UAAU,IAAI,SAAS,IAAI,oBAAoB,CAAC,SAAS,CAAC,CAC3D;QACD,OAAO,EAAE,KAAK,IAAqC,EAAE;YACnD,IACE,CAAC,kBAAkB;gBACnB,CAAC,SAAS;gBACV,CAAC,oBAAoB,CAAC,SAAS,CAAC,EAChC,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC;gBACrD,IAAI,EAAE,kBAAkB;gBACxB,SAAS,EAAE,IAAI;aAChB,CAAC,CAAC;YACH,OAAO,MAAM,IAAI,IAAI,CAAC,CAAC,iEAAiE;QAC1F,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,SAAgB,uBAAuB;IACrC,MAAM,UAAU,GAAG,IAAA,uCAAkB,GAAE,CAAC;IACxC,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,cAAc,EAAE,GAAG,IAAA,0CAAgB,GAAE,CAAC;IAE1E,wEAAwE;IACxE,MAAM,YAAY,GAAG;QACnB,qBAAqB;QACrB,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YAChC,QAAQ,EAAE,CAAC,eAAe,EAAE,SAAS,CAAC,GAAG,CAAC;YAC1C,oDAAoD;YACpD,OAAO,EAAE,oBAAoB,CAAC,SAAS,CAAC;YACxC,OAAO,EAAE,KAAK,IAAiC,EAAE;gBAC/C,6DAA6D;gBAC7D,IAAI,CAAC,oBAAoB,CAAC,SAAS,CAAC;oBAAE,OAAO,EAAE,CAAC;gBAEhD,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;gBAC7D,MAAM,SAAS,GAAuB,MAAM,EAAE,SAAS,IAAI,EAAE,CAAC;gBAC9D,uEAAuE;gBACvE,MAAM,eAAe,GAAuB,SAAS,CAAC,GAAG,CACvD,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;oBACb,MAAM,EAAE,SAAS;oBACjB,QAAQ;iBACT,CAAC,CACH,CAAC;gBACF,OAAO,eAAe,CAAC;YACzB,CAAC;SACF,CAAC,CAAC;QACH,4CAA4C;QAC5C,GAAG,CAAC,cAAc;YAChB,CAAC,CAAC;gBACE;oBACE,QAAQ,EAAE,CAAC,oBAAoB,EAAE,SAAS,CAAC;oBAC3C,OAAO,EAAE,IAAI;oBACb,OAAO,EAAE,KAAK,IAAsC,EAAE;wBACpD,IAAI,CAAC,cAAc;4BAAE,OAAO,EAAE,CAAC;wBAC/B,MAAM,SAAS,GAAG,MAAM,cAAc,CAAC,aAAa,EAAE,CAAC;wBACvD,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;4BAClC,MAAM,EAAE,IAAI;4BACZ,QAAQ;yBACT,CAAC,CAAC,CAAC;oBACN,CAAC;iBACF;aACF;YACH,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;IAEF,MAAM,OAAO,GAAG,IAAA,uBAAe,EAAC;QAC9B,OAAO,EAAE,YAAY;QACrB,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE;YACnB,yEAAyE;YACzE,MAAM,QAAQ,GAAG,mBAAmB,CAClC,OAAgD,CACjD,CAAC;YAEF,kDAAkD;YAClD,MAAM,aAAa,GAA4B,eAAe,CAAC,GAAG,CAChE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;gBACb,MAAM,EAAE,IAAI;gBACZ,QAAQ;aACT,CAAC,CACH,CAAC;YAEF,uEAAuE;YACvE,MAAM,OAAO,GAAG,CAAC,GAAG,aAAa,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YAErD,gEAAgE;YAChE,uDAAuD;YACvD,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;gBACzC,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;oBAC1B,gCAAgC;oBAChC,OAAO,KAAK,CAAC;gBACf,CAAC;gBACD,8CAA8C;gBAC9C,OAAO;oBACL,GAAG,KAAK;oBACR,QAAQ,EAAE;wBACR,GAAG,KAAK,CAAC,QAAQ;wBACjB,GAAG,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,SAAS,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE;qBACvD;iBACF,CAAC;YACJ,CAAC,CAAC,CAAC;YAEH,OAAO;gBACL,GAAG,QAAQ;gBACX,IAAI,EAAE,YAAY;aACnB,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,SAAgB,mBAAmB,CAAC,WAA+B;IACjE,MAAM,EAAE,cAAc,EAAE,GAAG,IAAA,0CAAgB,GAAE,CAAC;IAC9C,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,uBAAuB,EAAE,CAAC;IAE5D,4CAA4C;IAC5C,MAAM,aAAa,GAAG,eAAe,EAAE,IAAI,CACzC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,KAAK,WAAW,CAC9C,CAAC;IAEF,iEAAiE;IACjE,MAAM,YAAY,GAAG,aAAa,IAAI,IAAI,CAAC;IAC3C,MAAM,kBAAkB,GAAG,YAAY,IAAI,aAAa,CAAC,MAAM,KAAK,IAAI,CAAC;IACzE,MAAM,SAAS,GACb,YAAY,IAAI,aAAa,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IAE7E,4EAA4E;IAC5E,sEAAsE;IACtE,MAAM,mBAAmB,GACvB,YAAY,IAAI,SAAS;QACvB,CAAC,CAAC,WAAW,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,SAAS,GAAG,EAAE,EAAE,CAAC;QACrD,CAAC,CAAC,WAAW,CAAC;IAElB,wEAAwE;IACxE,2EAA2E;IAC3E,iCAAiC;IACjC,MAAM,iBAAiB,GAAG,cAAc,IAAI,IAAI,CAAC;IACjD,MAAM,qBAAqB,GACzB,YAAY,IAAI,SAAS,IAAI,IAAI,IAAI,oBAAoB,CAAC,SAAS,CAAC,CAAC;IACvE,MAAM,gBAAgB,GAAG,OAAO,CAC9B,WAAW,IAAI,CAAC,iBAAiB,IAAI,qBAAqB,CAAC,CAC5D,CAAC;IAEF,IAAI,WAA+B,CAAC;IACpC,IAAI,kBAAkB,IAAI,CAAC,CAAC,YAAY,IAAI,iBAAiB,CAAC,EAAE,CAAC;QAC/D,WAAW,GAAG,UAAU,CAAC;IAC3B,CAAC;SAAM,IAAI,SAAS,EAAE,CAAC;QACrB,WAAW,GAAG,SAAS,CAAC,GAAG,CAAC;IAC9B,CAAC;IAED,OAAO,IAAA,qBAAa,EAAC;QACnB,oEAAoE;QACpE,QAAQ,EAAE,CAAC,UAAU,EAAE,WAAW,EAAE,WAAW,CAAC;QAChD,OAAO,EAAE,gBAAgB;QACzB,OAAO,EAAE,KAAK,IAAwC,EAAE;YACtD,IAAI,CAAC,mBAAmB,EAAE,CAAC;gBACzB,OAAO,IAAI,CAAC;YACd,CAAC;YAED,oDAAoD;YACpD,yEAAyE;YACzE,kCAAkC;YAClC,IAAI,cAAc,IAAI,CAAC,CAAC,YAAY,IAAI,kBAAkB,CAAC,EAAE,CAAC;gBAC5D,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,WAAW,CAAC,mBAAmB,CAAC,CAAC;gBACrE,OAAO,MAAM,IAAI,IAAI,CAAC;YACxB,CAAC;YAED,+BAA+B;YAC/B,IAAI,SAAS,IAAI,oBAAoB,CAAC,SAAS,CAAC,EAAE,CAAC;gBACjD,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;oBACxD,GAAG,EAAE,mBAAmB;iBACzB,CAAC,CAAC;gBACH,OAAO,MAAM,IAAI,IAAI,CAAC;YACxB,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC;KACF,CAAC,CAAC;AACL,CAAC","sourcesContent":["import {\n GetPromptResult,\n type ListPromptsResult,\n type ListResourcesResult,\n type ReadResourceResult,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { UseQueryResult } from \"@tanstack/react-query\";\nimport { useTamboQueries, useTamboQuery } from \"../hooks\";\nimport { useTamboRegistry } from \"../providers/tambo-registry-provider\";\nimport {\n type ConnectedMcpServer,\n type McpServer,\n useTamboMcpServers,\n} from \"./tambo-mcp-provider\";\n\nexport type ListPromptItem = ListPromptsResult[\"prompts\"][number];\nexport interface ListPromptEntry {\n // Only connected servers produce prompt entries, so expose the connected type\n server: ConnectedMcpServer;\n prompt: ListPromptItem;\n}\n\nexport type ListResourceItem = ListResourcesResult[\"resources\"][number];\n\n/**\n * Registry resource entry - resources from the local registry (not MCP servers).\n *\n * These entries always have `server === null` and represent resources that\n * are registered locally via `TamboRegistryProvider` (static `resources`\n * props or dynamic `ResourceSource` functions).\n */\nexport interface RegistryResourceEntry {\n server: null;\n resource: ListResourceItem;\n}\n\n/**\n * MCP server resource entry - resources from connected MCP servers.\n *\n * These entries always have a non-null `server` with connection metadata and\n * are produced by the active MCP clients managed by `TamboMcpProvider`.\n */\nexport interface McpResourceEntry {\n server: ConnectedMcpServer;\n resource: ListResourceItem;\n}\n\n/**\n * Union type for all resource entries returned by `useTamboMcpResourceList`.\n *\n * - Registry resources have `server === null`.\n * - MCP-backed resources have a non-null `server` with connection metadata.\n */\nexport type ListResourceEntry = RegistryResourceEntry | McpResourceEntry;\n\n/**\n * Type guard for narrowing a `ListResourceEntry` to an MCP-backed resource\n * (entries where `server` is non-null).\n */\nexport function isMcpResourceEntry(\n entry: ListResourceEntry,\n): entry is McpResourceEntry {\n return entry.server !== null && isConnectedMcpServer(entry.server);\n}\n\n/**\n * Hook to get the prompts for all the registered MCP servers.\n * @returns The prompts for the MCP servers, including the server that the prompt was found on.\n */\nexport function useTamboMcpPromptList() {\n const mcpServers = useTamboMcpServers();\n\n const queries = useTamboQueries({\n queries: mcpServers.map((mcpServer) => ({\n queryKey: [\"mcp-prompts\", mcpServer.key],\n // Only run for connected servers that have a client\n enabled: isConnectedMcpServer(mcpServer),\n queryFn: async (): Promise<ListPromptEntry[]> => {\n // Fast path: if this server doesn't have a client, skip work\n if (!isConnectedMcpServer(mcpServer)) return [];\n\n const result = await mcpServer.client.client.listPrompts();\n const prompts: ListPromptItem[] = result?.prompts ?? [];\n // Return prompts without prefixes - we'll apply prefixing in combine\n const promptsEntries = prompts.map((prompt) => ({\n server: mcpServer,\n prompt,\n }));\n return promptsEntries;\n },\n })),\n combine: (results) => {\n const combined = combineArrayResults(results);\n\n // Always apply serverKey prefix to MCP prompts (breaking change for consistency with resources)\n // This ensures clear separation between local and remote prompts\n return {\n ...combined,\n data: combined.data.map((entry) => ({\n ...entry,\n prompt: {\n ...entry.prompt,\n name: `${entry.server.serverKey}:${entry.prompt.name}`,\n },\n })),\n };\n },\n });\n\n return queries;\n}\n// TODO: find a more general place for this\nfunction combineArrayResults<T>(results: UseQueryResult<T[]>[]): {\n data: T[];\n error: Error | null;\n errors: Error[];\n isPending: boolean;\n isSuccess: boolean;\n isError: boolean;\n isPaused: boolean;\n isRefetching: boolean;\n isFetching: boolean;\n isLoading: boolean;\n refetch: () => Promise<void>;\n} {\n const errors = results\n .filter((result) => result.isError)\n .map((result) => result.error);\n\n // Treat queries that are idle (disabled) as non-blocking for aggregate status\n const enabledish = results.filter(\n (r) => r.fetchStatus !== \"idle\" || r.isSuccess || r.isError,\n );\n\n return {\n // Prefer flatMap to avoid extra intermediate arrays\n data: results.flatMap((result) =>\n result.isSuccess && Array.isArray(result.data) ? result.data : [],\n ),\n // Preserve a single error for compatibility and expose the full list for diagnostics\n error: errors[0] ?? null,\n errors,\n isPending: enabledish.some((result) => result.isPending),\n isSuccess:\n enabledish.length > 0 && enabledish.every((result) => result.isSuccess),\n isError: errors.length > 0,\n isPaused: enabledish.some((result) => result.isPaused),\n isRefetching: enabledish.some((result) => result.isRefetching),\n isFetching: enabledish.some((result) => result.isFetching),\n isLoading: enabledish.some((result) => result.isLoading),\n // Aggregate refetch to trigger all underlying queries\n refetch: async () => {\n await Promise.all(\n results.map(async (r) => {\n await r.refetch();\n }),\n );\n },\n };\n}\n\n// Type guard for narrowing to connected servers\nfunction isConnectedMcpServer(server: McpServer): server is ConnectedMcpServer {\n return \"client\" in server && server.client != null;\n}\n\n/**\n * Hook to get the prompt for the specified name.\n * @param promptName - The name of the prompt to get. Can be prefixed with serverKey (e.g., \"linear:issue\") or unprefixed.\n * @param args - The arguments to pass to the prompt.\n * @returns The prompt for the specified name.\n */\nexport function useTamboMcpPrompt(\n promptName: string | undefined,\n args: Record<string, string> = {},\n) {\n // figure out which server has the prompt\n const { data: promptEntries } = useTamboMcpPromptList();\n const promptEntry = promptEntries?.find(\n (prompt) => prompt.prompt.name === promptName,\n );\n // Use the stable server key (and the server instance itself) instead of brittle\n // name/url/transport matching.\n const mcpServer = promptEntry?.server;\n\n // Strip the prefix to get the original prompt name for the MCP server call\n const originalPromptName = promptName?.includes(\":\")\n ? promptName.split(\":\").slice(1).join(\":\")\n : promptName;\n\n // Canonicalize args to avoid unstable cache keys from object identity/order\n const sortedArgsEntries = Object.keys(args)\n .sort()\n .map((k) => [k, args[k]] as const);\n return useTamboQuery({\n // Include server identity and sorted args to prevent stale cache hits\n queryKey: [\"mcp-prompt\", promptName, mcpServer?.key, sortedArgsEntries],\n // Only run when we have a prompt name and a connected server\n enabled: Boolean(\n promptName && mcpServer && isConnectedMcpServer(mcpServer),\n ),\n queryFn: async (): Promise<GetPromptResult | null> => {\n if (\n !originalPromptName ||\n !mcpServer ||\n !isConnectedMcpServer(mcpServer)\n ) {\n return null;\n }\n const result = await mcpServer.client.client.getPrompt({\n name: originalPromptName,\n arguments: args,\n });\n return result ?? null; // return null because react-query doesn't like undefined results\n },\n });\n}\n\n/**\n * Hook to get the resources for all the registered MCP servers and registry.\n * @returns The resources from MCP servers and the local registry, including the server that the resource was found on (null for registry resources).\n */\nexport function useTamboMcpResourceList() {\n const mcpServers = useTamboMcpServers();\n const { resources: staticResources, resourceSource } = useTamboRegistry();\n\n // Build list of queries: MCP servers + optional dynamic resource source\n const queriesToRun = [\n // MCP server queries\n ...mcpServers.map((mcpServer) => ({\n queryKey: [\"mcp-resources\", mcpServer.key],\n // Only run for connected servers that have a client\n enabled: isConnectedMcpServer(mcpServer),\n queryFn: async (): Promise<McpResourceEntry[]> => {\n // Fast path: if this server doesn't have a client, skip work\n if (!isConnectedMcpServer(mcpServer)) return [];\n\n const result = await mcpServer.client.client.listResources();\n const resources: ListResourceItem[] = result?.resources ?? [];\n // Return resources without prefixes - we'll apply prefixing in combine\n const resourceEntries: McpResourceEntry[] = resources.map(\n (resource) => ({\n server: mcpServer,\n resource,\n }),\n );\n return resourceEntries;\n },\n })),\n // Dynamic resource source query (if exists)\n ...(resourceSource\n ? [\n {\n queryKey: [\"registry-resources\", \"dynamic\"],\n enabled: true,\n queryFn: async (): Promise<RegistryResourceEntry[]> => {\n if (!resourceSource) return [];\n const resources = await resourceSource.listResources();\n return resources.map((resource) => ({\n server: null,\n resource,\n }));\n },\n },\n ]\n : []),\n ];\n\n const queries = useTamboQueries({\n queries: queriesToRun,\n combine: (results) => {\n // Type assertion needed because queries can return different entry types\n const combined = combineArrayResults(\n results as UseQueryResult<ListResourceEntry[]>[],\n );\n\n // Add static registry resources (no query needed)\n const staticEntries: RegistryResourceEntry[] = staticResources.map(\n (resource) => ({\n server: null,\n resource,\n }),\n );\n\n // Merge static resources with query results (registry resources first)\n const allData = [...staticEntries, ...combined.data];\n\n // Apply serverKey prefix to ALL MCP resources (breaking change)\n // Registry resources (server: null) are never prefixed\n const prefixedData = allData.map((entry) => {\n if (entry.server === null) {\n // Registry resource - no prefix\n return entry;\n }\n // MCP resource - always prefix with serverKey\n return {\n ...entry,\n resource: {\n ...entry.resource,\n uri: `${entry.server.serverKey}:${entry.resource.uri}`,\n },\n };\n });\n\n return {\n ...combined,\n data: prefixedData,\n };\n },\n });\n\n return queries;\n}\n\n/**\n * Hook to get the resource for the specified URI.\n * @param resourceUri - The URI of the resource to get. Can be prefixed with serverKey (e.g., \"linear:file://foo\") for MCP resources, or unprefixed for registry resources.\n * @returns The resource for the specified URI.\n */\nexport function useTamboMcpResource(resourceUri: string | undefined) {\n const { resourceSource } = useTamboRegistry();\n const { data: resourceEntries } = useTamboMcpResourceList();\n\n // Find which server/source has the resource\n const resourceEntry = resourceEntries?.find(\n (entry) => entry.resource.uri === resourceUri,\n );\n\n // Determine if this is a known registry resource or MCP resource\n const isKnownEntry = resourceEntry != null;\n const isRegistryResource = isKnownEntry && resourceEntry.server === null;\n const mcpServer =\n isKnownEntry && resourceEntry.server != null ? resourceEntry.server : null;\n\n // Strip the prefix to get the original resource URI for the MCP server call\n // Only strip if we found a matching resource entry with an MCP server\n const originalResourceUri =\n isKnownEntry && mcpServer\n ? resourceUri?.replace(`${mcpServer.serverKey}:`, \"\")\n : resourceUri;\n\n // Check if we can fetch this resource. Registry resources can always be\n // fetched when a resourceSource exists, even if they haven't appeared in a\n // previous listResources result.\n const hasRegistrySource = resourceSource != null;\n const hasConnectedMcpServer =\n isKnownEntry && mcpServer != null && isConnectedMcpServer(mcpServer);\n const canFetchResource = Boolean(\n resourceUri && (hasRegistrySource || hasConnectedMcpServer),\n );\n\n let locationKey: string | undefined;\n if (isRegistryResource || (!isKnownEntry && hasRegistrySource)) {\n locationKey = \"registry\";\n } else if (mcpServer) {\n locationKey = mcpServer.key;\n }\n\n return useTamboQuery({\n // Include server identity or \"registry\" to prevent stale cache hits\n queryKey: [\"resource\", resourceUri, locationKey],\n enabled: canFetchResource,\n queryFn: async (): Promise<ReadResourceResult | null> => {\n if (!originalResourceUri) {\n return null;\n }\n\n // Registry resource: use resourceSource.getResource\n // If this is not a known entry but we have a resourceSource, treat it as\n // a registry resource by default.\n if (resourceSource && (!isKnownEntry || isRegistryResource)) {\n const result = await resourceSource.getResource(originalResourceUri);\n return result ?? null;\n }\n\n // MCP resource: use MCP client\n if (mcpServer && isConnectedMcpServer(mcpServer)) {\n const result = await mcpServer.client.client.readResource({\n uri: originalResourceUri,\n });\n return result ?? null;\n }\n\n return null;\n },\n });\n}\n"]}
|
|
@@ -243,16 +243,16 @@ describe("useTamboMcpPromptList - individual server caching", () => {
|
|
|
243
243
|
react_2.default.createElement(tambo_mcp_provider_1.TamboMcpProvider, null,
|
|
244
244
|
react_2.default.createElement(Capture, null))))));
|
|
245
245
|
// Wait for prompts to be updated (server B prompts should disappear)
|
|
246
|
-
//
|
|
246
|
+
// Prompts are now always prefixed (breaking change)
|
|
247
247
|
await (0, react_1.waitFor)(() => {
|
|
248
248
|
expect(capturedPrompts.length).toBe(2);
|
|
249
249
|
});
|
|
250
250
|
const updatedPromptNames = capturedPrompts.map((p) => p.prompt.name);
|
|
251
|
-
expect(updatedPromptNames).toContain("prompt-a1");
|
|
252
|
-
expect(updatedPromptNames).toContain("prompt-a2");
|
|
251
|
+
expect(updatedPromptNames).toContain("server-a:prompt-a1");
|
|
252
|
+
expect(updatedPromptNames).toContain("server-a:prompt-a2");
|
|
253
253
|
expect(updatedPromptNames).not.toContain("prompt-b1");
|
|
254
254
|
expect(updatedPromptNames).not.toContain("prompt-b2");
|
|
255
|
-
expect(updatedPromptNames).not.toContain("
|
|
255
|
+
expect(updatedPromptNames).not.toContain("prompt-a1"); // Always prefixed now
|
|
256
256
|
// Verify server B's client was closed
|
|
257
257
|
expect(clientB.close).toHaveBeenCalled();
|
|
258
258
|
});
|
|
@@ -470,11 +470,11 @@ describe("useTamboMcpPromptList - individual server caching", () => {
|
|
|
470
470
|
react_2.default.createElement(tambo_mcp_token_provider_1.TamboMcpTokenProvider, null,
|
|
471
471
|
react_2.default.createElement(tambo_mcp_provider_1.TamboMcpProvider, null,
|
|
472
472
|
react_2.default.createElement(Capture, null))))));
|
|
473
|
-
// Wait for initial prompts from server A
|
|
473
|
+
// Wait for initial prompts from server A (always prefixed)
|
|
474
474
|
await (0, react_1.waitFor)(() => {
|
|
475
475
|
expect(capturedPrompts.length).toBe(1);
|
|
476
476
|
});
|
|
477
|
-
expect(capturedPrompts.map((p) => p.prompt.name)).toContain("prompt-a");
|
|
477
|
+
expect(capturedPrompts.map((p) => p.prompt.name)).toContain("server-a:prompt-a");
|
|
478
478
|
// Add server B
|
|
479
479
|
rerender(react_2.default.createElement(tambo_client_provider_1.TamboClientContext.Provider, { value: {
|
|
480
480
|
client: { baseURL: "https://api.tambo.co" },
|
|
@@ -519,6 +519,28 @@ describe("useTamboMcpResourceList - resource management", () => {
|
|
|
519
519
|
afterEach(() => {
|
|
520
520
|
queryClient.clear();
|
|
521
521
|
});
|
|
522
|
+
it("should identify MCP-backed entries with isMcpResourceEntry", () => {
|
|
523
|
+
const registryEntry = {
|
|
524
|
+
server: null,
|
|
525
|
+
// Resource shape is not important for this helper, so cast to keep the
|
|
526
|
+
// test focused on the discriminant field.
|
|
527
|
+
resource: {
|
|
528
|
+
uri: "file:///registry/doc.txt",
|
|
529
|
+
name: "Registry Doc",
|
|
530
|
+
mimeType: "text/plain",
|
|
531
|
+
},
|
|
532
|
+
};
|
|
533
|
+
const mcpEntry = {
|
|
534
|
+
server: { key: "server-a", client: {} },
|
|
535
|
+
resource: {
|
|
536
|
+
uri: "server-a:file:///home/user/doc.txt",
|
|
537
|
+
name: "Document",
|
|
538
|
+
mimeType: "text/plain",
|
|
539
|
+
},
|
|
540
|
+
};
|
|
541
|
+
expect((0, mcp_hooks_1.isMcpResourceEntry)(mcpEntry)).toBe(true);
|
|
542
|
+
expect((0, mcp_hooks_1.isMcpResourceEntry)(registryEntry)).toBe(false);
|
|
543
|
+
});
|
|
522
544
|
it("should fetch and combine resources from multiple servers", async () => {
|
|
523
545
|
// Mock two servers with different resources
|
|
524
546
|
const serverAResources = {
|
|
@@ -618,11 +640,15 @@ describe("useTamboMcpResourceList - resource management", () => {
|
|
|
618
640
|
expect(resourceUris).toContain("server-b:file:///workspace/README.md");
|
|
619
641
|
// Verify each resource has the correct server info
|
|
620
642
|
const resource1 = capturedResources.find((r) => r.resource.uri === "server-a:file:///home/user/doc1.txt");
|
|
621
|
-
expect(resource1
|
|
643
|
+
expect(resource1).toBeDefined();
|
|
644
|
+
expect(resource1.server).not.toBeNull();
|
|
645
|
+
expect(resource1.server.url).toBe("https://server-a.example");
|
|
622
646
|
const resource2 = capturedResources.find((r) => r.resource.uri === "server-b:file:///workspace/code.js");
|
|
623
|
-
expect(resource2
|
|
647
|
+
expect(resource2).toBeDefined();
|
|
648
|
+
expect(resource2.server).not.toBeNull();
|
|
649
|
+
expect(resource2.server.url).toBe("https://server-b.example");
|
|
624
650
|
});
|
|
625
|
-
it("should
|
|
651
|
+
it("should always prefix MCP resources even with single server", async () => {
|
|
626
652
|
const serverAResources = {
|
|
627
653
|
resources: [
|
|
628
654
|
{
|
|
@@ -671,10 +697,10 @@ describe("useTamboMcpResourceList - resource management", () => {
|
|
|
671
697
|
await (0, react_1.waitFor)(() => {
|
|
672
698
|
expect(capturedResources.length).toBe(1);
|
|
673
699
|
});
|
|
674
|
-
//
|
|
675
|
-
expect(capturedResources[0].resource.uri).toBe("file:///home/user/doc.txt");
|
|
700
|
+
// Always prefix MCP resources, even with 1 server (breaking change)
|
|
701
|
+
expect(capturedResources[0].resource.uri).toBe("server-a:file:///home/user/doc.txt");
|
|
676
702
|
});
|
|
677
|
-
it("should
|
|
703
|
+
it("should maintain prefixes even when servers are removed", async () => {
|
|
678
704
|
const serverAResources = {
|
|
679
705
|
resources: [
|
|
680
706
|
{
|
|
@@ -777,14 +803,15 @@ describe("useTamboMcpResourceList - resource management", () => {
|
|
|
777
803
|
react_2.default.createElement(tambo_mcp_token_provider_1.TamboMcpTokenProvider, null,
|
|
778
804
|
react_2.default.createElement(tambo_mcp_provider_1.TamboMcpProvider, null,
|
|
779
805
|
react_2.default.createElement(Capture, null))))));
|
|
780
|
-
// Wait for server B resources to be removed
|
|
806
|
+
// Wait for server B resources to be removed (prefixes maintained)
|
|
781
807
|
await (0, react_1.waitFor)(() => {
|
|
782
808
|
expect(capturedResources.length).toBe(2);
|
|
783
809
|
});
|
|
784
810
|
const updatedUris = capturedResources.map((r) => r.resource.uri);
|
|
785
|
-
|
|
786
|
-
expect(updatedUris).toContain("file:///home/user/
|
|
787
|
-
expect(updatedUris).
|
|
811
|
+
// Prefixes are maintained even with only 1 server (breaking change)
|
|
812
|
+
expect(updatedUris).toContain("server-a:file:///home/user/doc1.txt");
|
|
813
|
+
expect(updatedUris).toContain("server-a:file:///home/user/doc2.txt");
|
|
814
|
+
expect(updatedUris).not.toContain("file:///home/user/doc1.txt"); // Always prefixed now
|
|
788
815
|
expect(updatedUris).not.toContain("server-b:file:///workspace/code.js"); // Server B removed
|
|
789
816
|
});
|
|
790
817
|
});
|
|
@@ -803,7 +830,7 @@ describe("useTamboMcpResource - read individual resource", () => {
|
|
|
803
830
|
afterEach(() => {
|
|
804
831
|
queryClient.clear();
|
|
805
832
|
});
|
|
806
|
-
it("should read a resource from a single server (
|
|
833
|
+
it("should read a resource from a single server (prefixed)", async () => {
|
|
807
834
|
const serverAResources = {
|
|
808
835
|
resources: [
|
|
809
836
|
{
|
|
@@ -837,7 +864,8 @@ describe("useTamboMcpResource - read individual resource", () => {
|
|
|
837
864
|
createImpl.mockImplementation(async () => clientA);
|
|
838
865
|
let capturedResourceData = null;
|
|
839
866
|
const Capture = () => {
|
|
840
|
-
|
|
867
|
+
// MCP resources are always prefixed, even with single server
|
|
868
|
+
const { data: resourceData } = (0, mcp_hooks_1.useTamboMcpResource)("server-a:file:///home/user/doc.txt");
|
|
841
869
|
(0, react_2.useEffect)(() => {
|
|
842
870
|
if (resourceData) {
|
|
843
871
|
capturedResourceData = resourceData;
|
|
@@ -963,5 +991,42 @@ describe("useTamboMcpResource - read individual resource", () => {
|
|
|
963
991
|
uri: "file:///home/user/doc.txt",
|
|
964
992
|
});
|
|
965
993
|
});
|
|
994
|
+
it("should read registry resources via resourceSource even when not listed", async () => {
|
|
995
|
+
const registryUri = "file:///local/registry-doc.txt";
|
|
996
|
+
const listResources = jest.fn().mockResolvedValue([]);
|
|
997
|
+
const getResource = jest.fn().mockResolvedValue({
|
|
998
|
+
contents: [
|
|
999
|
+
{
|
|
1000
|
+
uri: registryUri,
|
|
1001
|
+
mimeType: "text/plain",
|
|
1002
|
+
text: "Registry content",
|
|
1003
|
+
},
|
|
1004
|
+
],
|
|
1005
|
+
});
|
|
1006
|
+
let capturedResourceData = null;
|
|
1007
|
+
const Capture = () => {
|
|
1008
|
+
const { data: resourceData } = (0, mcp_hooks_1.useTamboMcpResource)(registryUri);
|
|
1009
|
+
(0, react_2.useEffect)(() => {
|
|
1010
|
+
if (resourceData) {
|
|
1011
|
+
capturedResourceData = resourceData;
|
|
1012
|
+
}
|
|
1013
|
+
}, [resourceData]);
|
|
1014
|
+
return null;
|
|
1015
|
+
};
|
|
1016
|
+
(0, react_1.render)(react_2.default.createElement(tambo_client_provider_1.TamboClientContext.Provider, { value: {
|
|
1017
|
+
client: { baseURL: "https://api.tambo.co" },
|
|
1018
|
+
queryClient,
|
|
1019
|
+
isUpdatingToken: false,
|
|
1020
|
+
} },
|
|
1021
|
+
react_2.default.createElement(tambo_registry_provider_1.TamboRegistryProvider, { listResources: listResources, getResource: getResource },
|
|
1022
|
+
react_2.default.createElement(tambo_mcp_token_provider_1.TamboMcpTokenProvider, null,
|
|
1023
|
+
react_2.default.createElement(tambo_mcp_provider_1.TamboMcpProvider, null,
|
|
1024
|
+
react_2.default.createElement(Capture, null))))));
|
|
1025
|
+
await (0, react_1.waitFor)(() => {
|
|
1026
|
+
expect(capturedResourceData).not.toBeNull();
|
|
1027
|
+
});
|
|
1028
|
+
expect(getResource).toHaveBeenCalledWith(registryUri);
|
|
1029
|
+
expect(capturedResourceData.contents[0].text).toBe("Registry content");
|
|
1030
|
+
});
|
|
966
1031
|
});
|
|
967
1032
|
//# sourceMappingURL=mcp-hooks.test.js.map
|