@cyanheads/brapi-mcp-server 0.3.5

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 (238) hide show
  1. package/CLAUDE.md +391 -0
  2. package/Dockerfile +99 -0
  3. package/LICENSE +201 -0
  4. package/README.md +590 -0
  5. package/changelog/0.1.x/0.1.0.md +19 -0
  6. package/changelog/0.1.x/0.1.1.md +27 -0
  7. package/changelog/0.1.x/0.1.2.md +22 -0
  8. package/changelog/0.2.x/0.2.0.md +35 -0
  9. package/changelog/0.2.x/0.2.1.md +36 -0
  10. package/changelog/0.3.x/0.3.0.md +38 -0
  11. package/changelog/0.3.x/0.3.1.md +40 -0
  12. package/changelog/0.3.x/0.3.2.md +29 -0
  13. package/changelog/0.3.x/0.3.3.md +19 -0
  14. package/changelog/0.3.x/0.3.4.md +33 -0
  15. package/changelog/0.3.x/0.3.5.md +24 -0
  16. package/changelog/template.md +51 -0
  17. package/dist/config/alias-credentials.d.ts +82 -0
  18. package/dist/config/alias-credentials.d.ts.map +1 -0
  19. package/dist/config/alias-credentials.js +159 -0
  20. package/dist/config/alias-credentials.js.map +1 -0
  21. package/dist/config/server-config.d.ts +39 -0
  22. package/dist/config/server-config.d.ts.map +1 -0
  23. package/dist/config/server-config.js +128 -0
  24. package/dist/config/server-config.js.map +1 -0
  25. package/dist/index.d.ts +10 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +85 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/mcp-server/prompts/definitions/brapi-eda-study.prompt.d.ts +14 -0
  30. package/dist/mcp-server/prompts/definitions/brapi-eda-study.prompt.d.ts.map +1 -0
  31. package/dist/mcp-server/prompts/definitions/brapi-eda-study.prompt.js +75 -0
  32. package/dist/mcp-server/prompts/definitions/brapi-eda-study.prompt.js.map +1 -0
  33. package/dist/mcp-server/prompts/definitions/brapi-meta-analysis.prompt.d.ts +16 -0
  34. package/dist/mcp-server/prompts/definitions/brapi-meta-analysis.prompt.d.ts.map +1 -0
  35. package/dist/mcp-server/prompts/definitions/brapi-meta-analysis.prompt.js +109 -0
  36. package/dist/mcp-server/prompts/definitions/brapi-meta-analysis.prompt.js.map +1 -0
  37. package/dist/mcp-server/resources/definitions/brapi-calls.resource.d.ts +11 -0
  38. package/dist/mcp-server/resources/definitions/brapi-calls.resource.d.ts.map +1 -0
  39. package/dist/mcp-server/resources/definitions/brapi-calls.resource.js +46 -0
  40. package/dist/mcp-server/resources/definitions/brapi-calls.resource.js.map +1 -0
  41. package/dist/mcp-server/resources/definitions/brapi-dataset.resource.d.ts +13 -0
  42. package/dist/mcp-server/resources/definitions/brapi-dataset.resource.d.ts.map +1 -0
  43. package/dist/mcp-server/resources/definitions/brapi-dataset.resource.js +26 -0
  44. package/dist/mcp-server/resources/definitions/brapi-dataset.resource.js.map +1 -0
  45. package/dist/mcp-server/resources/definitions/brapi-filters.resource.d.ts +19 -0
  46. package/dist/mcp-server/resources/definitions/brapi-filters.resource.d.ts.map +1 -0
  47. package/dist/mcp-server/resources/definitions/brapi-filters.resource.js +45 -0
  48. package/dist/mcp-server/resources/definitions/brapi-filters.resource.js.map +1 -0
  49. package/dist/mcp-server/resources/definitions/brapi-germplasm.resource.d.ts +18 -0
  50. package/dist/mcp-server/resources/definitions/brapi-germplasm.resource.d.ts.map +1 -0
  51. package/dist/mcp-server/resources/definitions/brapi-germplasm.resource.js +34 -0
  52. package/dist/mcp-server/resources/definitions/brapi-germplasm.resource.js.map +1 -0
  53. package/dist/mcp-server/resources/definitions/brapi-server-info.resource.d.ts +11 -0
  54. package/dist/mcp-server/resources/definitions/brapi-server-info.resource.d.ts.map +1 -0
  55. package/dist/mcp-server/resources/definitions/brapi-server-info.resource.js +28 -0
  56. package/dist/mcp-server/resources/definitions/brapi-server-info.resource.js.map +1 -0
  57. package/dist/mcp-server/resources/definitions/brapi-study.resource.d.ts +18 -0
  58. package/dist/mcp-server/resources/definitions/brapi-study.resource.d.ts.map +1 -0
  59. package/dist/mcp-server/resources/definitions/brapi-study.resource.js +34 -0
  60. package/dist/mcp-server/resources/definitions/brapi-study.resource.js.map +1 -0
  61. package/dist/mcp-server/tools/definitions/brapi-connect.tool.d.ts +82 -0
  62. package/dist/mcp-server/tools/definitions/brapi-connect.tool.d.ts.map +1 -0
  63. package/dist/mcp-server/tools/definitions/brapi-connect.tool.js +106 -0
  64. package/dist/mcp-server/tools/definitions/brapi-connect.tool.js.map +1 -0
  65. package/dist/mcp-server/tools/definitions/brapi-describe-filters.tool.d.ts +41 -0
  66. package/dist/mcp-server/tools/definitions/brapi-describe-filters.tool.d.ts.map +1 -0
  67. package/dist/mcp-server/tools/definitions/brapi-describe-filters.tool.js +88 -0
  68. package/dist/mcp-server/tools/definitions/brapi-describe-filters.tool.js.map +1 -0
  69. package/dist/mcp-server/tools/definitions/brapi-find-genotype-calls.tool.d.ts +74 -0
  70. package/dist/mcp-server/tools/definitions/brapi-find-genotype-calls.tool.d.ts.map +1 -0
  71. package/dist/mcp-server/tools/definitions/brapi-find-genotype-calls.tool.js +386 -0
  72. package/dist/mcp-server/tools/definitions/brapi-find-genotype-calls.tool.js.map +1 -0
  73. package/dist/mcp-server/tools/definitions/brapi-find-germplasm.tool.d.ts +72 -0
  74. package/dist/mcp-server/tools/definitions/brapi-find-germplasm.tool.d.ts.map +1 -0
  75. package/dist/mcp-server/tools/definitions/brapi-find-germplasm.tool.js +290 -0
  76. package/dist/mcp-server/tools/definitions/brapi-find-germplasm.tool.js.map +1 -0
  77. package/dist/mcp-server/tools/definitions/brapi-find-images.tool.d.ts +65 -0
  78. package/dist/mcp-server/tools/definitions/brapi-find-images.tool.d.ts.map +1 -0
  79. package/dist/mcp-server/tools/definitions/brapi-find-images.tool.js +243 -0
  80. package/dist/mcp-server/tools/definitions/brapi-find-images.tool.js.map +1 -0
  81. package/dist/mcp-server/tools/definitions/brapi-find-locations.tool.d.ts +63 -0
  82. package/dist/mcp-server/tools/definitions/brapi-find-locations.tool.d.ts.map +1 -0
  83. package/dist/mcp-server/tools/definitions/brapi-find-locations.tool.js +278 -0
  84. package/dist/mcp-server/tools/definitions/brapi-find-locations.tool.js.map +1 -0
  85. package/dist/mcp-server/tools/definitions/brapi-find-observations.tool.d.ts +74 -0
  86. package/dist/mcp-server/tools/definitions/brapi-find-observations.tool.d.ts.map +1 -0
  87. package/dist/mcp-server/tools/definitions/brapi-find-observations.tool.js +288 -0
  88. package/dist/mcp-server/tools/definitions/brapi-find-observations.tool.js.map +1 -0
  89. package/dist/mcp-server/tools/definitions/brapi-find-studies.tool.d.ts +69 -0
  90. package/dist/mcp-server/tools/definitions/brapi-find-studies.tool.d.ts.map +1 -0
  91. package/dist/mcp-server/tools/definitions/brapi-find-studies.tool.js +243 -0
  92. package/dist/mcp-server/tools/definitions/brapi-find-studies.tool.js.map +1 -0
  93. package/dist/mcp-server/tools/definitions/brapi-find-variables.tool.d.ts +86 -0
  94. package/dist/mcp-server/tools/definitions/brapi-find-variables.tool.d.ts.map +1 -0
  95. package/dist/mcp-server/tools/definitions/brapi-find-variables.tool.js +337 -0
  96. package/dist/mcp-server/tools/definitions/brapi-find-variables.tool.js.map +1 -0
  97. package/dist/mcp-server/tools/definitions/brapi-find-variants.tool.d.ts +59 -0
  98. package/dist/mcp-server/tools/definitions/brapi-find-variants.tool.d.ts.map +1 -0
  99. package/dist/mcp-server/tools/definitions/brapi-find-variants.tool.js +248 -0
  100. package/dist/mcp-server/tools/definitions/brapi-find-variants.tool.js.map +1 -0
  101. package/dist/mcp-server/tools/definitions/brapi-get-germplasm.tool.d.ts +59 -0
  102. package/dist/mcp-server/tools/definitions/brapi-get-germplasm.tool.d.ts.map +1 -0
  103. package/dist/mcp-server/tools/definitions/brapi-get-germplasm.tool.js +306 -0
  104. package/dist/mcp-server/tools/definitions/brapi-get-germplasm.tool.js.map +1 -0
  105. package/dist/mcp-server/tools/definitions/brapi-get-image.tool.d.ts +57 -0
  106. package/dist/mcp-server/tools/definitions/brapi-get-image.tool.d.ts.map +1 -0
  107. package/dist/mcp-server/tools/definitions/brapi-get-image.tool.js +291 -0
  108. package/dist/mcp-server/tools/definitions/brapi-get-image.tool.js.map +1 -0
  109. package/dist/mcp-server/tools/definitions/brapi-get-study.tool.d.ts +75 -0
  110. package/dist/mcp-server/tools/definitions/brapi-get-study.tool.d.ts.map +1 -0
  111. package/dist/mcp-server/tools/definitions/brapi-get-study.tool.js +323 -0
  112. package/dist/mcp-server/tools/definitions/brapi-get-study.tool.js.map +1 -0
  113. package/dist/mcp-server/tools/definitions/brapi-manage-dataset.tool.d.ts +87 -0
  114. package/dist/mcp-server/tools/definitions/brapi-manage-dataset.tool.d.ts.map +1 -0
  115. package/dist/mcp-server/tools/definitions/brapi-manage-dataset.tool.js +296 -0
  116. package/dist/mcp-server/tools/definitions/brapi-manage-dataset.tool.js.map +1 -0
  117. package/dist/mcp-server/tools/definitions/brapi-raw-get.tool.d.ts +35 -0
  118. package/dist/mcp-server/tools/definitions/brapi-raw-get.tool.d.ts.map +1 -0
  119. package/dist/mcp-server/tools/definitions/brapi-raw-get.tool.js +148 -0
  120. package/dist/mcp-server/tools/definitions/brapi-raw-get.tool.js.map +1 -0
  121. package/dist/mcp-server/tools/definitions/brapi-raw-search.tool.d.ts +33 -0
  122. package/dist/mcp-server/tools/definitions/brapi-raw-search.tool.d.ts.map +1 -0
  123. package/dist/mcp-server/tools/definitions/brapi-raw-search.tool.js +126 -0
  124. package/dist/mcp-server/tools/definitions/brapi-raw-search.tool.js.map +1 -0
  125. package/dist/mcp-server/tools/definitions/brapi-server-info.tool.d.ts +51 -0
  126. package/dist/mcp-server/tools/definitions/brapi-server-info.tool.d.ts.map +1 -0
  127. package/dist/mcp-server/tools/definitions/brapi-server-info.tool.js +41 -0
  128. package/dist/mcp-server/tools/definitions/brapi-server-info.tool.js.map +1 -0
  129. package/dist/mcp-server/tools/definitions/brapi-submit-observations.tool.d.ts +117 -0
  130. package/dist/mcp-server/tools/definitions/brapi-submit-observations.tool.d.ts.map +1 -0
  131. package/dist/mcp-server/tools/definitions/brapi-submit-observations.tool.js +574 -0
  132. package/dist/mcp-server/tools/definitions/brapi-submit-observations.tool.js.map +1 -0
  133. package/dist/mcp-server/tools/definitions/brapi-walk-pedigree.tool.d.ts +52 -0
  134. package/dist/mcp-server/tools/definitions/brapi-walk-pedigree.tool.d.ts.map +1 -0
  135. package/dist/mcp-server/tools/definitions/brapi-walk-pedigree.tool.js +420 -0
  136. package/dist/mcp-server/tools/definitions/brapi-walk-pedigree.tool.js.map +1 -0
  137. package/dist/mcp-server/tools/shared/connect-auth-schema.d.ts +29 -0
  138. package/dist/mcp-server/tools/shared/connect-auth-schema.d.ts.map +1 -0
  139. package/dist/mcp-server/tools/shared/connect-auth-schema.js +55 -0
  140. package/dist/mcp-server/tools/shared/connect-auth-schema.js.map +1 -0
  141. package/dist/mcp-server/tools/shared/find-helpers.d.ts +143 -0
  142. package/dist/mcp-server/tools/shared/find-helpers.d.ts.map +1 -0
  143. package/dist/mcp-server/tools/shared/find-helpers.js +319 -0
  144. package/dist/mcp-server/tools/shared/find-helpers.js.map +1 -0
  145. package/dist/mcp-server/tools/shared/orientation-envelope.d.ts +97 -0
  146. package/dist/mcp-server/tools/shared/orientation-envelope.d.ts.map +1 -0
  147. package/dist/mcp-server/tools/shared/orientation-envelope.js +254 -0
  148. package/dist/mcp-server/tools/shared/orientation-envelope.js.map +1 -0
  149. package/dist/mcp-server/tools/shared/raw-routing-hints.d.ts +10 -0
  150. package/dist/mcp-server/tools/shared/raw-routing-hints.d.ts.map +1 -0
  151. package/dist/mcp-server/tools/shared/raw-routing-hints.js +46 -0
  152. package/dist/mcp-server/tools/shared/raw-routing-hints.js.map +1 -0
  153. package/dist/services/brapi-client/brapi-client.d.ts +76 -0
  154. package/dist/services/brapi-client/brapi-client.d.ts.map +1 -0
  155. package/dist/services/brapi-client/brapi-client.js +320 -0
  156. package/dist/services/brapi-client/brapi-client.js.map +1 -0
  157. package/dist/services/brapi-client/index.d.ts +9 -0
  158. package/dist/services/brapi-client/index.d.ts.map +1 -0
  159. package/dist/services/brapi-client/index.js +7 -0
  160. package/dist/services/brapi-client/index.js.map +1 -0
  161. package/dist/services/brapi-client/types.d.ts +82 -0
  162. package/dist/services/brapi-client/types.d.ts.map +1 -0
  163. package/dist/services/brapi-client/types.js +8 -0
  164. package/dist/services/brapi-client/types.js.map +1 -0
  165. package/dist/services/brapi-filters/catalog.d.ts +14 -0
  166. package/dist/services/brapi-filters/catalog.d.ts.map +1 -0
  167. package/dist/services/brapi-filters/catalog.js +490 -0
  168. package/dist/services/brapi-filters/catalog.js.map +1 -0
  169. package/dist/services/brapi-filters/index.d.ts +8 -0
  170. package/dist/services/brapi-filters/index.d.ts.map +1 -0
  171. package/dist/services/brapi-filters/index.js +7 -0
  172. package/dist/services/brapi-filters/index.js.map +1 -0
  173. package/dist/services/brapi-filters/types.d.ts +23 -0
  174. package/dist/services/brapi-filters/types.d.ts.map +1 -0
  175. package/dist/services/brapi-filters/types.js +9 -0
  176. package/dist/services/brapi-filters/types.js.map +1 -0
  177. package/dist/services/capability-registry/capability-registry.d.ts +51 -0
  178. package/dist/services/capability-registry/capability-registry.d.ts.map +1 -0
  179. package/dist/services/capability-registry/capability-registry.js +234 -0
  180. package/dist/services/capability-registry/capability-registry.js.map +1 -0
  181. package/dist/services/capability-registry/index.d.ts +9 -0
  182. package/dist/services/capability-registry/index.d.ts.map +1 -0
  183. package/dist/services/capability-registry/index.js +7 -0
  184. package/dist/services/capability-registry/index.js.map +1 -0
  185. package/dist/services/capability-registry/types.d.ts +67 -0
  186. package/dist/services/capability-registry/types.d.ts.map +1 -0
  187. package/dist/services/capability-registry/types.js +9 -0
  188. package/dist/services/capability-registry/types.js.map +1 -0
  189. package/dist/services/dataset-store/dataset-store.d.ts +35 -0
  190. package/dist/services/dataset-store/dataset-store.d.ts.map +1 -0
  191. package/dist/services/dataset-store/dataset-store.js +190 -0
  192. package/dist/services/dataset-store/dataset-store.js.map +1 -0
  193. package/dist/services/dataset-store/index.d.ts +8 -0
  194. package/dist/services/dataset-store/index.d.ts.map +1 -0
  195. package/dist/services/dataset-store/index.js +7 -0
  196. package/dist/services/dataset-store/index.js.map +1 -0
  197. package/dist/services/dataset-store/types.d.ts +65 -0
  198. package/dist/services/dataset-store/types.d.ts.map +1 -0
  199. package/dist/services/dataset-store/types.js +8 -0
  200. package/dist/services/dataset-store/types.js.map +1 -0
  201. package/dist/services/ontology-resolver/index.d.ts +8 -0
  202. package/dist/services/ontology-resolver/index.d.ts.map +1 -0
  203. package/dist/services/ontology-resolver/index.js +7 -0
  204. package/dist/services/ontology-resolver/index.js.map +1 -0
  205. package/dist/services/ontology-resolver/ontology-resolver.d.ts +49 -0
  206. package/dist/services/ontology-resolver/ontology-resolver.d.ts.map +1 -0
  207. package/dist/services/ontology-resolver/ontology-resolver.js +99 -0
  208. package/dist/services/ontology-resolver/ontology-resolver.js.map +1 -0
  209. package/dist/services/ontology-resolver/types.d.ts +38 -0
  210. package/dist/services/ontology-resolver/types.d.ts.map +1 -0
  211. package/dist/services/ontology-resolver/types.js +8 -0
  212. package/dist/services/ontology-resolver/types.js.map +1 -0
  213. package/dist/services/reference-data-cache/index.d.ts +9 -0
  214. package/dist/services/reference-data-cache/index.d.ts.map +1 -0
  215. package/dist/services/reference-data-cache/index.js +7 -0
  216. package/dist/services/reference-data-cache/index.js.map +1 -0
  217. package/dist/services/reference-data-cache/reference-data-cache.d.ts +31 -0
  218. package/dist/services/reference-data-cache/reference-data-cache.d.ts.map +1 -0
  219. package/dist/services/reference-data-cache/reference-data-cache.js +131 -0
  220. package/dist/services/reference-data-cache/reference-data-cache.js.map +1 -0
  221. package/dist/services/reference-data-cache/types.d.ts +42 -0
  222. package/dist/services/reference-data-cache/types.d.ts.map +1 -0
  223. package/dist/services/reference-data-cache/types.js +9 -0
  224. package/dist/services/reference-data-cache/types.js.map +1 -0
  225. package/dist/services/server-registry/index.d.ts +9 -0
  226. package/dist/services/server-registry/index.d.ts.map +1 -0
  227. package/dist/services/server-registry/index.js +7 -0
  228. package/dist/services/server-registry/index.js.map +1 -0
  229. package/dist/services/server-registry/server-registry.d.ts +57 -0
  230. package/dist/services/server-registry/server-registry.d.ts.map +1 -0
  231. package/dist/services/server-registry/server-registry.js +210 -0
  232. package/dist/services/server-registry/server-registry.js.map +1 -0
  233. package/dist/services/server-registry/types.d.ts +43 -0
  234. package/dist/services/server-registry/types.d.ts.map +1 -0
  235. package/dist/services/server-registry/types.js +10 -0
  236. package/dist/services/server-registry/types.js.map +1 -0
  237. package/package.json +86 -0
  238. package/server.json +99 -0
