Umbra open SAR archive

io.github.reesehammer由 GitHub 帳號 reesehammer 發布v0.1.4更新於 Oct 30, 2026

Search, preview, and measure Umbra open SAR from any MCP client. Umbra ships no search API.

已驗證Streamable HTTP可網頁執行網頁搜尋與抓取資料與分析媒體與設計

概覽

AI 產生的概覽

搜尋、預覽並量化 Umbra 開放 SAR 衛星典藏,支援變化合成圖、堆疊統計與場景解讀。

可以做什麼
  • 依邊界框、多邊形、地名或任務搜尋典藏,並列出重複取像最多的地點
  • 取得單一條目的完整中繼資料卡、快視圖,以及附大小檢查的資產下載
  • 產生變化合成圖、時序活動圖、堆疊統計與資料來源一致性檢查
  • 挑選最值得敘述的兩個時相,並只回報某地點自上次檢查以來的新取像
  • 依影像或文字尋找相似場景,並可借助選用模型描述場景或敘述變化
適用情境
適合讓助理不必自行撰寫串接程式就能探索開放 SAR 影像:尋找某區域的取像、檢視快視圖,並量化或敘述某地點隨時間的變化。也適用於重複站點監測與建立變化偵測輸入。
執行需求
可使用託管的遠端端點,或以 uvx 從 umbra-py 套件在本機執行(需 Python 3.10+)。開放資料不需任何憑證。選用密鑰:ANTHROPIC_API_KEY 或 OPENAI_API_KEY 供伺服器端視覺與文字嵌入工具使用,UMBRA_CANOPY_TOKEN 用於改查 Umbra 需驗證的商業典藏。選用的本機目錄索引(UMBRA_INDEX_DB)可加快搜尋,否則每次搜尋都要走訪公開儲存桶。需要網路存取。
安裝前請注意
設定 UMBRA_CANOPY_TOKEN 後搜尋會改為查詢商業典藏,該權杖會傳送給伺服器。若設定視覺密鑰,場景影像會傳送給 Anthropic 或 OpenAI 進行解讀。download_asset 會寫入本機磁碟,SAR 產品可能達數 GB,應先確認大小。託管 API 為盡力而為、無 SLA 且有速率限制。資料為 CC BY 4.0,衍生成果須保留 Umbra 署名。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Umbra open SAR archive,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Web executable,透過 Streamable HTTP。 遠端服務在工作區中設定後即可從網頁執行環境執行。

交給代理程式安裝

把這段提示詞貼上到 Claude Code、Codex、Cursor 等代理程式,或 SourceWeft 對話中。代理程式會讀取該伺服器的安裝指南,先向你展示發布者、端點和登入方式,經你同意後再把它新增到你的客戶端。金鑰不會寫進任何命令。

閱讀 https://sourceweft.com/mcp/io.github.reesehammer%2Fumbra-mcp/install.md,並按其中說明把這個 MCP 伺服器接入我的客戶端。修改任何設定之前,先告訴我它的發布者、端點和登入方式,等我確認。不要把 API 金鑰寫進命令或我會提交的檔案;問我金鑰應從哪裡取得。

檢視代理程式所依據的安裝指南

其他 MCP 客戶端

把它新增到你客戶端的 mcpServers 設定中。

{
  "mcpServers": {
    "umbra-open-sar-archive": {
      "type": "http",
      "url": "https://api.umbra-py.space/mcp"
    }
  }
}

README

umbra-py

[License] [Python] [CI] [codecov] [Docs]

Search, preview, load, and convert Umbra open SAR data.

Umbra publishes 16–25 cm SAR as CC BY 4.0 open data, but no search API — only a 17+ TB S3 bucket and a static STAC tree. umbra-py is that layer: search, preview, download, and analysis-ready arrays without the usual 500 lines of glue. A community STAC API (umbra serve) and MCP server sit on the same host, so pystac-client and Claude can query the archive with nothing installed.

📖 Docs: umbra-py.space · Showcase: browse the archive in the browser (no install) · Already listing the bucket? Replace your crawler (HTTP, pystac-client, or DuckDB over the weekly Parquet)

