Koskamo

ICOS Carbon Portal MCP

An official Model Context Protocol server operated by ICOS ERIC that provides AI assistants with access to greenhouse-gas observations across atmosphere, ocean, and ecosystem domains. It allows users to discover datasets, compute statistics on the server, fetch data, and automatically retrieve citations, licenses, and DOIs via RO-Crate data passports for every answer.

Endpoint and access

No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.

ICOS Carbon Portal MCP logo, by ICOS ERICVendor evidenceStreamable HTTPNo sign-inEndpoint checked 2026-11-01Operated by ICOS ERIC
MCP endpoint (Streamable HTTP)
https://mcp.icos-cp.eu/mcp
Vendor documentation

What you can do with it

  • List ICOS datasets with domain and coverage details
  • Compute aggregate statistics like mean or sum on the server
  • Fetch observations filtered by station, time, or region
  • Retrieve citation text, license, and DOI for data sources

Source and maintenance

Vendor evidenceRegistry 0.2.0

Protocol and capabilities

Server
icos 0.2.0
MCP protocol
2025-06-18
Tools
8 advertised
Resources
3 advertised
Resource templates
2 advertised
Prompts
3 advertised
Server-advertised capabilities
{
  "tools": {
    "listChanged": false
  },
  "prompts": {
    "listChanged": false
  },
  "resources": {
    "subscribe": false,
    "listChanged": false
  }
}

Server-provided instructions

Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.

ICOS (Integrated Carbon Observation System) observations: atmospheric greenhouse gases (CO2, CH4, N2O, CO, radon, 14CO2) and meteorology at ICOS stations, surface-ocean CO2 (SOCAT and ICOS ocean), and ecosystem fluxes (FLUXNET and near-real-time ETC data). How to use these tools: 1. search_variables to find the variable id -- ids look like icos-obspack.co2.co2. Prefer the primary measurement over its companions (std_dev, nvalue, flags). find_stations lists the stations carrying a variable, near a place, in a box or by name -- use it to turn "Hyltemossa" into HTM150. 2. estimate before get_data: it says how many rows a selection has. 3. For a mean, total, range or count, call aggregate -- it computes over the WHOLE selection on the server, by station, day, month or year. Never average rows from get_data yourself: get_data returns at most a few thousand rows, for looking at; for anything larger give the user its download_url. 4. The ecosystem fluxes NEE, GPP and RECO are served by /query as their PRESCRIBED reference slices -- NEE_VUT_REF (variable u* threshold, reference variant), GPP_NT_VUT_REF and RECO_NT_VUT_REF (night-time partitioning). Use those. The other variants (CUT, the u* percentiles, daytime partitioning) live in the zarr cubes NEE, GPP and RECO: search_variables lists them with access "zarr", and describe_variable gives the xarray line that reads any slice. Their UNITS differ by store: icos-fluxnet's daily/weekly/monthly/yearly NEE is gC m-2 d-1 (yearly gC m-2 y-1), the near-real-time icos-eco-nrt NEE is umol m-2 s-1 per half-hour -- say which when comparing. 5. The released stores (icos-fluxnet, icos-obspack releases) end months before today. For the latest days or weeks -- "this week", "latest", "recent" -- use the near-real-time data: icos-eco-nrt for ecosystem fluxes and meteorology, the NRT tail of icos-obspack for gases. 6. Two ocean stores, easily confused: icos-socat is the ICOS OCEAN NETWORK's own release (ICOS ships and stations, ICOS Ocean Level 2, its own DOI) -- "ICOS ocean data" means this one; socat is the GLOBAL SOCAT synthesis (every contributor worldwide, SOCAT v2026, the SOCAT DOI) -- "SOCAT" means this one, and socat-gridded is its monthly 1x1 degree grid. Cite the store you actually used. 7. For a gridded product, estimate's rows ARE the grid cells with data: that number answers "how many cells", do not count them by hand. 8. Always cite: every data answer carries the citation, licence (CC BY 4.0) and DOI. Pass them on to the user. Station ids are CASE-SENSITIVE: atmosphere stations are a trigram plus the sampling height (HTM150 = Hyltemossa, 150 m), FLUXNET sites are mixed-case site codes (SE-Htm).

Tools

8 advertised

list_datasets
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

List the ICOS datasets: one per data store, with domain (atmosphere, ocean, ecosystem), time and space coverage, licence and DOI.

