Tool reference
The MCP gateway turns Geopera’s operation surface into roughly 188 callable tools. Each tool name is a dotted operation_id, its input schema is that operation’s typed request body, and it carries the same scope and side-effect tier the operation enforces on POST /v1/op/{operation_id}.
The surface now includes the read and list operations an agent uses to read back what it creates — list and fetch orders, collections, items, notifications, balances, usage, job lists, alert rules and events, API keys, analytics indices, STAC search, and more. Every read tool carries readOnlyHint, so a well-behaved client knows it is safe to call freely. The practical effect: an agent can place an order and then poll its status, or create a collection and then list its contents, without leaving the governed surface.
The gateway adds nothing the operation does not already declare: it names each tool by its operation_id and stamps safety hints derived from the operation’s scope and side-effect tier. For how to connect a client, see Hosted MCP and the local quickstart.
How an operation becomes a tool
Every Geopera operation is reachable as POST /v1/op/{operation_id} with a JSON body. The gateway exposes one tool per customer-facing operation. The mapping is direct:
| MCP concept | Source on the operation |
|---|
| Tool name | operation_id (e.g. catalog.search) |
| Input schema | the operation’s typed request body |
x-api-key input field | optional header parameter forwarded with the request |
| Required scope | x-required-scope |
| Side-effect tier | x-side-effect |
| Safety hints | derived from x-side-effect (see below) |
The tool name is the canonical operation identity, not a slugified label. Calling the catalog.search tool with a body is exactly equivalent to POST /v1/op/catalog.search with that body, run as the identity behind the bearer token your MCP client presents. Scopes and authentication are unchanged from the HTTP surface — see Authentication and Scopes.
Side-effect tiers and safety hints
The gateway translates each operation’s x-side-effect tier into MCP ToolAnnotations so a client can reason about safety before it calls:
x-side-effect | readOnlyHint | destructiveHint | idempotentHint | openWorldHint |
|---|
read | true | false | false | true |
compute | false | false | false | false |
destructive | false | true | false | false |
external_spend | false | false | true | true |
share_export | false | false | false | true |
external_spend tools (money or external provider spend) are marked idempotent because their dedicated route honours an Idempotency-Key — a repeat with the same key is side-effect-free. See Idempotency and Errors. The scope and tier are also placed in each tool’s structured meta (x-required-scope, x-side-effect, x-produces) so a client can filter or route without parsing the description text.
Why some operations are not tools
A focused set of operations stays excluded. None of these are things an agent needs to work around — each is excluded for a concrete reason:
- Raster tiles and rendered images — map tiles and rendered PNG/JPEG/TIFF/WebP outputs (for example
cog.tile.render, WMTS capabilities). These are frontend map plumbing meant for a tile-rendering map view, not a request-to-single-result tool. - Binary downloads — file exports, generated reports (
reports.generate), and clip downloads (clip.job.download) return large binary payloads. Those belong on a signed URL the agent can hand off, not inlined into a tool result, so the download operation itself is withheld. - Streaming responses — NDJSON and server-sent-event listings and exports (for example
catalog.search_stream) do not fit the MCP request → single-result model. Their paged, non-streaming siblings are exposed instead (the paged stac.search and catalog.search are tools; the streaming export is not). - Admin, cron, and unsafe mutations — admin/internal/cron operations are scrubbed from the customer surface entirely, and a small set of untyped destructive or external-spend mutations is withheld for safety. The governed, typed mutations you need — place an order, create a collection, top up credits — remain available with their side-effect hints intact (see the side-effect table above).
To enumerate the exact tools your gateway exposes at runtime, call list_tools from your MCP client and read each tool’s name, annotations, and meta.
Exposed tools by domain
The tables below list representative tools, grouped by operation domain — both the read/list tools an agent uses to inspect state and the governed mutations it uses to change it. Each row is callable as the tool of that name and as POST /v1/op/{name}. For the authoritative, up-to-the-minute set, call list_tools from your MCP client.
catalog
| Tool | Summary | Scope | Side-effect |
|---|
catalog.search | Search a commercial-imagery host’s catalog (STAC, price-enriched) | catalog:read | read |
catalog.federated_search | Search every data source covering the AOI in one query | catalog:read | read |
catalog.granule_points | Extract a 3D point cloud from a GEDI or ICESat-2 granule | catalog:read | read |
catalog.sources.list | List every searchable data source + its collections | catalog:read | read |
stac.search | STAC-compliant search across the catalog (paged) | catalog:read | read |
items
| Tool | Summary | Scope | Side-effect |
|---|
items.get | Fetch a single catalog item by id | items:read | read |
items.search | Search a project’s items with STAC-compatible filters | items:read | read |
items.search_org | Search all items across the caller’s organization | items:read | read |
items.create | Create an item within a project | items:write | compute |
items.update | Update an item’s mutable metadata | items:write | compute |
items.duplicate | Duplicate an item with its assets + viz profiles | items:write | compute |
items.detect_asset_bands | Auto-detect band names from reflectance statistics | items:read | compute |
items.set_asset_band_names | Rename the bands on an item’s asset | items:write | compute |
items.delete | Soft-delete an item | items:write | destructive |
assets
| Tool | Summary | Scope | Side-effect |
|---|
assets.delete | Delete an asset (file) from an item | items:write | destructive |
collections
| Tool | Summary | Scope | Side-effect |
|---|
collections.create | Create an organizing collection within a project | collections:write | compute |
collections.update | Update a collection’s metadata | collections:write | compute |
collections.delete | Soft-delete a collection, unlinking its items | collections:write | destructive |
projects
| Tool | Summary | Scope | Side-effect |
|---|
projects.create | Create a workspace in the caller’s organization | projects:write | compute |
projects.update | Update a workspace’s metadata | projects:write | compute |
projects.archive | Archive a workspace, hiding it from the default list | projects:write | compute |
projects.add_member | Add a member to a workspace | projects:write | compute |
projects.update_member | Change a member’s role in a workspace | projects:write | compute |
projects.remove_member | Remove a member from a workspace | projects:write | destructive |
projects.delete | Permanently delete a workspace and all its data | projects:write | destructive |
orders
| Tool | Summary | Scope | Side-effect |
|---|
orders.list | List the org’s orders, with status and filters | orders:read | read |
orders.get | Fetch a single order by id (poll its status) | orders:read | read |
orders.archive.estimate | Preview the AOI price for a cart of archive captures | orders:read | read |
orders.tasking.estimate | Preview the price for an AOI-priced tasking request | orders:read | read |
orders.tasking.sensors | List the tasking sensor catalog | orders:read | read |
orders.tasking.templates.list | List the org’s active tasking templates | orders:read | read |
orders.tasking.templates.save | Save a reusable tasking acquisition template | orders:write | compute |
orders.tasking.templates.delete | Soft-delete a tasking template | orders:write | compute |
orders.update | Patch an order’s tags (metadata only) | orders:write | compute |
orders.place | Place order(s) from a FeatureCollection | orders:write | external_spend |
orders.archive.place | Place an archive order | orders:write | external_spend |
orders.tasking.place | Place a tasking order | orders:write | external_spend |
orders.cancel | Cancel an order (policy-gated), refunding its reservation | orders:write | external_spend |
processing
| Tool | Summary | Scope | Side-effect |
|---|
processing.create | Create a processing job | processing:process | external_spend |
processing.create_and_dispatch | Create and dispatch a processing job | processing:process | external_spend |
processing.dispatch | Dispatch an existing pending job to its worker | processing:process | external_spend |
processing.execute | Execute a process (reserve credits + dispatch) | processing:process | external_spend |
clip
| Tool | Summary | Scope | Side-effect |
|---|
clip.create_from_item | Create a clip from an item | processing:process | external_spend |
analytics
| Tool | Summary | Scope | Side-effect |
|---|
analytics.indices.list | List the available spectral indices | analytics:read | read |
analytics.operations.list | List the registered analytics operations | analytics:read | read |
analytics.execute | Run a registered analytics operation | analytics:process | read |
analytics.validate_formula | Validate a band-math formula without executing | analytics:read | read |
band_formulas
| Tool | Summary | Scope | Side-effect |
|---|
band_formulas.get | Fetch a custom band-math formula by id | band_formulas:read | read |
band_formulas.create | Create a custom band-math formula | band_formulas:write | compute |
band_formulas.update | Update a custom band-math formula | band_formulas:write | compute |
band_formulas.delete | Delete a custom band-math formula | band_formulas:write | destructive |
visualization
| Tool | Summary | Scope | Side-effect |
|---|
visualization.list_for | The visualizations available for an item | tiles:read | read |
visualization.profile.create | Create a visualization profile for an item | items:write | compute |
visualization.profile.update | Update a visualization profile | items:write | compute |
visualization.profile.set_default | Set a profile as the item’s default | items:write | compute |
visualization.profile.delete | Delete a visualization profile | items:write | destructive |
uploads
| Tool | Summary | Scope | Side-effect |
|---|
uploads.initiate | Start an upload session, reserving storage quota | uploads:write | compute |
uploads.signed_url | Mint a signed URL for uploading a file | uploads:write | compute |
uploads.progress | Update an upload session’s progress | uploads:write | compute |
uploads.complete | Complete an upload session | uploads:write | compute |
uploads.fail | Mark an upload session failed, releasing its reservation | uploads:write | compute |
share
| Tool | Summary | Scope | Side-effect |
|---|
share.link.validate | Validate a share link and return the shared target | shares:read | read |
share.link.create | Create a password-protected share link | shares:write | share_export |
share.link.revoke | Revoke a share link | shares:write | destructive |
provenance
| Tool | Summary | Scope | Side-effect |
|---|
provenance.get | Walk the provenance/lineage graph for an entity | provenance:read | read |
alerts
| Tool | Summary | Scope | Side-effect |
|---|
alerts.rules.list | List the org’s alert rules | alerts:read | read |
alerts.rule.get | Fetch a single alert rule by id | alerts:read | read |
alerts.events.list | List alert events, with filters | alerts:read | read |
alerts.test_rule | Test-evaluate an alert rule without persisting | alerts:read | read |
alerts.create_rule | Create an alert rule for the caller’s organization | alerts:write | compute |
alerts.update_rule | Update an alert rule | alerts:write | compute |
alerts.acknowledge_event | Mark an alert event acknowledged | alerts:write | compute |
alerts.delete_rule | Delete an alert rule | alerts:write | destructive |
event_subscriptions
| Tool | Summary | Scope | Side-effect |
|---|
event_subscriptions.create | Create a webhook subscription | event_subscriptions:write | compute |
event_subscriptions.update | Update a webhook subscription | event_subscriptions:write | compute |
event_subscriptions.test | Send a test event and return the delivery result | event_subscriptions:write | compute |
event_subscriptions.delete | Delete a webhook subscription | event_subscriptions:write | destructive |
notifications
| Tool | Summary | Scope | Side-effect |
|---|
notifications.list | List the caller’s notifications | notifications:read | read |
notifications.mark_read | Mark one notification as read | notifications:write | compute |
notifications.mark_all_read | Mark all unread notifications as read | notifications:write | compute |
notifications.dismiss | Dismiss one of the caller’s notifications | notifications:write | compute |
billing
| Tool | Summary | Scope | Side-effect |
|---|
billing.approvals.request | Request approval for a large credit purchase | billing:write | compute |
billing.approvals.reject | Reject a pending credit-purchase approval | billing:write | compute |
billing.set_auto_topup | Configure automatic top-up | billing:write | compute |
billing.approvals.approve | Approve a credit purchase and charge the saved card | billing:write | external_spend |
billing.topup | Top up credits | billing:write | external_spend |
payment_methods
| Tool | Summary | Scope | Side-effect |
|---|
payment_methods.create_setup_intent | Start saving a card to the org (off-session) | billing:write | compute |
payment_methods.attach | Persist a saved card for the org | billing:write | compute |
payment_methods.set_default | Make a saved payment method the org’s default | billing:write | compute |
payment_methods.detach | Detach a saved payment method from the org | billing:write | destructive |
api_keys
| Tool | Summary | Scope | Side-effect |
|---|
api_keys.list | List the org’s API keys (metadata only, no secrets) | api_keys:read | read |
api_keys.create | Mint an organization API key (secret returned once) | api_keys:write | share_export |
api_keys.revoke | Revoke an organization API key | api_keys:write | destructive |
organizations
| Tool | Summary | Scope | Side-effect |
|---|
organizations.create | Create an organization and enroll the caller as owner | organizations:write | compute |
Worked example: the catalog.search tool
catalog.search (scope catalog:read, side-effect read) searches a commercial-imagery host’s STAC catalog and price-enriches the results. As an MCP tool it carries readOnlyHint=true, and its input schema is the operation’s typed request body, CatalogSearchInput:
| Field | Type | Required | Notes |
|---|
host_name | string | yes | the imagery host to search |
bbox | number[] | no | bounding box [west, south, east, north] |
intersects | object | no | GeoJSON geometry to intersect |
collections | string[] | no | restrict to specific collections |
ids | string[] | no | fetch specific item ids |
datetime | string | no | RFC 3339 instant or interval |
query | object | no | per-field filters; e.g. cloudCoverage maps to {GT,GTE,LT,LTE} |
limit | integer | no | default 100, min 1, max 500 |
next | string | no | opaque pagination cursor |
full_catalog | boolean | no | search the host’s full catalog |
The tool also exposes an optional x-api-key header field, mapped from the operation’s header parameter and forwarded with the request; in normal use your MCP client’s bearer token is the identity, so you leave it unset. See Pagination for the next cursor contract and Concepts for the operation model.
A tool call carries arguments matching that schema:
{
"host_name": "umbra",
"bbox": [-122.52, 37.7, -122.35, 37.83],
"datetime": "2024-06-01T00:00:00Z/2024-09-01T00:00:00Z",
"query": { "cloudCoverage": { "LTE": 10 } },
"limit": 50
}
Because the tool maps directly to the operation, the same arguments are a valid HTTP request body. The equivalent direct call:
curl -X POST https://api.geopera.com/v1/op/catalog.search \
-H "Authorization: Bearer gpra_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"host_name": "umbra",
"bbox": [-122.52, 37.70, -122.35, 37.83],
"datetime": "2024-06-01T00:00:00Z/2024-09-01T00:00:00Z",
"query": { "cloudCoverage": { "LTE": 10 } },
"limit": 50
}'
Errors surface as RFC 9457 application/problem+json on the HTTP surface and propagate to the tool result — a missing scope, an invalid body, or a rate limit all carry a typed type and detail. See Errors and Rate limits.
See also
- Hosted MCP — connecting an MCP client with OAuth or a forwarded token
- Local quickstart — running the gateway over stdio with a static token
- Operations — the full operation index behind every tool
- Scopes — what each
*:read / *:write scope grants