Skip to content

feat(mcp): wire server tools to FlowWorker and implement download/recording in daemon - #228

Merged
ffroliva merged 7 commits into
ffroliva:developfrom
C1ph3r404:develop
Jun 30, 2026
Merged

ffroliva merged 7 commits into
ffroliva:developfrom
C1ph3r404:develop

Conversation

@C1ph3r404

Copy link
Copy Markdown
Contributor

Summary

  • Wired MCP image/video generation tool placeholders to actual FlowWorker execution path via new _run_generation_task helper.
  • Hooked up OperationRecorder and file download logic in FlowWorker.process_task to ensure generated assets are saved locally and recorded to SQLite.
  • Refactored FlowWorker to reuse its active DataStore connection with OperationRecorder instead of creating new instances.
  • Added support for profile pinning via --profile / GFLOW_CLI_PROFILE env var in MCP command.
  • Refactored Chrome cookie snapshot decryption to avoid KeyError on Linux/macOS by only passing Local State path on Windows and handling keyring connection errors.
  • Added 9 new integration tests for the wired MCP tools flow and updated worker mocks/tests to conform to the database schema.

Validation

  • Focused tests added or updated for behavior changes
  • Documentation updated or explicitly marked not applicable
    -uv run python scripts/ci/check_doc_links.py
  • uv run ruff check src tests
  • uv run pyright src
  • Relevant pytest command: uv run pytest tests/worker/test_daemon.py tests/mcp/test_tools_wired.py -v (and full suite validation with uv run python -m pytest -q --cov=gflow_cli)

1. Fix Playwright chrome channel validation in `browser_manager.py`:
   - `is_chrome_available()` was returning True for system Chromium, causing Playwright to request `channel="chrome"` which expects real Google Chrome.
   - Replaced with a strict check against Playwright's actual expected Chrome paths so it falls back to bundled Chromium correctly.

2. Fix image generation settings selector in `ui_automation.py`:
   - `GEN_SETTINGS_BUTTON_SELECTORS` lacked the `aria-haspopup='menu'` attribute and missed the `crop_original` icon.
   - Without it, the selector failed to find the panel after switching to image mode, leaving Flow's default generation count (2) active while the CLI only expected 1.

3. Warn on silent extra image generation in `client.py`:
   - If Flow generates more images than requested (e.g. 2 instead of 1 due to the settings panel miss), `_drive_image_generation` silently discarded the extras.
   - A warning is now logged showing the extra media IDs, alerting users to the extra credit consumption while preserving the single-image API contract.
…ording in daemon

- Wired MCP image/video generation tool placeholders to actual FlowWorker execution path via new `_run_generation_task` helper.
- Hooked up `OperationRecorder` and file download logic in `FlowWorker.process_task` to ensure generated assets are saved locally and recorded to SQLite.
- Refactored `FlowWorker` to reuse its active `DataStore` connection with `OperationRecorder` instead of creating new instances.
- Added support for profile pinning via `--profile` / `GFLOW_CLI_PROFILE` env var in MCP command.
- Refactored Chrome cookie snapshot decryption to avoid KeyError on Linux/macOS by only passing Local State path on Windows and handling keyring connection errors.
- Added 9 new integration tests for the wired MCP tools flow and updated worker mocks/tests to conform to the database schema.
…ffroliva-develop

# Conflicts:
#	src/gflow_cli/api/client.py
#	src/gflow_cli/api/transports/ui_automation.py
#	src/gflow_cli/browser_manager.py
* **ui_automation.py**: Kept the clean `GEN_SETTINGS_BUTTON_SELECTORS = MODE_SWITCH_TRIGGER_SELECTORS` alias from the `develop` branch to eliminate duplicate button selectors.
* **client.py**: Maintained the module-level `logger.warning`, kept detailed docstrings/hints, and removed obsolete local logger imports and instantiations.
* **browser_manager.py**: Preserved enhanced docstrings, strict Linux Chromium path resolutions (`/opt/google/chrome/chrome`), and the correct logic returning `True` over `bool(env_override)`.
@C1ph3r404
C1ph3r404 requested a review from ffroliva as a code owner June 30, 2026 06:58
@github-actions github-actions Bot added external-contribution Pull request from a non-maintainer or fork needs-copilot-review Ask GitHub Copilot for advisory code review needs-maintainer-review Requires maintainer review before merge labels Jun 30, 2026
@github-actions

Copy link
Copy Markdown

Thanks for the contribution. This PR has been marked as an external contribution and routed for maintainer review.

Before merge, please make sure:

  • The PR targets develop.
  • Commits use a real Git identity or GitHub noreply email.
  • External commits include a DCO sign-off: git commit -s.
  • The PR does not include secrets, cookies, account tokens, signed URLs, or private captured data.
  • Focused tests/docs are included for behavior changes.

GitHub Copilot code review may be requested as an advisory first pass, but maintainer approval is still required.

…prove worker error handling