list_datasets input schema
{
  "type": "object",
  "title": "list_datasetsArguments",
  "properties": {}
}
list_datasets output schema
{
  "type": "object",
  "$defs": {
    "Dataset": {
      "type": "object",
      "title": "Dataset",
      "required": [
        "store",
        "title",
        "domain",
        "n_variables",
        "agent_guide_url",
        "croissant_url"
      ],
      "properties": {
        "doi": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Doi",
          "default": null
        },
        "store": {
          "type": "string",
          "title": "Store"
        },
        "title": {
          "type": "string",
          "title": "Title"
        },
        "domain": {
          "type": "string",
          "title": "Domain"
        },
        "lat_max": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "title": "Lat Max",
          "default": null
        },
        "lat_min": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "title": "Lat Min",
          "default": null
        },
        "license": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "License",
          "default": null
        },
        "lon_max": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "title": "Lon Max",
          "default": null
        },
        "lon_min": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "title": "Lon Min",
          "default": null
        },
        "summary": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Summary",
          "default": null
        },
        "n_variables": {
          "type": "integer",
          "title": "N Variables",
          "description": "variables queryable through estimate and get_data; 0 means the store is read with xarray only (see its agent guide)"
        },
        "croissant_url": {
          "type": "string",
          "title": "Croissant Url"
        },
        "agent_guide_url": {
          "type": "string",
          "title": "Agent Guide Url"
        },
        "time_coverage_end": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Time Coverage End",
          "default": null
        },
        "time_coverage_start": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Time Coverage Start",
          "default": null
        }
      }
    }
  },
  "title": "Datasets",
  "required": [
    "datasets"
  ],
  "properties": {
    "datasets": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/Dataset"
      },
      "title": "Datasets"
    }
  }
}
list_datasets annotations
{
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
search_variables
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Find variable ids in the ICOS catalogue by name, quantity or unit. The ids are what estimate and get_data take. Primary measurements come before their companions (standard deviation, value counts, flags).

search_variables input schema
{
  "type": "object",
  "title": "search_variablesArguments",
  "required": [
    "text"
  ],
  "properties": {
    "text": {
      "type": "string",
      "title": "Text",
      "description": "what to look for: a gas, a quantity or a name, e.g. 'co2', 'methane', 'net ecosystem exchange', 'fCO2'"
    },
    "limit": {
      "type": "integer",
      "title": "Limit",
      "default": 15,
      "maximum": 50,
      "minimum": 1
    },
    "store": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Store",
      "default": null,
      "description": "limit to one store, e.g. icos-obspack.zarr"
    },
    "domain": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Domain",
      "default": null,
      "description": "atmosphere, ocean or ecosystem"
    }
  }
}
search_variables output schema
{
  "type": "object",
  "$defs": {
    "Variable": {
      "type": "object",
      "title": "Variable",
      "required": [
        "id",
        "name",
        "store",
        "query_kind"
      ],
      "properties": {
        "id": {
          "type": "string",
          "title": "Id"
        },
        "axes": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            },
            {
              "type": "null"
            }
          ],
          "title": "Axes",
          "default": null,
          "description": "zarr variables: each extra axis and its labels"
        },
        "name": {
          "type": "string",
          "title": "Name"
        },
        "unit": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Unit",
          "default": null
        },
        "store": {
          "type": "string",
          "title": "Store"
        },
        "access": {
          "enum": [
            "query",
            "zarr"
          ],
          "type": "string",
          "title": "Access",
          "default": "query",
          "description": "query: estimate/get_data/aggregate serve it; zarr: a multi-dimensional variable (e.g. the ONEFlux NEE cube) read with xarray -- see zarr_recipe, and `prescribed` for its /query slice"
        },
        "domain": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Domain",
          "default": null
        },
        "long_name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Long Name",
          "default": null
        },
        "prescribed": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Prescribed",
          "default": null,
          "description": "zarr variables: the id of the preferred slice /query serves"
        },
        "query_kind": {
          "type": "string",
          "title": "Query Kind",
          "description": "station_time (series at stations), obs_table (ship/cruise observations) or grid (gridded product)"
        },
        "zarr_recipe": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Zarr Recipe",
          "default": null
        },
        "quality_flag": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Quality Flag",
          "default": null
        },
        "vocabulary_uri": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Vocabulary Uri",
          "default": null
        }
      }
    }
  },
  "title": "Variables",
  "required": [
    "variables",
    "n_matches"
  ],
  "properties": {
    "n_matches": {
      "type": "integer",
      "title": "N Matches"
    },
    "variables": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/Variable"
      },
      "title": "Variables"
    }
  }
}
search_variables annotations
{
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
describe_variable
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

One variable in full: names, unit, which dataset, its coverage, how its quality flag is read, licence and DOI. For a multi-dimensional variable read through zarr (access 'zarr'), its axes with their labels, the slice /query serves (prescribed) and an xarray line for any other slice.

describe_variable input schema
{
  "type": "object",
  "title": "describe_variableArguments",
  "required": [
    "id"
  ],
  "properties": {
    "id": {
      "type": "string",
      "title": "Id",
      "description": "a variable id from search_variables"
    }
  }
}
describe_variable output schema
{
  "type": "object",
  "title": "VariableDetail",
  "required": [
    "id",
    "name",
    "store",
    "query_kind",
    "dataset_title"
  ],
  "properties": {
    "id": {
      "type": "string",
      "title": "Id"
    },
    "doi": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Doi",
      "default": null
    },
    "axes": {
      "anyOf": [
        {
          "type": "object",
          "additionalProperties": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        {
          "type": "null"
        }
      ],
      "title": "Axes",
      "default": null,
      "description": "zarr variables: each extra axis and its labels"
    },
    "name": {
      "type": "string",
      "title": "Name"
    },
    "unit": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Unit",
      "default": null
    },
    "store": {
      "type": "string",
      "title": "Store"
    },
    "access": {
      "enum": [
        "query",
        "zarr"
      ],
      "type": "string",
      "title": "Access",
      "default": "query",
      "description": "query: estimate/get_data/aggregate serve it; zarr: a multi-dimensional variable (e.g. the ONEFlux NEE cube) read with xarray -- see zarr_recipe, and `prescribed` for its /query slice"
    },
    "domain": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Domain",
      "default": null
    },
    "license": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "License",
      "default": null
    },
    "variants": {
      "anyOf": [
        {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        {
          "type": "null"
        }
      ],
      "title": "Variants",
      "default": null,
      "description": "the multi-dimensional variables this one is the PRESCRIBED slice of; their other slices are read through zarr (describe_variable on one gives the recipe)"
    },
    "long_name": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Long Name",
      "default": null
    },
    "prescribed": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Prescribed",
      "default": null,
      "description": "zarr variables: the id of the preferred slice /query serves"
    },
    "query_kind": {
      "type": "string",
      "title": "Query Kind",
      "description": "station_time (series at stations), obs_table (ship/cruise observations) or grid (gridded product)"
    },
    "zarr_recipe": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Zarr Recipe",
      "default": null
    },
    "quality_flag": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Quality Flag",
      "default": null
    },
    "dataset_title": {
      "type": "string",
      "title": "Dataset Title"
    },
    "vocabulary_uri": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Vocabulary Uri",
      "default": null
    },
    "quality_control": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Quality Control",
      "default": null,
      "description": "how the store's QC flag is read; apply_qc=true applies the recommended rule"
    },
    "time_coverage_end": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Time Coverage End",
      "default": null
    },
    "time_coverage_start": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Time Coverage Start",
      "default": null
    }
  }
}
describe_variable annotations
{
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
estimate
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

How big a selection is -- rows, stations, time span -- without fetching it. Call this before get_data.

estimate input schema
{
  "type": "object",
  "title": "estimateArguments",
  "required": [
    "id"
  ],
  "properties": {
    "id": {
      "type": "string",
      "title": "Id",
      "description": "a variable id from search_variables"
    },
    "end": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "End",
      "default": null,
      "description": "ISO date or datetime, EXCLUSIVE"
    },
    "start": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Start",
      "default": null,
      "description": "ISO date or datetime, inclusive (2025-01-01)"
    },
    "cruise": {
      "anyOf": [
        {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Cruise",
      "default": null,
      "description": "cruise expocodes, a list or a string; ocean observation tables only"
    },
    "lat_max": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 90,
          "minimum": -90
        },
        {
          "type": "null"
        }
      ],
      "title": "Lat Max",
      "default": null
    },
    "lat_min": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 90,
          "minimum": -90
        },
        {
          "type": "null"
        }
      ],
      "title": "Lat Min",
      "default": null
    },
    "lon_max": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 180,
          "minimum": -180
        },
        {
          "type": "null"
        }
      ],
      "title": "Lon Max",
      "default": null
    },
    "lon_min": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 180,
          "minimum": -180
        },
        {
          "type": "null"
        }
      ],
      "title": "Lon Min",
      "default": null
    },
    "station": {
      "anyOf": [
        {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Station",
      "default": null,
      "description": "station ids -- a list, or one id (or several, comma-separated) as a string; CASE-SENSITIVE: HTM150 (trigram + sampling height) for atmosphere, SE-Htm for FLUXNET sites"
    },
    "apply_qc": {
      "type": "boolean",
      "title": "Apply Qc",
      "default": true,
      "description": "DEFAULT TRUE: drop the observations the store's recommended quality control rejects; false keeps every observation, flagged ones included"
    },
    "height_max": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "null"
        }
      ],
      "title": "Height Max",
      "default": null
    },
    "height_min": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "null"
        }
      ],
      "title": "Height Min",
      "default": null
    }
  }
}
estimate output schema
{
  "type": "object",
  "title": "Estimate",
  "required": [
    "id",
    "rows",
    "exact"
  ],
  "properties": {
    "id": {
      "type": "string",
      "title": "Id"
    },
    "note": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Note",
      "default": null
    },
    "rows": {
      "anyOf": [
        {
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "title": "Rows",
      "description": "rows the selection holds; None when only an upper bound is known"
    },
    "exact": {
      "type": "boolean",
      "title": "Exact"
    },
    "time_max": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Time Max",
      "default": null
    },
    "time_min": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Time Min",
      "default": null
    },
    "est_bytes": {
      "anyOf": [
        {
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "title": "Est Bytes",
      "default": null
    },
    "n_stations": {
      "anyOf": [
        {
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "title": "N Stations",
      "default": null
    },
    "rows_at_most": {
      "anyOf": [
        {
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "title": "Rows At Most",
      "default": null
    }
  }
}
estimate annotations
{
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
get_data
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Observations for one variable, filtered by box, time, station, cruise, height and quality control. Returns at most max_rows rows as a table, the total, a download URL for the whole selection, and the citation the user must be given with any use of the data.

get_data input schema
{
  "type": "object",
  "title": "get_dataArguments",
  "required": [
    "id"
  ],
  "properties": {
    "id": {
      "type": "string",
      "title": "Id",
      "description": "a variable id from search_variables"
    },
    "end": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "End",
      "default": null,
      "description": "ISO date or datetime, EXCLUSIVE"
    },
    "start": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Start",
      "default": null,
      "description": "ISO date or datetime, inclusive (2025-01-01)"
    },
    "cruise": {
      "anyOf": [
        {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Cruise",
      "default": null,
      "description": "cruise expocodes, a list or a string; ocean observation tables only"
    },
    "lat_max": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 90,
          "minimum": -90
        },
        {
          "type": "null"
        }
      ],
      "title": "Lat Max",
      "default": null
    },
    "lat_min": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 90,
          "minimum": -90
        },
        {
          "type": "null"
        }
      ],
      "title": "Lat Min",
      "default": null
    },
    "lon_max": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 180,
          "minimum": -180
        },
        {
          "type": "null"
        }
      ],
      "title": "Lon Max",
      "default": null
    },
    "lon_min": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 180,
          "minimum": -180
        },
        {
          "type": "null"
        }
      ],
      "title": "Lon Min",
      "default": null
    },
    "station": {
      "anyOf": [
        {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Station",
      "default": null,
      "description": "station ids -- a list, or one id (or several, comma-separated) as a string; CASE-SENSITIVE: HTM150 (trigram + sampling height) for atmosphere, SE-Htm for FLUXNET sites"
    },
    "apply_qc": {
      "type": "boolean",
      "title": "Apply Qc",
      "default": true,
      "description": "DEFAULT TRUE: drop the observations the store's recommended quality control rejects; false keeps every observation, flagged ones included"
    },
    "max_rows": {
      "type": "integer",
      "title": "Max Rows",
      "default": 100,
      "maximum": 2000,
      "minimum": 1,
      "description": "rows to return; the whole selection is at download_url"
    },
    "height_max": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "null"
        }
      ],
      "title": "Height Max",
      "default": null
    },
    "height_min": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "null"
        }
      ],
      "title": "Height Min",
      "default": null
    }
  }
}
get_data output schema
{
  "type": "object",
  "$defs": {
    "Citation": {
      "type": "object",
      "title": "Citation",
      "properties": {
        "doi": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Doi",
          "default": null
        },
        "license": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "License",
          "default": null
        },
        "sources": {
          "anyOf": [
            {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            {
              "type": "null"
            }
          ],
          "title": "Sources",
          "default": null,
          "description": "the citation of each data object the selection came from -- what to cite when there is no collection citation (near-real-time data)"
        },
        "citation": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Citation",
          "default": null
        },
        "n_sources": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "title": "N Sources",
          "default": null,
          "description": "how many data objects the selection came from; in a data answer their citations are listed only when there are three or fewer -- get_citation (with the same stations) lists them all"
        },
        "license_url": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "License Url",
          "default": null
        },
        "selection_id": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Selection Id",
          "default": null,
          "description": "stable id of this exact selection over this exact store version"
        },
        "store_version": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Store Version",
          "default": null
        }
      },
      "description": "In data answers the author list is shortened (first author et al.);\nget_citation gives the full citation."
    }
  },
  "title": "Data",
  "required": [
    "id",
    "columns",
    "rows",
    "rows_returned",
    "rows_total",
    "truncated",
    "download_url",
    "citation"
  ],
  "properties": {
    "id": {
      "type": "string",
      "title": "Id"
    },
    "note": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Note",
      "default": null
    },
    "rows": {
      "type": "array",
      "items": {
        "type": "array",
        "items": {}
      },
      "title": "Rows"
    },
    "columns": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "title": "Columns"
    },
    "citation": {
      "$ref": "#/$defs/Citation"
    },
    "truncated": {
      "type": "boolean",
      "title": "Truncated"
    },
    "rows_total": {
      "anyOf": [
        {
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "title": "Rows Total",
      "description": "rows in the whole selection, when known"
    },
    "download_url": {
      "type": "string",
      "title": "Download Url",
      "description": "the selection as CSV when it fits one download; when it does not, the FIRST of download_urls"
    },
    "download_urls": {
      "anyOf": [
        {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        {
          "type": "null"
        }
      ],
      "title": "Download Urls",
      "default": null,
      "description": "when the selection is larger than one download (the proxy caps an answer at 500,000 rows): one CSV link per time window, together the WHOLE selection -- give the user all of them"
    },
    "rows_returned": {
      "type": "integer",
      "title": "Rows Returned"
    },
    "download_complete": {
      "type": "boolean",
      "title": "Download Complete",
      "default": true,
      "description": "false when no set of links could be planned to cover the whole selection; the note says what is missing"
    }
  }
}
get_data annotations
{
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
get_citation
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

How to cite a variable's data: the citation text, licence and DOI from its data passport, and -- for a selection (stations, a time window, a box) -- every data object it came from, in full. Data answers carry a short citation and only the COUNT of their sources; this lists them.

get_citation input schema
{
  "type": "object",
  "title": "get_citationArguments",
  "required": [
    "id"
  ],
  "properties": {
    "id": {
      "type": "string",
      "title": "Id",
      "description": "a variable id from search_variables"
    },
    "end": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "End",
      "default": null,
      "description": "ISO date or datetime, EXCLUSIVE"
    },
    "start": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Start",
      "default": null,
      "description": "ISO date or datetime, inclusive (2025-01-01)"
    },
    "lat_max": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 90,
          "minimum": -90
        },
        {
          "type": "null"
        }
      ],
      "title": "Lat Max",
      "default": null
    },
    "lat_min": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 90,
          "minimum": -90
        },
        {
          "type": "null"
        }
      ],
      "title": "Lat Min",
      "default": null
    },
    "lon_max": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 180,
          "minimum": -180
        },
        {
          "type": "null"
        }
      ],
      "title": "Lon Max",
      "default": null
    },
    "lon_min": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 180,
          "minimum": -180
        },
        {
          "type": "null"
        }
      ],
      "title": "Lon Min",
      "default": null
    },
    "station": {
      "anyOf": [
        {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Station",
      "default": null,
      "description": "station ids -- a list, or one id (or several, comma-separated) as a string; CASE-SENSITIVE: HTM150 (trigram + sampling height) for atmosphere, SE-Htm for FLUXNET sites"
    }
  }
}
get_citation output schema
{
  "type": "object",
  "title": "Citation",
  "properties": {
    "doi": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Doi",
      "default": null
    },
    "license": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "License",
      "default": null
    },
    "sources": {
      "anyOf": [
        {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        {
          "type": "null"
        }
      ],
      "title": "Sources",
      "default": null,
      "description": "the citation of each data object the selection came from -- what to cite when there is no collection citation (near-real-time data)"
    },
    "citation": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Citation",
      "default": null
    },
    "n_sources": {
      "anyOf": [
        {
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "title": "N Sources",
      "default": null,
      "description": "how many data objects the selection came from; in a data answer their citations are listed only when there are three or fewer -- get_citation (with the same stations) lists them all"
    },
    "license_url": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "License Url",
      "default": null
    },
    "selection_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Selection Id",
      "default": null,
      "description": "stable id of this exact selection over this exact store version"
    },
    "store_version": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Store Version",
      "default": null
    }
  },
  "description": "In data answers the author list is shortened (first author et al.);\nget_citation gives the full citation."
}
get_citation annotations
{
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
aggregate
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Statistics over a WHOLE selection, computed on the server: count, mean, min, max, sum and standard deviation of one variable, overall or per station, year, month or day. Use this for any average, total, range or trend instead of reading rows. Any size: a selection over 500,000 rows is split by time on the server and merged exactly. `std` is the POPULATION standard deviation (ddof 0). `sum` adds the values as stored, which is a total only for values that are themselves totals per row: summing a RATE (umol m-2 s-1 per half-hour, gC m-2 d-1 per day) or a concentration gives no physical quantity -- for a flux total multiply the mean by the period.

aggregate input schema
{
  "type": "object",
  "title": "aggregateArguments",
  "required": [
    "id"
  ],
  "properties": {
    "by": {
      "enum": [
        "none",
        "station",
        "year",
        "month",
        "day",
        "station_year",
        "station_month"
      ],
      "type": "string",
      "title": "By",
      "default": "none",
      "description": "the groups: none (one result), station, a period, or both"
    },
    "id": {
      "type": "string",
      "title": "Id",
      "description": "a variable id from search_variables"
    },
    "end": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "End",
      "default": null,
      "description": "ISO date or datetime, EXCLUSIVE"
    },
    "start": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Start",
      "default": null,
      "description": "ISO date or datetime, inclusive (2025-01-01)"
    },
    "cruise": {
      "anyOf": [
        {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Cruise",
      "default": null,
      "description": "cruise expocodes, a list or a string; ocean observation tables only"
    },
    "lat_max": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 90,
          "minimum": -90
        },
        {
          "type": "null"
        }
      ],
      "title": "Lat Max",
      "default": null
    },
    "lat_min": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 90,
          "minimum": -90
        },
        {
          "type": "null"
        }
      ],
      "title": "Lat Min",
      "default": null
    },
    "lon_max": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 180,
          "minimum": -180
        },
        {
          "type": "null"
        }
      ],
      "title": "Lon Max",
      "default": null
    },
    "lon_min": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 180,
          "minimum": -180
        },
        {
          "type": "null"
        }
      ],
      "title": "Lon Min",
      "default": null
    },
    "station": {
      "anyOf": [
        {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Station",
      "default": null,
      "description": "station ids -- a list, or one id (or several, comma-separated) as a string; CASE-SENSITIVE: HTM150 (trigram + sampling height) for atmosphere, SE-Htm for FLUXNET sites"
    },
    "apply_qc": {
      "type": "boolean",
      "title": "Apply Qc",
      "default": true,
      "description": "DEFAULT TRUE: drop the observations the store's recommended quality control rejects; false keeps every observation, flagged ones included"
    },
    "height_max": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "null"
        }
      ],
      "title": "Height Max",
      "default": null
    },
    "height_min": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "null"
        }
      ],
      "title": "Height Min",
      "default": null
    }
  }
}
aggregate output schema
{
  "type": "object",
  "$defs": {
    "Citation": {
      "type": "object",
      "title": "Citation",
      "properties": {
        "doi": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Doi",
          "default": null
        },
        "license": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "License",
          "default": null
        },
        "sources": {
          "anyOf": [
            {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            {
              "type": "null"
            }
          ],
          "title": "Sources",
          "default": null,
          "description": "the citation of each data object the selection came from -- what to cite when there is no collection citation (near-real-time data)"
        },
        "citation": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Citation",
          "default": null
        },
        "n_sources": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "title": "N Sources",
          "default": null,
          "description": "how many data objects the selection came from; in a data answer their citations are listed only when there are three or fewer -- get_citation (with the same stations) lists them all"
        },
        "license_url": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "License Url",
          "default": null
        },
        "selection_id": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Selection Id",
          "default": null,
          "description": "stable id of this exact selection over this exact store version"
        },
        "store_version": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Store Version",
          "default": null
        }
      },
      "description": "In data answers the author list is shortened (first author et al.);\nget_citation gives the full citation."
    }
  },
  "title": "Aggregate",
  "required": [
    "id",
    "variable",
    "by",
    "groups",
    "n_groups",
    "rows_used",
    "download_url",
    "citation"
  ],
  "properties": {
    "by": {
      "type": "string",
      "title": "By"
    },
    "id": {
      "type": "string",
      "title": "Id"
    },
    "note": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Note",
      "default": null
    },
    "unit": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Unit",
      "default": null
    },
    "groups": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": true
      },
      "title": "Groups",
      "description": "one entry per group: its keys (station, period), n (finite values), and mean, min, max, sum, std over them (null when n is 0)"
    },
    "citation": {
      "$ref": "#/$defs/Citation"
    },
    "n_groups": {
      "type": "integer",
      "title": "N Groups"
    },
    "variable": {
      "type": "string",
      "title": "Variable"
    },
    "rows_used": {
      "type": "integer",
      "title": "Rows Used"
    },
    "download_url": {
      "type": "string",
      "title": "Download Url"
    },
    "download_urls": {
      "anyOf": [
        {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        {
          "type": "null"
        }
      ],
      "title": "Download Urls",
      "default": null
    },
    "download_complete": {
      "type": "boolean",
      "title": "Download Complete",
      "default": true
    }
  }
}
aggregate annotations
{
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
find_stations
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

The stations that carry a variable: id, name, position, sampling height, country, ecosystem -- near a point (sorted by distance), in a box, by name or by country. The ids are what estimate and get_data take as station=.

find_stations input schema
{
  "type": "object",
  "title": "find_stationsArguments",
  "required": [
    "id"
  ],
  "properties": {
    "id": {
      "type": "string",
      "title": "Id",
      "description": "a station-based variable id from search_variables"
    },
    "text": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Text",
      "default": null,
      "description": "part of a station's id or name, e.g. 'Hyltemossa', 'HTM', 'Hyy'"
    },
    "limit": {
      "type": "integer",
      "title": "Limit",
      "default": 50,
      "maximum": 200,
      "minimum": 1
    },
    "country": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Country",
      "default": null,
      "description": "two-letter code, e.g. SE"
    },
    "lat_max": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 90,
          "minimum": -90
        },
        {
          "type": "null"
        }
      ],
      "title": "Lat Max",
      "default": null
    },
    "lat_min": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 90,
          "minimum": -90
        },
        {
          "type": "null"
        }
      ],
      "title": "Lat Min",
      "default": null
    },
    "lon_max": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 180,
          "minimum": -180
        },
        {
          "type": "null"
        }
      ],
      "title": "Lon Max",
      "default": null
    },
    "lon_min": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 180,
          "minimum": -180
        },
        {
          "type": "null"
        }
      ],
      "title": "Lon Min",
      "default": null
    },
    "near_lat": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 90,
          "minimum": -90
        },
        {
          "type": "null"
        }
      ],
      "title": "Near Lat",
      "default": null,
      "description": "search around this point, with near_lon and radius_km"
    },
    "near_lon": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 180,
          "minimum": -180
        },
        {
          "type": "null"
        }
      ],
      "title": "Near Lon",
      "default": null
    },
    "radius_km": {
      "type": "number",
      "title": "Radius Km",
      "default": 300,
      "maximum": 20000,
      "exclusiveMinimum": 0
    }
  }
}
find_stations output schema
{
  "type": "object",
  "$defs": {
    "Station": {
      "type": "object",
      "title": "Station",
      "required": [
        "id"
      ],
      "properties": {
        "id": {
          "type": "string",
          "title": "Id",
          "description": "the id station= takes, case-sensitive"
        },
        "url": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Url",
          "default": null
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Name",
          "default": null
        },
        "country": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Country",
          "default": null
        },
        "latitude": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "title": "Latitude",
          "default": null
        },
        "ecosystem": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Ecosystem",
          "default": null
        },
        "elevation": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "title": "Elevation",
          "default": null
        },
        "longitude": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "title": "Longitude",
          "default": null
        },
        "distance_km": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "title": "Distance Km",
          "default": null
        },
        "sampling_height": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "title": "Sampling Height",
          "default": null,
          "description": "intake height above ground, m (atmosphere)"
        }
      }
    }
  },
  "title": "StationList",
  "required": [
    "variable",
    "stations",
    "n_matches"
  ],
  "properties": {
    "stations": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/Station"
      },
      "title": "Stations"
    },
    "variable": {
      "type": "string",
      "title": "Variable"
    },
    "n_matches": {
      "type": "integer",
      "title": "N Matches"
    }
  }
}
find_stations annotations
{
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}

