A Copilot plugin for Copilot Studio MCP in any environment
October 26, 2026
Microsoft hosts the Copilot Studio MCP server once per Power Platform environment, and each environment has its own URL built from its environment ID. A Microsoft 365 Copilot plugin manifest can point at only one fixed URL, so there are two ways to give people Copilot Studio in Copilot:
- One plugin per environment. Publish a plugin for each environment you want to offer, all with the same base skills. Admins control exactly which environments Copilot can reach.
- One plugin with a gateway. Deploy a small gateway once, publish one plugin, and let each user reach every environment they have access to.
Both routes work. I built the gateway so an admin doesn’t have to deploy a plugin for every environment, but it’s optional. If you only want to offer a few environments in Copilot, the per-environment route is simpler and needs no Azure resources. If you build across many environments, especially as a pro-dev, the gateway is the one I recommend.
The Copilot Studio MCP Server folder in my SharingIsCaring repository has the gateway source, the Bicep, and the deployment script. The Copilot Studio plugin is the one that uses it.
Which route fits
| One plugin per environment | One plugin with the gateway | |
|---|---|---|
| Plugins to publish | One for each environment | One |
| Environments available | Only the ones you publish | Any the user can access |
| Azure resources to host | None | A Container App |
| Adding an environment | Publish another plugin | Nothing to do |
| Best for | A short, admin-controlled list | Pro-devs and makers working across many environments |
Pick the per-environment route when the list is short and you want to decide which environments Copilot can reach. Pick the gateway when you move between development, test, and production environments, or when new environments appear faster than you want to package plugins.
What the gateway does
The plugin talks to the gateway at one URL. The gateway:
- Adds a required
environmentIdargument to every Copilot Studio tool. - Adds a
list_environmentstool that returns the environments the signed-in user can access. - Forwards each call to the environment the model chose.
It doesn’t rewrite Copilot Studio’s tools. It reads the tool list from Copilot Studio when it needs it, so new tools and schema changes appear without a redeploy.
| Tool | What it does |
|---|---|
list_environments |
Lists the environments the user can access |
get_copilot_studio_skills, manage_agents, manage_workflows, discover_resources, get_consumption |
Copilot Studio’s own tools, each with environmentId as the first required argument |
Copilot asks which environment to use when it isn’t clear, and names the environment before it changes anything.
Each person signs in as themselves
The plugin signs the user in to the gateway’s own Microsoft Entra API with the scope access_as_user. The gateway then:
- Checks the token. It validates the signature, tenant, audience, lifetime, and scope. Requests from another tenant, for another audience, or without the scope are refused. A token issued for Power Platform is refused too.
- Exchanges it. It trades the token for a Power Platform token for the same user with the on-behalf-of flow. Entra only does this when the app has consent for the Power Platform permissions, so consent is the control point.
- Calls Copilot Studio. Copilot Studio and Power Platform permissions decide what the user can do.
A token issued for Power Platform carries a nonce in its header, so only Power Platform can verify its signature. A gateway that forwarded it would have to trust the caller. Issuing the token for the gateway itself avoids that.
A few design choices keep the gateway small and safe to run:
- No secret to store. The gateway proves it’s the Entra app with a token from its user-assigned managed identity, trusted through a federated credential that
deploy.ps1creates. - No user data stored. Exchanged tokens stay in memory, keyed by a hash of the caller’s token, and expire with it.
- Power Platform only. The hostname is built from a checked GUID plus the fixed suffix
environment.api.powerplatform.com, so a model-suppliedenvironmentIdcan’t point the gateway at another host. - No retries on tool calls. A retried call could create or change something twice.
- Single tenant. Tokens from other tenants are refused.
The server runs on .NET 10 as a stateless ASP.NET Core app, so any replica can answer any request. It uses plain JSON-RPC instead of the MCP C# SDK, so it can relay Copilot Studio’s messages as they are, including fields newer than the SDK.
Deploy the gateway
You need an Azure subscription, the Azure CLI, permission to register apps in Entra, and an admin to grant consent.
-
Create the Entra app that is both the plugin’s sign-in client and the gateway’s API:
.\scripts\New-PluginClientApp.ps1 -GrantAdminConsent -
Deploy the gateway with the tenant ID and client ID from step 1:
.\infra\deploy.ps1 -ResourceGroup rg-copilot-studio-mcp -TenantId <your tenant ID> -ClientId <client ID>The script provisions Container Apps, Container Registry, Log Analytics, and Application Insights. It builds the image in Azure Container Registry, so you don’t need local Docker. The last line prints the MCP endpoint, and the host without
https://or/mcpis the plugin’sCOPILOT_STUDIO_GATEWAY_HOST. -
Set the tenant ID, client ID, and gateway host in the Copilot Studio plugin, then provision, package, and share it with the
wiqdCLI. Its readme covers each command and the Microsoft 365 admin center upload.
Skills the plugin carries
The plugin ships two shared skills, copilot-studio-access and write-safety, and five scenario skills:
| Skill | Use it to | Changes things |
|---|---|---|
agent-authoring |
Create or edit an agent as a draft, preview it, then publish | Yes, after confirmation |
workflow-authoring-and-diagnostics |
Build workflows, run real tests, diagnose failed runs | Yes, after confirmation |
agent-evaluation |
Create and run evaluation suites and read the results | Yes, after confirmation |
connector-discovery |
Find connector operations, schemas, connections, and parameter values | No |
consumption-review |
See credit consumption by agent or workflow and remaining capacity | No |
These are the base skills in either route. The Copilot Studio MCP server is in preview and its actions can change, so the skills tell Copilot to read each action’s contract at run time instead of relying on fixed action names.
Troubleshooting
401from/mcp: The token is missing, expired, for another tenant, or not issued for the gateway’s app. Check that the plugin requestsapi://<client ID>/access_as_user.403from/mcp: The token lacksaccess_as_user. Check that the Entra app exposes the scope and has consent for it.- “Environment not found or access denied”: The user has no Copilot Studio access in that environment, or it has no Dataverse database.
list_environmentspermission denied:EnvironmentManagement.Environments.Readhas no admin consent. RunNew-PluginClientApp.ps1 -GrantAdminConsentagain or ask an admin.