From 095ebc70e6825b40d43620810be99500428b8403 Mon Sep 17 00:00:00 2001 From: Steve Yegge Date: Sun, 19 Oct 2025 23:23:33 -0700 Subject: [PATCH] Fix MCP server None/null crashes in list/ready/stats (bd-172, fixes #79) Add null safety checks in bd_daemon_client.py: - list_issues(): Return empty array if issues_data is None - ready(): Return empty array if issues_data is None - stats(): Use empty dict if stats_data is None This prevents TypeError crashes when daemon returns None/empty responses. Amp-Thread-ID: https://ampcode.com/threads/T-072304c3-3a03-4091-92a9-9e16b4538227 Co-authored-by: Amp --- .beads/issues.jsonl | 4 ++-- integrations/beads-mcp/src/beads_mcp/bd_daemon_client.py | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl index 3748ce2a..19245a8e 100644 --- a/.beads/issues.jsonl +++ b/.beads/issues.jsonl @@ -61,7 +61,7 @@ {"id":"bd-153","title":"Add daemon health checks and monitoring","description":"Add health check endpoint that validates daemon state, storage connections, and resource usage.","status":"closed","priority":0,"issue_type":"task","created_at":"2025-10-19T20:13:59.764154-07:00","updated_at":"2025-10-19T22:47:07.91262-07:00","closed_at":"2025-10-19T20:14:38.291678-07:00"} {"id":"bd-154","title":"Implement daemon crash recovery and restart","description":"Detect stale daemon processes, clean up orphaned resources, and auto-restart daemon after crashes.","status":"closed","priority":0,"issue_type":"task","created_at":"2025-10-19T20:13:59.766856-07:00","updated_at":"2025-10-19T22:47:07.912806-07:00","closed_at":"2025-10-19T20:15:02.211576-07:00"} {"id":"bd-155","title":"Implement resource limits and connection pooling","description":"Add configurable limits for connections, file descriptors, and memory usage.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-19T20:13:59.768745-07:00","updated_at":"2025-10-19T22:47:07.912981-07:00","closed_at":"2025-10-19T22:41:38.335156-07:00"} -{"id":"bd-156","title":"Add daemon telemetry and metrics","description":"Track and report daemon metrics: request count, latency, cache hits/misses, error rates.","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-19T20:13:59.77094-07:00","updated_at":"2025-10-19T22:47:07.913171-07:00"} +{"id":"bd-156","title":"Add daemon telemetry and metrics","description":"Track and report daemon metrics: request count, latency, cache hits/misses, error rates.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-19T20:13:59.77094-07:00","updated_at":"2025-10-19T23:15:11.871638-07:00","closed_at":"2025-10-19T23:15:11.871638-07:00"} {"id":"bd-157","title":"Improve daemon visibility and status reporting","description":"Add clear daemon status output, uptime reporting, and user-friendly error messages.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-19T20:13:59.772435-07:00","updated_at":"2025-10-19T22:47:07.913336-07:00","closed_at":"2025-10-19T21:44:50.340047-07:00"} {"id":"bd-158","title":"Add daemon/client version compatibility checks","description":"Verify daemon and client versions are compatible before allowing connections.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-19T20:13:59.774304-07:00","updated_at":"2025-10-19T22:47:07.913534-07:00","closed_at":"2025-10-19T22:29:49.795817-07:00"} {"id":"bd-159","title":"Enhance label functionality and documentation","description":"Improve beads label system to support cross-cutting concerns and contextual metadata beyond structured fields (status, priority, type).\n\nCurrent state: Basic label storage exists (labels table, Add/GetLabels methods)\nTarget state: Full label lifecycle management with CLI, filtering, automation, and documentation\n\nCore principles:\n- Labels for cross-cutting concerns (technical metadata, scope, effort, quality gates)\n- Structured fields for workflow state (status, priority, type remain primary)\n- Multi-dimensional tagging without schema changes\n\nSee removed LABELS.md for detailed use cases and design rationale.","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-10-19T20:45:24.163728-07:00","updated_at":"2025-10-19T23:07:06.666164-07:00","closed_at":"2025-10-19T23:07:06.666164-07:00"} @@ -69,7 +69,7 @@ {"id":"bd-160","title":"Implement label CLI commands (add, remove, list)","description":"Add CLI commands for label management:\n- bd label add \u003cissue\u003e \u003clabel...\u003e\n- bd label remove \u003cissue\u003e \u003clabel...\u003e\n- bd label list \u003cissue\u003e\n- bd labels (list all labels in use)\n\nBackend already has AddLabel/GetLabels/RemoveLabel methods in storage layer.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-19T20:45:36.861324-07:00","updated_at":"2025-10-19T22:47:07.913911-07:00","closed_at":"2025-10-19T20:53:02.799889-07:00","labels":["feature","working"]} {"id":"bd-161","title":"Add label filtering to bd list command","description":"Support label-based filtering in bd list:\n- --label \u003clabel1,label2\u003e (AND semantics)\n- --label-any \u003clabel1,label2\u003e (OR semantics)\n- --group-by label (group results by label)\n\nEnables queries like: bd list --priority 1 --label backend,needs-review","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-19T20:45:36.863417-07:00","updated_at":"2025-10-19T22:54:43.232225-07:00","closed_at":"2025-10-19T22:54:43.232225-07:00"} {"id":"bd-162","title":"Add label display to bd show and bd list output","description":"Include labels in issue display:\n- bd show \u003cissue\u003e should show labels\n- bd list should show labels (compact format)\n- JSON output should include labels array\n\nCurrently labels exist in DB but aren't shown in CLI output.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-19T20:45:36.865936-07:00","updated_at":"2025-10-19T22:47:07.914249-07:00","closed_at":"2025-10-19T22:44:31.418121-07:00"} -{"id":"bd-163","title":"Document label best practices and use cases","description":"Create documentation covering:\n- When to use labels vs structured fields\n- Common label sets (coding agents, open source, product dev, SRE)\n- Naming conventions (kebab-case, specificity, present tense)\n- Anti-patterns (too many labels, overlapping, personal labels)\n- Label lifecycle management\n\nContent from LABELS.md analysis document.","status":"open","priority":3,"issue_type":"task","created_at":"2025-10-19T20:45:36.867864-07:00","updated_at":"2025-10-19T22:47:07.914433-07:00"} +{"id":"bd-163","title":"Document label best practices and use cases","description":"Create documentation covering:\n- When to use labels vs structured fields\n- Common label sets (coding agents, open source, product dev, SRE)\n- Naming conventions (kebab-case, specificity, present tense)\n- Anti-patterns (too many labels, overlapping, personal labels)\n- Label lifecycle management\n\nContent from LABELS.md analysis document.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-10-19T20:45:36.867864-07:00","updated_at":"2025-10-19T23:11:46.125417-07:00","closed_at":"2025-10-19T23:11:46.125417-07:00"} {"id":"bd-164","title":"Implement label CLI commands (add, remove, list)","description":"Add CLI commands for label management:\n- bd label add \u003cissue\u003e \u003clabel...\u003e\n- bd label remove \u003cissue\u003e \u003clabel...\u003e\n- bd label list \u003cissue\u003e\n- bd labels (list all labels in use)\n\nBackend already has AddLabel/GetLabels/RemoveLabel methods in storage layer.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-19T20:49:44.344807-07:00","updated_at":"2025-10-19T22:47:07.914585-07:00","closed_at":"2025-10-19T21:14:12.231668-07:00"} {"id":"bd-165","title":"MCP server tools should accept workspace_root parameter","description":"","design":"After set_context is called, Amp appears to inject workspace_root as a parameter to subsequent tool calls. The beads-mcp server should accept this parameter (likely ignore it or map it to working_dir) to avoid errors.","notes":"Oracle review found two additional issues: 1) Missing workspace_root on where_am_i tool, 2) set_context should always set env vars even when DB not found (so init works right after). Both fixed.","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-10-19T21:17:06.93365-07:00","updated_at":"2025-10-19T22:47:07.914739-07:00","closed_at":"2025-10-19T21:29:38.326609-07:00"} {"id":"bd-166","title":"Update commands/ directory with new commands (comments, labels, etc)","description":"The commands/ directory contains documentation for bd commands, but several new commands have been added that aren't documented there yet: 'comments', 'labels', and possibly others. Need to audit what's missing and add documentation.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-19T21:54:04.65288-07:00","updated_at":"2025-10-19T22:47:07.914891-07:00","closed_at":"2025-10-19T21:57:28.943347-07:00"} diff --git a/integrations/beads-mcp/src/beads_mcp/bd_daemon_client.py b/integrations/beads-mcp/src/beads_mcp/bd_daemon_client.py index 39b35a3d..03f3a004 100644 --- a/integrations/beads-mcp/src/beads_mcp/bd_daemon_client.py +++ b/integrations/beads-mcp/src/beads_mcp/bd_daemon_client.py @@ -340,6 +340,8 @@ class BdDaemonClient(BdClientBase): data = await self._send_request("list", args) issues_data = json.loads(data) if isinstance(data, str) else data + if issues_data is None: + return [] return [Issue(**issue) for issue in issues_data] async def show(self, params: ShowIssueParams) -> Issue: @@ -375,6 +377,8 @@ class BdDaemonClient(BdClientBase): data = await self._send_request("ready", args) issues_data = json.loads(data) if isinstance(data, str) else data + if issues_data is None: + return [] return [Issue(**issue) for issue in issues_data] async def stats(self) -> Stats: @@ -385,6 +389,8 @@ class BdDaemonClient(BdClientBase): """ data = await self._send_request("stats", {}) stats_data = json.loads(data) if isinstance(data, str) else data + if stats_data is None: + stats_data = {} return Stats(**stats_data) async def blocked(self) -> List[BlockedIssue]: