npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@365businessdev/albuild-mcp

v0.4.27696

Published

ALbuild MCP server - exposes Business Central container/runtime-validation tools (provision, deploy, test) to LLM agents over stdio and streamable HTTP.

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 --http

On 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 it

Configuration (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). A direct MCP client already sees this async shape — start the tool, then poll get-job (and cancel-job to abort). The albuild CLI blocks by default (it polls for you); pass albuild … --no-wait to get the same start-and-poll-yourself flow from the CLI (see the CLI README's "Async / non-blocking" section).

| Tool | Tier | Notes | |---|---|---| | list-containers | read-only | docker state + pool metadata | | inspect-container | read-only | + installed apps + reachable web-client URL/protocol/credentials | | 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; optional http + reachability:'transparent' for a LAN-reachable HTTP container; optional language (e.g. de-DE) for the UI language | | 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 |

LAN-reachable HTTP container (for a browser agent)

By default a container is on Docker's NAT and serves the Web Client over the image's self-signed HTTPS — reachable only on the Docker host. To let an external browser agent (e.g. OpenClaw's Playwright on another host) open the Web Client and screenshot pages, ensure-container takes two opt-in inputs:

  • http: true — serve the Web Client over plain HTTP (image env useSSL=N); no self-signed-cert problem, NavUserPassword still works.
  • reachability: "transparent" — attach to a transparent Docker network so the container gets its own LAN IP via DHCP (reachable from other hosts; no port publishing/firewall). On a Hyper-V VM host, enable MACAddressSpoofing on the vNIC.

ensure-container and inspect-container then return the IP-based webClientUrl (e.g. http://<lan-ip>/BC/?tenant=default), protocol, ipAddress and the NavUserPassword credentials — everything the browser agent needs. The URL is re-resolved live on warm reuse (a transparent DHCP IP can change). The IP is read from docker inspect, with a docker exec fallback that reads the DHCP-assigned IP from inside the container — Docker's NetworkSettings IP is empty for a transparent network on Windows, so this fallback is what keeps ipAddress/webClientUrl populated on a transparent container.

Dev/Sandbox + trusted LAN only. HTTP + NavUserPassword sends credentials in clear text. The default (not exposed, HTTPS) is unchanged, and remove-container stays approval-gated.

UI language

ensure-container takes an optional language (a culture name, e.g. de-DE; default en-US). A non-default language sets the instance's DefaultLanguage and pins SupportedLanguages to it, so the web client shows that language even when the browser sends a different Accept-Language (a headless Chromium usually sends en-US). Setting it restarts the service tier (the keys are not dynamically updatable), so it is skipped for the en-US default.

The language module must be installed on the instance — use a matching country artifact (e.g. country: "de" ships de-DE; w1 does not). If it is not installed the container is still created and usable (it stays en-US with a warning; language comes back null) rather than being orphaned. ensure-container/inspect-container return the applied language and supportedLanguages. language is part of the warm-reuse key, so a de-DE request never reuses an en-US container.

Pool, warm-reuse & cleanup

Every container ensure-container provisions is registered in the server's pool and reported as managedByMcp: true by list-containers. Warm-reuse matches on country + artifactType + bcVersion

  • protocol + reachability + language; a second identical ensure-container call returns the same container (reused: true, path: "fast"). The pool entry is written as soon as the container is created — before the best-effort URL resolution — so a reachability hiccup can never leave a healthy container unmanaged. An agent may remove-container a container it created without approval (allowSelfCleanup); a failed provisioning removes its partial container automatically. Secrets never appear in error messages or logs (docker run command lines are redacted).

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:

  1. reconcile-dependencies — send the app.json dependencies and the merged (app + workspace) albuild.json feeds (the host can't read your repo). Private feeds carry their API key in feeds[].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.
  2. 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 by testExtensionId.

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-dependencies feeds[].token), kept out of logs and passed to PowerShell via a child env var (never inline). Relies on the authenticated, LAN/Tailscale-only channel.