@apollo/client-ai-apps 0.6.5 → 0.7.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.
Files changed (258) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/CONTRIBUTING.md +195 -0
  3. package/README.md +74 -0
  4. package/dist/core/AbstractApolloClient.d.ts +33 -0
  5. package/dist/core/AbstractApolloClient.d.ts.map +1 -0
  6. package/dist/core/AbstractApolloClient.js +129 -0
  7. package/dist/core/AbstractApolloClient.js.map +1 -0
  8. package/dist/core/ApolloClient.d.ts +3 -7
  9. package/dist/core/ApolloClient.d.ts.map +1 -1
  10. package/dist/core/ApolloClient.js +5 -4
  11. package/dist/core/ApolloClient.js.map +1 -1
  12. package/dist/{mcp/core → core}/McpAppManager.d.ts +14 -10
  13. package/dist/core/McpAppManager.d.ts.map +1 -0
  14. package/dist/core/McpAppManager.js +56 -0
  15. package/dist/core/McpAppManager.js.map +1 -0
  16. package/dist/core/typeRegistration.d.ts +0 -14
  17. package/dist/core/typeRegistration.d.ts.map +1 -1
  18. package/dist/core/typeRegistration.js.map +1 -1
  19. package/dist/index.d.ts +1 -1
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js.map +1 -1
  22. package/dist/index.mcp.d.ts +0 -1
  23. package/dist/index.mcp.d.ts.map +1 -1
  24. package/dist/index.mcp.js +0 -1
  25. package/dist/index.mcp.js.map +1 -1
  26. package/dist/index.openai.d.ts +0 -1
  27. package/dist/index.openai.d.ts.map +1 -1
  28. package/dist/index.openai.js +0 -1
  29. package/dist/index.openai.js.map +1 -1
  30. package/dist/link/ToolCallLink.d.ts +6 -1
  31. package/dist/link/ToolCallLink.d.ts.map +1 -1
  32. package/dist/link/ToolCallLink.js +17 -4
  33. package/dist/link/ToolCallLink.js.map +1 -1
  34. package/dist/link/ToolHydrationLink.d.ts +21 -0
  35. package/dist/link/ToolHydrationLink.d.ts.map +1 -0
  36. package/dist/link/ToolHydrationLink.js +57 -0
  37. package/dist/link/ToolHydrationLink.js.map +1 -0
  38. package/dist/mcp/core/ApolloClient.d.ts +3 -20
  39. package/dist/mcp/core/ApolloClient.d.ts.map +1 -1
  40. package/dist/mcp/core/ApolloClient.js +20 -101
  41. package/dist/mcp/core/ApolloClient.js.map +1 -1
  42. package/dist/mcp/index.d.ts +0 -1
  43. package/dist/mcp/index.d.ts.map +1 -1
  44. package/dist/mcp/index.js +0 -1
  45. package/dist/mcp/index.js.map +1 -1
  46. package/dist/openai/core/ApolloClient.d.ts +3 -20
  47. package/dist/openai/core/ApolloClient.d.ts.map +1 -1
  48. package/dist/openai/core/ApolloClient.js +36 -101
  49. package/dist/openai/core/ApolloClient.js.map +1 -1
  50. package/dist/openai/index.d.ts +0 -1
  51. package/dist/openai/index.d.ts.map +1 -1
  52. package/dist/openai/index.js +0 -1
  53. package/dist/openai/index.js.map +1 -1
  54. package/dist/openai/react/index.d.ts +0 -7
  55. package/dist/openai/react/index.d.ts.map +1 -1
  56. package/dist/openai/react/index.js +0 -7
  57. package/dist/openai/react/index.js.map +1 -1
  58. package/dist/react/ApolloProvider.d.ts.map +1 -1
  59. package/dist/react/ApolloProvider.js +1 -1
  60. package/dist/react/ApolloProvider.js.map +1 -1
  61. package/dist/{mcp/react/hooks → react}/createHydrationUtils.d.ts +1 -1
  62. package/dist/react/createHydrationUtils.d.ts.map +1 -0
  63. package/dist/{mcp/react/hooks → react}/createHydrationUtils.js +7 -9
  64. package/dist/react/createHydrationUtils.js.map +1 -0
  65. package/dist/react/hooks/internal/useApolloClient.d.ts +3 -0
  66. package/dist/react/hooks/internal/useApolloClient.d.ts.map +1 -0
  67. package/dist/{mcp/react/hooks → react/hooks/internal}/useApolloClient.js +3 -3
  68. package/dist/react/hooks/internal/useApolloClient.js.map +1 -0
  69. package/dist/react/hooks/useApp.d.ts.map +1 -0
  70. package/dist/react/hooks/useApp.js +5 -0
  71. package/dist/react/hooks/useApp.js.map +1 -0
  72. package/dist/react/hooks/useHostContext.d.ts.map +1 -0
  73. package/dist/{openai/react → react}/hooks/useHostContext.js +1 -1
  74. package/dist/react/hooks/useHostContext.js.map +1 -0
  75. package/dist/react/hooks/useToolInfo.d.ts +3 -0
  76. package/dist/react/hooks/useToolInfo.d.ts.map +1 -0
  77. package/dist/react/hooks/useToolInfo.js +5 -0
  78. package/dist/react/hooks/useToolInfo.js.map +1 -0
  79. package/dist/react/hooks/useToolMetadata.d.ts +2 -0
  80. package/dist/react/hooks/useToolMetadata.d.ts.map +1 -0
  81. package/dist/react/hooks/useToolMetadata.js +5 -0
  82. package/dist/react/hooks/useToolMetadata.js.map +1 -0
  83. package/dist/react/index.d.ts +5 -16
  84. package/dist/react/index.d.ts.map +1 -1
  85. package/dist/react/index.js +5 -19
  86. package/dist/react/index.js.map +1 -1
  87. package/dist/utilities/connectToHost.d.ts +3 -0
  88. package/dist/utilities/connectToHost.d.ts.map +1 -0
  89. package/dist/utilities/connectToHost.js +11 -0
  90. package/dist/utilities/connectToHost.js.map +1 -0
  91. package/dist/utilities/index.d.ts +1 -0
  92. package/dist/utilities/index.d.ts.map +1 -1
  93. package/dist/utilities/index.js +1 -0
  94. package/dist/utilities/index.js.map +1 -1
  95. package/package.json +5 -22
  96. package/src/core/AbstractApolloClient.ts +217 -0
  97. package/src/core/ApolloClient.ts +8 -10
  98. package/src/core/McpAppManager.ts +106 -0
  99. package/src/core/typeRegistration.ts +0 -15
  100. package/src/index.mcp.ts +0 -1
  101. package/src/index.openai.ts +0 -1
  102. package/src/index.ts +1 -6
  103. package/src/link/ToolCallLink.ts +27 -5
  104. package/src/link/ToolHydrationLink.ts +90 -0
  105. package/src/link/__tests__/ToolCallLink.test.ts +99 -0
  106. package/src/mcp/core/ApolloClient.ts +32 -170
  107. package/src/mcp/core/__tests__/ApolloClient.test.ts +398 -140
  108. package/src/mcp/index.ts +0 -1
  109. package/src/openai/core/ApolloClient.ts +48 -166
  110. package/src/openai/core/__tests__/ApolloClient.test.ts +680 -185
  111. package/src/openai/index.ts +0 -1
  112. package/src/openai/react/index.ts +0 -7
  113. package/src/react/ApolloProvider.tsx +1 -6
  114. package/src/react/__tests__/ApolloProvider/mcp.test.tsx +66 -29
  115. package/src/react/__tests__/ApolloProvider/openai.test.tsx +16 -41
  116. package/src/react/__tests__/createHydrationUtils.test.tsx +1260 -0
  117. package/src/{mcp/react/hooks → react}/createHydrationUtils.ts +7 -10
  118. package/src/react/hooks/__tests__/useApp.test.tsx +46 -0
  119. package/src/react/hooks/__tests__/useHostContext.test.tsx +99 -0
  120. package/src/react/hooks/__tests__/useToolInfo.test.tsx +98 -0
  121. package/src/react/hooks/__tests__/useToolMetadata.test.tsx +58 -0
  122. package/src/{mcp/react/hooks → react/hooks/internal}/useApolloClient.ts +3 -3
  123. package/src/{mcp/react → react}/hooks/useApp.ts +1 -1
  124. package/src/{openai/react → react}/hooks/useHostContext.ts +1 -1
  125. package/src/react/hooks/useToolInfo.ts +6 -0
  126. package/src/react/hooks/useToolMetadata.ts +5 -0
  127. package/src/react/index.ts +5 -36
  128. package/src/testing/internal/graphql/parseManifestOperation.ts +87 -0
  129. package/src/testing/internal/index.ts +3 -0
  130. package/src/testing/internal/matchers/index.ts +1 -0
  131. package/src/testing/internal/matchers/toEmitAnything.ts +43 -0
  132. package/src/testing/internal/matchers/types.ts +1 -0
  133. package/src/testing/internal/mcp/mockMcpHost.ts +25 -4
  134. package/src/testing/internal/tests/eachHostEnv.ts +22 -0
  135. package/src/testing/internal/utilities/createHostEnv.ts +117 -0
  136. package/src/utilities/connectToHost.ts +13 -0
  137. package/src/utilities/index.ts +1 -0
  138. package/tsconfig.vite.json +1 -1
  139. package/vitest.config.ts +13 -0
  140. package/dist/mcp/core/McpAppManager.d.ts.map +0 -1
  141. package/dist/mcp/core/McpAppManager.js +0 -88
  142. package/dist/mcp/core/McpAppManager.js.map +0 -1
  143. package/dist/mcp/link/ToolCallLink.d.ts +0 -28
  144. package/dist/mcp/link/ToolCallLink.d.ts.map +0 -1
  145. package/dist/mcp/link/ToolCallLink.js +0 -35
  146. package/dist/mcp/link/ToolCallLink.js.map +0 -1
  147. package/dist/mcp/react/hooks/createHydrationUtils.d.ts.map +0 -1
  148. package/dist/mcp/react/hooks/createHydrationUtils.js.map +0 -1
  149. package/dist/mcp/react/hooks/useApolloClient.d.ts +0 -3
  150. package/dist/mcp/react/hooks/useApolloClient.d.ts.map +0 -1
  151. package/dist/mcp/react/hooks/useApolloClient.js.map +0 -1
  152. package/dist/mcp/react/hooks/useApp.d.ts.map +0 -1
  153. package/dist/mcp/react/hooks/useApp.js +0 -5
  154. package/dist/mcp/react/hooks/useApp.js.map +0 -1
  155. package/dist/mcp/react/hooks/useHostContext.d.ts.map +0 -1
  156. package/dist/mcp/react/hooks/useHostContext.js +0 -7
  157. package/dist/mcp/react/hooks/useHostContext.js.map +0 -1
  158. package/dist/mcp/react/hooks/useToolInfo.d.ts +0 -3
  159. package/dist/mcp/react/hooks/useToolInfo.d.ts.map +0 -1
  160. package/dist/mcp/react/hooks/useToolInfo.js +0 -10
  161. package/dist/mcp/react/hooks/useToolInfo.js.map +0 -1
  162. package/dist/mcp/react/hooks/useToolInput.d.ts +0 -7
  163. package/dist/mcp/react/hooks/useToolInput.d.ts.map +0 -1
  164. package/dist/mcp/react/hooks/useToolInput.js +0 -9
  165. package/dist/mcp/react/hooks/useToolInput.js.map +0 -1
  166. package/dist/mcp/react/hooks/useToolMetadata.d.ts +0 -2
  167. package/dist/mcp/react/hooks/useToolMetadata.d.ts.map +0 -1
  168. package/dist/mcp/react/hooks/useToolMetadata.js +0 -5
  169. package/dist/mcp/react/hooks/useToolMetadata.js.map +0 -1
  170. package/dist/mcp/react/hooks/useToolName.d.ts +0 -7
  171. package/dist/mcp/react/hooks/useToolName.d.ts.map +0 -1
  172. package/dist/mcp/react/hooks/useToolName.js +0 -9
  173. package/dist/mcp/react/hooks/useToolName.js.map +0 -1
  174. package/dist/mcp/react/index.d.ts +0 -8
  175. package/dist/mcp/react/index.d.ts.map +0 -1
  176. package/dist/mcp/react/index.js +0 -8
  177. package/dist/mcp/react/index.js.map +0 -1
  178. package/dist/openai/core/McpAppManager.d.ts +0 -37
  179. package/dist/openai/core/McpAppManager.d.ts.map +0 -1
  180. package/dist/openai/core/McpAppManager.js +0 -97
  181. package/dist/openai/core/McpAppManager.js.map +0 -1
  182. package/dist/openai/link/ToolCallLink.d.ts +0 -28
  183. package/dist/openai/link/ToolCallLink.d.ts.map +0 -1
  184. package/dist/openai/link/ToolCallLink.js +0 -35
  185. package/dist/openai/link/ToolCallLink.js.map +0 -1
  186. package/dist/openai/react/hooks/createHydrationUtils.d.ts +0 -15
  187. package/dist/openai/react/hooks/createHydrationUtils.d.ts.map +0 -1
  188. package/dist/openai/react/hooks/createHydrationUtils.js +0 -113
  189. package/dist/openai/react/hooks/createHydrationUtils.js.map +0 -1
  190. package/dist/openai/react/hooks/useApp.d.ts +0 -2
  191. package/dist/openai/react/hooks/useApp.d.ts.map +0 -1
  192. package/dist/openai/react/hooks/useApp.js +0 -5
  193. package/dist/openai/react/hooks/useApp.js.map +0 -1
  194. package/dist/openai/react/hooks/useHostContext.d.ts +0 -2
  195. package/dist/openai/react/hooks/useHostContext.d.ts.map +0 -1
  196. package/dist/openai/react/hooks/useHostContext.js.map +0 -1
  197. package/dist/openai/react/hooks/useToolInfo.d.ts +0 -3
  198. package/dist/openai/react/hooks/useToolInfo.d.ts.map +0 -1
  199. package/dist/openai/react/hooks/useToolInfo.js +0 -10
  200. package/dist/openai/react/hooks/useToolInfo.js.map +0 -1
  201. package/dist/openai/react/hooks/useToolInput.d.ts +0 -7
  202. package/dist/openai/react/hooks/useToolInput.d.ts.map +0 -1
  203. package/dist/openai/react/hooks/useToolInput.js +0 -9
  204. package/dist/openai/react/hooks/useToolInput.js.map +0 -1
  205. package/dist/openai/react/hooks/useToolMetadata.d.ts +0 -2
  206. package/dist/openai/react/hooks/useToolMetadata.d.ts.map +0 -1
  207. package/dist/openai/react/hooks/useToolMetadata.js +0 -5
  208. package/dist/openai/react/hooks/useToolMetadata.js.map +0 -1
  209. package/dist/openai/react/hooks/useToolName.d.ts +0 -7
  210. package/dist/openai/react/hooks/useToolName.d.ts.map +0 -1
  211. package/dist/openai/react/hooks/useToolName.js +0 -9
  212. package/dist/openai/react/hooks/useToolName.js.map +0 -1
  213. package/dist/react/index.mcp.d.ts +0 -3
  214. package/dist/react/index.mcp.d.ts.map +0 -1
  215. package/dist/react/index.mcp.js +0 -3
  216. package/dist/react/index.mcp.js.map +0 -1
  217. package/dist/react/index.openai.d.ts +0 -3
  218. package/dist/react/index.openai.d.ts.map +0 -1
  219. package/dist/react/index.openai.js +0 -3
  220. package/dist/react/index.openai.js.map +0 -1
  221. package/dist/react/missingHook.d.ts +0 -2
  222. package/dist/react/missingHook.d.ts.map +0 -1
  223. package/dist/react/missingHook.js +0 -6
  224. package/dist/react/missingHook.js.map +0 -1
  225. package/src/mcp/core/McpAppManager.ts +0 -136
  226. package/src/mcp/link/ToolCallLink.ts +0 -40
  227. package/src/mcp/link/__tests__/ToolCallLink.test.ts +0 -113
  228. package/src/mcp/react/hooks/__tests__/createHydrationUtils.test.tsx +0 -1228
  229. package/src/mcp/react/hooks/__tests__/useApp.test.tsx +0 -46
  230. package/src/mcp/react/hooks/__tests__/useHostContext.test.tsx +0 -95
  231. package/src/mcp/react/hooks/__tests__/useToolInfo.test.tsx +0 -53
  232. package/src/mcp/react/hooks/__tests__/useToolInput.test.tsx +0 -50
  233. package/src/mcp/react/hooks/__tests__/useToolMetadata.test.tsx +0 -53
  234. package/src/mcp/react/hooks/__tests__/useToolName.test.tsx +0 -50
  235. package/src/mcp/react/hooks/useHostContext.ts +0 -14
  236. package/src/mcp/react/hooks/useToolInfo.ts +0 -13
  237. package/src/mcp/react/hooks/useToolInput.ts +0 -10
  238. package/src/mcp/react/hooks/useToolMetadata.ts +0 -5
  239. package/src/mcp/react/hooks/useToolName.ts +0 -10
  240. package/src/mcp/react/index.ts +0 -7
  241. package/src/openai/core/McpAppManager.ts +0 -148
  242. package/src/openai/link/ToolCallLink.ts +0 -40
  243. package/src/openai/react/hooks/__tests__/createHydrationUtils.test.tsx +0 -1333
  244. package/src/openai/react/hooks/__tests__/useToolInfo.test.tsx +0 -92
  245. package/src/openai/react/hooks/__tests__/useToolInput.test.tsx +0 -85
  246. package/src/openai/react/hooks/__tests__/useToolMetadata.test.tsx +0 -86
  247. package/src/openai/react/hooks/__tests__/useToolName.test.tsx +0 -50
  248. package/src/openai/react/hooks/createHydrationUtils.ts +0 -182
  249. package/src/openai/react/hooks/useApp.ts +0 -5
  250. package/src/openai/react/hooks/useToolInfo.ts +0 -13
  251. package/src/openai/react/hooks/useToolInput.ts +0 -10
  252. package/src/openai/react/hooks/useToolMetadata.ts +0 -5
  253. package/src/openai/react/hooks/useToolName.ts +0 -10
  254. package/src/react/index.mcp.ts +0 -10
  255. package/src/react/index.openai.ts +0 -10
  256. package/src/react/missingHook.ts +0 -9
  257. /package/dist/{mcp/react → react}/hooks/useApp.d.ts +0 -0
  258. /package/dist/{mcp/react → react}/hooks/useHostContext.d.ts +0 -0
