Elegant GitHub Agent using N8N, Docker, & MCP

Building AI-driven developer tooling used to demand weeks of custom code, orchestration scripts, and brittle plug-ins. In this project Foray Consulting compressed that timeline to a single afternoon: we stood up a fully agentic GitHub assistant on top of an n8n + MCP stack running entirely in Docker. Everything you see below can be reproduced from the public repo in minutes.

Architecture Overview

Frontend
The user interface is a lightweight React application that Claude Code generated in a single conversational session. The UI includes a built-in dark-mode theme, action buttons such as “Code Review,” “Surprise Me,” and “GitHub Actions,” and Markdown rendering. The browser never calls GitHub or the model directly; instead, every user action is transformed into a JSON payload and POSTed to a single public webhook, keeping the client free of business logic and simplifying security.

Orchestration
Inside that webhook lives an n8n workflow that acts as the control plane for all agent activity. The canvas contains five clearly defined nodes. A User Chat node receives the HTTP request, the Agent node injects the system prompt and any short-term memory, the Claude Sonnet 3.7 node performs language reasoning, the GitHub MCP Tool node retrieves structured repository data, and a Return Response node sends Markdown back to the caller. Because n8n exposes retries, execution logs, and version snapshots per node, operators can roll back or tune any step without touching code or YAML.

Large Language Model
Reasoning is provided by Anthropic’s Claude Sonnet 3.7, accessed through the OpenRouter gateway. OpenRouter abstracts away vendor APIs, so swapping to GPT-4o, Gemini 1.5, or a local Llama 3 instance is as simple as changing an endpoint URL. API keys are encrypted in n8n’s credential vault, and runtime parameters such as temperature or max-tokens surface as environment variables for on-the-fly experimentation.

Tools
Repository insight comes from a GitHub Model Context Protocol server that is wrapped by SuperGateway. SuperGateway converts the server’s traditional stdin/stdout stream into an HTTP Server-Sent Events (SSE) endpoint, allowing the agent to request file trees, commit diffs, and metadata in real time. Because the transport is now HTTP, additional tools (Fetch for web pages, Filesystem for local files, Jira for tickets) can be added by cloning a container definition and registering the new endpoint in the Agent node’s tool list.

Runtime
Everything runs inside a 60-line docker-compose.yml. The file declares n8n, each MCP server, a shared Postgres volume, health-check probes, and restart policies. Secrets flow in through an .env file, so nothing sensitive is baked into images. Idle memory usage stays below 300 MB, meaning the full stack can run on a laptop, a Raspberry Pi, or an on-prem VM behind a corporate firewall.

So… how does it feel to actually use?

When a visitor clicks “Code Review,” the React front-end sends a more verbose, hard-coded prompt as a webhook call to n8n. The Agent node passes it to Claude Sonnet along with tools registered via the GitHub MCP node. Recognising it needs repository context, Claude invokes the GitHub MCP. The MCP streams structured data (directory listings, diffs, recent commits) back to Claude over SSE. Claude synthesizes these details into a human-readable analysis, which n8n returns as Markdown. The UI renders the response with syntax highlighting and leaves the scroll position at the top so the user can read immediately. Because each layer is containerized and loosely coupled, developers can swap models, insert new tools, or tweak prompts without disrupting the rest of the pipeline, preserving an elegant user experience while encouraging rapid iteration.

Simplest Viable Design

"I wouldn't give a fig for the simplicity on this side of complexity; I would give my right arm for the simplicity on the far side of complexity."
-
Oliver Wendell Holmes

Complex problems invite complex solutions. But systems thinking teaches that complexity can (and should) be strategically isolated. Rather than piling on libraries, we strip each requirement down to the smallest unit that still delivers the outcome, then compose those units in ways that represents irreducible complexity rather than unnecessary complexity. The result is a simplest viable design: just enough architecture to satisfy today’s use-case, yet modular enough to evolve tomorrow.

  1. Anchor every layer to a single responsibility.
    UI renders Markdown, nothing more. n8n orchestrates flow, nothing more. MCP servers surface domain data through a uniform contract. By refusing to blur boundaries, we keep each component cognitively small and independently replaceable.

  2. Choose technologies that optimize for swap-ability.
    The landscape of LLMs, tool chains, and hosting models changes monthly. We pick OpenRouter (model abstraction) and SuperGateway (transport abstraction) precisely because they decouple the agent from any one vendor or protocol. When Claude 4, GPT-5, or a self-hosted Llama stops being hypothetical, a single endpoint update is all that’s required.

  3. Treat glue code as liability, not asset.
    Every custom script is future tech-debt, so we favor declarative configuration over imperative logic. A 60-line docker-compose.yml and an n8n JSON workflow express infrastructure and behavior without hidden side effects. Observability, retries, and credential management are inherited features—not bespoke code.

  4. Invest just enough in extensibility.
    The stack is deliberately tool-agnostic, yet we resist scaffolding “blank” connectors. Need Jira next week? Duplicate an MCP service block, register the endpoint, and you’re done. Until then, the system carries zero overhead.

  5. Exploit container economics.
    Docker gives isolation, reproducibility, and portability “for free.” The same compose file deploys to a localhost laptop for demos, a dev box for integration testing, or an on-prem VM for air-gapped production—without branching environments.

In short, simplicity is achieved by containing complexity, not denying it. By mapping each requirement to the minimum viable module and using industry-standard seams (HTTP + JSON, SSE, environment variables) we turn “AI agent” from a daunting R&D project into a weekend repo. Imminent innovations become plug-ins instead of wholesale rewrites.

Previous
Previous

Multi-Agent Research Flow & Emergence Case Study

Next
Next

Agentic AI for Sales Workflows