coherence-mcp-server 0.1.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 +379 -0
- package/package.json +30 -0
package/index.mjs
ADDED
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
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
|
|
12
|
+
*/
|
|
13
|
+
|
|
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));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const res = await fetch(url.toString(), {
|
|
36
|
+
signal: AbortSignal.timeout(15_000),
|
|
37
|
+
});
|
|
38
|
+
if (!res.ok) return { error: `${res.status} ${res.statusText}` };
|
|
39
|
+
return await res.json();
|
|
40
|
+
}
|
|
41
|
+
|
|
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();
|
|
56
|
+
}
|
|
57
|
+
|
|
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);
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "coherence-mcp-server",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for the Coherence Network — exposes ideas, specs, lineage, identity, and contributions as typed tools for AI agents",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"coherence-mcp-server": "index.mjs"
|
|
8
|
+
},
|
|
9
|
+
"engines": {
|
|
10
|
+
"node": ">=18.0.0"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@modelcontextprotocol/sdk": "^1.0.0"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"index.mjs"
|
|
17
|
+
],
|
|
18
|
+
"keywords": [
|
|
19
|
+
"mcp",
|
|
20
|
+
"coherence",
|
|
21
|
+
"ai-agent",
|
|
22
|
+
"model-context-protocol",
|
|
23
|
+
"tools"
|
|
24
|
+
],
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/seeker71/Coherence-Network.git"
|
|
29
|
+
}
|
|
30
|
+
}
|