Connect GitHub Copilot to MCP Servers

Agents, MCP & Agentic DevelopmentAcademy lesson 84Cluster 7 · Lesson 9 of 13Intermediate → Advanced15 min readVersion-sensitive
Published
Updated
Last technically verified
Connect GitHub Copilot to MCP ServersAgents, MCP & Agentic Development9Intermediate → Advanced/github-copilot/agents/connect-mcp-server/

MCP configuration looks portable and is not. The JSON is similar enough across clients to invite copying and different enough that a copied file frequently does nothing at all — with no error, because a configuration file that is not read cannot complain.

This lesson covers each client’s actual format, and what to check when a server does not appear.

The landscape

MCP configuration by clientVerified 2026-08-25
MCP configuration locations by Copilot client
ClientConfigurationAuthenticationRemote OAuth
VS Code.vscode/mcp.jsonTop-level key is `servers`. This file is not read by Copilot CLI.OAuth or personal access token for remote serversSupported
Copilot CLI~/.copilot/mcp-config.json, .mcp.json, or .github/mcp.jsonDoes not read .vscode/mcp.json. Migrating one requires reformatting.Per-server; the built-in GitHub server uses the CLI's own sessionNot documented
Copilot cloud agentJSON in repository settings on GitHubNot a file in the repository — configured by a repository administrator in settings.Tokens supplied in configuration; the default GitHub server uses a read-only repo-scoped tokenNot supported
Visual Studio, JetBrains, Xcode, EclipsePer-IDE MCP configurationOAuth or personal access token for remote serversSupported
  • VS Code. A Start button appears above the server list; starting a server discovers its tools and stores them for later sessions.
  • Copilot CLI. The GitHub MCP server is built in and needs no configuration. `copilot mcp add` manages others.
  • Copilot cloud agent. Only tools are supported — not resources or prompts. Copilot uses available tools autonomously without asking for approval.
  • Visual Studio, JetBrains, Xcode, Eclipse. GitHub lists growing remote-server support across these editors.

Read that table before writing any JSON. Nearly every “MCP does not work” report resolves to configuration living somewhere the client in use does not read.

VS Code

Configuration lives in .vscode/mcp.json for a workspace.

{
  "servers": {
    "github": {
      "type": "http",
      "url": "https://api.githubcopilot.com/mcp/readonly"
    }
  }
}

The top-level key is servers. A Start control appears above the server list; starting a server discovers its tools and stores them for later sessions, so tools are available without restarting each time.

For a local server started as a process:

{
  "servers": {
    "filesystem": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/me/projects"]
    }
  }
}

Copilot CLI

{
  "mcpServers": {
    "sentry": {
      "type": "http",
      "url": "https://mcp.example-monitoring.com/",
      "tools": ["list_issues", "get_issue"]
    }
  }
}

Managing servers from the CLI

Rather than editing JSON, the CLI can manage configuration for you.

copilot mcp add SERVER-NAME -- COMMAND [ARGS...]
copilot mcp add --transport http SERVER-NAME URL
copilot mcp list
copilot mcp get SERVER-NAME
copilot mcp remove SERVER-NAME

Options include --env KEY=VALUE, --header, --transport, --tools and --timeout.

Inside an interactive session, the same operations are available as slash commands — /mcp add opens a form, /mcp show lists servers or details for one, and /mcp edit, /mcp delete, /mcp disable and /mcp enable do what their names suggest.

The cloud agent

Configuration is JSON entered in repository settings on GitHub, by someone with administrative access to the repository. There is no file to commit and no local equivalent.

Three properties of this surface change what is worth configuring:

  • Only tools are supported. Not resources, not prompts.
  • Remote servers using OAuth are not currently supported.
  • Copilot uses available tools autonomously and will not ask for approval before use.

Naming servers

A small thing that becomes annoying at scale: server names appear in tool selection, in logs and in the mcp-servers field of agent profiles, so they are worth choosing rather than accepting.

Name the system, not the vendor’s product name. monitoring is more useful than the brand, because the brand may change and the role will not.

Keep names distinct across scopes. A personal server and a project server sharing a name is an ambiguity you do not need, and the resolution is not something to rely on.

Avoid names that collide conceptually. Two servers both plausibly called search will be selected between arbitrarily, which reads as unreliability rather than as a naming problem.

Other IDEs

Visual Studio, JetBrains, Xcode and Eclipse each have their own MCP configuration location, with growing support for remote servers. The server definitions are conceptually the same; the file and its schema are not.

Check your IDE’s own documentation for the location rather than assuming the VS Code path applies. This is the same class of mistake as the CLI case, with the same silent failure mode.

Transports, and which to pick

The type field selects how the client talks to the server, and the choice follows from where the server runs rather than from preference.

Local process, standard input and output. The client starts the server as a child process and communicates over its standard streams. Named stdio in VS Code and local in Copilot CLI — the same idea with different labels, which is one more reason copied configurations fail. This is what you use for a server distributed as a package you run yourself.

HTTP. The server is reachable at a URL. This is the shape of hosted servers, including GitHub’s own remote endpoint, and it is where authentication headers and OAuth come in.

Server-sent events. An older streaming transport, still supported and still seen in existing configurations. New setups generally use HTTP.

The practical guidance is short. If a server publishes a URL, use HTTP. If it publishes a command, run it locally. If documentation shows both, prefer the hosted one unless you have a reason — a network policy, an air-gapped environment, a version you need to pin — to take on running it yourself.

Restricting tools in configuration

The tools field is where a configuration stops being a connection and becomes a permission decision.

{
  "mcpServers": {
    "monitoring": {
      "type": "http",
      "url": "https://mcp.example-monitoring.internal/",
      "tools": ["list_alerts", "get_alert", "search_logs"]
    }
  }
}

Three named tools, all read-only. Whatever else that server exposes — silencing alerts, editing dashboards, changing routing rules — is not available, because it was not listed.

Contrast with the version that omits the field, or uses ["*"]. That grants every tool the server offers today and every tool it adds in a future version, without anyone revisiting the decision.

Credentials

Every client offers a way to supply a secret without writing it into the file. Use it.

Personal or project

Both scopes exist for the CLI, and choosing deliberately avoids two opposite problems.

Personal configuration~/.copilot/mcp-config.json — applies to everything you do. It is the right place for a server tied to you rather than to a codebase: your own notes system, a service you have credentials for that colleagues do not, anything experimental.

Project configuration.mcp.json or .github/mcp.json — applies to work in that repository and can be committed. It is the right place for a server the project genuinely needs, where everyone working on it should have the same setup.

The failure at one extreme: everything personal, so each developer has a different configuration and the same request behaves differently on different machines. Nobody can reproduce anyone else’s result, and the inconsistency gets blamed on Copilot.

The failure at the other: everything committed, including servers most people do not need, so the tool list is long, selection degrades, and someone eventually commits a credential because the file was already there.

Scoping servers to one agent

An agent profile’s mcp-servers field scopes MCP configuration to that agent.

This is worth using more than most people do. A server with genuinely powerful tools does not have to be present in every session — it can belong to one narrow agent whose job needs it, leaving ordinary work unaffected.

The pattern generalises: the more a server can do, the fewer sessions should have it. A monitoring server with read-only tools can reasonably be global. A server that can restart services should belong to exactly one agent, invoked deliberately.

Custom agents covers the profile format this field belongs to.

Migrating a VS Code configuration to the CLI

Since this is the failure everyone hits, here is the actual translation rather than a warning about it.

Start from a working VS Code file:

{
  "servers": {
    "monitoring": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@example/monitoring-mcp"],
      "env": { "MONITORING_REGION": "eu-west-1" }
    }
  }
}

Three changes make it a Copilot CLI personal configuration.

Move it. Into ~/.copilot/mcp-config.json, or into one of the two project files. Not .vscode/mcp.json, which the CLI does not read under any circumstances.

Rename the top-level key. servers becomes mcpServers.

Rename the transport. The stdio type in VS Code is called local here.

{
  "mcpServers": {
    "monitoring": {
      "type": "local",
      "command": "npx",
      "args": ["-y", "@example/monitoring-mcp"],
      "env": { "MONITORING_REGION": "eu-west-1" },
      "tools": ["list_alerts", "get_alert"]
    }
  }
}

The tools list is an addition rather than a translation, and it is worth making while you are here — a migration is a natural moment to narrow what was previously unrestricted.

When a server does not appear

In order, because the first two resolve most cases.

Is the configuration in a file this client reads? For the CLI, that is one of the three paths above and never .vscode/mcp.json. For the cloud agent, it is repository settings and never a file.

Is the top-level key right? servers for VS Code, mcpServers for the CLI’s personal file. A wrong key produces a valid JSON file describing nothing.

Does the client list the server? copilot mcp list, or the equivalent in your IDE. If the server is absent here, nothing downstream is worth investigating.

Did the server start? Local servers are processes and can fail to launch — a missing runtime, a wrong path, an uninstalled dependency. Client logs usually say so plainly.

Did authentication succeed? A started server with a rejected credential looks like a server with no tools.

Are the tools filtered? A tools list narrower than intended, or a read-only mode, will hide exactly the tools you are looking for.

