@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 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utilities/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,qCAAqC,EAAE,MAAM,4CAA4C,CAAC;AACnG,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC","sourcesContent":["export { aiClientSymbol } from \"./constants.js\";\nexport { getVariablesForOperationFromToolInput } from \"./getVariablesForOperationFromToolInput.js\";\nexport { getToolNamesFromDocument } from \"./getToolNamesFromDocument.js\";\nexport { getVariableNamesFromDocument } from \"./getVariableNamesFromDocument.js\";\nexport { cacheAsync } from \"./cacheAsync.js\";\nexport { invariant } from \"./invariant.js\";\nexport { promiseWithResolvers } from \"./promiseWithResolvers.js\";\nexport { warnOnVariableMismatch } from \"./warnOnVariableMismatch.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utilities/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,qCAAqC,EAAE,MAAM,4CAA4C,CAAC;AACnG,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC","sourcesContent":["export { aiClientSymbol } from \"./constants.js\";\nexport { connectToHost } from \"./connectToHost.js\";\nexport { getVariablesForOperationFromToolInput } from \"./getVariablesForOperationFromToolInput.js\";\nexport { getToolNamesFromDocument } from \"./getToolNamesFromDocument.js\";\nexport { getVariableNamesFromDocument } from \"./getVariableNamesFromDocument.js\";\nexport { cacheAsync } from \"./cacheAsync.js\";\nexport { invariant } from \"./invariant.js\";\nexport { promiseWithResolvers } from \"./promiseWithResolvers.js\";\nexport { warnOnVariableMismatch } from \"./warnOnVariableMismatch.js\";\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://www.schemastore.org/package.json",
3
3
  "name": "@apollo/client-ai-apps",
4
- "version": "0.6.5",
4
+ "version": "0.7.0",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -38,13 +38,6 @@
38
38
  },
39
39
  "default": "./dist/utilities/emptyModule.js"
40
40
  },
41
- "./mcp/react": {
42
- "mcp": {
43
- "types": "./dist/mcp/react/index.d.ts",
44
- "default": "./dist/mcp/react/index.js"
45
- },
46
- "default": "./dist/utilities/emptyModule.js"
47
- },
48
41
  "./openai": {
49
42
  "openai": {
50
43
  "types": "./dist/openai/index.d.ts",
@@ -67,18 +60,8 @@
67
60
  "default": "./dist/utilities/emptyModule.js"
68
61
  },
69
62
  "./react": {
70
- "mcp": {
71
- "types": "./dist/react/index.mcp.d.ts",
72
- "default": "./dist/react/index.mcp.js"
73
- },
74
- "openai": {
75
- "types": "./dist/react/index.openai.d.ts",
76
- "default": "./dist/react/index.openai.js"
77
- },
78
- "default": {
79
- "types": "./dist/react/index.d.ts",
80
- "default": "./dist/react/index.js"
81
- }
63
+ "types": "./dist/react/index.d.ts",
64
+ "default": "./dist/react/index.js"
82
65
  },
83
66
  "./tsconfig/core": "./dist/tsconfig/core/tsconfig.json",
84
67
  "./tsconfig/mcp": "./dist/tsconfig/mcp/tsconfig.json",
@@ -123,7 +106,7 @@
123
106
  "@types/node": "^24.10.4",
124
107
  "@types/react": "^19.2.2",
125
108
  "@vitejs/plugin-react": "^5.1.1",
126
- "@vitest/coverage-v8": "^4.0.13",
109
+ "@vitest/coverage-v8": "^4.1.0",
127
110
  "copyfiles": "^2.4.1",
128
111
  "esbuild": "^0.25.12",
129
112
  "graphql": "^16.12.0",
@@ -136,7 +119,7 @@
136
119
  "rxjs": "^7.8.1",
137
120
  "typescript": "^5.9.3",
138
121
  "vite": "^7.3.1",
139
- "vitest": "^4.0.13"
122
+ "vitest": "^4.1.0"
140
123
  },
141
124
  "peerDependencies": {
142
125
  "@apollo/client": "^4.0.0",
@@ -0,0 +1,217 @@
1
+ import {
2
+ ApolloLink,
3
+ ApolloClient as NativeApolloClient,
4
+ DocumentTransform,
5
+ ObservableQuery,
6
+ type OperationVariables,
7
+ type WatchQueryOptions,
8
+ } from "@apollo/client";
9
+ import { __DEV__ } from "@apollo/client/utilities/environment";
10
+ import { removeDirectivesFromDocument } from "@apollo/client/utilities/internal";
11
+ import { parse, visit } from "graphql";
12
+ import { equal } from "@wry/equality";
13
+ import type { ApplicationManifest } from "../types/application-manifest.js";
14
+ import { aiClientSymbol } from "../utilities/constants.js";
15
+ import {
16
+ McpAppManager,
17
+ type ConnectToHostImplementation,
18
+ } from "./McpAppManager.js";
19
+ import { ToolHydrationLink } from "../link/ToolHydrationLink.js";
20
+ import { ToolCallLink } from "../link/ToolCallLink.js";
21
+ import {
22
+ cacheAsync,
23
+ getToolNamesFromDocument,
24
+ getVariableNamesFromDocument,
25
+ getVariablesForOperationFromToolInput,
26
+ warnOnVariableMismatch,
27
+ } from "../utilities/index.js";
28
+ import type { ApolloMcpServerApps } from "./types.js";
29
+ import type { ToolInfo } from "./typeRegistration.js";
30
+
31
+ export declare namespace AbstractApolloClient {
32
+ export interface Options extends Omit<NativeApolloClient.Options, "link"> {
33
+ link?: NativeApolloClient.Options["link"];
34
+ manifest: ApplicationManifest;
35
+ }
36
+ }
37
+
38
+ export class AbstractApolloClient extends NativeApolloClient {
39
+ manifest: ApplicationManifest;
40
+ private readonly appManager: McpAppManager;
41
+
42
+ /** @internal */
43
+ readonly [aiClientSymbol] = true;
44
+
45
+ #hydratedToolInput: Record<string, unknown> | undefined;
46
+ #toolHydrationLink: ToolHydrationLink;
47
+
48
+ #toolInfo: ToolInfo | undefined;
49
+ #toolMetadata: ApolloMcpServerApps.CallToolResult["_meta"] | undefined;
50
+
51
+ constructor(
52
+ options: AbstractApolloClient.Options,
53
+ connectToHost: ConnectToHostImplementation
54
+ ) {
55
+ const toolHydrationLink = new ToolHydrationLink();
56
+ const link = options.link ?? new ToolCallLink();
57
+
58
+ if (__DEV__) {
59
+ validateTerminatingLink(link);
60
+ }
61
+
62
+ super({
63
+ ...options,
64
+ link: toolHydrationLink.concat(link),
65
+ // Strip out the prefetch/tool directives so they don't get sent with the operation to the server
66
+ documentTransform: new DocumentTransform((document) => {
67
+ const serverDocument = removeDirectivesFromDocument(
68
+ [{ name: "prefetch" }, { name: "tool" }],
69
+ document
70
+ )!;
71
+
72
+ return visit(serverDocument, {
73
+ OperationDefinition(node) {
74
+ return { ...node, description: undefined };
75
+ },
76
+ });
77
+ }).concat(options.documentTransform ?? DocumentTransform.identity()),
78
+ });
79
+
80
+ this.#toolHydrationLink = toolHydrationLink;
81
+ this.manifest = options.manifest;
82
+ this.appManager = new McpAppManager(this.manifest, connectToHost);
83
+ }
84
+
85
+ get toolInfo() {
86
+ return this.#toolInfo;
87
+ }
88
+
89
+ get toolMetadata() {
90
+ return this.#toolMetadata;
91
+ }
92
+
93
+ setLink(newLink: ApolloLink): void {
94
+ super.setLink(this.#toolHydrationLink.concat(newLink));
95
+ }
96
+
97
+ stop() {
98
+ super.stop();
99
+ this.appManager.close().catch(() => {});
100
+ }
101
+
102
+ protected get hydratedToolInput() {
103
+ return this.#hydratedToolInput;
104
+ }
105
+
106
+ protected clearHydratedToolInput() {
107
+ this.#hydratedToolInput = undefined;
108
+ }
109
+
110
+ watchQuery<
111
+ T = any,
112
+ TVariables extends OperationVariables = OperationVariables,
113
+ >(options: WatchQueryOptions<TVariables, T>): ObservableQuery<T, TVariables> {
114
+ if (__DEV__) {
115
+ const toolInput = this.#hydratedToolInput;
116
+
117
+ if (toolInput) {
118
+ const toolName = this.toolInfo?.toolName;
119
+ const hasMatchingTool =
120
+ !!toolName && getToolNamesFromDocument(options.query).has(toolName);
121
+
122
+ if (hasMatchingTool) {
123
+ // Clear after first matching comparison so this only fires once and
124
+ // remounting doesn't produce spurious warnings.
125
+ this.#hydratedToolInput = undefined;
126
+
127
+ const variableNames = getVariableNamesFromDocument(options.query);
128
+
129
+ if (variableNames.size > 0) {
130
+ const { variables } = options;
131
+ const toolInputVariables = Object.entries(toolInput).filter(
132
+ ([key]) => variableNames.has(key)
133
+ );
134
+
135
+ const hasToolInputMismatch = toolInputVariables.some(
136
+ ([key, value]) => !equal(value, variables?.[key])
137
+ );
138
+
139
+ if (hasToolInputMismatch) {
140
+ warnOnVariableMismatch(
141
+ options.query,
142
+ Object.fromEntries(toolInputVariables),
143
+ variables
144
+ );
145
+ }
146
+ }
147
+ }
148
+ }
149
+ }
150
+
151
+ return super.watchQuery(options);
152
+ }
153
+
154
+ connect = cacheAsync(async () => {
155
+ const { structuredContent, toolName, toolInput, _meta } =
156
+ await this.appManager.connect();
157
+
158
+ this.#hydratedToolInput = toolInput;
159
+ this.#toolMetadata = _meta;
160
+
161
+ if (toolName != null) {
162
+ this.#toolInfo = { toolName, toolInput };
163
+ }
164
+
165
+ this.manifest.operations.forEach((operation) => {
166
+ if (
167
+ operation.prefetchID &&
168
+ structuredContent.prefetch?.[operation.prefetchID]
169
+ ) {
170
+ this.writeQuery({
171
+ query: parse(operation.body),
172
+ data: structuredContent.prefetch[operation.prefetchID].data,
173
+ });
174
+ this.#toolHydrationLink.hydrate(operation, {
175
+ result: structuredContent.prefetch[operation.prefetchID],
176
+ variables: {},
177
+ });
178
+ }
179
+
180
+ if (
181
+ structuredContent.result &&
182
+ operation.tools.find((tool) => tool.name === toolName)
183
+ ) {
184
+ this.#toolHydrationLink.hydrate(operation, {
185
+ result: structuredContent.result,
186
+ variables: getVariablesForOperationFromToolInput(
187
+ operation,
188
+ toolInput
189
+ ),
190
+ });
191
+ }
192
+ });
193
+
194
+ this.#toolHydrationLink.complete();
195
+ });
196
+ }
197
+
198
+ function validateTerminatingLink(link: ApolloLink) {
199
+ let terminatingLink = link;
200
+
201
+ while (terminatingLink.right) {
202
+ terminatingLink = terminatingLink.right;
203
+ }
204
+
205
+ if (
206
+ !isNamedLink(terminatingLink) ||
207
+ terminatingLink.name !== "ToolCallLink"
208
+ ) {
209
+ throw new Error(
210
+ "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."
211
+ );
212
+ }
213
+ }
214
+
215
+ function isNamedLink(link: ApolloLink): link is ApolloLink & { name: string } {
216
+ return "name" in link;
217
+ }
@@ -1,25 +1,23 @@
1
- import { ApolloClient as BaseApolloClient } from "@apollo/client";
2
- import type { ApplicationManifest } from "../types/application-manifest.js";
1
+ import { AbstractApolloClient } from "./AbstractApolloClient.js";
3
2
  import { aiClientSymbol } from "../utilities/constants.js";
4
3
 
5
4
  export declare namespace ApolloClient {
6
- export interface Options extends Omit<BaseApolloClient.Options, "link"> {
7
- link?: BaseApolloClient.Options["link"];
8
- manifest: ApplicationManifest;
9
- }
5
+ export interface Options extends AbstractApolloClient.Options {}
10
6
  }
11
7
 
12
- export class ApolloClient extends BaseApolloClient {
8
+ export class ApolloClient extends AbstractApolloClient {
13
9
  /** @internal */
14
10
  readonly [aiClientSymbol] = true;
15
11
 
16
12
  constructor(options: ApolloClient.Options) {
17
- super(options as any);
13
+ super(options as any, () => {
14
+ throw new Error(
15
+ "Cannot connect an `ApolloClient` instance from `@apollo/client-ai-apps` without export conditions. Please set conditions or import from the `/openai` or `/mcp` subpath directly."
16
+ );
17
+ });
18
18
 
19
19
  throw new Error(
20
20
  "Cannot construct an `ApolloClient` instance from `@apollo/client-ai-apps` without export conditions. Please set conditions or import from the `/openai` or `/mcp` subpath directly."
21
21
  );
22
22
  }
23
-
24
- async connect() {}
25
23
  }
@@ -0,0 +1,106 @@
1
+ import {
2
+ App,
3
+ type McpUiHostContextChangedNotification,
4
+ } from "@modelcontextprotocol/ext-apps";
5
+ import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
6
+ import type { ApplicationManifest } from "../types/application-manifest.js";
7
+ import type { FormattedExecutionResult } from "graphql";
8
+ import type { DocumentNode, OperationVariables } from "@apollo/client";
9
+ import { print } from "@apollo/client/utilities";
10
+ import { cacheAsync } from "../utilities/index.js";
11
+ import type { ApolloMcpServerApps } from "./types.js";
12
+
13
+ type ExecuteQueryCallToolResult = Omit<CallToolResult, "structuredContent"> & {
14
+ structuredContent: FormattedExecutionResult;
15
+ _meta?: { structuredContent?: FormattedExecutionResult };
16
+ };
17
+
18
+ interface ConnectToHostResult {
19
+ structuredContent: ApolloMcpServerApps.StructuredContent;
20
+ toolInput: Record<string, unknown> | undefined;
21
+ _meta: ApolloMcpServerApps.Meta | undefined;
22
+ }
23
+
24
+ export type ConnectToHostImplementation = (
25
+ app: App
26
+ ) => Promise<ConnectToHostResult>;
27
+
28
+ /** @internal */
29
+ export class McpAppManager {
30
+ readonly app: App;
31
+
32
+ #connectToHost: ConnectToHostImplementation;
33
+
34
+ #hostContextCallbacks = new Set<
35
+ (params: McpUiHostContextChangedNotification["params"]) => void
36
+ >();
37
+
38
+ constructor(
39
+ manifest: ApplicationManifest,
40
+ connectToHost: ConnectToHostImplementation
41
+ ) {
42
+ this.app = new App({ name: manifest.name, version: manifest.appVersion });
43
+ this.#connectToHost = connectToHost;
44
+ }
45
+
46
+ onHostContextChanged(
47
+ cb: (params: McpUiHostContextChangedNotification["params"]) => void
48
+ ) {
49
+ this.#hostContextCallbacks.add(cb);
50
+
51
+ return () => {
52
+ this.#hostContextCallbacks.delete(cb);
53
+ };
54
+ }
55
+
56
+ connect = cacheAsync(async () => {
57
+ this.app.onhostcontextchanged = (params) => {
58
+ this.#hostContextCallbacks.forEach((cb) => cb(params));
59
+ };
60
+
61
+ const { structuredContent, _meta, toolInput } = await this.#connectToHost(
62
+ this.app
63
+ );
64
+
65
+ return {
66
+ structuredContent: {
67
+ ...structuredContent,
68
+ ..._meta?.structuredContent,
69
+ },
70
+ toolInput,
71
+ // Some hosts do not provide toolInfo in the ui/initialize response, so we
72
+ // fallback to `_meta.toolName` provided by Apollo MCP server if the value
73
+ // is not available.
74
+ toolName:
75
+ this.app.getHostContext()?.toolInfo?.tool.name ??
76
+ _meta?.toolName ??
77
+ // Some hosts do not forward `_meta` nor do they provide `toolInfo`. Our
78
+ // MCP server provides `toolName` in `structuredContent` as a workaround
79
+ // that we can use if all else fails
80
+ structuredContent.toolName,
81
+ _meta,
82
+ };
83
+ });
84
+
85
+ close() {
86
+ return this.app.close();
87
+ }
88
+
89
+ async executeQuery({
90
+ query,
91
+ variables,
92
+ }: {
93
+ query: DocumentNode;
94
+ variables: OperationVariables | undefined;
95
+ }) {
96
+ const result = (await this.app.callServerTool({
97
+ name: "execute",
98
+ arguments: { query: print(query), variables },
99
+ })) as ExecuteQueryCallToolResult;
100
+
101
+ return {
102
+ ...result.structuredContent,
103
+ ...result._meta?.structuredContent,
104
+ };
105
+ }
106
+ }
@@ -1,24 +1,9 @@
1
1
  export interface Register {}
2
2
 
3
- /**
4
- * @deprecated Please use the `ToolInfo` type instead. `ToolName` will be
5
- * removed in the next major version.
6
- */
7
- export type ToolName =
8
- Register extends { toolName: infer T extends string } ? T : string;
9
-
10
3
  type RegisteredToolInputs =
11
4
  Register extends { toolInputs: infer T extends Record<string, unknown> } ? T
12
5
  : never;
13
6
 
14
- /**
15
- * @deprecated Please use the `ToolInfo` type instead. `ToolInput` will be
16
- * removed in the next major version.
17
- */
18
- export type ToolInput =
19
- [RegisteredToolInputs] extends [never] ? Record<string, unknown>
20
- : RegisteredToolInputs[keyof RegisteredToolInputs];
21
-
22
7
  type ToolInfoFromInputs<T extends Record<string, unknown>> = {
23
8
  [K in keyof T]: {
24
9
  toolName: K;
package/src/index.mcp.ts CHANGED
@@ -2,4 +2,3 @@ export * from "./index.js";
2
2
 
3
3
  export { Platform } from "./mcp/core/Platform.js";
4
4
  export { ApolloClient } from "./mcp/core/ApolloClient.js";
5
- export { ToolCallLink } from "./mcp/link/ToolCallLink.js";
@@ -2,4 +2,3 @@ export * from "./index.js";
2
2
 
3
3
  export { Platform } from "./openai/core/Platform.js";
4
4
  export { ApolloClient } from "./openai/core/ApolloClient.js";
5
- export { ToolCallLink } from "./openai/link/ToolCallLink.js";
package/src/index.ts CHANGED
@@ -8,12 +8,7 @@ export type {
8
8
  ManifestWidgetSettings,
9
9
  } from "./types/application-manifest.js";
10
10
 
11
- export type {
12
- Register,
13
- ToolInfo,
14
- ToolInput,
15
- ToolName,
16
- } from "./core/typeRegistration.js";
11
+ export type { Register, ToolInfo } from "./core/typeRegistration.js";
17
12
 
18
13
  export { ApolloClient } from "./core/ApolloClient.js";
19
14
  export { ToolCallLink } from "./link/ToolCallLink.js";
@@ -1,4 +1,9 @@
1
- import { ApolloLink } from "@apollo/client";
1
+ import { ApolloClient, ApolloLink } from "@apollo/client";
2
+ import { __DEV__ } from "@apollo/client/utilities/environment";
3
+ import { from } from "rxjs";
4
+
5
+ import type { McpAppManager } from "../core/McpAppManager";
6
+ import { aiClientSymbol, invariant } from "../utilities/index.js";
2
7
 
3
8
  /**
4
9
  * A terminating link that sends a GraphQL request through an agent tool call.
@@ -23,11 +28,28 @@ import { ApolloLink } from "@apollo/client";
23
28
  * ```
24
29
  */
25
30
  export class ToolCallLink extends ApolloLink {
26
- constructor() {
27
- super();
31
+ readonly name = "ToolCallLink";
32
+ request(operation: ApolloLink.Operation) {
33
+ const client = getPrivateAccess(operation.client);
34
+
35
+ return from(
36
+ client.appManager.executeQuery({
37
+ query: operation.query,
38
+ variables: operation.variables,
39
+ })
40
+ );
41
+ }
42
+ }
28
43
 
29
- throw new Error(
30
- "Cannot construct a `ToolCallLink` from `@apollo/client-ai-apps` without export conditions. Please set export conditions or import from the `/openai` or `/mcp` subpath directly."
44
+ function getPrivateAccess(
45
+ client: ApolloClient
46
+ ): ApolloClient & { appManager: McpAppManager } {
47
+ if (__DEV__) {
48
+ invariant(
49
+ (client as any)[aiClientSymbol],
50
+ 'The "client" instance used with `ToolCallLink` is the wrong instance. You might have imported `ApolloClient` from `@apollo/client`. Please import `ApolloClient` from `@apollo/client-ai-apps` instead.'
31
51
  );
32
52
  }
53
+
54
+ return client as any;
33
55
  }
@@ -0,0 +1,90 @@
1
+ import { ApolloLink, Observable } from "@apollo/client";
2
+ import type { OperationVariables } from "@apollo/client";
3
+ import { canonicalStringify } from "@apollo/client/utilities";
4
+ import type { FormattedExecutionResult } from "graphql";
5
+ import { of } from "rxjs";
6
+ import type { ManifestOperation } from "../types/application-manifest.js";
7
+
8
+ type ResolveFn = () => void;
9
+ type OperationKey = string & { __type: "PendingKey" };
10
+
11
+ /**
12
+ * @internal
13
+ * Holds requests until the client is fully hydrated after a tool call. It is
14
+ * particularly useful for `network-only` and `cache-and-network` fetch policies
15
+ * where the request makes it to the link chain because it prevents a followup
16
+ * tool call to the MCP server for the just fetched data from the MCP server.
17
+ */
18
+ export class ToolHydrationLink extends ApolloLink {
19
+ #hydrated = false;
20
+ #pending: ResolveFn[] = [];
21
+ #operations = new Map<OperationKey, FormattedExecutionResult>();
22
+
23
+ hydrate(
24
+ operation: ManifestOperation,
25
+ {
26
+ result,
27
+ variables,
28
+ }: { result: FormattedExecutionResult; variables: OperationVariables }
29
+ ) {
30
+ this.#operations.set(
31
+ getKey({ operationName: operation.name, variables }),
32
+ result
33
+ );
34
+ }
35
+
36
+ complete(): void {
37
+ this.#hydrated = true;
38
+
39
+ for (const resolve of this.#pending.splice(0)) {
40
+ resolve();
41
+ }
42
+ }
43
+
44
+ request(
45
+ operation: ApolloLink.Operation,
46
+ forward: ApolloLink.ForwardFunction
47
+ ): Observable<ApolloLink.Result> {
48
+ const maybeSendToTerminatingLink = (): Observable<ApolloLink.Result> => {
49
+ const key = getKey(operation);
50
+ const result = this.#operations.get(key);
51
+
52
+ if (result) {
53
+ this.#operations.delete(key);
54
+ return of(result);
55
+ }
56
+
57
+ return forward(operation);
58
+ };
59
+
60
+ if (this.#hydrated) {
61
+ return maybeSendToTerminatingLink();
62
+ }
63
+
64
+ return new Observable((observer) => {
65
+ let active = true;
66
+
67
+ const resolve = () => {
68
+ if (!active) return;
69
+ maybeSendToTerminatingLink().subscribe(observer);
70
+ };
71
+ this.#pending.push(resolve);
72
+
73
+ return () => {
74
+ active = false;
75
+ const idx = this.#pending.indexOf(resolve);
76
+ if (idx !== -1) this.#pending.splice(idx, 1);
77
+ };
78
+ });
79
+ }
80
+ }
81
+
82
+ function getKey({
83
+ operationName,
84
+ variables,
85
+ }: {
86
+ operationName: string | undefined;
87
+ variables?: OperationVariables;
88
+ }): OperationKey {
89
+ return `${operationName}:${canonicalStringify(variables ?? {})}` as OperationKey;
90
+ }