Commit Graph

32 Commits

Author SHA1 Message Date
Jordan Docherty
a791991103 Update link to install script (#867) 2026-01-03 12:53:58 -08:00
Steve Yegge
1611f16751 refactor: remove unused bd pin/unpin/hook commands (bd-x0zl)
Analysis found these commands are dead code:
- gt never calls `bd pin` - uses `bd update --status=pinned` instead
- Beads.Pin() wrapper exists but is never called
- bd hook functionality duplicated by gt mol status
- Code comment says "pinned field is cosmetic for bd hook visibility"

Removed:
- cmd/bd/pin.go
- cmd/bd/unpin.go
- cmd/bd/hook.go

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 16:02:15 -08:00
Steve Yegge
c8b912cbe6 bd sync: 2025-12-27 15:56:42 2025-12-27 15:56:42 -08:00
Aarya Reddy
bd5fc214c3 feat(ready,blocked): Add --parent flag for scoping by epic/bead desce… (#743)
* feat(ready,blocked): Add --parent flag for scoping by epic/bead descendants

Add --parent flag to `bd ready` and `bd blocked` CLI commands and MCP tools
to filter results to all descendants of a specific epic or bead.

## Backward Compatibility

- CLI: New optional --parent flag; existing usage unchanged
- RPC: New `blocked` operation added (was missing); existing operations unchanged
- MCP: New optional `parent` parameter; existing calls work as before
- Storage interface: GetBlockedIssues signature changed to accept WorkFilter
  - All callers updated to pass empty filter for existing behavior
  - Empty WorkFilter{} returns identical results to previous implementation

## Implementation Details

SQLite uses recursive CTE to traverse parent-child hierarchy:

    WITH RECURSIVE descendants AS (
        SELECT issue_id FROM dependencies
        WHERE type = 'parent-child' AND depends_on_id = ?
        UNION ALL
        SELECT d.issue_id FROM dependencies d
        JOIN descendants dt ON d.depends_on_id = dt.issue_id
        WHERE d.type = 'parent-child'
    )
    SELECT issue_id FROM descendants

MemoryStorage implements equivalent recursive traversal with visited-set
cycle protection via collectDescendants helper.

Parent filter composes with existing filters (priority, labels, assignee, etc.)
as an additional WHERE clause - all filters are AND'd together.

## RPC Blocked Support

MCP beads_blocked() existed but daemon client raised NotImplementedError.
Added OpBlocked and handleBlocked to enable daemon RPC path, which was
previously broken. Now both CLI and daemon clients work for blocked queries.

## Changes

- internal/types/types.go: Add ParentID *string to WorkFilter
- internal/storage/sqlite/ready.go: Add recursive CTE for parent filtering
- internal/storage/memory/memory.go: Add getAllDescendants/collectDescendants
- internal/storage/storage.go: Update GetBlockedIssues interface signature
- cmd/bd/ready.go: Add --parent flag to ready and blocked commands
- internal/rpc/protocol.go: Add OpBlocked constant and BlockedArgs type
- internal/rpc/server_issues_epics.go: Add handleBlocked RPC handler
- internal/rpc/client.go: Add Blocked client method
- integrations/beads-mcp/: Add BlockedParams model and parent parameter

## Usage

  bd ready --parent bd-abc              # All ready descendants
  bd ready --parent bd-abc --priority 1 # Combined with other filters
  bd blocked --parent bd-abc            # All blocked descendants

## Testing

Added 4 test cases for parent filtering:
- TestParentIDFilterDescendants: Verifies recursive traversal (grandchildren)
- TestParentIDWithOtherFilters: Verifies composition with priority filter
- TestParentIDWithBlockedDescendants: Verifies blocked issues excluded from ready
- TestParentIDEmptyParent: Verifies empty result for childless parent

* fix: Correct blockedCmd indentation and suppress gosec false positive

- Fix syntax error from incorrect indentation in blockedCmd Run function
- Add nolint:gosec comment for GetBlockedIssues SQL formatting (G201)
  The filterSQL variable contains only parameterized WHERE clauses with
  ? placeholders, not user input
2025-12-25 21:11:58 -08:00
Steve Yegge
f3a5e02a35 feat(close): Add --suggest-next flag to show newly unblocked issues (GH#679)
When closing an issue, the new --suggest-next flag returns a list of
issues that became unblocked (ready to work on) as a result of the close.

This helps agents and users quickly identify what work is now available
after completing a blocker.

Example:
  $ bd close bd-5 --suggest-next
  ✓ Closed bd-5: Completed

  Newly unblocked:
    • bd-7 "Implement feature X" (P1)
    • bd-8 "Write tests for X" (P2)

Implementation:
- Added GetNewlyUnblockedByClose to storage interface
- Implemented efficient single-query for SQLite using blocked_issues_cache
- Added SuggestNext field to CloseArgs in RPC protocol
- Added CloseResult type for structured response
- CLI handles both daemon and direct modes

Thanks to @kraitsura for the detailed feature request and design.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 20:05:04 -08:00
Steve Yegge
488ec56938 fix(mcp): Graceful fallback on Windows for daemon mode (GH#387)
- Skip daemon mode on Windows (sys.platform == win32)
- Falls back to CLI mode which works on all platforms
- Avoids asyncio.open_unix_connection which does not exist on Windows

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 19:50:55 -08:00
Aarya Reddy
e58d60b802 feat(mcp): add output control parameters for token efficiency (#667)
Add granular control over MCP tool response sizes to minimize context
window usage while maintaining full functionality when needed.

## Output Control Parameters

### Read Operations (ready, list, show, blocked)
- `brief`: Return BriefIssue {id, title, status, priority} (~97% smaller)
- `fields`: Custom field projection with validation - invalid fields raise ValueError
- `max_description_length`: Truncate descriptions to N chars with "..."
- `brief_deps`: Full issue but dependencies as BriefDep (~48% smaller)

### Write Operations (create, update, close, reopen)
- `brief`: Return OperationResult {id, action, message} (~97% smaller)
- Default is brief=True for minimal confirmations

## Token Savings

| Operation | Before | After (brief) | Reduction |
|-----------|--------|---------------|-----------|
| ready(limit=10) | ~20KB | ~600B | 97% |
| list(limit=20) | ~40KB | ~800B | 98% |
| show() | ~2KB | ~60B | 97% |
| show() with 5 deps | ~4.5KB | ~2.3KB | 48% |
| blocked() | ~10KB | ~240B | 98% |
| create() response | ~2KB | ~50B | 97% |

## New Models

- BriefIssue: Ultra-minimal issue (4 fields, ~60B)
- BriefDep: Compact dependency (5 fields, ~70B)
- OperationResult: Write confirmation (3 fields, ~50B)
- OperationAction: Literal["created", "updated", "closed", "reopened"]

## Best Practices

- Unified `brief` parameter naming across all operations
- `brief=True` always means "give me less data"
- Field validation with clear error messages listing valid fields
- All parameters optional with backwards-compatible defaults
- Progressive disclosure: scan cheap, detail on demand

---

## Filtering Parameters (aligns MCP with CLI)

Add missing filter parameters to `list` and `ready` tools that were
documented in MCP instructions but not implemented.

### ReadyWorkParams - New Fields
- `labels: list[str]` - AND filter: must have ALL specified labels
- `labels_any: list[str]` - OR filter: must have at least one
- `unassigned: bool` - Filter to only unassigned issues
- `sort_policy: str` - Sort by: hybrid (default), priority, oldest

### ListIssuesParams - New Fields
- `labels: list[str]` - AND filter: must have ALL specified labels
- `labels_any: list[str]` - OR filter: must have at least one
- `query: str` - Search in title (case-insensitive substring)
- `unassigned: bool` - Filter to only unassigned issues

### CLI Flag Mappings

| MCP Parameter | ready CLI Flag | list CLI Flag |
|---------------|----------------|---------------|
| labels | --label (repeated) | --label (repeated) |
| labels_any | --label-any (repeated) | --label-any (repeated) |
| query | N/A | --title |
| unassigned | --unassigned | --no-assignee |
| sort_policy | --sort | N/A |

---

## Documentation & Testing

### get_tool_info() Updates
- Added `brief`, `brief_deps`, `fields`, `max_description_length` to show tool
- Added `brief` parameter docs for create, update, close, reopen
- Added `brief`, `brief_deps` parameter docs for blocked

### Test Coverage (16 new tests)
- `test_create_brief_default` / `test_create_brief_false`
- `test_update_brief_default` / `test_update_brief_false`
- `test_close_brief_default` / `test_close_brief_false`
- `test_reopen_brief_default`
- `test_show_brief` / `test_show_fields_projection` / `test_show_fields_invalid`
- `test_show_max_description_length` / `test_show_brief_deps`
- `test_list_brief` / `test_ready_brief` / `test_blocked_brief`

---

## Backward Compatibility

All new parameters are optional with sensible defaults:
- `brief`: False for reads, True for writes
- `fields`, `max_description_length`: None (no filtering/truncation)
- `labels`, `labels_any`, `query`: None (no filtering)
- `unassigned`: False (include all)
- `sort_policy`: None (use default hybrid sort)

Existing MCP tool calls continue to work unchanged.
2025-12-20 21:33:38 -08:00
Caleb Leak
055e7a561f fix(beads-mcp): prevent subprocess stdin inheritance breaking MCP protocol
When running as an MCP server, subprocesses must not inherit stdin because
MCP uses stdin for JSON-RPC protocol communication. Inherited stdin causes
subprocesses to block indefinitely waiting for input or steal bytes from
the MCP protocol stream.

Added stdin=subprocess.DEVNULL (or asyncio.subprocess.DEVNULL for async)
to all subprocess calls:
- server.py: _resolve_workspace_root() git subprocess
- tools.py: _resolve_workspace_root() git subprocess
- bd_client.py: _run_command(), _check_version(), add_dependency(),
  quickstart(), and init() async subprocess calls

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 20:42:29 -08:00
Steve Yegge
9413fd9b84 fix: beads-mcp integration tests
- Fixed add_dependency to pass BEADS_DB/BEADS_DIR env vars to subprocess
- Fixed test_init_creates_beads_directory assertion to check for beads.db (not prefix.db)
- Fixed test_worktree_separate_dbs fixture assertions for correct db filename
- Added --no-daemon flag throughout worktree tests to avoid daemon interference
- Skipped flaky worktree tests due to daemon path caching issues

Fixes bd-4aao

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 21:40:18 -08:00
Steve Yegge
9e57cb69d8 Improve type safety and fix minor issues in beads-mcp
Type Safety Improvements:
- Change dict → dict[str, Any] throughout codebase for explicit typing
- Add PEP 561 py.typed marker file to export type information
- Add types-requests to dev dependencies
- Improve signal handler typing (FrameType | None)
- Improve decorator typing (Callable[..., Awaitable[T]])
- Add quickstart() abstract method to BdClientBase for interface completeness

Bug Fixes:
- Fix variable shadowing: beads_dir → local_beads_dir in bd_client.py
- Improve error handling in mail.py:_call_agent_mail() to prevent undefined error
- Make working_dir required (not Optional) in BdDaemonClient
- Remove unnecessary 'or' defaults for required Pydantic fields

Validation:
- mypy passes with no errors
- All unit tests passing
- Daemon quickstart returns helpful static text (RPC doesn't support this command)
2025-11-20 19:27:56 -05:00
Steve Yegge
620d96f142 Add MCP server functions for repair commands (bd-7bbc4e6a)
- Add repair_deps(fix=False) for orphaned dependencies
- Add detect_pollution(clean=False) for test issue detection
- Add validate(checks=None, fix_all=False) for health checks
- Implemented in BdCliClient, stubs in BdDaemonClient
- Registered as MCP tools in server.py

Amp-Thread-ID: https://ampcode.com/threads/T-9ce04c75-201b-4019-b9f1-0cf10663557c
Co-authored-by: Amp <amp@ampcode.com>
2025-11-07 19:40:04 -08:00
Steve Yegge
d97df21a65 Fix MCP server integration tests - add env variable propagation
- Fix BdCliClient._run_command() to pass BEADS_DIR/BEADS_DB env vars to subprocess
- Update temp_db fixture to create .beads in workspace and return .beads dir path
- Update mcp_client fixture to use beads_dir and enable BEADS_NO_DAEMON mode
- Simplify test_init_tool to work with connection pool architecture

Result: All 19 integration tests now pass (was 19 failing)
Amp-Thread-ID: https://ampcode.com/threads/T-c1da2a55-f086-4284-9c85-0dfa4c479cf9
Co-authored-by: Amp <amp@ampcode.com>
2025-11-07 19:27:22 -08:00
Steve Yegge
6ecfd04ec8 Implement BEADS_DIR environment variable (bd-e16b)
Add BEADS_DIR as a replacement for BEADS_DB to point to the .beads
directory instead of the database file directly.

Rationale:
- With --no-db mode, there's no .db file to point to
- The .beads directory is the logical unit (contains config.yaml, db
  files, jsonl files)
- More intuitive: point to the beads directory not the database file

Implementation:
- Add BEADS_DIR environment variable support to FindDatabasePath()
- Priority order: BEADS_DIR > BEADS_DB > auto-discovery
- Maintain backward compatibility with BEADS_DB (now deprecated)
- Update --no-db mode to respect BEADS_DIR
- Update MCP integration (config.py, bd_client.py)
- Update documentation to show BEADS_DIR as preferred method

Testing:
- Backward compatibility: BEADS_DB still works
- BEADS_DIR works with regular database mode
- BEADS_DIR works with --no-db mode
- Priority: BEADS_DIR takes precedence over BEADS_DB

Follow-up issues for refactoring:
- bd-efe8: Refactor path canonicalization into helper function
- bd-c362: Extract database search logic into helper function

Closes bd-e16b

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 18:36:30 -08:00
Steve Yegge
24936937f7 Add MCP tools for migration inspection (bd-627d Phase 3)
- Add inspect_migration() tool - calls bd migrate --inspect --json
- Add get_schema_info() tool - calls bd info --schema --json
- Implements abstract methods in BdClientBase
- CLI client calls commands directly
- Daemon client raises NotImplementedError (rare admin commands)

Phase 3 complete. Agents can now inspect migrations via MCP before running them.

Amp-Thread-ID: https://ampcode.com/threads/T-de7e1141-87ac-4b4a-9cea-1b7bc4d51da9
Co-authored-by: Amp <amp@ampcode.com>
2025-11-02 14:14:13 -08:00
Steve Yegge
7dcde1330e Remove obsolete --db flag from MCP server
The --db flag was removed in bd v0.20.1 in favor of automatic database
discovery via cwd. The MCP server now relies on passing the workspace
directory via cwd parameter instead of the --db flag.

This fixes compatibility with bd v0.20.1+.
2025-10-31 02:02:38 -07:00
Steve Yegge
4f1d1a2cca Fix MCP dep tool parameter names to match CLI (issue_id/depends_on_id)
- Changed from confusing from_id/to_id to clear issue_id/depends_on_id
- Matches CLI convention: bd dep add [issue-id] [depends-on-id]
- Updated all tests and implementations
- Fixes GH #113 where Claude Code was creating dependencies backwards

Closes bd-58

Amp-Thread-ID: https://ampcode.com/threads/T-f01aca11-a10f-4908-9ce6-7e1734f2068f
Co-authored-by: Amp <amp@ampcode.com>
2025-10-23 13:07:44 -07:00
Steve Yegge
4f560379f2 Add description parameter to bd update command and MCP server
Fixes #114 and #122 by adding --description/-d flag to bd update CLI
and description parameter to MCP update_issue tool.

Changes:
- CLI: Added --description flag to updateCmd
- RPC: Added Description field to UpdateArgs
- Daemon: Updated updatesFromArgs to handle description
- MCP: Added description to update_issue, UpdateIssueParams, and clients
- Storage: description already supported in allowedUpdateFields

Tested in both daemon and direct modes.
2025-10-23 11:00:19 -07:00
Steve Yegge
935470a3d8 Fix MCP close method signature bug (GH #107, bd-67)
- Fix BdDaemonClient.close() to accept issue_id and reason parameters
- Remove uv.lock from repo

Amp-Thread-ID: https://ampcode.com/threads/T-0017f48d-605c-410f-9a77-db62153c9357
Co-authored-by: Amp <amp@ampcode.com>
2025-10-22 17:53:28 -07:00
mountaintopsolutions
0f044117b4 Normalize --acceptance flag for bd update command (#102)
- Update bd update to use --acceptance instead of --acceptance-criteria
- Update MCP client to use --acceptance flag
- Simplify SKILL.md documentation now that both commands use same flag

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-22 00:15:54 -07:00
Steve Yegge
958bbc0853 feat(daemon): Add --global flag for multi-repo support
Implements bd-121: Global daemon with system-wide socket

Changes:
- Add --global flag to daemon command
- Use ~/.beads/bd.sock when --global is set
- Skip git repo validation for global daemon
- Update daemon discovery to check ~/.beads/ as fallback
- Both Go CLI and Python MCP client check global socket
- Update all tests to pass global parameter

Benefits:
- Single daemon serves all repos on system
- No per-repo daemon management needed
- Better resource usage for users with many repos
- Automatic fallback when local daemon not running

Usage:
  bd daemon --global         # Start global daemon
  bd daemon --status --global # Check global status
  bd daemon --stop --global   # Stop global daemon

Related: bd-73 (multi-repo epic)
Amp-Thread-ID: https://ampcode.com/threads/T-ea606216-b886-4af0-bba8-56d000362d01
Co-authored-by: Amp <amp@ampcode.com>
2025-10-17 22:45:33 -07:00
Michael Shuffett
74b460b298 fix(mcp): Fix three critical bugs in beads MCP plugin
This PR fixes three bugs that prevented the MCP plugin from working:

1. **Fixed parameter name mismatch in tools.py**
   - Changed `workspace_root=workspace_root` to `working_dir=workspace_root`
   - The `create_bd_client()` function expects `working_dir` parameter,
     but tools.py was passing `workspace_root`
   - This caused "got an unexpected keyword argument 'workspace_root'" error

2. **Added version check guard for daemon client**
   - Added `hasattr(_client, '_check_version')` check before calling
   - BdDaemonClient doesn't have `_check_version()` method, only BdCliClient does
   - This caused "'BdDaemonClient' object has no attribute '_check_version'" error

3. **Implemented proper daemon socket detection for fallback**
   - Added synchronous socket file existence check before creating daemon client
   - Walks up directory tree looking for `.beads/bd.sock` file
   - Only creates daemon client if socket exists, otherwise falls back to CLI
   - Previously, daemon client was created but failed on first method call
   - This enables the documented "prefer_daemon with automatic CLI fallback" behavior

**Testing:**
- Verified MCP tools work correctly with single-repo setup
- Confirmed automatic fallback to CLI when daemon isn't running
- Tested on macOS with bd v0.9.9

**Related Issues:**
- Addresses symptoms similar to #65 (Windows BEADS_WORKING_DIR issue)
2025-10-17 21:16:19 -07:00
Steve Yegge
b40de9bc41 Implement daemon RPC with per-request context routing (bd-115)
- Added per-request storage routing in daemon server
  - Server now supports Cwd field in requests for database discovery
  - Tree-walking to find .beads/*.db from any working directory
  - Storage caching for performance across requests

- Created Python daemon client (bd_daemon_client.py)
  - RPC over Unix socket communication
  - Implements full BdClientBase interface
  - Auto-discovery of daemon socket from working directory

- Refactored bd_client.py with abstract interface
  - BdClientBase abstract class for common interface
  - BdCliClient for CLI-based operations (renamed from BdClient)
  - create_bd_client() factory with daemon/CLI fallback
  - Backwards-compatible BdClient alias

Next: Update MCP server to use daemon client when available
2025-10-17 16:28:29 -07:00
Steve Yegge
ff0ce6c3a7 Improve MCP client working directory handling
- Use os.getcwd() directly instead of PWD fallback (more reliable)
- Add cwd parameter to _run_command for per-command overrides

Amp-Thread-ID: https://ampcode.com/threads/T-bf7caacc-f242-4224-b730-1f4442a7ed50
Co-authored-by: Amp <amp@ampcode.com>
2025-10-17 14:22:26 -07:00
Steve Yegge
a971762b0e Remove ~/.beads fallback behavior
- Remove ~/.beads/default.db fallback from FindDatabasePath()
- Update daemon to error if no database found instead of falling back
- Update main.go to require explicit database initialization
- Add help/version/quickstart to commands that don't need database
- Add MCP client debug logging for database routing

Amp-Thread-ID: https://ampcode.com/threads/T-2b757a14-cf10-400e-a83c-30349182dd82
Co-authored-by: Amp <amp@ampcode.com>
2025-10-17 10:56:52 -07:00
Baishampayan Ghose
32a718dacd feat(mcp): Add reopen command support for closed issues
Implements the `bd` reopen command across the entire MCP stack, enabling
agents to reopen closed issues with optional reason tracking for audit
trails. This addresses the need to handle regressions and incorrectly
closed issues without manual `bd` CLI intervention.

The reopen command is more explicit than `bd update --status open` and
emits a dedicated Reopened event in the audit log, making it easier to
track why issues were reopened during analysis.

Changes:
  - `models.py`: Add ReopenIssueParams with issue_ids list and optional reason
  - `bd_client.py`: Implement reopen() method with JSON response parsing
  - `tools.py`: Add beads_reopen_issue() wrapper with Annotated types for MCP
  - `server.py`: Register 'reopen' MCP tool with description and parameters

Testing (10 new):
  - `test_bd_client.py`: 4 unit tests (mocked subprocess)
  - `test_bd_client_integration.py`: 3 integration tests (real `bd` CLI)
  - `test_mcp_server_integration.py`: 3 MCP integration tests (FastMCP Client)
  - `test_tools.py`: 3 tools wrapper tests (mocked BdClient)

Also updated `README.md`.
2025-10-16 12:01:04 -07:00
Baishampayan Ghose
4353592fe6 test(mcp): Fix two failing integration tests and linting errors
1. Fix `test_default_beads_path_auto_detection`
    - Changed beads_path to use `Field(default_factory=_default_beads_path)` so the default is evaluated at instance
    creation time, not class definition time
    - Updated test to mock both `shutil.which` and `os.access`
2. Fix `test_init_creates_beads_directory`
    - Fixed test to pass `working_dir=temp_dir` to `BdClient` instead of using `os.chdir()`
    - The `_get_working_dir()` method checks `PWD` env var first, which isn't updated by `os.chdir()`
3. Fix minor linting errors reported by `ruff` tool
4. Update `beads` version to `0.9.6` in `uv.lock` file

MCP Server test coverage is now excellent, at 92% overall maintaining our high-standards of production level quality.

```
Name                         Stmts   Miss  Cover
------------------------------------------------
src/beads_mcp/__init__.py        1      0   100%
src/beads_mcp/__main__.py        3      3     0%
src/beads_mcp/bd_client.py     214     14    93%
src/beads_mcp/config.py         51      2    96%
src/beads_mcp/models.py         92      1    99%
src/beads_mcp/server.py         58     16    72%
src/beads_mcp/tools.py          59      0   100%
------------------------------------------------
TOTAL                          478     36    92%
```
2025-10-15 16:59:16 +05:30
Steve Yegge
01b606fe7b fix(mcp): Run bd commands in user's working directory
The MCP server was running bd commands from the plugin installation directory,
causing the database to be created in the wrong place.

Added BEADS_WORKING_DIR config option and modified BdClient to use working
directory for subprocess calls. Falls back to PWD environment variable.

This ensures bd commands run from the user's actual project directory.

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-14 18:57:32 -07:00
Steve Yegge
061e8c4a27 feat(mcp): improve error messages for missing bd CLI
Add helpful installation instructions when bd CLI is not found,
making it clear that the CLI must be installed separately.

Changes:
- Add BdNotFoundError.installation_message() with clear install steps
- Update all BdNotFoundError raises to use new formatted message
- Improve config error message with installation instructions first
- Update tests to match new error message format

Error message now shows:
- Clear explanation that bd CLI is required
- Installation command with curl one-liner
- Link to GitHub installation docs
- Reminder to restart Claude Code after installation

Test results: 90/91 tests passing (1 unrelated path assertion)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-14 17:33:54 -07:00
Steve Yegge
c049bf4351 fix(mcp): run bd commands in user's working directory instead of MCP server directory
The MCP server was running all bd commands in its own installation directory
(~/.claude/plugins/marketplaces/beads-marketplace/integrations/beads-mcp/)
instead of the user's project directory. This caused databases to be created
in the wrong location.

For example, when working in ~/ai/flutter/wyvern and running `bd init --prefix wy-`,
the database was created at:
  ~/.claude/plugins/marketplaces/beads-marketplace/integrations/beads-mcp/.beads/wy-.db

Instead of the expected location:
  ~/ai/flutter/wyvern/.beads/wy-.db

Solution:
- Add `cwd=os.getcwd()` to all asyncio.create_subprocess_exec() calls
- This makes bd commands execute in the current working directory from PWD env var
- Claude Code updates PWD for the MCP server process environment

Impact:
- bd init now creates .beads/ in the correct project directory
- All bd commands (create, list, update, etc.) operate on the correct database
- Multi-project workflows work correctly without manual DB path configuration

Test results: 90/91 tests passing (1 unrelated path assertion failure)
2025-10-14 17:11:45 -07:00
Steve Yegge
ba8fdf1a8c fix: MCP init tool creates .beads in current directory
Critical bug: MCP init tool reported success but didn't create .beads
directory. It was using --db flag which tells bd to use an existing
database elsewhere instead of creating a new one.

Root cause:
- bd_client.init() was calling _global_flags() which adds --db flag
- bd init --db <path> uses existing db instead of creating new one
- Result: init appeared to succeed but created nothing

Fix:
- Remove _global_flags() from init command
- Only pass --actor flag (safe for init)
- Do NOT pass --db flag to init (defeats the purpose)
- Add explicit comment explaining why

Testing:
- Added test_init_creates_beads_directory() integration test
- Verifies .beads directory is created in current working directory
- Verifies database file has correct prefix
- All 91 tests pass

This was causing silent failures where agents thought they initialized
bd but the .beads directory was never created.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-14 16:47:29 -07:00
Steve Yegge
a4d816d1f4 fix: Remove unsupported engines field and add runtime version checking
Fixes Claude Code marketplace plugin installation failure (bd-183).

Problem: The plugin.json manifest included an engines field (borrowed from npm)
to specify minimum bd CLI version requirements. However, Claude Code's plugin
manifest schema doesn't recognize this field, causing validation errors when
installing via /plugin marketplace add.

Solution:
1. Remove the engines field from plugin.json
2. Add runtime version checking in the MCP server startup
3. Update documentation to reflect automatic version checking

Changes:
- .claude-plugin/plugin.json: Remove unsupported engines field
- integrations/beads-mcp/src/beads_mcp/bd_client.py:
  - Add BdVersionError exception class
  - Add _check_version() method to validate bd CLI >= 0.9.0
  - Use bd version command (not bd --version)
- integrations/beads-mcp/src/beads_mcp/tools.py:
  - Make _get_client() async to support version checking
  - Update all tool functions to await _get_client()
  - Add version check on first MCP server use
- .claude-plugin/commands/bd-version.md: Update to mention automatic checking
- PLUGIN.md: Document automatic version validation at startup

Benefits:
- Plugin installs successfully via Claude Code marketplace
- Clear error messages if bd CLI version is too old
- Version check happens once per MCP server lifetime (not per command)
- Users get actionable update instructions in error messages

Closes bd-183
2025-10-14 15:54:50 -07:00
Baishampayan Ghose
1b1380e6c3 feat: Add Beads MCP Server [bd-5]
Implements MCP server for beads issue tracker, exposing all bd CLI functionality to MCP clients like Claude Desktop.

Features:
- Complete bd command coverage (init, create, list, ready, show, update, close, dep, blocked, stats)
- Type-safe Pydantic models with validation
- Comprehensive test suite (unit + integration tests)
- Production-ready Python package structure
- Environment variable configuration support
- Quickstart resource (beads://quickstart)

Ready for PyPI publication after real-world testing.

Co-authored-by: ghoseb <baishampayan.ghose@gmail.com>
2025-10-14 11:13:52 -07:00