@@ -0,0 +1,254 @@
1
+ /**
2
+ * @fileoverview Shared builder for the BrAPI orientation envelope returned
3
+ * by both `brapi_connect` (inlined after registration) and
4
+ * `brapi_server_info` (on-demand). Pulls from CapabilityRegistry and the
5
+ * active ServerRegistry entry, then layers in cheap opportunistic counts via
6
+ * `pageSize=0` probes. Counts degrade silently — a server that doesn't
7
+ * honor the probe just omits the field rather than failing the whole call.
8
+ *
9
+ * @module mcp-server/tools/shared/orientation-envelope
10
+ */
11
+ import { z } from '@cyanheads/mcp-ts-core';
12
+ /**
13
+ * BrAPI endpoints we treat as the "common floor" — their absence is worth
14
+ * surfacing as a notable gap in the orientation envelope so the agent knows
15
+ * which tools will fail before they call them.
16
+ */
17
+ const COMMON_FLOOR = [
18
+ 'studies',
19
+ 'germplasm',
20
+ 'observations',
21
+ 'observationunits',
22
+ 'variables',
23
+ 'programs',
24
+ 'trials',
25
+ 'locations',
26
+ 'seasons',
27
+ 'search/studies',
28
+ 'search/germplasm',
29
+ 'search/observations',
30
+ ];
31
+ export const ServerIdentitySchema = z
32
+ .object({
33
+ name: z.string().optional().describe('Server display name from /serverinfo.'),
34
+ description: z.string().optional().describe('Free-form server description.'),
35
+ organizationName: z.string().optional().describe('Hosting organization.'),
36
+ organizationURL: z.string().optional().describe('Organization website.'),
37
+ documentationURL: z.string().optional().describe('Documentation URL for this server.'),
38
+ contactEmail: z.string().optional().describe('Contact email for the operator.'),
39
+ brapiVersion: z.string().optional().describe('Highest BrAPI version the server reports.'),
40
+ })
41
+ .describe('Normalized identity fields from /serverinfo. Every field is optional.');
42
+ export const OrientationAuthSchema = z
43
+ .object({
44
+ mode: z
45
+ .enum(['none', 'sgn', 'oauth2', 'api_key', 'bearer'])
46
+ .describe('Auth mode of the active connection.'),
47
+ headerName: z.string().optional().describe('HTTP header carrying credentials.'),
48
+ expiresAt: z.string().optional().describe('ISO 8601 token-expiry timestamp, when known.'),
49
+ })
50
+ .describe('Auth summary for the active connection — no secrets returned.');
51
+ export const OrientationCapabilitiesSchema = z
52
+ .object({
53
+ supportedCount: z
54
+ .number()
55
+ .int()
56
+ .nonnegative()
57
+ .describe('Total distinct services the server advertises in /calls.'),
58
+ supported: z
59
+ .array(z.string().describe('BrAPI service name (e.g. "studies", "search/germplasm").'))
60
+ .describe('Sorted list of supported service names.'),
61
+ notableGaps: z
62
+ .array(z.string().describe('Common-floor service the server does not expose.'))
63
+ .describe('Common-floor services this server does NOT expose.'),
64
+ })
65
+ .describe('Capability profile summary. Downstream tools pre-flight against `supported`.');
66
+ export const OrientationContentSchema = z
67
+ .object({
68
+ crops: z
69
+ .array(z.string().describe('Common crop name as returned by /commoncropnames.'))
70
+ .describe('Crops the server declares via /commoncropnames.'),
71
+ studyCount: z
72
+ .number()
73
+ .int()
74
+ .nonnegative()
75
+ .optional()
76
+ .describe('Total studies hosted, when the server exposes a cheap count.'),
77
+ germplasmCount: z
78
+ .number()
79
+ .int()
80
+ .nonnegative()
81
+ .optional()
82
+ .describe('Total germplasm hosted, when the server exposes a cheap count.'),
83
+ programCount: z
84
+ .number()
85
+ .int()
86
+ .nonnegative()
87
+ .optional()
88
+ .describe('Total programs hosted, when the server exposes a cheap count.'),
89
+ locationCount: z
90
+ .number()
91
+ .int()
92
+ .nonnegative()
93
+ .optional()
94
+ .describe('Total locations hosted, when the server exposes a cheap count.'),
95
+ })
96
+ .describe('Content summary. Counts are populated only when the server supports cheap totals.');
97
+ export const OrientationEnvelopeSchema = z.object({
98
+ alias: z.string().describe('Connection alias.'),
99
+ baseUrl: z.string().describe('BrAPI v2 base URL for this connection.'),
100
+ server: ServerIdentitySchema.describe('Normalized server identity block.'),
101
+ auth: OrientationAuthSchema.describe('Auth summary for the active connection.'),
102
+ capabilities: OrientationCapabilitiesSchema.describe('Capability profile derived from /serverinfo.'),
103
+ content: OrientationContentSchema.describe('Content summary (crops + optional totals).'),
104
+ notes: z
105
+ .array(z.string().describe('Server-specific quirk or degradation note.'))
106
+ .describe('Server-specific quirks or degradation notes.'),
107
+ fetchedAt: z.string().describe('ISO 8601 timestamp of when this envelope was composed.'),
108
+ });
109
+ /**
110
+ * Compose the orientation envelope for a connected server. Runs the
111
+ * CapabilityRegistry profile (cached after the first call) plus a parallel
112
+ * set of cheap `pageSize=0` probes for totals.
113
+ */
114
+ export async function buildOrientationEnvelope(ctx, connection, deps) {
115
+ const baseRequestOptions = {};
116
+ if (connection.resolvedAuth)
117
+ baseRequestOptions.auth = connection.resolvedAuth;
118
+ const capabilityLookup = {};
119
+ if (connection.resolvedAuth)
120
+ capabilityLookup.auth = connection.resolvedAuth;
121
+ const profile = await deps.registry.profile(connection.baseUrl, ctx, capabilityLookup);
122
+ const supportedServices = Object.keys(profile.supported).sort();
123
+ const supportedSet = new Set(supportedServices);
124
+ const notableGaps = COMMON_FLOOR.filter((svc) => !supportedSet.has(svc));
125
+ const notes = [];
126
+ if (supportedServices.length === 0) {
127
+ notes.push('Server did not advertise any calls via /serverinfo or /calls — downstream tools will fail until the capability profile populates.');
128
+ }
129
+ if (!profile.server.brapiVersion) {
130
+ notes.push('Server did not declare a BrAPI version; treating as v2 by default. Behavior may vary.');
131
+ }
132
+ const counts = await fetchOpportunisticCounts(deps.client, connection.baseUrl, ctx, supportedSet, baseRequestOptions);
133
+ const content = { crops: profile.crops };
134
+ if (counts.studyCount !== undefined)
135
+ content.studyCount = counts.studyCount;
136
+ if (counts.germplasmCount !== undefined)
137
+ content.germplasmCount = counts.germplasmCount;
138
+ if (counts.programCount !== undefined)
139
+ content.programCount = counts.programCount;
140
+ if (counts.locationCount !== undefined)
141
+ content.locationCount = counts.locationCount;
142
+ const auth = { mode: connection.authMode };
143
+ if (connection.resolvedAuth?.headerName)
144
+ auth.headerName = connection.resolvedAuth.headerName;
145
+ if (connection.resolvedAuth?.expiresAt)
146
+ auth.expiresAt = connection.resolvedAuth.expiresAt;
147
+ return {
148
+ alias: connection.alias,
149
+ baseUrl: connection.baseUrl,
150
+ server: { ...profile.server },
151
+ auth,
152
+ capabilities: {
153
+ supportedCount: supportedServices.length,
154
+ supported: supportedServices,
155
+ notableGaps,
156
+ },
157
+ content,
158
+ notes,
159
+ fetchedAt: new Date().toISOString(),
160
+ };
161
+ }
162
+ async function fetchOpportunisticCounts(client, baseUrl, ctx, supportedSet, baseOptions) {
163
+ const probes = [
164
+ { key: 'studyCount', path: '/studies', service: 'studies' },
165
+ { key: 'germplasmCount', path: '/germplasm', service: 'germplasm' },
166
+ { key: 'programCount', path: '/programs', service: 'programs' },
167
+ { key: 'locationCount', path: '/locations', service: 'locations' },
168
+ ];
169
+ const attempts = probes
170
+ .filter((probe) => supportedSet.has(probe.service))
171
+ .map(async (probe) => {
172
+ try {
173
+ const env = await client.get(baseUrl, probe.path, ctx, {
174
+ ...baseOptions,
175
+ params: { pageSize: 0 },
176
+ });
177
+ const total = env.metadata?.pagination?.totalCount;
178
+ if (typeof total === 'number' && Number.isFinite(total)) {
179
+ return { key: probe.key, total };
180
+ }
181
+ }
182
+ catch (err) {
183
+ ctx.log.debug('Opportunistic count probe failed', {
184
+ path: probe.path,
185
+ error: err instanceof Error ? err.message : String(err),
186
+ });
187
+ }
188
+ return;
189
+ });
190
+ const settled = await Promise.all(attempts);
191
+ const result = {};
192
+ for (const entry of settled) {
193
+ if (!entry)
194
+ continue;
195
+ result[entry.key] = entry.total;
196
+ }
197
+ return result;
198
+ }
199
+ export function formatOrientationEnvelope(envelope) {
200
+ const lines = [];
201
+ const title = envelope.server.name ?? envelope.alias;
202
+ lines.push(`# Connected: ${title}`);
203
+ lines.push('');
204
+ lines.push(`- **Alias:** ${envelope.alias}`);
205
+ lines.push(`- **Base URL:** ${envelope.baseUrl}`);
206
+ lines.push(`- **BrAPI version:** ${envelope.server.brapiVersion ?? 'unknown'}`);
207
+ if (envelope.server.organizationName)
208
+ lines.push(`- **Organization:** ${envelope.server.organizationName}`);
209
+ if (envelope.server.description)
210
+ lines.push(`- **Description:** ${envelope.server.description}`);
211
+ if (envelope.server.documentationURL)
212
+ lines.push(`- **Docs:** ${envelope.server.documentationURL}`);
213
+ if (envelope.server.contactEmail)
214
+ lines.push(`- **Contact:** ${envelope.server.contactEmail}`);
215
+ if (envelope.server.organizationURL)
216
+ lines.push(`- **Organization URL:** ${envelope.server.organizationURL}`);
217
+ lines.push('');
218
+ lines.push(`**Auth:** ${envelope.auth.mode}${envelope.auth.headerName ? ` (header: ${envelope.auth.headerName})` : ''}${envelope.auth.expiresAt ? ` · expires ${envelope.auth.expiresAt}` : ''}`);
219
+ lines.push('');
220
+ lines.push('## Capabilities');
221
+ lines.push(`- ${envelope.capabilities.supportedCount} service(s) advertised`);
222
+ if (envelope.capabilities.supported.length > 0) {
223
+ lines.push(`- Supported: ${envelope.capabilities.supported.join(', ')}`);
224
+ }
225
+ if (envelope.capabilities.notableGaps.length > 0) {
226
+ lines.push(`- Notable gaps (missing from the common floor): ${envelope.capabilities.notableGaps.join(', ')}`);
227
+ }
228
+ lines.push('');
229
+ lines.push('## Content');
230
+ if (envelope.content.crops.length > 0) {
231
+ lines.push(`- **Crops (${envelope.content.crops.length}):** ${envelope.content.crops.join(', ')}`);
232
+ }
233
+ else {
234
+ lines.push('- Crops: — (server did not expose /commoncropnames)');
235
+ }
236
+ if (envelope.content.studyCount !== undefined)
237
+ lines.push(`- Studies: ${envelope.content.studyCount}`);
238
+ if (envelope.content.germplasmCount !== undefined)
239
+ lines.push(`- Germplasm: ${envelope.content.germplasmCount}`);
240
+ if (envelope.content.programCount !== undefined)
241
+ lines.push(`- Programs: ${envelope.content.programCount}`);
242
+ if (envelope.content.locationCount !== undefined)
243
+ lines.push(`- Locations: ${envelope.content.locationCount}`);
244
+ if (envelope.notes.length > 0) {
245
+ lines.push('');
246
+ lines.push('## Notes');
247
+ for (const note of envelope.notes)
248
+ lines.push(`- ${note}`);
249
+ }
250
+ lines.push('');
251
+ lines.push(`_Fetched at ${envelope.fetchedAt}._`);
252
+ return lines.join('\n');
253
+ }
254
+ //# sourceMappingURL=orientation-envelope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orientation-envelope.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/shared/orientation-envelope.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @fileoverview Routing nudges emitted by `brapi_raw_get` / `brapi_raw_search`
3
+ * when the target endpoint is already covered by a curated goal-shaped tool.
4
+ * Keeps the raw surface honest about its role as a last-resort escape hatch.
5
+ *
6
+ * @module mcp-server/tools/shared/raw-routing-hints
7
+ */
8
+ export declare function suggestForGet(path: string): string | undefined;
9
+ export declare function suggestForSearch(noun: string): string | undefined;
10
+ //# sourceMappingURL=raw-routing-hints.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raw-routing-hints.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/shared/raw-routing-hints.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA8CH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG9D;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEjE"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @fileoverview Routing nudges emitted by `brapi_raw_get` / `brapi_raw_search`
3
+ * when the target endpoint is already covered by a curated goal-shaped tool.
4
+ * Keeps the raw surface honest about its role as a last-resort escape hatch.
5
+ *
6
+ * @module mcp-server/tools/shared/raw-routing-hints
7
+ */
8
+ /**
9
+ * Map from a normalized path segment (no leading slash, no query) to the
10
+ * goal-shaped tool that enriches it. Only endpoints that a curated tool
11
+ * strictly supersedes should appear here; niche endpoints stay quiet.
12
+ */
13
+ const GET_NUDGES = {
14
+ studies: 'This endpoint is also served by `brapi_find_studies` which enriches with program/trial/location FKs and returns distributions in one call.',
15
+ germplasm: 'This endpoint is also served by `brapi_find_germplasm` which adds distributions and dataset spillover.',
16
+ observations: 'This endpoint is also served by `brapi_find_observations` which adds distributions and dataset spillover.',
17
+ variables: 'This endpoint is also served by `brapi_find_variables` which adds free-text ranking via OntologyResolver.',
18
+ images: 'This endpoint is also served by `brapi_find_images`; use `brapi_get_image` to pull bytes inline.',
19
+ variants: 'This endpoint is also served by `brapi_find_variants` which handles distributions and dataset spillover.',
20
+ locations: 'This endpoint is also served by `brapi_find_locations` which adds distributions and optional bounding-box filtering.',
21
+ serverinfo: 'For a full orientation envelope, call `brapi_server_info` (which uses the cached capability profile).',
22
+ calls: 'The `brapi_server_info` envelope already surfaces the supported call set.',
23
+ commoncropnames: 'Crop names are included in `brapi_server_info.content.crops`.',
24
+ };
25
+ const SEARCH_NUDGES = {
26
+ studies: 'Consider `brapi_find_studies` — handles async polling + FK resolution automatically.',
27
+ germplasm: 'Consider `brapi_find_germplasm` — handles distributions + spillover.',
28
+ observations: 'Consider `brapi_find_observations` — handles spillover and distributions.',
29
+ variables: 'Consider `brapi_find_variables` — ranked client-side via OntologyResolver when text is provided.',
30
+ calls: 'Consider `brapi_find_genotype_calls` — handles async-search polling, maxCalls cap, and dataset spillover automatically.',
31
+ images: 'Consider `brapi_find_images`.',
32
+ variants: 'Consider `brapi_find_variants`.',
33
+ locations: 'Consider `brapi_find_locations`.',
34
+ };
35
+ /** Normalize "/images/123/imagecontent" → "images". */
36
+ function rootSegment(path) {
37
+ return path.replace(/^\/+/, '').split('/')[0] ?? '';
38
+ }
39
+ export function suggestForGet(path) {
40
+ const seg = rootSegment(path);
41
+ return GET_NUDGES[seg];
42
+ }
43
+ export function suggestForSearch(noun) {
44
+ return SEARCH_NUDGES[noun.replace(/^\/+/, '')];
45
+ }
46
+ //# sourceMappingURL=raw-routing-hints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raw-routing-hints.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/shared/raw-routing-hints.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;GAIG;AACH,MAAM,UAAU,GAA2B;IACzC,OAAO,EACL,4IAA4I;IAC9I,SAAS,EACP,wGAAwG;IAC1G,YAAY,EACV,2GAA2G;IAC7G,SAAS,EACP,2GAA2G;IAC7G,MAAM,EACJ,kGAAkG;IACpG,QAAQ,EACN,0GAA0G;IAC5G,SAAS,EACP,sHAAsH;IACxH,UAAU,EACR,uGAAuG;IACzG,KAAK,EAAE,2EAA2E;IAClF,eAAe,EAAE,+DAA+D;CACjF,CAAC;AAEF,MAAM,aAAa,GAA2B;IAC5C,OAAO,EAAE,sFAAsF;IAC/F,SAAS,EAAE,sEAAsE;IACjF,YAAY,EAAE,2EAA2E;IACzF,SAAS,EACP,kGAAkG;IACpG,KAAK,EACH,yHAAyH;IAC3H,MAAM,EAAE,+BAA+B;IACvC,QAAQ,EAAE,iCAAiC;IAC3C,SAAS,EAAE,kCAAkC;CAC9C,CAAC;AAEF,uDAAuD;AACvD,SAAS,WAAW,CAAC,IAAY;IAC/B,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAC9B,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;AACjD,CAAC"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * @fileoverview Low-level HTTP client for BrAPI v2 servers. Handles URL
3
+ * construction, header assembly, JSON envelope parsing, retry with exponential
4
+ * backoff, and the async-search poll loop
5
+ * (`POST /search/{noun}` → `searchResultsDbId` → `GET /search/{noun}/{id}`).
6
+ * Stateless across connections — callers pass `baseUrl` and resolved auth per
7
+ * call; connection state is owned by `ServerRegistry` (added in a later phase).
8
+ *
9
+ * @module services/brapi-client/brapi-client
10
+ */
11
+ import type { Context } from '@cyanheads/mcp-ts-core';
12
+ import type { FetchWithTimeoutOptions } from '@cyanheads/mcp-ts-core/utils';
13
+ import type { ServerConfig } from '../../config/server-config.js';
14
+ import type { BinaryResponse, BrapiEnvelope, BrapiRequestOptions, SearchResponse } from './types.js';
15
+ /**
16
+ * Signature of the underlying HTTP fetcher. Accepts the handler `Context`
17
+ * directly so callers (and tests) don't have to cast; the default
18
+ * implementation adapts to `fetchWithTimeout`.
19
+ */
20
+ export type Fetcher = (url: string | URL, timeoutMs: number, context: Context, options?: FetchWithTimeoutOptions) => Promise<Response>;
21
+ export declare class BrapiClient {
22
+ private readonly serverConfig;
23
+ private readonly fetcher;
24
+ constructor(serverConfig: ServerConfig, fetcher?: Fetcher);
25
+ /** GET /{path} with optional query params and auth. */
26
+ get<T>(baseUrl: string, path: string, ctx: Context, options?: BrapiRequestOptions): Promise<BrapiEnvelope<T>>;
27
+ /**
28
+ * GET /{path} returning raw bytes — used for image content and other binary
29
+ * payloads. Honors the same retry policy as `get()`. The `accept` option
30
+ * overrides the default `image/*`.
31
+ */
32
+ getBinary(baseUrl: string, path: string, ctx: Context, options?: BrapiRequestOptions & {
33
+ accept?: string;
34
+ }): Promise<BinaryResponse>;
35
+ /**
36
+ * Fetch binary bytes from an arbitrary URL — used as a fallback when a
37
+ * BrAPI server doesn't expose `/images/{id}/imagecontent` but the image's
38
+ * metadata carries an `imageURL` (CDN, S3, etc.). No auth is attached; the
39
+ * assumption is that these URLs are publicly reachable. Still honors the
40
+ * private-IP guard and request timeout.
41
+ */
42
+ fetchBinaryUrl(url: string, ctx: Context, accept?: string): Promise<BinaryResponse>;
43
+ /**
44
+ * POST /search/{noun}. Returns a discriminated union — `sync` when the
45
+ * server returns full results inline, `async` when it returns a
46
+ * `searchResultsDbId` the caller must poll via `getSearchResults`.
47
+ */
48
+ postSearch<T>(baseUrl: string, noun: string, body: Record<string, unknown>, ctx: Context, options?: BrapiRequestOptions): Promise<SearchResponse<T>>;
49
+ /**
50
+ * POST /{path} with a JSON body. Used for write endpoints (e.g. creating
51
+ * observations). Same retry + classification policy as `get()`. The body is
52
+ * serialized as JSON and `Content-Type: application/json` is forced.
53
+ */
54
+ post<T>(baseUrl: string, path: string, body: unknown, ctx: Context, options?: BrapiRequestOptions): Promise<BrapiEnvelope<T>>;
55
+ /**
56
+ * PUT /{path} with a JSON body. Used for upsert / update endpoints. BrAPI
57
+ * routes update calls (`PUT /observations`, `PUT /germplasm`) through this.
58
+ */
59
+ put<T>(baseUrl: string, path: string, body: unknown, ctx: Context, options?: BrapiRequestOptions): Promise<BrapiEnvelope<T>>;
60
+ private sendJson;
61
+ /**
62
+ * Poll `GET /search/{noun}/{searchResultsDbId}`. Returns the envelope once
63
+ * the server replies with 200. 202 means "still processing" — the method
64
+ * sleeps `searchPollIntervalMs` and retries until `searchPollTimeoutMs`.
65
+ */
66
+ getSearchResults<T>(baseUrl: string, noun: string, searchResultsDbId: string, ctx: Context, options?: BrapiRequestOptions): Promise<BrapiEnvelope<T>>;
67
+ private doFetch;
68
+ private buildUrl;
69
+ private buildHeaders;
70
+ private parseEnvelope;
71
+ }
72
+ export declare function initBrapiClient(serverConfig: ServerConfig, fetcher?: Fetcher): void;
73
+ export declare function getBrapiClient(): BrapiClient;
74
+ /** Test-only — clears the singleton so successive suites start clean. */
75
+ export declare function resetBrapiClient(): void;
76
+ //# sourceMappingURL=brapi-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brapi-client.d.ts","sourceRoot":"","sources":["../../../src/services/brapi-client/brapi-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAYtD,OAAO,KAAK,EAAE,uBAAuB,EAAkB,MAAM,8BAA8B,CAAC;AAE5F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,mBAAmB,EAEnB,cAAc,EACf,MAAM,YAAY,CAAC;AAWpB;;;;GAIG;AACH,MAAM,MAAM,OAAO,GAAG,CACpB,GAAG,EAAE,MAAM,GAAG,GAAG,EACjB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,uBAAuB,KAC9B,OAAO,CAAC,QAAQ,CAAC,CAAC;AAKvB,qBAAa,WAAW;IAEpB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO;gBADP,YAAY,EAAE,YAAY,EAC1B,OAAO,GAAE,OAAwB;IAGpD,uDAAuD;IACvD,GAAG,CAAC,CAAC,EACH,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,OAAO,EACZ,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAqB5B;;;;OAIG;IACH,SAAS,CACP,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,OAAO,EACZ,OAAO,GAAE,mBAAmB,GAAG;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO,GACtD,OAAO,CAAC,cAAc,CAAC;IAyB1B;;;;;;OAMG;IACG,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,SAAY,GAAG,OAAO,CAAC,cAAc,CAAC;IAY5F;;;;OAIG;IACH,UAAU,CAAC,CAAC,EACV,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,GAAG,EAAE,OAAO,EACZ,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;IAiC7B;;;;OAIG;IACH,IAAI,CAAC,CAAC,EACJ,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,OAAO,EACb,GAAG,EAAE,OAAO,EACZ,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAI5B;;;OAGG;IACH,GAAG,CAAC,CAAC,EACH,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,OAAO,EACb,GAAG,EAAE,OAAO,EACZ,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAI5B,OAAO,CAAC,QAAQ;IAmChB;;;;OAIG;IACG,gBAAgB,CAAC,CAAC,EACtB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,iBAAiB,EAAE,MAAM,EACzB,GAAG,EAAE,OAAO,EACZ,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;YAmCd,OAAO;IAkBrB,OAAO,CAAC,QAAQ;IAiBhB,OAAO,CAAC,YAAY;YAQN,aAAa;CAyB5B;AA2ED,wBAAgB,eAAe,CAAC,YAAY,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAEnF;AAED,wBAAgB,cAAc,IAAI,WAAW,CAK5C;AAED,yEAAyE;AACzE,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC"}