Skip to main content

Restrict MCP server access when using Github Copilot -

As GitHub Copilot expands its capabilities through the Model Context Protocol (MCP), it introduces an extra security challenge: how to give developers access to powerful AI tools while maintaining control over what external services those tools can access. This post walks you through setting up a curated MCP registry and enforcing access controls across your organization or enterprise when using Github Copilot.

Why restrict access?

MCP servers extend Copilot's capabilities by connecting it to external tools, databases, APIs, and services. While this opens up incredible possibilities for developer productivity, it also introduces potential security risks. Without proper controls, developers could:

  • Connect Copilot to unauthorized external services
  • Expose sensitive data to third-party MCP servers
  • Use tools that don't meet your organization's security or compliance requirements
  • Bypass established security policies through AI-assisted workflows

A way is needed to provide a curated catalog of approved MCP servers while preventing access to unapproved ones.

Understanding MCP registries

An MCP registry serves as a catalog of approved MCP servers, similar to a curated vendor list. Each registry entry points to a server's manifest, which describes the tools, resources, and prompts that server exposes.

The registry serves two key purposes:

  1. Discovery: Makes approved MCP servers visible and easily installable in MCP-compatible environments
  2. Enforcement: When combined with the "Registry only" policy, prevents usage of any MCP servers not defined in your internal registry

Think of the registry as your recommended vendor list, while the enforcement policy determines whether that list is merely suggested or strictly required.

Configuring MCP registry access

To manage the MCP registry access, go to the Organization settings in Github:

  • Click your profile picture, then Organizations
  • Next to your organization, click Settings
  • In the sidebar under "Code, planning, and automation," click CopilotPolicies

  • Under "Features," ensure MCP servers in Copilot is set to Enabled

  • In the MCP Registry URL (optional) field, enter your registry URL

 

  • Click Save

When you also select the "Registry only" enforcement option, the user experience changes significantly:

  • In IDEs: Blocked servers appear greyed out with a clear warning message
  • In configuration files: Blocked servers show "run": "blocked" in the mcp.json file
  • For developers: They can only install and use MCP servers from your approved registry

Remark: MCP registry and allowlist controls are still rolling out across Copilot environments, so it could be that this option doesn’t work yet in your IDE.

Important limitations

The current "Registry only" enforcement has some limitations you should be aware of:

  1. Name-based matching: Enforcement is based only on server name/ID matching, which can be bypassed by editing configuration files
  2. No strict installation prevention: The system doesn't yet prevent installation of non-registry servers at the filesystem level
  3. Recommended security posture: For maximum security, consider disabling MCP servers entirely until strict enforcement becomes available

GitHub is actively working on enhanced enforcement with stricter configuration matching that will verify command paths, arguments, and environment variables.

More information

Managing policies and features for GitHub Copilot in your enterprise - GitHub Enterprise Cloud Docs

Internal MCP registry and allowlist controls for VS Code Insiders - GitHub Changelog

Meet the GitHub MCP Registry: The fastest way to discover MCP Servers - The GitHub Blog

Popular posts from this blog

Podman– Command execution failed with exit code 125

After updating WSL on one of the developer machines, Podman failed to work. When we took a look through Podman Desktop, we noticed that Podman had stopped running and returned the following error message: Error: Command execution failed with exit code 125 Here are the steps we tried to fix the issue: We started by running podman info to get some extra details on what could be wrong: >podman info OS: windows/amd64 provider: wsl version: 5.3.1 Cannot connect to Podman. Please verify your connection to the Linux system using `podman system connection list`, or try `podman machine init` and `podman machine start` to manage a new Linux VM Error: unable to connect to Podman socket: failed to connect: dial tcp 127.0.0.1:2655: connectex: No connection could be made because the target machine actively refused it. That makes sense as the podman VM was not running. Let’s check the VM: >podman machine list NAME         ...

Cache stampede: when our cache turned against us

While investigating some performance issues, we ran into an ASP.NET Core API that cached a fairly expensive aggregation query for 60 seconds. Under normal load, that was fine: one request rebuilds the cache, everyone else reads from it. Under peak load, dozens of requests would arrive in that same expiry window, all see a cache miss, and all fire the same expensive query in parallel. The database didn't like that. That was the moment when our caching layer stopped helping and started hurting. A burst of requests comes in at the same time, all miss the cache, and all go hammer the database or the downstream API at once. That's a cache stampede . The cache was supposed to protect our backend, and for a few hundred milliseconds it did the opposite. Why this happens IMemoryCache.GetOrCreate (and its async sibling) looks like it protects you, but it doesn't add any locking on its own. Look at the naive version: public async Task<Report> GetReportAsync(string key) ...

The role of ActivitySource in OpenTelemetry for .NET

While doing some pair programming to integrate OpenTelemetry tracing to a .NET application, we had a discussion on how to use the ActivitySource . It looks simple. You new one up, give it a name, start an activity, done. The discussion started when we added a second ActivitySource with the exact same name in a different class. This made us wonder: "Are we duplicating traces now? Is this a memory leak? Do we need a singleton?" So we decided to dig deeper. This post is what we learned… What ActivitySource actually is ActivitySource is part of System.Diagnostics , not part of the OpenTelemetry NuGet packages. Microsoft built tracing primitives directly into the BCL, and OpenTelemetry's .NET SDK simply listens to them. This is why you can add distributed tracing to a library without taking a dependency on OpenTelemetry at all. An ActivitySource is a factory for Activity objects, and an Activity is .NET's name for what OpenTelemetry calls a span.(don’t ask m...