GitHub MCP Server, an assistant that sees your repository
A coding assistant working locally sees files but not what surrounds them: issues, pull requests, build results, discussion history. The GitHub MCP server fills that gap, exposing those things as tools a model can call.
The effect shows on tasks that used to require copying. Asking why a test stopped passing, or requesting a fix for an issue somebody else described, becomes one instruction rather than a series of copies from the browser.
Remote and local variants
The server exists in two forms and choosing between them is the first decision.
The remote variant runs on GitHub's side, so you install nothing and manage no token by hand, since authentication uses a standard authorisation flow. That is the simplest route and suffices for most uses.
The local variant runs as a container or an executable and takes your own token. Reach for it when working with a GitHub installation on your own infrastructure, when company policy forbids an outbound connection, or when you want precise control over what the server sees.
{
"mcpServers": {
"github": {
"command": "docker",
"args": ["run", "-i", "--rm",
"-e", "GITHUB_PERSONAL_ACCESS_TOKEN",
"-e", "GITHUB_TOOLSETS=repos,issues,pull_requests",
"ghcr.io/github/github-mcp-server"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${env:GITHUB_TOKEN}"
}
}
}
}The configuration goes into the settings file of whichever tool you use, Cursor or a terminal assistant for instance. The protocol itself is covered more broadly in the piece on MCP.
Toolsets
By default the server enables five toolsets: context, repositories, issues, pull requests, and users. Everything it can do, dozens of tools, arrives only with the toolset named all. With a set that size the model picks the wrong tool more often, and every description occupies context space.
Toolsets let you enable only what you actually use. Code work usually needs repositories, issues, and pull requests. Diagnosing a build pipeline adds action runs. Security review adds scanning alerts.
In the remote variant you name the set with a header or a URL fragment, in the local one with an environment variable. The effect is the same: a shorter tool list and better model choices.
The practical rule: stay on the default toolset or narrow it to three entries, and add more once you notice something missing. The reverse order, enabling everything and pruning later, ends with nobody tidying it up.
Read only mode
This is the most important setting from a security standpoint and worth understanding precisely.
Read only mode disables every writing tool: creating issues, commenting, merging, pushing changes. It acts as an overriding filter, so it applies even when your configuration asks for a toolset containing writing tools.
That distinction matters practically, since it separates two kinds of work. An assistant meant to help understand code and answer questions needs no write access. An assistant meant to open pull requests does, and then it is a deliberate decision with a bounded scope.
Enabling read only by default and widening permissions only where needed is cheap and removes a whole category of problems. An irreversible operation performed by a model's mistake hurts more than changing a setting once a week.
Token permissions
In the local variant the token is the only boundary on what the server can do, so its scope deserves attention.
A broadly scoped token grants access to every repository you can reach. On an organisation account that can be several hundred repositories, including ones you have forgotten. A narrowly scoped token, tied to specific repositories and specific permissions, limits that to what you actually work on.
A sensible permission set for code work covers reading repository contents plus reading and writing issues and pull requests. Administrative permissions, organisation management, and secret access are unnecessary and should not appear there.
Set an expiry date too. A token without one lives until somebody deletes it, and nobody deletes tokens they have forgotten.
Prompt injection through issue content
This threat is specific to the integration and rarely discussed, and it is worth understanding.
The server fetches the content of issues, comments, and pull request descriptions, and that content comes from anybody who can open an issue in your repository. If the assistant treats it as an instruction rather than as data, somebody outside can influence what the assistant does.
In a public repository that is not a theoretical scenario. An issue containing text posing as a command can push a model into an action nobody intended, particularly when the assistant holds write access and other tools.
Three things limit that risk. The first is read only mode wherever writing is unnecessary. The second is narrowing the token to the repositories you work on. The third is reviewing what the assistant intends to do before it does it, rather than allowing actions without confirmation.
Configuring the remote variant
The remote variant is configured by URL, so changing tool scope comes down to changing one line.
{
"mcpServers": {
"github": {
"url": "https://api.githubcopilot.com/mcp/x/repos/readonly"
}
}
}The URL fragment names the toolset and the suffix enables read only mode. Headers achieve the same effect, which is sometimes more convenient with programmatically generated configuration.
That arrangement allows something a single server could not: connecting two entries with different permissions. One with the full toolset in read only mode for browsing and questions, another narrow one with write access limited to issues. The assistant then sees a lot and can change little.
Check how your tool handles authentication for the remote variant. Some clients run the authorisation flow automatically on first use, some still require a token, and that changes how you configure it.
How it changes daily work
It helps to understand where the real saving sits, since it is not where people expect.
The point is not that an assistant does something a person cannot. The point is that switching context between editor and browser stops being necessary. Asking what changed in this module last month means opening the repository, finding the history, reviewing changes, and returning to the code. With the server it is one sentence without leaving the editor.
The second thing is combining sources. Answering why a test stopped passing requires putting a run log beside a code diff and sometimes beside issue text. A model does that in one step, since all three are available through tools.
The third is framing changes. An assistant that has read the issue alongside the code proposes a change addressing both rather than only what you pasted into a prompt.
The boundary sits at decisions. The server gives access to information rather than to an understanding of why the team decided something two years ago. That knowledge usually lives outside the repository, in conversations, and has to be sought there separately. The Slack server gives an assistant search across the thread archive, except that it runs on the token of whoever connected it, so it sees exactly the channels that person sees and nothing beyond.
What it is good for in practice
Four uses recur most often and are worth starting with.
Diagnosing a failed pipeline run: the assistant pulls the run log, finds the error, and ties it to the change that caused it. That task means several minutes of clicking by hand.
Working on an issue somebody else described: the assistant reads the description, finds the right place in the code, and proposes a change. Quality here follows directly from description quality, so a one sentence issue yields a one sentence result.
Reviewing your own pull request before asking somebody else: the assistant reads the diff alongside repository context and flags the obvious. That is a pre filter rather than a substitute for review.
Answering questions about history: when this function changed, who wrote this module, whether a similar problem occurred before. The advantage over searching in a browser is that the answer forms alongside code context.
Against the alternatives
| Option | Strength | Weakness | Pick it when |
|---|---|---|---|
| GitHub MCP server | Full access to issues, changes, and runs, official support | Needs care with permissions | Daily repository work inside an assistant |
| GitHub Copilot | Integration with no configuration | Less control over scope | Team already using that package |
| GitHub command line | Deterministic, scriptable | The model will not call it itself | Automation and scripts |
| Your own MCP server | Exactly the tools you want | You write and maintain it | An unusual workflow |
Consider the third row when a task is repeatable. A script built on the command line runs identically every time and costs nothing, while the same task assigned to a model costs tokens and is sometimes done differently.
The practical split runs like this: repeatable, well defined things go to scripts, things requiring comprehension of content go to an assistant with this server. That line shifts over time, but what draws it is cost and predictability rather than what the model can do.
Rolling out to a team
Individual configuration is one thing and team wide agreements another. A few decisions deserve making together before everybody configures the server their own way.
The first concerns token scope. Settle that nobody uses a full scope token for assistant work, and supply a sample permission set sufficient for daily tasks. Without that, the widest permission becomes the default practice, since it works immediately.
The second is repositories excluded from the integration. Repositories holding production configuration, deployment keys, or sensitive data belong outside the token's scope, even when the assistant runs read only.
The third is a rule about writing actions. A pull request opened by the assistant goes through the same review as any other, and whoever assigned it answers for the content. The same applies to issue comments, since they are visible to customers and to people outside the team.
The fourth is a shared configuration file in the repository. Toolset and read only settings can live as a sample file so a newcomer does not start from nothing and does not copy somebody's configuration with a token inside.
Common mistakes
The first is a full scope token. The assistant then reaches every repository in the organisation while working on one.
The second is enabling every toolset. Dozens of tools in context lower selection accuracy and occupy space that could hold code.
The third is working with write access where read suffices. Read only mode costs one setting and removes the risk of an irreversible operation.
The fourth is treating issue content as instructions. It is data from anybody outside, so an assistant should read it rather than execute it.
The fifth is a token without an expiry saved in a configuration file. Such a file sometimes reaches a repository, and the token lives on.
The sixth is assigning the assistant tasks described in one sentence. The result matches the description, so an issue like "improve performance" yields a proposal you cannot accept.
FAQ
How does this differ from GitHub Copilot?
It is a server exposing GitHub's tools to any assistant supporting the MCP protocol, so you can use it in Cursor, in a terminal assistant, or in your own application. GitHub Copilot is a finished product with its own integration, needing no configuration but offering less control over scope.
Remote or local variant?
Remote is simpler: no installation, standard authorisation flow, updates on the vendor's side. Choose local with a GitHub installation on your own infrastructure, under a ban on outbound connections, or when you want precise control over token scope.
Is it secure?
It depends on configuration. Read only mode by default, a token narrowed to specific repositories, and confirmation on writing actions keep the risk small. A full scope token with write access and automatic action execution is an entirely different situation.
How many tools should I enable?
The default toolset, meaning context, repositories, issues, pull requests, and users, covers most daily work and needs no configuration at all. Narrow it to three entries when context budget matters, and add more once you notice a gap, since a shorter tool list means better selection on the model's side.
Does it work with GitHub Enterprise?
Yes, the local variant supports installations on your own infrastructure by pointing at the instance address. That is in fact one of the main reasons this variant exists alongside the simpler remote option.
Documentation and code sit in the GitHub repository, and configuration details in the server configuration guide.