@apollo/client-ai-apps 0.6.4 → 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 (272) hide show
  1. package/CHANGELOG.md +100 -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/core/McpAppManager.d.ts +42 -0
  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/core/types.d.ts +2 -1
  20. package/dist/core/types.d.ts.map +1 -1
  21. package/dist/core/types.js.map +1 -1
  22. package/dist/index.d.ts +1 -1
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js.map +1 -1
  25. package/dist/index.mcp.d.ts +0 -1
  26. package/dist/index.mcp.d.ts.map +1 -1
  27. package/dist/index.mcp.js +0 -1
  28. package/dist/index.mcp.js.map +1 -1
  29. package/dist/index.openai.d.ts +0 -1
  30. package/dist/index.openai.d.ts.map +1 -1
  31. package/dist/index.openai.js +0 -1
  32. package/dist/index.openai.js.map +1 -1
  33. package/dist/link/ToolCallLink.d.ts +6 -1
  34. package/dist/link/ToolCallLink.d.ts.map +1 -1
  35. package/dist/link/ToolCallLink.js +17 -4
  36. package/dist/link/ToolCallLink.js.map +1 -1
  37. package/dist/link/ToolHydrationLink.d.ts +21 -0
  38. package/dist/link/ToolHydrationLink.d.ts.map +1 -0
  39. package/dist/link/ToolHydrationLink.js +57 -0
  40. package/dist/link/ToolHydrationLink.js.map +1 -0
  41. package/dist/mcp/core/ApolloClient.d.ts +3 -20
  42. package/dist/mcp/core/ApolloClient.d.ts.map +1 -1
  43. package/dist/mcp/core/ApolloClient.js +20 -98
  44. package/dist/mcp/core/ApolloClient.js.map +1 -1
  45. package/dist/mcp/index.d.ts +0 -1
  46. package/dist/mcp/index.d.ts.map +1 -1
  47. package/dist/mcp/index.js +0 -1
  48. package/dist/mcp/index.js.map +1 -1
  49. package/dist/openai/core/ApolloClient.d.ts +3 -20
  50. package/dist/openai/core/ApolloClient.d.ts.map +1 -1
  51. package/dist/openai/core/ApolloClient.js +36 -98
  52. package/dist/openai/core/ApolloClient.js.map +1 -1
  53. package/dist/openai/index.d.ts +0 -1
  54. package/dist/openai/index.d.ts.map +1 -1
  55. package/dist/openai/index.js +0 -1
  56. package/dist/openai/index.js.map +1 -1
  57. package/dist/openai/react/index.d.ts +0 -7
  58. package/dist/openai/react/index.d.ts.map +1 -1
  59. package/dist/openai/react/index.js +0 -7
  60. package/dist/openai/react/index.js.map +1 -1
  61. package/dist/react/ApolloProvider.d.ts.map +1 -1
  62. package/dist/react/ApolloProvider.js +1 -1
  63. package/dist/react/ApolloProvider.js.map +1 -1
  64. package/dist/{mcp/react/hooks → react}/createHydrationUtils.d.ts +1 -1
  65. package/dist/react/createHydrationUtils.d.ts.map +1 -0
  66. package/dist/{mcp/react/hooks → react}/createHydrationUtils.js +7 -9
  67. package/dist/react/createHydrationUtils.js.map +1 -0
  68. package/dist/react/hooks/internal/useApolloClient.d.ts +3 -0
  69. package/dist/react/hooks/internal/useApolloClient.d.ts.map +1 -0
  70. package/dist/{mcp/react/hooks → react/hooks/internal}/useApolloClient.js +3 -3
  71. package/dist/react/hooks/internal/useApolloClient.js.map +1 -0
  72. package/dist/react/hooks/useApp.d.ts.map +1 -0
  73. package/dist/react/hooks/useApp.js +5 -0
  74. package/dist/react/hooks/useApp.js.map +1 -0
  75. package/dist/react/hooks/useHostContext.d.ts.map +1 -0
  76. package/dist/{openai/react → react}/hooks/useHostContext.js +1 -1
  77. package/dist/react/hooks/useHostContext.js.map +1 -0
  78. package/dist/react/hooks/useToolInfo.d.ts +3 -0
  79. package/dist/react/hooks/useToolInfo.d.ts.map +1 -0
  80. package/dist/react/hooks/useToolInfo.js +5 -0
  81. package/dist/react/hooks/useToolInfo.js.map +1 -0
  82. package/dist/react/hooks/useToolMetadata.d.ts +2 -0
  83. package/dist/react/hooks/useToolMetadata.d.ts.map +1 -0
  84. package/dist/react/hooks/useToolMetadata.js +5 -0
  85. package/dist/react/hooks/useToolMetadata.js.map +1 -0
  86. package/dist/react/index.d.ts +5 -16
  87. package/dist/react/index.d.ts.map +1 -1
  88. package/dist/react/index.js +5 -19
  89. package/dist/react/index.js.map +1 -1
  90. package/dist/types/application-manifest.d.ts +1 -0
  91. package/dist/types/application-manifest.d.ts.map +1 -1
  92. package/dist/types/application-manifest.js.map +1 -1
  93. package/dist/utilities/connectToHost.d.ts +3 -0
  94. package/dist/utilities/connectToHost.d.ts.map +1 -0
  95. package/dist/utilities/connectToHost.js +11 -0
  96. package/dist/utilities/connectToHost.js.map +1 -0
  97. package/dist/utilities/index.d.ts +1 -0
  98. package/dist/utilities/index.d.ts.map +1 -1
  99. package/dist/utilities/index.js +1 -0
  100. package/dist/utilities/index.js.map +1 -1
  101. package/dist/vite/apolloClientAiApps.d.ts.map +1 -1
  102. package/dist/vite/apolloClientAiApps.js +2 -0
  103. package/dist/vite/apolloClientAiApps.js.map +1 -1
  104. package/package.json +5 -22
  105. package/src/core/AbstractApolloClient.ts +217 -0
  106. package/src/core/ApolloClient.ts +8 -10
  107. package/src/core/McpAppManager.ts +106 -0
  108. package/src/core/typeRegistration.ts +0 -15
  109. package/src/core/types.ts +2 -1
  110. package/src/index.mcp.ts +0 -1
  111. package/src/index.openai.ts +0 -1
  112. package/src/index.ts +1 -6
  113. package/src/link/ToolCallLink.ts +27 -5
  114. package/src/link/ToolHydrationLink.ts +90 -0
  115. package/src/link/__tests__/ToolCallLink.test.ts +99 -0
  116. package/src/mcp/core/ApolloClient.ts +32 -165
  117. package/src/mcp/core/__tests__/ApolloClient.test.ts +571 -71
  118. package/src/mcp/index.ts +0 -1
  119. package/src/openai/core/ApolloClient.ts +48 -161
  120. package/src/openai/core/__tests__/ApolloClient.test.ts +916 -118
  121. package/src/openai/index.ts +0 -1
  122. package/src/openai/react/index.ts +0 -7
  123. package/src/react/ApolloProvider.tsx +1 -6
  124. package/src/react/__tests__/ApolloProvider/mcp.test.tsx +66 -29
  125. package/src/react/__tests__/ApolloProvider/openai.test.tsx +16 -41
  126. package/src/react/__tests__/createHydrationUtils.test.tsx +1260 -0
  127. package/src/{mcp/react/hooks → react}/createHydrationUtils.ts +7 -10
  128. package/src/react/hooks/__tests__/useApp.test.tsx +46 -0
  129. package/src/react/hooks/__tests__/useHostContext.test.tsx +99 -0
  130. package/src/react/hooks/__tests__/useToolInfo.test.tsx +98 -0
  131. package/src/react/hooks/__tests__/useToolMetadata.test.tsx +58 -0
  132. package/src/{mcp/react/hooks → react/hooks/internal}/useApolloClient.ts +3 -3
  133. package/src/{mcp/react → react}/hooks/useApp.ts +1 -1
  134. package/src/{openai/react → react}/hooks/useHostContext.ts +1 -1
  135. package/src/react/hooks/useToolInfo.ts +6 -0
  136. package/src/react/hooks/useToolMetadata.ts +5 -0
  137. package/src/react/index.ts +5 -36
  138. package/src/testing/internal/graphql/parseManifestOperation.ts +87 -0
  139. package/src/testing/internal/index.ts +3 -0
  140. package/src/testing/internal/matchers/index.ts +1 -0
  141. package/src/testing/internal/matchers/toEmitAnything.ts +43 -0
  142. package/src/testing/internal/matchers/types.ts +1 -0
  143. package/src/testing/internal/mcp/mockMcpHost.ts +25 -4
  144. package/src/testing/internal/tests/eachHostEnv.ts +22 -0
  145. package/src/testing/internal/utilities/createHostEnv.ts +117 -0
  146. package/src/types/application-manifest.ts +1 -0
  147. package/src/utilities/connectToHost.ts +13 -0
  148. package/src/utilities/index.ts +1 -0
  149. package/src/vite/__tests__/apolloClientAiApps.test.ts +56 -0
  150. package/src/vite/apolloClientAiApps.ts +5 -0
  151. package/tsconfig.vite.json +1 -1
  152. package/vitest.config.ts +13 -0
  153. package/dist/mcp/core/McpAppManager.d.ts +0 -30
  154. package/dist/mcp/core/McpAppManager.d.ts.map +0 -1
  155. package/dist/mcp/core/McpAppManager.js +0 -82
  156. package/dist/mcp/core/McpAppManager.js.map +0 -1
  157. package/dist/mcp/link/ToolCallLink.d.ts +0 -28
  158. package/dist/mcp/link/ToolCallLink.d.ts.map +0 -1
  159. package/dist/mcp/link/ToolCallLink.js +0 -35
  160. package/dist/mcp/link/ToolCallLink.js.map +0 -1
  161. package/dist/mcp/react/hooks/createHydrationUtils.d.ts.map +0 -1
  162. package/dist/mcp/react/hooks/createHydrationUtils.js.map +0 -1
  163. package/dist/mcp/react/hooks/useApolloClient.d.ts +0 -3
  164. package/dist/mcp/react/hooks/useApolloClient.d.ts.map +0 -1
  165. package/dist/mcp/react/hooks/useApolloClient.js.map +0 -1
  166. package/dist/mcp/react/hooks/useApp.d.ts.map +0 -1
  167. package/dist/mcp/react/hooks/useApp.js +0 -5
  168. package/dist/mcp/react/hooks/useApp.js.map +0 -1
  169. package/dist/mcp/react/hooks/useHostContext.d.ts.map +0 -1
  170. package/dist/mcp/react/hooks/useHostContext.js +0 -7
  171. package/dist/mcp/react/hooks/useHostContext.js.map +0 -1
  172. package/dist/mcp/react/hooks/useToolInfo.d.ts +0 -3
  173. package/dist/mcp/react/hooks/useToolInfo.d.ts.map +0 -1
  174. package/dist/mcp/react/hooks/useToolInfo.js +0 -10
  175. package/dist/mcp/react/hooks/useToolInfo.js.map +0 -1
  176. package/dist/mcp/react/hooks/useToolInput.d.ts +0 -7
  177. package/dist/mcp/react/hooks/useToolInput.d.ts.map +0 -1
  178. package/dist/mcp/react/hooks/useToolInput.js +0 -9
  179. package/dist/mcp/react/hooks/useToolInput.js.map +0 -1
  180. package/dist/mcp/react/hooks/useToolMetadata.d.ts +0 -2
  181. package/dist/mcp/react/hooks/useToolMetadata.d.ts.map +0 -1
  182. package/dist/mcp/react/hooks/useToolMetadata.js +0 -5
  183. package/dist/mcp/react/hooks/useToolMetadata.js.map +0 -1
  184. package/dist/mcp/react/hooks/useToolName.d.ts +0 -7
  185. package/dist/mcp/react/hooks/useToolName.d.ts.map +0 -1
  186. package/dist/mcp/react/hooks/useToolName.js +0 -9
  187. package/dist/mcp/react/hooks/useToolName.js.map +0 -1
  188. package/dist/mcp/react/index.d.ts +0 -8
  189. package/dist/mcp/react/index.d.ts.map +0 -1
  190. package/dist/mcp/react/index.js +0 -8
  191. package/dist/mcp/react/index.js.map +0 -1
  192. package/dist/openai/core/McpAppManager.d.ts +0 -29
  193. package/dist/openai/core/McpAppManager.d.ts.map +0 -1
  194. package/dist/openai/core/McpAppManager.js +0 -91
  195. package/dist/openai/core/McpAppManager.js.map +0 -1
  196. package/dist/openai/link/ToolCallLink.d.ts +0 -28
  197. package/dist/openai/link/ToolCallLink.d.ts.map +0 -1
  198. package/dist/openai/link/ToolCallLink.js +0 -35
  199. package/dist/openai/link/ToolCallLink.js.map +0 -1
  200. package/dist/openai/react/hooks/createHydrationUtils.d.ts +0 -15
  201. package/dist/openai/react/hooks/createHydrationUtils.d.ts.map +0 -1
  202. package/dist/openai/react/hooks/createHydrationUtils.js +0 -113
  203. package/dist/openai/react/hooks/createHydrationUtils.js.map +0 -1
  204. package/dist/openai/react/hooks/useApp.d.ts +0 -2
  205. package/dist/openai/react/hooks/useApp.d.ts.map +0 -1
  206. package/dist/openai/react/hooks/useApp.js +0 -5
  207. package/dist/openai/react/hooks/useApp.js.map +0 -1
  208. package/dist/openai/react/hooks/useHostContext.d.ts +0 -2
  209. package/dist/openai/react/hooks/useHostContext.d.ts.map +0 -1
  210. package/dist/openai/react/hooks/useHostContext.js.map +0 -1
  211. package/dist/openai/react/hooks/useToolInfo.d.ts +0 -3
  212. package/dist/openai/react/hooks/useToolInfo.d.ts.map +0 -1
  213. package/dist/openai/react/hooks/useToolInfo.js +0 -10
  214. package/dist/openai/react/hooks/useToolInfo.js.map +0 -1
  215. package/dist/openai/react/hooks/useToolInput.d.ts +0 -7
  216. package/dist/openai/react/hooks/useToolInput.d.ts.map +0 -1
  217. package/dist/openai/react/hooks/useToolInput.js +0 -9
  218. package/dist/openai/react/hooks/useToolInput.js.map +0 -1
  219. package/dist/openai/react/hooks/useToolMetadata.d.ts +0 -2
  220. package/dist/openai/react/hooks/useToolMetadata.d.ts.map +0 -1
  221. package/dist/openai/react/hooks/useToolMetadata.js +0 -5
  222. package/dist/openai/react/hooks/useToolMetadata.js.map +0 -1
  223. package/dist/openai/react/hooks/useToolName.d.ts +0 -7
  224. package/dist/openai/react/hooks/useToolName.d.ts.map +0 -1
  225. package/dist/openai/react/hooks/useToolName.js +0 -9
  226. package/dist/openai/react/hooks/useToolName.js.map +0 -1
  227. package/dist/react/index.mcp.d.ts +0 -3
  228. package/dist/react/index.mcp.d.ts.map +0 -1
  229. package/dist/react/index.mcp.js +0 -3
  230. package/dist/react/index.mcp.js.map +0 -1
  231. package/dist/react/index.openai.d.ts +0 -3
  232. package/dist/react/index.openai.d.ts.map +0 -1
  233. package/dist/react/index.openai.js +0 -3
  234. package/dist/react/index.openai.js.map +0 -1
  235. package/dist/react/missingHook.d.ts +0 -2
  236. package/dist/react/missingHook.d.ts.map +0 -1
  237. package/dist/react/missingHook.js +0 -6
  238. package/dist/react/missingHook.js.map +0 -1
  239. package/src/mcp/core/McpAppManager.ts +0 -129
  240. package/src/mcp/link/ToolCallLink.ts +0 -40
  241. package/src/mcp/link/__tests__/ToolCallLink.test.ts +0 -62
  242. package/src/mcp/react/hooks/__tests__/createHydrationUtils.test.tsx +0 -1228
  243. package/src/mcp/react/hooks/__tests__/useApp.test.tsx +0 -46
  244. package/src/mcp/react/hooks/__tests__/useHostContext.test.tsx +0 -95
  245. package/src/mcp/react/hooks/__tests__/useToolInfo.test.tsx +0 -53
  246. package/src/mcp/react/hooks/__tests__/useToolInput.test.tsx +0 -50
  247. package/src/mcp/react/hooks/__tests__/useToolMetadata.test.tsx +0 -53
  248. package/src/mcp/react/hooks/__tests__/useToolName.test.tsx +0 -50
  249. package/src/mcp/react/hooks/useHostContext.ts +0 -14
  250. package/src/mcp/react/hooks/useToolInfo.ts +0 -13
  251. package/src/mcp/react/hooks/useToolInput.ts +0 -10
  252. package/src/mcp/react/hooks/useToolMetadata.ts +0 -5
  253. package/src/mcp/react/hooks/useToolName.ts +0 -10
  254. package/src/mcp/react/index.ts +0 -7
  255. package/src/openai/core/McpAppManager.ts +0 -139
  256. package/src/openai/link/ToolCallLink.ts +0 -40
  257. package/src/openai/react/hooks/__tests__/createHydrationUtils.test.tsx +0 -1333
  258. package/src/openai/react/hooks/__tests__/useToolInfo.test.tsx +0 -92
  259. package/src/openai/react/hooks/__tests__/useToolInput.test.tsx +0 -85
  260. package/src/openai/react/hooks/__tests__/useToolMetadata.test.tsx +0 -86
  261. package/src/openai/react/hooks/__tests__/useToolName.test.tsx +0 -50
  262. package/src/openai/react/hooks/createHydrationUtils.ts +0 -182
  263. package/src/openai/react/hooks/useApp.ts +0 -5
  264. package/src/openai/react/hooks/useToolInfo.ts +0 -13
  265. package/src/openai/react/hooks/useToolInput.ts +0 -10
  266. package/src/openai/react/hooks/useToolMetadata.ts +0 -5
  267. package/src/openai/react/hooks/useToolName.ts +0 -10
  268. package/src/react/index.mcp.ts +0 -10
  269. package/src/react/index.openai.ts +0 -10
  270. package/src/react/missingHook.ts +0 -9
  271. /package/dist/{mcp/react → react}/hooks/useApp.d.ts +0 -0
  272. /package/dist/{mcp/react → react}/hooks/useHostContext.d.ts +0 -0
