Use
bdkas the repository-local command-line surface for DevKit local-development workflows, host discovery, host Console Command forwarding and MCP diagnostics.
[TOC]
The DevKit CLI provides a single local-development command entry point for DevKit workflows. It is packaged as the BridgingIT.DevKit.Cli .NET tool and exposes the bdk command.
DevKit applications can expose local diagnostics and operations through several processes and transports. Developers need a consistent way to discover the hosts for the current workspace, select one safely, forward commands and connect MCP clients without copying endpoint addresses or transport details.
The bdk tool combines local command dispatch, workspace-aware host discovery, selected-host storage, Console Command forwarding and a STDIO MCP server. Running DevKit web hosts advertise supported local endpoints through user-local descriptors; the CLI resolves those descriptors without loading application assemblies or accessing application databases directly.
The CLI provides:
- local CLI commands registered through the existing Console Commands dispatcher
- workspace resolution
- host runtime descriptor discovery
- host selection storage
- shared host registry commands
- Console Command forwarding into a running DevKit web host
- STDIO MCP hosting through
bdk mcp - runtime diagnostics, operations and admin MCP tools
- official DevKit documentation tools for agents
flowchart LR
User[Developer or MCP client] --> CLI[bdk CLI]
CLI --> Commands[Local CLI commands]
CLI --> Registry[Workspace host registry]
Registry --> Descriptor[Host descriptors]
CLI --> ConsoleIPC[Console Command IPC]
CLI --> McpSTDIO[MCP over STDIO]
McpSTDIO --> McpIPC[Runtime MCP IPC]
ConsoleIPC --> Host[Running DevKit web host]
McpIPC --> Host
The CLI owns parsing, output, workspace resolution and local protocol clients. The web host owns descriptor publication and application-specific command or MCP execution.
- Restore one repository-local tool and use it consistently across developer machines.
- List, select, inspect, clean or terminate DevKit hosts for the current workspace.
- Forward a registered Console Command to a selected host process.
- Expose bounded diagnostics and operations to an MCP-compatible IDE or agent.
- Query official DevKit guides and generated API reference data through stable MCP tools.
- Produce JSON output and stable exit codes for scripts and CI tasks.
Create or restore the repository-local tool, run a command and check its exit code before consuming the result.
dotnet tool restore
$versionJson = dotnet tool run bdk version --output json
if ($LASTEXITCODE -ne 0) {
throw "bdk version failed with exit code $LASTEXITCODE."
}
$versionJsonThe command writes a JSON object containing the CLI version, registered modules and exit code 0. Once a Development host is running, list hosts for the same workspace:
dotnet tool run bdk hosts list --output json
if ($LASTEXITCODE -ne 0) {
throw "Host discovery failed with exit code $LASTEXITCODE."
}| Package | Responsibility |
|---|---|
BridgingIT.DevKit.Cli |
Provides the bdk .NET tool and local-development command surface. |
BridgingIT.DevKit.Common.Abstractions |
Provides shared host descriptor DTOs and MCP request/response abstractions used by the CLI and web hosts. |
BridgingIT.DevKit.Presentation.Web |
Writes local host descriptors, advertises endpoint metadata and provides built-in health, metrics and log MCP handlers. |
BridgingIT.DevKit.Presentation |
Provides the Console Commands model used for local CLI command binding/dispatch and host-side command execution. |
Use a repository-local .NET tool manifest for normal development setup.
dotnet new tool-manifest
dotnet tool install BridgingIT.DevKit.CliCommit the generated manifest:
.config/dotnet-tools.json
Developers restore tools with:
dotnet tool restoreRun the CLI through the local tool manifest:
dotnet tool run bdk versionDuring CLI development, run the project directly from the repository:
dotnet run --project src/Presentation.Cli/Presentation.Cli.csproj -- versionThis path uses the same command host as the packaged tool. Only the process launch mechanism differs.
| Option | Description |
|---|---|
--help |
Shows root, group or command help. |
--version |
Shows CLI version information. |
--workspace <path> |
Overrides workspace resolution for host filtering and selection storage. |
--verbose |
Enables additional human-readable diagnostic output where supported. |
--quiet |
Suppresses non-essential human-readable output. |
--no-color |
Disables ANSI color output. |
--nologo |
Suppresses the startup banner. |
--banner |
Forces the startup banner when it would normally be suppressed. |
--non-interactive |
Disables interactive behavior and prompts. |
--output text|json |
Selects human-readable text or structured JSON output. |
--quiet and --verbose cannot be used together. --nologo and --banner cannot be used together. JSON output implies no color and suppresses human-only output.
The CLI can render an animated startup banner to standard error for interactive text sessions. It is suppressed for JSON, quiet, CI and non-interactive invocations unless --banner is supplied.
Workspace-aware commands use a deterministic workspace path so host filtering and selected-host storage are stable.
Resolution order:
- The explicit
--workspace <path>value. - The nearest ancestor containing
.slnx,.slnor.git. - The current directory.
The resolved path is normalized before the CLI computes the workspace hash used for selection files.
Running DevKit web hosts created with DevKitWebApplication.CreateBuilder(args) can write host descriptors to an OS user-local registry.
Default locations:
| OS | Runtime descriptor location |
|---|---|
| Windows | %LOCALAPPDATA%\bdk\hosts\runtimes |
| Linux/macOS | $XDG_RUNTIME_DIR/bdk/hosts/runtimes |
| Fallback | $TMPDIR/bdk/hosts/runtimes |
Selected hosts are stored in the sibling bdk/hosts/selections directory, scoped by the workspace hash.
The CLI reads descriptors. It does not write host descriptors. Descriptor writing belongs to the Presentation Host feature.
flowchart LR
WebHost["DevKit web host"]
Descriptor["Host descriptor JSON"]
Registry["User-local runtime registry"]
Selection["Workspace selection file"]
Cli["bdk CLI"]
WebHost -->|"writes on startup"| Descriptor
Descriptor --> Registry
Cli -->|"reads and filters by workspace"| Registry
Cli -->|"stores selected runtime id"| Selection
Cli -->|"uses selected host for host run and MCP"| WebHost
Host descriptors use shared DTOs from Common.Abstractions/HostDiscovery.
Important fields:
| Field | Purpose |
|---|---|
schemaVersion |
Descriptor schema compatibility. |
runtimeId |
Stable id for the current host process. |
applicationName |
Display name for host lists. |
environmentName |
Host environment name. |
workspacePath |
Workspace used for default filtering. |
contentRootPath |
Host content root. |
projectPath |
Optional host project path. |
processId |
Local host process id. |
startedAt |
UTC host start timestamp. |
assembly |
Host entry assembly version metadata. |
features |
Host-advertised local endpoint capabilities. |
features.consoleCommands is required for bdk host run. features.mcp is required for runtime-bound tools exposed by bdk mcp.
Shows the CLI version and registered command modules. This command does not require a running host.
bdk version
bdk version --output jsonShows command groups and shared global options.
bdk help
bdk --helpOpens the official bITdevKit documentation in the default browser. Use --url to print the documentation URL without opening a browser. JSON output reports the URL and does not open a browser.
bdk docs
bdk docs --url
bdk docs --output jsonLists ready host descriptors for the current workspace. Stale descriptors are hidden by default because local development processes are often killed or restarted. Use --all to include stale descriptors and descriptors outside the current workspace.
bdk hosts list
bdk hosts list --all
bdk hosts list --feature consoleCommands
bdk hosts list --output jsonStatuses:
| Status | Meaning |
|---|---|
Ready |
Descriptor is valid and the process appears live. |
Stale |
The descriptor points to a process that is no longer running. |
Invalid |
The descriptor cannot be parsed or is missing required fields. |
VersionMismatch |
The descriptor schema is incompatible. |
FeatureUnavailable |
A requested endpoint capability is missing. |
Unreachable |
A descriptor is valid but its endpoint cannot be reached. |
Shows the currently selected host for the workspace.
bdk hosts current
bdk hosts current --output jsonStores the selected runtime id for the current workspace.
bdk hosts select commerce-api-5001Re-reads descriptors and reports current ready hosts. Stale descriptors remain hidden unless --all is supplied.
bdk hosts refresh
bdk hosts refresh --allShows entry assembly version metadata for ready hosts in the current workspace. Stale descriptors are hidden by default for the same reason as bdk hosts list; use --all to include stale descriptors and descriptors outside the current workspace.
bdk hosts versions
bdk hosts versions --all
bdk hosts versions --output jsonThis command reads descriptor metadata only. It does not enumerate all assemblies loaded inside the host process.
Removes stale, invalid or unreachable descriptors when explicitly confirmed.
bdk hosts clean
bdk hosts clean --yes
bdk hosts clean --yes --output jsonWithout --yes, the command reports that confirmation is required.
Terminates ready host processes for the current workspace. The command never targets stale descriptors, because stale descriptor process ids may have been reused by unrelated processes. Specify either one runtime id or --all, and add --yes to actually terminate processes.
bdk hosts kill commerce-api-5001
bdk hosts kill commerce-api-5001 --yes
bdk hosts kill --all --yes
bdk hosts kill --all --yes --output jsonWithout --yes, the command reports candidate processes and marks them as confirmation-required. Use bdk hosts clean --yes afterwards if you want to remove descriptors that became stale after termination.
Forwards a Console Command invocation to a selected running web host.
bdk host run status
bdk host run diag perf
bdk host run --host commerce-api-5001 -- seed products --count=50The host must advertise features.consoleCommands in its descriptor. The command executes inside the selected host process through the host's registered IConsoleCommand services and returns the host command output to the CLI.
Forwarded command tokens after bdk host run are preserved. Use -- to separate CLI forwarding options from host command tokens when needed.
Starts the CLI as a STDIO MCP server for local agents and IDEs.
bdk mcp
bdk mcp --toolset diagnostics,operations
bdk mcp --toolset diagnostics,operations,admin
bdk mcp --runtime-id commerce-api-5001The command speaks JSON-RPC over standard input and output. Human logs and diagnostics must go to standard error so MCP clients can parse standard output safely.
Runtime-bound MCP tools select a running host from the same workspace-aware host registry used by bdk hosts and bdk host run. Documentation tools use official online DevKit documentation and do not require a running host.
Toolsets:
| Toolset | Purpose |
|---|---|
diagnostics |
Read-only inspection tools. Enabled by default. |
operations |
Runtime actions such as retry, pause, resume, signal or trigger. |
admin |
Destructive maintenance tools such as purge. Admin tools also require confirm=true and the operation-specific confirmation phrase. |
| Exit code | Category | Meaning |
|---|---|---|
0 |
Success | Command completed successfully. |
1 |
CommandFailed | Command ran but failed. |
2 |
InvalidArguments | Arguments or options were invalid. |
3 |
HostNotFound | No compatible running host was found. |
4 |
HostSelectionRequired | Multiple compatible hosts require explicit selection. |
5 |
SelectedHostUnavailable | Selected host is stale, unreachable or incompatible. |
6 |
ProtocolVersionMismatch | CLI and host protocol versions are incompatible. |
7 |
InternalError | Unexpected CLI error. |
The CLI is a local-development tool. Host discovery and command forwarding use OS user-local descriptor and IPC locations.
Rules:
- Descriptors are stored outside the repository.
- Descriptor presence alone is not authorization to execute host commands.
- Host endpoint nonces are sent with local IPC requests.
- Non-development hosts should not advertise CLI-connectable endpoints by default.
- Destructive host commands remain responsible for their own confirmations and safeguards.
The nonce helps avoid accidental use of stale or spoofed descriptors in the same user-local registry. It is not production authentication.
The CLI aligns terminal behavior with the existing Console Commands feature. Local bdk commands use the same Spectre.Console style, while bdk host run executes the selected host's IConsoleCommand implementation in the host process.
sequenceDiagram
participant User
participant CLI as bdk CLI
participant Registry as Host registry
participant IPC as Local IPC
participant Host as DevKit web host
participant Command as IConsoleCommand
User->>CLI: bdk host run status
CLI->>Registry: Discover ready consoleCommands runtimes
Registry-->>CLI: Matching descriptors
CLI->>IPC: Forward command tokens with nonce
IPC->>Host: Console command request
Host->>Command: Execute in host DI scope
Command-->>Host: Output and exit code
Host-->>CLI: Console command result
CLI-->>User: Render output
MCP is implemented as a command module inside bdk. The CLI owns STDIO protocol handling, stable MCP tool names, runtime discovery and runtime selection. Running DevKit web hosts own application-specific execution through app-side MCP handlers.
The stable catalog includes runtime tools, investigation tools, logs/errors, health/metrics, messaging, queueing, jobs, orchestrations, documentation and project-owned operation dispatch. Project operations remain discoverable through capabilities and callable through bdk_project_call; they are not added as dynamic MCP tools by default.
bdk mcp is a local bridge between an MCP client and one or more running DevKit hosts in the same workspace.
flowchart LR
subgraph ClientSide["Agent or IDE process"]
Client["MCP client"]
end
subgraph CliSide["bdk CLI process"]
Stdio["StdioMcpServer"]
Catalog["McpToolCatalog"]
Executor["McpToolExecutor"]
RuntimeTools["McpRuntimeTools"]
DocsTools["McpDocumentationTools"]
IpcClient["McpIpcClient"]
end
subgraph HostSide["DevKit web host process"]
IpcServer["McpIpcServer"]
Dispatcher["McpDispatcher"]
Handler["IMcpHandler"]
AppService["Application service"]
end
Client -->|"JSON-RPC over STDIO"| Stdio
Stdio --> Catalog
Stdio --> Executor
Executor -->|"docs tools"| DocsTools
Executor -->|"runtime tools"| RuntimeTools
RuntimeTools --> IpcClient
IpcClient -->|"named pipe or Unix socket"| IpcServer
IpcServer -->|"validated nonce and protocol"| Dispatcher
Dispatcher --> Handler
Handler --> AppService
AppService --> Handler
Handler --> Dispatcher
Dispatcher --> IpcServer
IpcServer --> IpcClient
IpcClient --> RuntimeTools
RuntimeTools --> Executor
DocsTools --> Executor
Executor --> Stdio
Stdio --> Client
Runtime-bound tool calls follow this sequence:
sequenceDiagram
participant Client as MCP client
participant Stdio as StdioMcpServer
participant Exec as McpToolExecutor
participant Runtime as McpRuntimeTools
participant Registry as Host registry
participant IpcClient as McpIpcClient
participant IpcServer as McpIpcServer
participant Dispatcher as McpDispatcher
participant Handler as Feature IMcpHandler
participant Service as Application service
Client->>Stdio: tools/call bdk_queueing_messages
Stdio->>Exec: Execute stable tool
Exec->>Exec: Validate toolset
Exec->>Runtime: Forward queueing.messages
Runtime->>Registry: Resolve selected runtime
Registry-->>Runtime: Runtime descriptor with features.mcp
Runtime->>IpcClient: Invoke operation over local IPC
IpcClient->>IpcServer: MCP IPC request with nonce
IpcServer->>IpcServer: Validate nonce and protocol
IpcServer->>Dispatcher: Dispatch operation and toolset
Dispatcher->>Handler: Handle queueing.messages
Handler->>Service: Query retained queue messages
Service-->>Handler: Bounded result
Handler-->>Dispatcher: McpResponse
Dispatcher-->>IpcServer: McpIpcResponse
IpcServer-->>IpcClient: JSON response
IpcClient-->>Runtime: McpResponse
Runtime-->>Exec: Tool result
Exec-->>Stdio: MCP content
Stdio-->>Client: JSON-RPC result
Key components:
| Component | Responsibility |
|---|---|
StdioMcpServer |
Implements the MCP JSON-RPC loop over standard input/output. |
McpToolCatalog |
Defines the stable public bdk_* tool list shown to MCP clients. |
McpToolExecutor |
Maps stable tool names to runtime operations, docs operations or project operation dispatch. |
McpRuntimeTools |
Resolves workspaces, selected runtimes, capabilities and IPC forwarding. |
McpIpcClient / McpIpcServer |
Carry bounded MCP requests between the CLI process and the selected web host. |
McpDispatcher |
Finds the app-side handler that advertises the requested operation. |
IMcpHandler |
Feature-owned operation handler implemented by Presentation.Web packages or the application. |
Runtime selection follows the same rules as host commands:
--runtime-id <id>or--host <id>onbdk mcpwins.- A saved workspace selection from
bdk_runtimes_selectorbdk hosts selectis used. - If exactly one ready MCP runtime exists, it is selected automatically.
- If multiple ready runtimes exist, runtime-bound tools return
runtime_selection_required.
flowchart TD
Start([Runtime-bound MCP tool call])
Explicit{--runtime-id or --host supplied?}
ExplicitReady{Matching ready MCP runtime?}
Saved{Workspace selection exists?}
SavedReady{Selected runtime ready?}
Count{Ready MCP runtime count}
UseExplicit[Use explicit runtime]
UseSaved[Use saved runtime]
UseOnly[Use only ready runtime]
SelectionRequired[Return runtime_selection_required]
NoRuntime[Return no_runtime_found]
SelectedUnavailable[Return selected_runtime_unavailable]
Start --> Explicit
Explicit -->|Yes| ExplicitReady
ExplicitReady -->|Yes| UseExplicit
ExplicitReady -->|No| SelectedUnavailable
Explicit -->|No| Saved
Saved -->|Yes| SavedReady
SavedReady -->|Yes| UseSaved
SavedReady -->|No| SelectedUnavailable
Saved -->|No| Count
Count -->|0| NoRuntime
Count -->|1| UseOnly
Count -->|More than 1| SelectionRequired
The CLI enforces coarse toolset authorization before any IPC call. The host dispatcher also verifies that the requested toolset matches the advertised capability. This gives two safeguards: the MCP process must be started with the toolset, and the selected host must explicitly expose the operation under that toolset.
Feature packages contribute MCP handlers through their presentation registration extensions. For example, messaging, queueing, job scheduling and orchestration presentation packages register their handlers when their endpoints or console commands are registered. Built-in Presentation.Web handlers provide health, metrics and retained-log diagnostics when the corresponding services are available.
Documentation tools are different from runtime tools. bdk_docs_search and bdk_docs_get read the official DevKit documentation from GitHub. API-reference tools first use generated Pages data under .github/pages/api when it exists in the resolved workspace, then fall back to the published GitHub Pages API reference.
MCP client configuration can be source-controlled for the repo:
.mcp.jsonfor clients that read repo-level MCP configuration..vscode/mcp.jsonfor VS Code.- Rider and Visual Studio can be configured with the same command shape documented in MCP Clients.
The MCP catalog is intentionally stable. Adding tools should be deliberate because every bdk_* tool becomes part of the agent-facing CLI surface.
Use this checklist for new DevKit-owned MCP tools:
- Decide whether the operation should be a stable
bdk_*tool or a project-owned operation. - Pick the least powerful toolset:
diagnostics,operationsoradmin. - Define the app-side operation name, such as
queueing.messagesororchestrations.signal. - Add or extend an app-side
IMcpHandlerin the owning presentation feature package. - Advertise a matching
McpCapabilitywith the correct operation name, feature and toolset. - Register the handler through the feature's presentation registration extension.
- Add the stable tool definition to
McpToolCatalogonly when this is a DevKit-owned tool. - Add the tool-to-operation mapping in
McpToolExecutor. - Add tests for catalog exposure, forwarding/toolset behavior and handler behavior.
- Update this documentation and the MCP developer documentation when the tool changes how developers use MCP.
Use project-owned operations instead of stable tools when the behavior belongs to one application or module. This is the extension model for client projects that want to offer their own MCP tool platform on top of bdk without changing the CLI catalog:
App IMcpHandler
-> advertises owner/category/operation/toolset/schema
bdk_project_operations
-> lists project-owned capabilities from the selected runtime
bdk_project_call
-> invokes one project-owned operation by name and toolset
Register project handlers through the DevKit web application builder:
var builder = DevKitWebApplication.CreateBuilder(args)
.AddConfiguration()
.AddLogging()
.AddModules(modules => modules
.WithModule<CommerceModule>())
.AddMcp(mcp => mcp
.WithHandler<CommerceMcpHandler>());For several handlers in the same module assembly, use:
.AddMcp(mcp => mcp
.WithHandlersFromAssembly<CommerceModule>())AddMcp(...) defaults to the host's evaluated local MCP tooling decision. It registers project handlers only when local MCP hosting is enabled for that host. Use .Enabled(true) or .Enabled(false) on the MCP registration builder only when an application needs an explicit override.
Project calls use the stable dispatcher shape:
{
"operation": "commerce_inspect_customer",
"toolset": "diagnostics",
"arguments": {
"customerNumber": "CUST-10042",
"includeRecentOrders": true
}
}toolset is optional for compatibility and defaults to diagnostics, but new project tools should supply it explicitly. The CLI validates that the value is one of diagnostics, operations or admin before forwarding to the selected runtime.
Project-owned operations must use client-safe names with lowercase letters, digits, underscores or hyphens. They must not use the reserved bdk_ prefix and should usually use the diagnostics toolset unless they perform an explicit runtime action.
Safety requirements:
| Requirement | Guidance |
|---|---|
| Keep CLI logic thin | The CLI must not query application databases, call dashboard HTTP endpoints or load application configuration for runtime tools. |
| Keep handlers feature-owned | Put the handler next to the presentation feature that owns the application service contract. |
| Keep responses bounded | Return compact models, page large results and mark truncated responses when applicable. |
| Keep admin explicit | Purge or destructive cleanup tools must require confirm=true and a phrase-specific confirmation argument. |
| Keep docs remote | bdk_docs_* tools must use official online DevKit documentation, not local repository docs. |
| Keep protocols separate | App-side handlers use DevKit IMcpHandler; they do not depend on the MCP SDK or STDIO transport types. |
Typical file changes for a new stable runtime tool:
| File area | Change |
|---|---|
src/Common.Abstractions/Mcp |
Add shared request/response helpers only when the existing envelope is insufficient. |
src/Presentation.Cli/Mcp/McpToolCatalog.cs |
Add the public bdk_* tool definition and input schema. |
src/Presentation.Cli/Mcp/McpToolExecutor.cs |
Map the public tool to the internal operation and required toolset. |
src/Presentation.Web.<Feature>/Mcp/* |
Implement or extend the feature-owned handler. |
src/Presentation.Web.<Feature>/ServiceCollectionExtensions.cs |
Register the handler through feature setup. |
tests/Presentation.UnitTests |
Cover catalog/toolset behavior and handler success/failure paths. |
docs/features-cli-mcp.md |
Explain developer-facing usage if the tool adds a new workflow. |
Start a DevKit web application that uses DevKitWebApplication.CreateBuilder(args) in Development. Raw WebApplication.CreateBuilder(args) applications do not write host descriptors by convention.
Check that the selected host advertises features.consoleCommands:
bdk hosts list --feature consoleCommandsAlso verify local CLI integration is not disabled by configuration:
{
"DevKit": {
"Cli": {
"Enabled": false,
"ConsoleCommands": false
}
}
}Select a host once for the workspace:
bdk hosts select commerce-api-5001Or pass an explicit selector:
bdk host run --host commerce-api-5001 -- status