-
Notifications
You must be signed in to change notification settings - Fork 38
Add Entra OAuth proxy (via FastMCP AzureAuthProvider) and automated Entra app registration #18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| @@ -0,0 +1,219 @@ | |||
| import asyncio | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These files were based off the same files in azure-search-openai-demo.
I was hoping that I could use Bicep instead, but I think that'd require a FastMCP change, as they accept a client secret, whereas Bicep can also set up MI-as-FIC.
There was a problem hiding this 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 pull request adds comprehensive support for Microsoft Entra ID (Azure AD) OAuth authentication to the MCP server via FastMCP's AzureAuthProvider, alongside automating Azure app registration through pre- and post-provision hooks. The implementation introduces a new authenticated server variant (auth_mcp.py), a custom Cosmos DB storage adapter for OAuth client persistence, and extensive infrastructure updates to support both Entra and existing Keycloak authentication options.
Key Changes:
- Automated Azure/Entra ID app registration with pre-provision hooks that create app registrations and post-provision hooks that update redirect URIs with deployed URLs
- New
auth_mcp.pyserver implementation supporting both Entra OAuth and Keycloak authentication with user-scoped data storage - CosmosDB-backed OAuth client storage via custom
CosmosDBStoreimplementing the py-key-value AsyncKeyValue protocol - Infrastructure updates enabling dynamic MCP entry point selection based on authentication configuration
Reviewed changes
Copilot reviewed 19 out of 21 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
| uv.lock | Updated dependencies for FastMCP 2.13.3, MCP 1.22.0, msgraph-sdk, dotenv-azd, and related OAuth packages |
| servers/deployed_mcp.py | Removed Keycloak authentication logic; simplified to basic MCP server without auth |
| servers/auth_mcp.py | New authenticated MCP server supporting both Entra OAuth and Keycloak with user-scoped expense tracking |
| servers/cosmosdb_store.py | New Cosmos DB implementation of AsyncKeyValue protocol for OAuth client storage |
| servers/Dockerfile | Updated CMD to use environment variable for dynamic entry point selection (deployed vs auth) |
| pyproject.toml | Added msgraph-sdk and dotenv-azd dependencies; bumped fastmcp version requirement |
| infra/main.bicep | Added useFastMcpAuth parameter, entraProxyClientId/Secret parameters, and new Cosmos containers |
| infra/server.bicep | Added Entra OAuth environment variables and secrets; dynamic entry point selection logic |
| infra/main.parameters.json | Added parameter mappings for USE_FASTMCP_AUTH and Entra client credentials |
| infra/fastmcp_auth_init.py | Pre-provision script to create/update Entra app registration with OAuth configuration |
| infra/fastmcp_auth_update.py | Post-provision script to update app registration with deployed server URL |
| infra/auth_init.sh/ps1 | Shell hooks to invoke fastmcp_auth_init.py during pre-provision |
| infra/auth_update.sh/ps1 | Shell hooks to invoke fastmcp_auth_update.py during post-provision |
| infra/write_env.sh/ps1 | Updated to write new Entra auth environment variables to .env file |
| azure.yaml | Wired up preprovision and postprovision hooks for both POSIX and Windows |
| README.md | Added comprehensive Entra OAuth deployment documentation and troubleshooting guidance |
| AGENTS.md | New developer instructions for adding azd environment variables |
| .vscode/mcp.json | Fixed JSON formatting (trailing comma) |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
README.md
Outdated
| |----------|-------------| | ||
| | `FASTMCP_AUTH_AZURE_CLIENT_ID` | The App Registration's client ID | | ||
| | `FASTMCP_AUTH_AZURE_CLIENT_SECRET` | The App Registration's client secret | | ||
| | `FASTMCP_AUTH_AZURE_TENANT_ID` | Your Azure tenant ID | |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The environment variable name is inconsistent. The table lists FASTMCP_AUTH_AZURE_TENANT_ID, but the actual code uses AZURE_TENANT_ID (without the FASTMCP_AUTH prefix).
Looking at the code in auth_mcp.py line 90 and server.bicep line 109-110, the variable is named AZURE_TENANT_ID.
Update the documentation to use AZURE_TENANT_ID instead of FASTMCP_AUTH_AZURE_TENANT_ID.
| | `FASTMCP_AUTH_AZURE_TENANT_ID` | Your Azure tenant ID | | |
| | `AZURE_TENANT_ID` | Your Azure tenant ID | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
infra/auth_init.sh
Outdated
| exit 0 | ||
| fi | ||
|
|
||
| echo "Setting up Azure/Entra ID app registration for FastMCP OAuth Proxy..." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hit a KeyError: 'AZURE_TENANT_ID' during azd up here. I think it is because the variable isn't exported to pre-provision hooks.
I manually added:
AZURE_TENANT_ID=$(azd env get-value AZURE_TENANT_ID 2>/dev/null)
if [ $? -ne 0 ]; then AZURE_TENANT_ID=""; fi
export AZURE_TENANT_ID
if [ -z "$AZURE_TENANT_ID" ]; then
# Fallback: Extract tenant ID from azd auth token
token_json=$(azd auth token --output json 2>/dev/null)
if [ -n "$token_json" ]; then
AZURE_TENANT_ID=$(python -c "import sys, json, base64; ... print(json.loads(base64.b64decode(payload).decode('utf-8'))['tid'])" <<< "$token_json")
export AZURE_TENANT_ID
fi
fi
and it worked.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I've added that as explicit step to the README, just to have them run "azd env set". That's how we do it in the other repo, as we allow them to set a different tenant ID than the main tenant. I could also do that here, distinguish it as AZURE_AUTH_TENANT_ID, if we want to enable cross-tenant setups. (But that wouldnt work if I manage to move this all to Bicep one day)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 22 out of 27 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 22 out of 27 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 21 out of 27 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This pull request introduces support for deploying the MCP server with Microsoft Entra ID (Azure AD) OAuth authentication, alongside infrastructure and documentation updates. The main changes add pre- and post-provision hooks to automate Azure app registration, update Bicep templates and environment handling for OAuth, and provide comprehensive documentation for using the new authentication option.
Entra OAuth Proxy Integration
infra/auth_init.sh,infra/auth_init.ps1) and post-provision (infra/auth_update.sh,infra/auth_update.ps1) hooks to automate creation and configuration of Azure/Entra ID app registrations for FastMCP OAuth Proxy. These scripts call new Python scripts to handle Azure resource setup. [1] [2] [3] [4]infra/fastmcp_auth_init.py(pre-provision): creates or updates the Entra ID app registration, sets up redirect URIs (including for VS Code), exposes an API scope, generates a client secret, and stores credentials in azd environment variables.infra/fastmcp_auth_update.py(post-provision): updates the app registration with the actual deployed server URL as an OAuth redirect URI after deployment..vscode/mcp.jsonto fix minor JSON formatting.Infrastructure and Bicep Updates
infra/main.bicepfor enabling Entra OAuth Proxy (useFastMcpAuth), and for passing the app registration client ID and secret. Also added new CosmosDB containers for OAuth client and user storage. [1] [2] [3]azure.yamlto wire up the new pre- and post-provision hooks for both POSIX and Windows environments.Documentation
README.mdwith detailed instructions for deploying with Entra OAuth Proxy, including deployment steps, environment variables, local testing, VS Code integration, and troubleshooting. [1] [2]AGENTS.mdinstructions for properly adding new azd environment variables, including Bicep and script updates.These changes collectively make it much easier to deploy the MCP server with secure Microsoft Entra ID authentication, automate the required Azure setup, and provide clear guidance for developers.