Skip to content

Add initial, rough support for Streamable HTTP for remote hosted MCP servers#1020

Merged
vukelich merged 7 commits intomainfrom
feature/2.0beta-remote
Nov 3, 2025
Merged

Add initial, rough support for Streamable HTTP for remote hosted MCP servers#1020
vukelich merged 7 commits intomainfrom
feature/2.0beta-remote

Conversation

@vukelich
Copy link
Copy Markdown
Member

@vukelich vukelich commented Oct 30, 2025

What does this PR do?

This work is a collaboration with @anuchandy and @srnagar.

Remote MCP server

  • server start --run-as-remote-http-service to start the server as a remote HTTP service expecting incoming Entra authenticated calls. Incoming Authorization headers are expected to have the correctly configured audience as determined by owner of the remote MCP server's deployment infrastructure, however, Bearer tokens are required to have the Mcp.Tools.ReadWrite scp claim for user principals or Mcp.Tools.ReadWrite.All roles claim for service principals. These claim values are hardcoded and will be configurable if additional scopes or app roles are needed in the future.
    • NOTE: an upcoming commit on 2025-11-03 or 2025-11-04 will replace server start --run-as-remote-http-service with server start --transport http.
  • Remote MCP server requires some use of .NET configuration sources to set up required Microsoft.Identity.Web libraries. See /servers/Azure.Mcp.Server/src/TROUBLESHOOTING.md for details.
  • Remote MCP server supports
  • The ENABLE_REMOTE MSBuild constant is used to #if sections of code dependent on the non-trimmable Microsoft.Identity.Web library. Work is planned for how to build a CLI vs a remote server with build pipelines. This constant is enabled within /Directory.Build.props when PublishTrimmed is not true.
  • No CORS restrictions are in place to support any browser-based HTTP agentic experiences. This may be changed in the future.
  • Remote MCP server supports OAuth Protected Resource Metadata to allow discovery of OAuth 2.0 auth requirements for clients. VS Code supports this feature when connecting to remote MCP servers. Dynamic client registration is NOT supported. Clients must have a client app registration in Entra ID.

Outgoing authentication
IAzureTokenCredentialProvider abstracts how to get outgoing Entra OAuth access tokens, and a singleton implementation is injected into dependency injection containers. Two strategies exist as represented by OutgoingAuthStrategy:

  • UseHostingEnvironmentIdentity - Wraps the preexisting CustomChainedCredential that uses the identity of the signed in user or a managed identity. The SingleIdentityTokenCredentialProvider implements IAzureTokenCredentialProvider using this strategy.
    • Non-remote MCP server: Default and only allowed strategy.
    • Remote MCP server: Allowed when using explicit server start option --outgoing-auth-strategy UseHostingEnvironmentIdentity.
  • UseOnBehalfOf - Uses Entra OAuth 2.0 On-Behalf-Of flow to exchange the incoming access token for a new access token to call downstream services. The HttpOnBehalfOfTokenCredentialProvider implements IAzureTokenCredentialProvider using this strategy.
    • Non-remote MCP server: Not allowed.
    • Remote MCP server: Default strategy. Can also be explicitly selected using server start option --outgoing-auth-strategy UseOnBehalfOf.

Refactoring

  • BaseAzureService:
    • Requires non-null ITenantService in its constructor. This type is used as a step to get to IAzureTokenCredentialProvider.
      • This results in a circular dependency when TenantService (which implements ITenantService) inherits from BaseAzureService. An ugly internal mitigation is in place for TenantService to set its own ITenantService dependency after construction.
    • Constructor no longer takes in ILoggerFactory. This was not needed since BaseAzureService is not creating instances of CustomChainedCredential directly anymore.
  • Some general cleanliness along the way. Namespaces and fields without any use have been removed when happened upon. Removal was not exhaustive and was mostly random and coincidental.

Testing

  • All refactoring passes existing unit and live tests.
  • Light manual testing has been done on the Azure.Mcp.Server.
  • Tests for new code, as often happens, will come soon... hopefully.

Documentation

  • Basic documentation added to describe how to debug the remote MCP server scenario.

GitHub issue number?

[Link to the GitHub issue this PR addresses]

