@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
@@ -0,0 +1,99 @@
1
+ import { expect, test } from "vitest";
2
+ import { gql, InMemoryCache } from "@apollo/client";
3
+ import { execute } from "@apollo/client/link";
4
+ import {
5
+ eachHostEnv,
6
+ mockApplicationManifest,
7
+ ObservableStream,
8
+ spyOnConsole,
9
+ } from "../../testing/internal/index.js";
10
+ import { ToolCallLink } from "../ToolCallLink.js";
11
+
12
+ eachHostEnv((setupHost, ApolloClient) => {
13
+ test("merges _meta.structuredContent into result for @private fields", async () => {
14
+ using _ = spyOnConsole("debug");
15
+ const query = gql`
16
+ query GreetingQuery {
17
+ greeting @private
18
+ }
19
+ `;
20
+
21
+ const client = new ApolloClient({
22
+ cache: new InMemoryCache(),
23
+ manifest: mockApplicationManifest(),
24
+ });
25
+
26
+ using env = await setupHost({
27
+ client,
28
+ toolCall: {
29
+ name: "GetProduct",
30
+ result: { structuredContent: { result: { data: { product: null } } } },
31
+ },
32
+ });
33
+ const { host, params } = env;
34
+
35
+ host.sendToolInput(params.toolInput);
36
+ host.sendToolResult(params.toolResult);
37
+
38
+ host.mockToolCall("execute", () => ({
39
+ structuredContent: {},
40
+ _meta: {
41
+ structuredContent: { data: { greeting: "Hello, private world" } },
42
+ },
43
+ }));
44
+
45
+ await client.connect();
46
+
47
+ const observable = execute(new ToolCallLink(), { query }, { client });
48
+ const stream = new ObservableStream(observable);
49
+
50
+ await expect(stream).toEmitValue({
51
+ data: { greeting: "Hello, private world" },
52
+ });
53
+
54
+ await expect(stream).toComplete();
55
+ });
56
+
57
+ test("delegates query execution to MCP host", async () => {
58
+ using _ = spyOnConsole("debug");
59
+ const query = gql`
60
+ query GreetingQuery {
61
+ greeting
62
+ }
63
+ `;
64
+
65
+ const client = new ApolloClient({
66
+ cache: new InMemoryCache(),
67
+ manifest: mockApplicationManifest(),
68
+ });
69
+
70
+ using env = await setupHost({
71
+ client,
72
+ toolCall: {
73
+ name: "GetProduct",
74
+ result: { structuredContent: { result: { data: { product: null } } } },
75
+ },
76
+ });
77
+ const { host, params } = env;
78
+
79
+ host.sendToolInput(params.toolInput);
80
+ host.sendToolResult(params.toolResult);
81
+
82
+ host.mockToolCall("execute", () => ({
83
+ structuredContent: {
84
+ data: { greeting: "Hello, world" },
85
+ },
86
+ }));
87
+
88
+ await client.connect();
89
+
90
+ const observable = execute(new ToolCallLink(), { query }, { client });
91
+ const stream = new ObservableStream(observable);
92
+
93
+ await expect(stream).toEmitValue({
94
+ data: { greeting: "Hello, world" },
95
+ });
96
+
97
+ await expect(stream).toComplete();
98
+ });
99
+ });
@@ -1,178 +1,40 @@
1
- import {
2
- ApolloLink,
3
- ApolloClient as BaseApolloClient,
4
- DocumentTransform,
5
- } from "@apollo/client";
6
- import type {
7
- WatchQueryOptions,
8
- ObservableQuery,
9
- OperationVariables,
10
- } from "@apollo/client";
11
- import { removeDirectivesFromDocument } from "@apollo/client/utilities/internal";
12
- import { parse, visit } from "graphql";
13
- import { equal } from "@wry/equality";
14
- import { __DEV__ } from "@apollo/client/utilities/environment";
15
- import type { ApplicationManifest } from "../../types/application-manifest.js";
16
- import { ToolCallLink } from "../link/ToolCallLink.js";
17
- import {
18
- aiClientSymbol,
19
- cacheAsync,
20
- getToolNamesFromDocument,
21
- getVariableNamesFromDocument,
22
- getVariablesForOperationFromToolInput,
23
- warnOnVariableMismatch,
24
- } from "../../utilities/index.js";
25
- import { McpAppManager } from "./McpAppManager.js";
1
+ import type { App } from "@modelcontextprotocol/ext-apps";
2
+ import { AbstractApolloClient } from "../../core/AbstractApolloClient.js";
3
+ import { connectToHost, promiseWithResolvers } from "../../utilities/index.js";
4
+ import type { ApolloMcpServerApps } from "../../core/types.js";
26
5
 
27
6
  export declare namespace ApolloClient {
28
- export interface Options extends Omit<BaseApolloClient.Options, "link"> {
29
- link?: BaseApolloClient.Options["link"];
30
- manifest: ApplicationManifest;
31
- }
7
+ export interface Options extends AbstractApolloClient.Options {}
32
8
  }
33
9
 