package/src/mcp/index.ts CHANGED
@@ -1,2 +1 @@
1
1
  export { ApolloClient } from "./core/ApolloClient.js";
2
- export { ToolCallLink } from "./link/ToolCallLink.js";
@@ -1,172 +1,59 @@
1
- import type { ApolloLink } from "@apollo/client";
2
- import { ApolloClient as BaseApolloClient } from "@apollo/client";
3
- import { DocumentTransform } from "@apollo/client";
4
- import type {
5
- WatchQueryOptions,
6
- ObservableQuery,
7
- OperationVariables,
8
- } from "@apollo/client";
9
- import { removeDirectivesFromDocument } from "@apollo/client/utilities/internal";
10
- import { parse, visit } from "graphql";
11
- import { equal } from "@wry/equality";
12
- import { __DEV__ } from "@apollo/client/utilities/environment";
13
- import type { ApplicationManifest } from "../../types/application-manifest.js";
14
- import { ToolCallLink } from "../link/ToolCallLink.js";
15
- import {
16
- aiClientSymbol,
17
- cacheAsync,
18
- getToolNamesFromDocument,
19
- getVariablesForOperationFromToolInput,
20
- warnOnVariableMismatch,
21
- } from "../../utilities/index.js";
22
- import { McpAppManager } from "./McpAppManager.js";
23
- import { getVariableNamesFromDocument } from "../../utilities/getVariableNamesFromDocument.js";
1
+ import { AbstractApolloClient } from "../../core/AbstractApolloClient.js";
2
+ import { connectToHost, promiseWithResolvers } from "../../utilities/index.js";
3
+ import type { ApolloMcpServerApps } from "../../core/types.js";
24
4
 