Prompts

3 advertised

station_record — A station's record

Advertised by the server during the last successful anonymous check.

Plot or describe one station's time series.

quantity
No description
station
No description
period
No description
compare_stations — Compare stations

Advertised by the server during the last successful anonymous check.

Compare one quantity across several stations.

quantity
No description
stations
No description
period
No description
ocean_region — Ocean CO2 in a region

Advertised by the server during the last successful anonymous check.

What surface-ocean CO2 observations exist in a region.

region
No description
period
No description

Resources

3 advertised

catalogue

Advertised by the server during the last successful anonymous check.

every queryable variable of the public stores: id, names, unit, QC flag, store

catalogue URI
icos://catalogue

MIME type: application/json

llms_txt

Advertised by the server during the last successful anonymous check.

the service's own guide for language models

llms_txt URI
icos://llms.txt

MIME type: text/plain

data_passport

Advertised by the server during the last successful anonymous check.

what the data passport in every answer contains and how to cite

data_passport URI
icos://data-passport

MIME type: text/markdown

agent_guide

Advertised by the server during the last successful anonymous check.

how to open and read one ICOS store: layout, coordinates, QC, citation -- written for agents

agent_guide URI template
icos://stores/{store}/agent-guide

MIME type: application/json

croissant

Advertised by the server during the last successful anonymous check.