Status: v0.1.4. Discovery, download, xarray loading, SICD → geocoded COG, change/timescan composites, chips, a STAC API (umbra serve, with a community host), and an MCP server all ship. This is not an InSAR toolbox (phase is not preserved through convert). Not affiliated with Umbra Lab, Inc.

Hosted API (api.umbra-py.space): best-effort 99% monthly uptime, no SLA, 120 requests/minute, page size 10,000. Limits, CORS, and the parquet fallback.

Install

bash
pip install umbra-py              # core: search + download + metadatapip install "umbra-py[load]"      # + xarray / rasteriopip install "umbra-py[viz]"       # + quicklooks, maps, galleriespip install "umbra-py[convert]"   # + SICD → geocoded COGpip install "umbra-py[all]"       # convert + load + viz + export

Python 3.10+. Other extras (dask, serve, mcp, ai, langchain, llamaindex) are listed in the install guide.

Five minutes to a scene

Fetch the weekly catalog snapshot, then search and preview offline. A live walk of the bucket (umbra search without --local) works but is slow.

bash
pip install "umbra-py[viz,load]"umbra index fetchumbra search --local --area Centerfield --product GEC --limit 3umbra gallery --local --area Centerfield --limit 6 --out gallery.html --db
python
from umbra_py import CatalogIndex, to_xarray
with CatalogIndex.from_release() as index:    item = next(iter(index.search(area="Centerfield", product_types=["GEC"], limit=1)))
# Stream a downsampled window over HTTP — no multi-GB download. Needs [load].da = to_xarray(item, max_size=1024, db=True)print(item.summary())

If the snapshot is missing, the same search against the live bucket is UmbraCatalog().search(...) / umbra search --area Centerfield.

What you can do

More detail, options, and caveats live in the docs.

Search by bbox, place name, polygon, or Umbra task (area=). --local reads the snapshot; omit it to walk S3.

python
from umbra_py import UmbraCatalog
for item in UmbraCatalog().search(area="Centerfield", product_types=["GEC"], limit=5):    print(item.summary())

Preview without downloading the scene: umbra gallery, umbra quicklook <stac-url> --out scene.png --db, umbra view <stac-url> (full-res tiles), or umbra change --area Centerfield --out change.png.

Load a geocoded GEC into xarray or a GeoTIFF (to_xarray, to_geotiff, to_stack). Needs [load].

Convert a SICD to a north-up amplitude COG (sicd_to_geocoded_cog, umbra convert) — phase is discarded. Needs [convert]. Open products generally have no radiometric metadata, so --calibrate / --noise-model measured refuse rather than invent numbers. See limitations and the complex-product handoff.

Chip scenes into georeferenced ML tiles for SR / ATR-style benchmarks from open Umbra GEC/SICD: umbra chips --area Centerfield --out chips/. See the ISR training-set cookbook and Used in research.

Drive it from an agent. Copy-paste recipes for Claude Desktop and Claude Code: Connect Claude (MCP).

Zero-install remote MCP (no uvx):

bash
# Claude Codeclaude mcp add --transport http umbra https://api.umbra-py.space/mcp --scope user
json
{  "mcpServers": {    "umbra": {      "url": "https://api.umbra-py.space/mcp"    }  }}

Paste that JSON into Claude Desktop (claude_desktop_config.json). Claude Code needs "type": "http" on the same URL — see the MCP page.

Local stdio (server on your machine):

bash
uvx --from 'umbra-py[mcp]' umbra-mcp
json
{  "mcpServers": {    "umbra": {      "command": "uvx",      "args": ["--from", "umbra-py[mcp]", "umbra-mcp"]    }  }}

That command is published to the MCP registry as io.github.reesehammer/umbra-mcp. STAC for pystac-client / QGIS is https://api.umbra-py.space/ (not /mcp). docker compose -f deploy/docker-compose.yml up is the one-command self-host.

What the data looks like

AssetWhat it isUse it for
GECGeocoded cloud-optimized GeoTIFFMap-ready imagery. Start here.
CSIColor sub-aperture GeoTIFFQuick-look RGB, not a measurement
SIDDGeocoded detected image (NITF)Detected imagery in a standard format
SICDComplex slant-plane image (NITF). Open archive: RGAZIM/PFA.Phase-preserving downstream. Download; do not convert.
CPHDCompensated phase historyCustom formation outside umbra-py (download; do not convert). Not an image.

umbra-py downloads SICD/CPHD. umbra convert geocodes a SICD to amplitude and discards phase. It does not form interferograms or compute coherence. For a processor that needs the complex pixels, see Complex products (SICD/CPHD).

Data license & attribution

Umbra's imagery is CC BY 4.0. If you use or redistribute the data or derived products you must attribute Umbra. The copyright notice Umbra's terms require is quoted under Citing umbra-py. umbra-py also stamps this shorter line on its own outputs:

Contains Umbra open data, licensed under CC BY 4.0.

umbra-py itself is Apache 2.0 (LICENSE). The two licenses are independent and compatible.

Citing umbra-py

[DOI]

Cite all versions with the concept DOI 10.5281/zenodo.23676715 (Zenodo's Cite all versions? value). It resolves to the latest archived release. The v0.1.4 version DOI is 10.5281/zenodo.23676716. Machine-readable metadata lives in CITATION.cff (GitHub's Cite this repository button) and .zenodo.json (what Zenodo archives).

bibtex
@software{hammerstrom2026umbrapy,  author  = {Hammerstrom, Reese},  title   = {umbra-py},  year    = {2026},  version = {0.1.4},  doi     = {10.5281/zenodo.23676715},  url     = {https://github.com/reesehammer/umbra-py},  license = {Apache-2.0}}

Imagery is © Umbra Space, licensed CC BY 4.0. Umbra's terms require this copyright notice on or adjacent to adapted materials, with [YEAR] the year the image was first created:

SAR-derived data © [YEAR] Umbra Lab, Inc.

Also credit Umbra, link the license, and say if you changed the data. The open-data program is umbra.space/open-data.

Repo layout

PathRole
src/umbra_py/Package source
docs/Published user manual (mkdocs → umbra-py.space)
docs/schemas/Public JSON contracts (also in the wheel)
.github/TODO.mdMaintainer ledger of scoped-out follow-ups
deploy/Dockerfiles, docker-compose.yml, entrypoint
railway.tomlRailway Config-as-Code (dockerfilePath → deploy/Dockerfile.mcp)

Self-host: docker compose -f deploy/docker-compose.yml up (build context stays the repo root). More in docs/README.md and the deploy guide.

Community

Acknowledgements

Built on the SAR open-source community, including sarpy and Umbra's open data program. Not affiliated with or endorsed by Umbra Lab, Inc.

來源:README.md,提交 62ed4a8

工具

19

search_catalog

Search Umbra's catalog and return compact context cards. Filters (all optional, combine freely): ``bbox`` as ``[min_lon, min_lat, max_lon, max_lat]`` in WGS84 degrees; ``intersects`` as a GeoJSON polygon object (a ``Polygon`` / ``MultiPolygon`` geometry, or a ``Feature`` / ``FeatureCollection`` wrapping one) to keep only footprints intersecting it -- a tighter spatial filter than the rectangular ``bbox``, and mutually exclusive with ``bbox`` / ``place``; ``place`` as a free-text name geocoded to a bbox; ``area`` as a substring of the Umbra task (site) name (set ``fuzzy`` to match it loosely -- word-order- and punctuation-independent and typo-tolerant, resolved deterministically with no model call, so ``"beet piler"`` still reaches ``"Beet Piler - ND"`` and ``"utah centerfield"`` still reaches ``"Centerfield, Utah"``; set ``semantic`` instead to treat ``area`` as a plain-language *description* of a site whose name you don't know and resolve it to the closest task names by *meaning* via the prebuilt embedding index, so ``"grain storage north dakota"`` reaches ``"Beet Piler - ND"`` -- a query that shares no word with the label, which ``fuzzy`` cannot and should not fake; ``semantic`` and ``fuzzy`` are mutually exclusive, and the resolved task name is returned as ``resolved_area`` with the ranked candidates in ``semantic_matches`` so you can audit and retry with a different one, and ``min_score`` -- a cosine threshold in ``[0, 1]`` -- drops weak aliases, so a description that matches nothing confidently returns an empty result rather than an arbitrary top pick); ``start``/``end`` as acquisition-date bounds -- an ISO ``YYYY-MM-DD`` date, a bare year/month (``2024``, ``2024-03``), or a relative expression (``today``, ``yesterday``, ``3 months ago``, ``last month``), resolved deterministically with no model call; ``products`` to restrict to product types (any of

輸入參數endareabboxfuzzylimitlocalplacestartproductssemanticcanonicalmin_score另有 6 個

find_repeat_sites

Rank the archive's most repeat-imaged sites — where change detection has something to measure. The discovery step *before* every analysis verb. ``change`` / ``timescan`` / ``stack`` / ``pick_change_interval`` / ``narrate_change`` all answer *what* changed at a site, but each assumes the caller already knows *which* site to point them at. Umbra files every pass of an area under one task (site), so a site's coverage is just how many dated passes share its task; the sites with the most are exactly the ones where a time series exists to analyse. This tool ranks them, so ``find_repeat_sites → pick_change_interval → narrate_change`` is a complete chain a model can drive with no site known in advance — the deterministic answer to "where is there something to look at?" (the discovery moat; no model is called). Reach for this (or ``search_catalog(area=..., fuzzy=True)``) before ``semantic=True`` when the site name is roughly known. The filters scope the *pool* of acquisitions the ranking is computed over, and are the same ones ``search_catalog`` takes: ``bbox`` (``[min_lon, min_lat, max_lon, max_lat]`` WGS84), ``intersects`` (a GeoJSON polygon, mutually exclusive with ``bbox`` / ``place``), ``place`` (free-text, geocoded to a bbox), ``area`` (a task-name substring, loosened by ``fuzzy``), ``start`` / ``end`` date bounds, ``products`` (GEC / SICD / SIDD / CPHD), and the SAR property filters ``polarizations`` / ``min_incidence`` / ``max_incidence`` / ``max_resolution``. ``top`` caps how many sites are returned, and ``min_passes`` is how many passes a site needs to qualify (2 is the minimum a change composite can use; raise it to find only deeply-revisited series), counted on the depth ``rank_by`` measures -- raw dated passes by default, the usable (comparable) series' depth under ``rank_by="comparable"``. ``rank_by`` chooses the order: ``"passes"`` (the default) ranks by

輸入參數endtopareabboxfuzzylimitlocalplacestartrank_byproductsintersects另有 13 個

get_item

Return the full context card for one item. ``url`` is the JSON URL of an open-data STAC sidecar, a GEC/SICD (or other product) filename such as ``2025-05-17-17-43-46_UMBRA-08_GEC.tif``, or the acquisition stem ``2025-05-17-17-43-46_UMBRA-08``. A filename or stem is resolved through the local catalog index: the stem is matched against asset hrefs, which is what distinguishes ``sar-data/tasks/``, ``sar-data/task-data/``, and ``open-data/`` — the name itself does not. Zero matches is an error. More than one match lists the candidate STAC URLs; pass one of those. The hosted server resolves a filename or stem with the catalog index it already loaded. A local server does the same after ``umbra index fetch``. When the index contains a STAC URL, the indexed snapshot is returned — the same document ``search_catalog`` already answered from — rather than a live re-fetch that can disagree on asset filenames or product types. When the server is configured with a token (``$UMBRA_CANOPY_TOKEN``) and ``url`` is a bare acquisition id (no ``://``, and not a filename or stem), it is instead looked up in Umbra's authenticated commercial archive by a keyed STAC search — the retrieval complement to ``search_catalog`` over the paid catalog, since archive cards carry an ``id`` (not a fetchable sidecar URL) as their hand-off pointer. A filename or stem still resolves from the local open-data index when a token is set. On the public host a URL is fetched only when it is https on Umbra's public open-data bucket. Any other URL is refused before a request. A bare id that is not in the local index is refused the same way. The card (:meth:`UmbraItem.to_llm_context`) carries the id, ISO datetime, place, bbox, resolution, polarization *with the change-detection caveat*, the per-product-type explanations and asset URLs, and the mandatory attribution line — everything a model needs to reaso

輸入參數url必填

geocode_place

Resolve a free-text place name to a bounding box via Nominatim. Returns ``{"bbox": [min_lon, min_lat, max_lon, max_lat], "display_name": ...}`` so the agent can inspect the box before searching, or pass it straight to ``search_catalog``'s ``bbox``.

輸入參數query必填

index_stats

Report on the local catalog index, if one has been built or fetched. Lets a long-running agent decide whether searches will be instant (index present) or pay a live S3 walk, and how stale the snapshot is. ``end`` is the newest acquisition that is not ``datetime_suspect``. ``datetime_suspect_count`` is how many kept rows carry that flag. ``quarantined_future_count`` is how many source rows the last build dropped for a datetime more than a day ahead (they are not in the index). ``unique_captures`` is how many rows are the canonical copy of their collect; it equals ``items`` until republished copies have been linked.

無需輸入參數。

quicklook

Return a scene's quicklook PNG as an image block. Prefers a baked catalog preview (``preview="auto"``, the default) so a public host can show the radar scene without proxying Umbra COGs. **A baked preview is typically 512 px** (the published weekly sidecar). ``max_size`` applies only to a fresh ``preview="render"`` stream; when a cached thumbnail is smaller than requested, the caption says ``max_size`` was ignored *and* includes a JSON ``{"image": {source, width, height, requested_max_size, substituted}}`` sidecar. For a higher-resolution picture (typically 1024 px), run a local ``uvx --from 'umbra-py[mcp]' umbra-mcp`` server, or download the GEC href from ``get_item``. ``preview="baked"`` refuses rather than stream; ``preview="render"`` always streams (needs ``[viz]``, refused on ``umbra serve --public``).

輸入參數dburl必填assetpreviewmax_size

change_composite

Composite 2-3 passes of one site into a change image. Pass the STAC URLs of two or three acquisitions of the *same* site in time order. Colors encode change: bright green = signal appeared after the first date, magenta = signal vanished, grey = unchanged. Refuses to mix polarizations (HH vs VV are not comparable). Returns the image block plus a caption naming the color semantics and attribution -- and, when a pass carries no polarization metadata so same-polarization could not be *verified*, a structured caution text block naming that gap.

輸入參數dburls必填assetmax_size

timescan

Summarize a whole time series into one activity image. Pass the STAC URLs of a site's passes; the timescan encodes per-pixel temporal statistics so bright/colored areas are *where activity happened* over the series. Returns the image block plus attribution.

輸入參數dburls必填assetmax_size

stack_stats

Measure how much a site changed across its passes, as numbers. The quantitative counterpart to ``change_composite`` / ``timescan``: those return a picture of *where* change is, this returns the *how much*. Pass the STAC URLs of a site's passes (2 or more, any order); they are co-registered onto one shared grid and reduced to a per-pass statistics series plus a net baseline-to-latest record — mean/median/spread of each pass, the signed decibel change against the pass before it, the fraction of ground that moved past ``change_threshold_db``, and that fraction as an **area in km²**. Change is always reported in decibels (a ratio of backscatter is a difference on the log scale). The default ``crs="utm"`` puts the grid in the site's UTM zone so every cell covers the same ground and the area figures mean something; pass ``crs="EPSG:4326"`` for a lon/lat grid, and the areas come back ``None`` rather than wrong. ``extent="intersection"`` (the default) compares only ground every pass covers; ``"union"`` keeps all of it and compares per cell where two passes overlap. ``bbox`` (lon/lat ``[min_lon, min_lat, max_lon, max_lat]``) narrows the measurement to a sub-area, e.g. one facility inside the scene. ``blocks=N`` adds the *where* to the *how much*: the scene is cut into an N x N grid (6 is a good default; 0, the default, skips it) and the extra ``spatial`` key reports each block's own net change, a compass label and lon/lat centre to locate it by, and the consecutive pair of passes that block moved most between — plus ``peak_block`` and an ASCII ``grid_text`` heat-map of the net change. Ask for it whenever the question is *where on this site* something happened, or when a scene-wide mean looks small but the picture from ``change_composite`` shows an obvious hot spot: a change confined to one corner is averaged away scene-wide and stands out per block. ``block_series=True

輸入參數crsbboxurls必填assetblocksextentmax_sizeblock_seriesspeckle_filterspeckle_windowchange_threshold_db

stack_provenance

Check whether a site's passes are one measurement, before measuring them. ``stack_stats`` refuses a selection whose rasters were made by *different* ``umbra convert`` settings — a calibrated pass differenced against an uncalibrated one puts the difference between two conversions on the time axis and reports it as change on the ground. This is the question that refusal answers, asked ahead of it: it reads each acquisition's ``UMBRA_*`` conversion record straight from its raster header (kilobytes per pass, no pixels, no co-registration) and groups the selection by what its pixel values *are*. Returns ``agrees`` (whether ``stack_stats`` would accept the selection), ``groups`` largest-first — each with the conversion ``record`` its members share, their ``item_ids`` and the ``hrefs`` to re-run on — plus ``shared`` (the record they all agree on) when they agree, ``refusal`` (verbatim the error ``stack_stats`` would raise) when they do not, and ``unreadable`` for any source that could not be opened at all, which is an incomplete answer rather than a mixed one. Reach for it in two situations. **After** a ``stack_stats`` call fails with a provenance refusal: ``groups[0]["hrefs"]`` is the largest set of passes that *do* agree, so re-running ``stack_stats`` on those is a measurement rather than a guess — the refusal itself cannot name that subset. And **before** measuring a long series you did not assemble yourself, since the check costs a header read per pass and saves the whole cube when the answer is no. A series of Umbra's published products as they ship (the common case) agrees trivially: every pass reads as ``"(unrecorded)"``, which is one value, so ``agrees`` is true and ``shared`` is empty. **No model is called.**

輸入參數urls必填asset

pick_change_interval

Scan a site's whole series and name the two passes worth narrating. The deterministic first half of the "watch a site over time" story, and the step that turns a wall of passes into an answer. Given the STAC URLs of a site's passes (2 or more, any order), it co-registers them into a ``to_stack`` cube, reduces it with ``stack_stats``, and returns the *one* consecutive pass-pair whose measured change stands **furthest clear of the speckle detection floor** — the pair a reader should look at first. No model is called: a number picks the frames (the determinism boundary applied to frame selection), so the choice is reproducible and safe to quote. Why this exists as its own tool: ``narrate_change`` reads a *pair* of passes, but a site has many, and "which two?" is a measurement question, not a model one — a picture past three dates encodes nothing a model can separate, so the pair has to be chosen before the model is called. This answers it. The returned ``urls`` are the two chosen passes in time order, ready to hand straight to ``narrate_change`` (or ``change_composite`` to see them): the two tools chain into scan → narrate with no server and no model in the selection. Returns ``selected_interval`` (the interval's ``earlier_id`` / ``later_id``, their datetimes, the ``changed_fraction`` and signed ``mean_delta_db``, the cube's ``false_alarm_fraction`` speckle floor, the ``excess`` of the change over that floor, and ``stands_clear`` — whether the change cleared the floor by a usable margin), ``urls`` (the earlier then the later pass's STAC URL), and the license/attribution. When ``stands_clear`` is false the series' own largest change is still inside the speckle, so the pair is offered but the reader is warned the difference may be interference rather than change. ``selected_interval`` is ``None`` (and ``urls`` empty) when the series has fewer than two comparabl

輸入參數crsurls必填assetextentmax_sizechange_threshold_db

download_asset

Download one asset of an item to local disk, gated by a size check. SAR products can be multiple GB, so this is a two-step handshake: call it first with ``confirm=False`` (the default) to get the byte size without downloading, then again with ``confirm=True`` to fetch it. On a local or stdio server, ``confirm=True`` returns ``{asset, path, bytes}``. ``confirm=False`` returns a size-and-hint object and does not write a file. On a public host (``umbra serve --public``, COG streaming off), ``confirm=True`` does not transfer the file. It returns a link plan: ``mode`` ``"link"``, ``downloaded`` false, ``asset``, ``filename`` (a basename), the direct public ``href``, ``bytes``, and ``how_to_fetch``. When the href is https on the public open-data bucket, ``how_to_fetch`` is ``curl -L -C - -o <filename> <href>`` and ``umbra download ITEM --asset ASSET --dest DIR``. ``bytes`` is the STAC ``file:size`` or ``size`` when that is a non-negative integer; otherwise the host HEADs that href for ``Content-Length``, with no redirects and no retries. A href that is not on that bucket is not requested: ``how_to_fetch.curl`` and ``how_to_fetch.umbra`` are null, ``bytes`` is null, and ``note`` says the commands were omitted. A 404 or 410 from an allowlisted HEAD raises. Any other HEAD failure, including a full quick-request slot, leaves ``bytes`` null and still returns the plan. The hosted server never transfers the file. A local ``uvx --from 'umbra-py[mcp]' umbra-mcp`` server downloads to your own disk. ``confirm=False`` on this host returns the same size-and-hint object and does not write a file. It HEADs for ``Content-Length`` only when the href is https on the public open-data bucket, with no retries, and it does not follow redirects. A 404 or 410 raises, and so does any other non-redirect HEAD error. A redirect leaves ``bytes`` null. A href outside the bucket is not requeste

輸入參數url必填assetconfirmdest_dir

watch_site

Report only the acquisitions **new** since the last check of this site. SAR's value for monitoring is its cadence, so the natural workflow is *standing*: run the same search each time and act only on what changed. This tool packages that idempotent delta — call it in one turn, come back a day (or a session) later and call it again, and it returns just the passes published in between, not the whole list again. The scheduler is you: ask the agent to check the site, and it reports the delta. Define the site with the same filters as ``search_catalog`` — ``place`` (geocoded to a bbox), ``area`` (task/site-name substring, loosened by ``fuzzy``), ``bbox``, ``products``, and ``start``/``end`` date bounds. The watch is identified by a stable ``name`` derived from those filters (pass an explicit ``name`` to run several independent watches over the same site); ``reset=True`` re-establishes the baseline, reporting everything as new. State persists in the local catalog index's ``meta`` table (created on first use), so a watch survives across sessions with no extra setup. ``local`` selects the search backend exactly as in ``search_catalog`` — leave it unset to use the on-disk index when present and a live S3 walk otherwise; for true monitoring a live walk (``local=false``) catches freshly published passes. **No model is called** — this is pure set arithmetic over the deterministic search — and the returned ``new_items`` are context cards ready to hand straight to ``change_composite`` / ``timescan``, closing the standing-analyst loop (new pass → composite → describe) without leaving the conversation.

輸入參數endareabboxnamefuzzylocalplaceresetstartproducts

find_similar

Find archived scenes that **look like** the acquisition at ``url``. This is the one search that lives in the pixels, not the metadata: where ``search_catalog`` filters by date/bbox/task-name, this renders the query item's quicklook, embeds it, and ranks the pre-embedded scene index by visual (cosine) similarity — "find scenes that look like this flooded field / crowded berth / runway". The query item is excluded from its own results. Requires a scene-embedding index built ahead of time with ``umbra embed build`` (a sidecar ``catalog.embed.db`` beside the catalog index) and a user-supplied multimodal embedding key (``OPENAI_API_KEY``, optionally ``OPENAI_BASE_URL`` / ``UMBRA_SCENE_EMBED_MODEL``) — the only model call is turning the query image into a vector; ranking is deterministic. ``asset`` picks which product's quicklook to embed (default ``GEC``; match how the index was built); ``model`` must match the index's embedding model. Returns the ranked matches as compact records (each with the acquisition's ``href``, so hand it to ``get_item`` / ``quicklook`` / ``change_composite`` next) plus the attribution line.

輸入參數url必填assetmodeltop_kmin_score

find_similar_text

Find archived scenes matching a plain-language ``query`` over their imagery. Text-to-scene search: embeds ``query`` ("ships at a berth", "a flooded field") and ranks the stored *image* vectors by cosine similarity. It only works when the index was built and this query is embedded with the **same** joint CLIP-family model whose text and image encoders share a vector space (a dimension mismatch is reported as an error; ``model`` selects it). Requires the same prebuilt ``catalog.embed.db`` (``umbra embed build``) and embedding key as ``find_similar``; the only model call is turning the text query into a vector. Returns the ranked matches as compact records (each with the acquisition's ``href`` for ``get_item`` / ``quicklook``) plus attribution.

輸入參數modelquery必填top_kmin_score

describe_scene

Return a SAR-literate reading of the scene at ``url``. The picture and the metadata card are produced deterministically; a model only interprets them. How that model is reached depends on whether this process holds a vision key: - **No key** (the public community host): this tool does **not** call a vision model. It returns the PNG plus a reading kit (SAR rules, the metadata card, the JSON schema). Produce the JSON, then call :func:`stamp_description` — that is the validation boundary (provenance-stamped ``{summary, observed_features, confidence, caveats}``). Until you stamp it, your prose is not pipeline output. A baked preview is typically 512 px; the kit names the size and that a local server can stream a higher-resolution GeoTIFF. - **Key configured** (local stdio): sends the picture to that vision model, validates through ``parse_description``, and returns the stamped object directly. The packaged SAR rules are the value over just looking at ``quicklook``: brightness is backscatter not sunlight, speckle is not structure, a dark patch may be radar shadow not water, one frame is not change. ``preview`` defaults to ``"auto"``: a baked catalog preview if this server has one, else a fresh render. ``"render"`` is refused on the public host.

輸入參數dburl必填assetmodelpreviewmax_size

narrate_change

Return a grounded reading of *what changed* between passes. Sibling of :func:`describe_scene`. The composite and the per-block dB grid are produced deterministically; a model only narrates change those numbers support. Pass the STAC URLs in time order; mixed polarizations are refused. This tool **streams Umbra COGs** to build the composite, so a public community host refuses it (use a local ``uvx --from 'umbra-py[mcp]' umbra-mcp`` server, or describe each pass with :func:`describe_scene` / :func:`quicklook` on baked previews). On a local server: - **No vision key:** returns the composite as an MCP image block plus a reading kit (SAR change primer, the dB grid, the JSON schema). **You** (the client's model) narrate, grounded in the numbers. - **Key configured:** sends picture + grid to that vision model, validates through ``parse_narration``, and returns a provenance-stamped ``{summary, changes[], confidence, caveats[], change_stats}`` object.

輸入參數dburls必填assetmodelmax_size

stamp_description

Validate a client-produced scene reading and stamp provenance. This is the interpretation boundary for the no-key kit path: you read the picture ``describe_scene`` returned, produce ``{summary, observed_features, confidence, caveats}``, and pass it here. The library checks the shape, stamps CC-BY and the AI-interpretation note (the model never sets those), and — when ``image`` is the record from the kit — appends a deterministic caveat if the picture was a smaller baked preview. Until this returns, the reading is unvalidated prose, not pipeline output.

輸入參數assetimagemodelitem_idreading必填

stamp_narration

Validate a client-produced change narration and stamp provenance. Sibling of :func:`stamp_description` for the no-key ``narrate_change`` kit. Pass the JSON you produced plus the ``change_stats`` grid from the kit so the stamped object carries the numbers the prose was grounded in.

輸入參數assetmodelreading必填item_idschange_stats

版本歷史

3
  1. v0.1.4最新Oct 29, 2026
  2. v0.1.3Oct 16, 2026
  3. v0.1.2Sep 16, 2026

評分

已滿足適用檢查項的 100%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通必需25 分
  • 已宣告認證方式必需10 分
  • 已列出工具必需15 分
  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分