Skip to main content

Setup and Configuration

Prerequisites

Before running Flowon Logic Assist, ensure the following are in place:

RequirementDetails
.NET Runtime.NET 10 or later (the server targets net10.0)
Logic ComposerInstalled and licensed in the target Dataverse environment (the baseline for most tool groups)
Process OrchestratorOptional - required only for the Business Process tools
Dataverse ConnectionA Dataverse connection string or service-principal credentials for the target environment
AI ClientAn MCP-compatible AI assistant (Claude, GitHub Copilot, etc.)
Microsoft Entra appRequired only for Secure HTTP mode (JWT Bearer / On-Behalf-Of auth)

Tool groups register conditionally based on the Flowon solutions installed in the connected environment. Logic Composer alone is enough to run Flowon Logic Assist; Process Orchestrator only adds the Business Process tools. Metadata, Data, and Solution tools are always available. See Product Scope.


Host Modes

Flowon Logic Assist runs in one of three host modes, selected by the --transport argument and the incoming-auth flag. The mode determines the transport and how incoming requests are authenticated.

ModeWhen to useTransportIncoming auth
Stdio (default)Local desktop MCP clientsStandard I/O streamsNone (local process)
HTTPDev / testing onlyPOST /mcpDisabled (--disable-http-incoming-auth); CORS restricted to localhost
Secure HTTPProduction / team-sharedPOST /mcpJWT Bearer (Microsoft Entra ID), with On-Behalf-Of user impersonation

The HostBuilderFactory selects the mode automatically: --transport Http + --disable-http-incoming-authHTTP; --transport Http (without that flag) → Secure HTTP; otherwise → Stdio.


Running the Server

Configuration has two independent axes:

  1. Transport + incoming auth — the host mode above (--transport, --disable-http-incoming-auth).
  2. Dataverse (outgoing) auth — how the server authenticates to Dataverse, set with --dataverse-auth-strategy. Connection details are supplied through environment variables, chosen by the strategy. There is no connection-string argument.

CLI Arguments

ArgumentValuesDefault
--transportStdio, HttpStdio
--dataverse-auth-strategyUseHostingEnvironmentIdentity, UseOnBehalfOf, UseClientCredentials, UseUserCredentialsauto
--disable-http-incoming-authflagfalse

Log level is set with the LOG_LEVEL environment variable (TraceError, default Information).

Dataverse Authentication Strategies

StrategyHow the server authenticates to DataverseRequired environment variables
UseHostingEnvironmentIdentityThe host's managed/ambient identity (like DefaultAzureCredential). All calls use the same identity — ideal for cloud/managed-identity hosting.DATAVERSE_URL
UseOnBehalfOfExchanges the incoming user's token for a Dataverse token — the server acts as the calling user. HTTP modes only.DATAVERSE_URL + AzureAd__*
UseClientCredentialsApp-only, using a client id + secret (service principal).DATAVERSE_URL, DATAVERSE_CLIENT_ID, DATAVERSE_CLIENT_SECRET
UseUserCredentialsUsername + password (on-prem Dynamics).DYNAMICS_URL, DYNAMICS_APP_ID, DYNAMICS_USER_NAME, DYNAMICS_PASSWORD

Environment Variables

VariablePurpose
DATAVERSE_URLDataverse environment URL (client-credentials, OBO, and hosting-identity strategies)
DATAVERSE_CLIENT_ID / DATAVERSE_CLIENT_SECRETService-principal credentials (UseClientCredentials)
DYNAMICS_URL / DYNAMICS_APP_ID / DYNAMICS_USER_NAME / DYNAMICS_PASSWORDOn-prem Dynamics credentials (UseUserCredentials)
AzureAd__ClientId, AzureAd__TenantId, AzureAd__Instance, AzureAd__ClientCredentials__0__SourceType, AzureAd__ClientCredentials__0__ClientSecretMicrosoft Entra app registration — required for incoming JWT auth (Secure HTTP) and the OBO token exchange
AZURE_CLOUDAzure sovereign-cloud override
LOG_LEVELTrace, Debug, Information, Warning, Error (default Information)
ASPNETCORE_URLSBind address/port, e.g. http://localhost:1033
FLOWON_MCP_COLLECT_TELEMETRYSet true to emit OpenTelemetry traces/metrics
FLOWON_MCP_DANGEROUSLY_DISABLE_HTTPS_REDIRECTIONSet true to skip HTTPS redirection (useful behind a reverse proxy)
ALLOW_INSECURE_EXTERNAL_BINDINGSet true to allow wildcard/external binding in dev HTTP mode

