@365businessdev/albuild-mcp
v0.1.26233
Published
ALbuild MCP server - exposes Business Central container/runtime-validation tools (provision, deploy, test) to LLM agents over stdio and streamable HTTP.
Maintainers
Readme
ALbuild MCP server
An MCP server that exposes ALbuild's Business Central container / runtime-validation capabilities to LLM agents (OpenClaw 365 local agents, Claude Code CLI/VSCode on any OS). It closes the gap between "it compiles" (the AL MCP's job) and "it actually runs and the tests pass against a specific BC version".
Built on the businessdev.ALbuild PowerShell module — every tool is a thin, typed wrapper over an
existing cmdlet.
Why
A fast inner loop: provision or reuse a warm BC container and iterate deploy → test in well
under two minutes, versus 15+ minutes for a full CI pipeline. CI remains the authoritative gate; this
is the development loop before it. Container ops are Windows + Docker only — so the remote HTTP
deployment is the only way a Mac developer/agent gets real BC runtime validation.
Transports
One binary, two transports (chosen at start):
| Transport | Start | Use |
|---|---|---|
| stdio | node dist/index.js (default) | local Claude Code on a Windows box with Docker |
| Streamable HTTP | node dist/index.js --http | shared Windows Server; OpenClaw agents + Mac Claude Code over LAN/Tailscale |
Auth is opt-in: with no ALBUILD_MCP_TOKENS configured the HTTP endpoint is open and
accepts every request, scoped to the default agent; set tokens to require a per-agent bearer token.
It binds to 127.0.0.1 by default (LAN/Tailscale-only — never expose it publicly without mTLS + an
IP allowlist; on an open, non-loopback host, anyone who can reach the port has full access).
New here? Follow the bundled
INSTALL.md(included in this package) — a step-by-step guide for the local (stdio) and remote (HTTP) setups, including the AI-client config snippets.
Build & run
npm install
npm run build
albuild-mcp --check # preflight: verifies PowerShell + businessdev.ALbuild module + Docker
# local stdio
node dist/index.js
# shared HTTP host
ALBUILD_MCP_TOKENS='{"<token-agent1>":"agent1","<token-agent2>":"agent2"}' node dist/index.js --httpOn start the server runs the same preflight as a hard gate and refuses to start if PowerShell or the
module is missing (bypass with ALBUILD_MCP_SKIP_PREFLIGHT=1). Drop the bundled templates/ai/CLAUDE.md
(included in this package) into your repo so the assistant follows the right workflow.
Tests
npm run build
node dist/test/smoke.js # fast: protocol + read-only tools + governance gate (no container)
npm run live-test # slow: creates a real BC 28.2/de container, inspects it, removes itConfiguration (environment)
| Variable | Default | Purpose |
|---|---|---|
| ALBUILD_MODULE_PATH | repo path else installed module | The PowerShell module to import. |
| ALBUILD_POWERSHELL | pwsh (falls back to powershell) | PowerShell executable. |
| ALBUILD_DOCKER | docker | Docker executable. |
| ALBUILD_MAX_WARM_CONTAINERS | 2 | Pool size cap (LRU eviction beyond it). RAM-bound. |
| ALBUILD_CONTAINER_MEMORY | 8G | Memory per container; ceiling for a tool's memoryLimit request. |
| ALBUILD_DEFAULT_ARTIFACT_TYPE | Sandbox | Fallback artifact type. |
| ALBUILD_ALLOW_SELF_CLEANUP | true | Agent may remove containers it created without approval. |
| ALBUILD_POOL_STATE | %LOCALAPPDATA%/albuild-mcp/pool.json | Pool registry file. |
| ALBUILD_MCP_HTTP_HOST | 127.0.0.1 | HTTP bind host. |
| ALBUILD_MCP_PORT | 5020 | HTTP port (OpenClaw reserves 5010–5099). |
| ALBUILD_MCP_TOKENS | (none) | JSON { "<token>": "<agentId>" } for HTTP bearer auth. Unset ⇒ open: every request is accepted as the default agent. |
| ALBUILD_MCP_AGENT | claude-code | Agent identity for the stdio transport (scopes the toolset). |
| ALBUILD_MCP_AGENT_TOOLSETS | (none) | Inline JSON { "<agent>": ["tool", …] } mapping agents to allowed tools. |
| ALBUILD_MCP_AGENTS_FILE | (none) | Path to a JSON file with the same shape (see examples/agent-toolsets.example.json). |
Tools
Read-only are synchronous; mutating/long tools return a jobId (poll get-job).
| Tool | Tier | Notes |
|---|---|---|
| list-containers | read-only | docker state + pool metadata |
| inspect-container | read-only | + installed apps |
| find-artifact | read-only | resolve a BC artifact URL |
| get-build-order | read-only | multi-project dependency order |
| resolve-dependencies-plan | read-only | dry-run dependency resolution |
| ensure-container | mutating (job) | warm-reuse or provision; optional dependency install |
| restart-container | mutating (job) | |
| remove-container | destructive | self-created → runs; shared → approval_required |
| reconcile-dependencies | read-only | manifest vs container vs feeds → satisfied / feed-available / missing |
| publish-app | mutating (job) | upload a built .app (base64) and publish it — the remote file transport |
| deploy-and-test | mutating (job) | appFolder (local) or apps:[{name,base64}] (remote) → publish clean → run tests |
| run-tests | mutating (job) | re-run tests without redeploy |
| get-job / cancel-job | read-only | async job control |
Remote app/dependency flow
When the agent is not on the MCP host (e.g. OpenClaw/Claude Code on a Mac → Windows MCP host), a filesystem path is meaningless on the host, so:
reconcile-dependencies— send theapp.jsondependencies and the merged (app + workspace)albuild.jsonfeeds (the host can't read your repo). Private feeds carry their API key infeeds[].token— the host doesn't have these credentials, so the agent supplies them (kept out of logs, passed to PowerShell via a child env var). Get back what's satisfied (in the container, incl. Microsoft apps), availableFromFeed, and missing.publish-app/deploy-and-test(upload form) — send the missing.apps (and the app + test app) as base64; the server stages them on the host and publishes. Tests run bytestExtensionId.
Per-agent tool scoping
Each agent (by stdio ALBUILD_MCP_AGENT or HTTP token) sees only its allowed tools — a correctness
requirement for small local models. The mapping is configurable, not baked in: set
ALBUILD_MCP_AGENT_TOOLSETS (inline JSON) or ALBUILD_MCP_AGENTS_FILE (a JSON file) to
{ "<agent>": ["tool", …] }, where ["*"] means all tools and a "*" agent key is the catch-all.
- Default (no config): permissive — every agent gets every tool (
{ "*": ["*"] }), so the package works out of the box. - With a config that has no
"*"key: deny-by-default — an unlisted agent gets no tools.
See examples/agent-toolsets.example.json for a ready roster
(e.g. a coding agent, an ops agent, read-only architecture/DevOps agents, and a full claude-code).
Governance
- Mutating tools run as logged async jobs.
remove-container(and other destructive/external actions) on shared/pre-existing resources return{ status: "approval_required" }for the OpenClaw Escalation Router instead of acting.- The host's own secrets (its PAT, signing cert) live on the host as the service identity. Per-feed API
keys, which the host does not have, are sent by the agent (
reconcile-dependenciesfeeds[].token), kept out of logs and passed to PowerShell via a child env var (never inline). Relies on the authenticated, LAN/Tailscale-only channel.
