Skip to content

feat(github): add 64 actions for MCP parity and modularise the integration - #443

Closed
risheetperi wants to merge 2 commits into
masterfrom
feat/442/github-mcp-parity-actions
Closed

feat(github): add 64 actions for MCP parity and modularise the integration#443
risheetperi wants to merge 2 commits into
masterfrom
feat/442/github-mcp-parity-actions

Conversation

@risheetperi

Copy link
Copy Markdown
Contributor

Closes #442

Brings the GitHub integration's action set to the union of what shipped and every GitHub MCP server capability, implemented directly against the GitHub REST API. 47 → 111 actions.

⚠️ One thing to confirm before merge

The security_events OAuth scope must be grantable by Autohive's shared GitHub OAuth app.

auth.type is platform, so scopes are requested against that shared app, which I can't inspect from this repo. If it can't grant security_events, the 11 Security actions will return 403. The fix is a one-line revert in config.json plus dropping those actions — nothing else in this PR depends on it.

What's new

Domain New Detail
Search 7 code, commits, issues, PRs, repositories, users, orgs
Issues 12 label CRUD, issue labels, sub-issue hierarchy, org issue types & fields
Pull requests 13 update, update-branch, diff, files, commits, combined status, reviews, comments, replies, pending-review lifecycle
Actions & workflows 12 dispatch, re-run, re-run failed, cancel, jobs, job logs, artifacts, run timing
Security 11 code scanning, Dependabot, secret scanning, code quality, advisories
Repos & files 4 fork, git tree, collaborators, atomic push_files
Users & gists 5 teams, team members, gist get/list/update

Out of scope, documented in the README rather than silently dropped: Notifications, Discussions (GraphQL-only), Projects v2, Stars, Copilot, and create_pull_request_with_copilot (no public API — the MCP server implements it against its own hosted service).

Structural change

github.py (2,834 lines) becomes a ~30-line entry point plus an actions/ package and a shared helpers.py. This is the layout validate_integration.py already whitelists and that facebook/, aws/, humanitix/ and instagram/ already use.

Existing action bodies were moved by AST line range and verified to have identical ASTs afterwards — the move is behaviour-preserving. github/__init__.py is deleted deliberately: with an actions/ package present, from github import github inside an action module resolves to the partially-initialised package and binds the module rather than the Integration, so every decorator raises AttributeError. This is why the validator makes __init__.py optional when actions/ exists, and why no other modular integration has one.

Notable API findings

These changed the implementation and are worth a reviewer's attention:

  • addPullRequestReviewComment is deprecated wholesale (every input field flagged, removal slated 2023-10-01). add_comment_to_pending_review uses addPullRequestReviewThread instead. This is the only GraphQL action — REST cannot attach a comment to an existing pending review.
  • Four endpoints are cursor-paginated and silently ignore page. Dependabot alerts, code quality findings and both advisory endpoints return an identical set for page=1 and page=2. Walking them with the normal paginator would have silently duplicated results. Those actions return a single capped page, with a regression test each.
  • Workflow run logs and artifacts cannot be returned. Both 302 to a signed ZIP; context.fetch follows redirects and decodes as text, so .text() raises UnicodeDecodeError and the SDK's own handler re-raises. Both actions return archive_download_url metadata and never request the archive. get_job_logs is unaffected (plain text) and returns log content, tail-trimmed.
  • There is no /search/orgs — confirmed 404. search_orgs scopes /search/users with type:org.
  • search_issues and search_pull_requests share /search/issues, disambiguated by the documented is:issue / is:pr qualifiers, injected only when the caller hasn't already scoped the query.

Security

list_secret_scanning_alerts and get_secret_scanning_alert return alert metadata but never the leaked credential. Both hardcode hide_secret=true with no opt-out, and shape output through a strict allow-list, so a provider-side regression still cannot leak it. Tests assert the secret never appears in the serialised output, and that a caller-supplied hide_secret: false is ignored.

Bug fixes

  • diff_branch_to_branch crashed on commits with a null author (deleted accounts, some bot commits) — the same crash list_commits was fixed for in 2.4.0, which this action never received.
  • get_rate_limit crashed when GitHub omits the graphql resource block, which it does for some token types.

Both have regression tests.

Documentation