the store's Croissant (ML dataset) description: every queryable variable with its unit

croissant URI template
icos://stores/{store}/croissant

MIME type: application/ld+json

30-day availability

Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.

Successful checks
1 of 1 (100%)
Average latency
1280 ms
95th percentile latency
1280 ms

Maintenance history

Public check and source-refresh events. Editorial and ownership records remain private.

  • · probe · passed · 1280 ms · metadata changed · 8 tool(s), 3 resource(s), 2 resource template(s), 3 prompt(s)

Connect from your client

Each snippet registers the same endpoint; pick the client you use.

This server is operated by the named third party. Listing and endpoint checks are not an endorsement or a security audit. Review the operator's permissions, terms, and data handling before connecting. How listings are checked and corrected.

Claude Code

Run this once in a terminal. It registers the remote server. Use --scope project to write .mcp.json for the repo.
Claude Code configuration
claude mcp add --transport http icos-carbon-portal-mcp https://mcp.icos-cp.eu/mcp

Codex

Run this once. Codex stores MCP servers in ~/.codex/config.toml (or .codex/config.toml in a trusted project).
Codex configuration
codex mcp add icos-carbon-portal-mcp --url https://mcp.icos-cp.eu/mcp

Cursor

Merge this server into .cursor/mcp.json in your project, then enable icos-carbon-portal-mcp in your MCP settings.
Cursor configuration
{
  "mcpServers": {
    "icos-carbon-portal-mcp": {
      "url": "https://mcp.icos-cp.eu/mcp"
    }
  }
}

