@chrischall/gemini-mcp 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "metadata": {
9
9
  "description": "MCP server for Google Gemini image generation and editing — generate and edit images via the Gemini API",
10
- "version": "1.0.2"
10
+ "version": "1.0.3"
11
11
  },
12
12
  "plugins": [
13
13
  {
@@ -15,7 +15,7 @@
15
15
  "displayName": "Gemini Images",
16
16
  "source": "./",
17
17
  "description": "Generate and edit images with Google Gemini image models (Nano Banana / Nano Banana Pro) via natural language prompts",
18
- "version": "1.0.2",
18
+ "version": "1.0.3",
19
19
  "author": {
20
20
  "name": "Chris Hall"
21
21
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "gemini-mcp",
3
3
  "displayName": "Gemini Images",
4
- "version": "1.0.2",
4
+ "version": "1.0.3",
5
5
  "description": "MCP server for Google Gemini image generation and editing — generate and edit images via the Gemini API",
6
6
  "author": {
7
7
  "name": "Chris Hall",
package/README.md CHANGED
@@ -18,6 +18,7 @@ Developed and maintained by AI (Claude Code).
18
18
  | `GEMINI_INPUT_DIR` | No | Directory to resolve bare input-image filenames against (so `images: ["foo.jpg"]` works) |
19
19
  | `GEMINI_TIMEOUT_MS` | No | Upstream request timeout in ms (default: `60000`, or `120000` for `image_size: "4K"`); each generation tool also takes a per-call `timeout_ms` |
20
20
  | `GEMINI_HEARTBEAT_MS` | No | Progress-notification cadence in ms while a generation runs (default: `10000`; `0` disables) — keeps MCP hosts that reset their timeout on progress from timing out long generations |
21
+ | `GEMINI_CHAIN_RETRY_MS` | No | How long to wait out interactions-store lag when a chained call 404s (default: `120000`; `0` disables retrying) |
21
22
 
22
23
  ### Long generations and client timeouts
23
24
 
@@ -28,6 +29,39 @@ anyway: the image is written to the output dir, `gemini_interact` also writes an
28
29
  `<image>.json` sidecar recording the `interaction_id`, and `continue_last: true` resumes the
29
30
  interaction the lost response belonged to.
30
31
 
32
+ ### When a chained call 404s
33
+
34
+ A 404 on a request carrying `previous_interaction_id` is **not** proof the chain expired. The
35
+ only 404 body observed live is generic — `"Requested entity was not found."` — and never names
36
+ *which* entity. An unknown or renamed **model id**, and an expired Files API **`files/…` uri**
37
+ (~48h TTL), return exactly the same thing. So the server no longer asserts a cause it can't
38
+ establish: the upstream text is surfaced verbatim, and `gemini_interact` runs an experiment to
39
+ find out which it was.
40
+
41
+ Most often the id isn't missing at all — it just isn't *visible* yet. The interactions store is
42
+ eventually consistent, and a freshly created id can 404 while the same id resolves fine minutes
43
+ later; heavy turns (4K, Pro, `thinking_level: high`) are the likeliest to hit it, which is
44
+ exactly the turn you most want to chain from. So a chained 404 is retried with exponential
45
+ backoff for up to **120s** (`GEMINI_CHAIN_RETRY_MS`) before anything is declared broken. The
46
+ 404 generates nothing and isn't billed, so the wait costs only time.
47
+
48
+ After that budget is spent, the tool looks up that id's sidecar, re-attaches the image it
49
+ produced, and re-issues the request **without** the chain:
50
+
51
+ - **The re-issue succeeds** → the chain really was the problem, and you get your image anyway,
52
+ reported as `chain_recovered: { expired_interaction_id, reanchored_on }`. The 404'd attempt
53
+ generates nothing, so this costs the one generation you'd have paid for re-anchoring manually.
54
+ - **The re-issue 404s too** → the interaction id was never the cause. You get told exactly that,
55
+ with the upstream text, and pointed at the model id and any `files/…` uri instead of being
56
+ sent to chase an interaction that was fine all along.
57
+ - **No sidecar matches the dead id** → the original error, rather than a guess. Re-anchoring on
58
+ the wrong picture would silently corrupt the edit.
59
+
60
+ Separately, `continue_last` no longer dies with the server process: with no in-memory id it
61
+ resumes from the newest `<image>.json` sidecar in the output dir and reports
62
+ `continued_from_sidecar: true`. That case was never an expired chain at all — the interaction
63
+ was alive upstream the whole time; only our memory of its id was gone.
64
+
31
65
  For hosts whose timeout can't be tamed (e.g. Claude Desktop, a fixed ~30s cap that ignores
32
66
  progress), two guards make re-issuing safe and unnecessary:
33
67