Skip to content

feat(init): detect GitHub repos and register github-mcp-server behind the gateway - #137

Merged
getappz merged 3 commits into
masterfrom
feat/gateway-github-detect
Jul 11, 2026
Merged

feat(init): detect GitHub repos and register github-mcp-server behind the gateway#137
getappz merged 3 commits into
masterfrom
feat/gateway-github-detect

Conversation

@getappz

@getappz getappz commented Jul 11, 2026

Copy link
Copy Markdown
Owner

What

During agentflare init, detect when the project is a GitHub repo and — with
per-integration consent — register github-mcp-server
behind the existing gateway (~/.agentflare/gateway.toml), so its ~160
tools stay reachable via gateway_search/gateway_execute instead of bloating
the host's always-on tool list.

Step 0 of the "GitHub coordinated across multiple AI agents" roadmap.

How

  • Detectgit remote -v output mentions github (matches github.com
    in HTTPS/SSH URLs and SSH host aliases like git@github-alias:org/repo.git,
    and — unlike a fixed .git/config read — worktrees and run-from-subdir).
  • Confirm[Y/n] at the MCP-adding stage (honors --yes), separate from
    the rest of init since it wires an outside service.
  • Register — append [servers.github] (remote HTTP, zero-install) to
    gateway.toml, then print how to store the token
    (agentflare gateway secret set github_token, value Bearer ghp_…).
  • Idempotent — presence checked via gateway_registry::parse_config, so
    re-running never duplicates or clobbers.
  • ExtensibleINTEGRATIONS table (detect fn + TOML block + notes); a
    new gateway-fronted MCP is one entry, no new plumbing.

Tests

5 new unit tests (detection incl. SSH-alias shape, valid parseable output,
idempotent no-duplicate, preserves an existing server); existing init tests
still green.

Closes #136

Summary by CodeRabbit

  • New Features
    • Added optional GitHub MCP integration during setup, with automatic GitHub detection and a separate consent prompt.
    • Registers the integration into the user’s gateway configuration and shows follow-up authentication instructions.
    • Uses idempotent behavior to prevent duplicate entries and preserves any existing gateway configuration.
  • Tests
    • Added coverage for GitHub remote detection (HTTPS/SSH and common host variants) and for integration registration idempotency and preservation of unrelated configuration.

… the gateway

During `init`, detect a GitHub remote (git remote mentions github, incl.
SSH host aliases) and, with per-integration consent, append a [servers.github]
mcp_http entry to ~/.agentflare/gateway.toml so its tools stay behind
gateway_search/gateway_execute. Idempotent via gateway_registry::parse_config;
extensible via the INTEGRATIONS table.

Closes #136
@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

No new commits to review since the last review.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6d6bd76b-5c1a-4b18-8c99-f0efc2a43b70

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR adds a GitHub gateway integration with remote detection, consent-based initialization wiring, idempotent TOML registration, and follow-up token instructions.

Changes

Gateway integration

Layer / File(s) Summary
Integration detection and registration
src/gateway_integrations.rs
Defines the GitHub integration, detects GitHub remotes, checks existing gateway servers, appends the [servers.github] configuration, generates token instructions, and tests registration behavior.
Init consent flow
src/init.rs, src/main.rs
Adds per-integration detection, consent, registration, and follow-up output to initialization, and declares the new module.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Init
  participant GatewayIntegrations
  participant GatewayConfig
  User->>Init: run init
  Init->>GatewayIntegrations: detect GitHub integration
  GatewayIntegrations->>GatewayConfig: check existing registration
  GatewayIntegrations->>User: request consent
  User-->>GatewayIntegrations: approve
  GatewayIntegrations->>GatewayConfig: append servers.github
  GatewayIntegrations-->>User: print registration result and secret instructions
Loading

Possibly related PRs

  • getappz/agentflare#104: Provides the gateway registry parsing used to detect existing server registrations.
  • getappz/agentflare#108: Adds parsing and backend support for the mcp_http authentication fields used by the GitHub gateway configuration.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the PR’s main change: GitHub repo detection and gateway-registered github-mcp-server support.
