DEV Community

johann
johann

Posted on

How to Give AI Agents Safe GitHub Control Without Leaking Secrets: A Least-Privilege MCP Server

How to Give AI Agents Safe GitHub Control Without Leaking Secrets: A Least-Privilege MCP Server in Python

In 2026, autonomous coding agents like Claude Desktop, Cursor, and LangGraph can write entire feature branches, refactor legacy codebases, and generate unit tests in minutes.

However, connecting an LLM directly to your GitHub repository using standard Personal Access Tokens creates critical security vulnerabilities:

  1. Catastrophic Force Pushes: A hallucinated or misconfigured agent can execute a force push (git push -f) directly to main or master, rewriting history and destroying uncommitted team commits.
  2. Abandoned Failing PRs: Agents often push code, submit a Pull Request, and terminate the session immediately. They never check GitHub Actions check-runs, leaving broken builds and failed unit test suites for human developers to debug.
  3. Over-Privileged Token Leakage: If you grant an agent full repo and admin scopes, any prompt injection attack or compromised dependency can read your production environment secrets or delete releases.

In this tutorial, we will build RepoControl, an enterprise-grade Model Context Protocol (MCP) server in Python that provides a least-privilege GitHub control plane with automated branch safety guards, CI/CD failure extraction, and cryptographic evidence attestation.


Architecture: The Autonomous GitHub Control Plane

Instead of granting raw API access, all GitHub interactions from Claude or Cursor are mediated through RepoControl over standardized JSON-RPC stdio:

           +-----------------------------------------------+
           |       AI Agent / LLM (Claude, Cursor, Swarm)  |
           +-----------------------------------------------+
                                   |
                         (MCP JSON-RPC Tools)
                                   v
           +-----------------------------------------------+
           |          RepoControl Pro MCP Server           |
           +-----------------------------------------------+
              |                     |                     |
     (1. Security Guard)    (2. Log Analyzer)    (3. Evidence Ledger)
              v                     v                     v
       +-------------+       +-------------+       +-------------+
       | Permission  |       | CI Failure  |       | SQLite WAL  |
       | & Branch    |       | Extractor   |       | SHA-256     |
       | Guard       |       | (Auto-Fix)  |       | Attestation |
       +-------------+       +-------------+       +-------------+
              |                     |                     |
              +---------------------+---------------------+
                                   |
                           (GitHub REST API)
                                   v
                   +-------------------------------+
                   |      GitHub Repository        |
                   +-------------------------------+
Enter fullscreen mode Exit fullscreen mode

1. Enforcing Branch Protection & Least Privilege

The first line of defense is ensuring agents can never target protected production branches (main, master, prod, release) with destructive operations or open PRs where the head equals base:

PROTECTED_BRANCHES = {"main", "master", "prod", "production", "release"}
DISALLOWED_ACTIONS = {"delete_repo", "delete_branch", "force_push", "delete_release", "read_secrets"}

class PermissionGuard:
    def __init__(self, max_mutations_per_min: int = 30):
        self.max_mutations = max_mutations_per_min
        self.mutation_timestamps = []

    def validate_action(self, action_name: str, params: dict):
        if action_name in DISALLOWED_ACTIONS:
            raise PermissionError(f"Action '{action_name}' is forbidden by Least-Privilege Guard.")

        target_branch = params.get("base") or params.get("branch") or params.get("head")
        if target_branch:
            clean = str(target_branch).strip().lower()
            if action_name.startswith("delete") and clean in PROTECTED_BRANCHES:
                raise PermissionError(f"Destructive action blocked on protected branch '{target_branch}'.")

        # Sliding-window rate limit prevents recursive agent loops
        self._check_rate_limit()
Enter fullscreen mode Exit fullscreen mode

If an agent attempts to delete a branch or force-push, the MCP tool immediately returns a structured permission rejection, preventing catastrophic accidents.


2. Automated CI/CD Failure Extraction & Auto-Fixing

When a pull request triggers a failing GitHub Actions build, asking a human developer to copy/paste error logs defeats the purpose of autonomous agents.

RepoControl fetches the failed job log, strips ANSI terminal escape codes, and runs an intelligent failure parser:

class CIAnalyzer:
    @classmethod
    def parse_log(cls, raw_log: str) -> dict:
        clean_text = cls.strip_ansi(raw_log)
        lines = clean_text.splitlines()

        matched_errors = []
        context_snippets = []

        for i, line in enumerate(lines):
            stripped = line.strip()
            # Detect pytest failures, assertions, and compiler tracebacks
            if any(k in stripped for k in ("FAILED", "AssertionError", "Traceback", "##[error]")):
                matched_errors.append(stripped)
                start = max(0, i - 1)
                end = min(len(lines), i + 2)
                context_snippets.append("\n".join(l.strip() for l in lines[start:end]))

        return {
            "has_failure": len(matched_errors) > 0,
            "matched_errors": matched_errors[:10],
            "actionable_snippets": context_snippets[:5]
        }
Enter fullscreen mode Exit fullscreen mode

The tool get_action_failure_summary formats this into an actionable remediation prompt:

### CI Failure Remediation Context (owner/repo - Run #12345)
**Detected Errors:**
- FAILED tests/test_auth.py::test_login - AssertionError: Expected 200 got 401

**Log Snippets:**
Enter fullscreen mode Exit fullscreen mode

File 'test_auth.py', line 42, in test_login
assert resp.status == 200

**Action Required:** Modify the offending code, verify locally, and re-push.
Enter fullscreen mode Exit fullscreen mode

The LLM receives the exact root cause directly in its conversation context and can self-heal without human intervention!


3. Cryptographic Evidence Ledger & PR Attestation

To satisfy enterprise compliance and security audits, every action taken by an agent is hashed using SHA-256 and logged into an ACID SQLite WAL ledger.

RepoControl generates an automated Markdown attestation badge embedded in the PR description:

<!-- REPOCONTROL-ATTESTATION-START -->
### ๐Ÿ›ก๏ธ RepoControl Compliance & Evidence Attestation

| Metric | Attestation Value |
|---|---|
| **Verified By** | `Claude-3-7-Sonnet (via RepoControl)` |
| **Target PR** | #42 |
| **Head Commit SHA** | `5694011a6ea3` |
| **Diff SHA-256** | `8f4b2390a12...` |
| **CI Verification** | `Run #8892` (success) |
| **Timestamp** | `2026-10-21 01:15:00Z` |

> *This attestation confirms that changes were validated under Least-Privilege Guard with no protected branch violations.*
<!-- REPOCONTROL-ATTESTATION-END -->
Enter fullscreen mode Exit fullscreen mode

4. Connecting to Claude Desktop & Cursor

In your claude_desktop_config.json:

{
  "mcpServers": {
    "repocontrol": {
      "command": "repocontrol",
      "args": ["run"],
      "env": {
        "GITHUB_TOKEN": "ghp_your_bounded_github_token"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Now, Claude or Cursor can safely invoke:

  • create_pull_request(repo="owner/repo", title="fix(auth): handle expired jwt", head="fix/jwt-expiry")
  • check_ci_status(repo="owner/repo", ref="fix/jwt-expiry")
  • get_action_failure_summary(repo="owner/repo", run_id=12345)

Open Source vs. Enterprise Pro

We have published the open-source RepoControl Lite edition:

For teams deploying autonomous engineering agents at scale, the RepoControl Pro Edition includes:

  • ๐Ÿ” Automated CI/CD Failure Analyzer: Real-time log triage and structured error extraction for agent self-healing.
  • ๐Ÿ›ก๏ธ Least-Privilege Token Scoper & Mutation Throttler: Blocks dangerous API commands and runaway agent mutation loops.
  • ๐Ÿ“œ Cryptographic Evidence Audit Ledger: SQLite WAL audit trail and automated Markdown attestation for PRs.
  • ๐Ÿณ Production Docker & Compose: Containerized sidecar setup.
  • ๐Ÿงช 100% Passing Pytest Test Suite (16/16 tests passing).

๐Ÿ‘‰ Get RepoControl Pro on Gumroad ($14.99 USD)


Summary

AI coding agents are transforming software engineering, but safety boundaries are non-negotiable. With RepoControl and the Model Context Protocol, you get the speed of autonomous agent development with the peace of mind of zero-trust security.

How are you securing AI access to your GitHub repositories? Let's discuss in the comments below!

Top comments (0)