34
- export class ApolloClient extends BaseApolloClient {
35
- manifest: ApplicationManifest;
36
- private readonly appManager: McpAppManager;
37
-
38
- /** @internal */
39
- readonly [aiClientSymbol] = true;
40
-
41
- #toolInput: Record<string, unknown> | undefined;
42
-
10
+ export class ApolloClient extends AbstractApolloClient {
43
11
  constructor(options: ApolloClient.Options) {
44
- const link = options.link ?? new ToolCallLink();
45
-
46
- if (__DEV__) {
47
- validateTerminatingLink(link);
48
- }
49
-
50
- super({
51
- ...options,
52
- link,
53
- // Strip out the prefetch/tool directives so they don't get sent with the operation to the server
54
- documentTransform: new DocumentTransform((document) => {
55
- const serverDocument = removeDirectivesFromDocument(
56
- [{ name: "prefetch" }, { name: "tool" }],
57
- document
58
- )!;
59
-
60
- return visit(serverDocument, {
61
- OperationDefinition(node) {
62
- return { ...node, description: undefined };
63
- },
64
- });
65
- }).concat(options.documentTransform ?? DocumentTransform.identity()),
66
- });
67
-
68
- this.manifest = options.manifest;
69
- this.appManager = new McpAppManager(this.manifest);
70
- }
71
-
72
- stop() {
73
- super.stop();
74
- this.appManager.close().catch(() => {});
75
- }
76
-
77
- get toolInput() {
78
- return this.#toolInput;
79
- }
80
-
81
- clearToolInput() {
82
- this.#toolInput = undefined;
83
- }
84
-
85
- watchQuery<
86
- T = any,
87
- TVariables extends OperationVariables = OperationVariables,
88
- >(options: WatchQueryOptions<TVariables, T>): ObservableQuery<T, TVariables> {
89
- if (__DEV__) {
90
- const toolInput = this.#toolInput;
91
-
92
- if (toolInput) {
93
- const toolName = this.appManager.toolName;
94
- const hasMatchingTool =
95
- !!toolName && getToolNamesFromDocument(options.query).has(toolName);
96
-
97
- if (hasMatchingTool) {
98
- // Clear after first matching comparison so this only fires once and
99
- // remounting doesn't produce spurious warnings.
100
- this.#toolInput = undefined;
101
-
102
- const variableNames = getVariableNamesFromDocument(options.query);
103
-
104
- if (variableNames.size > 0) {
105
- const { variables } = options;
106
- const toolInputVariables = Object.entries(toolInput).filter(
107
- ([key]) => variableNames.has(key)
108
- );
109
-
110
- const hasToolInputMismatch = toolInputVariables.some(
111
- ([key, value]) => !equal(value, variables?.[key])
112
- );
113
-
114
- if (hasToolInputMismatch) {
115
- warnOnVariableMismatch(
116
- options.query,
117
- Object.fromEntries(toolInputVariables),
118
- variables
119
- );
120
- }
121
- }
122
- }
123
- }
124
- }
125
-
126
- return super.watchQuery(options);
127
- }
128
-
129
- connect = cacheAsync(async () => {
130
- const { structuredContent, toolName, args } =
131
- await this.appManager.connect();
132
-
133
- this.#toolInput = args;
134
-
135
- this.manifest.operations.forEach((operation) => {
136
- if (
137
- operation.prefetchID &&
138
- structuredContent.prefetch?.[operation.prefetchID]
139
- ) {
140
- this.writeQuery({
141
- query: parse(operation.body),
142
- data: structuredContent.prefetch[operation.prefetchID].data,
143
- });
144
- }
145
-
146
- if (operation.tools.find((tool) => tool.name === toolName)) {
147
- if (structuredContent.result?.data) {
148
- this.writeQuery({
149
- query: parse(operation.body),
150
- data: structuredContent.result.data,
151
- variables: getVariablesForOperationFromToolInput(operation, args),
152
- });
153
- }
154
- }
12
+ super(options, async (app) => {
13
+ const toolResult =
14
+ promiseWithResolvers<ApolloMcpServerApps.CallToolResult>();
15
+ const toolInput =
16
+ promiseWithResolvers<Parameters<App["ontoolinput"]>[0]>();
17
+
18
+ app.ontoolresult = (params) => {
19
+ toolResult.resolve(
20
+ params as unknown as ApolloMcpServerApps.CallToolResult
21
+ );
22
+ };
23
+
24
+ app.ontoolinput = (params) => {
25
+ toolInput.resolve(params);
26
+ };
27
+
28
+ await connectToHost(app);
29
+
30
+ const { structuredContent, _meta } = await toolResult.promise;
31
+ const { arguments: args } = await toolInput.promise;
32
+
33
+ return {
34
+ structuredContent,
35
+ toolInput: args,
36
+ _meta,
37
+ };
155
38
  });
156
- });
157
- }
158
-
159
- function validateTerminatingLink(link: ApolloLink) {
160
- let terminatingLink = link;
161
-
162
- while (terminatingLink.right) {
163
- terminatingLink = terminatingLink.right;
164
39
  }
165
-
166
- if (
167
- !isNamedLink(terminatingLink) ||
168
- terminatingLink.name !== "ToolCallLink"
169
- ) {
170
- throw new Error(
171
- "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."
172
- );
173
- }
174
- }
175
-
176
- function isNamedLink(link: ApolloLink): link is ApolloLink & { name: string } {
177
- return "name" in link;
178
40
  }