@cyanheads/gbif-biodiversity-mcp-server 0.4.0 → 0.5.1
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.
- package/CLAUDE.md +2 -2
- package/Dockerfile +10 -6
- package/README.md +19 -5
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp-server/resources/definitions/gbif-dataset.resource.d.ts +16 -0
- package/dist/mcp-server/resources/definitions/gbif-dataset.resource.d.ts.map +1 -1
- package/dist/mcp-server/resources/definitions/gbif-dataset.resource.js +61 -1
- package/dist/mcp-server/resources/definitions/gbif-dataset.resource.js.map +1 -1
- package/dist/mcp-server/resources/definitions/gbif-species.resource.js +1 -1
- package/dist/mcp-server/tools/definitions/gbif-bulk-match-species.tool.d.ts +22 -0
- package/dist/mcp-server/tools/definitions/gbif-bulk-match-species.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/gbif-bulk-match-species.tool.js +126 -0
- package/dist/mcp-server/tools/definitions/gbif-bulk-match-species.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/gbif-get-dataset.tool.d.ts +7 -0
- package/dist/mcp-server/tools/definitions/gbif-get-dataset.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/gbif-get-dataset.tool.js +41 -14
- package/dist/mcp-server/tools/definitions/gbif-get-dataset.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/gbif-get-occurrence.tool.d.ts +21 -0
- package/dist/mcp-server/tools/definitions/gbif-get-occurrence.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/gbif-get-occurrence.tool.js +77 -0
- package/dist/mcp-server/tools/definitions/gbif-get-occurrence.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/gbif-get-species-children.tool.d.ts +3 -1
- package/dist/mcp-server/tools/definitions/gbif-get-species-children.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/gbif-get-species-children.tool.js +20 -4
- package/dist/mcp-server/tools/definitions/gbif-get-species-children.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/gbif-get-species.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/gbif-get-species.tool.js +19 -2
- package/dist/mcp-server/tools/definitions/gbif-get-species.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/gbif-match-species.tool.js +1 -1
- package/dist/mcp-server/tools/definitions/gbif-match-species.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/gbif-search-species.tool.js +1 -1
- package/dist/mcp-server/tools/utils.d.ts +34 -0
- package/dist/mcp-server/tools/utils.d.ts.map +1 -1
- package/dist/mcp-server/tools/utils.js +41 -0
- package/dist/mcp-server/tools/utils.js.map +1 -1
- package/dist/services/gbif/types.d.ts +30 -6
- package/dist/services/gbif/types.d.ts.map +1 -1
- package/package.json +6 -5
- package/server.json +3 -3
package/CLAUDE.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Developer Protocol
|
|
2
2
|
|
|
3
3
|
**Server:** @cyanheads/gbif-biodiversity-mcp-server
|
|
4
|
-
**Version:** 0.
|
|
5
|
-
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.10.
|
|
4
|
+
**Version:** 0.5.1
|
|
5
|
+
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.10.14`
|
|
6
6
|
**Engines:** Bun ≥1.3.0, Node ≥24.0.0
|
|
7
7
|
**MCP SDK:** `@modelcontextprotocol/sdk` ^1.29.0
|
|
8
8
|
**Zod:** ^4.4.3
|
package/Dockerfile
CHANGED
|
@@ -4,15 +4,17 @@
|
|
|
4
4
|
# This stage installs all dependencies (including dev), builds the TypeScript
|
|
5
5
|
# source code into JavaScript, and prepares the production assets.
|
|
6
6
|
# ==============================================================================
|
|
7
|
-
FROM oven/bun:1.3 AS build
|
|
7
|
+
FROM oven/bun:1.3.14 AS build
|
|
8
8
|
|
|
9
9
|
WORKDIR /usr/src/app
|
|
10
10
|
|
|
11
11
|
# Copy dependency manifests for optimized layer caching
|
|
12
12
|
COPY package.json bun.lock ./
|
|
13
13
|
|
|
14
|
-
# Install all dependencies (including dev dependencies for building)
|
|
15
|
-
|
|
14
|
+
# Install all dependencies (including dev dependencies for building).
|
|
15
|
+
# The BuildKit cache mount persists Bun's global package cache across builds.
|
|
16
|
+
RUN --mount=type=cache,target=/root/.bun/install/cache \
|
|
17
|
+
bun install --frozen-lockfile --ignore-scripts
|
|
16
18
|
|
|
17
19
|
# Copy the rest of the source code
|
|
18
20
|
COPY . .
|
|
@@ -28,7 +30,7 @@ RUN bun run build
|
|
|
28
30
|
# application. It uses a slim base image and only includes production
|
|
29
31
|
# dependencies and build artifacts.
|
|
30
32
|
# ==============================================================================
|
|
31
|
-
FROM oven/bun:1.3-slim AS production
|
|
33
|
+
FROM oven/bun:1.3.14-slim AS production
|
|
32
34
|
|
|
33
35
|
WORKDIR /usr/src/app
|
|
34
36
|
|
|
@@ -49,13 +51,15 @@ COPY package.json bun.lock ./
|
|
|
49
51
|
|
|
50
52
|
# Install only production dependencies, ignoring any lifecycle scripts (like 'prepare')
|
|
51
53
|
# that are not needed in the final production image.
|
|
52
|
-
RUN bun
|
|
54
|
+
RUN --mount=type=cache,target=/root/.bun/install/cache \
|
|
55
|
+
bun install --production --frozen-lockfile --ignore-scripts
|
|
53
56
|
|
|
54
57
|
# Conditionally install OpenTelemetry optional peer dependencies (Tier 3).
|
|
55
58
|
# These are not bundled by default to keep the base image lean. Enable at build time
|
|
56
59
|
# with: docker build --build-arg OTEL_ENABLED=true
|
|
57
60
|
ARG OTEL_ENABLED=true
|
|
58
|
-
RUN
|
|
61
|
+
RUN --mount=type=cache,target=/root/.bun/install/cache \
|
|
62
|
+
if [ "$OTEL_ENABLED" = "true" ]; then \
|
|
59
63
|
bun add @hono/otel \
|
|
60
64
|
@opentelemetry/instrumentation-http \
|
|
61
65
|
@opentelemetry/exporter-metrics-otlp-http \
|
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
<h1>@cyanheads/gbif-biodiversity-mcp-server</h1>
|
|
3
3
|
<p><b>Search GBIF species taxonomy, occurrence records, datasets, and publishers via MCP. STDIO or Streamable HTTP.</b>
|
|
4
|
-
<div>
|
|
4
|
+
<div>13 Tools • 2 Resources</div>
|
|
5
5
|
</p>
|
|
6
6
|
</div>
|
|
7
7
|
|
|
8
8
|
<div align="center">
|
|
9
9
|
|
|
10
|
-
[](./CHANGELOG.md) [](./LICENSE) [](https://github.com/users/cyanheads/packages/container/package/gbif-biodiversity-mcp-server) [](https://modelcontextprotocol.io/) [](https://www.npmjs.com/package/@cyanheads/gbif-biodiversity-mcp-server) [](https://www.typescriptlang.org/) [](https://bun.sh/)
|
|
11
11
|
|
|
12
12
|
</div>
|
|
13
13
|
|
|
@@ -25,11 +25,12 @@
|
|
|
25
25
|
|
|
26
26
|
## Tools
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
13 tools for working with GBIF species taxonomy, occurrence records, datasets, and publishers:
|
|
29
29
|
|
|
30
30
|
| Tool | Description |
|
|
31
31
|
|:---|:---|
|
|
32
32
|
| `gbif_match_species` | Match a species name against the GBIF backbone taxonomy — returns taxonKey, confidence score, and full classification |
|
|
33
|
+
| `gbif_bulk_match_species` | Match up to 50 scientific names to backbone taxon keys in one call — results in input order, per-name NONE/ERROR isolation |
|
|
33
34
|
| `gbif_get_species` | Fetch a single backbone taxon by key — full classification, authorship, synonymy, vernacular name, descendant count |
|
|
34
35
|
| `gbif_search_species` | Search or browse the GBIF backbone taxonomy by name fragment, rank, kingdom, family, or genus |
|
|
35
36
|
| `gbif_get_species_classification` | Return the complete parent chain for a taxon — root-first ordered array from kingdom to immediate parent |
|
|
@@ -55,6 +56,17 @@ Match a scientific or common name against the GBIF backbone taxonomy.
|
|
|
55
56
|
|
|
56
57
|
---
|
|
57
58
|
|
|
59
|
+
### `gbif_bulk_match_species`
|
|
60
|
+
|
|
61
|
+
Match up to 50 scientific names against the GBIF backbone taxonomy in a single call.
|
|
62
|
+
|
|
63
|
+
- The batch counterpart to `gbif_match_species` — built for checklist, inventory, and species-list workflows that would otherwise need one round trip per name
|
|
64
|
+
- Returns one result per input name, in input order; each carries `taxonKey`, `matchType`, and confidence
|
|
65
|
+
- Per-name isolation: an unmatched name yields `matchType NONE` and a per-name lookup failure yields `matchType ERROR` — neither sinks the rest of the batch
|
|
66
|
+
- `strict: true` requires an exact match for every name; common names are not supported (use `gbif_search_species`)
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
58
70
|
### `gbif_get_species`
|
|
59
71
|
|
|
60
72
|
Fetch a complete taxon record by GBIF backbone key.
|
|
@@ -126,7 +138,8 @@ Count occurrences matching a filter without fetching any records.
|
|
|
126
138
|
|
|
127
139
|
Fetch a single occurrence record by GBIF occurrence key.
|
|
128
140
|
|
|
129
|
-
- Complete Darwin Core record — all coordinate fields,
|
|
141
|
+
- Complete Darwin Core record — all coordinate fields, administrative geography (continent, country, state/province, locality), dates
|
|
142
|
+
- `occurrenceID`, full classification (`class`/`classKey`), GADM administrative units (levels 0–2, each with a stable GID and name), and source `identifiers`
|
|
130
143
|
- Collections metadata: institution code, collection code, catalog number
|
|
131
144
|
- Collector and identifier names, individual count, sex, life stage
|
|
132
145
|
- Associated media (images, audio, video) with URLs and license
|
|
@@ -162,6 +175,7 @@ Fetch full dataset metadata by UUID.
|
|
|
162
175
|
|
|
163
176
|
- Full description, citation text (for academic reference), license, DOI
|
|
164
177
|
- Contacts with role, name, organization, and email
|
|
178
|
+
- Temporal and geographic coverage ranges when the publisher declares them
|
|
165
179
|
- `numConstituents` for aggregate datasets (e.g. iNaturalist, eBird)
|
|
166
180
|
- Use after `gbif_search_datasets` or when an occurrence record's `datasetKey` needs provenance detail
|
|
167
181
|
|
|
@@ -338,7 +352,7 @@ All configuration is validated at startup via Zod schemas in `src/config/server-
|
|
|
338
352
|
|
|
339
353
|
| Directory | Purpose |
|
|
340
354
|
|:---|:---|
|
|
341
|
-
| `src/mcp-server/tools` | Tool definitions (`*.tool.ts`).
|
|
355
|
+
| `src/mcp-server/tools` | Tool definitions (`*.tool.ts`). Thirteen tools across species taxonomy, occurrences, datasets, and publishers. |
|
|
342
356
|
| `src/mcp-server/resources` | Resource definitions. Species and dataset stable-URI resources. |
|
|
343
357
|
| `src/services/gbif` | GBIF REST API service layer — client, request handling, type definitions. |
|
|
344
358
|
| `src/config` | Server-specific environment variable parsing and validation with Zod. |
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,7 @@ import { getServerConfig } from './config/server-config.js';
|
|
|
8
8
|
// Resources
|
|
9
9
|
import { gbifDatasetResource } from './mcp-server/resources/definitions/gbif-dataset.resource.js';
|
|
10
10
|
import { gbifSpeciesResource } from './mcp-server/resources/definitions/gbif-species.resource.js';
|
|
11
|
+
import { gbifBulkMatchSpecies } from './mcp-server/tools/definitions/gbif-bulk-match-species.tool.js';
|
|
11
12
|
import { gbifCountOccurrences } from './mcp-server/tools/definitions/gbif-count-occurrences.tool.js';
|
|
12
13
|
import { gbifGetDataset } from './mcp-server/tools/definitions/gbif-get-dataset.tool.js';
|
|
13
14
|
import { gbifGetOccurrence } from './mcp-server/tools/definitions/gbif-get-occurrence.tool.js';
|
|
@@ -30,6 +31,7 @@ await createApp({
|
|
|
30
31
|
instructions: 'Use the gbif_* tools to query species taxonomy, occurrences, datasets, and publishers via the GBIF API. Keyless; an optional API key only raises rate limits. Resolve any name with gbif_match_species first — it returns the backbone taxonKey the occurrence tools expect and resolves synonyms, unlike the raw scientificName filter. Countries use ISO 3166-1 alpha-2; datasets and publishers are keyed by UUID, occurrences by integer key. Occurrence paging caps at offset+limit ≈ 100,000 — switch to gbif_occurrence_facets for larger aggregate analysis.',
|
|
31
32
|
tools: [
|
|
32
33
|
gbifMatchSpecies,
|
|
34
|
+
gbifBulkMatchSpecies,
|
|
33
35
|
gbifGetSpecies,
|
|
34
36
|
gbifSearchSpecies,
|
|
35
37
|
gbifGetSpeciesClassification,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,YAAY;AACZ,OAAO,EAAE,mBAAmB,EAAE,MAAM,6DAA6D,CAAC;AAClG,OAAO,EAAE,mBAAmB,EAAE,MAAM,6DAA6D,CAAC;AAClG,OAAO,EAAE,oBAAoB,EAAE,MAAM,+DAA+D,CAAC;AACrG,OAAO,EAAE,cAAc,EAAE,MAAM,yDAAyD,CAAC;AACzF,OAAO,EAAE,iBAAiB,EAAE,MAAM,4DAA4D,CAAC;AAC/F,OAAO,EAAE,cAAc,EAAE,MAAM,yDAAyD,CAAC;AACzF,OAAO,EAAE,sBAAsB,EAAE,MAAM,kEAAkE,CAAC;AAC1G,OAAO,EAAE,4BAA4B,EAAE,MAAM,wEAAwE,CAAC;AACtH,iBAAiB;AACjB,OAAO,EAAE,gBAAgB,EAAE,MAAM,2DAA2D,CAAC;AAC7F,OAAO,EAAE,oBAAoB,EAAE,MAAM,+DAA+D,CAAC;AACrG,8BAA8B;AAC9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,6DAA6D,CAAC;AACjG,mBAAmB;AACnB,OAAO,EAAE,qBAAqB,EAAE,MAAM,gEAAgE,CAAC;AACvG,OAAO,EAAE,oBAAoB,EAAE,MAAM,+DAA+D,CAAC;AACrG,OAAO,EAAE,iBAAiB,EAAE,MAAM,4DAA4D,CAAC;AAC/F,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAElE,MAAM,SAAS,CAAC;IACd,IAAI,EAAE,8BAA8B;IACpC,KAAK,EAAE,8BAA8B;IACrC,YAAY,EACV,siBAAsiB;IACxiB,KAAK,EAAE;QACL,gBAAgB;QAChB,cAAc;QACd,iBAAiB;QACjB,4BAA4B;QAC5B,sBAAsB;QACtB,qBAAqB;QACrB,oBAAoB;QACpB,iBAAiB;QACjB,oBAAoB;QACpB,kBAAkB;QAClB,cAAc;QACd,oBAAoB;KACrB;IACD,SAAS,EAAE,CAAC,mBAAmB,EAAE,mBAAmB,CAAC;IACrD,OAAO,EAAE,EAAE;IACX,6EAA6E;IAC7E,OAAO,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE;IAC/B,KAAK,CAAC,IAAI;QACR,MAAM,GAAG,GAAG,eAAe,EAAE,CAAC;QAC9B,eAAe,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE;YACzC,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,SAAS,EAAE,GAAG,CAAC,gBAAgB;SAChC,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,YAAY;AACZ,OAAO,EAAE,mBAAmB,EAAE,MAAM,6DAA6D,CAAC;AAClG,OAAO,EAAE,mBAAmB,EAAE,MAAM,6DAA6D,CAAC;AAClG,OAAO,EAAE,oBAAoB,EAAE,MAAM,gEAAgE,CAAC;AACtG,OAAO,EAAE,oBAAoB,EAAE,MAAM,+DAA+D,CAAC;AACrG,OAAO,EAAE,cAAc,EAAE,MAAM,yDAAyD,CAAC;AACzF,OAAO,EAAE,iBAAiB,EAAE,MAAM,4DAA4D,CAAC;AAC/F,OAAO,EAAE,cAAc,EAAE,MAAM,yDAAyD,CAAC;AACzF,OAAO,EAAE,sBAAsB,EAAE,MAAM,kEAAkE,CAAC;AAC1G,OAAO,EAAE,4BAA4B,EAAE,MAAM,wEAAwE,CAAC;AACtH,iBAAiB;AACjB,OAAO,EAAE,gBAAgB,EAAE,MAAM,2DAA2D,CAAC;AAC7F,OAAO,EAAE,oBAAoB,EAAE,MAAM,+DAA+D,CAAC;AACrG,8BAA8B;AAC9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,6DAA6D,CAAC;AACjG,mBAAmB;AACnB,OAAO,EAAE,qBAAqB,EAAE,MAAM,gEAAgE,CAAC;AACvG,OAAO,EAAE,oBAAoB,EAAE,MAAM,+DAA+D,CAAC;AACrG,OAAO,EAAE,iBAAiB,EAAE,MAAM,4DAA4D,CAAC;AAC/F,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAElE,MAAM,SAAS,CAAC;IACd,IAAI,EAAE,8BAA8B;IACpC,KAAK,EAAE,8BAA8B;IACrC,YAAY,EACV,siBAAsiB;IACxiB,KAAK,EAAE;QACL,gBAAgB;QAChB,oBAAoB;QACpB,cAAc;QACd,iBAAiB;QACjB,4BAA4B;QAC5B,sBAAsB;QACtB,qBAAqB;QACrB,oBAAoB;QACpB,iBAAiB;QACjB,oBAAoB;QACpB,kBAAkB;QAClB,cAAc;QACd,oBAAoB;KACrB;IACD,SAAS,EAAE,CAAC,mBAAmB,EAAE,mBAAmB,CAAC;IACrD,OAAO,EAAE,EAAE;IACX,6EAA6E;IAC7E,OAAO,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE;IAC/B,KAAK,CAAC,IAAI;QACR,MAAM,GAAG,GAAG,eAAe,EAAE,CAAC;QAC9B,eAAe,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE;YACzC,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,SAAS,EAAE,GAAG,CAAC,gBAAgB;SAChC,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -17,6 +17,22 @@ export declare const gbifDatasetResource: import("@cyanheads/mcp-ts-core").Resou
|
|
|
17
17
|
publishingCountry: z.ZodOptional<z.ZodString>;
|
|
18
18
|
recordCount: z.ZodOptional<z.ZodNumber>;
|
|
19
19
|
numConstituents: z.ZodOptional<z.ZodNumber>;
|
|
20
|
+
contacts: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
21
|
+
type: z.ZodOptional<z.ZodString>;
|
|
22
|
+
firstName: z.ZodOptional<z.ZodString>;
|
|
23
|
+
lastName: z.ZodOptional<z.ZodString>;
|
|
24
|
+
organization: z.ZodOptional<z.ZodString>;
|
|
25
|
+
email: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
26
|
+
}, z.core.$strip>>>;
|
|
27
|
+
contactsTotal: z.ZodOptional<z.ZodNumber>;
|
|
28
|
+
contactsReturned: z.ZodOptional<z.ZodNumber>;
|
|
29
|
+
temporalCoverages: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
30
|
+
start: z.ZodOptional<z.ZodString>;
|
|
31
|
+
end: z.ZodOptional<z.ZodString>;
|
|
32
|
+
}, z.core.$strip>>>;
|
|
33
|
+
geographicCoverages: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
34
|
+
description: z.ZodOptional<z.ZodString>;
|
|
35
|
+
}, z.core.$strip>>>;
|
|
20
36
|
}, z.core.$strip>, readonly [{
|
|
21
37
|
readonly reason: "not_found";
|
|
22
38
|
readonly code: JsonRpcErrorCode.NotFound;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gbif-dataset.resource.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/gbif-dataset.resource.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAY,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAY,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"gbif-dataset.resource.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/gbif-dataset.resource.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAY,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAY,MAAM,+BAA+B,CAAC;AAgB3E,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkI9B,CAAC"}
|
|
@@ -4,8 +4,13 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { resource, z } from '@cyanheads/mcp-ts-core';
|
|
6
6
|
import { JsonRpcErrorCode, McpError } from '@cyanheads/mcp-ts-core/errors';
|
|
7
|
-
import { stripHtml } from '../../../mcp-server/tools/utils.js';
|
|
7
|
+
import { compactGeographicCoverages, compactTemporalCoverages, projectContacts, stripHtml, } from '../../../mcp-server/tools/utils.js';
|
|
8
8
|
import { getGbifService } from '../../../services/gbif/gbif-service.js';
|
|
9
|
+
/**
|
|
10
|
+
* Fixed contact cap for the resource. The resource has no contactLimit input (unlike
|
|
11
|
+
* gbif_get_dataset), so it applies a constant cap while still reporting the full count.
|
|
12
|
+
*/
|
|
13
|
+
const CONTACT_CAP = 10;
|
|
9
14
|
export const gbifDatasetResource = resource('gbif://dataset/{datasetKey}', {
|
|
10
15
|
name: 'gbif-dataset',
|
|
11
16
|
title: 'GBIF Dataset',
|
|
@@ -27,6 +32,58 @@ export const gbifDatasetResource = resource('gbif://dataset/{datasetKey}', {
|
|
|
27
32
|
publishingCountry: z.string().optional().describe('Publishing organization country.'),
|
|
28
33
|
recordCount: z.number().optional().describe('Number of records. May be absent.'),
|
|
29
34
|
numConstituents: z.number().optional().describe('Number of sub-datasets. May be absent.'),
|
|
35
|
+
contacts: z
|
|
36
|
+
.array(z
|
|
37
|
+
.object({
|
|
38
|
+
type: z
|
|
39
|
+
.string()
|
|
40
|
+
.optional()
|
|
41
|
+
.describe('Contact type (e.g., ADMINISTRATIVE_POINT_OF_CONTACT). May be absent.'),
|
|
42
|
+
firstName: z.string().optional().describe('First name. May be absent.'),
|
|
43
|
+
lastName: z.string().optional().describe('Last name. May be absent.'),
|
|
44
|
+
organization: z.string().optional().describe('Organization name. May be absent.'),
|
|
45
|
+
email: z
|
|
46
|
+
.array(z.string())
|
|
47
|
+
.optional()
|
|
48
|
+
.describe('Contact email addresses. May be absent.'),
|
|
49
|
+
})
|
|
50
|
+
.describe('A dataset contact with role, name, organization, and email.'))
|
|
51
|
+
.optional()
|
|
52
|
+
.describe('Dataset contacts, capped at 10. Absent when the dataset has no contacts.'),
|
|
53
|
+
contactsTotal: z
|
|
54
|
+
.number()
|
|
55
|
+
.optional()
|
|
56
|
+
.describe('Total contacts before the cap. Present when the dataset has any contacts.'),
|
|
57
|
+
contactsReturned: z
|
|
58
|
+
.number()
|
|
59
|
+
.optional()
|
|
60
|
+
.describe('Number of contacts included (≤ 10). Present when the dataset has any contacts.'),
|
|
61
|
+
temporalCoverages: z
|
|
62
|
+
.array(z
|
|
63
|
+
.object({
|
|
64
|
+
start: z
|
|
65
|
+
.string()
|
|
66
|
+
.optional()
|
|
67
|
+
.describe('Coverage start as an ISO 8601 date-time. May be absent.'),
|
|
68
|
+
end: z
|
|
69
|
+
.string()
|
|
70
|
+
.optional()
|
|
71
|
+
.describe('Coverage end as an ISO 8601 date-time. May be absent.'),
|
|
72
|
+
})
|
|
73
|
+
.describe('A temporal coverage range.'))
|
|
74
|
+
.optional()
|
|
75
|
+
.describe('Temporal coverage ranges declared by the dataset. May be absent.'),
|
|
76
|
+
geographicCoverages: z
|
|
77
|
+
.array(z
|
|
78
|
+
.object({
|
|
79
|
+
description: z
|
|
80
|
+
.string()
|
|
81
|
+
.optional()
|
|
82
|
+
.describe('Geographic coverage description (e.g. "Worldwide"). May be absent.'),
|
|
83
|
+
})
|
|
84
|
+
.describe('A geographic coverage entry.'))
|
|
85
|
+
.optional()
|
|
86
|
+
.describe('Geographic coverage descriptions declared by the dataset. May be absent.'),
|
|
30
87
|
}),
|
|
31
88
|
errors: [
|
|
32
89
|
{
|
|
@@ -68,6 +125,9 @@ export const gbifDatasetResource = resource('gbif://dataset/{datasetKey}', {
|
|
|
68
125
|
publishingCountry: raw.publishingCountry,
|
|
69
126
|
recordCount: raw.numRecords ?? raw.recordCount,
|
|
70
127
|
numConstituents: raw.numConstituents,
|
|
128
|
+
...projectContacts(raw.contacts, CONTACT_CAP),
|
|
129
|
+
temporalCoverages: compactTemporalCoverages(raw.temporalCoverages),
|
|
130
|
+
geographicCoverages: compactGeographicCoverages(raw.geographicCoverages),
|
|
71
131
|
};
|
|
72
132
|
},
|
|
73
133
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gbif-dataset.resource.js","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/gbif-dataset.resource.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,
|
|
1
|
+
{"version":3,"file":"gbif-dataset.resource.js","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/gbif-dataset.resource.ts"],"names":[],"mappings":"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"}
|
|
@@ -76,7 +76,7 @@ export const gbifSpeciesResource = resource('gbif://species/{taxonKey}', {
|
|
|
76
76
|
taxonomicStatus: raw.taxonomicStatus,
|
|
77
77
|
kingdom: raw.kingdom,
|
|
78
78
|
phylum: raw.phylum,
|
|
79
|
-
class: raw.
|
|
79
|
+
class: raw.class,
|
|
80
80
|
order: raw.order,
|
|
81
81
|
family: raw.family,
|
|
82
82
|
genus: raw.genus,
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Resolve many scientific names to GBIF backbone taxon keys in one call.
|
|
3
|
+
* @module mcp-server/tools/definitions/gbif-bulk-match-species
|
|
4
|
+
*/
|
|
5
|
+
import { z } from '@cyanheads/mcp-ts-core';
|
|
6
|
+
export declare const gbifBulkMatchSpecies: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
|
|
7
|
+
names: z.ZodArray<z.ZodString>;
|
|
8
|
+
strict: z.ZodDefault<z.ZodBoolean>;
|
|
9
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
10
|
+
results: z.ZodArray<z.ZodObject<{
|
|
11
|
+
name: z.ZodString;
|
|
12
|
+
taxonKey: z.ZodOptional<z.ZodNumber>;
|
|
13
|
+
scientificName: z.ZodOptional<z.ZodString>;
|
|
14
|
+
canonicalName: z.ZodOptional<z.ZodString>;
|
|
15
|
+
rank: z.ZodOptional<z.ZodString>;
|
|
16
|
+
status: z.ZodOptional<z.ZodString>;
|
|
17
|
+
confidence: z.ZodOptional<z.ZodNumber>;
|
|
18
|
+
matchType: z.ZodString;
|
|
19
|
+
error: z.ZodOptional<z.ZodString>;
|
|
20
|
+
}, z.core.$strip>>;
|
|
21
|
+
}, z.core.$strip>, undefined, undefined>;
|
|
22
|
+
//# sourceMappingURL=gbif-bulk-match-species.tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gbif-bulk-match-species.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/gbif-bulk-match-species.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAGjD,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;wCA+H/B,CAAC"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Resolve many scientific names to GBIF backbone taxon keys in one call.
|
|
3
|
+
* @module mcp-server/tools/definitions/gbif-bulk-match-species
|
|
4
|
+
*/
|
|
5
|
+
import { tool, z } from '@cyanheads/mcp-ts-core';
|
|
6
|
+
import { getGbifService } from '../../../services/gbif/gbif-service.js';
|
|
7
|
+
export const gbifBulkMatchSpecies = tool('gbif_bulk_match_species', {
|
|
8
|
+
title: 'Bulk Match Species Names',
|
|
9
|
+
description: 'Resolve up to 50 scientific names to GBIF backbone taxon keys in one call — the batch ' +
|
|
10
|
+
'counterpart to gbif_match_species for checklist, inventory, and species-list workflows that ' +
|
|
11
|
+
'would otherwise need one round trip per name. Each name is matched independently and results ' +
|
|
12
|
+
'are returned in input order, one entry per name. A name with no backbone match yields ' +
|
|
13
|
+
'matchType NONE (no taxonKey) instead of failing the batch; a per-name lookup failure yields ' +
|
|
14
|
+
'matchType ERROR with the reason, leaving the rest of the batch intact. Resolves synonyms to ' +
|
|
15
|
+
'the accepted backbone key. Common names are not supported — use gbif_search_species for ' +
|
|
16
|
+
'vernacular searches. Below confidence 80, review the match.',
|
|
17
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
|
|
18
|
+
input: z.object({
|
|
19
|
+
names: z
|
|
20
|
+
.array(z.string().min(1).describe('A scientific name to match, e.g. "Panthera leo".'))
|
|
21
|
+
.min(1)
|
|
22
|
+
.max(50)
|
|
23
|
+
.describe('Scientific names to match against the GBIF backbone. 1–50 per call, matched in parallel.'),
|
|
24
|
+
strict: z
|
|
25
|
+
.boolean()
|
|
26
|
+
.default(false)
|
|
27
|
+
.describe('When true, require an exact match for every name (no fuzzy matching). When false (default), GBIF applies fuzzy matching to tolerate minor misspellings.'),
|
|
28
|
+
}),
|
|
29
|
+
output: z.object({
|
|
30
|
+
results: z
|
|
31
|
+
.array(z
|
|
32
|
+
.object({
|
|
33
|
+
name: z.string().describe('The input name this entry corresponds to.'),
|
|
34
|
+
taxonKey: z
|
|
35
|
+
.number()
|
|
36
|
+
.optional()
|
|
37
|
+
.describe('Matched GBIF backbone taxon key — use in gbif_search_occurrences, gbif_count_occurrences, and gbif_occurrence_facets. Absent when matchType is NONE or ERROR.'),
|
|
38
|
+
scientificName: z
|
|
39
|
+
.string()
|
|
40
|
+
.optional()
|
|
41
|
+
.describe('Full matched scientific name with authorship. Absent when unmatched.'),
|
|
42
|
+
canonicalName: z
|
|
43
|
+
.string()
|
|
44
|
+
.optional()
|
|
45
|
+
.describe('Matched scientific name without authorship. Absent when unmatched.'),
|
|
46
|
+
rank: z.string().optional().describe('Taxonomic rank of the matched taxon.'),
|
|
47
|
+
status: z
|
|
48
|
+
.string()
|
|
49
|
+
.optional()
|
|
50
|
+
.describe('Taxonomic status: ACCEPTED, SYNONYM, or DOUBTFUL.'),
|
|
51
|
+
confidence: z
|
|
52
|
+
.number()
|
|
53
|
+
.optional()
|
|
54
|
+
.describe('Match confidence 0–100. Below 80 warrants review. Absent on ERROR.'),
|
|
55
|
+
matchType: z
|
|
56
|
+
.string()
|
|
57
|
+
.describe('EXACT, FUZZY, or HIGHERRANK for a match; NONE when GBIF found no usable match; ERROR when the lookup itself failed for this name (see error).'),
|
|
58
|
+
error: z
|
|
59
|
+
.string()
|
|
60
|
+
.optional()
|
|
61
|
+
.describe('Failure reason when matchType is ERROR. Absent otherwise.'),
|
|
62
|
+
})
|
|
63
|
+
.describe('Match outcome for one input name.'))
|
|
64
|
+
.describe('One result per input name, in input order.'),
|
|
65
|
+
}),
|
|
66
|
+
async handler(input, ctx) {
|
|
67
|
+
ctx.log.info('Bulk matching species names', {
|
|
68
|
+
count: input.names.length,
|
|
69
|
+
strict: input.strict,
|
|
70
|
+
});
|
|
71
|
+
const gbif = getGbifService();
|
|
72
|
+
// Per-name isolation: each lookup resolves to a result entry and never rejects, so a
|
|
73
|
+
// single unmatched name (NONE) or transient failure (ERROR) cannot sink the batch.
|
|
74
|
+
// Promise.all preserves input order. The in-loop try/catch is the deliberate batch-tool
|
|
75
|
+
// exception to "handlers throw" — per-item isolation is the point.
|
|
76
|
+
const results = await Promise.all(input.names.map(async (name) => {
|
|
77
|
+
try {
|
|
78
|
+
const raw = await gbif.matchSpecies({ name, strict: input.strict }, ctx);
|
|
79
|
+
if (raw.usageKey == null || raw.matchType == null || raw.matchType === 'NONE') {
|
|
80
|
+
return { name, matchType: 'NONE' };
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
name,
|
|
84
|
+
taxonKey: raw.usageKey,
|
|
85
|
+
scientificName: raw.scientificName ?? undefined,
|
|
86
|
+
canonicalName: raw.canonicalName ?? undefined,
|
|
87
|
+
rank: raw.rank ?? undefined,
|
|
88
|
+
status: raw.status ?? undefined,
|
|
89
|
+
confidence: raw.confidence ?? undefined,
|
|
90
|
+
matchType: raw.matchType,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
return {
|
|
95
|
+
name,
|
|
96
|
+
matchType: 'ERROR',
|
|
97
|
+
error: err instanceof Error ? err.message : String(err),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
}));
|
|
101
|
+
return { results };
|
|
102
|
+
},
|
|
103
|
+
format: (result) => {
|
|
104
|
+
const lines = [];
|
|
105
|
+
for (const r of result.results) {
|
|
106
|
+
lines.push(`## ${r.name}`);
|
|
107
|
+
if (r.canonicalName)
|
|
108
|
+
lines.push(`**Canonical name:** ${r.canonicalName}`);
|
|
109
|
+
if (r.scientificName)
|
|
110
|
+
lines.push(`**Scientific name:** ${r.scientificName}`);
|
|
111
|
+
if (r.taxonKey != null)
|
|
112
|
+
lines.push(`**Taxon key:** ${r.taxonKey}`);
|
|
113
|
+
if (r.rank)
|
|
114
|
+
lines.push(`**Rank:** ${r.rank}`);
|
|
115
|
+
if (r.status)
|
|
116
|
+
lines.push(`**Status:** ${r.status}`);
|
|
117
|
+
lines.push(`**Match type:** ${r.matchType}`);
|
|
118
|
+
if (r.confidence != null)
|
|
119
|
+
lines.push(`**Confidence:** ${r.confidence}/100`);
|
|
120
|
+
if (r.error)
|
|
121
|
+
lines.push(`**Error:** ${r.error}`);
|
|
122
|
+
}
|
|
123
|
+
return [{ type: 'text', text: lines.join('\n') }];
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
//# sourceMappingURL=gbif-bulk-match-species.tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gbif-bulk-match-species.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/gbif-bulk-match-species.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEjE,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,CAAC,yBAAyB,EAAE;IAClE,KAAK,EAAE,0BAA0B;IACjC,WAAW,EACT,wFAAwF;QACxF,8FAA8F;QAC9F,+FAA+F;QAC/F,wFAAwF;QACxF,8FAA8F;QAC9F,8FAA8F;QAC9F,0FAA0F;QAC1F,6DAA6D;IAC/D,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE;IAC/E,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,KAAK,EAAE,CAAC;aACL,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,kDAAkD,CAAC,CAAC;aACrF,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,EAAE,CAAC;aACP,QAAQ,CACP,0FAA0F,CAC3F;QACH,MAAM,EAAE,CAAC;aACN,OAAO,EAAE;aACT,OAAO,CAAC,KAAK,CAAC;aACd,QAAQ,CACP,yJAAyJ,CAC1J;KACJ,CAAC;IACF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,OAAO,EAAE,CAAC;aACP,KAAK,CACJ,CAAC;aACE,MAAM,CAAC;YACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2CAA2C,CAAC;YACtE,QAAQ,EAAE,CAAC;iBACR,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CACP,+JAA+J,CAChK;YACH,cAAc,EAAE,CAAC;iBACd,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,sEAAsE,CAAC;YACnF,aAAa,EAAE,CAAC;iBACb,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,oEAAoE,CAAC;YACjF,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sCAAsC,CAAC;YAC5E,MAAM,EAAE,CAAC;iBACN,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,mDAAmD,CAAC;YAChE,UAAU,EAAE,CAAC;iBACV,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,oEAAoE,CAAC;YACjF,SAAS,EAAE,CAAC;iBACT,MAAM,EAAE;iBACR,QAAQ,CACP,+IAA+I,CAChJ;YACH,KAAK,EAAE,CAAC;iBACL,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,2DAA2D,CAAC;SACzE,CAAC;aACD,QAAQ,CAAC,mCAAmC,CAAC,CACjD;aACA,QAAQ,CAAC,4CAA4C,CAAC;KAC1D,CAAC;IAEF,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG;QACtB,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,6BAA6B,EAAE;YAC1C,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM;YACzB,MAAM,EAAE,KAAK,CAAC,MAAM;SACrB,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;QAE9B,qFAAqF;QACrF,mFAAmF;QACnF,wFAAwF;QACxF,mEAAmE;QACnE,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;YAC7B,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,EAAE,GAAG,CAAC,CAAC;gBACzE,IAAI,GAAG,CAAC,QAAQ,IAAI,IAAI,IAAI,GAAG,CAAC,SAAS,IAAI,IAAI,IAAI,GAAG,CAAC,SAAS,KAAK,MAAM,EAAE,CAAC;oBAC9E,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;gBACrC,CAAC;gBACD,OAAO;oBACL,IAAI;oBACJ,QAAQ,EAAE,GAAG,CAAC,QAAQ;oBACtB,cAAc,EAAE,GAAG,CAAC,cAAc,IAAI,SAAS;oBAC/C,aAAa,EAAE,GAAG,CAAC,aAAa,IAAI,SAAS;oBAC7C,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,SAAS;oBAC3B,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,SAAS;oBAC/B,UAAU,EAAE,GAAG,CAAC,UAAU,IAAI,SAAS;oBACvC,SAAS,EAAE,GAAG,CAAC,SAAS;iBACzB,CAAC;YACJ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO;oBACL,IAAI;oBACJ,SAAS,EAAE,OAAO;oBAClB,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;iBACxD,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,CACH,CAAC;QAEF,OAAO,EAAE,OAAO,EAAE,CAAC;IACrB,CAAC;IAED,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE;QACjB,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YAC/B,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YAC3B,IAAI,CAAC,CAAC,aAAa;gBAAE,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC;YAC1E,IAAI,CAAC,CAAC,cAAc;gBAAE,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC;YAC7E,IAAI,CAAC,CAAC,QAAQ,IAAI,IAAI;gBAAE,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;YACnE,IAAI,CAAC,CAAC,IAAI;gBAAE,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YAC9C,IAAI,CAAC,CAAC,MAAM;gBAAE,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;YACpD,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;YAC7C,IAAI,CAAC,CAAC,UAAU,IAAI,IAAI;gBAAE,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,UAAU,MAAM,CAAC,CAAC;YAC5E,IAAI,CAAC,CAAC,KAAK;gBAAE,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QACnD,CAAC;QACD,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpD,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -27,6 +27,13 @@ export declare const gbifGetDataset: import("@cyanheads/mcp-ts-core").ToolDefini
|
|
|
27
27
|
}, z.core.$strip>>>;
|
|
28
28
|
contactsTotal: z.ZodOptional<z.ZodNumber>;
|
|
29
29
|
contactsReturned: z.ZodOptional<z.ZodNumber>;
|
|
30
|
+
temporalCoverages: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
31
|
+
start: z.ZodOptional<z.ZodString>;
|
|
32
|
+
end: z.ZodOptional<z.ZodString>;
|
|
33
|
+
}, z.core.$strip>>>;
|
|
34
|
+
geographicCoverages: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
35
|
+
description: z.ZodOptional<z.ZodString>;
|
|
36
|
+
}, z.core.$strip>>>;
|
|
30
37
|
}, z.core.$strip>, readonly [{
|
|
31
38
|
readonly reason: "not_found";
|
|
32
39
|
readonly code: JsonRpcErrorCode.NotFound;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gbif-get-dataset.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/gbif-get-dataset.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAY,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"gbif-get-dataset.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/gbif-get-dataset.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAY,MAAM,+BAA+B,CAAC;AAU3E,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA+LzB,CAAC"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { tool, z } from '@cyanheads/mcp-ts-core';
|
|
6
6
|
import { JsonRpcErrorCode, McpError } from '@cyanheads/mcp-ts-core/errors';
|
|
7
7
|
import { getGbifService } from '../../../services/gbif/gbif-service.js';
|
|
8
|
-
import { stripHtml } from '../utils.js';
|
|
8
|
+
import { compactGeographicCoverages, compactTemporalCoverages, projectContacts, stripHtml, } from '../utils.js';
|
|
9
9
|
export const gbifGetDataset = tool('gbif_get_dataset', {
|
|
10
10
|
title: 'Get Dataset',
|
|
11
11
|
description: 'Fetch full dataset metadata by UUID key — title, description, citation text, contacts, license, ' +
|
|
@@ -71,6 +71,32 @@ export const gbifGetDataset = tool('gbif_get_dataset', {
|
|
|
71
71
|
.number()
|
|
72
72
|
.optional()
|
|
73
73
|
.describe('Number of contacts included in this response (≤ contactLimit). Present when the dataset has any contacts.'),
|
|
74
|
+
temporalCoverages: z
|
|
75
|
+
.array(z
|
|
76
|
+
.object({
|
|
77
|
+
start: z
|
|
78
|
+
.string()
|
|
79
|
+
.optional()
|
|
80
|
+
.describe('Coverage start as an ISO 8601 date-time. May be absent.'),
|
|
81
|
+
end: z
|
|
82
|
+
.string()
|
|
83
|
+
.optional()
|
|
84
|
+
.describe('Coverage end as an ISO 8601 date-time. May be absent.'),
|
|
85
|
+
})
|
|
86
|
+
.describe('A temporal coverage range.'))
|
|
87
|
+
.optional()
|
|
88
|
+
.describe('Temporal coverage ranges declared by the dataset. May be absent.'),
|
|
89
|
+
geographicCoverages: z
|
|
90
|
+
.array(z
|
|
91
|
+
.object({
|
|
92
|
+
description: z
|
|
93
|
+
.string()
|
|
94
|
+
.optional()
|
|
95
|
+
.describe('Geographic coverage description (e.g. "Worldwide"). May be absent.'),
|
|
96
|
+
})
|
|
97
|
+
.describe('A geographic coverage entry.'))
|
|
98
|
+
.optional()
|
|
99
|
+
.describe('Geographic coverage descriptions declared by the dataset. May be absent.'),
|
|
74
100
|
}),
|
|
75
101
|
errors: [
|
|
76
102
|
{
|
|
@@ -99,15 +125,6 @@ export const gbifGetDataset = tool('gbif_get_dataset', {
|
|
|
99
125
|
...ctx.recoveryFor('not_found'),
|
|
100
126
|
});
|
|
101
127
|
}
|
|
102
|
-
const allContacts = raw.contacts ?? [];
|
|
103
|
-
const contactsTotal = allContacts.length;
|
|
104
|
-
const contacts = allContacts.slice(0, input.contactLimit).map((c) => ({
|
|
105
|
-
type: c.type,
|
|
106
|
-
firstName: c.firstName,
|
|
107
|
-
lastName: c.lastName,
|
|
108
|
-
organization: c.organization,
|
|
109
|
-
email: c.email?.length ? c.email : undefined,
|
|
110
|
-
}));
|
|
111
128
|
return {
|
|
112
129
|
key: raw.key,
|
|
113
130
|
title: raw.title,
|
|
@@ -119,10 +136,11 @@ export const gbifGetDataset = tool('gbif_get_dataset', {
|
|
|
119
136
|
publishingCountry: raw.publishingCountry,
|
|
120
137
|
recordCount: raw.numRecords ?? raw.recordCount,
|
|
121
138
|
numConstituents: raw.numConstituents,
|
|
122
|
-
|
|
123
|
-
//
|
|
124
|
-
|
|
125
|
-
|
|
139
|
+
// contactLimit: 0 suppresses contact detail while projectContacts still reports
|
|
140
|
+
// contactsTotal/contactsReturned, so callers learn the dataset has contacts.
|
|
141
|
+
...projectContacts(raw.contacts, input.contactLimit),
|
|
142
|
+
temporalCoverages: compactTemporalCoverages(raw.temporalCoverages),
|
|
143
|
+
geographicCoverages: compactGeographicCoverages(raw.geographicCoverages),
|
|
126
144
|
};
|
|
127
145
|
},
|
|
128
146
|
format: (result) => {
|
|
@@ -142,6 +160,15 @@ export const gbifGetDataset = tool('gbif_get_dataset', {
|
|
|
142
160
|
lines.push(`**Records:** ${result.recordCount.toLocaleString()}`);
|
|
143
161
|
if (result.numConstituents != null)
|
|
144
162
|
lines.push(`**Constituent datasets:** ${result.numConstituents}`);
|
|
163
|
+
if (result.temporalCoverages?.length) {
|
|
164
|
+
const ranges = result.temporalCoverages.map((t) => `${t.start ?? '?'} → ${t.end ?? '?'}`);
|
|
165
|
+
lines.push(`**Temporal coverage:** ${ranges.join('; ')}`);
|
|
166
|
+
}
|
|
167
|
+
if (result.geographicCoverages?.length) {
|
|
168
|
+
const descs = result.geographicCoverages.map((g) => g.description).filter(Boolean);
|
|
169
|
+
if (descs.length > 0)
|
|
170
|
+
lines.push(`**Geographic coverage:** ${descs.join('; ')}`);
|
|
171
|
+
}
|
|
145
172
|
if (result.citationText)
|
|
146
173
|
lines.push(`\n**Citation:**\n> ${result.citationText}`);
|
|
147
174
|
if (result.description)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gbif-get-dataset.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/gbif-get-dataset.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEjE,OAAO,
|
|
1
|
+
{"version":3,"file":"gbif-get-dataset.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/gbif-get-dataset.tool.ts"],"names":[],"mappings":"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"}
|