@abderraouf-yt/got-mcp 3.2.0 → 3.2.1
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/dist/context/ContextStore.js +89 -0
- package/dist/context/index.js +4 -0
- package/dist/graph/ThoughtGraph.js +123 -0
- package/dist/server/http.js +2 -1
- package/dist/server/mcp.js +227 -58
- package/dist/types.js +5 -4
- package/package.json +60 -60
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Context Store (CA-MCP pattern, arXiv 2601.11595)
|
|
3
|
+
* Key-value store for intermediate reasoning state.
|
|
4
|
+
* Tracks provenance (source) for trust scoring.
|
|
5
|
+
*
|
|
6
|
+
* @module context/ContextStore
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* In-memory shared context store.
|
|
10
|
+
* Enables cross-tool knowledge sharing within a session,
|
|
11
|
+
* reducing redundant LLM calls (CA-MCP, 2026).
|
|
12
|
+
*/
|
|
13
|
+
export class ContextStore {
|
|
14
|
+
store = new Map();
|
|
15
|
+
/**
|
|
16
|
+
* Set a key-value pair with source provenance.
|
|
17
|
+
*/
|
|
18
|
+
set(key, value, source) {
|
|
19
|
+
this.store.set(key, {
|
|
20
|
+
value,
|
|
21
|
+
source,
|
|
22
|
+
updatedAt: new Date().toISOString(),
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Get a value by key. Returns undefined if not found.
|
|
27
|
+
*/
|
|
28
|
+
get(key) {
|
|
29
|
+
return this.store.get(key)?.value;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get value with full provenance metadata.
|
|
33
|
+
*/
|
|
34
|
+
getWithProvenance(key) {
|
|
35
|
+
return this.store.get(key);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Check if a key exists.
|
|
39
|
+
*/
|
|
40
|
+
has(key) {
|
|
41
|
+
return this.store.has(key);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Delete a key.
|
|
45
|
+
*/
|
|
46
|
+
delete(key) {
|
|
47
|
+
return this.store.delete(key);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* List all keys with their sources (no values — lightweight).
|
|
51
|
+
*/
|
|
52
|
+
list() {
|
|
53
|
+
return Array.from(this.store.entries()).map(([key, entry]) => ({
|
|
54
|
+
key,
|
|
55
|
+
source: entry.source,
|
|
56
|
+
updatedAt: entry.updatedAt,
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Get full store as a serializable object.
|
|
61
|
+
*/
|
|
62
|
+
getAll() {
|
|
63
|
+
const result = {};
|
|
64
|
+
for (const [key, entry] of this.store) {
|
|
65
|
+
result[key] = entry;
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Clear all context.
|
|
71
|
+
*/
|
|
72
|
+
clear() {
|
|
73
|
+
this.store.clear();
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Number of entries in the store.
|
|
77
|
+
*/
|
|
78
|
+
get size() {
|
|
79
|
+
return this.store.size;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// Singleton context store instance
|
|
83
|
+
let contextInstance = null;
|
|
84
|
+
export function getContextInstance() {
|
|
85
|
+
if (!contextInstance) {
|
|
86
|
+
contextInstance = new ContextStore();
|
|
87
|
+
}
|
|
88
|
+
return contextInstance;
|
|
89
|
+
}
|
|
@@ -673,6 +673,129 @@ export class ThoughtGraph {
|
|
|
673
673
|
release();
|
|
674
674
|
}
|
|
675
675
|
}
|
|
676
|
+
// ==========================================
|
|
677
|
+
// v4.0: Self-Reflection + Multi-Dimensional Scoring
|
|
678
|
+
// ==========================================
|
|
679
|
+
/**
|
|
680
|
+
* Compute a composite score from a ConfidenceVector.
|
|
681
|
+
* Weights: logical (35%), factual (30%), relevance (25%), novelty (10%).
|
|
682
|
+
*/
|
|
683
|
+
computeCompositeScore(confidence) {
|
|
684
|
+
const score = (confidence.factual * 0.30 +
|
|
685
|
+
confidence.logical * 0.35 +
|
|
686
|
+
confidence.relevance * 0.25 +
|
|
687
|
+
confidence.novelty * 0.10);
|
|
688
|
+
return Math.round(score * 100) / 100;
|
|
689
|
+
}
|
|
690
|
+
/**
|
|
691
|
+
* Self-reflection loop (2026 pattern).
|
|
692
|
+
* Creates a critique node linked via "reflection" edge.
|
|
693
|
+
* If a refined thought is provided, also creates a branch.
|
|
694
|
+
*
|
|
695
|
+
* @param nodeId - Node to reflect on
|
|
696
|
+
* @param critique - The critique text
|
|
697
|
+
* @param confidence - Multi-dimensional confidence assessment
|
|
698
|
+
* @param refinedThought - Optional improved version of the thought
|
|
699
|
+
* @returns IDs of created nodes
|
|
700
|
+
*/
|
|
701
|
+
reflectAndRefine(nodeId, critique, confidence, refinedThought) {
|
|
702
|
+
const node = this.nodes.get(nodeId);
|
|
703
|
+
if (!node) {
|
|
704
|
+
throw new ThoughtGraphNotFoundError(nodeId);
|
|
705
|
+
}
|
|
706
|
+
const compositeScore = this.computeCompositeScore(confidence);
|
|
707
|
+
// Update the original node with confidence data
|
|
708
|
+
this.nodes.set(nodeId, {
|
|
709
|
+
...node,
|
|
710
|
+
score: compositeScore,
|
|
711
|
+
confidence,
|
|
712
|
+
updatedAt: new Date().toISOString(),
|
|
713
|
+
});
|
|
714
|
+
// Create critique node
|
|
715
|
+
const critiqueId = this.addNode(`[Reflection] ${critique}`);
|
|
716
|
+
this.addEdge(nodeId, critiqueId, "reflection");
|
|
717
|
+
// Update critique node with assessment metadata
|
|
718
|
+
const critiqueNode = this.nodes.get(critiqueId);
|
|
719
|
+
this.nodes.set(critiqueId, {
|
|
720
|
+
...critiqueNode,
|
|
721
|
+
score: compositeScore,
|
|
722
|
+
confidence,
|
|
723
|
+
status: compositeScore >= 0.7 ? "validated" : "active",
|
|
724
|
+
metadata: {
|
|
725
|
+
...(critiqueNode.metadata ?? {}),
|
|
726
|
+
reflectionOf: nodeId,
|
|
727
|
+
assessmentType: "self-reflection",
|
|
728
|
+
},
|
|
729
|
+
});
|
|
730
|
+
let branchId;
|
|
731
|
+
// If critique reveals a flaw and refined version provided, branch
|
|
732
|
+
if (refinedThought && compositeScore < 0.7) {
|
|
733
|
+
branchId = this.addNode(refinedThought);
|
|
734
|
+
this.addEdge(nodeId, branchId, "branch");
|
|
735
|
+
const branchNode = this.nodes.get(branchId);
|
|
736
|
+
this.nodes.set(branchId, {
|
|
737
|
+
...branchNode,
|
|
738
|
+
status: "active",
|
|
739
|
+
metadata: {
|
|
740
|
+
...(branchNode.metadata ?? {}),
|
|
741
|
+
refinedFrom: nodeId,
|
|
742
|
+
refinementReason: critique,
|
|
743
|
+
},
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
this.stateVersion++;
|
|
747
|
+
this.save();
|
|
748
|
+
return { critiqueId, branchId, compositeScore };
|
|
749
|
+
}
|
|
750
|
+
/**
|
|
751
|
+
* Export the winning path as a structured reasoning trace.
|
|
752
|
+
* Format compatible with Long CoT used by DeepSeek-R1 and o3.
|
|
753
|
+
*/
|
|
754
|
+
exportReasoningTrace() {
|
|
755
|
+
const result = this.findWinningPath({ beamWidth: 1 });
|
|
756
|
+
if (result.path.length === 0) {
|
|
757
|
+
return {
|
|
758
|
+
question: "",
|
|
759
|
+
steps: [],
|
|
760
|
+
conclusion: "",
|
|
761
|
+
compositeScore: 0,
|
|
762
|
+
totalNodes: this.nodes.size,
|
|
763
|
+
totalEdges: this.edges.length,
|
|
764
|
+
exportedAt: new Date().toISOString(),
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
const steps = result.path.map((node, index) => {
|
|
768
|
+
// Find reflection children
|
|
769
|
+
const reflections = this.edges
|
|
770
|
+
.filter(e => e.from === node.id && e.relation === "reflection")
|
|
771
|
+
.map(e => this.nodes.get(e.to)?.thought ?? "")
|
|
772
|
+
.filter(Boolean);
|
|
773
|
+
// Find branch siblings (alternative paths)
|
|
774
|
+
const alternatives = this.edges
|
|
775
|
+
.filter(e => e.from === node.id && e.relation === "branch")
|
|
776
|
+
.map(e => this.nodes.get(e.to)?.thought ?? "")
|
|
777
|
+
.filter(Boolean);
|
|
778
|
+
return {
|
|
779
|
+
step: index + 1,
|
|
780
|
+
nodeId: node.id,
|
|
781
|
+
thought: node.thought,
|
|
782
|
+
score: node.score,
|
|
783
|
+
confidence: node.confidence,
|
|
784
|
+
status: node.status,
|
|
785
|
+
reflections,
|
|
786
|
+
alternatives,
|
|
787
|
+
};
|
|
788
|
+
});
|
|
789
|
+
return {
|
|
790
|
+
question: result.path[0].thought,
|
|
791
|
+
steps,
|
|
792
|
+
conclusion: result.path[result.path.length - 1].thought,
|
|
793
|
+
compositeScore: result.totalScore / result.path.length,
|
|
794
|
+
totalNodes: this.nodes.size,
|
|
795
|
+
totalEdges: this.edges.length,
|
|
796
|
+
exportedAt: new Date().toISOString(),
|
|
797
|
+
};
|
|
798
|
+
}
|
|
676
799
|
}
|
|
677
800
|
// ==========================================
|
|
678
801
|
// SESSION REGISTRY (replaces singleton)
|
package/dist/server/http.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import express from "express";
|
|
2
2
|
import cors from "cors";
|
|
3
3
|
import net from "net";
|
|
4
|
+
import crypto from "crypto";
|
|
4
5
|
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
5
6
|
import { SERVER_CONFIG } from "../types.js";
|
|
6
7
|
import { getGraphInstance } from "../graph/index.js";
|
|
@@ -54,7 +55,7 @@ export async function startHttpServer() {
|
|
|
54
55
|
app.use(express.json());
|
|
55
56
|
const activeSessions = new Map();
|
|
56
57
|
app.get("/sse", async (req, res) => {
|
|
57
|
-
const sessionId = `session_${
|
|
58
|
+
const sessionId = `session_${crypto.randomUUID()}`;
|
|
58
59
|
const transport = new SSEServerTransport("/messages", res);
|
|
59
60
|
const mcpServer = createServerInstance();
|
|
60
61
|
activeSessions.set(sessionId, transport);
|
package/dist/server/mcp.js
CHANGED
|
@@ -2,18 +2,19 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { SERVER_CONFIG, RESOURCE_URIS } from "../types.js";
|
|
4
4
|
import { getGraphInstance } from "../graph/index.js";
|
|
5
|
+
import { getContextInstance } from "../context/index.js";
|
|
5
6
|
/**
|
|
6
7
|
* Trigger autonomous LLM audit via MCP Sampling.
|
|
7
8
|
*/
|
|
8
9
|
async function triggerAutonomousAudit(server, node, graph) {
|
|
9
|
-
const auditPrompt = `Please audit this thought node:
|
|
10
|
-
Thought: "${node.thought}"
|
|
11
|
-
Current Score: ${node.score}
|
|
12
|
-
Context Graph: ${JSON.stringify(graph.getSimpleGraph())}
|
|
13
|
-
|
|
14
|
-
Provide a JSON response with:
|
|
15
|
-
- score: number (0.0 to 1.0)
|
|
16
|
-
- status: "validated" | "rejected" | "branching"
|
|
10
|
+
const auditPrompt = `Please audit this thought node:
|
|
11
|
+
Thought: "${node.thought}"
|
|
12
|
+
Current Score: ${node.score}
|
|
13
|
+
Context Graph: ${JSON.stringify(graph.getSimpleGraph())}
|
|
14
|
+
|
|
15
|
+
Provide a JSON response with:
|
|
16
|
+
- score: number (0.0 to 1.0)
|
|
17
|
+
- status: "validated" | "rejected" | "branching"
|
|
17
18
|
- critique: string`;
|
|
18
19
|
try {
|
|
19
20
|
const auditResult = await server.server.request({
|
|
@@ -55,6 +56,7 @@ export function createServerInstance() {
|
|
|
55
56
|
version: SERVER_CONFIG.version,
|
|
56
57
|
});
|
|
57
58
|
const graph = getGraphInstance();
|
|
59
|
+
const contextStore = getContextInstance();
|
|
58
60
|
// 1. Register Resources
|
|
59
61
|
server.resource("Current Thought Graph", RESOURCE_URIS.currentGraph, async (uri) => ({
|
|
60
62
|
contents: [{
|
|
@@ -63,18 +65,30 @@ export function createServerInstance() {
|
|
|
63
65
|
mimeType: "application/json"
|
|
64
66
|
}]
|
|
65
67
|
}));
|
|
68
|
+
// v4.0: Shared Context Store resource (CA-MCP pattern)
|
|
69
|
+
server.resource("Shared Context Store", RESOURCE_URIS.contextStore, async (uri) => ({
|
|
70
|
+
contents: [{
|
|
71
|
+
uri: uri.href,
|
|
72
|
+
text: JSON.stringify(contextStore.getAll(), null, 2),
|
|
73
|
+
mimeType: "application/json"
|
|
74
|
+
}]
|
|
75
|
+
}));
|
|
66
76
|
// Helper to notify clients of updates
|
|
67
77
|
const notifyUpdate = () => {
|
|
68
78
|
// @ts-ignore - The MCP SDK expects a stricter Notification type intersection
|
|
69
79
|
server.server.notification({ method: "notifications/resources/updated", params: { uri: RESOURCE_URIS.currentGraph } });
|
|
70
80
|
};
|
|
71
81
|
// 2. Register Tools
|
|
72
|
-
server.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
.
|
|
77
|
-
.
|
|
82
|
+
server.registerTool("propose_thought", {
|
|
83
|
+
description: "Propose a new unit of reasoning (node) in the thought graph.",
|
|
84
|
+
inputSchema: {
|
|
85
|
+
thought: z.string().min(1, "Thought content is required").max(5000, "Thought exceeds 5000 chars").describe("The content of the thought"),
|
|
86
|
+
parentId: z.string().optional().describe("Optional parent node ID if this thought builds on a previous one"),
|
|
87
|
+
relation: z.enum(["refinement", "contradiction", "support", "branch"])
|
|
88
|
+
.default("refinement")
|
|
89
|
+
.describe("How this thought relates to its parent"),
|
|
90
|
+
},
|
|
91
|
+
annotations: { destructiveHint: true }
|
|
78
92
|
}, async ({ thought, parentId, relation }) => {
|
|
79
93
|
try {
|
|
80
94
|
const nodeId = graph.addNode(thought);
|
|
@@ -94,12 +108,22 @@ export function createServerInstance() {
|
|
|
94
108
|
return { content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }], isError: true };
|
|
95
109
|
}
|
|
96
110
|
});
|
|
97
|
-
server.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
111
|
+
server.registerTool("evaluate_thought", {
|
|
112
|
+
description: "Assign a score or status to a thought node. If score is omitted, triggers autonomous LLM audit via sampling.",
|
|
113
|
+
inputSchema: {
|
|
114
|
+
nodeId: z.string().min(1, "Node ID is required").describe("The ID of the node to evaluate"),
|
|
115
|
+
score: z.number().min(0).max(1).optional().describe("Omit to trigger autonomous LLM audit (0.0 to 1.0)"),
|
|
116
|
+
status: z.enum(["active", "validated", "rejected", "branching"]).optional().describe("Update the node status"),
|
|
117
|
+
critique: z.string().max(2000, "Critique exceeds 2000 chars").optional().describe("Reasoning for the evaluation"),
|
|
118
|
+
confidence: z.object({
|
|
119
|
+
factual: z.number().min(0).max(1).describe("Grounded in verifiable facts"),
|
|
120
|
+
logical: z.number().min(0).max(1).describe("Reasoning chain is valid"),
|
|
121
|
+
relevance: z.number().min(0).max(1).describe("Addresses the problem directly"),
|
|
122
|
+
novelty: z.number().min(0).max(1).describe("Adds new information"),
|
|
123
|
+
}).optional().describe("v4.0: Multi-dimensional confidence — if provided, composite score is auto-computed"),
|
|
124
|
+
},
|
|
125
|
+
annotations: { destructiveHint: true }
|
|
126
|
+
}, async ({ nodeId, score, status, critique, confidence }) => {
|
|
103
127
|
try {
|
|
104
128
|
const node = graph.getNode(nodeId);
|
|
105
129
|
if (!node) {
|
|
@@ -113,8 +137,13 @@ export function createServerInstance() {
|
|
|
113
137
|
structuredContent: { nodeId, audited: true, message: auditResult }
|
|
114
138
|
};
|
|
115
139
|
}
|
|
140
|
+
// v4.0: if confidence provided, compute composite score automatically
|
|
141
|
+
const finalScore = confidence
|
|
142
|
+
? graph.computeCompositeScore(confidence)
|
|
143
|
+
: score;
|
|
116
144
|
graph.updateNode(nodeId, {
|
|
117
|
-
score,
|
|
145
|
+
score: finalScore,
|
|
146
|
+
confidence,
|
|
118
147
|
status: status ?? node.status,
|
|
119
148
|
metadata: critique ? { critique } : undefined,
|
|
120
149
|
});
|
|
@@ -128,14 +157,22 @@ export function createServerInstance() {
|
|
|
128
157
|
return { content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }], isError: true };
|
|
129
158
|
}
|
|
130
159
|
});
|
|
131
|
-
server.
|
|
160
|
+
server.registerTool("get_thought_graph", {
|
|
161
|
+
description: "Retrieve the entire current thought graph.",
|
|
162
|
+
inputSchema: {},
|
|
163
|
+
annotations: { readOnlyHint: true }
|
|
164
|
+
}, async () => {
|
|
132
165
|
const graphState = graph.getGraph();
|
|
133
166
|
return {
|
|
134
167
|
content: [{ type: "text", text: JSON.stringify(graphState, null, 2) }],
|
|
135
168
|
structuredContent: graphState
|
|
136
169
|
};
|
|
137
170
|
});
|
|
138
|
-
server.
|
|
171
|
+
server.registerTool("reset_graph", {
|
|
172
|
+
description: "Clear the current reasoning session, emptying all nodes and edges.",
|
|
173
|
+
inputSchema: {},
|
|
174
|
+
annotations: { destructiveHint: true }
|
|
175
|
+
}, async () => {
|
|
139
176
|
graph.clear();
|
|
140
177
|
notifyUpdate();
|
|
141
178
|
return {
|
|
@@ -144,10 +181,14 @@ export function createServerInstance() {
|
|
|
144
181
|
};
|
|
145
182
|
});
|
|
146
183
|
// 3. GoT Primitives — Aggregate, Prune, Converge
|
|
147
|
-
server.
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
184
|
+
server.registerTool("aggregate_thoughts", {
|
|
185
|
+
description: "GoT Primitive: Merge 2+ thought nodes into a weighted synthesis. Uses formula: Σ(score×weight)/Σ(weights). Retains full provenance and computes aggregation confidence (1 - stddev).",
|
|
186
|
+
inputSchema: {
|
|
187
|
+
nodeIds: z.array(z.string()).min(2, "At least 2 node IDs required").describe("Array of node IDs to merge"),
|
|
188
|
+
synthesis: z.string().min(1, "Synthesis content is required").describe("The merged conclusion that combines insights from all source nodes"),
|
|
189
|
+
weights: z.array(z.number().min(0).max(1)).optional().describe("Optional per-node weights (defaults to each node's score as its confidence weight)"),
|
|
190
|
+
},
|
|
191
|
+
annotations: { destructiveHint: true }
|
|
151
192
|
}, async ({ nodeIds, synthesis, weights }) => {
|
|
152
193
|
try {
|
|
153
194
|
const newId = graph.aggregateNodes(nodeIds, synthesis, weights);
|
|
@@ -170,12 +211,16 @@ export function createServerInstance() {
|
|
|
170
211
|
return { content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }], isError: true };
|
|
171
212
|
}
|
|
172
213
|
});
|
|
173
|
-
server.
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
214
|
+
server.registerTool("prune_branch", {
|
|
215
|
+
description: "GoT Primitive: Recursively reject a node and ALL its descendants. Modes: 'hard' (score=0, status=rejected) or 'soft' (score decayed by factor, status preserved). Tracks trigger origin and original scores.",
|
|
216
|
+
inputSchema: {
|
|
217
|
+
nodeId: z.string().min(1, "Node ID is required").describe("The root node of the branch to prune"),
|
|
218
|
+
reason: z.string().optional().describe("Why this branch is being pruned"),
|
|
219
|
+
mode: z.enum(["hard", "soft"]).default("hard").describe("'hard' zeroes scores and rejects; 'soft' decays scores while preserving status"),
|
|
220
|
+
decayFactor: z.number().min(0).max(1).default(0.5).describe("Score multiplier for soft prune (0.5 = halve scores)"),
|
|
221
|
+
trigger: z.enum(["manual", "auto"]).default("manual").describe("Whether this prune was triggered manually or by an auto-threshold"),
|
|
222
|
+
},
|
|
223
|
+
annotations: { destructiveHint: true }
|
|
179
224
|
}, async ({ nodeId, reason, mode, decayFactor, trigger }) => {
|
|
180
225
|
try {
|
|
181
226
|
const result = graph.pruneFromNode(nodeId, reason, { mode, decayFactor, trigger });
|
|
@@ -195,10 +240,14 @@ export function createServerInstance() {
|
|
|
195
240
|
return { content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }], isError: true };
|
|
196
241
|
}
|
|
197
242
|
});
|
|
198
|
-
server.
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
243
|
+
server.registerTool("find_winning_path", {
|
|
244
|
+
description: "GoT Primitive: Trace the best scoring path(s) from root to leaf. Default: greedy (beamWidth=1). Set beamWidth>1 for k-best beam search. Supports score threshold gating and path length caps.",
|
|
245
|
+
inputSchema: {
|
|
246
|
+
beamWidth: z.number().int().min(1).max(10).default(1).describe("Number of top paths to track (1=greedy DFS, >1=beam search)"),
|
|
247
|
+
scoreThreshold: z.number().min(0).max(1).default(0).describe("Minimum node score to include in path (filters low-confidence nodes)"),
|
|
248
|
+
maxPathLength: z.number().int().min(1).default(50).describe("Maximum path depth to prevent runaway traversal"),
|
|
249
|
+
},
|
|
250
|
+
annotations: { readOnlyHint: true }
|
|
202
251
|
}, async ({ beamWidth, scoreThreshold, maxPathLength }) => {
|
|
203
252
|
try {
|
|
204
253
|
const result = graph.findWinningPath({ beamWidth, scoreThreshold, maxPathLength });
|
|
@@ -232,7 +281,11 @@ export function createServerInstance() {
|
|
|
232
281
|
}
|
|
233
282
|
});
|
|
234
283
|
// 4. Observability — Graph Metrics
|
|
235
|
-
server.
|
|
284
|
+
server.registerTool("get_graph_metrics", {
|
|
285
|
+
description: "Returns structured observability metrics: node count, edge count, max depth, avg score, prune ratio, status breakdown, and root count. Use this to monitor graph health.",
|
|
286
|
+
inputSchema: {},
|
|
287
|
+
annotations: { readOnlyHint: true }
|
|
288
|
+
}, async () => {
|
|
236
289
|
try {
|
|
237
290
|
const metrics = graph.getMetrics();
|
|
238
291
|
const limits = graph.getLimits();
|
|
@@ -255,7 +308,11 @@ export function createServerInstance() {
|
|
|
255
308
|
}
|
|
256
309
|
});
|
|
257
310
|
// 5. Replay — Snapshot Export/Restore
|
|
258
|
-
server.
|
|
311
|
+
server.registerTool("export_snapshot", {
|
|
312
|
+
description: "Export a full snapshot of the current graph state for replay, recovery, or debugging. Returns all nodes, edges, and counter as a serializable JSON object.",
|
|
313
|
+
inputSchema: {},
|
|
314
|
+
annotations: { readOnlyHint: true }
|
|
315
|
+
}, async () => {
|
|
259
316
|
try {
|
|
260
317
|
const snapshot = graph.exportSnapshot();
|
|
261
318
|
return {
|
|
@@ -267,25 +324,29 @@ export function createServerInstance() {
|
|
|
267
324
|
return { content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }], isError: true };
|
|
268
325
|
}
|
|
269
326
|
});
|
|
270
|
-
server.
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
327
|
+
server.registerTool("restore_snapshot", {
|
|
328
|
+
description: "Restore graph state from a previously exported snapshot. Replaces ALL current state. Use for deterministic replay or recovery.",
|
|
329
|
+
inputSchema: {
|
|
330
|
+
snapshot: z.object({
|
|
331
|
+
nodes: z.array(z.object({
|
|
332
|
+
id: z.string(),
|
|
333
|
+
thought: z.string(),
|
|
334
|
+
status: z.enum(["active", "validated", "rejected", "branching"]),
|
|
335
|
+
score: z.number(),
|
|
336
|
+
metadata: z.record(z.string(), z.any()).optional(),
|
|
337
|
+
createdAt: z.string(),
|
|
338
|
+
updatedAt: z.string()
|
|
339
|
+
})).describe("Array of ThoughtNode objects"),
|
|
340
|
+
edges: z.array(z.object({
|
|
341
|
+
from: z.string(),
|
|
342
|
+
to: z.string(),
|
|
343
|
+
relation: z.enum(["refinement", "contradiction", "support", "branch", "aggregation"]),
|
|
344
|
+
createdAt: z.string()
|
|
345
|
+
})).describe("Array of ThoughtEdge objects"),
|
|
346
|
+
nodeCounter: z.number().int().min(0).describe("The node counter value from the snapshot"),
|
|
347
|
+
}).describe("A snapshot object previously returned by export_snapshot"),
|
|
348
|
+
},
|
|
349
|
+
annotations: { destructiveHint: true }
|
|
289
350
|
}, async ({ snapshot }) => {
|
|
290
351
|
try {
|
|
291
352
|
const beforeCount = graph.size;
|
|
@@ -304,5 +365,113 @@ export function createServerInstance() {
|
|
|
304
365
|
return { content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }], isError: true };
|
|
305
366
|
}
|
|
306
367
|
});
|
|
368
|
+
// ==========================================
|
|
369
|
+
// v4.0: Self-Reflection Tool (2026 pattern)
|
|
370
|
+
// ==========================================
|
|
371
|
+
server.registerTool("reflect_and_refine", {
|
|
372
|
+
description: "Self-reflection loop: auto-critique a thought, assess confidence on 4 axes (factual, logical, relevance, novelty), and optionally branch a refined version. Implements DeepSeek-R1 self-verification pattern.",
|
|
373
|
+
inputSchema: {
|
|
374
|
+
nodeId: z.string().min(1).describe("Node to reflect on"),
|
|
375
|
+
critique: z.string().min(1).max(5000).describe("Your critique of this thought"),
|
|
376
|
+
confidence: z.object({
|
|
377
|
+
factual: z.number().min(0).max(1).describe("Grounded in verifiable facts (0-1)"),
|
|
378
|
+
logical: z.number().min(0).max(1).describe("Reasoning chain is valid (0-1)"),
|
|
379
|
+
relevance: z.number().min(0).max(1).describe("Addresses the problem directly (0-1)"),
|
|
380
|
+
novelty: z.number().min(0).max(1).describe("Adds new information vs restating (0-1)"),
|
|
381
|
+
}).describe("Multi-dimensional confidence assessment"),
|
|
382
|
+
refinedThought: z.string().max(5000).optional()
|
|
383
|
+
.describe("If critique reveals a flaw, provide the improved version to auto-branch"),
|
|
384
|
+
},
|
|
385
|
+
annotations: { destructiveHint: true }
|
|
386
|
+
}, async ({ nodeId, critique, confidence, refinedThought }) => {
|
|
387
|
+
try {
|
|
388
|
+
const result = graph.reflectAndRefine(nodeId, critique, confidence, refinedThought);
|
|
389
|
+
notifyUpdate();
|
|
390
|
+
const parts = [
|
|
391
|
+
`Reflection on ${nodeId}: composite score ${result.compositeScore}`,
|
|
392
|
+
`Critique node: ${result.critiqueId}`,
|
|
393
|
+
];
|
|
394
|
+
if (result.branchId) {
|
|
395
|
+
parts.push(`Refined branch: ${result.branchId} (auto-branched because score < 0.7)`);
|
|
396
|
+
}
|
|
397
|
+
return {
|
|
398
|
+
content: [{ type: "text", text: parts.join("\n") }],
|
|
399
|
+
structuredContent: {
|
|
400
|
+
nodeId,
|
|
401
|
+
critiqueId: result.critiqueId,
|
|
402
|
+
branchId: result.branchId ?? null,
|
|
403
|
+
compositeScore: result.compositeScore,
|
|
404
|
+
confidence,
|
|
405
|
+
},
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
catch (err) {
|
|
409
|
+
return { content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }], isError: true };
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
// ==========================================
|
|
413
|
+
// v4.0: Shared Context Store Tools (CA-MCP)
|
|
414
|
+
// ==========================================
|
|
415
|
+
server.registerTool("context_set", {
|
|
416
|
+
description: "Write a key-value pair to the shared context store. Tracks source provenance for trust scoring. Use this to share intermediate results between reasoning steps.",
|
|
417
|
+
inputSchema: {
|
|
418
|
+
key: z.string().min(1).max(200).describe("Context key (e.g. 'user_requirements', 'domain_constraints')"),
|
|
419
|
+
value: z.unknown().describe("Any JSON-serializable value"),
|
|
420
|
+
source: z.string().min(1).max(200).describe("Source of this context (e.g. 'propose_thought:node_3', 'user_input')"),
|
|
421
|
+
},
|
|
422
|
+
annotations: { destructiveHint: true }
|
|
423
|
+
}, async ({ key, value, source }) => {
|
|
424
|
+
contextStore.set(key, value, source);
|
|
425
|
+
return {
|
|
426
|
+
content: [{ type: "text", text: `Context set: ${key} (source: ${source})` }],
|
|
427
|
+
structuredContent: { key, source, totalEntries: contextStore.size },
|
|
428
|
+
};
|
|
429
|
+
});
|
|
430
|
+
server.registerTool("context_get", {
|
|
431
|
+
description: "Read a value from the shared context store. Returns value + source provenance. Check context before generating redundant thoughts.",
|
|
432
|
+
inputSchema: {
|
|
433
|
+
key: z.string().min(1).describe("Context key to retrieve"),
|
|
434
|
+
},
|
|
435
|
+
annotations: { destructiveHint: true }
|
|
436
|
+
}, async ({ key }) => {
|
|
437
|
+
const entry = contextStore.getWithProvenance(key);
|
|
438
|
+
if (!entry) {
|
|
439
|
+
return { content: [{ type: "text", text: `Context key '${key}' not found` }], isError: true };
|
|
440
|
+
}
|
|
441
|
+
return {
|
|
442
|
+
content: [{ type: "text", text: JSON.stringify(entry, null, 2) }],
|
|
443
|
+
structuredContent: { key, ...entry },
|
|
444
|
+
};
|
|
445
|
+
});
|
|
446
|
+
server.registerTool("context_list", {
|
|
447
|
+
description: "List all keys in the shared context store with their sources. Use to see what knowledge is already available before generating new thoughts.",
|
|
448
|
+
inputSchema: {},
|
|
449
|
+
annotations: { readOnlyHint: true }
|
|
450
|
+
}, async () => {
|
|
451
|
+
const entries = contextStore.list();
|
|
452
|
+
return {
|
|
453
|
+
content: [{ type: "text", text: entries.length > 0 ? JSON.stringify(entries, null, 2) : "Context store is empty" }],
|
|
454
|
+
structuredContent: { entries, count: entries.length },
|
|
455
|
+
};
|
|
456
|
+
});
|
|
457
|
+
// ==========================================
|
|
458
|
+
// v4.0: Reasoning Trace Export
|
|
459
|
+
// ==========================================
|
|
460
|
+
server.registerTool("export_reasoning_trace", {
|
|
461
|
+
description: "Export the current graph's best reasoning path as a structured trace. Compatible with Long CoT format used by DeepSeek-R1 and o3 for RL training and context.",
|
|
462
|
+
inputSchema: {},
|
|
463
|
+
annotations: { readOnlyHint: true }
|
|
464
|
+
}, async () => {
|
|
465
|
+
try {
|
|
466
|
+
const trace = graph.exportReasoningTrace();
|
|
467
|
+
return {
|
|
468
|
+
content: [{ type: "text", text: JSON.stringify(trace, null, 2) }],
|
|
469
|
+
structuredContent: trace,
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
catch (err) {
|
|
473
|
+
return { content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }], isError: true };
|
|
474
|
+
}
|
|
475
|
+
});
|
|
307
476
|
return server;
|
|
308
477
|
}
|
package/dist/types.js
CHANGED
|
@@ -20,13 +20,14 @@ export const DEFAULT_GRAPH_LIMITS = {
|
|
|
20
20
|
* Server configuration constants.
|
|
21
21
|
*/
|
|
22
22
|
export const SERVER_CONFIG = {
|
|
23
|
-
name: "got-mcp",
|
|
24
|
-
version: "
|
|
25
|
-
description: "Graph of Thoughts (GoT) MCP Server — bounded, auditable reasoning",
|
|
23
|
+
name: "@abderraouf-yt/got-mcp",
|
|
24
|
+
version: "4.0.0",
|
|
25
|
+
description: "Graph of Thoughts (GoT) MCP Server — bounded, auditable reasoning with self-reflection and shared context",
|
|
26
26
|
};
|
|
27
27
|
/**
|
|
28
28
|
* Resource URIs used by the server.
|
|
29
29
|
*/
|
|
30
30
|
export const RESOURCE_URIS = {
|
|
31
|
-
currentGraph: "got-mcp://current",
|
|
31
|
+
currentGraph: "@abderraouf-yt/got-mcp://current",
|
|
32
|
+
contextStore: "@abderraouf-yt/got-mcp://context",
|
|
32
33
|
};
|
package/package.json
CHANGED
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@abderraouf-yt/got-mcp",
|
|
3
|
-
"version": "3.2.
|
|
4
|
-
"description": "Graph of Thoughts (GoT) MCP Server — bounded, auditable reasoning for AI agents",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"bin": {
|
|
7
|
-
"got-mcp": "./dist/index.js"
|
|
8
|
-
},
|
|
9
|
-
"publishConfig": {
|
|
10
|
-
"access": "public"
|
|
11
|
-
},
|
|
12
|
-
"type": "module",
|
|
13
|
-
"license": "MIT",
|
|
14
|
-
"author": "Abderraouf-yt",
|
|
15
|
-
"repository": {
|
|
16
|
-
"type": "git",
|
|
17
|
-
"url": "git+https://github.com/Abderraouf-yt/got-mcp.git"
|
|
18
|
-
},
|
|
19
|
-
"homepage": "https://github.com/Abderraouf-yt/got-mcp#readme",
|
|
20
|
-
"bugs": {
|
|
21
|
-
"url": "https://github.com/Abderraouf-yt/got-mcp/issues"
|
|
22
|
-
},
|
|
23
|
-
"keywords": [
|
|
24
|
-
"mcp",
|
|
25
|
-
"model-context-protocol",
|
|
26
|
-
"graph-of-thoughts",
|
|
27
|
-
"got",
|
|
28
|
-
"reasoning",
|
|
29
|
-
"ai-agents",
|
|
30
|
-
"dag",
|
|
31
|
-
"beam-search",
|
|
32
|
-
"weighted-aggregation",
|
|
33
|
-
"thought-graph"
|
|
34
|
-
],
|
|
35
|
-
"engines": {
|
|
36
|
-
"node": ">=20.0.0"
|
|
37
|
-
},
|
|
38
|
-
"files": [
|
|
39
|
-
"dist",
|
|
40
|
-
"README.md",
|
|
41
|
-
"LICENSE"
|
|
42
|
-
],
|
|
43
|
-
"scripts": {
|
|
44
|
-
"build": "tsc",
|
|
45
|
-
"start": "node dist/index.js",
|
|
46
|
-
"dev": "tsc --watch",
|
|
47
|
-
"prepublishOnly": "npm run build"
|
|
48
|
-
},
|
|
49
|
-
"dependencies": {
|
|
50
|
-
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
51
|
-
"cors": "^2.8.5",
|
|
52
|
-
"express": "^4.21.0",
|
|
53
|
-
"zod": "^3.
|
|
54
|
-
},
|
|
55
|
-
"devDependencies": {
|
|
56
|
-
"@types/cors": "^2.8.17",
|
|
57
|
-
"@types/express": "^4.17.21",
|
|
58
|
-
"@types/node": "^20.19.30",
|
|
59
|
-
"typescript": "^5.9.3"
|
|
60
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@abderraouf-yt/got-mcp",
|
|
3
|
+
"version": "3.2.1",
|
|
4
|
+
"description": "Graph of Thoughts (GoT) MCP Server — bounded, auditable reasoning for AI agents",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"got-mcp": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"publishConfig": {
|
|
10
|
+
"access": "public"
|
|
11
|
+
},
|
|
12
|
+
"type": "module",
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"author": "Abderraouf-yt",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/Abderraouf-yt/got-mcp.git"
|
|
18
|
+
},
|
|
19
|
+
"homepage": "https://github.com/Abderraouf-yt/got-mcp#readme",
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/Abderraouf-yt/got-mcp/issues"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"mcp",
|
|
25
|
+
"model-context-protocol",
|
|
26
|
+
"graph-of-thoughts",
|
|
27
|
+
"got",
|
|
28
|
+
"reasoning",
|
|
29
|
+
"ai-agents",
|
|
30
|
+
"dag",
|
|
31
|
+
"beam-search",
|
|
32
|
+
"weighted-aggregation",
|
|
33
|
+
"thought-graph"
|
|
34
|
+
],
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=20.0.0"
|
|
37
|
+
},
|
|
38
|
+
"files": [
|
|
39
|
+
"dist",
|
|
40
|
+
"README.md",
|
|
41
|
+
"LICENSE"
|
|
42
|
+
],
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "tsc",
|
|
45
|
+
"start": "node dist/index.js",
|
|
46
|
+
"dev": "tsc --watch",
|
|
47
|
+
"prepublishOnly": "npm run build"
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
51
|
+
"cors": "^2.8.5",
|
|
52
|
+
"express": "^4.21.0",
|
|
53
|
+
"zod": "^4.3.6"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@types/cors": "^2.8.17",
|
|
57
|
+
"@types/express": "^4.17.21",
|
|
58
|
+
"@types/node": "^20.19.30",
|
|
59
|
+
"typescript": "^5.9.3"
|
|
60
|
+
}
|
|
61
61
|
}
|