Cline

Merge this into cline_mcp_settings.json (Cline → MCP Servers → Configure).
Cline configuration
{
  "mcpServers": {
    "icos-carbon-portal-mcp": {
      "type": "streamableHttp",
      "url": "https://mcp.icos-cp.eu/mcp",
      "disabled": false
    }
  }
}

VS Code

Merge this server into .vscode/mcp.json. Use MCP: List Servers to start icos-carbon-portal-mcp and inspect its tools.
VS Code configuration
{
  "servers": {
    "icos-carbon-portal-mcp": {
      "type": "http",
      "url": "https://mcp.icos-cp.eu/mcp"
    }
  }
}

Gemini CLI

Run this once. It writes .gemini/settings.json in the current project; pass --scope user for ~/.gemini/settings.json.
Gemini CLI configuration
gemini mcp add --transport http icos-carbon-portal-mcp https://mcp.icos-cp.eu/mcp

Claude Desktop

Merge this into claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\), then restart Claude Desktop.
Claude Desktop configuration
{
  "mcpServers": {
    "icos-carbon-portal-mcp": {
      "url": "https://mcp.icos-cp.eu/mcp"
    }
  }
}

Windsurf

Merge this into ~/.codeium/windsurf/mcp_config.json, then refresh MCP in Cascade. Windsurf remote servers use serverUrl, not url.
Windsurf configuration
{
  "mcpServers": {
    "icos-carbon-portal-mcp": {
      "serverUrl": "https://mcp.icos-cp.eu/mcp"
    }
  }
}

Let your agent find its tools

Find servers like ICOS Carbon Portal MCP from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.

Do you run ICOS Carbon Portal MCP?

Prove ownership with a DNS record, a well-known file, or your Official MCP Registry entry, and your edits publish immediately. Proofs are re-checked weekly; admins can still hide or remove a listing.

Claim this listing