25
5
  export declare namespace ApolloClient {
26
- export interface Options extends Omit<BaseApolloClient.Options, "link"> {
27
- link?: BaseApolloClient.Options["link"];
28
- manifest: ApplicationManifest;
29
- }
6
+ export interface Options extends AbstractApolloClient.Options {}
30
7
  }
31
8
 
32
- export class ApolloClient extends BaseApolloClient {
33
- manifest: ApplicationManifest;
34
- private readonly appManager: McpAppManager;
35
-
36
- /** @internal */
37
- readonly [aiClientSymbol] = true;
38
-
39
- #toolInput: Record<string, unknown> | undefined;
40
-
9
+ export class ApolloClient extends AbstractApolloClient {
41
10
  constructor(options: ApolloClient.Options) {
42
- const link = options.link ?? new ToolCallLink();
43
-
44
- if (__DEV__) {
45
- validateTerminatingLink(link);
46
- }
47
-
48
- super({
49
- ...options,
50
- link,
51
- // Strip out the prefetch/tool directives so they don't get sent with the operation to the server
52
- documentTransform: new DocumentTransform((document) => {
53
- const serverDocument = removeDirectivesFromDocument(
54
- [{ name: "prefetch" }, { name: "tool" }],
55
- document
56
- )!;
57
-
58
- return visit(serverDocument, {
59
- OperationDefinition(node) {
60
- return { ...node, description: undefined };
61
- },
62
- });
63
- }).concat(options.documentTransform ?? DocumentTransform.identity()),
64
- });
65
-
66
- this.manifest = options.manifest;
67
- this.appManager = new McpAppManager(this.manifest);
68
- }
69
-
70
- stop() {
71
- super.stop();
72
- this.appManager.close().catch(() => {});
73
- }
74
-
75
- get toolInput() {
76
- return this.#toolInput;
77
- }
78
-
79
- clearToolInput() {
80
- this.#toolInput = undefined;
81
- }
82
-
83
- watchQuery<
84
- T = any,
85
- TVariables extends OperationVariables = OperationVariables,
86
- >(options: WatchQueryOptions<TVariables, T>): ObservableQuery<T, TVariables> {
87
- if (__DEV__) {
88
- const toolInput = this.#toolInput;
89
-
90
- if (toolInput) {
91
- const toolName = this.appManager.toolName;
92
- const hasMatchingTool =
93
- !!toolName && getToolNamesFromDocument(options.query).has(toolName);
94
-
95
- if (hasMatchingTool) {
96
- // Clear after first matching comparison so this only fires once and
97
- // remounting doesn't produce spurious warnings.
98
- this.#toolInput = undefined;
99
-
100
- const variableNames = getVariableNamesFromDocument(options.query);
101
-
102
- if (variableNames.size > 0) {
103
- const { variables } = options;
104
-
105
- const toolInputVariables = Object.entries(toolInput).filter(
106
- ([key]) => variableNames.has(key)
107
- );
108
-
109
- const hasToolInputMismatch = toolInputVariables.some(
110
- ([key, value]) => !equal(value, variables?.[key])
111
- );
112
-
113
- if (hasToolInputMismatch) {
114
- warnOnVariableMismatch(
115
- options.query,
116
- Object.fromEntries(toolInputVariables),
117
- variables
118
- );
119
- }
120
- }
121
- }
122
- }
123
- }
124
-
125
- return super.watchQuery(options);
126
- }
127
-
128
- connect = cacheAsync(async () => {
129
- const { prefetch, result, toolName, args } =
130
- await this.appManager.connect();
131
-
132
- this.#toolInput = args;
133
-
134
- this.manifest.operations.forEach((operation) => {
135
- if (operation.prefetchID && prefetch?.[operation.prefetchID]) {
136
- this.writeQuery({
137
- query: parse(operation.body),
138
- data: prefetch[operation.prefetchID].data,
11
+ super(options, async (app) => {
12
+ const toolResult =
13
+ promiseWithResolvers<ApolloMcpServerApps.CallToolResult>();
14
+
15
+ app.ontoolresult = (params) => {
16
+ toolResult.resolve(
17
+ params as unknown as ApolloMcpServerApps.CallToolResult
18
+ );
19
+ };
20
+
21
+ await connectToHost(app);
22
+
23
+ // After a page refresh, OpenAI does not re-send `ui/notifications/tool-result`.
24
+ // Instead, the tool result is available immediately via `window.openai.toolOutput`.
25
+ // If it's already set, resolve the promise now rather than waiting for the
26
+ // notification that will never arrive.
27
+ if (window.openai.toolOutput !== null) {
28
+ toolResult.resolve({
29
+ structuredContent: window.openai.toolOutput,
30
+ content: [],
139
31
  });
140
32
  }
141
33
 
142
- if (operation.tools.find((tool) => tool.name === toolName)) {
143
- this.writeQuery({
144
- query: parse(operation.body),
145
- data: result.data,
146
- variables: getVariablesForOperationFromToolInput(operation, args),
147
- });
148
- }
34
+ const { structuredContent } = await toolResult.promise;
35
+
36
+ return {
37
+ structuredContent,
38
+ // OpenAI is not consistent about sending `ui/notifications/tool-input`.
39
+ // Sometimes it doesn't send at all, other times it sends more than once
40
+ // before we get the tool result (which should always happen and at most
41
+ // once according to the spec). Rather than relying on the
42
+ // `ui/notifications/tool-input` notification to set the tool input value,
43
+ // we read from `window.openai.toolInput so that we have the most recent
44
+ // set value.
45
+ //
46
+ // When OpenAI fixes this issue and sends `ui/notifications/tool-input`
47
+ // consistently according to the MCP Apps specification, this can be
48
+ // reverted to use the `app.ontoolinput` callback.
49
+ toolInput: window.openai.toolInput,
50
+
51
+ // OpenAI doesn't provide access to `_meta` from ui/notifications/tool-result,
52
+ // so we need to use window.openai.toolResponseMetadata directly
53
+ _meta: window.openai.toolResponseMetadata as
54
+ | ApolloMcpServerApps.Meta
55
+ | undefined,
56
+ };
149
57
  });
150
- });
151
- }
152
-
153
- function validateTerminatingLink(link: ApolloLink) {
154
- let terminatingLink = link;
155
-
156
- while (terminatingLink.right) {
157
- terminatingLink = terminatingLink.right;
158
- }
159
-
160
- if (
161
- !isNamedLink(terminatingLink) ||
162
- terminatingLink.name !== "ToolCallLink"
163
- ) {
164
- throw new Error(
165
- "The terminating link must be a `ToolCallLink`. If you are using a `split` link, ensure the `right` branch uses a `ToolCallLink` as the terminating link."
166
- );
167
58
  }
168
59
  }
169
-
170
- function isNamedLink(link: ApolloLink): link is ApolloLink & { name: string } {
171
- return "name" in link;
172
- }