On-Behalf-Of needs its own app registration. For UseOnBehalfOf, the AzureAd app must expose the MCP API scope and be consented for the on-behalf-of exchange — typically a different registration than the one used for plain client-credentials runs.

⚠️ Never commit real secrets. The values below are placeholders — supply them through your environment, a secret store, or container secrets.

Examples

# HTTP, unauthenticated incoming, app-only Dataverse auth (local dev)
DATAVERSE_URL="https://yourorg.crm.dynamics.com/" \
DATAVERSE_CLIENT_ID="<app-id>" \
DATAVERSE_CLIENT_SECRET="<secret>" \
ASPNETCORE_URLS="http://localhost:1033" \
dotnet run -- --transport http --disable-http-incoming-auth --dataverse-auth-strategy UseClientCredentials
# Secure HTTP with On-Behalf-Of (acts as the calling user)
DATAVERSE_URL="https://yourorg.crm.dynamics.com/" \
AzureAd__Instance="https://login.microsoftonline.com/" \
AzureAd__TenantId="<tenant-id>" \
AzureAd__ClientId="<obo-app-id>" \
AzureAd__ClientCredentials__0__SourceType="ClientSecret" \
AzureAd__ClientCredentials__0__ClientSecret="<secret>" \
dotnet run -- --transport http --dataverse-auth-strategy UseOnBehalfOf
# On-prem Dynamics with user credentials
DYNAMICS_URL="https://dynamics.contoso.com/" \
DYNAMICS_APP_ID="<app-id>" \
DYNAMICS_USER_NAME="DOMAIN\\user" \
DYNAMICS_PASSWORD="<password>" \
dotnet run -- --transport http --disable-http-incoming-auth --dataverse-auth-strategy UseUserCredentials

Endpoints (HTTP modes)

EndpointDescription
POST /mcpThe MCP endpoint. In Secure HTTP mode it requires the McpAccess authorization policy.
GET /healthAnonymous health check (Secure HTTP mode only).
GET /.well-known/oauth-protected-resourceOAuth Protected Resource metadata (RFC 9728) describing the resource, its authorization servers, and supported scopes ({clientId}/Mcp.Tools.ReadWrite). MCP clients use this for discovery.

In Secure HTTP mode, every tool call executes under the calling user's Dynamics identity, resolved from the incoming JWT via the Microsoft Entra On-Behalf-Of (OBO) flow. Dataverse row-level security, business-unit scoping, and team membership apply to every query and action.


On-Behalf-Of (OBO)

UseOnBehalfOf is the recommended mode for shared, production deployments. Instead of a single service account, the server acts as the calling user for every Dataverse operation:

  1. The MCP client calls with the user's access token (Authorization: Bearer …).
  2. The server validates the Entra JWT and enforces the McpAccess policy — the token must carry the delegated scope Mcp.Tools.ReadWrite (or, for app-only callers, the app permission Mcp.Tools.ReadWrite.All).
  3. The server performs the On-Behalf-Of exchange to obtain a downstream Dataverse token for that same user (the token's tenant must match the user's tid claim).
  4. Every Dataverse read/write then runs with the user's own identity — so row-level security, business-unit scoping, and team membership apply exactly as they would in the Dynamics UI.

App registration requirements

