coherence-mcp-server 0.3.1 → 0.4.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/index.mjs CHANGED
@@ -1,379 +1,46 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * Coherence Network MCP Server
5
- *
6
- * Exposes the Coherence Network API as typed MCP tools that any
7
- * MCP-compatible AI agent (Claude, Cursor, Windsurf, etc.) can invoke.
8
- *
9
- * Usage:
10
- * npx coherence-mcp-server
11
- * COHERENCE_API_URL=http://localhost:8000 npx coherence-mcp-server
4
+ * Coherence Network MCP Server — Bridge
5
+ *
6
+ * This is a lightweight Node.js wrapper that executes the Python-based
7
+ * MCP server. It ensures that 'npx coherence-mcp-server' continues to
8
+ * work while the primary implementation is centralized in Python.
12
9
  */
13
10
 
14
- import { Server } from "@modelcontextprotocol/sdk/server/index.js";
15
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
16
- import {
17
- CallToolRequestSchema,
18
- ListToolsRequestSchema,
19
- } from "@modelcontextprotocol/sdk/types.js";
20
-
21
- const API_BASE = process.env.COHERENCE_API_URL || "https://api.coherencycoin.com";
22
- const API_KEY = process.env.COHERENCE_API_KEY || "";
23
-
24
- // ---------------------------------------------------------------------------
25
- // HTTP helpers
26
- // ---------------------------------------------------------------------------
27
-
28
- async function apiGet(path, params) {
29
- const url = new URL(path, API_BASE);
30
- if (params) {
31
- for (const [k, v] of Object.entries(params)) {
32
- if (v != null) url.searchParams.set(k, String(v));
11
+ import { spawn } from "node:child_process";
12
+ import { fileURLToPath } from "node:url";
13
+ import { dirname, join } from "node:path";
14
+
15
+ const __dirname = dirname(fileURLToPath(import.meta.url));
16
+
17
+ function main() {
18
+ // Use uvx if available, otherwise fallback to python3
19
+ const args = ["run", "coherence-mcp-server"];
20
+ const options = {
21
+ stdio: "inherit",
22
+ shell: true,
23
+ cwd: __dirname
24
+ };
25
+
26
+ // Check if we are running in a context where we should use the local package
27
+ // instead of 'uvx' (which fetches from PyPI).
28
+ const pythonServer = spawn("uv", args, options);
29
+
30
+ pythonServer.on("error", (err) => {
31
+ if (err.code === 'ENOENT') {
32
+ // Fallback to python3 if 'uv' is not installed
33
+ console.error("Warning: 'uv' not found. Falling back to 'python3'.");
34
+ spawn("python3", ["-m", "coherence_mcp_server"], options);
35
+ } else {
36
+ console.error("Failed to start Python MCP server:", err);
37
+ process.exit(1);
33
38
  }
34
- }
35
- const res = await fetch(url.toString(), {
36
- signal: AbortSignal.timeout(15_000),
37
39
  });
38
- if (!res.ok) return { error: `${res.status} ${res.statusText}` };
39
- return await res.json();
40
- }
41
40
 
42
- async function apiPost(path, body) {
43
- const headers = { "Content-Type": "application/json" };
44
- if (API_KEY) headers["X-API-Key"] = API_KEY;
45
- const res = await fetch(new URL(path, API_BASE).toString(), {
46
- method: "POST",
47
- headers,
48
- body: JSON.stringify(body),
49
- signal: AbortSignal.timeout(15_000),
50
- });
51
- if (!res.ok) {
52
- const err = await res.json().catch(() => ({}));
53
- return { error: err.detail || `${res.status} ${res.statusText}` };
54
- }
55
- return await res.json();
41
+ // Handle termination
42
+ process.on("SIGINT", () => pythonServer.kill("SIGINT"));
43
+ process.on("SIGTERM", () => pythonServer.kill("SIGTERM"));
56
44
  }
57
45
 
58
- // ---------------------------------------------------------------------------
59
- // Tool definitions
60
- // ---------------------------------------------------------------------------
61
-
62
- const TOOLS = [
63
- // Ideas
64
- {
65
- name: "coherence_list_ideas",
66
- description: "Browse the idea portfolio ranked by ROI and free-energy score. Returns ideas with scores, manifestation status, and selection weights.",
67
- inputSchema: {
68
- type: "object",
69
- properties: {
70
- limit: { type: "number", description: "Max ideas to return (default 20)", default: 20 },
71
- search: { type: "string", description: "Search keyword to filter ideas" },
72
- },
73
- },
74
- },
75
- {
76
- name: "coherence_get_idea",
77
- description: "Get full details for a single idea including scores, open questions, value gap, and linked tasks.",
78
- inputSchema: {
79
- type: "object",
80
- properties: {
81
- idea_id: { type: "string", description: "The idea ID" },
82
- },
83
- required: ["idea_id"],
84
- },
85
- },
86
- {
87
- name: "coherence_idea_progress",
88
- description: "Get progress for an idea: stage, tasks by phase, CC staked/spent, contributors.",
89
- inputSchema: {
90
- type: "object",
91
- properties: { idea_id: { type: "string" } },
92
- required: ["idea_id"],
93
- },
94
- },
95
- {
96
- name: "coherence_select_idea",
97
- description: "Let the portfolio engine select the next highest-ROI idea to work on. Temperature controls exploration vs exploitation.",
98
- inputSchema: {
99
- type: "object",
100
- properties: {
101
- temperature: { type: "number", description: "0=deterministic (highest ROI), >1=explore (default 0.5)", default: 0.5 },
102
- },
103
- },
104
- },
105
- {
106
- name: "coherence_showcase",
107
- description: "List validated, shipped ideas that have proven their value.",
108
- inputSchema: { type: "object", properties: {} },
109
- },
110
- {
111
- name: "coherence_resonance",
112
- description: "Show which ideas are generating the most energy and activity right now.",
113
- inputSchema: { type: "object", properties: {} },
114
- },
115
-
116
- // Specs
117
- {
118
- name: "coherence_list_specs",
119
- description: "List feature specs with ROI metrics, value gaps, and implementation summaries.",
120
- inputSchema: {
121
- type: "object",
122
- properties: {
123
- limit: { type: "number", default: 20 },
124
- search: { type: "string", description: "Search keyword" },
125
- },
126
- },
127
- },
128
- {
129
- name: "coherence_get_spec",
130
- description: "Get full spec detail including implementation summary, pseudocode, and ROI.",
131
- inputSchema: {
132
- type: "object",
133
- properties: { spec_id: { type: "string" } },
134
- required: ["spec_id"],
135
- },
136
- },
137
-
138
- // Lineage
139
- {
140
- name: "coherence_list_lineage",
141
- description: "List value lineage chains connecting ideas to specs, implementations, and payouts.",
142
- inputSchema: {
143
- type: "object",
144
- properties: { limit: { type: "number", default: 20 } },
145
- },
146
- },
147
- {
148
- name: "coherence_lineage_valuation",
149
- description: "Get ROI valuation for a lineage chain — measured value, estimated cost, and ROI ratio.",
150
- inputSchema: {
151
- type: "object",
152
- properties: { lineage_id: { type: "string" } },
153
- required: ["lineage_id"],
154
- },
155
- },
156
-
157
- // Identity
158
- {
159
- name: "coherence_list_providers",
160
- description: "List all 37 supported identity providers grouped by category (Social, Dev, Crypto/Web3, Professional, Identity, Custom).",
161
- inputSchema: { type: "object", properties: {} },
162
- },
163
- {
164
- name: "coherence_link_identity",
165
- description: "Link a provider identity (GitHub, Discord, Ethereum, etc.) to a contributor. No registration required.",
166
- inputSchema: {
167
- type: "object",
168
- properties: {
169
- contributor_id: { type: "string", description: "Contributor name" },
170
- provider: { type: "string", description: "Provider key (github, discord, ethereum, solana, ...)" },
171
- provider_id: { type: "string", description: "Handle, address, or username on that provider" },
172
- },
173
- required: ["contributor_id", "provider", "provider_id"],
174
- },
175
- },
176
- {
177
- name: "coherence_lookup_identity",
178
- description: "Find which contributor owns a specific provider identity. Reverse lookup.",
179
- inputSchema: {
180
- type: "object",
181
- properties: {
182
- provider: { type: "string" },
183
- provider_id: { type: "string" },
184
- },
185
- required: ["provider", "provider_id"],
186
- },
187
- },
188
- {
189
- name: "coherence_get_identities",
190
- description: "Get all linked identities for a contributor.",
191
- inputSchema: {
192
- type: "object",
193
- properties: { contributor_id: { type: "string" } },
194
- required: ["contributor_id"],
195
- },
196
- },
197
-
198
- // Contributions
199
- {
200
- name: "coherence_record_contribution",
201
- description: "Record a contribution. Identify by contributor_id OR by provider+provider_id (no registration needed).",
202
- inputSchema: {
203
- type: "object",
204
- properties: {
205
- contributor_id: { type: "string", description: "Contributor name (optional if provider+provider_id given)" },
206
- provider: { type: "string", description: "Identity provider (optional)" },
207
- provider_id: { type: "string", description: "Identity handle (optional)" },
208
- type: { type: "string", description: "Contribution type: code, docs, review, design, community, other" },
209
- amount_cc: { type: "number", description: "CC value (default 1)", default: 1 },
210
- idea_id: { type: "string", description: "Related idea ID (optional)" },
211
- },
212
- required: ["type"],
213
- },
214
- },
215
- {
216
- name: "coherence_contributor_ledger",
217
- description: "Get a contributor's CC balance and contribution history.",
218
- inputSchema: {
219
- type: "object",
220
- properties: { contributor_id: { type: "string" } },
221
- required: ["contributor_id"],
222
- },
223
- },
224
-
225
- // Status
226
- {
227
- name: "coherence_status",
228
- description: "Get network health: API status, uptime, federation nodes, idea count.",
229
- inputSchema: { type: "object", properties: {} },
230
- },
231
- {
232
- name: "coherence_friction_report",
233
- description: "Get friction report — where the pipeline struggles.",
234
- inputSchema: {
235
- type: "object",
236
- properties: {
237
- window_days: { type: "number", default: 30 },
238
- },
239
- },
240
- },
241
-
242
- // Governance
243
- {
244
- name: "coherence_list_change_requests",
245
- description: "List governance change requests.",
246
- inputSchema: { type: "object", properties: {} },
247
- },
248
-
249
- // Federation
250
- {
251
- name: "coherence_list_federation_nodes",
252
- description: "List federated nodes and their capabilities.",
253
- inputSchema: { type: "object", properties: {} },
254
- },
255
- ];
256
-
257
- // ---------------------------------------------------------------------------
258
- // Tool handlers
259
- // ---------------------------------------------------------------------------
260
-
261
- async function handleTool(name, args) {
262
- switch (name) {
263
- // Ideas
264
- case "coherence_list_ideas":
265
- if (args.search) return apiGet("/api/ideas/cards", { search: args.search, limit: args.limit || 20 });
266
- return apiGet("/api/ideas", { limit: args.limit || 20 });
267
- case "coherence_get_idea":
268
- return apiGet(`/api/ideas/${args.idea_id}`);
269
- case "coherence_idea_progress":
270
- return apiGet(`/api/ideas/${args.idea_id}/progress`);
271
- case "coherence_select_idea":
272
- return apiPost("/api/ideas/select", { temperature: args.temperature ?? 0.5 });
273
- case "coherence_showcase":
274
- return apiGet("/api/ideas/showcase");
275
- case "coherence_resonance":
276
- return apiGet("/api/ideas/resonance");
277
-
278
- // Specs
279
- case "coherence_list_specs":
280
- if (args.search) return apiGet("/api/spec-registry/cards", { search: args.search, limit: args.limit || 20 });
281
- return apiGet("/api/spec-registry", { limit: args.limit || 20 });
282
- case "coherence_get_spec":
283
- return apiGet(`/api/spec-registry/${args.spec_id}`);
284
-
285
- // Lineage
286
- case "coherence_list_lineage":
287
- return apiGet("/api/value-lineage/links", { limit: args.limit || 20 });
288
- case "coherence_lineage_valuation":
289
- return apiGet(`/api/value-lineage/links/${args.lineage_id}/valuation`);
290
-
291
- // Identity
292
- case "coherence_list_providers":
293
- return apiGet("/api/identity/providers");
294
- case "coherence_link_identity":
295
- return apiPost("/api/identity/link", {
296
- contributor_id: args.contributor_id,
297
- provider: args.provider,
298
- provider_id: args.provider_id,
299
- display_name: args.provider_id,
300
- });
301
- case "coherence_lookup_identity":
302
- return apiGet(`/api/identity/lookup/${encodeURIComponent(args.provider)}/${encodeURIComponent(args.provider_id)}`);
303
- case "coherence_get_identities":
304
- return apiGet(`/api/identity/${encodeURIComponent(args.contributor_id)}`);
305
-
306
- // Contributions
307
- case "coherence_record_contribution":
308
- return apiPost("/api/contributions/record", {
309
- contributor_id: args.contributor_id || undefined,
310
- provider: args.provider || undefined,
311
- provider_id: args.provider_id || undefined,
312
- type: args.type,
313
- amount_cc: args.amount_cc ?? 1,
314
- idea_id: args.idea_id || undefined,
315
- });
316
- case "coherence_contributor_ledger":
317
- return apiGet(`/api/contributions/ledger/${encodeURIComponent(args.contributor_id)}`);
318
-
319
- // Status
320
- case "coherence_status": {
321
- const [health, count, nodes] = await Promise.all([
322
- apiGet("/api/health"),
323
- apiGet("/api/ideas/count"),
324
- apiGet("/api/federation/nodes"),
325
- ]);
326
- return { health, ideas: count, federation_nodes: Array.isArray(nodes) ? nodes.length : 0 };
327
- }
328
- case "coherence_friction_report":
329
- return apiGet("/api/friction/report", { window_days: args.window_days || 30 });
330
-
331
- // Governance
332
- case "coherence_list_change_requests":
333
- return apiGet("/api/governance/change-requests");
334
-
335
- // Federation
336
- case "coherence_list_federation_nodes": {
337
- const [nodes, caps] = await Promise.all([
338
- apiGet("/api/federation/nodes"),
339
- apiGet("/api/federation/nodes/capabilities"),
340
- ]);
341
- return { nodes, capabilities: caps };
342
- }
343
-
344
- default:
345
- return { error: `Unknown tool: ${name}` };
346
- }
347
- }
348
-
349
- // ---------------------------------------------------------------------------
350
- // MCP server setup
351
- // ---------------------------------------------------------------------------
352
-
353
- const server = new Server(
354
- { name: "coherence-network", version: "0.1.0" },
355
- { capabilities: { tools: {} } },
356
- );
357
-
358
- server.setRequestHandler(ListToolsRequestSchema, async () => ({
359
- tools: TOOLS,
360
- }));
361
-
362
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
363
- const { name, arguments: args } = request.params;
364
- try {
365
- const result = await handleTool(name, args || {});
366
- return {
367
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
368
- };
369
- } catch (err) {
370
- return {
371
- content: [{ type: "text", text: `Error: ${err.message}` }],
372
- isError: true,
373
- };
374
- }
375
- });
376
-
377
- // Start
378
- const transport = new StdioServerTransport();
379
- await server.connect(transport);
46
+ main();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "coherence-mcp-server",
3
- "version": "0.3.1",
4
- "description": "MCP server for the Coherence Network \u2014 20 typed tools for AI agents to browse ideas, trace value chains, link identities, and record contributions. Works with Claude, Cursor, Windsurf, and any MCP client.",
3
+ "version": "0.4.0",
4
+ "description": "Unified MCP server for the Coherence Network \u2014 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": {
7
7
  "coherence-mcp-server": "index.mjs"
@@ -14,7 +14,9 @@
14
14
  },
15
15
  "files": [
16
16
  "index.mjs",
17
- "README.md"
17
+ "README.md",
18
+ "coherence_mcp_server/",
19
+ "pyproject.toml"
18
20
  ],
19
21
  "keywords": [
20
22
  "mcp",
@@ -46,5 +48,8 @@
46
48
  "bugs": {
47
49
  "url": "https://github.com/seeker71/Coherence-Network/issues"
48
50
  },
49
- "author": "Coherence Network Contributors"
51
+ "author": "Coherence Network Contributors",
52
+ "publishConfig": {
53
+ "access": "public"
54
+ }
50
55
  }
package/pyproject.toml ADDED
@@ -0,0 +1,54 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.18.0"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "coherence-mcp-server"
7
+ version = "0.4.0"
8
+ 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."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "Coherence Network Contributors" }]
13
+ keywords = [
14
+ "mcp",
15
+ "model-context-protocol",
16
+ "coherence-network",
17
+ "ai-agent",
18
+ "ideas",
19
+ "specs",
20
+ "ontology",
21
+ "living-codex",
22
+ ]
23
+ classifiers = [
24
+ "Development Status :: 4 - Beta",
25
+ "Intended Audience :: Developers",
26
+ "License :: OSI Approved :: MIT License",
27
+ "Programming Language :: Python :: 3",
28
+ "Programming Language :: Python :: 3.10",
29
+ "Programming Language :: Python :: 3.11",
30
+ "Programming Language :: Python :: 3.12",
31
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
32
+ ]
33
+ dependencies = [
34
+ "httpx>=0.28.0",
35
+ "mcp>=1.0.0",
36
+ ]
37
+
38
+ [project.urls]
39
+ Homepage = "https://coherencycoin.com"
40
+ Repository = "https://github.com/seeker71/Coherence-Network"
41
+ Documentation = "https://api.coherencycoin.com/docs"
42
+ "Bug Tracker" = "https://github.com/seeker71/Coherence-Network/issues"
43
+
44
+ [project.scripts]
45
+ coherence-mcp-server = "coherence_mcp_server.__main__:main"
46
+
47
+ [tool.hatch.build.targets.sdist]
48
+ include = [
49
+ "/coherence_mcp_server",
50
+ "/README.md",
51
+ ]
52
+
53
+ [tool.hatch.build.targets.wheel]
54
+ packages = ["coherence_mcp_server"]