Skip to content

Fix BC MCP proxy to target current MCP server endpoint#354

Open
DmitryKatson wants to merge 1 commit into
microsoft:masterfrom
DmitryKatson:fix/bc-mcp-proxy-endpoint
Open

Fix BC MCP proxy to target current MCP server endpoint#354
DmitryKatson wants to merge 1 commit into
microsoft:masterfrom
DmitryKatson:fix/bc-mcp-proxy-endpoint

Conversation

@DmitryKatson
Copy link
Copy Markdown
Contributor

Summary

The Business Central MCP proxy samples (Python bc-mcp-proxy and .NET BcMCPProxy) currently fail with HTTP 400 Bad Request as soon as they try to talk to Business Central, even when device-code sign-in succeeds and the Azure app registration is configured exactly as documented.

Root cause: Microsoft moved the BC MCP server. The proxies still call the old preview URL pattern, which BC no longer accepts.

Old (broken) Current (fixed)
URL https://api.businesscentral.dynamics.com/v2.0/<env>/mcp https://mcp.businesscentral.dynamics.com
Routing environment in path, Company header only TenantId, EnvironmentName, Company HTTP headers
OAuth scope https://api.businesscentral.dynamics.com/.default https://mcp.businesscentral.dynamics.com/.default

This matches the official guidance in Connect to Business Central MCP server with non-Microsoft clients and the connection string emitted by the Model Context Protocol (MCP) Server Configurations page in BC.

Changes

  • samples/BcMCPProxyPython/bc_mcp_proxy/config.py — update base_url and token_scope defaults
  • samples/BcMCPProxyPython/bc_mcp_proxy/proxy.py — drop /v2.0/<env>/mcp path suffix, add TenantId / EnvironmentName headers
  • samples/BcMCPProxyPython/README.md — update parameter table defaults to match
  • samples/BcMCPProxy/Models/ConfigOptions.cs — update Url and TokenScope defaults
  • samples/BcMCPProxy/Runtime/MCPServerProxy.cs — same URL/header changes for the .NET proxy

Test plan

Verified end-to-end against a sandbox BC environment:

  • Device-code sign-in succeeds and acquires a token for the mcp.businesscentral.dynamics.com resource
  • MCP initialize handshake completes against mcp.businesscentral.dynamics.com (HTTP 200, server identifies itself as Microsoft Dynamics 365 Business Central v28.0)
  • tools/list returns the BC dynamic tools (bc_actions_search, bc_actions_describe, bc_actions_invoke)
  • bc_actions_search returns matching action names
  • bc_actions_describe returns the action schema
  • bc_actions_invoke on List_Customers_PAG30009 returns real CRONUS customer data (3 of 5 records)
  • bc_actions_invoke on List_Items_PAG30008 returns real CRONUS item data (3 of 80 records)

Existing app registrations that already have Dynamics 365 Business Centraluser_impersonation (delegated) continue to work — no Azure changes are required for end users.

Reproduction

Before this PR (with valid app registration and successful device-code sign-in):

INFO:bc_mcp_proxy:Connecting to Business Central MCP endpoint at https://api.businesscentral.dynamics.com/v2.0/Production/mcp
INFO:httpx:HTTP Request: POST https://api.businesscentral.dynamics.com/v2.0/Production/mcp "HTTP/1.1 400 Bad Request"

After this PR:

INFO:bc_mcp_proxy:Connecting to Business Central MCP endpoint at https://mcp.businesscentral.dynamics.com
INFO:httpx:HTTP Request: POST https://mcp.businesscentral.dynamics.com "HTTP/1.1 200 OK"
DEBUG:bc_mcp_proxy:Connected to remote MCP server (protocol 2025-11-25)

Notes for maintainers

  • The Python sample's pyproject.toml version is unchanged (0.1.2). Once this PR is merged, the package will need a version bump and a PyPI release so end users get the fix without rebuilding from source.
  • The BcMCPProxy.exe published artifact will likewise need a rebuild.

Microsoft moved the Business Central MCP server from
api.businesscentral.dynamics.com/v2.0/<env>/mcp to a dedicated host at
mcp.businesscentral.dynamics.com, with environment routing via HTTP
headers (TenantId, EnvironmentName, Company). The previous proxy URL
returns 400 Bad Request after a successful sign-in, even when the Azure
app registration is correctly configured.

Update both the Python (bc-mcp-proxy) and .NET (BcMCPProxy) samples:
- Default Url/BaseUrl -> https://mcp.businesscentral.dynamics.com
- Default scope -> https://mcp.businesscentral.dynamics.com/.default
- Drop the /v2.0/<env>/mcp path suffix from the request URL
- Send TenantId and EnvironmentName headers in addition to Company

Verified end-to-end against a sandbox environment: the proxy completes
the MCP initialize handshake, lists tools, and successfully invokes
List_Customers / List_Items via bc_actions_invoke.
@DmitryKatson DmitryKatson force-pushed the fix/bc-mcp-proxy-endpoint branch from 4a3a6e4 to 652727b Compare May 19, 2026 03:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant