bc-dev-mcp
v0.1.1
Published
MCP server for Business Central AL development — run tests with coverage and debug interactively against the BC dev endpoint
Maintainers
Readme
bc-dev-mcp
MCP server for Business Central AL development: run tests (with code coverage) and debug interactively against a BC server's dev endpoint — the same SignalR hubs the AL VS Code extension uses.
Overview
| Metric | Value |
|--------|-------|
| Runtime | Bun (dev/build) · Node 18+ (dist) |
| Runtime dependencies | 3 (@microsoft/signalr, @modelcontextprotocol/sdk, zod) |
| Transport | MCP over stdio |
| Server requirement | BC dev API WebApiVersion >= 7.0 (AL 18 platform, e.g. BC28) |
| Auth | UserPassword (on-prem / docker) |
| Validation | Live E2E against BC28 (scripts/e2e-results-2026-07-03.md) |
Features
| Feature | Description |
|---------|-------------|
| Structured test runs | Per-method pass/fail/skip with duration and failure output — every tool returns structuredContent validated by a published outputSchema |
| Code coverage | procedure mode, mapped back to local source files (line mode exists but is unproven against real BC) |
| Multi-codeunit plans | Sequential codeunit groups over one hub connection |
| Interactive debugging | Attach, file/line breakpoints, break-on-error, stack + variables + watch, stepping |
| Debug-a-test | Test run bound to the debug session — breakpoints fire during test execution |
| Config auto-discovery | Server/instance/tenant read from the AL project's .vscode/launch.json |
| Preflight diagnostics | bcdev_status distinguishes unreachable / bad credentials / unsupported dev API |
Prerequisites
- A reachable BC server with dev API
WebApiVersion >= 7.0(check withbcdev_status) - UserPassword credentials for the dev endpoint
- Bun (to run from source) or Node 18+ (to run the built
dist/index.js)
Installation
Claude Code — one command:
claude mcp add bc-dev --env BC_DEV_USER=admin --env BC_DEV_PASSWORD=... -- npx -y bc-dev-mcpAny other MCP client — .mcp.json (or your client's equivalent):
{
"mcpServers": {
"bc-dev": {
"command": "npx",
"args": ["-y", "bc-dev-mcp"],
"env": { "BC_DEV_USER": "admin", "BC_DEV_PASSWORD": "..." }
}
}
}(bunx bc-dev-mcp works too.) That's all the config there is: credentials via env, everything else (server, instance, tenant) is read from your AL project's .vscode/launch.json — and every connection-opening tool accepts overrides as parameters.
Running from source instead: git clone → bun install && bun run build → point command at node dist/index.js, or bun run compile for a standalone bc-dev-mcp.exe.
Quick Start
bcdev_status— verify reachability, auth, and that test running is supported.bcdev_test_discover— list test codeunits and[Test]methods from local.alfiles.bcdev_test_run { codeunits: [{ id: 50100 }], coverage: "procedure" }— structured results.bcdev_debug_attach { breakOnError: true }→bcdev_debug_run_tests { codeunits: [{ id: 50100 }] }→bcdev_debug_wait→ inspect withbcdev_debug_variables/bcdev_debug_eval→bcdev_debug_continue→bcdev_debug_detach.
Configuration
| Setting | Source | Default | Description |
|---------|--------|---------|-------------|
| BC_DEV_USER | env var | — | Dev endpoint username (required) |
| BC_DEV_PASSWORD | env var | — | Dev endpoint password (required) |
| server | launch.json / tool param | — | BC server URL, e.g. http://bcserver |
| serverInstance | launch.json / tool param | — | Server instance, e.g. BC |
| port | launch.json / tool param | 7049 | Developer service port |
| tenant | launch.json / tool param | default | Tenant (hub negotiate requires one) |
| project | tool param | server cwd | AL project dir for launch.json and .al scanning |
Connection-opening tools (bcdev_status, bcdev_test_run, bcdev_debug_attach, bcdev_debug_run_tests) accept server/serverInstance/port/tenant as parameters; session-scoped debug tools reuse the attached session.
Architecture
MCP client (agent)
|
v (stdio)
src/mcp/server.ts ── tools/ (11 bcdev_* tools) ── state.ts (session, event queue)
|
v
src/core/ (pure library — typed returns, injected deps)
|-- launch-config.ts launch.json + env credentials
|-- server-info.ts GET dev/metadata, feature gates
|-- al-objects.ts file <-> (objectType, objectId) index, test discovery
|-- hubs/test-runner-hub.ts ──> <server>/BC/dev/TestRunnerHub (SignalR)
|-- hubs/debugger-hub.ts ──> <server>/BC/dev/DebuggerHub (SignalR)Tools
| Tool | Purpose |
|------|---------|
| bcdev_status | Preflight: reachability, auth, dev API version, feature gates |
| bcdev_test_discover | List test codeunits and [Test] methods from local .al files |
| bcdev_test_run | Run tests, structured results, optional coverage |
| bcdev_debug_attach | Attach debugger, set file/line breakpoints |
| bcdev_debug_run_tests | Run tests with breakpoints live |
| bcdev_debug_wait | Long-poll for break / run-finished events |
| bcdev_debug_continue | continue / stepOver / stepInto / stepOut |
| bcdev_debug_variables | Inspect locals, globals, expand records |
| bcdev_debug_eval | Evaluate watch expression |
| bcdev_debug_breakpoints | Add/remove breakpoints mid-session |
| bcdev_debug_detach | End the debug session |
Skills
The server ships its own operational manual as Agent Skills over MCP
resources (draft SEP-2640):
skill://bc-al-testing/SKILL.md, skill://bc-al-debugging/SKILL.md, discovery index at
skill://index.json. Clients that understand the io.modelcontextprotocol/skills extension pick
these up automatically; everything else sees them as plain readable resources.
Sources live in skills/; bun run embed-skills regenerates src/mcp/skills.generated.ts.
Key Files
| File | Purpose |
|------|---------|
| src/mcp/index.ts | stdio entry: builds deps, calls buildServer, connects transport |
| src/mcp/server.ts | buildServer: registerTool/registerResource wiring (testable over InMemoryTransport) |
| src/mcp/tools/ | The 11 bcdev_* tool definitions (zod schemas + metadata + handlers) |
| src/mcp/state.ts | Debug session singleton, event queue, run lock |
| src/core/hubs/test-runner-hub.ts | TestRunnerHub client (Initialize/RunTests, coverage) |
| src/core/hubs/debugger-hub.ts | DebuggerHub client (attach, breakpoints, stepping, inspection) |
| src/core/hubs/signalr-base.ts | Hub seam: auth query params, key normalization, HubProxy |
| scripts/e2e.md | Real-server wire-assumption checklist + known server behaviours |
Development
| Command | Description |
|---------|-------------|
| bun test | Unit tests (fake-hub based, no server needed) |
| bun run typecheck | tsc --noEmit |
| bun run build | Bundle to dist/index.js (Node target) |
| bun run compile | Single executable bc-dev-mcp.exe |
Wire-format assumptions carry // WIRE: comments citing the decompiled source; anything inferred rather than decompile-verified is validated per AL major via scripts/e2e.md.
Author: Torben Leth ([email protected]) License: MIT (see LICENSE)