MCP Tools Updates:
- gflow_generate_image: Added 'reference_images' parameter, classifying as local paths vs UUIDs and mapping to 'i2i' mode when present.
- gflow_generate_video: Renamed 'image_path' to 'initial_frame' and 'end_image' to 'end_frame', mapped them cleanly to the daemon payload. Added 'reference_images' for 'r2v' mode.
- Added strict mutually exclusive validation checking that 'reference_images' cannot be used alongside 'initial_frame' or 'end_frame'.
- Fixed line-length formatting issues and strict type hints in tools.py.

Worker Daemon Updates:
- Explicitly fail tasks and log reasons if video generation tasks return un-succeeded statuses from the Flow API (via FlowWorker).

@ffroliva ffroliva left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Council review — changes requested 🔴

Thanks for this, @C1ph3r404 — wiring the MCP tools to the real FlowWorker queue (instead of the old status:"pending" stubs) is genuinely useful work, and the core wiring is correct: task-type dispatch and payload keys line up in both directions, security is clean (no injection/traversal, output paths go through validate_job_id()), and the MCP↔CLI flag naming actually improved. The blockers below are mostly mechanical — happy to help once they're addressed.

Must-fix (blocking)

  1. CI is red because the new video tests use an incomplete fake. FakeVideoStatus/_FakeVideoStatus (tests/worker/test_daemon.py:29, tests/mcp/test_tools_wired.py) only set media_id + status="completed", but production calls result.status.succeeded — a property on the real VideoStatus that returns status == "MEDIA_GENERATION_STATUS_SUCCESSFUL". The fake has no succeeded, so the worker raises, the task is marked failed, and the test asserts failed == completed. The production code is correct; the test fixtures are wrong. Please construct the real VideoStatus (or mirror succeeded/failure_reasons/error_message and use the MEDIA_GENERATION_STATUS_SUCCESSFUL string). You did this correctly for the image fakes — same treatment for video.
  2. Unclosed DB connection in the new fixtures. The temp_db fixtures return store with no teardown → ResourceWarning: unclosed sqlite3.Connection in CI. Use yield store + store.close().
  3. A recording error can mark a successful, credit-spent video as failed. In worker/daemon.py, record_completed_video(...) runs inside the try whose except re-raises — but it executes after the Veo credit is spent. A DB hiccup then flips a real success to failed. Recording/DB errors after a successful generation should warn, not fail the task (same principle as our exit-16 data-store handling).
  4. i2v must require initial_frame. In mcp/tools.py, initial_frame is optional and only validated when present, though the docstring says it's "required for i2v". Calling i2v with no frame sends start_image=None, which routes to the text-to-video endpoint and burns a credit on the wrong call. Please enforce it for mode="i2v".
  5. docs/MCP.md is now stale. Lines 48-49 still show gflow_generate_image(...) without reference_images and gflow_generate_video(prompt, initial_frame_path, ...) (old name, missing end_frame/mode). Our docs are a living spec — please update them in this PR.
  6. Heads-up on auth/cookies.py. Your _get_chrome_cookies3 change touches the exact function an in-flight macOS cookie investigation (#222) depends on. No textual conflict, but it changes the macOS key_file handling and adds a KeyError→PermissionError mapping that affects which failures fall back to the headless reader. Could you split the cookie/--profile changes into a separate PR? It keeps this one scoped to "MCP wiring" and avoids entangling the #222 debugging.

Worth adding (not blocking)

  • Real coverage for the headline behavior. Download and recording are fully AsyncMock'd, so "download/recording in daemon" isn't actually exercised — a test asserting a file is written and an asset/DB row recorded would lock it in.
  • Extract the ~150-line process_task into _process_image_task/_process_video_task, and factor the path-validation block that's copy-pasted 4× in mcp/tools.py.
  • Please rebase onto current develop — this branch was cut before some merged work, so the diff re-presents changes that are already in.

(On testing strategy: we won't ask an external PR to run live-credit e2e — but constructing the real domain dataclasses in tests, as in must-fix #1, is exactly what catches this class of bug.)

ffroliva added 2 commits July 1, 2026 00:02
…iva#228)

Maintainer follow-up to @C1ph3r404's MCP->FlowWorker wiring, addressing
the PR ffroliva#228 council review.

- CI-RED: tests hand-rolled a fake VideoStatus missing `.succeeded`, so
  completed videos flipped to "failed". Use the real VideoStatus/VideoResult.
- worker: apply tool_specs so the MCP `tools` parameter actually expands the
  prompt (it was packed into the payload but never applied -> silent no-op).
- daemon: post-success video recording warns instead of failing a
  credit-spent task.
- mcp/tools: require initial_frame for i2v and reference_images for r2v at the
  tool boundary; treat any non-"completed" status as failure.
- cleanup: close temp_db fixtures (no ResourceWarning); dedupe image-path
  validation into a shared helper; flatten _run_generation_task DataStore
  lifecycle (no nested store / double-close).
- docs/MCP.md: correct stale tool signatures.
- merged origin/develop (picks up ffroliva#223); cookies.py KeyError->PermissionError
  mapping now covered by tests.
@github-actions
github-actions Bot requested a review from ffroliva June 30, 2026 23:29
@ffroliva

Copy link
Copy Markdown
Owner

Hi @C1ph3r404 — thanks for this, the wiring is solid! To land it without a round-trip, I (maintainer) have pushed follow-up commits to your branch (maintainerCanModify) addressing the council review rather than block on back-and-forth. Your authorship on the original commits is preserved.

What changed on top of your work:

  • CI-red fix: the tests hand-rolled a fake VideoStatus missing .succeeded, so completed videos flipped to failed (assert "failed" == "completed"). Now using the real VideoStatus/VideoResult.
  • tool_specs wiring: the MCP tools parameter was packed into the payload but the worker never applied it, so prompt expansion (creative-director, etc.) was a silent no-op. Wired apply_tool_option into the worker so it actually mirrors the CLI --tool flag.
  • daemon: post-success video recording now warns instead of failing a credit-spent task.
  • mcp/tools: i2v now requires initial_frame and r2v requires reference_images (clear 400 at the boundary); any non-completed task status is treated as a failure rather than a false success.
  • cleanups: closed the test DB fixtures (no ResourceWarning), deduped the image-path validation into one helper, and flattened the DataStore lifecycle in _run_generation_task.
  • rebase + docs: merged develop (picks up fix(browser): diagnose + fail loud on chrome→bundled strategy downgrade (Refs #222) #223) and refreshed docs/MCP.md tool signatures.

Full suite green locally (1918 passed). Thanks again for the contribution! 🙏

@ffroliva
ffroliva merged commit 4c9c9f3 into ffroliva:develop Jun 30, 2026
9 checks passed
@ffroliva ffroliva mentioned this pull request Jul 1, 2026
ffroliva added a commit that referenced this pull request Jul 1, 2026
The #228 boundary guards pushed gflow_generate_image/video over the cognitive-
complexity threshold and duplicated the bad-parameter error literal. Extract:

- `_BAD_PARAM_TYPE` constant + `_bad_param()` builder (fixes S1192 duplicated literal)
- `_resolve_image_references()` and `_build_video_media_inputs()` helpers, moving
  the mode/mutual-exclusion/path validation out of the tool functions (fixes S3776
  cognitive complexity on both)

Adds unit tests for the extracted helpers plus the #230 `_preread_flow_session_cookies`
capture path (D4 council gap) and the video `tool_specs` expansion branch — lifting
new-code coverage back over 80%. Behavior-preserving; 38 affected tests green,
pyright src 0 errors.
15990166686ll-crypto pushed a commit to 15990166686ll-crypto/gflow-cli that referenced this pull request Aug 24, 2026
…iva#228)

Maintainer follow-up to @C1ph3r404's MCP->FlowWorker wiring, addressing
the PR ffroliva#228 council review.

- CI-RED: tests hand-rolled a fake VideoStatus missing `.succeeded`, so
  completed videos flipped to "failed". Use the real VideoStatus/VideoResult.
- worker: apply tool_specs so the MCP `tools` parameter actually expands the
  prompt (it was packed into the payload but never applied -> silent no-op).
- daemon: post-success video recording warns instead of failing a
  credit-spent task.
- mcp/tools: require initial_frame for i2v and reference_images for r2v at the
  tool boundary; treat any non-"completed" status as failure.
- cleanup: close temp_db fixtures (no ResourceWarning); dedupe image-path
  validation into a shared helper; flatten _run_generation_task DataStore
  lifecycle (no nested store / double-close).
- docs/MCP.md: correct stale tool signatures.
- merged origin/develop (picks up ffroliva#223); cookies.py KeyError->PermissionError
  mapping now covered by tests.
15990166686ll-crypto pushed a commit to 15990166686ll-crypto/gflow-cli that referenced this pull request Aug 24, 2026
feat(mcp): wire server tools to FlowWorker and implement download/recording in daemon
15990166686ll-crypto pushed a commit to 15990166686ll-crypto/gflow-cli that referenced this pull request Aug 24, 2026
The ffroliva#228 boundary guards pushed gflow_generate_image/video over the cognitive-
complexity threshold and duplicated the bad-parameter error literal. Extract:

- `_BAD_PARAM_TYPE` constant + `_bad_param()` builder (fixes S1192 duplicated literal)
- `_resolve_image_references()` and `_build_video_media_inputs()` helpers, moving
  the mode/mutual-exclusion/path validation out of the tool functions (fixes S3776
  cognitive complexity on both)

Adds unit tests for the extracted helpers plus the ffroliva#230 `_preread_flow_session_cookies`
capture path (D4 council gap) and the video `tool_specs` expansion branch — lifting
new-code coverage back over 80%. Behavior-preserving; 38 affected tests green,
pyright src 0 errors.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

external-contribution Pull request from a non-maintainer or fork needs-copilot-review Ask GitHub Copilot for advisory code review needs-maintainer-review Requires maintainer review before merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants