Skip to content

Replace hand-rolled GitHub read tools with github-mcp-server (allowlisted subset) #4181

@bokelley

Description

@bokelley

Problem

Addie's GitHub read tools have two functional gaps:

  1. No diff / file / review-thread access. get_github_issue (server/src/addie/mcp/member-tools.ts:5395) only hits /repos/{org}/{repo}/issues/{number} — issue-shaped metadata + top-level comments. It cannot fetch:

    • PR diffs or changed files (/pulls/{N}/files, raw-diff content-type)
    • Inline review-thread comments (/pulls/{N}/comments)
    • Reviews (/pulls/{N}/reviews)
    • Commits (/pulls/{N}/commits, /commits/{sha})

    Result: when a user pastes a PR URL and asks Addie to review the change, she can read the description but not the actual code.

  2. No fork access. parseAllowedRepo (member-tools.ts:425) hard-codes GITHUB_READ_ALLOWED_ORGS = ['adcontextprotocol', 'prebid'], so PRs from contributor forks (e.g. patmmccann/adcp) are rejected before the API call. Cross-fork PRs do live under the base repo's PR number, but that only helps once we have a diff endpoint to actually read.

Proposal

Mount the official github/github-mcp-server with an explicit read-only tool allowlist. ~6–8 tools mounted, not the full ~70.

Allowlist (initial):

  • get_pull_request
  • get_pull_request_diff
  • get_pull_request_files
  • get_pull_request_comments (review-thread comments)
  • get_pull_request_reviews
  • get_issue
  • search_issues
  • search_pull_requests

Auth: reuse the existing WorkOS Pipes GitHub connection per user (same path as create_github_issue). Reads inherit the user's repo permissions, so private forks work iff the user has access. No service-account token required.

Retire:

  • get_github_issue (member-tools.ts:5395)
  • list_github_issues (member-tools.ts:5479)

These become redundant once the GH MCP read tools land. Keep create_github_issue and draft_github_issue — they have specific WorkOS Pipes + draft-link UX that the GH MCP server doesn't replicate.

Trust boundary

Removing the org allowlist widens the prompt-injection surface: any PR body / review comment becomes attacker-controlled text in Addie's context. Existing mitigation is wrapUntrusted() around GitHub-sourced content. Audit task: confirm every github-mcp-server tool output is wrapped before reaching model context. If the GH MCP server returns structured JSON, add a thin output-mapper that wraps each user-controlled string field.

Out of scope (deferred)

  • Single facade tool (github_read with action enum) — revisit if 6–8 tools clutter the catalog noticeably.
  • Subagent-based isolation (read-only GH-reader agent) — revisit if PR-text injection in Addie's main loop becomes a real problem.

Acceptance

  • github-mcp-server mounted with the allowlist above
  • Tool outputs pass through wrapUntrusted (or equivalent) for any user-controlled field
  • get_github_issue and list_github_issues removed; references updated
  • Tool catalog (generated/tool-catalog.generated.ts) regenerates cleanly
  • Manual smoke: PR diff on a fork PR, review threads on an adcontextprotocol/adcp PR

Metadata

Metadata

Assignees

No one assigned

    Labels

    addieIssues related to Addie (via any channel)claude-triagedIssue has been triaged by the Claude Code triage routine. Remove to re-triage.enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions