Skip to content

feat: extract github-projects-client, generalize MCP server for any board#31

Merged
BigLep merged 10 commits into
masterfrom
003-generalize-mcp-client
May 4, 2026
Merged

feat: extract github-projects-client, generalize MCP server for any board#31
BigLep merged 10 commits into
masterfrom
003-generalize-mcp-client

Conversation

@BigLep
Copy link
Copy Markdown
Contributor

@BigLep BigLep commented Apr 24, 2026

Summary

  • Extracted github-projects-client/ — a standalone, reusable Python client for GitHub Projects v2 boards. No MCP dependency; pure requests-based. Context-efficient (~200-300 bytes per item vs ~8KB from GitHub's API).
  • Generalized filozzy-mcp — the MCP server now reads org/project/board-names from environment variables instead of hardcoding FilOzone/Project 14. Works with any GitHub Projects v2 board.
  • Migrated foc-pr-report — PR-specific logic extracted into pr_enrichment.py; shared board logic now comes from github-projects-client. Backward-compat shim kept in foc_project14_client.py.
  • Migrated github-project-export — now imports directly from github-projects-client.
  • Added cross-package test infrastructurescripts/test-all.sh runs 30 integration tests across 3 packages (27 github-projects-client + 2 filozzy-mcp + 1 foc-pr-report).
  • Consolidated redundant tests — reduced from 50 tests with heavy overlap to 30 tests with zero overlap.
  • Rebased onto master — integrated PR feat(foc-pr-report): triage-first ordering and table action hints #33 (triage-first ordering, has_non_user_review reviewer tracking) into the extracted pr_enrichment.py.

Architecture

github-projects-client/     <- shared library (no MCP dep)
  ├── api.py                  GraphQL + REST helpers
  ├── items.py                list_items, get_item, list_fields
  ├── fields.py               list_field_options
  ├── views.py                resolve_view_url
  └── mutations.py            set_field_value

filozzy-mcp/                <- thin MCP adapter
  └── server.py               env config -> github_projects_client calls + audit log

foc-pr-report/              <- PR reporting
  ├── pr_enrichment.py        PR-specific queries + reviewer enrichment
  └── foc_project14_client.py backward-compat re-export shim

Test plan

  • ./scripts/test-all.sh — all 30 tests pass (27 + 2 + 1)
  • MCP server starts with env var config and responds to queries
  • set_board_item_field mutations work (Status, Cycle Theme)
  • foc-pr-report CLI produces correct markdown output
  • github-project-export works with new imports
  • Rebased onto master — conflict in foc_project14_client.py resolved (kept shim, ported PR feat(foc-pr-report): triage-first ordering and table action hints #33 changes to pr_enrichment.py)
  • Fixed test_lookup_by_short_ref — filter to org-local items since short refs expand using default org

🤖 Generated with Claude Code

@FilOzzy FilOzzy added this to FOC Apr 24, 2026
@github-project-automation github-project-automation Bot moved this to 📌 Triage in FOC Apr 24, 2026
@BigLep BigLep moved this from 📌 Triage to 🔎 Awaiting review in FOC Apr 24, 2026
@BigLep BigLep moved this from 🔎 Awaiting review to 📌 Triage in FOC Apr 24, 2026
@BigLep BigLep changed the title feat: extract ghprojects-client, generalize MCP server for any board feat: extract github-projects-client, generalize MCP server for any board Apr 24, 2026
@BigLep BigLep requested a review from Copilot April 24, 2026 18:54
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR extracts a reusable github-projects-client Python library for GitHub Projects v2 and refactors existing tools (the filozzy-mcp MCP server, foc-pr-report, and github-project-export) to consume it, while adding a root test runner and accompanying specs/docs.

Changes:

  • Added github-projects-client/ with REST/GraphQL helpers, compact item shaping, view URL resolution, and mutations.
  • Updated filozzy-mcp, foc-pr-report, and github-project-export to depend on/import from the shared client and added cross-package integration test runner.
  • Added a full specification package under specs/003-generalize-mcp-client/ describing the design, contracts, and migration.

Reviewed changes

Copilot reviewed 34 out of 40 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
specs/003-generalize-mcp-client/tasks.md Task breakdown for extracting the shared client and migrating consumers.
specs/003-generalize-mcp-client/spec.md Feature spec defining scenarios, requirements, and success criteria.
specs/003-generalize-mcp-client/research.md Captures key implementation decisions (packaging, boundaries, config).
specs/003-generalize-mcp-client/quickstart.md Setup/migration guide and repo layout after refactor.
specs/003-generalize-mcp-client/plan.md Implementation plan and target repo/package structure.
specs/003-generalize-mcp-client/data-model.md Defines entity shapes (BoardItem, MutationResult, etc.).
specs/003-generalize-mcp-client/contracts/shared-client-api.md Contract for the new library’s public API.
specs/003-generalize-mcp-client/contracts/mcp-tools.md Contract for MCP tool behavior/config/audit logging.
specs/003-generalize-mcp-client/checklists/requirements.md Spec quality checklist for the feature.
scripts/test-all.sh Root script to run pytest across multiple packages and summarize results.
github-projects-client/pyproject.toml New package definition for the shared client.
github-projects-client/uv.lock Lockfile for shared client package dependencies.
github-projects-client/README.md Usage docs and API overview for the shared client.
github-projects-client/github_projects_client/init.py Public re-exports for shared client API.
github-projects-client/github_projects_client/api.py REST/GraphQL request helpers + pagination utilities.
github-projects-client/github_projects_client/fields.py Field option enumeration via GraphQL.
github-projects-client/github_projects_client/items.py Compact item shaping, listing, and item reference resolution.
github-projects-client/github_projects_client/views.py View URL parsing and filter/field-order resolution.
github-projects-client/github_projects_client/mutations.py Shared mutation logic to set field values by name.
github-projects-client/tests/init.py Test package marker for shared client tests.
github-projects-client/tests/test_integration.py Integration tests against live GitHub API for shared client.
github-project-export/pyproject.toml Switch dependency from foc-pr-report to github-projects-client.
github-project-export/uv.lock Lockfile updated for new shared client dependency.
github-project-export/github_project_export/rest_export.py Updated imports to use shared client REST helpers.
foc_wg_pr_notifier.py Updated imports to use new pr_enrichment module.
foc-pr-report/pyproject.toml Adds dependency on github-projects-client and test config.
foc-pr-report/uv.lock Lockfile updated for shared client + pytest dev deps.
foc-pr-report/foc_pr_report/cli.py Uses pr_enrichment instead of the old client module.
foc-pr-report/foc_pr_report/report.py Uses pr_enrichment.field_values_by_name after refactor.
foc-pr-report/foc_pr_report/pr_enrichment.py New PR-specific module (reviewer enrichment + REST→GraphQL mapping).
foc-pr-report/foc_pr_report/foc_project14_client.py Backward-compat shim re-exporting to shared client + pr_enrichment.
foc-pr-report/tests/init.py Test package marker for foc-pr-report tests.
foc-pr-report/tests/test_integration.py End-to-end integration test for the PR report pipeline.
filozzy-mcp/pyproject.toml Switch dependency from foc-pr-report to github-projects-client.
filozzy-mcp/uv.lock Lockfile updated for shared client dependency.
filozzy-mcp/filozzy_mcp/server.py Reads board config from env and delegates to shared client; logs mutations.
filozzy-mcp/tests/test_integration.py Integration tests updated to focus on MCP-layer behavior.
filozzy-mcp/README.md Docs updated for env-based board config and shared-client architecture.
README.md Root README updated to describe new packages and add test runner instructions.
CLAUDE.md Notes active technologies relevant to this feature.
Comments suppressed due to low confidence (3)

github-projects-client/github_projects_client/mutations.py:47

  • The docstring contains mojibake characters ("���") in "No audit logging ��� that's...", which will render poorly and can cause encoding issues in downstream tooling. Replace with a normal dash/em dash and ensure the file is saved as UTF-8.
    github-projects-client/github_projects_client/mutations.py:138
  • set_field_value returns a dict keyed with item rather than item_ref, and error returns omit item_ref/field entirely. This conflicts with the MutationResult shape described in the spec/data-model and makes it harder for callers (including the MCP layer) to consistently log/handle failures. Align the result shape with the contract (e.g., always include item_ref, field, success, and either old_value/new_value or error).
    filozzy-mcp/filozzy_mcp/server.py:504
  • set_board_item_field only logs successful mutations. For auditability/debugging, failed mutation attempts (item not found, field/option invalid, API errors) should also be recorded in the action log with result reflecting the failure reason and without old_value/new_value when unavailable.
    if result.get("success"):
        old = result.get("old_value", "")
        new = result.get("new_value", "")

        log_action(
            tool="set_board_item_field",
            params={
                "org": GITHUB_ORG,
                "project_number": GITHUB_PROJECT_NUMBER,
                "item_ref": item_ref,
                "field_name": field_name,
                "value": value,
            },
            result="success",
            old_value=old,
            new_value=new,
        )

        return (
            f"Updated {item_ref}: {field_name} "
            f"{'from \"' + old + '\" ' if old else ''}"
            f'to "{new}"'
        )
    else:
        return f"Failed: {result.get('error', 'unknown error')}"


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread filozzy-mcp/filozzy_mcp/server.py Outdated
Comment thread specs/003-generalize-mcp-client/contracts/mcp-tools.md Outdated
Comment thread specs/003-generalize-mcp-client/contracts/shared-client-api.md Outdated
Comment thread specs/003-generalize-mcp-client/quickstart.md
Comment thread specs/003-generalize-mcp-client/contracts/mcp-tools.md
Comment thread specs/003-generalize-mcp-client/plan.md
@BigLep BigLep moved this from 📌 Triage to 🔎 Awaiting review in FOC Apr 24, 2026
@BigLep BigLep self-assigned this Apr 27, 2026
BigLep added a commit that referenced this pull request Apr 27, 2026
- Parse GITHUB_PROJECT_NUMBER defensively with clear error on invalid input
- Document default values for GITHUB_ORG, GITHUB_PROJECT_NUMBER, BOARD_NAMES
  in mcp-tools.md contract
- Remove verbose param from shared-client-api.md (MCP-layer concern only)
- Fix corrupted box-drawing characters in quickstart.md and plan.md
- Update audit log JSON example to match actual implementation schema

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@BigLep BigLep requested a review from rjan90 April 27, 2026 23:59
@BigLep BigLep marked this pull request as draft April 29, 2026 14:30
@BigLep BigLep moved this from 🔎 Awaiting review to ⌨️ In Progress in FOC May 1, 2026
BigLep and others added 10 commits May 3, 2026 13:14
Defines the feature spec for extracting a shared, board-agnostic client
library from filozzy-mcp and foc_project14_client.py. Covers:
- Three-layer responsibility boundaries (shared client / MCP adapter / external tools)
- Current boundary violations to fix during refactor
- First-class tool vs. external tool decisions
- Board alias configuration for LLM routing
- Cross-package test infrastructure requirements

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase 0 research (package structure, naming, extraction boundaries,
test runner, config approach, migration strategy) and Phase 1 design
(data model, shared client API contract, MCP tools contract, quickstart).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
46 tasks across 6 phases: setup, shared client extraction, MCP server
generalization (MVP), cross-package test runner, foc-pr-report migration,
and polish. Uses git mv to preserve file history where possible.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Create the shared client library package with pyproject.toml,
hatchling build, and pytest config. No code yet — populated in
the next phase.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract shared GitHub Projects v2 board logic from foc_project14_client.py
and filozzy-mcp into a new ghprojects-client package. All functions are
parameterized by org/project_number with no hardcoded defaults.

- ghprojects-client: api.py, fields.py, items.py, views.py, mutations.py
  with 21 integration tests
- filozzy-mcp server.py: reads GITHUB_ORG, GITHUB_PROJECT_NUMBER,
  BOARD_NAMES from env; imports from ghprojects_client; audit logging
  stays in MCP layer
- foc-pr-report: PR-specific functions moved to pr_enrichment.py;
  foc_project14_client.py is now a thin backward-compat shim
- github-project-export: imports directly from ghprojects_client
- scripts/test-all.sh: cross-package test runner

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move shared-client tests that only existed in filozzy-mcp into
ghprojects-client (6 tests). Strip filozzy-mcp down to 2 MCP-layer-
specific tests (docstring query validation). Zero overlap between
the two test suites.

Before: 21 + 29 = 50 tests (heavy duplication)
After:  27 +  2 = 29 tests (no duplication)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add FilOzzy MCP Server and ghprojects-client sections to root README
- Update filozzy-mcp README with env var docs and architecture section
- Rewrite ghprojects-client README with full public API table
- Add foc-pr-report integration test and pytest dev dependency
- Mark all remaining spec tasks as complete

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rename package directory, Python module, and all references for
consistency with existing github-milestone-creator and
github-project-export naming conventions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Parse GITHUB_PROJECT_NUMBER defensively with clear error on invalid input
- Document default values for GITHUB_ORG, GITHUB_PROJECT_NUMBER, BOARD_NAMES
  in mcp-tools.md contract
- Remove verbose param from shared-client-api.md (MCP-layer concern only)
- Fix corrupted box-drawing characters in quickstart.md and plan.md
- Update audit log JSON example to match actual implementation schema

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Port fetch_pull_request_review_activity (renamed from
  fetch_pull_request_review_logins) with has_non_user_review return
  value into pr_enrichment.py, matching master's PR #33 changes
- Update enrich_pull_items_with_submitted_reviewers to set
  _has_non_user_submitted_review on each PR item
- Add backward-compat alias for old function name
- Export fetch_pull_request_review_activity from shim
- Fix test_lookup_by_short_ref: filter to org items since short refs
  expand using the default org

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@BigLep BigLep force-pushed the 003-generalize-mcp-client branch from f9abf5d to 6c84654 Compare May 4, 2026 02:59
@BigLep BigLep marked this pull request as ready for review May 4, 2026 03:00
@BigLep
Copy link
Copy Markdown
Contributor Author

BigLep commented May 4, 2026

@rjan90 : I am going to merge this one since it's at the base of #32 and #34

Happy to do any further improvements here afterwards though.

@BigLep BigLep merged commit 9239637 into master May 4, 2026
@github-project-automation github-project-automation Bot moved this from ⌨️ In Progress to 🎉 Done in FOC May 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: 🎉 Done

Development

Successfully merging this pull request may close these issues.

3 participants