From b72eb7e4a6e8ac4d479406b5021d08aff0bb061c Mon Sep 17 00:00:00 2001 From: jepegit Date: Tue, 22 Sep 2026 12:42:24 +0200 Subject: [PATCH] =?UTF-8?q?Document=20MCP=20find=5Fcells=20and=20the=20SAL?= =?UTF-8?q?=2010=E2=80=9315=20agent=20prompt.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tool lives in cellpy-mcp; this repo tracks #1080 and the docs agents need to discover it. Co-authored-by: Cursor --- .../03-solved-issues/issue1080_original.md | 31 +++++++++ .../03-solved-issues/issue1080_plan.md | 69 +++++++++++++++++++ .../03-solved-issues/issue1080_status.md | 6 ++ AGENTS.md | 1 + HISTORY.md | 3 + docs/getting_started/agent_prompts.md | 12 ++++ docs/getting_started/agents.md | 4 ++ docs/getting_started/mcp.md | 2 +- 8 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 .issueflows/03-solved-issues/issue1080_original.md create mode 100644 .issueflows/03-solved-issues/issue1080_plan.md create mode 100644 .issueflows/03-solved-issues/issue1080_status.md diff --git a/.issueflows/03-solved-issues/issue1080_original.md b/.issueflows/03-solved-issues/issue1080_original.md new file mode 100644 index 00000000..502d6d5c --- /dev/null +++ b/.issueflows/03-solved-issues/issue1080_original.md @@ -0,0 +1,31 @@ +# Issue #1080: MCP find_cells tool (no silent raw crawl) + +Source: https://github.com/jepegit/cellpy/issues/1080 + +## Original issue text + +## Context + +Part of epic #1074 (agent summary-plots SAL cells 10–15 from local files). Stage 2: the library can find (`filefinder.find_by_project`, #1076); the agent still cannot. Add one MCP tool that lists matches from configured dirs and **stops**. Existing `load_cell` / `collect` / `render` finish the plot. No raw crawl in this stage. + +## Scope + +In `cellpy-mcp`, add a tool (suggested `find_cells`) that calls `filefinder.find_by_project`. Inputs: `project`, `number_min`, `number_max`, `kind` defaulting to `cellpy`. Output: handles/facts only — count, names, numbers, paths the sandbox may read. + +If `kind=cellpy` and the list is empty, return `{found: 0, offer_raw: true}` (or equivalent) and **do not** search `rawdatadir`. If `cellpydatadir` is a remote URI, say so (`remote: true`, reason) rather than pretending the sandbox can walk it. + +Update `docs/getting_started/agents.md` / MCP chapter and add a short agent-prompt snippet for “summary-plot SAL 10–15” that uses find → load → collect → render. + +Implement in the `cellpy-mcp` repo; this GitHub issue stays the tracker on `jepegit/cellpy`. + +## Acceptance criteria + +- MCP `find_cells(project="SAL", 10, 15)` returns the matching local cellpy files, or a structured empty + `offer_raw` — never a raw listing. + +Goal: MCP `find_cells(project="SAL", 10, 15)` returns the matching local cellpy files, or a structured empty + `offer_raw` — never a raw listing. + +Model: default + +Depends on: #1076 + +Part of epic #1074. diff --git a/.issueflows/03-solved-issues/issue1080_plan.md b/.issueflows/03-solved-issues/issue1080_plan.md new file mode 100644 index 00000000..3a4be372 --- /dev/null +++ b/.issueflows/03-solved-issues/issue1080_plan.md @@ -0,0 +1,69 @@ +# Issue #1080 plan + +## Goal + +An MCP client can call `find_cells(project="SAL", 10, 15)` and get matching +local `.cellpy` files, or `{found: 0, offer_raw: true}` — never a raw listing. +Existing `load_cell` / `collect` / `render` finish Scenario 1. + +## Constraints + +- Two repos: tool in `cellpy-mcp`; docs + this tracker on `jepegit/cellpy`. +- Do not search `rawdatadir` when `kind` is `cellpy` (even if empty). +- Sandbox stays local-only. Remote `cellpydatadir` → `remote: true` + reason, + no pretend walk. Remote *load* is Stage 3 / Later. +- Handles/facts only — no file bytes. +- `find_by_project` is on cellpy `master` (#1079) but not a released pin yet. + Do not bump `cellpy>=` to an unreleased version. + +### Prior art + +- `cellpy.filefinder.find_by_project` (#1076) — call it; do not re-walk. +- MCP `list_cells` is **session** only (already loaded). New tool is disk find. +- `sandbox.default_roots` / `_is_local_dir` — reuse for remote honesty. +- `tests/test_cell_tools.py` `drive` harness — same pattern. +- Agent prompts live in cellpy `docs/getting_started/agent_prompts.md` (#1064). + +## Approach + +**cellpy-mcp** (branch `1080-mcp-find-cells` on that repo): + +1. Tool `find_cells(project, number_min, number_max, kind="cellpy")`. +2. If `kind` not in `cellpy`/`raw` → `Refused`. +3. If `kind=cellpy` and `config.paths.cellpydatadir` is a remote URI → + `{found: 0, remote: true, reason: "…"}` and stop. +4. Else call `filefinder.find_by_project(...)`. If the attribute is missing + (old cellpy), `Refused` naming #1076 / `find_by_project`. +5. Filter returned paths through `sandbox.resolve` (drop anything outside + roots; do not crash the whole list). +6. Empty + `kind=cellpy` → `{found: 0, offer_raw: true, cells: []}`. + Hits → `{found: N, offer_raw: false, cells: [{name, number, path}]}`. + `kind=raw` may list raw (Stage 3 will add `needs_metadata`); this stage + still must not auto-switch from cellpy-empty to raw. + +**cellpy** (this worktree): + +- `docs/getting_started/mcp.md` — document `find_cells`. +- `docs/getting_started/agent_prompts.md` — SAL 10–15: find → load → collect + → render (`` + latest URL if that page’s convention + requires it). +- One line in `agents.md` / `AGENTS.md` if the MCP tool list is mirrored. + +## Files to touch + +- `cellpy-mcp/src/cellpy_mcp/cells.py` — register `find_cells` +- `cellpy-mcp/tests/test_cell_tools.py` — empty/`offer_raw`, hits, remote +- `docs/getting_started/mcp.md`, `agent_prompts.md`, maybe `agents.md` / `AGENTS.md` +- `HISTORY.md` (cellpy close); cellpy-mcp changelog if they have one + +## Test strategy + +- cellpy-mcp: `uv run pytest` (existing essential mark on cell-tool tests). + Monkeypatch `find_by_project` so tests do not need a released cellpy. +- cellpy: no new library tests; docs checker if the new prompt gets an + `agent-doc` comment (`00-tools/check_rtd_latest_links.py` after zensical). + +## Open questions + +None that block. `kind=raw` on this tool is allowed but unused by Scenario 1; +Stage 3 will extend the empty-cellpy dialogue. diff --git a/.issueflows/03-solved-issues/issue1080_status.md b/.issueflows/03-solved-issues/issue1080_status.md new file mode 100644 index 00000000..58129aef --- /dev/null +++ b/.issueflows/03-solved-issues/issue1080_status.md @@ -0,0 +1,6 @@ +# Issue #1080 status + +- [x] Done + +`find_cells` in cellpy-mcp (empty → `offer_raw`, remote honesty). +Docs + SAL 10–15 prompt on cellpy. diff --git a/AGENTS.md b/AGENTS.md index 8eefe6cb..4f2c2e4c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -370,6 +370,7 @@ Quick facts: - Find by project + number range: `from cellpy import filefinder` then `filefinder.find_by_project("SAL", 10, 15, kind="cellpy")` (or `kind="raw"`). Uses `cellpydatadir` / `rawdatadir`; empty list if none match. + MCP: `find_cells` (empty cellpy → `offer_raw`, no silent raw crawl). - Metadata peek (no frames): `cellpy.read_meta(path)` → dict with `cell` / `tests`. - Ingestion form fields: `cellpy.instrument_meta_schema(instrument)` → `fields` / `units`. - Frames: `c.data.raw` / `.steps` / `.summary`; columns via `c.schema.*`. diff --git a/HISTORY.md b/HISTORY.md index 1b78c59e..1aa8d3f6 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -2,6 +2,9 @@ ## [Unreleased] +* Docs: MCP `find_cells` (project + number range; empty cellpy offers raw, + never a silent crawl) and a SAL 10–15 agent prompt. (#1080) + * `filefinder.find_by_project` lists cellpy or raw files by project token and inclusive number range. (#1076) diff --git a/docs/getting_started/agent_prompts.md b/docs/getting_started/agent_prompts.md index c4734193..307fd52b 100644 --- a/docs/getting_started/agent_prompts.md +++ b/docs/getting_started/agent_prompts.md @@ -88,6 +88,18 @@ Use `c.schema` for column names, not hardcoded header strings. Follow https://cellpy.readthedocs.io/en/latest/getting_started/agents/. ``` +## How to summary-plot SAL cells 10–15 + + +```text +Using cellpy MCP, find project SAL cells numbered 10–15 (names like +_SAL), load them, and write a summary plot. Call find_cells +first (kind=cellpy). If found is 0 and offer_raw is true, ask before +searching raw — do not crawl rawdatadir yourself. Then load_cell, collect +kind=summary with a plot family, and render. Follow +https://cellpy.readthedocs.io/en/latest/getting_started/mcp/. +``` + ## How to fetch the agent docs map diff --git a/docs/getting_started/agents.md b/docs/getting_started/agents.md index 4a074a6d..efa5cd26 100644 --- a/docs/getting_started/agents.md +++ b/docs/getting_started/agents.md @@ -128,6 +128,10 @@ hits = filefinder.find_by_project("SAL", 10, 15, kind="cellpy") raw_hits = filefinder.find_by_project("SAL", 10, 15, kind="raw") ``` +MCP equivalent: `find_cells` (same arguments). Empty `kind=cellpy` returns +`offer_raw: true` and does not search raw. See +[Connect an agent IDE to cellpy](mcp.md). + ## Core mental model for app code ```text diff --git a/docs/getting_started/mcp.md b/docs/getting_started/mcp.md index 428663c7..da5981af 100644 --- a/docs/getting_started/mcp.md +++ b/docs/getting_started/mcp.md @@ -79,7 +79,7 @@ the last line. cellpy mcp check --client cursor ``` - Success prints the handshake, the tool names (`load_cell`, + Success prints the handshake, the tool names (`find_cells`, `load_cell`, `search_api`, …) and how many instruments the server can see. A failure names the cause: an interpreter path that does not exist, a server that printed to stdout, or one that died (its last stderr line is quoted).