feat: add bulk mutations, field clearing, and robustness fixes#32
Merged
Conversation
f9abf5d to
6c84654
Compare
There was a problem hiding this comment.
Pull request overview
This PR generalizes the GitHub Projects integration work across the repo by introducing a reusable github-projects-client package, updating filozzy-mcp and foc-pr-report to depend on it, and adding a root test runner. It also adds a new bulk field-mutation capability intended to make repeated board updates much more efficient.
Changes:
- Added a new shared
github-projects-clientpackage with API, field, item, view, and mutation helpers plus integration tests and README. - Refactored
filozzy-mcpto use the shared client, added env-based board configuration, and introducedbulk_set_board_item_field. - Migrated
foc-pr-reportandgithub-project-exportoff the old FOC-specific client; added repo-wide test runner and updated documentation/spec artifacts.
Reviewed changes
Copilot reviewed 35 out of 41 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| specs/003-generalize-mcp-client/tasks.md | New task breakdown for the generalization work. |
| specs/003-generalize-mcp-client/spec.md | Feature spec describing board-agnostic client/server goals. |
| specs/003-generalize-mcp-client/research.md | Research decisions for package structure and migration. |
| specs/003-generalize-mcp-client/quickstart.md | Setup and migration quickstart for the new layout. |
| specs/003-generalize-mcp-client/plan.md | Implementation plan for the shared client refactor. |
| specs/003-generalize-mcp-client/data-model.md | Data model for board config, items, fields, and mutation results. |
| specs/003-generalize-mcp-client/contracts/shared-client-api.md | Contract for the new shared client API. |
| specs/003-generalize-mcp-client/contracts/mcp-tools.md | Contract for MCP-layer behavior and logging. |
| specs/003-generalize-mcp-client/checklists/requirements.md | Spec quality checklist for the feature. |
| scripts/test-all.sh | Root-level script to run tests across packages. |
| github-projects-client/tests/test_integration.py | New integration coverage for shared-client read APIs. |
| github-projects-client/tests/init.py | Test package marker for shared client. |
| github-projects-client/pyproject.toml | Package metadata and pytest config for shared client. |
| github-projects-client/github_projects_client/views.py | New view URL resolution helper. |
| github-projects-client/github_projects_client/mutations.py | New shared mutation logic, including bulk updates. |
| github-projects-client/github_projects_client/items.py | Shared item listing, formatting, and lookup logic. |
| github-projects-client/github_projects_client/fields.py | Shared field metadata and option discovery logic. |
| github-projects-client/github_projects_client/api.py | Shared GraphQL/REST transport helpers. |
| github-projects-client/github_projects_client/init.py | Public exports for the shared client package. |
| github-projects-client/README.md | Usage docs for the new shared client. |
| github-project-export/uv.lock | Lockfile updated for shared-client dependency. |
| github-project-export/pyproject.toml | Swapped dependency from foc-pr-report to shared client. |
| github-project-export/github_project_export/rest_export.py | Updated imports to consume shared-client REST helpers. |
| foc_wg_pr_notifier.py | Updated notifier import to pr_enrichment. |
| foc-pr-report/uv.lock | Lockfile updated for shared-client dependency and test deps. |
| foc-pr-report/tests/test_integration.py | New end-to-end regression test for PR report pipeline. |
| foc-pr-report/tests/init.py | Test package marker for PR report. |
| foc-pr-report/pyproject.toml | Added shared-client dependency and pytest config. |
| foc-pr-report/foc_pr_report/report.py | Switched report logic to pr_enrichment. |
| foc-pr-report/foc_pr_report/pr_enrichment.py | New home for PR-report-specific enrichment logic. |
| foc-pr-report/foc_pr_report/foc_project14_client.py | Reduced old client to a backward-compatibility shim. |
| foc-pr-report/foc_pr_report/cli.py | Switched CLI imports to pr_enrichment. |
| filozzy-mcp/uv.lock | Lockfile updated for shared-client dependency. |
| filozzy-mcp/tests/test_integration.py | Narrowed MCP tests to MCP-layer concerns. |
| filozzy-mcp/pyproject.toml | Replaced dependency on foc-pr-report with shared client. |
| filozzy-mcp/filozzy_mcp/server.py | Refactored MCP tools onto shared client; added bulk mutation tool and env config. |
| filozzy-mcp/filozzy_mcp/mutation_tools.py | Removed old MCP-local mutation implementation. |
| filozzy-mcp/README.md | Updated docs for board-agnostic MCP setup and architecture. |
| README.md | Root README updated to describe new shared client and test runner. |
| CLAUDE.md | Added active technology notes for this feature. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
7692874 to
8e31903
Compare
3 tasks
rjan90
reviewed
May 4, 2026
rjan90
approved these changes
May 4, 2026
Contributor
rjan90
left a comment
There was a problem hiding this comment.
One comment on the Python compatibility issue, once that is addressed. This LGTM
7 tasks
Add set_field_value_bulk to the shared client, which resolves field info once and batches GraphQL mutations using aliases (groups of 25). The existing set_field_value is now a thin wrapper around the bulk function. Also adds query filter tips to the list_board_items tool description to help LLMs use targeted queries like -has:"cycle-theme" instead of fetching all items and scanning manually. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
set_board_item_field and bulk_set_board_item_field now accept an empty
string ("") as the value to clear a field. Uses the GraphQL
clearProjectV2ItemFieldValue mutation with batched aliases for bulk ops.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The filter is passed via `query`, not `filter`. FastMCP silently ignores unknown parameters, so passing `filter` would fall back to defaults with no error — a subtle footgun. Updated the docstring to make this explicit. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ookup When item_refs contain raw project item node IDs (PVTI_ strings), the bulk operation skips the get_item() lookup for those entries. Also adds "Node ID" as a requestable synthetic field in list_items so callers can obtain node IDs for follow-up mutations. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bump GraphQL field limits from 50 to 100, add null project check in fields.py, and rename result key from "item" to "item_ref" to match the data-model contract. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract string fragments into local variables before interpolation, since f-string expressions cannot contain backslashes on Python <3.12. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ec9da64 to
7d2c09d
Compare
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.
Background
This was the set of changes/improvements I needed while building out #34.
Summary
bulk_set_board_item_fieldMCP tool: Sets a single field+value on multiple items in one call. Resolves field info once and batches GraphQL mutations in groups of 25 using aliased queries.clearProjectV2ItemFieldValuemutation).PVTI_-prefixed node IDs directly to skip per-item REST lookups — useful when IDs are already known from a priorlist_board_itemscall.set_field_valueis now a thin wrapper aroundset_field_value_bulk, reducing duplication.fields.pyandviews.py, added null-project guard infields.py, renamed result key"item"→"item_ref"to match the data-model contract.list_board_itemsquery parameter naming and documented how to obtain node IDs for bulk operations.Files changed
github-projects-client/.../mutations.pyset_field_value_bulk()with batched aliased mutations, clear support, node ID fast path;set_field_value()refactored as wrappergithub-projects-client/.../__init__.pyset_field_value_bulkgithub-projects-client/.../fields.pygithub-projects-client/.../views.pygithub-projects-client/.../items.pygithub-projects-client/tests/test_integration.pygithub-projects-client/tests/test_items_unit.pyfilozzy-mcp/filozzy_mcp/server.pybulk_set_board_item_fieldtool with action loggingTest plan
test_integration.py,test_items_unit.py,test_filozzy_mcp.py,test_foc_pr_report.py)Additional Notes
Before merging, this should be retargeted to
masterafter #31 lands.🤖 Generated with Claude Code