@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,57 @@
1
+ /**
2
+ * @fileoverview Session-scoped BrAPI connection registry. Maps named aliases
3
+ * to resolved connection state (base URL, auth header) within a tenant's
4
+ * `ctx.state`. Multi-server workflows register distinct aliases; tools read
5
+ * the alias from input (defaulting to `default`) and pull the base URL +
6
+ * auth header for routing. Auth modes that require a token exchange
7
+ * (`sgn`, `oauth2`) perform the exchange at registration time.
8
+ *
9
+ * @module services/server-registry/server-registry
10
+ */
11
+ import type { Context } from '@cyanheads/mcp-ts-core';
12
+ import type { ServerConfig } from '../../config/server-config.js';
13
+ import type { AuthMode, ConnectAuth, RegisteredServer } from './types.js';
14
+ export declare const DEFAULT_ALIAS = "default";
15
+ export interface RegisterInput {
16
+ alias?: string;
17
+ auth?: ConnectAuth;
18
+ baseUrl: string;
19
+ }
20
+ export declare class ServerRegistry {
21
+ private readonly serverConfig;
22
+ private readonly tokenFetcher;
23
+ constructor(serverConfig: ServerConfig, tokenFetcher?: TokenFetcher);
24
+ /**
25
+ * Register a connection under an alias. Resolves the auth mode to a
26
+ * ready-to-use header (performing token exchange for `sgn` / `oauth2`) and
27
+ * persists the result in `ctx.state`.
28
+ */
29
+ register(ctx: Context, input: RegisterInput): Promise<RegisteredServer>;
30
+ /** Fetch a registered connection or throw `NotFound`. */
31
+ get(ctx: Context, alias?: string): Promise<RegisteredServer>;
32
+ /** Non-throwing variant of `get`. */
33
+ getOptional(ctx: Context, alias?: string): Promise<RegisteredServer | null>;
34
+ list(ctx: Context): Promise<RegisteredServer[]>;
35
+ unregister(ctx: Context, alias?: string): Promise<void>;
36
+ private resolveAuth;
37
+ private exchangeSgnToken;
38
+ }
39
+ /**
40
+ * Swappable token-exchange fetcher. Production uses `fetchWithTimeout`; tests
41
+ * inject a stub to avoid real network calls.
42
+ */
43
+ export type TokenFetcher = (url: string, body: Record<string, unknown>, ctx: Context, options: {
44
+ timeoutMs: number;
45
+ rejectPrivateIPs: boolean;
46
+ }) => Promise<TokenResponse>;
47
+ interface TokenResponse {
48
+ access_token?: string;
49
+ expires_in?: number;
50
+ token_type?: string;
51
+ [key: string]: unknown;
52
+ }
53
+ export declare function initServerRegistry(serverConfig: ServerConfig): void;
54
+ export declare function getServerRegistry(): ServerRegistry;
55
+ export declare function resetServerRegistry(): void;
56
+ export type { AuthMode, ConnectAuth, RegisteredServer };
57
+ //# sourceMappingURL=server-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-registry.d.ts","sourceRoot":"","sources":["../../../src/services/server-registry/server-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAStD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAE9D,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE1E,eAAO,MAAM,aAAa,YAAY,CAAC;AAIvC,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,cAAc;IAEvB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,YAAY;gBADZ,YAAY,EAAE,YAAY,EAC1B,YAAY,GAAE,YAAkC;IAGnE;;;;OAIG;IACG,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAmB7E,yDAAyD;IACnD,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,GAAE,MAAsB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAWjF,qCAAqC;IACrC,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,GAAE,MAAsB,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAIpF,IAAI,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAe/C,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,GAAE,MAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;YAI9D,WAAW;YA6BX,gBAAgB;CAoC/B;AAED;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,CACzB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,GAAG,EAAE,OAAO,EACZ,OAAO,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,OAAO,CAAA;CAAE,KACtD,OAAO,CAAC,aAAa,CAAC,CAAC;AAE5B,UAAU,aAAa;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AA4FD,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI,CAEnE;AAED,wBAAgB,iBAAiB,IAAI,cAAc,CAKlD;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAED,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,gBAAgB,EAAE,CAAC"}
@@ -0,0 +1,210 @@
1
+ /**
2
+ * @fileoverview Session-scoped BrAPI connection registry. Maps named aliases
3
+ * to resolved connection state (base URL, auth header) within a tenant's
4
+ * `ctx.state`. Multi-server workflows register distinct aliases; tools read
5
+ * the alias from input (defaulting to `default`) and pull the base URL +
6
+ * auth header for routing. Auth modes that require a token exchange
7
+ * (`sgn`, `oauth2`) perform the exchange at registration time.
8
+ *
9
+ * @module services/server-registry/server-registry
10
+ */
11
+ import { forbidden, notFound, serviceUnavailable, validationError, } from '@cyanheads/mcp-ts-core/errors';
12
+ import { fetchWithTimeout } from '@cyanheads/mcp-ts-core/utils';
13
+ export const DEFAULT_ALIAS = 'default';
14
+ const CONN_PREFIX = 'brapi/conn/';
15
+ export class ServerRegistry {
16
+ serverConfig;
17
+ tokenFetcher;
18
+ constructor(serverConfig, tokenFetcher = defaultTokenFetcher) {
19
+ this.serverConfig = serverConfig;
20
+ this.tokenFetcher = tokenFetcher;
21
+ }
22
+ /**
23
+ * Register a connection under an alias. Resolves the auth mode to a
24
+ * ready-to-use header (performing token exchange for `sgn` / `oauth2`) and
25
+ * persists the result in `ctx.state`.
26
+ */
27
+ async register(ctx, input) {
28
+ const alias = input.alias?.trim() || DEFAULT_ALIAS;
29
+ validateAlias(alias);
30
+ validateBaseUrl(input.baseUrl);
31
+ const auth = input.auth ?? { mode: 'none' };
32
+ const registered = {
33
+ alias,
34
+ baseUrl: normalizeBaseUrl(input.baseUrl),
35
+ authMode: auth.mode,
36
+ registeredAt: new Date().toISOString(),
37
+ };
38
+ const resolvedAuth = await this.resolveAuth(auth, registered.baseUrl, ctx);
39
+ if (resolvedAuth)
40
+ registered.resolvedAuth = resolvedAuth;
41
+ await ctx.state.set(connKey(alias), registered);
42
+ return registered;
43
+ }
44
+ /** Fetch a registered connection or throw `NotFound`. */
45
+ async get(ctx, alias = DEFAULT_ALIAS) {
46
+ const entry = await ctx.state.get(connKey(alias));
47
+ if (!entry) {
48
+ throw notFound(`No BrAPI connection registered under alias '${alias}'. Call brapi_connect first.`, { alias, reason: 'unknown_alias' });
49
+ }
50
+ return entry;
51
+ }
52
+ /** Non-throwing variant of `get`. */
53
+ getOptional(ctx, alias = DEFAULT_ALIAS) {
54
+ return ctx.state.get(connKey(alias));
55
+ }
56
+ async list(ctx) {
57
+ const servers = [];
58
+ let cursor;
59
+ do {
60
+ const listOpts = { limit: 100 };
61
+ if (cursor !== undefined)
62
+ listOpts.cursor = cursor;
63
+ const page = await ctx.state.list(CONN_PREFIX, listOpts);
64
+ for (const item of page.items) {
65
+ if (isRegisteredServer(item.value))
66
+ servers.push(item.value);
67
+ }
68
+ cursor = page.cursor;
69
+ } while (cursor);
70
+ return servers;
71
+ }
72
+ async unregister(ctx, alias = DEFAULT_ALIAS) {
73
+ await ctx.state.delete(connKey(alias));
74
+ }
75
+ async resolveAuth(auth, baseUrl, ctx) {
76
+ switch (auth.mode) {
77
+ case 'none':
78
+ return;
79
+ case 'bearer':
80
+ return { headerName: 'Authorization', headerValue: `Bearer ${auth.token}` };
81
+ case 'api_key':
82
+ return {
83
+ headerName: auth.headerName ?? this.serverConfig.defaultApiKeyHeader,
84
+ headerValue: auth.apiKey,
85
+ };
86
+ case 'sgn':
87
+ return await this.exchangeSgnToken(auth, baseUrl, ctx);
88
+ case 'oauth2':
89
+ throw validationError('OAuth2 auth is not yet implemented. Use mode="bearer" with a pre-obtained access token for now.', { mode: 'oauth2' });
90
+ default: {
91
+ const _exhaustive = auth;
92
+ throw validationError('Unknown auth mode', { received: _exhaustive });
93
+ }
94
+ }
95
+ }
96
+ async exchangeSgnToken(auth, baseUrl, ctx) {
97
+ const tokenUrl = joinUrl(baseUrl, '/token');
98
+ const payload = await this.tokenFetcher(tokenUrl, {
99
+ username: auth.username,
100
+ password: auth.password,
101
+ grant_type: 'password',
102
+ }, ctx, {
103
+ timeoutMs: this.serverConfig.requestTimeoutMs,
104
+ rejectPrivateIPs: !this.serverConfig.allowPrivateIps,
105
+ });
106
+ if (!payload.access_token) {
107
+ throw forbidden('SGN token exchange returned no access_token', {
108
+ tokenUrl,
109
+ payloadKeys: Object.keys(payload),
110
+ reason: 'auth_no_access_token',
111
+ ...ctx.recoveryFor('auth_no_access_token'),
112
+ });
113
+ }
114
+ const resolved = {
115
+ headerName: 'Authorization',
116
+ headerValue: `Bearer ${payload.access_token}`,
117
+ };
118
+ if (payload.expires_in && Number.isFinite(payload.expires_in)) {
119
+ resolved.expiresAt = new Date(Date.now() + payload.expires_in * 1000).toISOString();
120
+ }
121
+ return resolved;
122
+ }
123
+ }
124
+ const defaultTokenFetcher = async (url, body, ctx, options) => {
125
+ const form = new URLSearchParams();
126
+ for (const [key, value] of Object.entries(body)) {
127
+ if (value !== undefined && value !== null)
128
+ form.set(key, String(value));
129
+ }
130
+ let response;
131
+ try {
132
+ response = await fetchWithTimeout(url, options.timeoutMs, ctx, {
133
+ method: 'POST',
134
+ headers: {
135
+ 'Content-Type': 'application/x-www-form-urlencoded',
136
+ Accept: 'application/json',
137
+ },
138
+ body: form.toString(),
139
+ signal: ctx.signal,
140
+ rejectPrivateIPs: options.rejectPrivateIPs,
141
+ });
142
+ }
143
+ catch (err) {
144
+ throw forbidden(`Token exchange failed at ${url}. Verify credentials and that the server exposes /token.`, {
145
+ tokenUrl: url,
146
+ reason: 'auth_token_exchange_failed',
147
+ ...ctx.recoveryFor('auth_token_exchange_failed'),
148
+ }, { cause: err });
149
+ }
150
+ const text = await response.text();
151
+ if (!text) {
152
+ throw serviceUnavailable('Token exchange returned an empty body', { tokenUrl: url });
153
+ }
154
+ try {
155
+ return JSON.parse(text);
156
+ }
157
+ catch (err) {
158
+ throw serviceUnavailable('Token exchange returned non-JSON response', { tokenUrl: url, bodyPreview: text.slice(0, 200) }, { cause: err });
159
+ }
160
+ };
161
+ function connKey(alias) {
162
+ return `${CONN_PREFIX}${alias}`;
163
+ }
164
+ function validateAlias(alias) {
165
+ if (!/^[a-zA-Z0-9_-]+$/.test(alias)) {
166
+ throw validationError(`Invalid connection alias '${alias}'. Use letters, digits, '_', or '-'.`, { alias });
167
+ }
168
+ }
169
+ function validateBaseUrl(baseUrl) {
170
+ let parsed;
171
+ try {
172
+ parsed = new URL(baseUrl);
173
+ }
174
+ catch {
175
+ throw validationError(`Invalid baseUrl '${baseUrl}' — not a valid URL.`, { baseUrl });
176
+ }
177
+ if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
178
+ throw validationError(`Invalid baseUrl protocol '${parsed.protocol}'. Use http or https.`, {
179
+ baseUrl,
180
+ });
181
+ }
182
+ }
183
+ function normalizeBaseUrl(baseUrl) {
184
+ return baseUrl.replace(/\/+$/, '');
185
+ }
186
+ function joinUrl(baseUrl, path) {
187
+ const trimmedBase = baseUrl.replace(/\/+$/, '');
188
+ const prefixedPath = path.startsWith('/') ? path : `/${path}`;
189
+ return `${trimmedBase}${prefixedPath}`;
190
+ }
191
+ function isRegisteredServer(value) {
192
+ if (typeof value !== 'object' || value === null)
193
+ return false;
194
+ const v = value;
195
+ return (typeof v.alias === 'string' && typeof v.baseUrl === 'string' && typeof v.authMode === 'string');
196
+ }
197
+ let _registry;
198
+ export function initServerRegistry(serverConfig) {
199
+ _registry = new ServerRegistry(serverConfig);
200
+ }
201
+ export function getServerRegistry() {
202
+ if (!_registry) {
203
+ throw new Error('ServerRegistry not initialized — call initServerRegistry() in setup()');
204
+ }
205
+ return _registry;
206
+ }
207
+ export function resetServerRegistry() {
208
+ _registry = undefined;
209
+ }
210
+ //# sourceMappingURL=server-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-registry.js","sourceRoot":"","sources":["../../../src/services/server-registry/server-registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * @fileoverview Types for ServerRegistry — session-scoped connection aliases.
3
+ * A `RegisteredServer` holds everything tools need to route a request: the
4
+ * base URL, the resolved auth header, and the declared auth mode (so tools
5
+ * can surface meaningful re-auth guidance).
6
+ *
7
+ * @module services/server-registry/types
8
+ */
9
+ import type { ResolvedAuth } from '../../services/brapi-client/index.js';
10
+ export type AuthMode = 'none' | 'sgn' | 'oauth2' | 'api_key' | 'bearer';
11
+ export interface RegisteredServer {
12
+ alias: string;
13
+ authMode: AuthMode;
14
+ baseUrl: string;
15
+ registeredAt: string;
16
+ /** Resolved header to attach to outbound requests. Omitted for `none`. */
17
+ resolvedAuth?: ResolvedAuth;
18
+ }
19
+ /**
20
+ * Input accepted by `ServerRegistry.register`. Discriminated by `mode`.
21
+ * Optional fields allow `undefined` explicitly so Zod-parsed values (which
22
+ * carry optional-as-undefined) assign cleanly under `exactOptionalPropertyTypes`.
23
+ */
24
+ export type ConnectAuth = {
25
+ mode: 'none';
26
+ } | {
27
+ mode: 'sgn';
28
+ username: string;
29
+ password: string;
30
+ } | {
31
+ mode: 'oauth2';
32
+ clientId: string;
33
+ clientSecret: string;
34
+ tokenUrl?: string | undefined;
35
+ } | {
36
+ mode: 'api_key';
37
+ apiKey: string;
38
+ headerName?: string | undefined;
39
+ } | {
40
+ mode: 'bearer';
41
+ token: string;
42
+ };
43
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/server-registry/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAErE,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;AAExE,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED;;;;GAIG;AACH,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACnD;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B,GACD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GACpE;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @fileoverview Types for ServerRegistry — session-scoped connection aliases.
3
+ * A `RegisteredServer` holds everything tools need to route a request: the
4
+ * base URL, the resolved auth header, and the declared auth mode (so tools
5
+ * can surface meaningful re-auth guidance).
6
+ *
7
+ * @module services/server-registry/types
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/services/server-registry/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
package/package.json ADDED
@@ -0,0 +1,86 @@
1
+ {
2
+ "name": "@cyanheads/brapi-mcp-server",
3
+ "mcpName": "io.github.cyanheads/brapi-mcp-server",
4
+ "version": "0.3.5",
5
+ "description": "BrAPI v2.1 MCP server — studies, germplasm, observations, genotypes, images, and pedigrees.",
6
+ "author": "Casey Hand @cyanheads (https://github.com/cyanheads/brapi-mcp-server#readme)",
7
+ "type": "module",
8
+ "main": "dist/index.js",
9
+ "types": "dist/index.d.ts",
10
+ "bin": {
11
+ "brapi-mcp-server": "dist/index.js"
12
+ },
13
+ "files": [
14
+ "changelog/",
15
+ "dist/",
16
+ "README.md",
17
+ "LICENSE",
18
+ "CLAUDE.md",
19
+ "Dockerfile",
20
+ "server.json"
21
+ ],
22
+ "scripts": {
23
+ "build": "tsx scripts/build.ts",
24
+ "rebuild": "tsx scripts/clean.ts && tsx scripts/build.ts",
25
+ "clean": "tsx scripts/clean.ts",
26
+ "devcheck": "tsx scripts/devcheck.ts",
27
+ "tree": "tsx scripts/tree.ts",
28
+ "format": "biome check --write --unsafe .",
29
+ "lint:mcp": "tsx scripts/lint-mcp.ts",
30
+ "changelog:build": "tsx scripts/build-changelog.ts",
31
+ "changelog:check": "tsx scripts/build-changelog.ts --check",
32
+ "test": "bunx --bun vitest run",
33
+ "start": "node dist/index.js",
34
+ "start:stdio": "MCP_TRANSPORT_TYPE=stdio node dist/index.js",
35
+ "start:http": "MCP_TRANSPORT_TYPE=http node dist/index.js"
36
+ },
37
+ "keywords": [
38
+ "mcp",
39
+ "mcp-server",
40
+ "model-context-protocol",
41
+ "claude",
42
+ "brapi",
43
+ "breedbase",
44
+ "plant-breeding",
45
+ "bioinformatics",
46
+ "agriculture",
47
+ "phenotyping",
48
+ "genotyping",
49
+ "germplasm",
50
+ "pedigree",
51
+ "observations",
52
+ "llm-tools",
53
+ "typescript"
54
+ ],
55
+ "repository": {
56
+ "type": "git",
57
+ "url": "git+https://github.com/cyanheads/brapi-mcp-server.git"
58
+ },
59
+ "homepage": "https://github.com/cyanheads/brapi-mcp-server#readme",
60
+ "bugs": {
61
+ "url": "https://github.com/cyanheads/brapi-mcp-server/issues"
62
+ },
63
+ "license": "Apache-2.0",
64
+ "engines": {
65
+ "node": ">=22.0.0",
66
+ "bun": ">=1.2.0"
67
+ },
68
+ "packageManager": "bun@1.3.11",
69
+ "publishConfig": {
70
+ "access": "public"
71
+ },
72
+ "dependencies": {
73
+ "@cyanheads/mcp-ts-core": "^0.8.7",
74
+ "pino-pretty": "^13.1.3"
75
+ },
76
+ "devDependencies": {
77
+ "@biomejs/biome": "^2.4.13",
78
+ "@types/node": "^25.6.0",
79
+ "depcheck": "^1.4.7",
80
+ "ignore": "^7.0.5",
81
+ "tsc-alias": "^1.8.16",
82
+ "tsx": "^4.21.0",
83
+ "typescript": "^6.0.3",
84
+ "vitest": "^4.1.5"
85
+ }
86
+ }
package/server.json ADDED
@@ -0,0 +1,99 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
+ "name": "io.github.cyanheads/brapi-mcp-server",
4
+ "description": "BrAPI v2.1 MCP server — studies, germplasm, observations, genotypes, images, and pedigrees.",
5
+ "repository": {
6
+ "url": "https://github.com/cyanheads/brapi-mcp-server",
7
+ "source": "github"
8
+ },
9
+ "version": "0.3.5",
10
+ "packages": [
11
+ {
12
+ "registryType": "npm",
13
+ "registryBaseUrl": "https://registry.npmjs.org",
14
+ "identifier": "@cyanheads/brapi-mcp-server",
15
+ "runtimeHint": "node",
16
+ "version": "0.3.5",
17
+ "packageArguments": [
18
+ { "type": "positional", "value": "run" },
19
+ { "type": "positional", "value": "start:stdio" }
20
+ ],
21
+ "environmentVariables": [
22
+ {
23
+ "name": "BRAPI_DEFAULT_BASE_URL",
24
+ "description": "Default BrAPI v2 base URL. Optional — connections can be opened at runtime via the brapi_connect tool instead.",
25
+ "format": "string",
26
+ "isRequired": false
27
+ },
28
+ {
29
+ "name": "MCP_LOG_LEVEL",
30
+ "description": "Sets the minimum log level for output (e.g., 'debug', 'info', 'warn').",
31
+ "format": "string",
32
+ "isRequired": false,
33
+ "default": "info"
34
+ }
35
+ ],
36
+ "transport": {
37
+ "type": "stdio"
38
+ }
39
+ },
40
+ {
41
+ "registryType": "npm",
42
+ "registryBaseUrl": "https://registry.npmjs.org",
43
+ "identifier": "@cyanheads/brapi-mcp-server",
44
+ "runtimeHint": "node",
45
+ "version": "0.3.5",
46
+ "packageArguments": [
47
+ { "type": "positional", "value": "run" },
48
+ { "type": "positional", "value": "start:http" }
49
+ ],
50
+ "environmentVariables": [
51
+ {
52
+ "name": "BRAPI_DEFAULT_BASE_URL",
53
+ "description": "Default BrAPI v2 base URL. Optional — connections can be opened at runtime via the brapi_connect tool instead.",
54
+ "format": "string",
55
+ "isRequired": false
56
+ },
57
+ {
58
+ "name": "MCP_HTTP_HOST",
59
+ "description": "The hostname for the HTTP server.",
60
+ "format": "string",
61
+ "isRequired": false,
62
+ "default": "127.0.0.1"
63
+ },
64
+ {
65
+ "name": "MCP_HTTP_PORT",
66
+ "description": "The port to run the HTTP server on.",
67
+ "format": "string",
68
+ "isRequired": false,
69
+ "default": "3010"
70
+ },
71
+ {
72
+ "name": "MCP_HTTP_ENDPOINT_PATH",
73
+ "description": "The endpoint path for the MCP server.",
74
+ "format": "string",
75
+ "isRequired": false,
76
+ "default": "/mcp"
77
+ },
78
+ {
79
+ "name": "MCP_AUTH_MODE",
80
+ "description": "Authentication mode to use: 'none', 'jwt', or 'oauth'.",
81
+ "format": "string",
82
+ "isRequired": false,
83
+ "default": "none"
84
+ },
85
+ {
86
+ "name": "MCP_LOG_LEVEL",
87
+ "description": "Sets the minimum log level for output (e.g., 'debug', 'info', 'warn').",
88
+ "format": "string",
89
+ "isRequired": false,
90
+ "default": "info"
91
+ }
92
+ ],
93
+ "transport": {
94
+ "type": "streamable-http",
95
+ "url": "http://localhost:3010/mcp"
96
+ }
97
+ }
98
+ ]
99
+ }