Description check ✅ Passed The description covers the summary, implementation approach, tests, and reviewer notes, though it uses different section headings than the template.
Linked Issues check ✅ Passed The PR satisfies #136 by detecting GitHub remotes, prompting separately, registering the gateway-backed github server, and keeping the flow idempotent.
Out of Scope Changes check ✅ Passed The changes stay focused on GitHub gateway integration and related tests, with no clear unrelated additions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/gateway-github-detect

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
src/gateway_integrations.rs (2)

52-56: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Substring match can misfire on non-GitHub remotes.

contains("github") matches the literal anywhere in git remote -v output, so a repo hosted elsewhere but named/org'd with github (e.g. https://gitlab.com/org/github-mirror.git) would be misdetected as a GitHub repo. Consider tightening to match the host (e.g. github.com) plus the SSH host-alias case you explicitly support, rather than any occurrence of the word.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/gateway_integrations.rs` around lines 52 - 56, Update
remotes_mention_github to detect GitHub only when the remote host is github.com
or an explicitly supported SSH alias such as github-work, rather than matching
the substring “github” anywhere in git remote output. Preserve case-insensitive
matching and support both HTTPS and SSH remote formats while avoiding repository
or organization path names containing “github”.

136-146: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test does not exercise the double-register path it claims to guard.

The name and inline comment assert that "even a direct re-register must not corrupt the file into two [servers.github]", but register(&GITHUB) is invoked only once here. Since register appends unconditionally (idempotency is enforced by the caller via already_registered), a second direct call would in fact append a duplicate block. Either call register twice to prove the assertion, or reword the test to reflect that dedupe is the caller's responsibility.

💚 Option: exercise the double-register path
     with_temp_home(|| {
         register(&GITHUB);
+        register(&GITHUB); // direct re-register must not duplicate the block
         let first = fs::read_to_string(gateway_toml_path()).unwrap();
         assert!(already_registered("github"));
         assert_eq!(first.matches("[servers.github]").count(), 1);
     });