Pre-merge Checklist

  • Required for All PRs
    • Read contribution guidelines
    • PR title clearly describes the change
    • Commit history is clean with descriptive messages (cleanup guide)
    • Added comprehensive tests for new/modified functionality
    • Updated servers/Azure.Mcp.Server/CHANGELOG.md and/or servers/Fabric.Mcp.Server/CHANGELOG.md for product changes (features, bug fixes, UI/UX, updated dependencies)
  • For MCP tool changes:
    • One tool per PR: This PR adds or modifies only one MCP tool for faster review cycles
    • Updated servers/Azure.Mcp.Server/README.md and/or servers/Fabric.Mcp.Server/README.md documentation
    • Validate README.md changes using script at eng/scripts/Process-PackageReadMe.ps1. See Package README
    • Updated command list in /servers/Azure.Mcp.Server/docs/azmcp-commands.md and/or /docs/fabric-commands.md
    • Run .\eng\scripts\Update-AzCommandsMetadata.ps1 to update tool metadata in azmcp-commands.md (required for CI)
    • For new or modified tool descriptions, ran ToolDescriptionEvaluator and obtained a score of 0.4 or more and a top 3 ranking for all related test prompts
    • For new tools associated with Azure services or publicly available tools/APIs/products, add URL to documentation in the PR description
  • Extra steps for Azure MCP Server tool changes:
    • Updated test prompts in /servers/Azure.Mcp.Server/docs/e2eTestPrompts.md
    • 👉 For Community (non-Microsoft team member) PRs:
      • Security review: Reviewed code for security vulnerabilities, malicious code, or suspicious activities before running tests (crypto mining, spam, data exfiltration, etc.)
      • Manual tests run: added comment /azp run mcp - pullrequest - live to run Live Test Pipeline

vukelich and others added 5 commits October 24, 2025 12:54
…token acquisition. (#910)

Add remote HTTP server mode with OAuth authentication and downstream token acquisition

- Add RunAsRemoteHttpService and OutgoingAuthStrategy options to enable MCP server to run as a remote HTTP service
- Introduce ITokenProvider abstraction for dependency injection of downstream authentication tokens and credentials
- Add support for On-Behalf-Of (OBO) token flow and hosting environment identity modes for outgoing authentication
- Implement OAuth Protected Resource Metadata endpoint at /.well-known/oauth-protected-resource with WWW-Authenticate challenge
- Add Visual Studio and dotnet run launch profile for debugging remote MCP server with Microsoft.Identity.Web configuration
- Modernize HTTP host creation using WebApplicationBuilder with authentication and authorization middleware
…functionality only in non-trimmed builds (#1008)

* Exclude Obo roots when building in trim mode given the AOT violations in Obo apis

* Use aot safe apis for incoming auth

* unblock template cli, fix CreateArmClientAsync_CreatesAndUsesCachedClient

* dotnet format

* Define ENABLE_REMOTE build property for untrimmed build
Copilot AI review requested due to automatic review settings October 30, 2025 22:58
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces authentication abstraction and remote HTTP MCP server support with on-behalf-of (OBO) authentication flow. The changes refactor credential management to use a provider pattern and add support for running the MCP server as an authenticated HTTP service.

  • Introduces IAzureTokenCredentialProvider interface with two implementations: SingleIdentityTokenCredentialProvider (for single-identity scenarios) and HttpOnBehalfOfTokenCredentialProvider (for OBO flow in multi-user scenarios)
  • Adds remote HTTP service support with Azure AD authentication, including OAuth metadata endpoints and authorization policies
  • Refactors TenantService to use the new credential provider pattern and adds extension methods for DI registration

Reviewed Changes

Copilot reviewed 35 out of 35 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
IAzureTokenCredentialProvider.cs New interface defining token credential provider contract
SingleIdentityTokenCredentialProvider.cs Implementation for single-identity credential scenarios
HttpOnBehalfOfTokenCredentialProvider.cs Implementation for OBO authentication in HTTP contexts
AuthenticationServiceCollectionExtensions.cs DI registration extensions for authentication providers
TenantService.cs Refactored to use credential provider and support new authentication pattern
TenantServiceCollectionExtensions.cs New DI registration extension for tenant service
ITenantService.cs Updated with new method signatures and comprehensive documentation
BaseAzureService.cs Refactored credential management to use TenantService
ServiceStartCommand.cs Added remote HTTP server hosting with authentication/authorization
OAuthProtectedResourceMetadata.cs New model for OAuth 2.0 protected resource metadata endpoint
OutgoingAuthStrategy.cs New enum defining outgoing authentication strategies
ServiceStartOptions.cs Added options for remote HTTP service configuration
ServiceOptionDefinitions.cs Added CLI option definitions for remote HTTP mode
Directory.Build.props Added ENABLE_REMOTE conditional compilation symbol
Directory.Packages.props Added Microsoft.Identity.* package references
Multiple test files Updated to use new authentication provider pattern
launchSettings.json Added debug profile for remote HTTP development
CONTRIBUTING.md / TROUBLESHOOTING.md Added documentation for HTTP mode

Comment thread core/Azure.Mcp.Core/src/Services/Azure/Tenant/ITenantService.cs
Comment thread core/Azure.Mcp.Core/src/Services/Azure/Tenant/ITenantService.cs
Comment thread core/Azure.Mcp.Core/src/Services/Azure/Tenant/ITenantService.cs
Comment thread core/Azure.Mcp.Core/src/Services/Azure/Tenant/ITenantService.cs
Comment thread core/Azure.Mcp.Core/src/Services/Azure/Tenant/ITenantService.cs
Comment thread core/Azure.Mcp.Core/src/Services/Azure/Tenant/TenantService.cs
@joshfree joshfree added this to the 2025-11 milestone Oct 31, 2025
@joshfree joshfree moved this from Untriaged to In Progress in Azure MCP Server Oct 31, 2025
…ure all derived types can make authenticated Azure calls always. Fixes product, live tests, and unit tests. (#1029)

Require non-null ITenantService parameter to BaseAzureService to ensure all derived types can make authenticated Azure calls always. Fixes product, live tests, and unit tests.
@anuchandy
Copy link
Copy Markdown
Member

/azp run mcp - pullrequest - live

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

…ments (#1005)

* Update contributing guide and troubleshooting guide to address PR comments

* move launchSettings instructions to wiki

* minor update

* update doc

* address pr comments

* change endpoint placeholder
@vukelich vukelich merged commit 5665c76 into main Nov 3, 2025
44 checks passed
@github-project-automation github-project-automation Bot moved this from In Progress to Done in Azure MCP Server Nov 3, 2025
@vukelich vukelich deleted the feature/2.0beta-remote branch November 3, 2025 01:51
@haolingdong-msft
Copy link
Copy Markdown
Member

haolingdong-msft commented Nov 3, 2025

Hi @vukelich @srnagar @anuchandy, thanks for the PR. I'm sooo interested to learn about remote MCP. May I ask two quick questions to confirm my understanding? I'm sorry I may be lack of context. Thank you in advance for your patience!

  1. Is this PR just about adding support on StreamableHTTP, not including deployment part (e.g. deploy the remote server to Azuer FuncApp)?
  2. server start --run-as-remote-http-service Seems this command is able to run locally? https://github.com/microsoft/mcp/pull/1020/files#diff-eca12c0a30e25b4b46522ebf89465a03ba72a03f540796c979137931d8f92055R230
    This looks interesting. I thought we can only run in stdio mode from local previously. Curious do I need any particular environment set up to be able to run locally using StreamableHTTP mode?

colbytimm pushed a commit to colbytimm/microsoft-mcp that referenced this pull request Dec 8, 2025
…servers (microsoft#1020)

* Add remote HTTP server mode with OAuth authentication and downstream token acquisition. (microsoft#910)

Add remote HTTP server mode with OAuth authentication and downstream token acquisition

- Add RunAsRemoteHttpService and OutgoingAuthStrategy options to enable MCP server to run as a remote HTTP service
- Introduce ITokenProvider abstraction for dependency injection of downstream authentication tokens and credentials
- Add support for On-Behalf-Of (OBO) token flow and hosting environment identity modes for outgoing authentication
- Implement OAuth Protected Resource Metadata endpoint at /.well-known/oauth-protected-resource with WWW-Authenticate challenge
- Add Visual Studio and dotnet run launch profile for debugging remote MCP server with Microsoft.Identity.Web configuration
- Modernize HTTP host creation using WebApplicationBuilder with authentication and authorization middleware

* Update contributing guide for HTTP mode (microsoft#962)

* Add support for ENABLE_REMOTE compilation constant to include remote functionality only in non-trimmed builds (microsoft#1008)

* Exclude Obo roots when building in trim mode given the AOT violations in Obo apis

* Use aot safe apis for incoming auth

* unblock template cli, fix CreateArmClientAsync_CreatesAndUsesCachedClient

* dotnet format

* Define ENABLE_REMOTE build property for untrimmed build

* Require non-null ITenantService parameter to BaseAzureService to ensure all derived types can make authenticated Azure calls always. Fixes product, live tests, and unit tests. (microsoft#1029)

Require non-null ITenantService parameter to BaseAzureService to ensure all derived types can make authenticated Azure calls always. Fixes product, live tests, and unit tests.

* Update contributing guide and troubleshooting guide to address PR comments (microsoft#1005)

* Update contributing guide and troubleshooting guide to address PR comments

* move launchSettings instructions to wiki

* minor update

* update doc

* address pr comments

* change endpoint placeholder

---------

Co-authored-by: Srikanta <51379715+srnagar@users.noreply.github.com>
Co-authored-by: Anu Thomas <anuamd@hotmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

6 participants