Releases: igor-ctrl/bcli
bcli 0.4.0 — Agent Interface Profile v0.1
The Agent Interface Profile (AIP) v0.1 lands: a small kernel of CLI primitives any agent runtime can drive deterministically, without parallel schemas or hand-written MCP tools.
bcli describe --format jsonprojects the live Typer surface, registry, and profile as one canonical artifact.- Mutation result envelope (
--result-out PATH/--result-fd N) on every write — failures are diagnosable side-channel, no stdout scraping. - Batch operation ledger — durable SQLite, survives
SIGKILL. Three new commands:bcli batch state,bcli batch list,bcli batch rollback. - Exit code taxonomy (
0–8) replaces "non-zero = error"; agents key off specific codes. - JSON on pipe by default — pipelines, redirects, CI all get machine-readable output without flag dance.
--idempotency-keyon writes + per-stepidempotency_key:in batch YAML — same-run replay protection.bcli_mcprewrote from 4 hand-written tools to 23 generated frombcli describe, including 5 new mutating verbs that return envelopes.- Skills layer —
bcli skill installprojects saved queries and batch workflows as Claude Code slash commands;bcli skill initis an interactive wizard for per-user personalization. Entry-point groupbcli.skill_init.role_templateslets downstream packages contribute role-tailored templates without forking bcli.
Breaking changes
Two intentional breaks (one-line migrations):
- Policy refusals (read-only profile + missing
--yes) now exit8(was1). - MCP tool names match the CLI command path:
query→bcli_get,list_endpoints→bcli_endpoint_list, etc. Migration table indocs/mcp-server.md.
Full changelog
See CHANGELOG.md for the full entry, including deferred-to-v0.5 items.
v0.1.5 — drop WorkOS, default to browser PKCE
First release with simpler auth and a one-line install.
Highlights
Auth flow simplified. Browser PKCE is now the default for humans and AI agents running locally. Client-credentials covers automation. Business Central remains the permission boundary. WorkOS AuthKit support has been removed.
bcli config init picks the right flow for you.
bcli config init # browser PKCE (default — humans, agents)
bcli config init --automation # client-credentials (CI, scripts, services)
bcli config init --headless # device-code (no local browser)
Installation got simpler. CLI runtime deps (typer, rich, pyyaml, keyring) are now part of the base install:
pip install bc-cli # working bcli, no extras needed
uv tool install bc-cli # same
The [cli] extra is kept as a no-op for back-compat. The [mcp] extra no longer pulls bc-cli[cli].
New docs
docs/business-central-admin-setup.md — a zero-knowledge admin walkthrough covering Entra app registration, localhost redirect setup, delegated BC permissions, admin consent, BC user permission sets, first bcli config init, and verification.
Full changelog
See CHANGELOG.md and #8.
v0.1.3 — agent-context: error hints, AGENTS.md, Windows render fixes
Quality-of-life release focused on AI agents driving bcli and on Windows-console rendering.
Added
bcli-mcppreview server — an MCP (Model Context Protocol) server that lets Claude Desktop and other MCP clients drive bcli. Four read-only tools:query,list_endpoints,describe_endpoint,list_companies. Subprocess-only architecture inherits profile, auth, retry, telemetry, anddisable_writesfrom the CLI. Install withpip install "bc-cli[mcp]". Seedocs/mcp-server.md.AGENTS.md— discovery-first recipes for AI agents driving bcli (endpoint/field discovery, format selection, common errors).fields_discoveredhint + opt-in field discovery in MCP, so agents learn an entity's schema by touching it once.
Changed
- Errors now teach the discovery flow at the moment of failure — wrong entity name, unknown filter field, etc. surface a "did-you-mean" plus a one-liner for the right next command instead of a raw 400.
bcli company listaccepts--format(json,markdown,csv,ndjson,table).bcli endpoint listandbcli endpoint infoaccept--format json.
Fixed
- Classic Windows console: default to markdown output and stop truncating the first column.
bcliis now usable incmd.exewithout a Unicode terminal. - Workflow loader: reject YAML 1.1 boolean-key trap (
on:,yes:,no:parsed as booleans) at load time with a clear error. - Tests: catch
ConnectionErrorin WorkOS callback drain calls under Python 3.12+. - CI: remove unused
jsonimport intest_mcp/test_runner.py.
v0.1.2 — security release
Security release. Closes four findings from a third-party security scan against the repo. No public SDK signature changes; the CLI gains one new flag (bcli batch run --yes).
Security
- WorkOS localhost callback now binds a per-login high-entropy state token. Any unsolicited request reaching the loopback callback during the login window is rejected with 400 (state mismatch) or 404 (wrong path) instead of being exchanged for a role-bearing identity and persisted to disk. (vuln-0001, HIGH, CWE-352)
bcli batch runnow honoursdisable_writes. Mutating batch steps on a read-only profile prompt for confirmation interactively or abort with exit 1 in non-interactive sessions. New--yes/-yflag opts scripted use past the prompt. Pure GET batches and--dry-runare unaffected. (vuln-0002, MEDIUM, CWE-841)- Browser auth callback listener now binds an ephemeral kernel-assigned port and serves continuously until a state-bound callback arrives or the timeout expires. Stray requests (
/favicon.ico) and state-mismatched callbacks no longer consume the only callback slot. Microsoft Entra accepts any port forhttp://localhostredirect URIs on public clients per RFC 8252, so existing app registrations continue to work. (vuln-0003, MEDIUM) SafeContextwrites are now bound to the explicitenvironmentandcompany_idpassed toclient.safe_write(env, company), not the client's profile-bound target. Previously the safety gate validated operator intent but the underlying URL still resolved against the profile, so writes insidesafe_write("Sandbox", "company-SANDBOX")could still hitProduction/company-PROD. (vuln-0004, HIGH, CWE-841)
Upgrade notes
- CI scripts running mutating batches against a
disable_writesprofile now abort unless--yesis passed. Existing automation against writable profiles is unaffected. - Browser auth no longer requires port 8400 to be free; existing Entra app registrations of
http://localhostorhttp://localhost:8400continue to work.
v0.1.1 — OSS-readiness polish
OSS-readiness polish. No SDK behaviour changes; one CLI rename and a README/docstring cleanup pass.
Changed
- Renamed the document-attachment CLI command to
bcli attach, with subcommandsbcli attach uploadandbcli attach test. Functionality unchanged. The previous name was a customer-name leftover from internal development. - Genericised customer-named example values in
docs/authentication.md,examples/attach-purchase-invoice-pdf.yaml, and SDK docstrings.
Fixed
- README license badge said Apache 2.0 but the License section said MIT. Now consistent: Apache 2.0 throughout (matches the actual
LICENSEfile andpyproject.toml).
v0.1.0 — first OSS release
First public release on PyPI as bc-cli.
The PyPI distribution name is
bc-cli—bcliis squatted by an unrelated 2018-era package. The Python import name (import bcli) and CLI binary (bcli) are unaffected.
Added
- SDK —
BCClient(sync) andAsyncBCClient(async) for Microsoft Dynamics 365 Business Central. Profile-based and programmatic construction modes. - CLI — Typer-based
bcliwith subcommands for query (get), write (post/patch/delete/attach), config, auth, registry import, batch, saved queries (q), and ETL. - Three-tier endpoint resolution. Custom registry → standard v2.0 → fuzzy-match suggestion. Imports from Postman v2.1, raw JSON, or live
$metadata. - Auth — Client-credentials, device-code, browser (PKCE), and WorkOS AuthKit. Token cache with 5-min expiry buffer; OS keychain via
keyring. - Write safety —
SafeContextenforces explicitenvironment+company_idon writes; production writes requireconfirm_production=True. Thedisable_writesprofile flag adds an interactive confirmation before any mutating call. - Saved queries (
bcli q) — Named, parameterised aliases per-profile with type/pattern/min/max/enum validation. OData v4 escape on string interpolation intofilter:. - ETL pipeline — Built-in dlt source for incremental backup. Polaris REST catalog integration for Iceberg snapshots.
- Telemetry — Pluggable backends (
null,console,azure_monitor, arbitrarymodule:Class). Privacy-first defaults; opt-in capture of filter text and signed-in UPN. - Structured logging — JSON request logs on the
bcli.httplogger.
Security
Two independent review passes before publish. Highlights:
- Project-level
.bcli.tomlcannot override[telemetry] backend(closes an arbitrary-Python-import RCE). - Token and identity caches written with
0o600via atomic write; parent dir0o700. - WorkOS role cache expires after 1 hour.
@odata.nextLinkvalidated against a BC host allowlist before bearer attachment.- CI hardened — actions pinned by full SHA, default
permissions: contents: read,uv sync --locked. - Saved-query OData injection prevention.
See CHANGELOG.md for the full record.