bd sync: 2025-12-27 15:56:42
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "beads-mcp"
|
||||
version = "0.38.0"
|
||||
version = "0.36.0"
|
||||
description = "MCP server for beads issue tracker."
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10"
|
||||
|
||||
@@ -4,4 +4,4 @@ This package provides an MCP (Model Context Protocol) server that exposes
|
||||
beads (bd) issue tracker functionality to MCP Clients.
|
||||
"""
|
||||
|
||||
__version__ = "0.38.0"
|
||||
__version__ = "0.36.0"
|
||||
|
||||
@@ -12,7 +12,6 @@ from .config import load_config
|
||||
from .models import (
|
||||
AddDependencyParams,
|
||||
BlockedIssue,
|
||||
BlockedParams,
|
||||
CloseIssueParams,
|
||||
CreateIssueParams,
|
||||
InitParams,
|
||||
@@ -127,7 +126,7 @@ class BdClientBase(ABC):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def blocked(self, params: Optional[BlockedParams] = None) -> List[BlockedIssue]:
|
||||
async def blocked(self) -> List[BlockedIssue]:
|
||||
"""Get blocked issues."""
|
||||
pass
|
||||
|
||||
@@ -396,8 +395,6 @@ class BdCliClient(BdClientBase):
|
||||
args.append("--unassigned")
|
||||
if params.sort_policy:
|
||||
args.extend(["--sort", params.sort_policy])
|
||||
if params.parent_id:
|
||||
args.extend(["--parent", params.parent_id])
|
||||
|
||||
data = await self._run_command(*args)
|
||||
if not isinstance(data, list):
|
||||
@@ -667,21 +664,13 @@ class BdCliClient(BdClientBase):
|
||||
|
||||
return Stats.model_validate(data)
|
||||
|
||||
async def blocked(self, params: BlockedParams | None = None) -> list[BlockedIssue]:
|
||||
async def blocked(self) -> list[BlockedIssue]:
|
||||
"""Get blocked issues.
|
||||
|
||||
Args:
|
||||
params: Query parameters
|
||||
|
||||
Returns:
|
||||
List of blocked issues with blocking information
|
||||
"""
|
||||
params = params or BlockedParams()
|
||||
args = ["blocked"]
|
||||
if params.parent_id:
|
||||
args.extend(["--parent", params.parent_id])
|
||||
|
||||
data = await self._run_command(*args)
|
||||
data = await self._run_command("blocked")
|
||||
if not isinstance(data, list):
|
||||
return []
|
||||
|
||||
@@ -842,6 +831,11 @@ def create_bd_client(
|
||||
If prefer_daemon is True and daemon is not running, falls back to CLI client.
|
||||
To check if daemon is running without falling back, use BdDaemonClient directly.
|
||||
"""
|
||||
# Windows doesn't support Unix domain sockets (GH#387)
|
||||
# Skip daemon mode entirely on Windows
|
||||
if prefer_daemon and sys.platform == 'win32':
|
||||
prefer_daemon = False
|
||||
|
||||
if prefer_daemon:
|
||||
try:
|
||||
from .bd_daemon_client import BdDaemonClient
|
||||
|
||||
@@ -11,7 +11,6 @@ from .bd_client import BdClientBase, BdError
|
||||
from .models import (
|
||||
AddDependencyParams,
|
||||
BlockedIssue,
|
||||
BlockedParams,
|
||||
CloseIssueParams,
|
||||
CreateIssueParams,
|
||||
InitParams,
|
||||
@@ -433,9 +432,6 @@ class BdDaemonClient(BdClientBase):
|
||||
args["sort_policy"] = params.sort_policy
|
||||
if params.limit:
|
||||
args["limit"] = params.limit
|
||||
# Parent filtering (descendants of a bead/epic)
|
||||
if params.parent_id:
|
||||
args["parent_id"] = params.parent_id
|
||||
|
||||
data = await self._send_request("ready", args)
|
||||
issues_data = json.loads(data) if isinstance(data, str) else data
|
||||
@@ -455,25 +451,18 @@ class BdDaemonClient(BdClientBase):
|
||||
stats_data = {}
|
||||
return Stats(**stats_data)
|
||||
|
||||
async def blocked(self, params: Optional[BlockedParams] = None) -> List[BlockedIssue]:
|
||||
async def blocked(self) -> List[BlockedIssue]:
|
||||
"""Get blocked issues.
|
||||
|
||||
Args:
|
||||
params: Query parameters (optional)
|
||||
|
||||
Returns:
|
||||
List of blocked issues with their blockers
|
||||
"""
|
||||
params = params or BlockedParams()
|
||||
args: Dict[str, Any] = {}
|
||||
if params.parent_id:
|
||||
args["parent_id"] = params.parent_id
|
||||
|
||||
data = await self._send_request("blocked", args)
|
||||
issues_data = json.loads(data) if isinstance(data, str) else data
|
||||
if issues_data is None:
|
||||
return []
|
||||
return [BlockedIssue(**issue) for issue in issues_data]
|
||||
Note:
|
||||
This operation may not be implemented in daemon RPC yet
|
||||
"""
|
||||
# Note: blocked operation may not be in RPC protocol yet
|
||||
# This is a placeholder for when it's added
|
||||
raise NotImplementedError("Blocked operation not yet supported via daemon")
|
||||
|
||||
async def inspect_migration(self) -> dict[str, Any]:
|
||||
"""Get migration plan and database state for agent analysis.
|
||||
|
||||
@@ -209,13 +209,6 @@ class ReadyWorkParams(BaseModel):
|
||||
labels_any: list[str] | None = None # OR: must have at least one
|
||||
unassigned: bool = False # Filter to only unassigned issues
|
||||
sort_policy: str | None = None # hybrid, priority, oldest
|
||||
parent_id: str | None = None # Filter to descendants of this bead/epic
|
||||
|
||||
|
||||
class BlockedParams(BaseModel):
|
||||
"""Parameters for querying blocked issues."""
|
||||
|
||||
parent_id: str | None = None # Filter to descendants of this bead/epic
|
||||
|
||||
|
||||
class ListIssuesParams(BaseModel):
|
||||
|
||||
@@ -18,7 +18,6 @@ if TYPE_CHECKING:
|
||||
from .models import (
|
||||
AddDependencyParams,
|
||||
BlockedIssue,
|
||||
BlockedParams,
|
||||
CloseIssueParams,
|
||||
CreateIssueParams,
|
||||
DependencyType,
|
||||
@@ -310,14 +309,11 @@ async def beads_ready_work(
|
||||
labels_any: Annotated[list[str] | None, "Filter by labels (OR: must have at least one)"] = None,
|
||||
unassigned: Annotated[bool, "Filter to only unassigned issues"] = False,
|
||||
sort_policy: Annotated[str | None, "Sort policy: hybrid (default), priority, oldest"] = None,
|
||||
parent: Annotated[str | None, "Filter to descendants of this bead/epic"] = None,
|
||||
) -> list[Issue]:
|
||||
"""Find issues with no blocking dependencies that are ready to work on.
|
||||
|
||||
Ready work = status is 'open' AND no blocking dependencies.
|
||||
Perfect for agents to claim next work!
|
||||
|
||||
Use 'parent' to filter to all descendants of an epic/bead.
|
||||
"""
|
||||
client = await _get_client()
|
||||
params = ReadyWorkParams(
|
||||
@@ -328,7 +324,6 @@ async def beads_ready_work(
|
||||
labels_any=labels_any,
|
||||
unassigned=unassigned,
|
||||
sort_policy=sort_policy,
|
||||
parent_id=parent,
|
||||
)
|
||||
return await client.ready(params)
|
||||
|
||||
@@ -540,18 +535,13 @@ async def beads_stats() -> Stats:
|
||||
return await client.stats()
|
||||
|
||||
|
||||
async def beads_blocked(
|
||||
parent: Annotated[str | None, "Filter to descendants of this bead/epic"] = None,
|
||||
) -> list[BlockedIssue]:
|
||||
async def beads_blocked() -> list[BlockedIssue]:
|
||||
"""Get blocked issues.
|
||||
|
||||
Returns issues that have blocking dependencies, showing what blocks them.
|
||||
|
||||
Use 'parent' to filter to all descendants of an epic/bead.
|
||||
"""
|
||||
client = await _get_client()
|
||||
params = BlockedParams(parent_id=parent)
|
||||
return await client.blocked(params)
|
||||
return await client.blocked()
|
||||
|
||||
|
||||
async def beads_inspect_migration() -> dict[str, Any]:
|
||||
|
||||
Reference in New Issue
Block a user