Skip to main content
Glama

inaturalist-mcp-server

Inaturalist Get Observation

inaturalist_get_observation
Read-onlyIdempotent

Fetch up to 10 distinct observations by id with their community identification thread — who identified what, whether each identification agrees, and the consensus taxon the community landed on. The whole attempted batch costs one upstream request. Records come back in requested order; remaining distinct ids are deferred for another call with the same include. Missing attempted ids appear in unresolved; the call fails only when nothing resolved and no deferred work remains. Long threads and observation-field lists share a response budget across resolved records — up to 40 entries per array for one record, 4 for a full batch — and every record reports the size of each array beside what it kept.

Input Schema

NameRequiredDescriptionDefault
includeNoEmbedded arrays to expand per record. identifications is the default and is what carries the thread; the others cost context, so check photo_count and sound_count first. identifications and comments — like the observation_fields every record carries — share a 40-entry budget across the batch: each record keeps at most 40 ÷ records returned entries per array (never fewer than 4), and reports identifications_total, comments_total, and observation_fields_total beside what it kept — request one id alone for the 40-entry view.
observation_idYesObservation ids to fetch, 1 to 100 submitted ids. The first 10 distinct ids are attempted; any remaining distinct ids are deferred to another call. Find current ids for an area with inaturalist_search_observations.

Output Schema

NameRequiredDescriptionDefault
errorNoPresent when the call failed. Absent on success.
noticeNoGuidance when part of the batch did not resolve, or when a thread or observation-field list was cut to fit the response.
deferredNoDistinct ids beyond the attempted batch, in requested order. Empty when no work remains.
unresolvedNoRequested ids upstream returned nothing for. They may have been deleted, or never existed.
observationsNoThe observations that resolved, in the requested order with unresolved ids left out, carrying the expansions that were requested.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed29 schema fields changed
    • changedInput schema / properties / observation_id / description
      Previous value: -"Observation ids to fetch, 1 to 10. Find current ids for an area with inaturalist_search_observations."New value: +"Observation ids to fetch, 1 to 100 submitted ids. The first 10 distinct ids are attempted; any remaining distinct ids are deferred to another call. Find current ids for an area with inaturalist_search_observations."
    • changedInput schema / properties / observation_id / maxItems
      Previous value: -10New value: +100
    • changedOutput schema / anyOf
      Previous value: -[
      -  {
      -    "not": {
      -      "required": [
      -        "error"
      -      ]
      -    },
      -    "required": [
      -      "observations",
      -      "unresolved"
      -    ]
      -  },
      -  {
      -    "required": [
      -      "error"
      -    ]
      -  }
      -]New value: +[
      +  {
      +    "not": {
      +      "required": [
      +        "error"
      +      ]
      +    },
      +    "required": [
      +      "observations",
      +      "unresolved",
      +      "deferred"
      +    ]
      +  },
      +  {
      +    "required": [
      +      "error"
      +    ]
      +  }
      +]
    • addedOutput schema / properties / deferred
      Added value: +{
      +  "description": "Distinct ids beyond the attempted batch, in requested order. Empty when no work remains.",
      +  "items": {
      +    "additionalProperties": false,
      +    "description": "One id to request in a subsequent call.",
      +    "properties": {
      +      "observation_id": {
      +        "description": "An id not attempted in this call.",
      +        "type": "number"
      +      }
      +    },
      +    "required": [
      +      "observation_id"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • changedOutput schema / properties / error / properties / data / properties / reason / description
      Previous value: -"Machine-readable failure mode. Declared by this tool: `not_found`: None of the requested ids resolved to an observation. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `not_found`: None of the attempted ids resolved to an observation and no deferred ids remain. Other values are possible when a failure originates below the handler."
    • changedOutput schema / properties / observations / items / properties / annotations / items / properties / attribute / description
      Previous value: -"Decoded attribute label, e.g. \"Life Stage\". Null when the id is not in the vocabulary."New value: +"Attribute label, e.g. \"Life Stage\"; null for an unknown id."
    • changedOutput schema / properties / observations / items / properties / annotations / items / properties / value / description
      Previous value: -"Decoded value label, e.g. \"Larva\". Null when the id is not in the vocabulary."New value: +"Value label, e.g. \"Larva\"; null for an unknown id."
    • changedOutput schema / properties / observations / items / properties / comments / description
      Previous value: -"Discussion comments, cut to their first entries in upstream order (not strictly chronological) when they exceed the per-record share of a 40-entry budget. Present when \"comments\" was included."New value: +"Requested comments, first entries in upstream order (not strictly chronological), sharing a 40-entry budget across records."
    • changedOutput schema / properties / observations / items / properties / comments_shown / description
      Previous value: -"How many of them comments carries. Below comments_total when the thread was cut. Present when \"comments\" was included."New value: +"Comment entries returned; below comments_total when capped."
    • changedOutput schema / properties / observations / items / properties / comments_total / description
      Previous value: -"How many comments upstream holds on the record. Present when \"comments\" was included."New value: +"Comment count before the cap; present with \"comments\"."
    • changedOutput schema / properties / observations / items / properties / community_taxon / description
      Previous value: -"Consensus taxon, resolved. Present on the by-id tool; null when the thread has reached none."New value: +"Resolved consensus taxon on detail records; null without consensus."
    • changedOutput schema / properties / observations / items / properties / coordinate / anyOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "accuracy_m": {
      -        "description": "Public positional accuracy radius in metres. On an obscured record this is tens of kilometres and the point is a locality, not a sighting position.",
      -        "type": [
      -          "number",
      -          "null"
      -        ]
      -      },
      -      "lat": {
      -        "description": "Latitude in decimal degrees.",
      -        "type": "number"
      -      },
      -      "lng": {
      -        "description": "Longitude in decimal degrees.",
      -        "type": "number"
      -      }
      -    },
      -    "required": [
      -      "lat",
      -      "lng",
      -      "accuracy_m"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "accuracy_m": {
      +        "description": "Public accuracy radius, metres. An obscured point is a locality, not a sighting position.",
      +        "type": [
      +          "number",
      +          "null"
      +        ]
      +      },
      +      "lat": {
      +        "description": "Latitude in decimal degrees.",
      +        "type": "number"
      +      },
      +      "lng": {
      +        "description": "Longitude in decimal degrees.",
      +        "type": "number"
      +      }
      +    },
      +    "required": [
      +      "lat",
      +      "lng",
      +      "accuracy_m"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • changedOutput schema / properties / observations / items / properties / description / description
      Previous value: -"The observer’s own note on the sighting — host plant, behaviour, habitat, count. Third-party free text. Present on the by-id tool; null when the observer wrote none."New value: +"Verbatim observer note on detail records; null when none was written, distinct from an empty string."
    • changedOutput schema / properties / observations / items / properties / identification_disagreements_count / description
      Previous value: -"Count of disagreeing identifications as upstream tallies it. Present on the by-id tool."New value: +"Upstream disagreement count on detail records."
    • changedOutput schema / properties / observations / items / properties / identifications / description
      Previous value: -"The identification thread, cut to its first entries in upstream order (roughly but not strictly chronological) when it exceeds the per-record share of a 40-entry budget. Present when \"identifications\" was included."New value: +"Requested identification thread, first entries in upstream order (not strictly chronological), sharing a 40-entry budget across records."
    • changedOutput schema / properties / observations / items / properties / identifications_count / description
      Previous value: -"Upstream’s tally of identifications currently agreeing or disagreeing with the community taxon — agreements + disagreements. Not the thread size: it leaves out the observer’s own identification and any that neither agrees nor disagrees, such as a coarser or withdrawn one. The thread size is identifications_total, on inaturalist_get_observation."New value: +"Tally against the community taxon: agreements + disagreements. Excludes the observer and neutral/withdrawn ids; thread size is identifications_total on inaturalist_get_observation."
    • changedOutput schema / properties / observations / items / properties / identifications_shown / description
      Previous value: -"How many of them identifications carries. Below identifications_total when the thread was cut. Present when \"identifications\" was included."New value: +"Identification entries returned; below identifications_total when capped."
    • changedOutput schema / properties / observations / items / properties / identifications_total / description
      Previous value: -"How many identifications upstream holds on the record — the thread size. Present when \"identifications\" was included."New value: +"Thread size before the cap; present with \"identifications\"."
    • changedOutput schema / properties / observations / items / properties / obscured / description
      Previous value: -"True when the true coordinate is withheld, typically for a threatened taxon. The point is never resolved or approximated."New value: +"True when the true coordinate is withheld; the public point is a locality."
    • changedOutput schema / properties / observations / items / properties / observation_fields / description
      Previous value: -"Observation-field values filled in on the record, usually by a project; fields left blank are dropped. Cut to the first filled fields in upstream order when they exceed the per-record share of a 40-entry budget. Present on the by-id tool."New value: +"Filled fields on detail records, verbatim; blanks omitted. First entries in upstream order, sharing a 40-entry budget across records."
    • changedOutput schema / properties / observations / items / properties / observation_fields / items / properties / name / description
      Previous value: -"Field name, as its creator wrote it, e.g. \"Habitat_Description\"."New value: +"Verbatim field name, e.g. \"Habitat_Description\"."
    • changedOutput schema / properties / observations / items / properties / observation_fields_shown / description
      Previous value: -"How many of them observation_fields carries. Below observation_fields_total when the list was cut. Present on the by-id tool."New value: +"Filled fields returned; below observation_fields_total when capped."
    • changedOutput schema / properties / observations / items / properties / observation_fields_total / description
      Previous value: -"How many filled observation fields the record carries. Present on the by-id tool."New value: +"Filled field count before the cap on detail records."
    • changedOutput schema / properties / observations / items / properties / observer / description
      Previous value: -"Login of the observer. The rest of the upstream profile is not relayed."New value: +"Observer login."
    • changedOutput schema / properties / observations / items / properties / photo / anyOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "description": "A photo with the attribution and licence that must travel with it.",
      -    "properties": {
      -      "attribution": {
      -        "description": "Attribution string, verbatim and never reformatted. Reproduce it with any use of the image.",
      -        "type": [
      -          "string",
      -          "null"
      -        ]
      -      },
      -      "license_code": {
      -        "description": "Photo licence code. Null means all rights reserved, independent of the record.",
      -        "type": [
      -          "string",
      -          "null"
      -        ]
      -      },
      -      "medium_url": {
      -        "description": "Medium variant. Supplied by upstream where it publishes every size, otherwise derived by substituting the size qualifier in the path. Absent when the path did not match the documented shape.",
      -        "type": "string"
      -      },
      -      "open": {
      -        "description": "True when the photo is served from the host the upstream reserves for open licences. A photo can move hosts when its licence changes, so this reflects fetch time.",
      -        "type": "boolean"
      -      },
      -      "square_url": {
      -        "description": "75px square variant, exactly as upstream published it. Null when absent.",
      -        "type": [
      -          "string",
      -          "null"
      -        ]
      -      }
      -    },
      -    "required": [
      -      "square_url",
      -      "attribution",
      -      "license_code",
      -      "open"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "description": "A photo with the attribution and licence that must travel with it.",
      +    "properties": {
      +      "attribution": {
      +        "description": "Verbatim attribution; reproduce with any use of the image.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "license_code": {
      +        "description": "Photo licence code. Null means all rights reserved, independent of the record.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "medium_url": {
      +        "description": "Medium image URL; derived from the size path if needed. Absent when no variant is available.",
      +        "type": "string"
      +      },
      +      "open": {
      +        "description": "True when served from the open-licence host at fetch time; licences can change.",
      +        "type": "boolean"
      +      },
      +      "square_url": {
      +        "description": "75px square variant, exactly as upstream published it. Null when absent.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      }
      +    },
      +    "required": [
      +      "square_url",
      +      "attribution",
      +      "license_code",
      +      "open"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • changedOutput schema / properties / observations / items / properties / photo_count / description
      Previous value: -"How many photos the record carries, so include \"photos\" can be spent knowingly."New value: +"Photo count; include \"photos\" for every photo."
    • changedOutput schema / properties / observations / items / properties / photos / items / properties / attribution / description
      Previous value: -"Attribution string, verbatim and never reformatted. Reproduce it with any use of the image."New value: +"Verbatim attribution; reproduce with any use of the image."
    • changedOutput schema / properties / observations / items / properties / photos / items / properties / medium_url / description
      Previous value: -"Medium variant. Supplied by upstream where it publishes every size, otherwise derived by substituting the size qualifier in the path. Absent when the path did not match the documented shape."New value: +"Medium image URL; derived from the size path if needed. Absent when no variant is available."
    • changedOutput schema / properties / observations / items / properties / photos / items / properties / open / description
      Previous value: -"True when the photo is served from the host the upstream reserves for open licences. A photo can move hosts when its licence changes, so this reflects fetch time."New value: +"True when served from the open-licence host at fetch time; licences can change."
  2. Changed16 schema fields changed
    • changedInput schema / properties / include / description
      Previous value: -"Embedded arrays to expand per record. identifications is the default and is what carries the thread; the others cost context, so check photo_count and sound_count first."New value: +"Embedded arrays to expand per record. identifications is the default and is what carries the thread; the others cost context, so check photo_count and sound_count first. identifications and comments — like the observation_fields every record carries — share a 40-entry budget across the batch: each record keeps at most 40 ÷ records returned entries per array (never fewer than 4), and reports identifications_total, comments_total, and observation_fields_total beside what it kept — request one id alone for the 40-entry view."
    • changedOutput schema / properties / notice / description
      Previous value: -"Guidance when part of the batch did not resolve."New value: +"Guidance when part of the batch did not resolve, or when a thread or observation-field list was cut to fit the response."
    • changedOutput schema / properties / observations / description
      Previous value: -"The observations that resolved, with the expansions that were requested."New value: +"The observations that resolved, in the requested order with unresolved ids left out, carrying the expansions that were requested."
    • changedOutput schema / properties / observations / items / properties / agreements / description
      Previous value: -"How many identifications agree with the current taxon."New value: +"How many identifications currently agree with the community taxon."
    • changedOutput schema / properties / observations / items / properties / comments / description
      Previous value: -"Discussion comments. Present when \"comments\" was included."New value: +"Discussion comments, cut to their first entries in upstream order (not strictly chronological) when they exceed the per-record share of a 40-entry budget. Present when \"comments\" was included."
    • addedOutput schema / properties / observations / items / properties / comments_shown
      Added value: +{
      +  "description": "How many of them comments carries. Below comments_total when the thread was cut. Present when \"comments\" was included.",
      +  "type": "number"
      +}
    • addedOutput schema / properties / observations / items / properties / comments_total
      Added value: +{
      +  "description": "How many comments upstream holds on the record. Present when \"comments\" was included.",
      +  "type": "number"
      +}
    • addedOutput schema / properties / observations / items / properties / description
      Added value: +{
      +  "description": "The observer’s own note on the sighting — host plant, behaviour, habitat, count. Third-party free text. Present on the by-id tool; null when the observer wrote none.",
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • changedOutput schema / properties / observations / items / properties / disagreements / description
      Previous value: -"How many identifications disagree with the current taxon."New value: +"How many identifications currently disagree with the community taxon."
    • changedOutput schema / properties / observations / items / properties / identifications / description
      Previous value: -"The identification thread. Present when \"identifications\" was included."New value: +"The identification thread, cut to its first entries in upstream order (roughly but not strictly chronological) when it exceeds the per-record share of a 40-entry budget. Present when \"identifications\" was included."
    • changedOutput schema / properties / observations / items / properties / identifications_count / description
      Previous value: -"How many identifications the thread holds."New value: +"Upstream’s tally of identifications currently agreeing or disagreeing with the community taxon — agreements + disagreements. Not the thread size: it leaves out the observer’s own identification and any that neither agrees nor disagrees, such as a coarser or withdrawn one. The thread size is identifications_total, on inaturalist_get_observation."
    • addedOutput schema / properties / observations / items / properties / identifications_shown
      Added value: +{
      +  "description": "How many of them identifications carries. Below identifications_total when the thread was cut. Present when \"identifications\" was included.",
      +  "type": "number"
      +}
    • addedOutput schema / properties / observations / items / properties / identifications_total
      Added value: +{
      +  "description": "How many identifications upstream holds on the record — the thread size. Present when \"identifications\" was included.",
      +  "type": "number"
      +}
    • addedOutput schema / properties / observations / items / properties / observation_fields
      Added value: +{
      +  "description": "Observation-field values filled in on the record, usually by a project; fields left blank are dropped. Cut to the first filled fields in upstream order when they exceed the per-record share of a 40-entry budget. Present on the by-id tool.",
      +  "items": {
      +    "additionalProperties": false,
      +    "description": "One filled observation field.",
      +    "properties": {
      +      "name": {
      +        "description": "Field name, as its creator wrote it, e.g. \"Habitat_Description\".",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "value": {
      +        "description": "The value filled in, verbatim.",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "name",
      +      "value"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / properties / observations / items / properties / observation_fields_shown
      Added value: +{
      +  "description": "How many of them observation_fields carries. Below observation_fields_total when the list was cut. Present on the by-id tool.",
      +  "type": "number"
      +}
    • addedOutput schema / properties / observations / items / properties / observation_fields_total
      Added value: +{
      +  "description": "How many filled observation fields the record carries. Present on the by-id tool.",
      +  "type": "number"
      +}
  3. First observed

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With annotations already covering read-only, open-world, and idempotent behavior, the description adds substantial operational detail: one upstream request per attempted batch, order preservation, deferred ids, unresolved missing ids, and failure only when no resolution and no deferral remain. It also discloses response-budget behavior across arrays.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but front-loaded and purposeful. Each sentence adds operational information about batching, deferral, failure, or response budgets without wasting space.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the output schema, rich annotations, and full schema coverage, the description is complete for correct invocation. It covers the non-obvious batch, deferral, unresolved-id, and response-budget behavior that an agent must understand.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents both parameters in detail. The description reinforces the 10-id attempt limit and include continuity but does not add much beyond the schema's own parameter explanations.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: fetching observations by id, including their community identification thread. It delineates scope precisely with batch limits and the consensus/identification content, making it clearly distinct from search-based sibling tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explains the batch continuation model and failure condition, and the schema points to inaturalist_search_observations for obtaining ids. However, the main description does not explicitly say when to prefer this tool over alternatives beyond the implicit 'by id' framing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.