Analysts with an AI assistant, agent builders
MCP server
The Model Context Protocol server for AI assistants and agents: endpoint and transport, the auth header, every tool with its typed arguments, the tool-error shape, client configurations, the configuration checker and example prompts.
Last reviewed
MCP in one paragraph
The Model Context Protocol (MCP) is an open protocol that lets an AI assistant or agent call tools on a server over JSON-RPC. A client lists the server's tools (tools/list), each with a JSON schema for its arguments, and calls one (tools/call); the result comes back as structured content the assistant can reason over. Coastal Intelligence exposes its agency tools as one MCP server, so an analyst can ask questions in plain language and the assistant fetches scoped, licensed data with its sources attached.
Endpoint and transport
- Endpoint:
https://coastal-intelligence.triskelionaisystems.com/api/mcp(this deployment's API origin plus/mcp). - Transport: MCP streamable HTTP, stateless, JSON responses. Every
POSTis self-contained; there is no session to keep, so a client can retry freely and a load balancer needs no affinity. - Server name
coastal-intelligence-agency, version1.0.0. The server's instructions to the assistant: "Coastal Intelligence agency data access. Read-only tools over the shared layers of the bays in your approved access request: bays and the public site register, daily signals, dated bay events, model skill against ground-truth stations, model, satellite and station time series, the bloom back-test and the dataset registry. Every row names its source, product, scale, lead_hours and licence; cite the attribution lines when you publish. Operator records are never available. Every call is logged." - Read-only: every tool is annotated read-only, non-destructive and idempotent; the server has no resources or prompts.
Authentication
Send the agency key as an HTTP header on every request: Authorization: Bearer <key> (or X-API-Key: <key>). The key is checked before the protocol starts: a missing, unknown or revoked key is answered 401 with WWW-Authenticate: Bearer, and the rate limit (60 calls per minute per key by default, shared with REST) is answered 429 with Retry-After. Both are plain HTTP responses with a JSON detail, not tool errors. See Authentication and keys.
The tools
9 tools, one per shared layer. The table lists every argument; ? marks an optional one. A date is a UTC day as YYYY-MM-DD. Each result is the envelope described on the REST API page, returned as structured content and as JSON text.
| Tool | Arguments | Product needed | REST route |
|---|---|---|---|
| list_bays | none | none | /agency/bays |
| list_sites | bay | none | /agency/sites |
| get_signals | target, kind?, from_date?, to_date? | signals | /agency/signals |
| get_events | bay, from_date?, to_date? | events | /agency/events |
| get_skill | site, variable? | skill | /agency/skill |
| get_timeseries | site, variable, product, from_date?, to_date? | the dataset key given as product | /agency/timeseries |
| get_backtest | bay | backtest | /agency/backtest |
| get_risk_index | bay, from_date?, to_date? | risk_index | /agency/risk-index |
| describe_datasets | none | none | /agency/datasets |
list_bays: List bays
The bays this key may read, with name, country, region and bounding box [lon_min, lat_min, lon_max, lat_max].
Product needed: none. REST: GET /agency/bays.
list_sites: List sites of a bay
Sites and ground-truth stations of one bay, public register fields only: id, name, type, position (lon, lat) and licence reference. `site_level` says whether this key may ask for that site's own series.
Product needed: none. REST: GET /agency/sites.
| Argument | Type | Required | Meaning |
|---|---|---|---|
bay | string | yes | A bay id inside the key's approved bays (list_bays). |
get_signals: Get signals
Daily signals (thermal, bloom, runoff, growth) for a bay or a site between 'from_date' and 'to_date' (UTC days). A bay id gives the bay aggregate per kind and day (sites counted per label, max and mean value); a site id gives that site's series (needs site-level access). Labels: low, watch, stress, critical; growth carries the season stage.
Product needed: signals. REST: GET /agency/signals.
| Argument | Type | Required | Meaning |
|---|---|---|---|
target | string | yes | A bay id (the bay aggregate per kind and day) or a site id (that site's series; needs site-level access). |
kind | string | no | One signal kind: thermal, bloom, runoff or growth. Omitted: all four. |
from_date (REST: from) | date | no | First UTC day, YYYY-MM-DD, inside the approved date range. Omitted: 30 days before the end of the window. |
to_date (REST: to) | date | no | Last UTC day (inclusive), YYYY-MM-DD, inside the approved date range. Omitted: today plus the 10-day forecast horizon. |
get_events: Get bay events
Dated bay events between 'from_date' and 'to_date' (UTC days, overlapping the window): HAB closures and phytoplankton exceedances from the Marine Institute bulletin, marine heatwaves and storms (wave or gale episodes at the bay reference cell).
Product needed: events. REST: GET /agency/events.
| Argument | Type | Required | Meaning |
|---|---|---|---|
bay | string | yes | A bay id inside the key's approved bays (list_bays). |
from_date (REST: from) | date | no | First UTC day, YYYY-MM-DD, inside the approved date range. Omitted: 30 days before the end of the window. |
to_date (REST: to) | date | no | Last UTC day (inclusive), YYYY-MM-DD, inside the approved date range. Omitted: today plus the 10-day forecast horizon. |
get_skill: Get model skill
How well the regional model matches ground truth at a site: bias (truth minus model), RMSE and MAE of daily means over 7, 30 and 90 days, against the bay's buoy. 'variable' is sst or hs.
Product needed: skill. REST: GET /agency/skill.
| Argument | Type | Required | Meaning |
|---|---|---|---|
site | string | yes | A site or station id of an approved bay (list_sites). With bay aggregation only ground-truth stations are allowed. |
variable | string | no (default sst) | The variable to read: for get_skill sst or hs; for get_timeseries a variable of the dataset (describe_datasets). |
get_timeseries: Get a time series
One variable of one shared dataset ('product', a dataset key of the registry such as phy_daily, sst_l4, buoys; see describe_datasets) at a site or station between 'from_date' and 'to_date' (UTC days), grouped into series by source, product and depth. Points carry lead_hours: null observation, 0 analysis, above 0 forecast. Operator records are never returned.
Product needed: the dataset key given as product. REST: GET /agency/timeseries.
| Argument | Type | Required | Meaning |
|---|---|---|---|
site | string | yes | A site or station id of an approved bay (list_sites). With bay aggregation only ground-truth stations are allowed. |
variable | string | yes | The variable to read: for get_skill sst or hs; for get_timeseries a variable of the dataset (describe_datasets). |
product | string | yes | The dataset key to read (describe_datasets), for example phy_daily, sst_l4, buoys. The key must be approved for it. |
from_date (REST: from) | date | no | First UTC day, YYYY-MM-DD, inside the approved date range. Omitted: 30 days before the end of the window. |
to_date (REST: to) | date | no | Last UTC day (inclusive), YYYY-MM-DD, inside the approved date range. Omitted: today plus the 10-day forecast horizon. |
get_backtest: Get the bloom back-test
The back-test of the bay's bloom signal against Marine Institute HAB bulletin events: hits, misses, lead time and false-alarm rate per alert level, with the dated events inside the approved range.
Product needed: backtest. REST: GET /agency/backtest.
| Argument | Type | Required | Meaning |
|---|---|---|---|
bay | string | yes | A bay id inside the key's approved bays (list_bays). |
get_risk_index: Get the bay risk index
The bay risk index between 'from_date' and 'to_date' (UTC days): one row per day and peril (thermal, bloom, runoff, storm), index 0-100 aggregated across the bay's sites (half the worst site, half the mean), with its level (low, watch, stress, critical), the number of sites and the lowest confidence. A day and peril with fewer than three contributing sites is suppressed (index null). Method: the 'Insurer data sharing' help article, /help/insurer-data-sharing.
Product needed: risk_index. REST: GET /agency/risk-index.
| Argument | Type | Required | Meaning |
|---|---|---|---|
bay | string | yes | A bay id inside the key's approved bays (list_bays). |
from_date (REST: from) | date | no | First UTC day, YYYY-MM-DD, inside the approved date range. Omitted: 30 days before the end of the window. |
to_date (REST: to) | date | no | Last UTC day (inclusive), YYYY-MM-DD, inside the approved date range. Omitted: today plus the 10-day forecast horizon. |
describe_datasets: Describe datasets
Every shared dataset behind the data (provider ids, variables, scale, frequency), with its licence and the attribution line it requires, and the products this key may read.
Product needed: none. REST: GET /agency/datasets.
Argument naming and dates
- Over MCP the date arguments are
from_dateandto_date(the REST query names arefromandto). The tool schemas sayadditionalProperties: false: a call with an argument the tool does not declare, such asfrom, is refused as a tool error instead of quietly using the default window. - Dates are UTC days,
YYYY-MM-DD, inside the key's approved range. Omitted, the window is the last 30 days up to today plus the 10-day forecast horizon; at most 366 days and 20,000 rows per call.
The tool-error shape
A refusal inside the protocol (outside the scope, unknown bay or site, bad argument, too large a window) is not an HTTP error: the call succeeds at the transport level and the result carries isError: true with the reason as a text content block, so the assistant can read it and adjust the call. Shape, with placeholders:
{
"jsonrpc": "2.0",
"id": "<request id>",
"result": {
"isError": true,
"content": [
{
"type": "text",
"text": "<the reason, for example: bay '<bay id>' is outside this key's approved scope (...)>"
}
]
}
}The reasons are the same texts REST returns in detail for 403, 404 and 422. Only the key check (401) and the rate limit (429) are HTTP responses.
Client configurations
Any client that reads an mcpServers file with type http
Keep the key in an environment variable (AGENCY_KEY), not in the file:
{
"mcpServers": {
"coastal-intelligence": {
"type": "http",
"url": "https://coastal-intelligence.triskelionaisystems.com/api/mcp",
"headers": {
"Authorization": "Bearer ${AGENCY_KEY}"
}
}
}
}Claude Code
Save the file above as .mcp.json in your project, or add the server from the command line:
claude mcp add --transport http coastal-intelligence https://coastal-intelligence.triskelionaisystems.com/api/mcp \ --header "Authorization: Bearer $AGENCY_KEY"
Claude Desktop and other clients that only start local commands
Bridge to the HTTP endpoint with mcp-remote (needs Node.js):
{
"mcpServers": {
"coastal-intelligence": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://coastal-intelligence.triskelionaisystems.com/api/mcp",
"--header",
"Authorization:Bearer ${AGENCY_KEY}"
],
"env": {
"AGENCY_KEY": "<your key>"
}
}
}
}Checking a configuration
The backend ships a checker, the Python module app.agency.client_check (it needs the official MCP Python SDK). It reads an mcpServers file, expands ${VAR} from the environment, connects with the SDK client, lists the tools and calls one; it prints the tool list and the call's row count and licences, never the key, and exits non-zero on any error:
AGENCY_KEY=<your key> python -m app.agency.client_check \
--config agency.mcp.json --call get_events \
--args '{"bay": "<bay id>", "from_date": "<YYYY-MM-DD>", "to_date": "<YYYY-MM-DD>"}'Without --call it only lists the tools. The type: http configuration above was tested this way against the API.
Three example prompts
Once the server is connected, a user can type requests like these to their assistant:
- "List the bays my key can read, then give me the bay-level bloom signal for <bay> over the last 30 days and tell me which days were at stress or above."
- "Which HAB closures, heatwaves and storm events did <bay> have between <from> and <to>? Give the dates and the source of each, with the attribution lines I must cite."
- "Show the daily risk index for <bay> in <month> as a table per peril, note any suppressed days, and summarise the model skill for sea temperature at the bay's buoy."
Tool descriptions carry the AI disclosure, and every result names its sources and the attribution lines to cite. Signals are favourable, marginal or unfavourable style indicators, not food-safety advice. The REST face of the same tools is at https://coastal-intelligence.triskelionaisystems.com/api/agency/.
Related
Authentication and keys
The request and approval flow, the Authorization and X-API-Key headers, what a key's scope means, revocation, the exact meaning of 401, 403, 404, 422 and 429, and what the access log records.
Last reviewed 1 Nov 2026Integrators, data engineersREST API
The base URL of this deployment, every partner endpoint with its parameters, the date rules, the response envelope field by field, examples in curl, Python and JavaScript, and the live OpenAPI reference.
Last reviewed 1 Nov 2026Insurers, reinsurers, brokersRisk index and signed exports
The insurer product: the 0 to 100 index per peril, the bay aggregation and suppression rules, the CSV export, verifying its Ed25519 signature with a complete Python example, and how to cite the licences.
Last reviewed 1 Nov 2026