MCP Server
Connect MCP-aware agents to DubStack stack tools, gated by a per-repo security model.
DubStack includes a stdio Model Context Protocol server so agents can inspect and (optionally) drive a tracked repository without shelling out to free-form commands.
Install
From any shell where dub is available:
claude mcp add dubstack dub mcpThen ask your MCP-aware agent about the current repository:
Show me the current DubStack stack.The agent can call dubstack.log and receive structured JSON for the tracked stack tree.
Read-only tools
| Tool | Description |
|---|---|
dubstack.log | Returns the tracked stack tree as JSON |
dubstack.doctor | Returns health issues and remediation steps |
dubstack.status | Returns current branch, tracking info, PR state, and drift |
dubstack.parent | Returns the direct parent for a branch |
dubstack.children | Returns direct children for a branch |
dubstack.trunk | Returns the trunk/root branch for a branch |
dubstack.history | Returns recent Dub command history |
dubstack.branch | Returns single-branch stack metadata |
dubstack.diff | Returns a branch diff vs its parent or an explicit base |
dubstack.ready | Returns a pre-submit readiness checklist |
dubstack.merge_check | Returns a PR/branch/stack mergeability snapshot |
AI-cooperative tools
These tools call the configured AI provider but do not mutate git, DubStack
state, or GitHub. They are available in every MCP mode when the repo has
dub config ai-assistant on and a provider configured.
| Tool | Description |
|---|---|
dubstack.propose_branch_name | Suggests a branch name from a diff |
dubstack.propose_commit_message | Suggests a Conventional Commit message from a diff |
dubstack.propose_pr_description | Suggests PR markdown from branch/base/message/diff context |
Mutating tools
| Tool | Description |
|---|---|
dubstack.create | Create a stacked branch (optionally with a commit message or --ai) |
dubstack.modify | Amend the current tip or commit new changes, then restack children |
dubstack.submit | Push the current path or stack and create/update GitHub PRs |
dubstack.sync | Sync tracked branches with the remote and reconcile divergence |
dubstack.checkout | Switch to a tracked branch (stack-aware) |
dubstack.back | Return to a previously checked-out branch (steps optional) |
dubstack.delete | Delete a local branch and update DubStack metadata |
dubstack.reorder | Reorder or drop commits on the current tracked branch from a supplied todo |
dubstack.freeze | Mark a branch or stack scope as frozen |
dubstack.unfreeze | Clear the frozen marker from a branch or stack scope |
dubstack.split | Split the current branch by file, commit, or AI proposal (by-hunk remains terminal-only) |
dubstack.absorb | Distribute fixup commits to their targets |
dubstack.squash | Collapse branch commits into one commit |
dubstack.fold | Combine the current branch into its parent |
dubstack.pop | Pop recent commits into staged changes |
dubstack.rename | Rename a tracked branch and update stack metadata |
dubstack.move | Move a branch before/after another branch in the stack |
dubstack.unlink | Detach a branch from its parent without deleting branches |
dubstack.revert | Create a tracked revert branch on trunk |
dubstack.stash | Create a branch-aware stash entry |
dubstack.stash-pop | Pop the most recent branch-aware stash |
Mutating tools are gated by the configured MCP mode (see below).
Return shapes
Read-only and AI-cooperative tools return JSON as both MCP text content and
structuredContent:
{
"content": [{ "type": "text", "text": "{ ... }" }],
"structuredContent": {
"branch": "feat/example",
"base": "main",
"diff": "..."
}
}Mutating tools wrap the command result and captured terminal output:
{
"content": [{ "type": "text", "text": "{ ... }" }],
"structuredContent": {
"result": { "branch": "feat/example" },
"output": "..."
}
}Refusals and user-facing command failures return isError: true with a
text payload suitable for agent display.
Security model
Choose how aggressive the agent's automation is for this repository:
dub config mcp-mode read-only # only read tools work; mutating tools return a refusal payload
dub config mcp-mode interactive # mutating tools require explicit y/n confirmation in the dub mcp terminal (DEFAULT)
dub config mcp-mode trusted # mutating tools run without confirmationRun dub config mcp-mode with no argument to inspect the current value.
read-only
Mutating tools return a structured refusal that the agent can surface cleanly:
{
"isError": true,
"content": [{
"type": "text",
"text": "dubstack.create refused: repo is in read-only MCP mode. Run `dub config mcp-mode interactive` to enable mutating tools."
}]
}interactive (default)
When the MCP server receives a mutating tool call, it opens the controlling terminal (/dev/tty) where dub mcp is running, prints a confirmation prompt, and waits for y/n. If no controlling terminal is available, the tool refuses with a clear message asking you to switch to trusted or read-only mode.
This is the right default for workflows like Claude Code, where dub mcp runs in a known terminal pane.
trusted
Mutating tools execute immediately without confirmation. Use this only when you fully trust the agent driving DubStack.
Audit history
Every MCP tool invocation — successful, refused, or failed — is appended to dub history:
dub historyFor mutating tools, the audit command includes redacted arguments plus an
args_sha256 fingerprint so reviewers can compare what an agent passed without
exposing secrets in history.
Protocol
dub mcp uses MCP stdio transport. Clients write newline-delimited JSON-RPC messages to stdin, and DubStack writes JSON-RPC responses to stdout.
The server supports:
initializetools/listtools/callpingnotifications/initialized