The README claimed 14 OAuth scopes when config.json requests six (it listed admin:org, admin:public_key, admin:gpg_key, write:packages, read:packages among others), and documented a result/error output envelope the actions have never returned. The action reference is now generated from config.json, so it cannot drift again, and each scope carries a justification.

Verification

Unit tests        389/389 passed, 94% coverage
Structure         0 errors, 0 warnings
Config↔code sync  0 errors, 0 warnings (all 111 actions)
Lint / format     clean
Bandit            clean
README check      passed
Version check     passed (2.6.0 → 3.0.0)

pip-audit fails on my machine only — ensurepip aborts building its isolated temp venv, and it fails identically on a trivially clean requests==2.32.3 file. requirements.txt is byte-identical to master (SDK pin only, no new dependencies).

Live tests: read-only coverage for the new read actions runs against public repositories and needs GITHUB_ACCESS_TOKEN. Write coverage is double-gated behind the destructive marker and a GITHUB_TEST_REPO env var, so nothing destructive can run against a repository that wasn't explicitly nominated. Neither has been run yet — credentials pending. Flagging that plainly rather than implying live verification that hasn't happened.

pytest github/
pytest github/tests/test_github_integration.py -m "integration and not destructive"
GITHUB_TEST_REPO=owner/scratch pytest github/tests/test_github_integration.py -m "integration and destructive"

Author commitment

  • I understand the third-party API areas I implemented.
  • I can explain every action, endpoint, permission, dependency, and important helper.
  • I used the documented Autohive SDK process and repository conventions.
  • I reviewed the generated or written code myself.
  • I removed dead code, generic boilerplate, hallucinated behavior, and unnecessary abstractions.
  • I tested the integration with meaningful mocked tests.
  • I included real API integration tests where safe and practical, or documented why not.
  • I ran local validation and fixed issues before requesting review.
  • I documented the integration clearly for users and future maintainers.

Every endpoint was verified against the live GitHub documentation before implementation; anything that turned out deprecated, GraphQL-only or absent is called out above rather than guessed at. Dead code was removed as part of this change: three previously-unused GitHubAPI methods are now wired up (update_pull_request, get_gist, list_gists) and the two that remained genuinely unused (get_webhook, delete_gist) are deleted — no unused methods remain.

…ation

Brings the action set to the union of what shipped and every GitHub MCP
server capability, implemented directly against the GitHub REST API.
47 -> 111 actions.

New actions by domain:
  search (7)        code, commits, issues, PRs, repositories, users, orgs
  issues (12)       label CRUD, issue labels, sub-issue hierarchy, org
                    issue types and fields
  pull requests (13) update, update branch, diff, files, commits, combined
                    status, reviews, comments, reply, and the pending
                    review lifecycle
  workflows (12)    dispatch, re-run, re-run failed, cancel, jobs, job
                    logs, artifacts, run timing, delete logs
  security (11)     code scanning, Dependabot, secret scanning, code
                    quality findings, security advisories
  repos/files (4)   fork, git tree, collaborators, atomic push_files
  users/gists (5)   teams, team members, gist get/list/update

Restructures github.py into an actions/ package with a shared helpers.py,
matching the layout the tooling already supports and facebook/, aws/,
humanitix/ and instagram/ already use. Existing action bodies moved with
identical ASTs; behaviour is unchanged apart from the two fixes below.

Adds the security_events OAuth scope, required by the Dependabot, code
scanning and secret scanning actions.

Fixes:
- diff_branch_to_branch crashed on commits with a null author (deleted
  accounts, some bot commits) - the same fix list_commits received in
  2.4.0, which this action never got.
- get_rate_limit crashed when GitHub omits the graphql resource block,
  which it does for some token types.

Secret scanning never returns the leaked credential: both actions send
hide_secret=true and shape output through a strict allow-list, so a
provider-side regression still cannot leak it.

Documentation: the README previously listed 14 OAuth scopes when the
integration requests 6, and described a result/error output envelope the
actions never returned. The action reference is now generated from
config.json so it cannot drift again.

389 unit tests, 94% coverage. Live read-only tests cover the new read
actions against public repositories; write tests are gated behind both
the destructive marker and a GITHUB_TEST_REPO env var.

Closes #442
@github-actions

github-actions Bot commented Aug 19, 2026

Copy link
Copy Markdown

🔍 Integration Validation Results

Commit: 3a1c923e614e3eca4c8bacda56ef41a17b18ec56 · chore(github): bump SDK pin to ~=2.0.1
Changed directories: github

Check Result
Structure ✅ Passed
Code ✅ Passed
Tests ✅ Passed
README ✅ Passed
Version ✅ Passed
✅ Structure Check output
Validating 1 integration(s)...

============================================================
Integration: github
============================================================

✅ Structure valid

============================================================
SUMMARY
============================================================
Integrations validated: 1
Total errors: 0
Total warnings: 0

✅ All validations passed!
✅ Code Check output
----------------------------------------
Checking: github
----------------------------------------

🐍 Checking Python syntax...
   ✅ Syntax OK

📥 Checking imports...
   ✅ Imports OK

📄 Checking JSON files...
   ✅ JSON files OK

🔍 Linting with ruff...
   ✅ Lint OK

🎨 Checking formatting with ruff...
   ✅ Formatting OK

🔒 Scanning for security issues with bandit...
   ✅ Security OK
   Warnings:
     ⚠️ nosec encountered (B105) in github/actions/security.py:474
     ⚠️ nosec encountered (B105) in github/actions/security.py:500
     ⚠️ nosec encountered (B105) in github/tests/conftest.py:17
     ⚠️ nosec encountered (B105) in github/tests/conftest.py:18
     ⚠️ nosec encountered (B105) in github/tests/test_github_security_unit.py:90
     ⚠️ nosec encountered (B105) in github/tests/test_github_security_unit.py:91
     ⚠️ nosec encountered (B105) in github/tests/test_github_security_unit.py:92
     ⚠️ nosec encountered (B105) in github/tests/test_github_security_unit.py:95
     ⚠️ nosec encountered (B105) in github/tests/test_github_security_unit.py:96
     ⚠️ nosec encountered (B105) in github/tests/test_github_security_unit.py:97
     ⚠️ nosec encountered (B105) in github/tests/test_github_security_unit.py:98
     ⚠️ nosec encountered (B105) in github/tests/test_github_security_unit.py:99
     ⚠️ nosec encountered (B105) in github/tests/test_github_security_unit.py:100
     ⚠️ nosec encountered (B105) in github/tests/test_github_security_unit.py:101
     ⚠️ nosec encountered (B105) in github/tests/test_github_security_unit.py:102
     ⚠️ nosec encountered (B105) in github/tests/test_github_security_unit.py:103
     ⚠️ nosec encountered (B105) in github/tests/test_github_security_unit.py:104
     ⚠️ nosec encountered (B105) in github/tests/test_github_security_unit.py:105
     ⚠️ nosec encountered (B105) in github/tests/test_github_security_unit.py:114
     ⚠️ nosec encountered (B105) in github/tests/test_github_security_unit.py:93
     ⚠️ nosec encountered (B105) in github/tests/test_github_security_unit.py:94
     ⚠️ nosec encountered (B105) in github/tests/test_github_security_unit.py:439
     ⚠️ nosec encountered (B105) in github/tests/test_github_security_unit.py:440

🛡️ Checking dependencies for vulnerabilities with pip-audit...
   ✅ Dependencies OK

🔗 Checking config-code sync...
   ✅ Config-code sync OK

🔄 Checking fetch patterns...
   ✅ Fetch patterns OK

========================================
✅ CODE CHECK PASSED
========================================
✅ Tests Check output
Integration      Tests  Coverage        Status
----------------------------------------------
github         389/389       94%      ✅ Passed
----------------------------------------------
Total          389/389            ✅ All passed

✅ Tests passed: github
✅ README Check output
========================================
✅ README CHECK PASSED
========================================
✅ Version Check output
✅ github: 2.6.0 → 3.0.0 (major bump)

========================================
✅ VERSION CHECK PASSED
========================================

The tooling flags ~=2.0.0 as deprecated. 2.0.1 is what CI and local
development already resolve to under the previous pin, so this only makes
the declared floor match what is actually installed and tested against.
Clears the sole remaining validation warning.
@risheetperi

Copy link
Copy Markdown
Contributor Author

Closed for now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(github): close capability gap against the GitHub MCP server

1 participant