Hi
@NH-10091149-0,
I don't think you need to create one Copilot Studio agent per tenant, but I also don't see a supported way to directly parameterize the MCP Server URL in the MCP tool configuration.
The current Copilot Studio MCP configuration expects a concrete HTTPS Server URL when the MCP server is added. Copilot Studio connects to that URL during the MCP handshake and reads the tools exposed by the server.
So something like:
https://app.simplicontract.com/tenants/{tenant}/mcp
shouldn't be assumed to work as a runtime template.
I would change the MCP architecture slightly
Instead of making the tenant part of the MCP URL:
Copilot Studio
↓
https://app.simplicontract.com/tenants/abc/mcp
https://app.simplicontract.com/tenants/xyz/mcp
expose a single stable MCP endpoint:
Copilot Studio
↓
https://app.simplicontract.com/mcp
↓
Tenant resolution / authentication
↓
Keycloak
↓
Tenant-specific backend
Then make the tenant a property of the authenticated identity/context rather than part of the MCP server URL.
This is particularly relevant because Copilot Studio's MCP authentication supports OAuth 2.0, including dynamic discovery and dynamic/manual configuration. The dynamic discovery option allows the MCP client to discover the required OAuth endpoints from the server's discovery mechanism.
For your Keycloak scenario
If each customer has a different Keycloak issuer, I'd investigate whether you can make the single MCP endpoint determine the tenant from the authenticated user/token and then select the appropriate issuer internally.
Conceptually:
User
↓
Copilot Studio
↓
https://app.simplicontract.com/mcp
↓
Authenticate
↓
Identify tenant = abc
↓
Keycloak issuer for abc
↓
Tenant-specific MCP operations
rather than:
Tenant ABC → /tenants/abc/mcp
Tenant XYZ → /tenants/xyz/mcp
The current Copilot Studio documentation explicitly supports OAuth 2.0 authentication for MCP servers, including dynamic discovery where the client discovers the necessary authorization endpoints.
One important distinction
If your reason for having a tenant-specific URL is only to allow the MCP server to discover which Keycloak issuer to use, I'd move that tenant-resolution logic behind the MCP endpoint if possible.
If the tenant-specific URL is an actual hard security boundary and the server cannot determine the tenant from the authenticated identity/token, then I don't see a documented Copilot Studio feature that would dynamically substitute {tenant} into the MCP Server URL at runtime.
In that case, your options would be closer to:
Option A — Preferred
One MCP endpoint
→ resolve tenant from identity/token
→ tenant-specific Keycloak/backend
or:
Option B
One stable MCP gateway
→ determine tenant
→ proxy to /tenants/{tenant}/mcp
or, if neither is possible:
Option C
One agent/MCP configuration per tenant
I would not recommend Option C for a SaaS product with potentially hundreds or thousands of tenants unless there is no way to centralize the MCP endpoint.
Also, because MCP support and authentication configuration are still evolving in Copilot Studio, I would avoid relying on undocumented URL templating or internal configuration values. Microsoft currently documents the Server URL as a configured endpoint, and the documented dynamic functionality is around OAuth discovery/authentication rather than runtime MCP URL substitution.
So the architectural question I'd take back to the Simplicontract team is:
Can the MCP gateway identify the tenant from the authenticated Keycloak identity/token instead of requiring the tenant in the MCP URL?
If yes, a single Copilot Studio agent/MCP tool configuration should be a much cleaner SaaS architecture.