@cyanheads/gbif-biodiversity-mcp-server 0.2.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 (82) hide show
  1. package/CLAUDE.md +393 -0
  2. package/Dockerfile +99 -0
  3. package/LICENSE +201 -0
  4. package/README.md +367 -0
  5. package/dist/config/server-config.d.ts +14 -0
  6. package/dist/config/server-config.d.ts.map +1 -0
  7. package/dist/config/server-config.js +27 -0
  8. package/dist/config/server-config.js.map +1 -0
  9. package/dist/index.d.ts +7 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +53 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/mcp-server/resources/definitions/gbif-dataset.resource.d.ts +20 -0
  14. package/dist/mcp-server/resources/definitions/gbif-dataset.resource.d.ts.map +1 -0
  15. package/dist/mcp-server/resources/definitions/gbif-dataset.resource.js +50 -0
  16. package/dist/mcp-server/resources/definitions/gbif-dataset.resource.js.map +1 -0
  17. package/dist/mcp-server/resources/definitions/gbif-species.resource.d.ts +27 -0
  18. package/dist/mcp-server/resources/definitions/gbif-species.resource.d.ts.map +1 -0
  19. package/dist/mcp-server/resources/definitions/gbif-species.resource.js +67 -0
  20. package/dist/mcp-server/resources/definitions/gbif-species.resource.js.map +1 -0
  21. package/dist/mcp-server/tools/definitions/gbif-count-occurrences.tool.d.ts +15 -0
  22. package/dist/mcp-server/tools/definitions/gbif-count-occurrences.tool.d.ts.map +1 -0
  23. package/dist/mcp-server/tools/definitions/gbif-count-occurrences.tool.js +42 -0
  24. package/dist/mcp-server/tools/definitions/gbif-count-occurrences.tool.js.map +1 -0
  25. package/dist/mcp-server/tools/definitions/gbif-get-dataset.tool.d.ts +33 -0
  26. package/dist/mcp-server/tools/definitions/gbif-get-dataset.tool.d.ts.map +1 -0
  27. package/dist/mcp-server/tools/definitions/gbif-get-dataset.tool.js +143 -0
  28. package/dist/mcp-server/tools/definitions/gbif-get-dataset.tool.js.map +1 -0
  29. package/dist/mcp-server/tools/definitions/gbif-get-occurrence.tool.d.ts +58 -0
  30. package/dist/mcp-server/tools/definitions/gbif-get-occurrence.tool.d.ts.map +1 -0
  31. package/dist/mcp-server/tools/definitions/gbif-get-occurrence.tool.js +264 -0
  32. package/dist/mcp-server/tools/definitions/gbif-get-occurrence.tool.js.map +1 -0
  33. package/dist/mcp-server/tools/definitions/gbif-get-species-children.tool.d.ts +25 -0
  34. package/dist/mcp-server/tools/definitions/gbif-get-species-children.tool.d.ts.map +1 -0
  35. package/dist/mcp-server/tools/definitions/gbif-get-species-children.tool.js +91 -0
  36. package/dist/mcp-server/tools/definitions/gbif-get-species-children.tool.js.map +1 -0
  37. package/dist/mcp-server/tools/definitions/gbif-get-species-classification.tool.d.ts +22 -0
  38. package/dist/mcp-server/tools/definitions/gbif-get-species-classification.tool.d.ts.map +1 -0
  39. package/dist/mcp-server/tools/definitions/gbif-get-species-classification.tool.js +82 -0
  40. package/dist/mcp-server/tools/definitions/gbif-get-species-classification.tool.js.map +1 -0
  41. package/dist/mcp-server/tools/definitions/gbif-get-species.tool.d.ts +45 -0
  42. package/dist/mcp-server/tools/definitions/gbif-get-species.tool.d.ts.map +1 -0
  43. package/dist/mcp-server/tools/definitions/gbif-get-species.tool.js +182 -0
  44. package/dist/mcp-server/tools/definitions/gbif-get-species.tool.js.map +1 -0
  45. package/dist/mcp-server/tools/definitions/gbif-match-species.tool.d.ts +49 -0
  46. package/dist/mcp-server/tools/definitions/gbif-match-species.tool.d.ts.map +1 -0
  47. package/dist/mcp-server/tools/definitions/gbif-match-species.tool.js +148 -0
  48. package/dist/mcp-server/tools/definitions/gbif-match-species.tool.js.map +1 -0
  49. package/dist/mcp-server/tools/definitions/gbif-occurrence-facets.tool.d.ts +45 -0
  50. package/dist/mcp-server/tools/definitions/gbif-occurrence-facets.tool.d.ts.map +1 -0
  51. package/dist/mcp-server/tools/definitions/gbif-occurrence-facets.tool.js +116 -0
  52. package/dist/mcp-server/tools/definitions/gbif-occurrence-facets.tool.js.map +1 -0
  53. package/dist/mcp-server/tools/definitions/gbif-search-datasets.tool.d.ts +34 -0
  54. package/dist/mcp-server/tools/definitions/gbif-search-datasets.tool.d.ts.map +1 -0
  55. package/dist/mcp-server/tools/definitions/gbif-search-datasets.tool.js +112 -0
  56. package/dist/mcp-server/tools/definitions/gbif-search-datasets.tool.js.map +1 -0
  57. package/dist/mcp-server/tools/definitions/gbif-search-occurrences.tool.d.ts +66 -0
  58. package/dist/mcp-server/tools/definitions/gbif-search-occurrences.tool.d.ts.map +1 -0
  59. package/dist/mcp-server/tools/definitions/gbif-search-occurrences.tool.js +278 -0
  60. package/dist/mcp-server/tools/definitions/gbif-search-occurrences.tool.js.map +1 -0
  61. package/dist/mcp-server/tools/definitions/gbif-search-publishers.tool.d.ts +23 -0
  62. package/dist/mcp-server/tools/definitions/gbif-search-publishers.tool.d.ts.map +1 -0
  63. package/dist/mcp-server/tools/definitions/gbif-search-publishers.tool.js +90 -0
  64. package/dist/mcp-server/tools/definitions/gbif-search-publishers.tool.js.map +1 -0
  65. package/dist/mcp-server/tools/definitions/gbif-search-species.tool.d.ts +48 -0
  66. package/dist/mcp-server/tools/definitions/gbif-search-species.tool.d.ts.map +1 -0
  67. package/dist/mcp-server/tools/definitions/gbif-search-species.tool.js +151 -0
  68. package/dist/mcp-server/tools/definitions/gbif-search-species.tool.js.map +1 -0
  69. package/dist/mcp-server/tools/utils.d.ts +7 -0
  70. package/dist/mcp-server/tools/utils.d.ts.map +1 -0
  71. package/dist/mcp-server/tools/utils.js +20 -0
  72. package/dist/mcp-server/tools/utils.js.map +1 -0
  73. package/dist/services/gbif/gbif-service.d.ts +99 -0
  74. package/dist/services/gbif/gbif-service.d.ts.map +1 -0
  75. package/dist/services/gbif/gbif-service.js +255 -0
  76. package/dist/services/gbif/gbif-service.js.map +1 -0
  77. package/dist/services/gbif/types.d.ts +254 -0
  78. package/dist/services/gbif/types.d.ts.map +1 -0
  79. package/dist/services/gbif/types.js +6 -0
  80. package/dist/services/gbif/types.js.map +1 -0
  81. package/package.json +91 -0
  82. package/server.json +117 -0
