Add FarmVibes MCP server - #256
Draft
Renato L. de F. Cunha (renatolfc) wants to merge 16 commits into
Draft
Conversation
Copilot started reviewing on behalf of
Renato L. de F. Cunha (renatolfc)
August 27, 2026 01:10
View session
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a standalone stdio MCP server while migrating FarmVibes to Python 3.11 and Pydantic 2’s v1 compatibility layer.
Changes:
- Adds seven MCP tools with unit and subprocess tests.
- Migrates enums and Pydantic imports while preserving wire formats.
- Updates package metadata, CI, environments, and documentation for Python 3.11.
Reviewed changes
Copilot reviewed 56 out of 56 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
src/vibe_server/vibe_server/workflow/spec_validator.py |
Updates node-type validation. |
src/vibe_server/vibe_server/workflow/spec_parser.py |
Migrates task enums and parsing. |
src/vibe_server/vibe_server/workflow/runner/runner.py |
Migrates workflow event enum. |
src/vibe_server/vibe_server/workflow/parameter.py |
Corrects schema import. |
src/vibe_server/vibe_server/server.py |
Uses v1 compatibility and stdlib enums. |
src/vibe_server/tests/test_remote_workflow_runner.py |
Updates compatibility imports. |
src/vibe_server/tests/test_op_parallelism.py |
Patches the v1 namespace. |
src/vibe_server/setup.py |
Targets Python 3.11. |
src/vibe_notebook/setup.py |
Declares Python 3.11 support. |
src/vibe_lib/vibe_lib/geometry.py |
Migrates geometry enum. |
src/vibe_lib/vibe_lib/comet_farm/comet_server.py |
Uses Pydantic v1 model. |
src/vibe_lib/vibe_lib/comet_farm/comet_model.py |
Uses Pydantic v1 models. |
src/vibe_lib/vibe_lib/airbus.py |
Migrates Airbus enums. |
src/vibe_lib/setup.py |
Targets Python 3.11. |
src/vibe_dev/vibe_dev/mock_utils.py |
Uses Pydantic v1 model. |
src/vibe_dev/setup.py |
Targets Python 3.11. |
src/vibe_core/vibe_core/datamodel.py |
Migrates models and run statuses. |
src/vibe_core/vibe_core/data/utils.py |
Uses Pydantic v1 model. |
src/vibe_core/vibe_core/data/sentinel.py |
Migrates processing-level enum. |
src/vibe_core/vibe_core/data/json_converter.py |
Preserves v1 serialization. |
src/vibe_core/vibe_core/data/core_types.py |
Preserves v1 core models. |
src/vibe_core/vibe_core/client.py |
Migrates cluster enum. |
src/vibe_core/vibe_core/cli/osartifacts.py |
Uses importlib.resources. |
src/vibe_core/pyproject.toml |
Requires Python 3.11 and Pydantic 2. |
src/vibe_common/vibe_common/schemas.py |
Preserves v1 dataclasses. |
src/vibe_common/vibe_common/messaging.py |
Migrates models and enums. |
src/vibe_common/vibe_common/dropdapr.py |
Uses v1 configuration. |
src/vibe_common/tests/test_messaging.py |
Updates serialization imports. |
src/vibe_common/setup.py |
Updates runtime requirements. |
src/vibe_agent/setup.py |
Declares Python 3.11 support. |
src/farmvibes_mcp/tests/test_stdio.py |
Tests a real stdio session. |
src/farmvibes_mcp/tests/test_server.py |
Tests all MCP tools. |
src/farmvibes_mcp/pyproject.toml |
Defines the MCP package. |
src/farmvibes_mcp/farmvibes_mcp/server.py |
Implements seven MCP tools. |
src/farmvibes_mcp/farmvibes_mcp/__main__.py |
Adds module execution. |
src/farmvibes_mcp/farmvibes_mcp/__init__.py |
Exports the MCP server. |
resources/envs/worker-requirements.txt |
Updates worker dependencies. |
resources/envs/services-requirements.txt |
Updates service dependencies. |
ops/weed_detection/weed_detection.py |
Migrates operation enum. |
ops/merge_geometries/merge_geometries.py |
Migrates merge enum. |
notebooks/weed_detection/weed_detection_env.yaml |
Targets Python 3.11. |
notebooks/sensor/optimal_locations.yaml |
Targets Python 3.11. |
notebooks/segment_anything/env_gpu.yaml |
Updates Python, but conflicts with builds. |
notebooks/segment_anything/env_cpu.yaml |
Targets Python 3.11. |
notebooks/irrigation/env.yaml |
Targets Python 3.11. |
notebooks/heatmaps/nutrients.yaml |
Targets Python 3.11. |
notebooks/env.yaml |
Updates the shared environment. |
notebooks/deepmc/deepmc_env.yaml |
Updates Python, but conflicts with PyTorch. |
notebooks/deepmc_neighbors/deepmc_neighbors_env.yaml |
Updates Python and Pydantic. |
notebooks/crop_segmentation/crop_env.yaml |
Updates Python, but conflicts with PyTorch. |
notebooks/crop_cycles/env.yaml |
Updates Python, but conflicts with TensorFlow. |
docs/source/index.md |
Links MCP documentation. |
docs/source/docfiles/markdown/QUICKSTART.md |
Updates Python prerequisite. |
docs/source/docfiles/markdown/MCP.md |
Documents MCP installation and tools. |
docs/source/docfiles/markdown/AKS.md |
Updates Python prerequisite. |
.github/workflows/lint-test.yml |
Builds and tests the MCP package. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Copilot started reviewing on behalf of
Renato L. de F. Cunha (renatolfc)
August 27, 2026 02:31
View session
Copilot started reviewing on behalf of
Renato L. de F. Cunha (renatolfc)
August 27, 2026 02:42
View session
Copilot started reviewing on behalf of
Renato L. de F. Cunha (renatolfc)
August 27, 2026 03:02
View session
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 39 out of 39 changed files in this pull request and generated no new comments.
Suppressed comments (2)
Previously missed (2) — in code that hasn't changed since the last review.
src/farmvibes_mcp/farmvibes_mcp/server.py:75
- Malformed GeoJSON is validated only after
shape()succeeds. Inputs permitted by thedictschema such as{}raise anAttributeErrorin supported Shapely versions, bypassing_execute's handled exceptions and exposing an internal parsing error instead of the documented geometry validation message. Normalize parsing failures before checkingis_empty/is_valid(and cover malformed GeoJSON in the tests).
parsed_geometry = shape(geometry)
if parsed_geometry.is_empty or not parsed_geometry.is_valid:
raise ValueError("geometry must be a nonempty valid GeoJSON geometry")
src/farmvibes_mcp/farmvibes_mcp/server.py:114
get_runstill downloads the full/v0/runs/{id}response and_jsonable(run)serializes the potentially large output before it is removed. Large run outputs therefore impose the same REST transfer and substantial peak memory cost this tool is intended to avoid, and serialization can fail on data that would never be returned. Fetch only the required run fields (or add a client/API option that excludes output) instead of discarding it afterward.
run = _execute(lambda: _client().describe_run(run_id))
result = _jsonable(run)
result.pop("output", None)
Copilot started reviewing on behalf of
Renato L. de F. Cunha (renatolfc)
August 27, 2026 03:41
View session
Copilot started reviewing on behalf of
Renato L. de F. Cunha (renatolfc)
August 27, 2026 04:08
View session
Copilot started reviewing on behalf of
Renato L. de F. Cunha (renatolfc)
August 27, 2026 04:17
View session
Copilot started reviewing on behalf of
Renato L. de F. Cunha (renatolfc)
August 27, 2026 18:17
View session
Comment on lines
+116
to
+119
| run = _execute(lambda: _client().describe_run(run_id)) | ||
| result = _jsonable(run) | ||
| result.pop("output", None) | ||
| return result |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
FarmVibes can currently be automated through Python or REST, but MCP clients cannot reuse that behavior directly because
vibe_corewas pinned to Pydantic 1 while the current MCP SDK requires Pydantic 2.This PR makes
vibe_corecompatible with Pydantic 1.10.17 through 2.x by running the existing models throughpydantic.v1. Legacy service, worker, and notebook environments deliberately remain on Pydantic 1, so adding MCP does not force unrelated geospatial and ML dependency upgrades. The standalone MCP environment selects Pydantic 2. This also leaves a clear upgrade path: each runtime can modernize independently, and native Pydantic 2 models can come later without blocking MCP now.fastapi-utilsenum usage moves to the already-installedstrenumpackage.The new standalone
farmvibes-mcppackage requires Python 3.11, runs over stdio, and importsFarmvibesAiClientdirectly. Local/remote URL discovery, bearer-token handling, request payloads, output rewriting, and error behavior therefore remain in one place. It exposes seven tools: list/describe workflows, submit runs, list/get runs, retrieve output, and cancel runs.The MCP process has its own environment because MCP 2 and the legacy FastAPI service stack require incompatible Starlette, Uvicorn, and OpenTelemetry versions. CI builds all six packages through PEP 517 and checks those dependency sets separately.
Validation
vibe_core,vibe_common,vibe_server, andvibe_agenttests pass under both Pydantic 1.10.26 and Pydantic 2.13.4.pip checkpasses in separate service-stack and MCP environments; Ruff and pinned Pyright pass.helloworld, submitted run2fd63c03-6a97-4050-a084-1227aa0e3cac, observedqueued → done, and retrieved therasteroutput.The user guide includes isolated installation, VS Code and generic MCP configuration, tool usage, local/remote discovery, a tested Codespaces setup, and cleanup.
This first version is stdio-only. It intentionally skips prompts, resources, asset downloads, arbitrary existing-asset submission, and a blocking wait tool.