The AzureAd app used for OBO must be:

  • A confidential client (has a client secret — supplied via AzureAd__ClientCredentials__0__*).
  • Configured to expose an API scope Mcp.Tools.ReadWrite (delegated) and/or an app role Mcp.Tools.ReadWrite.All (app-only).
  • Granted delegated permission to Dataverse (user_impersonation) and admin-consented, so the OBO exchange can succeed.

Wire it up with AzureAd__ClientId, AzureAd__TenantId, AzureAd__Instance, and AzureAd__ClientCredentials__0__SourceType / AzureAd__ClientCredentials__0__ClientSecret. This is typically a different registration than one used for a plain client-credentials run.

Client discovery

MCP clients can discover the authorization server and scope from GET /.well-known/oauth-protected-resource, which advertises the authorization server ({instance}/{tenantId}/v2.0) and the supported scope ({clientId}/Mcp.Tools.ReadWrite). The WWW-Authenticate challenge on an unauthenticated request points clients here.


Running with Docker

Flowon Logic Assist ships with a Dockerfile (Alpine-based, linux-x64/linux-arm64) for containerised deployments:

# Build a publish image
dotnet publish -c Release

# Or build the Docker image directly, then run it
docker build -t flowon-logic-assist .
docker run \
-e DATAVERSE_URL="https://yourorg.crm.dynamics.com/" \
-e DATAVERSE_CLIENT_ID="<app-id>" \
-e DATAVERSE_CLIENT_SECRET="<secret>" \
-p 5260:5260 flowon-logic-assist \
--transport http --disable-http-incoming-auth --dataverse-auth-strategy UseClientCredentials

The container listens on port 5260 by default (override with ASPNETCORE_URLS). Pass whichever environment variables match your chosen strategy — e.g. the AzureAd__* set for UseOnBehalfOf.


Connecting to Your AI Client

Once the server is running, point your AI client's MCP configuration at it. The exact file location and format depend on your client — refer to its documentation.

Stdio Mode

Suitable for local development and desktop AI clients. The client launches the server process:

{
"mcpServers": {
"flowon-logic-assist": {
"command": "dotnet",
"args": [
"run",
"--project", "FlowOn.Xrm.Assist.Mcp.Server.csproj",
"--",
"--dataverse-auth-strategy", "UseClientCredentials"
],
"env": {
"DATAVERSE_URL": "https://yourorg.crm.dynamics.com/",
"DATAVERSE_CLIENT_ID": "<app-id>",
"DATAVERSE_CLIENT_SECRET": "<secret>"
}
}
}
}

HTTP Mode

Suitable for server-hosted deployments and team-shared MCP configurations. Point the client at the /mcp endpoint:

{
"mcpServers": {
"flowon-logic-assist": {
"url": "https://your-mcp-server-host:port/mcp"
}
}
}

Product Scope

Flowon Logic Assist registers tools conditionally, based on which Flowon solutions are installed in the connected Dataverse environment. At startup it always registers the Metadata, Data, Project, and Solution tools, then queries Dataverse for the installed Flowon solutions and enables the matching tool groups:

Installed solutionEnables
FlowOnLogicLogic Block, Logic Flow, Logic Recipe, Configuration, Localized Resource, Service Connection, Schedule, and Event tools
FlowOnBpmBusiness Process tools
FlowOnApiAPI Builder–related tools

Calling a tool whose product is not installed returns an error. No configuration list is required — availability is derived from the environment itself.


One Instance Per Environment

┌─────────────────────────────────────────────────────────────────────┐
│ ENVIRONMENT ISOLATION PATTERN │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Logic Assist │ │ Logic Assist │ │ Logic Assist │ │
│ │ (Dev) │ │ (UAT) │ │ (Prod) │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Dataverse │ │ Dataverse │ │ Dataverse │ │
│ │ Dev Env │ │ UAT Env │ │ Prod Env │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ AI agents connect to the environment-specific instance. │
│ Managed solution protection prevents accidental production edits. │
│ │
└─────────────────────────────────────────────────────────────────────┘

Configure a separate Flowon Logic Assist instance for each Dataverse environment. This ensures AI agents operate only in the intended environment and that Managed Solution Protection guards production correctly.