package/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright 2025 Casey Hand @cyanheads
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
package/README.md ADDED
@@ -0,0 +1,367 @@
1
+ <div align="center">
2
+ <h1>@cyanheads/gbif-biodiversity-mcp-server</h1>
3
+ <p><b>Search GBIF species taxonomy, occurrence records, datasets, and publishers via MCP. STDIO or Streamable HTTP.</b>
4
+ <div>12 Tools • 2 Resources</div>
5
+ </p>
6
+ </div>
7
+
8
+ <div align="center">
9
+
10
+ [![Version](https://img.shields.io/badge/Version-0.2.0-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![Docker](https://img.shields.io/badge/Docker-ghcr.io-2496ED?style=flat-square&logo=docker&logoColor=white)](https://github.com/users/cyanheads/packages/container/package/gbif-biodiversity-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^1.29.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![npm](https://img.shields.io/npm/v/@cyanheads/gbif-biodiversity-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/gbif-biodiversity-mcp-server) [![TypeScript](https://img.shields.io/badge/TypeScript-^6.0.3-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.3.2-blueviolet.svg?style=flat-square)](https://bun.sh/)
11
+
12
+ </div>
13
+
14
+ <div align="center">
15
+
16
+ [![Install in Claude Desktop](https://img.shields.io/badge/Install_in-Claude_Desktop-D97757?style=for-the-badge&logo=anthropic&logoColor=white)](https://github.com/cyanheads/gbif-biodiversity-mcp-server/releases/latest/download/gbif-biodiversity-mcp-server.mcpb) [![Install in Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=gbif-biodiversity-mcp-server&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjeWFuaGVhZHMvZ2JpZi1iaW9kaXZlcnNpdHktbWNwLXNlcnZlciJdfQ==) [![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_Server-0098FF?style=for-the-badge&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect?url=vscode:mcp/install?%7B%22name%22%3A%22gbif-biodiversity-mcp-server%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40cyanheads%2Fgbif-biodiversity-mcp-server%22%5D%7D)
17
+
18
+ [![Framework](https://img.shields.io/badge/Built%20on-@cyanheads/mcp--ts--core-67E8F9?style=flat-square)](https://www.npmjs.com/package/@cyanheads/mcp-ts-core)
19
+
20
+ **Public Hosted Server:** [https://gbif-biodiversity.caseyjhand.com/mcp](https://gbif-biodiversity.caseyjhand.com/mcp)
21
+
22
+ </div>
23
+
24
+ ---
25
+
26
+ ## Tools
27
+
28
+ 12 tools for working with GBIF species taxonomy, occurrence records, datasets, and publishers:
29
+
30
+ | Tool | Description |
31
+ |:---|:---|
32
+ | `gbif_match_species` | Match a species name against the GBIF backbone taxonomy — returns taxonKey, confidence score, and full classification |
33
+ | `gbif_get_species` | Fetch a single backbone taxon by key — full classification, authorship, synonymy, vernacular name, descendant count |
34
+ | `gbif_search_species` | Search or browse the GBIF backbone taxonomy by name fragment, rank, kingdom, family, or genus |
35
+ | `gbif_get_species_classification` | Return the complete parent chain for a taxon — root-first ordered array from kingdom to immediate parent |
36
+ | `gbif_get_species_children` | List direct children of a backbone taxon — genera within a family, species within a genus |
37
+ | `gbif_search_occurrences` | Search 2.4B+ GBIF occurrence records with Darwin Core filters — country, bounding box, WKT geometry, year, month, basis of record |
38
+ | `gbif_count_occurrences` | Count occurrences matching a filter without fetching records — fast single-number response |
39
+ | `gbif_get_occurrence` | Fetch a single occurrence record by key — full Darwin Core record with GADM geography, media, and quality flags |
40
+ | `gbif_occurrence_facets` | Aggregate occurrence counts by a dimension — country, year, basis of record, dataset, kingdom, and more |
41
+ | `gbif_search_datasets` | Search GBIF datasets by keyword, type, country, or publishing organization |
42
+ | `gbif_get_dataset` | Fetch full dataset metadata by UUID — title, description, citation, contacts, license, DOI, coverage |
43
+ | `gbif_search_publishers` | Search GBIF-registered publishing organizations by name fragment or country |
44
+
45
+ ### `gbif_match_species`
46
+
47
+ Match a scientific or common name against the GBIF backbone taxonomy.
48
+
49
+ - Fuzzy matching handles minor typos and vernacular names; set `strict: true` for exact-only matching
50
+ - Returns `taxonKey` — the backbone key required by `gbif_search_occurrences`, `gbif_count_occurrences`, and `gbif_occurrence_facets`
51
+ - Confidence score 0–100; below 80 warrants review
52
+ - Full classification hierarchy with keys at each rank: kingdom, phylum, class, order, family, genus, species
53
+ - `matchType NONE` indicates no usable match — try removing strict mode or broadening the name
54
+ - Resolves synonyms: always returns the accepted backbone key regardless of which name form was queried
55
+
56
+ ---
57
+
58
+ ### `gbif_get_species`
59
+
60
+ Fetch a complete taxon record by GBIF backbone key.
61
+
62
+ - Full classification, authorship string, and vernacular (English) name when available
63
+ - `taxonomicStatus`: ACCEPTED, SYNONYM, DOUBTFUL — when SYNONYM, `acceptedKey` and `accepted` identify the current name
64
+ - `numDescendants` and `numOccurrences` for scope at a glance
65
+ - `extinct` field present only when explicitly flagged — not false on unlabeled taxa
66
+ - `publishedIn` carries the original description citation when available
67
+
68
+ ---
69
+
70
+ ### `gbif_search_species`
71
+
72
+ Search or browse the GBIF backbone taxonomy.
73
+
74
+ - Accepts name fragments matching scientific and vernacular names
75
+ - Filter by rank, kingdom, family, or genus to scope browsing
76
+ - `isExtinct` filter for extinct vs. extant taxa
77
+ - Scope to a specific checklist dataset with `datasetKey` (omit for the GBIF backbone)
78
+ - Paginated — limit up to 1000, use offset to walk through large groups
79
+
80
+ ---
81
+
82
+ ### `gbif_get_species_classification`
83
+
84
+ Return the full parent chain for a taxon as an ordered array.
85
+
86
+ - Root-first (kingdom → phylum → class → order → family → genus → species → up to parent of queried taxon)
87
+ - Each entry: rank, canonical name, scientific name, taxon key
88
+ - Useful for building taxonomic trees or placing an unfamiliar taxon in context without manual backbone navigation
89
+
90
+ ---
91
+
92
+ ### `gbif_get_species_children`
93
+
94
+ List direct children of a backbone taxon.
95
+
96
+ - Genera within a family, species within a genus, subspecies within a species
97
+ - Each child: key, name, rank, taxonomic status, common name, occurrence count, descendant count
98
+ - Paginated — limit up to 1000, iterate with offset for large groups like Coleoptera
99
+
100
+ ---
101
+
102
+ ### `gbif_search_occurrences`
103
+
104
+ Search 2.4B+ GBIF occurrence records with full Darwin Core filtering.
105
+
106
+ - Use `taxonKey` from `gbif_match_species` for reliable results — resolves synonyms automatically; `scientificName` filter does not
107
+ - Geographic filters: `country` (ISO 3166-1 alpha-2), bounding box (`decimalLatitude`/`decimalLongitude` ranges as "min,max"), or WKT polygon (`geometry`)
108
+ - Temporal filters: `year` as single year or range, `month` (1–12) for seasonal queries
109
+ - `basisOfRecord` enum: `HUMAN_OBSERVATION`, `PRESERVED_SPECIMEN`, `MACHINE_OBSERVATION`, and more
110
+ - `hasCoordinate` to require or exclude georeferenced records
111
+ - Pagination capped at offset+limit ≈ 100,000 — use `gbif_occurrence_facets` for aggregate analysis beyond this
112
+
113
+ ---
114
+
115
+ ### `gbif_count_occurrences`
116
+
117
+ Count occurrences matching a filter without fetching any records.
118
+
119
+ - Backed by the lightweight `/occurrence/count` endpoint — fast single-number response
120
+ - Supported filters: `taxonKey`, `country`, `isGeoreferenced`, `datasetKey`, `year`
121
+ - Use to assess result set size before deciding whether to paginate a full search
122
+
123
+ ---
124
+
125
+ ### `gbif_get_occurrence`
126
+
127
+ Fetch a single occurrence record by GBIF occurrence key.
128
+
129
+ - Complete Darwin Core record — all coordinate fields, GADM administrative geography (continent, country, state/province, locality), dates
130
+ - Collections metadata: institution code, collection code, catalog number
131
+ - Collector and identifier names, individual count, sex, life stage
132
+ - Associated media (images, audio, video) with URLs and license
133
+ - GBIF data quality issue flags for provenance assessment
134
+
135
+ ---
136
+
137
+ ### `gbif_occurrence_facets`
138
+
139
+ Aggregate occurrence counts across a dimension.
140
+
141
+ - Facets: `COUNTRY`, `YEAR`, `BASIS_OF_RECORD`, `DATASET_KEY`, `KINGDOM_KEY`, `PHYLUM_KEY`, `CLASS_KEY`, `ORDER_KEY`, `FAMILY_KEY`, `GENUS_KEY`, `SPECIES_KEY`, `PUBLISHING_COUNTRY`, `MONTH`
142
+ - Scope with `taxonKey`, `country`, `year`, `geometry`, or `basisOfRecord` filters
143
+ - Returns top-N values (up to 100) ranked by count — no record payloads
144
+ - Core tool for distribution analysis ("which countries have the most records?") and trend queries ("how has observation volume changed since 2010?")
145
+
146
+ ---
147
+
148
+ ### `gbif_search_datasets`
149
+
150
+ Search GBIF datasets by keyword, type, country, or publishing organization.
151
+
152
+ - Filters: free-text query, dataset type (`OCCURRENCE`, `CHECKLIST`, `METADATA`, `SAMPLING_EVENT`), publishing country, hosting organization UUID
153
+ - Returns title, type, description, license, DOI, and record count
154
+ - Use `hostingOrg` from `gbif_search_publishers` to scope to datasets from one organization
155
+ - Paginated — limit up to 1000
156
+
157
+ ---
158
+
159
+ ### `gbif_get_dataset`
160
+
161
+ Fetch full dataset metadata by UUID.
162
+
163
+ - Full description, citation text (for academic reference), license, DOI
164
+ - Contacts with role, name, organization, and email
165
+ - `numConstituents` for aggregate datasets (e.g. iNaturalist, eBird)
166
+ - Use after `gbif_search_datasets` or when an occurrence record's `datasetKey` needs provenance detail
167
+
168
+ ---
169
+
170
+ ### `gbif_search_publishers`
171
+
172
+ Search organizations registered with GBIF.
173
+
174
+ - Filter by name fragment or country
175
+ - Returns organization key, title, and country — sufficient to chain into `gbif_search_datasets` with `hostingOrg`
176
+ - Paginated — limit up to 1000
177
+
178
+ ## Resources
179
+
180
+ | Type | Name | Description |
181
+ |:---|:---|:---|
182
+ | Resource | `gbif://species/{taxonKey}` | Taxon record from the GBIF backbone — classification, authorship, synonymy status, vernacular name |
183
+ | Resource | `gbif://dataset/{datasetKey}` | Dataset metadata — title, description, citation, license, contacts, coverage |
184
+
185
+ ## Features
186
+
187
+ Built on [`@cyanheads/mcp-ts-core`](https://github.com/cyanheads/mcp-ts-core):
188
+
189
+ - Declarative tool definitions — single file per tool, framework handles registration and validation
190
+ - Unified error handling across all tools
191
+ - Pluggable auth (`none`, `jwt`, `oauth`)
192
+ - Swappable storage backends: `in-memory`, `filesystem`, `Supabase`, `Cloudflare KV/R2/D1`
193
+ - Structured logging with optional OpenTelemetry tracing
194
+ - Runs locally (stdio/HTTP) or on Cloudflare Workers from the same codebase
195
+
196
+ GBIF-specific:
197
+
198
+ - Full GBIF REST API v1 coverage: species taxonomy, occurrences, datasets, and publishers
199
+ - `gbif_match_species` as the entry point — resolves synonyms to backbone taxon keys used throughout
200
+ - Occurrence pagination cap detection with `paginationNote` — redirects to facet aggregation before hitting the ~100,000 row limit
201
+ - WKT polygon geometry support for geographic occurrence queries
202
+ - Darwin Core field mapping with explicit provenance on sparse upstream fields
203
+
204
+ Agent-friendly output:
205
+
206
+ - `gbif_match_species` is the mandatory first step — all downstream tools document which key they expect
207
+ - Graceful sparse-field handling — optional fields absent from the API response are omitted rather than null-filled
208
+ - Discriminated error contracts with typed reasons, structured recovery hints, and `when` documentation per tool
209
+
210
+ ## Getting started
211
+
212
+ ### Self-Hosted / Local
213
+
214
+ Add the following to your MCP client configuration file.
215
+
216
+ ```json
217
+ {
218
+ "mcpServers": {
219
+ "gbif": {
220
+ "type": "stdio",
221
+ "command": "bunx",
222
+ "args": ["@cyanheads/gbif-biodiversity-mcp-server@latest"],
223
+ "env": {
224
+ "MCP_TRANSPORT_TYPE": "stdio",
225
+ "MCP_LOG_LEVEL": "info"
226
+ }
227
+ }
228
+ }
229
+ }
230
+ ```
231
+
232
+ Or with npx (no Bun required):
233
+
234
+ ```json
235
+ {
236
+ "mcpServers": {
237
+ "gbif": {
238
+ "type": "stdio",
239
+ "command": "npx",
240
+ "args": ["-y", "@cyanheads/gbif-biodiversity-mcp-server@latest"],
241
+ "env": {
242
+ "MCP_TRANSPORT_TYPE": "stdio",
243
+ "MCP_LOG_LEVEL": "info"
244
+ }
245
+ }
246
+ }
247
+ }
248
+ ```
249
+
250
+ Or with Docker:
251
+
252
+ ```json
253
+ {
254
+ "mcpServers": {
255
+ "gbif": {
256
+ "type": "stdio",
257
+ "command": "docker",
258
+ "args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "ghcr.io/cyanheads/gbif-biodiversity-mcp-server:latest"]
259
+ }
260
+ }
261
+ }
262
+ ```
263
+
264
+ For Streamable HTTP, set the transport and start the server:
265
+
266
+ ```sh
267
+ MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
268
+ # Server listens at http://localhost:3010/mcp
269
+ ```
270
+
271
+ ### Prerequisites
272
+
273
+ - [Bun v1.3.2](https://bun.sh/) or higher.
274
+ - Optional: [GBIF API key](https://www.gbif.org/developer/summary) for higher rate limits.
275
+
276
+ ### Installation
277
+
278
+ 1. **Clone the repository:**
279
+
280
+ ```sh
281
+ git clone https://github.com/cyanheads/gbif-biodiversity-mcp-server.git
282
+ ```
283
+
284
+ 2. **Navigate into the directory:**
285
+
286
+ ```sh
287
+ cd gbif-biodiversity-mcp-server
288
+ ```
289
+
290
+ 3. **Install dependencies:**
291
+
292
+ ```sh
293
+ bun install
294
+ ```
295
+
296
+ ## Configuration
297
+
298
+ All configuration is validated at startup via Zod schemas in `src/config/server-config.ts`. Key environment variables:
299
+
300
+ | Variable | Description | Default |
301
+ |:---|:---|:---|
302
+ | `MCP_TRANSPORT_TYPE` | Transport: `stdio` or `http` | `stdio` |
303
+ | `MCP_HTTP_PORT` | HTTP server port | `3010` |
304
+ | `MCP_HTTP_ENDPOINT_PATH` | HTTP endpoint path where the MCP server is mounted | `/mcp` |
305
+ | `MCP_PUBLIC_URL` | Public origin override for TLS-terminating reverse-proxy deployments | none |
306
+ | `MCP_AUTH_MODE` | Authentication: `none`, `jwt`, or `oauth` | `none` |
307
+ | `MCP_LOG_LEVEL` | Log level (`debug`, `info`, `warning`, `error`, etc.) | `info` |
308
+ | `MCP_GC_PRESSURE_INTERVAL_MS` | Opt-in Bun-only forced-GC pressure loop (ms). Try `60000` if RSS grows under sustained HTTP load. | `0` (disabled) |
309
+ | `LOGS_DIR` | Directory for log files (Node.js only) | `<project-root>/logs` |
310
+ | `STORAGE_PROVIDER_TYPE` | Storage backend: `in-memory`, `filesystem`, `supabase`, `cloudflare-kv/r2/d1` | `in-memory` |
311
+ | `GBIF_API_KEY` | GBIF API key. Sent as HTTP Basic Auth username for higher rate limits. | none |
312
+ | `GBIF_BASE_URL` | GBIF API base URL override | `https://api.gbif.org/v1` |
313
+ | `GBIF_REQUEST_TIMEOUT_MS` | HTTP request timeout in milliseconds | `10000` |
314
+ | `OTEL_ENABLED` | Enable OpenTelemetry | `false` |
315
+
316
+ ## Running the server
317
+
318
+ ### Local development
319
+
320
+ - **Build and run the production version**:
321
+
322
+ ```sh
323
+ # One-time build
324
+ bun run rebuild
325
+
326
+ # Run the built server
327
+ bun run start:http
328
+ # or
329
+ bun run start:stdio
330
+ ```
331
+
332
+ - **Run checks and tests**:
333
+ ```sh
334
+ bun run devcheck # Lints, formats, type-checks, and more
335
+ bun run test # Runs the test suite
336
+ ```
337
+
338
+ ## Project structure
339
+
340
+ | Directory | Purpose |
341
+ |:---|:---|
342
+ | `src/mcp-server/tools` | Tool definitions (`*.tool.ts`). Twelve tools across species taxonomy, occurrences, datasets, and publishers. |
343
+ | `src/mcp-server/resources` | Resource definitions. Species and dataset stable-URI resources. |
344
+ | `src/services/gbif` | GBIF REST API service layer — client, request handling, type definitions. |
345
+ | `src/config` | Server-specific environment variable parsing and validation with Zod. |
346
+ | `tests/` | Unit and integration tests, mirroring the `src/` structure. |
347
+
348
+ ## Development guide
349
+
350
+ See [`CLAUDE.md`](./CLAUDE.md) for development guidelines and architectural rules. The short version:
351
+
352
+ - Handlers throw, framework catches — no `try/catch` in tool logic
353
+ - Use `ctx.log` for logging, `ctx.state` for storage
354
+ - Register new tools and resources in the `createApp()` arrays
355
+
356
+ ## Contributing
357
+
358
+ Issues and pull requests are welcome. Run checks and tests before submitting:
359
+
360
+ ```sh
361
+ bun run devcheck
362
+ bun run test
363
+ ```
364
+
365
+ ## License
366
+
367
+ This project is licensed under the Apache 2.0 License. See the [LICENSE](./LICENSE) file for details.
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @fileoverview Server-specific configuration for gbif-biodiversity-mcp-server.
3
+ * @module config/server-config
4
+ */
5
+ import { z } from '@cyanheads/mcp-ts-core';
6
+ declare const ServerConfigSchema: z.ZodObject<{
7
+ apiKey: z.ZodOptional<z.ZodString>;
8
+ baseUrl: z.ZodDefault<z.ZodString>;
9
+ requestTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
10
+ }, z.core.$strip>;
11
+ type ServerConfig = z.infer<typeof ServerConfigSchema>;
12
+ export declare function getServerConfig(): ServerConfig;
13
+ export {};
14
+ //# sourceMappingURL=server-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-config.d.ts","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAG3C,QAAA,MAAM,kBAAkB;;;;iBAYtB,CAAC;AAEH,KAAK,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAIvD,wBAAgB,eAAe,IAAI,YAAY,CAO9C"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @fileoverview Server-specific configuration for gbif-biodiversity-mcp-server.
3
+ * @module config/server-config
4
+ */
5
+ import { z } from '@cyanheads/mcp-ts-core';
6
+ import { parseEnvConfig } from '@cyanheads/mcp-ts-core/config';
7
+ const ServerConfigSchema = z.object({
8
+ apiKey: z
9
+ .string()
10
+ .optional()
11
+ .describe('GBIF API key for higher rate limits. Sent as HTTP Basic Auth username with empty password.'),
12
+ baseUrl: z.string().default('https://api.gbif.org/v1').describe('GBIF API base URL.'),
13
+ requestTimeoutMs: z.coerce
14
+ .number()
15
+ .default(10_000)
16
+ .describe('HTTP request timeout in milliseconds.'),
17
+ });
18
+ let _config;
19
+ export function getServerConfig() {
20
+ _config ??= parseEnvConfig(ServerConfigSchema, {
21
+ apiKey: 'GBIF_API_KEY',
22
+ baseUrl: 'GBIF_BASE_URL',
23
+ requestTimeoutMs: 'GBIF_REQUEST_TIMEOUT_MS',
24
+ });
25
+ return _config;
26
+ }
27
+ //# sourceMappingURL=server-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-config.js","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAE/D,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,MAAM,EAAE,CAAC;SACN,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,4FAA4F,CAC7F;IACH,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC,QAAQ,CAAC,oBAAoB,CAAC;IACrF,gBAAgB,EAAE,CAAC,CAAC,MAAM;SACvB,MAAM,EAAE;SACR,OAAO,CAAC,MAAM,CAAC;SACf,QAAQ,CAAC,uCAAuC,CAAC;CACrD,CAAC,CAAC;AAIH,IAAI,OAAiC,CAAC;AAEtC,MAAM,UAAU,eAAe;IAC7B,OAAO,KAAK,cAAc,CAAC,kBAAkB,EAAE;QAC7C,MAAM,EAAE,cAAc;QACtB,OAAO,EAAE,eAAe;QACxB,gBAAgB,EAAE,yBAAyB;KAC5C,CAAC,CAAC;IACH,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @fileoverview gbif-biodiversity-mcp-server MCP server entry point.
4
+ * @module index
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG"}