Note: this assertion will only hold if register itself dedupes; today it does not. If you keep dedupe in the caller only, prefer rewording the test/comment instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/gateway_integrations.rs` around lines 136 - 146, Update
register_is_idempotent_and_never_duplicates to reflect the actual contract:
either invoke register(&GITHUB) twice and implement deduplication in register,
or rename/reword the test and inline comment to verify only caller-side
already_registered guarding. Keep assertions consistent with the chosen
responsibility and current register behavior.
src/init.rs (1)

247-250: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Follow-up note prints even when registration failed.

register() can return a fail writing … status on an I/O error, but the loop still prints post_note() (the "store your token" guidance) as if registration succeeded. Gate the note on success so users aren't told to store a token for a server that wasn't written.

♻️ Suggestion
-        println!("  {}", register(intg));
-        for line in (intg.post_note)() {
-            println!("{line}");
-        }
+        let status = register(intg);
+        let ok = status.starts_with("ok");
+        println!("  {status}");
+        if ok {
+            for line in (intg.post_note)() {
+                println!("{line}");
+            }
+        }

A cleaner alternative is to have register return a Result/bool instead of a status string, so callers don't string-match on "ok".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/init.rs` around lines 247 - 250, Update the registration flow around
register and the post_note loop so post_note() is printed only when registration
succeeds. Use the existing register result/status to distinguish success from
the fail writing status, while preserving the status output and avoiding
token-storage guidance after an I/O failure.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/gateway_integrations.rs`:
- Around line 52-56: Update remotes_mention_github to detect GitHub only when
the remote host is github.com or an explicitly supported SSH alias such as
github-work, rather than matching the substring “github” anywhere in git remote
output. Preserve case-insensitive matching and support both HTTPS and SSH remote
formats while avoiding repository or organization path names containing
“github”.
- Around line 136-146: Update register_is_idempotent_and_never_duplicates to
reflect the actual contract: either invoke register(&GITHUB) twice and implement
deduplication in register, or rename/reword the test and inline comment to
verify only caller-side already_registered guarding. Keep assertions consistent
with the chosen responsibility and current register behavior.

In `@src/init.rs`:
- Around line 247-250: Update the registration flow around register and the
post_note loop so post_note() is printed only when registration succeeds. Use
the existing register result/status to distinguish success from the fail writing
status, while preserving the status output and avoiding token-storage guidance
after an I/O failure.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 07cb44f7-2d01-4d87-be2a-ec983e6d6c64

📥 Commits

Reviewing files that changed from the base of the PR and between c09b89d and 3fdc43b.

📒 Files selected for processing (3)
  • src/gateway_integrations.rs
  • src/init.rs
  • src/main.rs

…uarded

Review follow-up on #137. register() appended the [servers.github] block
unconditionally, relying on the caller's already_registered check; a direct
double-call would have written two [servers.github] tables (invalid TOML). Guard
inside register() so it no-ops on the second call, and make the idempotency test
actually call it twice and assert the file still parses. Also document the
deliberately-broad 'github' substring match.
CodeRabbit follow-up on #137. The post-registration note (how to store the
token) printed even when register() returned a fail/skip status. Gate it on the
'ok' status so a failed write doesn't tell the user to configure a server that
was never written.
@getappz

getappz commented Jul 11, 2026

Copy link
Copy Markdown
Owner Author

Addressed in c4fe5d2: the follow-up token-setup note is now gated on register() returning ok, so it no longer prints when a write fails/skips.

The other two nitpicks:

  • double-register test — already fixed in bd730c8 (the test now calls register twice and asserts the file still parses).
  • substring github match — kept intentionally broad and documented: a rare false positive only yields a declinable prompt, and it must catch SSH host aliases like git@github-appzdev:... (this repo's own remote), which a strict github.com check would miss.

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
git log --oneline -10
echo "---"
git show c4fe5d2 --stat 2>/dev/null || echo "commit not found in shallow history"
echo "---"
git show bd730c8 --stat 2>/dev/null || echo "commit not found in shallow history"
echo "---"
cat src/gateway_integrations.rs 2>/dev/null | sed -n '1,250p'
echo "---init---"
sed -n '1,200p' src/init.rs 2>/dev/null | grep -n "post_note\|register\|ok"

Length of output: 10832


All three follow-ups check out against the current code:

  • Token note gatingsrc/init.rs now only prints post_note() when register() returns a status starting with ok (per c4fe5d2).
  • Idempotencyregister() itself checks already_registered(intg.name) and returns skip before writing, so a direct double-call no longer produces a duplicate [servers.github] table; the test register_is_idempotent_and_never_duplicates now calls register twice and asserts a single [servers.github] block plus successful re-parse (per bd730c8).
  • Broad github substring match — confirmed in remotes_mention_github, with the rationale documented inline (catches SSH aliases like git@github-work:..., and a false positive only surfaces a declinable prompt). That's a reasonable, well-documented trade-off — no further action needed from my side.

Everything looks solid. Triggering a fresh review pass now to confirm nothing else needs attention.


✏️ Learnings added
Learnt from: getappz
URL: https://github.com/getappz/agentflare/pull/137

Timestamp: 2026-07-11T11:49:48.139Z
Learning: In agentflare (Rust), `src/gateway_integrations.rs` intentionally uses a broad, deliberate substring match (`.to_lowercase().contains("github")`) in `remotes_mention_github()` for detecting GitHub remotes, instead of a strict `github.com` host check. This is because it must also catch SSH host aliases such as `gitgithub-appzdev:...`, which a strict check would miss. A rare false positive only leads to a declinable consent prompt, which is an accepted trade-off.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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(init): detect GitHub repos and register github-mcp-server behind the gateway

1 participant