Building and Scaling a Production MCP Server for Developer Tooling

github · Tech · 2026 · source Agentic: yes · promotional bias: low · source-backed · extracted with prompt 0.5.5 (schema v2)

Generated from extraction.json — do not edit by hand. Every claim cites verbatim source evidence; stated means the quote directly asserts the claim, implied means it supports it indirectly.

Problem

Domain: Developer tooling infrastructure

GitHub needed to run a production MCP server that gives agents broad access to GitHub tools without overwhelming model context, weakening security, or making tool calls unreliable at large public adoption scale.

Constraints:

Architecture

GitHub operates its MCP server as a stateless remote HTTP service. Each request creates a fresh SDK server instance, dynamically adds tools according to user configuration, token scopes, OAuth grants, policies, and server-token context, then calls GitHub APIs on the agent's behalf. Redis session storage tracks client identity rather than holding stateful MCP process state. The team reduced default tool context, grouped CRUD operations, trimmed tool outputs, encoded multi-call GitHub workflows behind higher-level tools, added evals that test tools against each other, and moved authentication toward OAuth 2.1 with PKCE, step-up OAuth, and permission-based tool filtering.

Diagram confidence: explicit (topology described by the source).

flowchart LR
  mcp-clients[MCP clients] --> remote-mcp-service[Remote MCP service]
  mcp-clients --> oauth-flow[OAuth flow]
  oauth-flow --> permission-filter[Permission filter]
  remote-mcp-service --> request-server-instance[Request server instance]
  remote-mcp-service --> redis-session-storage[Redis session storage]
  remote-mcp-service --> observability-stack[Observability stack]
  request-server-instance --> tool-configuration-and-policies[Tool configuration and policies]
  tool-configuration-and-policies --> permission-filter
  permission-filter --> github-api-tools[GitHub API tools]
  request-server-instance --> github-api-tools
  github-api-tools --> github-apis[GitHub APIs]
  evaluation-pipeline[Evaluation pipeline] --> github-api-tools
  evaluation-pipeline --> observability-stack
  insiders-feature-flags[Insiders feature flags] --> remote-mcp-service
  insiders-feature-flags --> mcp-clients
Drag to pan · scroll or use +/− to zoom · reconstructed from the source's described component topology

Components

Component Role Interacts with
MCP clients Developer clients, IDEs, agent harnesses, and experimental clients that connect to GitHub's MCP server. Remote MCP service, OAuth flow
Remote MCP service Stateless production service that receives MCP requests, creates per-request server instances, and coordinates tool execution. MCP clients, Request server instance, Redis session storage, Observability stack
Request server instance Fresh SDK server instance created on every request with the exact tools the user requested or is allowed to use. Remote MCP service, Tool configuration and policies, Permission filter, GitHub API tools
Tool configuration and policies Default tool set, read-only mode, grouped tools, feature flags, and enterprise policies that shape the exposed tool surface. Request server instance, Permission filter
Permission filter Filters tools by PAT scopes, OAuth scopes, step-up challenges, and server-token identity to avoid unauthorized or guaranteed-failing calls. Request server instance, OAuth flow, GitHub API tools
OAuth flow Remote authentication path using OAuth 2.1, PKCE, and step-up OAuth for additional scopes. MCP clients, Permission filter
GitHub API tools Higher-level MCP tools for repositories, issues, pull requests, actions, projects, and user-specific GitHub operations. Request server instance, GitHub APIs
GitHub APIs Underlying GitHub platform APIs invoked by MCP tools, sometimes in multi-call server-side workflows. GitHub API tools
Redis session storage Session store used mainly to identify self-reported client identity without requiring sticky server process state. Remote MCP service
Evaluation pipeline Runs evaluations that test tools in competition with one another so descriptions and tool surfaces are tuned holistically. GitHub API tools, Observability stack
Observability stack Tracks usage patterns, tool failures, client identity, token consumption, and production operation of the remote server. Remote MCP service, Evaluation pipeline
Insiders feature flags Opt-in experimental channel for capabilities such as MCP apps and human-editable issue drafting. Remote MCP service, MCP clients

Data flow

A client connects to GitHub's remote MCP server using OAuth or a token. On each request, the service creates a new MCP server instance, filters the available tools according to user configuration, token scopes, policies, or server-token identity, and exposes only the allowed tool surface. The agent calls those tools; server-side implementations may perform multiple GitHub API calls to satisfy the intent robustly. Redis-backed session data records client identity, observability tracks tool usage and failures, and evals compare tools in the pool to tune descriptions, context footprint, and call behavior.

3 supporting quotes
“we actually make a brand new in the SDK sense a brand new server instance on every single request and we add the tools to it at the start.”transcript, stated
“if you log into GitHub MCP with a PAT token that we just immediately filter the tools down by the scopes that the token has.”transcript, stated
“we have been using Redis for session storage, you know, it's standard observability and deep kind of stack. Like this is not a weird picture, but I guess one of the weird things for some people is a lot of people are running a stateful MCP server process in”transcript, stated

Why this architecture

GitHub's design pushes complexity into the MCP server because agents perform worse when every raw tool and edge case is dumped into context. Dynamic request-time tool construction lets defaults, permissions, and policies be applied automatically, matching the reality that users rarely configure tool sets. OAuth and step-up scopes make secure remote auth the easier path, while stateless per-request instances and Redis-backed client identity keep the service horizontally scalable. Evaluating tools against each other matches the actual agent decision problem: tools compete inside one context window.

4 supporting quotes
“know, of the exact kind of problems we were seeing. More tools don't make better agents, you know, they get confused and forgetful. Well, I say more tools like more context and more tools shoved directly into the context to be precise. But uh yeah, GitHub's a really expansive platform. And we”transcript, stated
“Everyone used the default settings. It was really annoying because like in a way we had all these elegant solutions.”transcript, stated
“And we wanted to make secure connection path of least resistance. Uh we didn't want users to have to download a local runtime.”transcript, stated
“you try to test them against each other to try and make sure that they're called at the right times and not called at the wrong times.”transcript, stated

Models used: agent client models · Claude Code tool search · OpenAI tool-search-like APIs

Scale

Alternatives considered (roads not taken)

Expose every GitHub tool directly in the model context

Rejected because: Agents became confused and forgetful when over 100 tools and too much context were shoved directly into the window.

“More tools don't make better agents, you know, they get confused and forgetful. Well, I say more tools like more context and more tools shoved directly into the context to be precise.”transcript, stated

Rely on users to configure tool sets, dynamic tool selection, or semantic tool search

Rejected because: Those designs required user configuration, and most users simply kept defaults.

“I quick- quickly added this thing tool sets, which was, you know, a kind of grouping concept of related product tools. And users could just pick which ones they wanted and configure it.”transcript, stated
“all they did was require users to actually, you know, configure the JSON a little bit. And most users just don't.”transcript, stated

Expose low-level API sequences to the agent

Rejected because: GitHub moved robust multi-call operations into server-side tools to save round trips, context, time, and improve success.

“you might have to make five API calls to make it more robust. But you know, in that case, we do that in the server side to reduce round trips”transcript, stated

Dynamic client registration for OAuth

Rejected because: GitHub judged it operationally risky because it caused app-database growth, rate-limit bucketing problems, and unreliable app identity.

“it's hard not to have unbounded growth of app databases and challenges of how you would bucket them for rate limits and there isn't a reliable app identity.”transcript, stated

Stateful singular MCP server processes

Rejected because: GitHub chose a stateless server setup with Redis and per-request server construction to scale without session affinity.

“we run a completely sort of stateless server setup and um we have been using Redis for session storage, you know, it's standard observability and deep kind of stack. Like this is not a weird picture, but I guess one of the weird things for some people is a”transcript, stated
“we've been able to scale to this point we serve around 7 million tool calls a week. And we you know, we don't have session affinity.”transcript, stated

Patterns

tool-use-orchestration (agent-tooling)

GitHub wraps platform operations as MCP tools, dynamically exposes the right tools per request, and hides multi-call GitHub API workflows behind single agent-facing tools.

“we do that in the server side to reduce round trips cuz that, you know, saves context, saves time, and usually um [snorts] makes uh massively better experience”transcript, stated

context-compaction (context-management)

The team reduced default tool context, grouped tools, filtered by permissions, and cut verbose outputs so agents see less irrelevant MCP context.

“we cut the amount of context used by focusing the tools more specifically to the general case. And based on usage to like about 49% reduction of the initial load.”transcript, stated

safety-policy-enforcement (security)

PAT scopes, OAuth scopes, server-token identity, and policies dynamically remove tools the user should not or cannot use.

“if you log into GitHub MCP with a PAT token that we just immediately filter the tools down by the scopes that the token has.”transcript, stated
“server tokens as well. Like they didn't have a like on actions and things, they didn't have a user. So, user-specific tools are kind of out there and then by removing those”transcript, stated

eval-driven-development (quality)

GitHub evaluates tools in the context of the full tool pool, checking whether each tool is called at the right and wrong times rather than only optimizing isolated descriptions.

“instead of micro-optimizing individual tool descriptions, you know, you try to test them against each other to try and make sure that they're called at the right times and not called at the wrong times.”transcript, stated

human-in-the-loop-gate (workflow)

Insiders MCP apps let users review and edit agent-drafted GitHub issues before posting them publicly.

“it's quite nice when you're talking to the agent to have the opportunity to kind of edit the AI-generated uh issue”transcript, stated

Tradeoffs

Context strategy

Chose optimize and filter the default tool set over exposing the full GitHub tool universe by default.

Rationale: Broad access was valuable, but too much tool context degraded agent performance; the default needed to work for users who never configure anything.

“More tools don't make better agents, you know, they get confused and forgetful.”transcript, stated
“all they did was require users to actually, you know, configure the JSON a little bit. And most users just don't.”transcript, stated