@@ -1,136 +0,0 @@
1
- import {
2
- App,
3
- PostMessageTransport,
4
- type McpUiHostContextChangedNotification,
5
- } from "@modelcontextprotocol/ext-apps";
6
- import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
7
- import type { ApplicationManifest } from "../../types/application-manifest";
8
- import type { FormattedExecutionResult } from "graphql";
9
- import type { DocumentNode, OperationVariables } from "@apollo/client";
10
- import { print } from "@apollo/client/utilities";
11
- import { cacheAsync, promiseWithResolvers } from "../../utilities";
12
- import type { ApolloMcpServerApps } from "../../core/types";
13
-
14
- type ExecuteQueryCallToolResult = Omit<CallToolResult, "structuredContent"> & {
15
- structuredContent: FormattedExecutionResult;
16
- _meta?: { structuredContent?: FormattedExecutionResult };
17
- };
18
-
19
- /** @internal */
20
- export class McpAppManager {
21
- readonly app: App;
22
-
23
- #toolName: string | undefined;
24
- #toolMetadata: ApolloMcpServerApps.CallToolResult["_meta"] | undefined;
25
- #toolInput: Record<string, unknown> | undefined;
26
-
27
- #hostContextCallbacks = new Set<
28
- (params: McpUiHostContextChangedNotification["params"]) => void
29
- >();
30
-
31
- constructor(manifest: ApplicationManifest) {
32
- this.app = new App({ name: manifest.name, version: manifest.appVersion });
33
- }
34
-
35
- get toolName() {
36
- return this.#toolName;
37
- }
38
-
39
- get toolMetadata() {
40
- return this.#toolMetadata;
41
- }
42
-
43
- get toolInput() {
44
- return this.#toolInput;
45
- }
46
-
47
- onHostContextChanged(
48
- cb: (params: McpUiHostContextChangedNotification["params"]) => void
49
- ) {
50
- this.#hostContextCallbacks.add(cb);
51
-
52
- return () => {
53
- this.#hostContextCallbacks.delete(cb);
54
- };
55
- }
56
-
57
- connect = cacheAsync(async () => {
58
- let toolResult = promiseWithResolvers<ApolloMcpServerApps.CallToolResult>();
59
- let toolInput = promiseWithResolvers<Parameters<App["ontoolinput"]>[0]>();
60
-
61
- this.app.ontoolresult = (params) => {
62
- toolResult.resolve(
63
- params as unknown as ApolloMcpServerApps.CallToolResult
64
- );
65
- };
66
-
67
- this.app.ontoolinput = (params) => {
68
- toolInput.resolve(params);
69
- };
70
-
71
- this.app.onhostcontextchanged = (params) => {
72
- this.#hostContextCallbacks.forEach((cb) => cb(params));
73
- };
74
-
75
- await this.connectToHost();
76
-
77
- const { structuredContent, _meta } = await toolResult.promise;
78
- const { arguments: args } = await toolInput.promise;
79
-
80
- // Some hosts do not provide toolInfo in the ui/initialize response, so we
81
- // fallback to `_meta.toolName` provided by Apollo MCP server if the value
82
- // is not available.
83
- this.#toolName =
84
- this.app.getHostContext()?.toolInfo?.tool.name ??
85
- _meta?.toolName ??
86
- // Some hosts do not forward `_meta` nor do they provide `toolInfo`. Our
87
- // MCP server provides `toolName` in `structuredContent` as a workaround
88
- // that we can use if all else fails
89
- structuredContent.toolName;
90
- this.#toolMetadata = _meta;
91
- this.#toolInput = args;
92
-
93
- return {
94
- structuredContent: {
95
- ...structuredContent,
96
- ..._meta?.structuredContent,
97
- },
98
- toolName: this.toolName,
99
- args,
100
- };
101
- });
102
-
103
- close() {
104
- return this.app.close();
105
- }
106
-
107
- async executeQuery({
108
- query,
109
- variables,
110
- }: {
111
- query: DocumentNode;
112
- variables: OperationVariables | undefined;
113
- }) {
114
- const result = (await this.app.callServerTool({
115
- name: "execute",
116
- arguments: { query: print(query), variables },
117
- })) as ExecuteQueryCallToolResult;
118
-
119
- return {
120
- ...result.structuredContent,
121
- ...result._meta?.structuredContent,
122
- };
123
- }
124
-
125
- private async connectToHost() {
126
- try {
127
- return await this.app.connect(
128
- new PostMessageTransport(window.parent, window.parent)
129
- );
130
- } catch (e) {
131
- const error = e instanceof Error ? e : new Error("Failed to connect");
132
-
133
- throw error;
134
- }
135
- }
136
- }
@@ -1,40 +0,0 @@
1
- import { ApolloLink, Observable } from "@apollo/client";
2
- import { from } from "rxjs";
3
- import type { ApolloClient as McpApolloClient } from "../core/ApolloClient";
4
-
5
- /**
6
- * A terminating link that sends a GraphQL request through an agent tool call.
7
- * When providing a custom link chain to `ApolloClient`, `ApolloClient` will
8
- * validate that the terminating link is an instance of this link.
9
- *
10
- * @example Providing a custom link chain
11
- *
12
- * ```ts
13
- * import { ApolloLink } from "@apollo/client";
14
- * import { ApolloClient, ToolCallLink } from "@apollo/client-ai-apps";
15
- *
16
- * const link = ApolloLink.from([
17
- * ...otherLinks,
18
- * new ToolCallLink()
19
- * ]);
20
- *
21
- * const client = new ApolloClient({
22
- * link,
23
- * // ...
24
- * });
25
- * ```
26
- */
27
- export class ToolCallLink extends ApolloLink {
28
- readonly name = "ToolCallLink";
29
-
30
- request(operation: ApolloLink.Operation): Observable<ApolloLink.Result> {
31
- const client = operation.client as McpApolloClient;
32
-
33
- return from(
34
- client["appManager"].executeQuery({
35
- query: operation.query,
36
- variables: operation.variables,
37
- })
38
- );
39
- }
40
- }
@@ -1,113 +0,0 @@
1
- import { expect, test } from "vitest";
2
- import { gql, InMemoryCache } from "@apollo/client";
3
- import { execute } from "@apollo/client/link";
4
- import { ApolloClient } from "../../core/ApolloClient.js";
5
- import {
6
- minimalHostContextWithToolName,
7
- mockApplicationManifest,
8
- mockMcpHost,
9
- ObservableStream,
10
- spyOnConsole,
11
- } from "../../../testing/internal/index.js";
12
- import { ToolCallLink } from "../ToolCallLink.js";
13
-
14
- test("merges _meta.structuredContent into result for @private fields", async () => {
15
- using _ = spyOnConsole("debug");
16
- const query = gql`
17
- query GreetingQuery {
18
- greeting @private
19
- }
20
- `;
21
-
22
- const client = new ApolloClient({
23
- cache: new InMemoryCache(),
24
- manifest: mockApplicationManifest(),
25
- });
26
-
27
- using host = await mockMcpHost({
28
- hostContext: minimalHostContextWithToolName("GetProduct"),
29
- });
30
- host.onCleanup(() => client.stop());
31
-
32
- host.sendToolInput({ arguments: {} });
33
- host.sendToolResult({
34
- _meta: { toolName: "GetProduct" },
35
- content: [],
36
- structuredContent: {
37
- result: {
38
- data: {
39
- product: null,
40
- },
41
- },
42
- },
43
- });
44
-
45
- host.mockToolCall("execute", () => ({
46
- content: [],
47
- structuredContent: {},
48
- _meta: {
49
- structuredContent: { data: { greeting: "Hello, private world" } },
50
- },
51
- }));
52
-
53
- await client.connect();
54
-
55
- const observable = execute(new ToolCallLink(), { query }, { client });
56
- const stream = new ObservableStream(observable);
57
-
58
- await expect(stream).toEmitValue({
59
- data: { greeting: "Hello, private world" },
60
- });
61
-
62
- await expect(stream).toComplete();
63
- });
64
-
65
- test("delegates query execution to MCP host", async () => {
66
- using _ = spyOnConsole("debug");
67
- const query = gql`
68
- query GreetingQuery {
69
- greeting
70
- }
71
- `;
72
-
73
- const client = new ApolloClient({
74
- cache: new InMemoryCache(),
75
- manifest: mockApplicationManifest(),
76
- });
77
-
78
- using host = await mockMcpHost({
79
- hostContext: minimalHostContextWithToolName("GetProduct"),
80
- });
81
- host.onCleanup(() => client.stop());
82
-
83
- host.sendToolInput({ arguments: {} });
84
- host.sendToolResult({
85
- _meta: { toolName: "GetProduct" },
86
- content: [],
87
- structuredContent: {
88
- result: {
89
- data: {
90
- product: null,
91
- },
92
- },
93
- },
94
- });
95
-
96
- host.mockToolCall("execute", () => ({
97
- content: [],
98
- structuredContent: {
99
- data: { greeting: "Hello, world" },
100
- },
101
- }));
102
-
103
- await client.connect();
104
-
105
- const observable = execute(new ToolCallLink(), { query }, { client });
106
- const stream = new ObservableStream(observable);
107
-
108
- await expect(stream).toEmitValue({
109
- data: { greeting: "Hello, world" },
110
- });
111
-
112
- await expect(stream).toComplete();
113
- });