v1.6.0
BC Online (SaaS) support: the server now runs against
businesscentral.dynamics.com as well as on-prem, with a password-free
sign-in for the UI tools and device-code OAuth for bc_query. On-prem
NavUserPassword is unchanged.
Added
- SaaS
/cshweb-client session (ESTS cookie). A portal URL
https://businesscentral.dynamics.com/{aadTenant}/{environment}selects
authMode: SaasWeb. The first UI tool opens a local127.0.0.1sign-in
window (password and MFA stay there — never in env, never in chat); portal
cookies persist underSTATE_DIR/saas-web-cookies.json(mode 0600, per
repo) and are reused across process restarts. The/cshWebSocket is
discovered on the cluster host after sign-in — no cluster URL in config. - OAuth / Microsoft Entra ID authentication for
bc_query. A SaaS portal
URL (orBC_AUTH=OAuth) acquires a Standard API token via device-code and
uses it asAuthorization: Bearerforbc_query. Refresh tokens are cached
underSTATE_DIR(mode 0600).BC_USERNAME/BC_PASSWORDare not required
in this mode. bc_queryno longer opens a/cshsession. The OData tool is
independent of the web-client WebSocket, so SaaS OAuth works for bulk reads
even when the first-party web-client cookie session cannot be established.- Device-code sign-in surfaces in chat. When
bc_queryneeds a sign-in it
fails fast withDEVICE_LOGIN_REQUIREDwhose message carries the
https://microsoft.com/devicelogin URL and user code (instead of blocking the
tool call and printing the code on stderr, which MCP clients never show).
The pending sign-in is persisted inSTATE_DIR/oauth-pending.json; retrying
the tool polls once and resumes — same code, no re-prompt — then runs the
query once sign-in is complete.BC_CLIENT_IDis required: a
publisher-owned multi-tenant public app (see README "bc_query on SaaS") —
customer tenants never register anything. Borrowed Microsoft first-party
clients fail at sign-in withAADSTS65002on hardened tenants. - SaaS URL parsing. A portal URL such as
https://businesscentral.dynamics.com/7bcb54ae-…/DEVis split into Entra
tenant + environment. OData is derived as
https://api.businesscentral.dynamics.com/v2.0/{tenant}/{environment}.
A verified AAD domain (contoso.onmicrosoft.com) is accepted in the tenant
segment as well as a GUID. npx business-central-mcp loginprimes the SaaS cookie file ahead of
the first tool call.
Changed
- Config: new
BC_AUTH,BC_AAD_TENANT_ID,BC_ENVIRONMENT,BC_OAUTH_SCOPE,
BC_CLIENT_ID.BC_USERNAME/BC_PASSWORDare required only for
NavUserPassword; a SaaS password in env is ignored. - Session-lifecycle hardening. A dead or revoked SaaS session is detected
and reopens interactive sign-in via a windowed, episode-based escalation
(transient outages never destroy valid cookies; a brief portal interstitial
during backoff never escalates; a genuinely dead session does). A fresh
sign-in is verified behaviorally — signing in with the wrong Microsoft
account or tenant fails with a clear, non-retryable error and saves nothing,
instead of silently degrading into repeat prompts. A session revoked while
the cluster tab is bound now recovers instead of wedging. - HTTP route-gating. Unknown REST paths
404and non-POST/mcp405
before any BC session is created, so a stray request (a LAN scanner's
GET /favicon.ico) can no longer trigger session creation or pop the
interactive SaaS sign-in window. Sign-in-flow errors on the REST path now
carry their code and payload (verification URL, user code) instead of an
opaque500.
Fixed
bc_queryOData errors preserve their typed BC error (code + hint) instead
of collapsing aDEVICE_LOGIN_REQUIREDinto a generic network error.- Cookie handling:
Set-Cookiedeletions (Max-Age=0/ pastExpires) are
honored per RFC 6265; cookies scoped to a bare public suffix are rejected;
the portal auth cookie is matched by resolved-GUID suffix so domain-form
tenants work; the SaaS cluster host is allow-listed todynamics.com. - OAuth token refresh is single-flighted, so concurrent
bc_querycalls at
token expiry share one grant instead of racing and wiping the cache; a
captive-portal non-JSON200during device-code polling no longer churns
the pending code.
What's Changed
- docs: upgrade VSCode install badge to prompt for credentials via inputs by @SShadowS in #6
- docs: document BC_APPLICATION_ID=NAV for on-prem containers by @SShadowS in #11
- feat(saas): BC Online /csh web-client session (ESTS) by @FBakkensen in #12
- fix(saas): PR #12 review follow-ups (#11-16 hardening/cleanup) by @SShadowS in #13
- feat(saas): session-lifecycle hardening — escalation, sign-in verification, warm-path recovery by @FBakkensen in #15
- docs: correct the bc_query SaaS error-path description by @SShadowS in #16
New Contributors
- @SShadowS made their first contribution in #6
- @FBakkensen made their first contribution in #12
Full Changelog: v1.5.0...v1.6.0