coherence-mcp-server 0.4.4 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Give your AI agent native access to every idea, spec, contributor, and value chain in the Coherence Network.**
4
4
 
5
- An [MCP](https://modelcontextprotocol.io/) (Model Context Protocol) server that exposes the full Coherence Network API as 56 typed tools — so Claude, Cursor, Windsurf, or any MCP-compatible agent can browse ideas, look up specs, trace value lineage, link identities, record contributions, execute tasks, discover resonant peers, and apply project blueprints without writing a single API call.
5
+ An [MCP](https://modelcontextprotocol.io/) (Model Context Protocol) server that exposes the full Coherence Network API as 57 typed tools — so Claude, Cursor, Windsurf, or any MCP-compatible agent can browse ideas, look up specs, trace value lineage, link identities, record contributions, execute tasks, discover resonant peers, apply project blueprints, and read repository content via direct links without writing a single API call.
6
6
 
7
7
  ```bash
8
8
  npx coherence-mcp-server
@@ -27,6 +27,7 @@ This MCP server changes that. It gives any agent a typed interface to:
27
27
  - **Signal** — ingest news, track trending keywords, and measure concept resonance
28
28
  - **Peers** — discover resonant contributors by shared interests or proximity
29
29
  - **Blueprint** — apply standardized project roadmaps (templates) to instantly seed work
30
+ - **Direct Access** — read specs and documentation via direct repository links
30
31
  - **Ontology** — explore the Living Codex (184 universal concepts, 53 axes)
31
32
  - **Govern** — propose changes, vote on requests, and monitor network health
32
33
 
@@ -75,7 +76,7 @@ Point your MCP client at `npx coherence-mcp-server` via stdio transport.
75
76
 
76
77
  ---
77
78
 
78
- ## Tools (56)
79
+ ## Tools (57)
79
80
 
80
81
  ### Ideas — the portfolio engine
81
82
 
@@ -95,7 +96,7 @@ Point your MCP client at `npx coherence-mcp-server` via stdio transport.
95
96
  | Tool | What it does |
96
97
  |------|-------------|
97
98
  | `coherence_list_specs` | Specs with ROI metrics and value gaps. Searchable. |
98
- | `coherence_get_spec" | Full spec: summary, implementation plan, pseudocode, estimated ROI. |
99
+ | `coherence_get_spec` | Full spec: summary, implementation plan, pseudocode, estimated ROI. |
99
100
 
100
101
  ### Value lineage — end-to-end traceability
101
102
 
@@ -154,6 +155,12 @@ Point your MCP client at `npx coherence-mcp-server` via stdio transport.
154
155
  | `coherence_list_blueprints` | List available project roadmap templates. |
155
156
  | `coherence_apply_blueprint` | Seed a full roadmap of ideas and edges from a template. |
156
157
 
158
+ ### Repository Content — direct access
159
+
160
+ | Tool | What it does |
161
+ |------|-------------|
162
+ | `coherence_read_file` | Read raw file content (specs, docs) via direct link. |
163
+
157
164
  ### Assets — tracked artifacts
158
165
 
159
166
  | Tool | What it does |
@@ -249,7 +256,7 @@ Every part of the network links to every other. Jump in wherever makes sense.
249
256
  | **Web** | Browse ideas, specs, and contributors visually | [coherencycoin.com](https://coherencycoin.com) |
250
257
  | **API** | 100+ endpoints, full OpenAPI docs, the engine behind everything | [api.coherencycoin.com/docs](https://api.coherencycoin.com/docs) |
251
258
  | **CLI** | Terminal-first access — `npm i -g coherence-cli` then `cc help` | [npm: coherence-cli](https://www.npmjs.com/package/coherence-cli) |
252
- | **MCP Server** | This package — 56 typed tools for AI agents | [npm: coherence-mcp-server](https://www.npmjs.com/package/coherence-mcp-server) |
259
+ | **MCP Server** | This package — 57 typed tools for AI agents | [npm: coherence-mcp-server](https://www.npmjs.com/package/coherence-mcp-server) |
253
260
  | **OpenClaw Skill** | Auto-triggers in any OpenClaw instance for ideas, specs, coherence | [ClawHub: coherence-network](https://clawhub.com/skills/coherence-network) |
254
261
  | **GitHub** | Source code, specs, issues, and contribution tracking | [github.com/seeker71/Coherence-Network](https://github.com/seeker71/Coherence-Network) |
255
262
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Give your AI agent native access to every idea, spec, contributor, and value chain in the Coherence Network.**
4
4
 
5
- An [MCP](https://modelcontextprotocol.io/) (Model Context Protocol) server that exposes the full Coherence Network API as 56 typed tools — so Claude, Cursor, Windsurf, or any MCP-compatible agent can browse ideas, look up specs, trace value lineage, link identities, record contributions, execute tasks, discover resonant peers, and apply project blueprints without writing a single API call.
5
+ An [MCP](https://modelcontextprotocol.io/) (Model Context Protocol) server that exposes the full Coherence Network API as 57 typed tools — so Claude, Cursor, Windsurf, or any MCP-compatible agent can browse ideas, look up specs, trace value lineage, link identities, record contributions, execute tasks, discover resonant peers, apply project blueprints, and read repository content via direct links without writing a single API call.
6
6
 
7
7
  ```bash
8
8
  npx coherence-mcp-server
@@ -27,6 +27,7 @@ This MCP server changes that. It gives any agent a typed interface to:
27
27
  - **Signal** — ingest news, track trending keywords, and measure concept resonance
28
28
  - **Peers** — discover resonant contributors by shared interests or proximity
29
29
  - **Blueprint** — apply standardized project roadmaps (templates) to instantly seed work
30
+ - **Direct Access** — read specs and documentation via direct repository links
30
31
  - **Ontology** — explore the Living Codex (184 universal concepts, 53 axes)
31
32
  - **Govern** — propose changes, vote on requests, and monitor network health
32
33
 
@@ -75,7 +76,7 @@ Point your MCP client at `npx coherence-mcp-server` via stdio transport.
75
76
 
76
77
  ---
77
78
 
78
- ## Tools (56)
79
+ ## Tools (57)
79
80
 
80
81
  ### Ideas — the portfolio engine
81
82
 
@@ -95,7 +96,7 @@ Point your MCP client at `npx coherence-mcp-server` via stdio transport.
95
96
  | Tool | What it does |
96
97
  |------|-------------|
97
98
  | `coherence_list_specs` | Specs with ROI metrics and value gaps. Searchable. |
98
- | `coherence_get_spec" | Full spec: summary, implementation plan, pseudocode, estimated ROI. |
99
+ | `coherence_get_spec` | Full spec: summary, implementation plan, pseudocode, estimated ROI. |
99
100
 
100
101
  ### Value lineage — end-to-end traceability
101
102
 
@@ -154,6 +155,12 @@ Point your MCP client at `npx coherence-mcp-server` via stdio transport.
154
155
  | `coherence_list_blueprints` | List available project roadmap templates. |
155
156
  | `coherence_apply_blueprint` | Seed a full roadmap of ideas and edges from a template. |
156
157
 
158
+ ### Repository Content — direct access
159
+
160
+ | Tool | What it does |
161
+ |------|-------------|
162
+ | `coherence_read_file` | Read raw file content (specs, docs) via direct link. |
163
+
157
164
  ### Assets — tracked artifacts
158
165
 
159
166
  | Tool | What it does |
@@ -249,7 +256,7 @@ Every part of the network links to every other. Jump in wherever makes sense.
249
256
  | **Web** | Browse ideas, specs, and contributors visually | [coherencycoin.com](https://coherencycoin.com) |
250
257
  | **API** | 100+ endpoints, full OpenAPI docs, the engine behind everything | [api.coherencycoin.com/docs](https://api.coherencycoin.com/docs) |
251
258
  | **CLI** | Terminal-first access — `npm i -g coherence-cli` then `cc help` | [npm: coherence-cli](https://www.npmjs.com/package/coherence-cli) |
252
- | **MCP Server** | This package — 56 typed tools for AI agents | [npm: coherence-mcp-server](https://www.npmjs.com/package/coherence-mcp-server) |
259
+ | **MCP Server** | This package — 57 typed tools for AI agents | [npm: coherence-mcp-server](https://www.npmjs.com/package/coherence-mcp-server) |
253
260
  | **OpenClaw Skill** | Auto-triggers in any OpenClaw instance for ideas, specs, coherence | [ClawHub: coherence-network](https://clawhub.com/skills/coherence-network) |
254
261
  | **GitHub** | Source code, specs, issues, and contribution tracking | [github.com/seeker71/Coherence-Network](https://github.com/seeker71/Coherence-Network) |
255
262
 
@@ -1,6 +1,6 @@
1
1
  """Coherence Network MCP server — Python implementation.
2
2
 
3
- Exposes the Coherence Network API as 22 typed MCP tools.
3
+ Exposes the Coherence Network API as 60 typed MCP tools.
4
4
  """
5
5
 
6
6
  from __future__ import annotations
@@ -90,6 +90,9 @@ TOOLS: list[Tool] = [
90
90
  "properties": {
91
91
  "limit": {"type": "number", "description": "Max ideas to return (default 20)", "default": 20},
92
92
  "search": {"type": "string", "description": "Search keyword to filter ideas"},
93
+ "workspace_id": {"type": "string", "description": "Optional workspace filter. Defaults to all workspaces."},
94
+ "pillar": {"type": "string", "description": "Optional pillar filter."},
95
+ "curated_only": {"type": "boolean", "description": "If true, only return curated super-ideas."},
93
96
  },
94
97
  },
95
98
  ),
@@ -142,6 +145,7 @@ TOOLS: list[Tool] = [
142
145
  "properties": {
143
146
  "limit": {"type": "number", "default": 20},
144
147
  "search": {"type": "string", "description": "Search keyword"},
148
+ "workspace_id": {"type": "string", "description": "Optional workspace filter. Defaults to all workspaces."},
145
149
  },
146
150
  },
147
151
  ),
@@ -252,12 +256,6 @@ TOOLS: list[Tool] = [
252
256
  "properties": {"window_days": {"type": "number", "default": 30}},
253
257
  },
254
258
  ),
255
- # Governance
256
- Tool(
257
- name="coherence_list_change_requests",
258
- description="List governance change requests.",
259
- inputSchema={"type": "object", "properties": {}},
260
- ),
261
259
  # Federation
262
260
  Tool(
263
261
  name="coherence_list_federation_nodes",
@@ -351,7 +349,7 @@ TOOLS: list[Tool] = [
351
349
  # Ideas (Lifecycle)
352
350
  Tool(
353
351
  name="coherence_create_idea",
354
- description="Create a new idea in the portfolio.",
352
+ description="Create a new idea in the portfolio. Scoped to a workspace (default: coherence-network).",
355
353
  inputSchema={
356
354
  "type": "object",
357
355
  "required": ["id", "name", "description"],
@@ -361,8 +359,54 @@ TOOLS: list[Tool] = [
361
359
  "description": {"type": "string", "description": "Detailed vision and value proposition"},
362
360
  "potential_value": {"type": "number", "description": "Estimated CC value (0-1000)", "default": 100},
363
361
  "estimated_cost": {"type": "number", "description": "Estimated CC cost (0-1000)", "default": 50},
364
- "parent_idea_id": {"type": "string", "description": "Optional parent idea for hierarchy"},
362
+ "parent_idea_id": {"type": "string", "description": "Optional parent idea for hierarchy. Must belong to the same workspace."},
365
363
  "tags": {"type": "array", "items": {"type": "string"}, "description": "List of tags"},
364
+ "workspace_id": {"type": "string", "description": "Owning workspace slug. Defaults to 'coherence-network'."},
365
+ "pillar": {"type": "string", "description": "Top-level pillar (must be one of the workspace's declared pillars)."},
366
+ },
367
+ },
368
+ ),
369
+ # Workspaces (Tenant primitive)
370
+ Tool(
371
+ name="coherence_list_workspaces",
372
+ description="List all workspaces (tenants). Each workspace owns its own ideas, specs, pillars, and agent personas.",
373
+ inputSchema={"type": "object", "properties": {}},
374
+ ),
375
+ Tool(
376
+ name="coherence_get_workspace",
377
+ description="Get a workspace's full manifest (name, description, pillars, visibility).",
378
+ inputSchema={
379
+ "type": "object",
380
+ "required": ["workspace_id"],
381
+ "properties": {
382
+ "workspace_id": {"type": "string", "description": "Workspace slug (e.g. 'coherence-network')"},
383
+ },
384
+ },
385
+ ),
386
+ Tool(
387
+ name="coherence_create_workspace",
388
+ description="Create a new workspace (tenant) with its own pillar taxonomy. Use this to onboard a contributor team with isolated ideas/specs/agents.",
389
+ inputSchema={
390
+ "type": "object",
391
+ "required": ["id", "name"],
392
+ "properties": {
393
+ "id": {"type": "string", "description": "Slug: lowercase + hyphens (e.g. 'my-startup')"},
394
+ "name": {"type": "string", "description": "Human name"},
395
+ "description": {"type": "string", "description": "Workspace purpose"},
396
+ "pillars": {"type": "array", "items": {"type": "string"}, "description": "Top-level taxonomy for grouping ideas"},
397
+ "visibility": {"type": "string", "description": "public | federation | private", "default": "public"},
398
+ "owner_contributor_id": {"type": "string", "description": "Contributor who owns this workspace"},
399
+ },
400
+ },
401
+ ),
402
+ Tool(
403
+ name="coherence_get_workspace_pillars",
404
+ description="Get the pillar taxonomy declared by a workspace. Use this before setting `pillar` on a new idea.",
405
+ inputSchema={
406
+ "type": "object",
407
+ "required": ["workspace_id"],
408
+ "properties": {
409
+ "workspace_id": {"type": "string"},
366
410
  },
367
411
  },
368
412
  ),
@@ -663,6 +707,17 @@ TOOLS: list[Tool] = [
663
707
  },
664
708
  },
665
709
  ),
710
+ Tool(
711
+ name="coherence_read_file",
712
+ description="Read raw file content from the repository (specs, docs, etc.) via direct link.",
713
+ inputSchema={
714
+ "type": "object",
715
+ "required": ["path"],
716
+ "properties": {
717
+ "path": {"type": "string", "description": "Relative path from repo root (e.g. 'specs/169-procedural-memory.md')"},
718
+ },
719
+ },
720
+ ),
666
721
  # Concepts (Living Codex ontology)
667
722
  Tool(
668
723
  name="coherence_list_concepts",
@@ -702,6 +757,71 @@ TOOLS: list[Tool] = [
702
757
  },
703
758
  },
704
759
  ),
760
+ # Spec CRUD
761
+ Tool(
762
+ name="coherence_create_spec",
763
+ description="Create a new spec in the registry. Requires spec_id (slug), title, summary, and idea_id.",
764
+ inputSchema={
765
+ "type": "object",
766
+ "required": ["spec_id", "title", "summary"],
767
+ "properties": {
768
+ "spec_id": {"type": "string", "description": "Unique spec slug (e.g. '170-my-feature')"},
769
+ "title": {"type": "string", "description": "Spec title"},
770
+ "summary": {"type": "string", "description": "Spec summary"},
771
+ "idea_id": {"type": "string", "description": "Parent idea ID"},
772
+ "potential_value": {"type": "number", "description": "Estimated CC value", "default": 0},
773
+ "estimated_cost": {"type": "number", "description": "Estimated CC cost", "default": 0},
774
+ "content_path": {"type": "string", "description": "Path to spec content file"},
775
+ "implementation_summary": {"type": "string", "description": "Implementation summary text"},
776
+ },
777
+ },
778
+ ),
779
+ Tool(
780
+ name="coherence_update_spec",
781
+ description="Update an existing spec's properties (title, summary, value, cost, implementation summary).",
782
+ inputSchema={
783
+ "type": "object",
784
+ "required": ["spec_id"],
785
+ "properties": {
786
+ "spec_id": {"type": "string", "description": "The spec ID"},
787
+ "title": {"type": "string"},
788
+ "summary": {"type": "string"},
789
+ "potential_value": {"type": "number"},
790
+ "estimated_cost": {"type": "number"},
791
+ "actual_value": {"type": "number"},
792
+ "actual_cost": {"type": "number"},
793
+ "idea_id": {"type": "string"},
794
+ "implementation_summary": {"type": "string"},
795
+ "process_summary": {"type": "string"},
796
+ "content_path": {"type": "string"},
797
+ },
798
+ },
799
+ ),
800
+ # Workflow
801
+ Tool(
802
+ name="coherence_advance_idea",
803
+ description="Check prerequisites and advance an idea to its next lifecycle stage. Returns current state, prerequisite check results, and whether advancement succeeded.",
804
+ inputSchema={
805
+ "type": "object",
806
+ "required": ["idea_id"],
807
+ "properties": {
808
+ "idea_id": {"type": "string", "description": "The idea ID to advance"},
809
+ "force": {"type": "boolean", "description": "Skip prerequisite checks", "default": False},
810
+ },
811
+ },
812
+ ),
813
+ Tool(
814
+ name="coherence_trace",
815
+ description="Trace the full lineage of any entity — from idea to specs to tasks to source files. Provides navigation breadcrumbs across the entire system.",
816
+ inputSchema={
817
+ "type": "object",
818
+ "required": ["entity_id"],
819
+ "properties": {
820
+ "entity_id": {"type": "string", "description": "An idea slug, spec slug, or task ID"},
821
+ "entity_type": {"type": "string", "description": "idea, spec, or task", "default": "idea"},
822
+ },
823
+ },
824
+ ),
705
825
  ]
706
826
 
707
827
  TOOL_MAP: dict[str, Tool] = {t.name: t for t in TOOLS}
@@ -716,7 +836,14 @@ def dispatch(name: str, args: dict[str, Any]) -> Any:
716
836
  case "coherence_list_ideas":
717
837
  if args.get("search"):
718
838
  return api_get("/api/ideas/cards", {"search": args["search"], "limit": args.get("limit", 20)})
719
- return api_get("/api/ideas", {"limit": args.get("limit", 20)})
839
+ params = {"limit": args.get("limit", 20)}
840
+ if args.get("workspace_id"):
841
+ params["workspace_id"] = args["workspace_id"]
842
+ if args.get("pillar"):
843
+ params["pillar"] = args["pillar"]
844
+ if args.get("curated_only"):
845
+ params["curated_only"] = "true"
846
+ return api_get("/api/ideas", params)
720
847
  case "coherence_get_idea":
721
848
  return api_get(f"/api/ideas/{args['idea_id']}")
722
849
  case "coherence_idea_progress":
@@ -731,7 +858,10 @@ def dispatch(name: str, args: dict[str, Any]) -> Any:
731
858
  case "coherence_list_specs":
732
859
  if args.get("search"):
733
860
  return api_get("/api/spec-registry/cards", {"search": args["search"], "limit": args.get("limit", 20)})
734
- return api_get("/api/spec-registry", {"limit": args.get("limit", 20)})
861
+ params = {"limit": args.get("limit", 20)}
862
+ if args.get("workspace_id"):
863
+ params["workspace_id"] = args["workspace_id"]
864
+ return api_get("/api/spec-registry", params)
735
865
  case "coherence_get_spec":
736
866
  return api_get(f"/api/spec-registry/{args['spec_id']}")
737
867
  # Lineage
@@ -782,9 +912,6 @@ def dispatch(name: str, args: dict[str, Any]) -> Any:
782
912
  }
783
913
  case "coherence_friction_report":
784
914
  return api_get("/api/friction/report", {"window_days": args.get("window_days", 30)})
785
- # Governance
786
- case "coherence_list_change_requests":
787
- return api_get("/api/governance/change-requests")
788
915
  # Federation
789
916
  case "coherence_list_federation_nodes":
790
917
  nodes = api_get("/api/federation/nodes")
@@ -849,7 +976,25 @@ def dispatch(name: str, args: dict[str, Any]) -> Any:
849
976
  "estimated_cost": args.get("estimated_cost", 50),
850
977
  "parent_idea_id": args.get("parent_idea_id"),
851
978
  "tags": args.get("tags"),
979
+ "workspace_id": args.get("workspace_id"),
980
+ "pillar": args.get("pillar"),
981
+ })
982
+ # Workspaces
983
+ case "coherence_list_workspaces":
984
+ return api_get("/api/workspaces")
985
+ case "coherence_get_workspace":
986
+ return api_get(f"/api/workspaces/{args['workspace_id']}")
987
+ case "coherence_create_workspace":
988
+ return api_post("/api/workspaces", {
989
+ "id": args["id"],
990
+ "name": args["name"],
991
+ "description": args.get("description", ""),
992
+ "pillars": args.get("pillars", []),
993
+ "visibility": args.get("visibility", "public"),
994
+ "owner_contributor_id": args.get("owner_contributor_id"),
852
995
  })
996
+ case "coherence_get_workspace_pillars":
997
+ return api_get(f"/api/workspaces/{args['workspace_id']}/pillars")
853
998
  case "coherence_update_idea":
854
999
  return api_patch(f"/api/ideas/{args['idea_id']}", {
855
1000
  "name": args.get("name"),
@@ -968,6 +1113,8 @@ def dispatch(name: str, args: dict[str, Any]) -> Any:
968
1113
  return api_get("/api/blueprints")
969
1114
  case "coherence_apply_blueprint":
970
1115
  return api_post(f"/api/blueprints/{args['blueprint_id']}/apply", {"prefix": args.get("prefix", "")})
1116
+ case "coherence_read_file":
1117
+ return api_get("/api/content/file", {"path": args["path"]})
971
1118
  # Concepts
972
1119
  case "coherence_list_concepts":
973
1120
  if args.get("search"):
@@ -987,6 +1134,123 @@ def dispatch(name: str, args: dict[str, Any]) -> Any:
987
1134
  "relationship_type": args["relationship_type"],
988
1135
  "created_by": args.get("created_by", "mcp"),
989
1136
  })
1137
+ # Spec CRUD
1138
+ case "coherence_create_spec":
1139
+ return api_post("/api/spec-registry", {
1140
+ "spec_id": args["spec_id"],
1141
+ "title": args["title"],
1142
+ "summary": args["summary"],
1143
+ "idea_id": args.get("idea_id"),
1144
+ "potential_value": args.get("potential_value", 0),
1145
+ "estimated_cost": args.get("estimated_cost", 0),
1146
+ "content_path": args.get("content_path"),
1147
+ "implementation_summary": args.get("implementation_summary"),
1148
+ })
1149
+ case "coherence_update_spec":
1150
+ body = {
1151
+ k: v for k, v in {
1152
+ "title": args.get("title"),
1153
+ "summary": args.get("summary"),
1154
+ "potential_value": args.get("potential_value"),
1155
+ "estimated_cost": args.get("estimated_cost"),
1156
+ "actual_value": args.get("actual_value"),
1157
+ "actual_cost": args.get("actual_cost"),
1158
+ "idea_id": args.get("idea_id"),
1159
+ "implementation_summary": args.get("implementation_summary"),
1160
+ "process_summary": args.get("process_summary"),
1161
+ "content_path": args.get("content_path"),
1162
+ }.items() if v is not None
1163
+ }
1164
+ return api_patch(f"/api/spec-registry/{args['spec_id']}", body)
1165
+ # Workflow
1166
+ case "coherence_advance_idea":
1167
+ idea_id = args["idea_id"]
1168
+ force = args.get("force", False)
1169
+ idea = api_get(f"/api/ideas/{idea_id}")
1170
+ if isinstance(idea, dict) and "error" in idea:
1171
+ return idea
1172
+ progress = api_get(f"/api/ideas/{idea_id}/progress")
1173
+ current_stage = idea.get("stage", "none") if isinstance(idea, dict) else "none"
1174
+ stage_order = ["none", "specced", "implementing", "testing", "reviewing", "complete"]
1175
+ idx = stage_order.index(current_stage) if current_stage in stage_order else 0
1176
+ if idx >= len(stage_order) - 1:
1177
+ return {"idea_id": idea_id, "current_stage": current_stage, "next_stage": None,
1178
+ "prerequisites_met": False, "prerequisite_details": {"reason": "already at final stage"},
1179
+ "advanced": False, "result": None}
1180
+ next_stage = stage_order[idx + 1]
1181
+ # Check prerequisites from progress tasks
1182
+ tasks_by_phase = progress.get("tasks_by_phase", {}) if isinstance(progress, dict) else {}
1183
+ prereq_checks = {
1184
+ "specced": ("spec", "at least 1 spec task completed"),
1185
+ "implementing": ("impl", "at least 1 impl task exists"),
1186
+ "testing": ("impl", "at least 1 impl task completed"),
1187
+ "reviewing": ("test", "at least 1 test task completed"),
1188
+ "complete": ("review", "at least 1 review task completed"),
1189
+ }
1190
+ prereqs_met = True
1191
+ prereq_details: dict[str, Any] = {}
1192
+ if next_stage in prereq_checks:
1193
+ phase_key, description = prereq_checks[next_stage]
1194
+ phase_tasks = tasks_by_phase.get(phase_key, [])
1195
+ if next_stage == "implementing":
1196
+ prereqs_met = len(phase_tasks) > 0
1197
+ prereq_details = {"check": description, "phase": phase_key, "task_count": len(phase_tasks)}
1198
+ else:
1199
+ completed = [t for t in phase_tasks if isinstance(t, dict) and t.get("status") == "completed"]
1200
+ prereqs_met = len(completed) > 0
1201
+ prereq_details = {"check": description, "phase": phase_key,
1202
+ "completed_count": len(completed), "total_count": len(phase_tasks)}
1203
+ advanced = False
1204
+ result = None
1205
+ if prereqs_met or force:
1206
+ result = api_patch(f"/api/ideas/{idea_id}", {"stage": next_stage})
1207
+ advanced = not (isinstance(result, dict) and "error" in result)
1208
+ return {"idea_id": idea_id, "current_stage": current_stage, "next_stage": next_stage,
1209
+ "prerequisites_met": prereqs_met, "prerequisite_details": prereq_details,
1210
+ "advanced": advanced, "result": result}
1211
+ case "coherence_trace":
1212
+ entity_id = args["entity_id"]
1213
+ entity_type = args.get("entity_type", "idea")
1214
+ if entity_type == "idea":
1215
+ idea = api_get(f"/api/ideas/{entity_id}")
1216
+ progress = api_get(f"/api/ideas/{entity_id}/progress")
1217
+ specs = api_get("/api/spec-registry/cards", {"q": entity_id, "limit": 50})
1218
+ all_tasks = api_get("/api/agent/tasks", {"status": None, "limit": 50})
1219
+ task_list = all_tasks.get("tasks", []) if isinstance(all_tasks, dict) else []
1220
+ idea_tasks = [t for t in task_list if isinstance(t, dict)
1221
+ and isinstance(t.get("context"), dict) and t["context"].get("idea_id") == entity_id]
1222
+ spec_items = specs if isinstance(specs, list) else specs.get("items", []) if isinstance(specs, dict) else []
1223
+ spec_ids = [s.get("spec_id", s.get("id", "")) for s in spec_items if isinstance(s, dict)]
1224
+ return {"entity_type": "idea", "idea": idea, "progress": progress,
1225
+ "specs": spec_items, "tasks": idea_tasks,
1226
+ "navigation": {"idea_file": f"ideas/{entity_id}.md",
1227
+ "spec_files": [f"specs/{s}.md" for s in spec_ids],
1228
+ "api": f"/api/ideas/{entity_id}",
1229
+ "cli": f"cc idea {entity_id}"}}
1230
+ elif entity_type == "spec":
1231
+ spec = api_get(f"/api/spec-registry/{entity_id}")
1232
+ spec_file = api_get("/api/content/file", {"path": f"specs/{entity_id}.md"})
1233
+ idea_id = spec.get("idea_id") if isinstance(spec, dict) else None
1234
+ parent_idea = api_get(f"/api/ideas/{idea_id}") if idea_id else None
1235
+ nav: dict[str, Any] = {"spec_file": f"specs/{entity_id}.md",
1236
+ "api": f"/api/spec-registry/{entity_id}",
1237
+ "cli": f"cc spec {entity_id}"}
1238
+ if idea_id:
1239
+ nav["idea_file"] = f"ideas/{idea_id}.md"
1240
+ return {"entity_type": "spec", "spec": spec, "spec_file_content": spec_file,
1241
+ "parent_idea": parent_idea, "navigation": nav}
1242
+ elif entity_type == "task":
1243
+ task = api_get(f"/api/agent/tasks/{entity_id}")
1244
+ events = api_get(f"/api/agent/tasks/{entity_id}/stream")
1245
+ context = task.get("context", {}) if isinstance(task, dict) else {}
1246
+ idea_id = context.get("idea_id") if isinstance(context, dict) else None
1247
+ parent_idea = api_get(f"/api/ideas/{idea_id}") if idea_id else None
1248
+ return {"entity_type": "task", "task": task, "events": events,
1249
+ "parent_idea": parent_idea,
1250
+ "navigation": {"api": f"/api/agent/tasks/{entity_id}",
1251
+ "cli": f"cc task {entity_id}"}}
1252
+ else:
1253
+ return {"error": f"Unknown entity_type: {entity_type}. Use 'idea', 'spec', or 'task'."}
990
1254
  case _:
991
1255
  return {"error": f"Unknown tool: {name}"}
992
1256
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coherence-mcp-server",
3
- "version": "0.4.4",
3
+ "version": "0.5.0",
4
4
  "description": "Unified MCP server for the Coherence Network — 51 typed tools for AI agents to browse ideas, manage tasks, link identities, and navigate the universal graph.",
5
5
  "type": "module",
6
6
  "bin": {