Is an organisation policy blocking it? For Business and Enterprise, the “MCP servers in Copilot” policy gates everything. Check this early in a work account.

Verifying a new server

Adding a server and assuming it works is how people end up debugging the wrong thing a week later. Four checks, each taking seconds.

Confirm the client sees it. copilot mcp list or the IDE equivalent. Present or absent — no interpretation required.

Confirm the tools you expect are exposed. A server can be connected and exposing nothing useful, most often because the tools list or a read-only mode is narrower than intended.

Ask for something only that server can answer. Not a question the model could answer from general knowledge — something specific to the system behind the server, where a fabricated answer would be obviously fabricated.

Confirm the boundary. Ask for something that would require a tool you did not enable. It should decline or fail. If it succeeds, your configuration grants more than you thought, and finding that out deliberately is much better than finding it out later.

Keeping configuration reviewable

Some habits that save trouble once more than one person is involved.

Commit project configuration; keep personal configuration personal. A server the team needs belongs in .github/mcp.json. An experiment belongs in your home directory.

Pin the tools list explicitly. A configuration that enumerates its tools tells a reviewer exactly what was granted. One that omits the field grants whatever the server offers today and whatever it adds tomorrow.

Review configuration changes as permission changes. A pull request adding a server is a pull request adding capability. The diff is small and the consequences are not.

Re-check after server updates. Servers gain tools between versions, and nothing announces it. A periodic look at what is actually exposed is worth more than a policy nobody re-reads.

Why the silence

It is worth understanding why these failures produce no error, because it changes how you debug them.

A client looks for configuration in the places it knows about. A file somewhere else is not a malformed configuration — it is not a configuration at all, as far as that client is concerned. There is nothing to report, because from the client’s position nothing happened.

The same applies within a file. A top-level key the client does not recognise describes no servers, so the client starts none. It is valid JSON and it parses cleanly. Nothing is wrong except that it means nothing here.

This is the same silent-ignore behaviour that agent profiles and skill frontmatter have, and it has the same consequence: absence of an error is not evidence that something worked. The only reliable signal is positive confirmation — the server appearing in a list, a tool actually being called, an answer that could only have come from the system behind it.

Build the habit of confirming rather than assuming, and MCP configuration stops being mysterious.

Common questions

Can I use the same file for VS Code and the CLI? No. Different locations, different top-level keys, different transport names, and the CLI does not read the VS Code file at all. Translate it once, following the migration section above.

Does the CLI need the GitHub MCP server configured? No. It is built into Copilot CLI and uses the CLI’s own authenticated session, so configuring it there is effort spent on something you already have.

What is the difference between .mcp.json and .github/mcp.json? Both are project-level for the CLI; .github/mcp.json is the conventional place for configuration meant to be shared with the repository.

Can a project configuration override a personal one? Both are read. If the same server name appears in more than one, expect the more specific location to apply, and avoid the ambiguity by not duplicating names.

Do I need to restart after changing configuration? Behaviour differs by client. VS Code discovers tools when a server starts and remembers them; the CLI picks up configuration when a session begins. When in doubt, start a fresh session before concluding a change had no effect.

Can I disable a server temporarily? In the CLI, /mcp disable SERVER-NAME does exactly that without deleting the configuration, which is useful for isolating whether a server is responsible for odd behaviour.

How do I remove a server cleanly? copilot mcp remove SERVER-NAME for the CLI, or delete the entry. Also revoke any credential you created for it — a removed server with a live token is a token nobody is managing.

A configuration review checklist

When an MCP configuration arrives in a pull request, six questions cover it.

Which server is this, and who maintains it? An official server from the vendor whose system it reaches, a registry-listed server, or an unfamiliar package are three different levels of trust.

What are its tools, and is the list enumerated? A tools field naming specific tools is reviewable. An omitted field or a wildcard is a grant of whatever exists now and whatever appears later.

Can any of those tools change something? Sort them mentally into read, mutate and act-outside. Anything in the third category needs a stated reason.

What credentials does it use, and where do they come from? A literal string in the file is a finding. An input prompt, an environment variable or a secret is fine.

Which surfaces does this configuration reach? A file committed to the repository affects everyone who works in it, including on surfaces with no per-call approval.

Is this replacing something simpler? If the context could have been a paste, a skill or a small script, the server is infrastructure that will need maintaining for a benefit that was already available.

Next

The GitHub MCP server is the one most worth configuring first. The MCP guide covers the protocol, tool risk and the injection surface these configurations open. From here, the cluster turns to complete agents: DevOps is the first.

Sources

Every version-sensitive claim on this page was checked against first-party documentation. Only sources actually used are listed.

Primary sources