Tool abstraction

Chose server-side intent-encoded tools over agent-managed sequences of raw GitHub API calls.

Rationale: Moving edge cases into server code reduces round trips, context use, time, and tool failures.

“you might have to make five API calls to make it more robust. But you know, in that case, we do that in the server side to reduce round trips”transcript, stated

Authentication path

Chose remote OAuth with PKCE and step-up scopes over local runtimes and long-lived plaintext access tokens.

Rationale: OAuth made secure connection easier for clients and allowed incremental permission grants instead of broad token exposure.

“And we wanted to make secure connection path of least resistance. Uh we didn't want users to have to download a local runtime.”transcript, stated
“On OAuth, we support step-up OAuth. So, you know, you can get a we could return a scope challenge and then it will interactively ask the user if they want to allow the scope.”transcript, stated

OAuth client identity

Chose reject dynamic client registration over accepting unbounded dynamic client records.

Rationale: GitHub judged DCR too costly for application databases, rate-limit grouping, and reliable app identity.

“if you implement it kind of properly, it's hard not to have unbounded growth of app databases and challenges of how you would bucket them for rate limits and there isn't a reliable app identity.”transcript, stated

Deployment model

Chose stateless per-request MCP server construction over stateful singular MCP server processes.

Rationale: A fresh request-scoped instance lets the service dynamically assemble tools and scale without session affinity.

“we actually make a brand new in the SDK sense a brand new server instance on every single request and we add the tools to it at the start.”transcript, stated

Gotchas (what bit them)

Large MCP tool surfaces can make agents worse, not better.

Root cause: Over 100 tool descriptions and platform coverage were shoved into context, causing confusion and faster context-window exhaustion.

Resolution: Optimize the default tool surface, group CRUD tools, reduce outputs, and continue experimenting with better tool discovery approaches.

“After a month or so of new features, agents in some ways were getting worse at using GitHub and context windows were getting blown out quicker.”transcript, stated

Elegant configuration options failed because users kept defaults.

Root cause: Tool sets, dynamic selection, and semantic discovery still depended on users or clients configuring the server.

Resolution: Treat the default experience as the product and optimize it from observed usage patterns.

“Everyone used the default settings. It was really annoying because like in a way we had all these elegant solutions.”transcript, stated

Plaintext access tokens created a standing security hazard.

Root cause: MCP users often stored long-lived, over-privileged tokens where agents could access them.

Resolution: Move secure remote HTTP/OAuth to the path of least resistance and support OAuth 2.1, PKCE, token-scope filtering, and step-up scopes.

“we've a lot of people using plain text access tokens for MCP in the wild. And uh usually they're stored somewhere the agent can access. They're frequently long-lived. They're often over-privileged.”transcript, stated

Some tool failures came from agents not knowing permissions.

Root cause: Agents may call repositories or user-specific tools they cannot access, and hallucination cannot be eliminated entirely.

Resolution: Filter available tools by token scopes, OAuth scopes, server-token identity, and user-specific context before the agent sees them.

“not all failure is preventable cuz agents don't necessarily know which repos they have write permission on. They still hallucinate.”transcript, stated

Prompt-injection exfiltration remains structurally hard for useful agents.

Root cause: Useful agents combine private-data access, external instructions, and external communication, the same capabilities behind the lethal-trifecta attack.

Resolution: Support different user risk profiles and security postures while acknowledging the industry has not solved the underlying conflict.

“the utility of agents is in conflict direct conflict with kind of protecting this stuff and it's like it's an active space trying to work out how to prevent these problems, but uh it's not solved”transcript, stated

Evaluation

GitHub evaluates the MCP server by looking at production usage patterns, tool failure data, token consumption, and tool-choice evals that test tools against each other in the same pool rather than optimizing descriptions in isolation.

Metrics: over 95% tool-call success rate · 49% initial context-load reduction · over 75% token reduction for list pull requests output · around 7 million tool calls per week · approaching 8 million tool calls per week

3 supporting quotes
“And the success rate is roughly, I think, over 95% at this point. But uh like not all failure is preventable cuz agents don't necessarily know which repos they have write permission on.”transcript, stated
“one of the gists is instead of micro-optimizing individual tool descriptions, you know, you try to test them against each other”transcript, stated
“But uh like we started trying to optimize and we looked at the use the usage patterns on our remote server. And initially, you know, we cut the amount of context used by focusing the tools more specifically to the general case.”transcript, stated

Outcomes

The talk frames the server as high-scale production infrastructure: per-request stateless MCP construction, no session affinity, millions of weekly tool calls, and open-source traffic over seven issues/PRs per day for more than a year.

3 supporting quotes
“we've been able to scale to this point we serve around 7 million tool calls a week. And we you know, we don't have session affinity.”transcript, stated
“over 2,300 issues and PRs which it's been over seven a day like every single day for over a year now”transcript, stated
“nearly 30,000 stars and uh we're fast approaching 8 million tool calls a week.”transcript, stated