aminghadersohi opened a new pull request, #44694:
URL: https://github.com/apache/superset/pull/44694

   ### SUMMARY
   
   Adds `get_catalog`, a read-only MCP tool. It returns a small, paged catalog 
of the databases, datasets, charts, or dashboards the **calling user** can see. 
Assistants often need an inventory ("what dashboards are there?") without 
calling the full list tools again and again. The list tools also return heavy 
fields for this purpose, such as dataset SQL, `extra`, and metrics.
   
   **Contract**
   
   - Request (wrapped in `request`, like other tools): `asset_type` ∈ 
{`databases`, `datasets`, `charts`, `dashboards`}; `page_size` (default 50, max 
100); `cursor` (opaque, optional); `search` (case-insensitive name substring, 
optional).
   - Response: `{asset_type, items: [{id, uuid, name, description, changed_on, 
url}], next_cursor, restricted, truncated, message}`.
   
   **Design and security properties**
   
   - **Same visibility as the list tools.** Rows are read through `DAO.list`, 
which always applies the model's `base_filter` (`DatabaseFilter`, 
`DatasourceFilter`, `ChartFilter`, `DashboardAccessFilter`). Soft-deleted rows 
are excluded by the global listener.
   - **Per-asset-type RBAC.** Each asset type checks `can_read` on its class 
(`Database`, `Dataset`, `Chart`, `Dashboard`) plus token scopes, following the 
`get_schema` pattern. A denial raises the generic permission error.
   - **`privacy.py` honored.** Users without data-model metadata access get 
`restricted: true` with no items for `databases` and `datasets`, rather than an 
error. Charts and dashboards still list, because they expose no data-model 
fields.
   - **Strict field allowlist.** Only `id`, `uuid`, the name column, 
`description`, `changed_on`, and `slug` (dashboards, used for the link) are 
selected from the database. The response models use `extra="forbid"`. SQL, 
`extra`, template params, metric expressions, connection info, owners, and row 
data are never loaded or returned.
   - **Live, per call, no caching.** Nothing is stored. The tool is added to a 
new `ALWAYS_EXCLUDED_TOOLS` set that `_build_caching_settings` always merges 
into the response-cache exclusions, even if an operator enables the shared 
response cache. A revoked grant therefore takes effect on the next call.
   - **Bounded output.**
     - `page_size` must be at most 100 (a validation error otherwise).
     - Names are capped at 256 characters and descriptions at 500.
     - Each response is kept at or under 32 KiB of JSON by moving trailing 
items to the next page; `truncated` reports this.
   - **Stable pagination.** `next_cursor` is an opaque keyset cursor (last seen 
id). It is tied to the asset type and search term, and a mismatched or 
malformed cursor is rejected. Pages stay complete and free of duplicates when 
assets are added or removed between reads. The cursor grants no access: every 
page is filtered again for the current caller.
   - **Dataset scope.** In deployments that configure 
`MCP_DATASET_ROLE_ALLOWLIST`, the tool is not in the dataset-scoped tool list, 
so it is refused. This fails closed.
   
   Chart→dataset relationships are intentionally left out, so no possibly stale 
relationship data is returned.
   
   ### BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
   
   N/A (new MCP tool).
   
   ### TESTING INSTRUCTIONS
   
   ```bash
   pytest tests/unit_tests/mcp_service/catalog
   pytest tests/unit_tests/mcp_service
   ```
   
   `tests/unit_tests/mcp_service/catalog/tool/test_get_catalog.py` has 40 
tests. They run the real DAO base filters on in-memory SQLite, with RBAC 
enabled, and simulate roles at the security-manager grant lookups. Coverage:
   
   - **Roles:**
     - Admin sees every asset.
     - A Gamma-like user with a datasource-level grant on one table sees only 
that table's dataset, charts, and dashboards.
     - A user without data-model access gets a `restricted` page for databases 
and datasets, and still gets filtered charts and dashboards.
     - A missing class permission is denied.
   - **Revocation:** a grant removed between two calls disappears on the second 
call, for every asset type. Losing data-model access flips the page to 
`restricted`.
   - **Cross-user isolation:** an admin read never affects a following 
restricted read. A cursor issued to an admin gives another user nothing extra.
   - **Allowlist:** SQL, `extra`, template params, metric expressions, chart 
params, dashboard JSON, and the SQLAlchemy URI are planted with marker values, 
and none of them appear in the output. Item keys are a subset of the allowlist, 
and unknown request or response fields are rejected.
   - **Bounds:**
     - `page_size` values of 0, 101, and 1000 are rejected, including over MCP.
     - 150 datasets with 5,000-character descriptions stay at or under 32 KiB 
per page, with none lost or duplicated.
     - Cursor pages over 250+ rows stay complete and in order when a row is 
deleted and another added mid-pagination.
     - Tampered or mismatched cursors are rejected.
   
   Mutation checks were run locally. Each of the following makes the 
corresponding tests fail:
   
   - bypassing the DAO base filter
   - adding a per-process page cache
   - dropping the privacy check
   - dropping the RBAC check
   - dropping the byte bound
   
   The tool inventory budget, registration metadata, and caching tests are 
updated.
   
   ### ADDITIONAL INFORMATION
   
   - [ ] Has associated issue:
   - [ ] Required feature flags:
   - [ ] Changes UI
   - [ ] Includes DB Migration (follow approval process in 
[SIP-59](https://github.com/apache/superset/issues/13351))
     - [ ] Migration is atomic, supports rollback & is backwards-compatible
     - [ ] Confirm DB migration upgrade and downgrade tested
     - [ ] Runtime estimates and downtime expectations provided
   - [x] Introduces new feature or API
   - [ ] Removes existing feature or API
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to