@reposkein/mcp 0.3.0 → 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 +76 -1
- package/binary-digests.json +4 -4
- package/dist/SKILL.md +19 -0
- package/dist/cli/agentAdapters.d.ts +68 -0
- package/dist/cli/agentAdapters.js +223 -0
- package/dist/cli/agentAdapters.js.map +1 -0
- package/dist/cli/ansi.d.ts +24 -0
- package/dist/cli/ansi.js +40 -0
- package/dist/cli/ansi.js.map +1 -0
- package/dist/cli/doctor.d.ts +34 -2
- package/dist/cli/doctor.js +51 -6
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/doctorFreshness.d.ts +43 -0
- package/dist/cli/doctorFreshness.js +111 -0
- package/dist/cli/doctorFreshness.js.map +1 -0
- package/dist/cli/doctorSummaries.d.ts +2 -0
- package/dist/cli/doctorSummaries.js +95 -0
- package/dist/cli/doctorSummaries.js.map +1 -0
- package/dist/cli/federatedDiscovery.d.ts +16 -0
- package/dist/cli/federatedDiscovery.js +75 -0
- package/dist/cli/federatedDiscovery.js.map +1 -0
- package/dist/cli/init.d.ts +69 -6
- package/dist/cli/init.js +194 -28
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/sourceSlices.d.ts +17 -0
- package/dist/cli/sourceSlices.js +59 -0
- package/dist/cli/sourceSlices.js.map +1 -0
- package/dist/cli/stats.d.ts +29 -0
- package/dist/cli/stats.js +180 -0
- package/dist/cli/stats.js.map +1 -0
- package/dist/cli/view.d.ts +71 -3
- package/dist/cli/view.js +170 -14
- package/dist/cli/view.js.map +1 -1
- package/dist/index.d.ts +8 -48
- package/dist/index.js +94 -295
- package/dist/index.js.map +1 -1
- package/dist/indexer/fetchBinary.d.ts +14 -0
- package/dist/indexer/fetchBinary.js +81 -40
- package/dist/indexer/fetchBinary.js.map +1 -1
- package/dist/indexer/indexLock.d.ts +13 -0
- package/dist/indexer/indexLock.js +66 -0
- package/dist/indexer/indexLock.js.map +1 -0
- package/dist/indexer/runIndexer.d.ts +8 -2
- package/dist/indexer/runIndexer.js +20 -4
- package/dist/indexer/runIndexer.js.map +1 -1
- package/dist/serve/serve.d.ts +95 -0
- package/dist/serve/serve.js +581 -0
- package/dist/serve/serve.js.map +1 -0
- package/dist/serve/tokens.d.ts +49 -0
- package/dist/serve/tokens.js +108 -0
- package/dist/serve/tokens.js.map +1 -0
- package/dist/serve/watch.d.ts +73 -0
- package/dist/serve/watch.js +135 -0
- package/dist/serve/watch.js.map +1 -0
- package/dist/server/createMcpServer.d.ts +129 -0
- package/dist/server/createMcpServer.js +464 -0
- package/dist/server/createMcpServer.js.map +1 -0
- package/dist/store/JsonlGraphStore.d.ts +18 -4
- package/dist/store/JsonlGraphStore.js +61 -19
- package/dist/store/JsonlGraphStore.js.map +1 -1
- package/dist/store/decisions.d.ts +20 -2
- package/dist/store/decisions.js +35 -2
- package/dist/store/decisions.js.map +1 -1
- package/dist/store/indexedAt.d.ts +18 -0
- package/dist/store/indexedAt.js +56 -0
- package/dist/store/indexedAt.js.map +1 -0
- package/dist/store/instrumentTool.d.ts +40 -0
- package/dist/store/instrumentTool.js +82 -0
- package/dist/store/instrumentTool.js.map +1 -0
- package/dist/store/repoContextCache.d.ts +15 -0
- package/dist/store/repoContextCache.js +26 -0
- package/dist/store/repoContextCache.js.map +1 -0
- package/dist/store/repoSession.d.ts +63 -0
- package/dist/store/repoSession.js +123 -0
- package/dist/store/repoSession.js.map +1 -0
- package/dist/store/resolveRepoPath.d.ts +31 -0
- package/dist/store/resolveRepoPath.js +85 -0
- package/dist/store/resolveRepoPath.js.map +1 -0
- package/dist/store/sessionLog.d.ts +98 -0
- package/dist/store/sessionLog.js +216 -0
- package/dist/store/sessionLog.js.map +1 -0
- package/dist/store/sessionStats.d.ts +55 -0
- package/dist/store/sessionStats.js +140 -0
- package/dist/store/sessionStats.js.map +1 -0
- package/dist/store/sidecar.d.ts +39 -3
- package/dist/store/sidecar.js +89 -5
- package/dist/store/sidecar.js.map +1 -1
- package/dist/store/summaryShards.d.ts +117 -0
- package/dist/store/summaryShards.js +291 -0
- package/dist/store/summaryShards.js.map +1 -0
- package/dist/store/teamConfig.d.ts +17 -0
- package/dist/store/teamConfig.js +55 -0
- package/dist/store/teamConfig.js.map +1 -0
- package/dist/tools/indexerTools.d.ts +14 -2
- package/dist/tools/indexerTools.js +17 -5
- package/dist/tools/indexerTools.js.map +1 -1
- package/dist/tools/recordDecision.d.ts +3 -0
- package/dist/tools/recordDecision.js +7 -2
- package/dist/tools/recordDecision.js.map +1 -1
- package/dist/tools/writeSemanticSummary.d.ts +4 -1
- package/dist/tools/writeSemanticSummary.js +5 -2
- package/dist/tools/writeSemanticSummary.js.map +1 -1
- package/dist/viz/assets/{graph.worker-CC7BeE-8.js → graph.worker-DkH6-lMU.js} +1 -1
- package/dist/viz/assets/index-BnqIVYFE.css +1 -0
- package/dist/viz/assets/index-IhtszTp0.js +5 -0
- package/dist/viz/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
- package/dist/viz/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
- package/dist/viz/assets/jetbrains-mono-latin-700-normal-BYuf6tUa.woff2 +0 -0
- package/dist/viz/assets/r3f-Bn9htB92.js +336 -0
- package/dist/viz/assets/tanstack-CSzx6NDA.js +62 -0
- package/dist/viz/assets/three-Cpu5RUEM.js +4116 -0
- package/dist/viz/index.html +5 -4
- package/package.json +5 -4
- package/dist/viz/assets/index-C_8UkiJ8.js +0 -9
- package/dist/viz/assets/r3f-Cku1OhB-.js +0 -277
- package/dist/viz/assets/tanstack-DyXcNRWk.js +0 -77
- package/dist/viz/assets/three-Z8XaLGmf.js +0 -3839
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { Neo4jGraphStore } from "../store/Neo4jGraphStore.js";
|
|
6
|
+
import { UnconfiguredStore } from "../store/UnconfiguredStore.js";
|
|
7
|
+
import { JsonlGraphStore } from "../store/JsonlGraphStore.js";
|
|
8
|
+
import { makeReadCypher } from "../tools/readCypher.js";
|
|
9
|
+
import { makeGetContextProfile } from "../tools/getContextProfile.js";
|
|
10
|
+
import { makeWriteSemanticSummary } from "../tools/writeSemanticSummary.js";
|
|
11
|
+
import { makeInitCpgSkeleton, makeReindexFile } from "../tools/indexerTools.js";
|
|
12
|
+
import { makeSemanticFind } from "../tools/semanticFind.js";
|
|
13
|
+
import { makeTemporalContext } from "../tools/temporalContext.js";
|
|
14
|
+
import { makeImpact } from "../tools/impact.js";
|
|
15
|
+
import { makeRecordDecision } from "../tools/recordDecision.js";
|
|
16
|
+
import { makeSetDecisionStatus } from "../tools/setDecisionStatus.js";
|
|
17
|
+
import { makeReaffirmDecision } from "../tools/reaffirmDecision.js";
|
|
18
|
+
import { makeListDecisions } from "../tools/listDecisions.js";
|
|
19
|
+
import { makeGetDecision } from "../tools/getDecision.js";
|
|
20
|
+
import { resolveRepoId } from "../store/repoId.js";
|
|
21
|
+
import { RepoSession } from "../store/repoSession.js";
|
|
22
|
+
import { makeCache } from "../store/repoContextCache.js";
|
|
23
|
+
import { ensureGraph } from "../indexer/ensureGraph.js";
|
|
24
|
+
import { ensureIndexerBinary } from "../indexer/fetchBinary.js";
|
|
25
|
+
import { spawnIndexer } from "../indexer/runIndexer.js";
|
|
26
|
+
import { SessionLogger, resolveSessionId } from "../store/sessionLog.js";
|
|
27
|
+
import { createToolLogger } from "../store/instrumentTool.js";
|
|
28
|
+
/** Selects the store backend.
|
|
29
|
+
* REPOSKEIN_STORE = "jsonl" | "neo4j" | "auto" (default "auto").
|
|
30
|
+
* - auto: JSONL if <repoPath>/.reposkein/nodes.jsonl exists, else Neo4j if
|
|
31
|
+
* NEO4J_PASSWORD is set, else Unconfigured.
|
|
32
|
+
* - jsonl: JSONL if available, else Unconfigured.
|
|
33
|
+
* - neo4j: Neo4j if configured, else Unconfigured.
|
|
34
|
+
*
|
|
35
|
+
* `agent` names the writer for sidecar selection (one summaries file per
|
|
36
|
+
* agent, see store/sidecar.ts); undefined keeps the REPOSKEIN_AGENT default. */
|
|
37
|
+
export function buildStore(repoPath, repoId, agent) {
|
|
38
|
+
const mode = (process.env.REPOSKEIN_STORE ?? "auto").toLowerCase();
|
|
39
|
+
const jsonlReady = !!repoPath && !!repoId && existsSync(join(repoPath, ".reposkein", "nodes.jsonl"));
|
|
40
|
+
const neo4j = () => {
|
|
41
|
+
try {
|
|
42
|
+
return Neo4jGraphStore.fromEnv();
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return new UnconfiguredStore();
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
if (mode === "jsonl") {
|
|
49
|
+
return jsonlReady ? new JsonlGraphStore(repoPath, repoId, agent) : new UnconfiguredStore();
|
|
50
|
+
}
|
|
51
|
+
if (mode === "neo4j") {
|
|
52
|
+
return neo4j();
|
|
53
|
+
}
|
|
54
|
+
// auto
|
|
55
|
+
if (jsonlReady)
|
|
56
|
+
return new JsonlGraphStore(repoPath, repoId, agent);
|
|
57
|
+
return neo4j();
|
|
58
|
+
}
|
|
59
|
+
/** Structured, actionable message for repo-scoped tool calls when no repo
|
|
60
|
+
* resolved (see `resolveRepoPath`). Names the discovered candidates when
|
|
61
|
+
* resolution failed due to workspace-mode ambiguity, and points at
|
|
62
|
+
* `list_repos` / `select_repo` so the agent can pick one instead of
|
|
63
|
+
* abandoning the tools. */
|
|
64
|
+
export function repoRequiredMessage(resolution) {
|
|
65
|
+
if (resolution.candidates && resolution.candidates.length > 0) {
|
|
66
|
+
return (`Multiple RepoSkein repos were found under ${process.cwd()} and none is selected: ` +
|
|
67
|
+
resolution.candidates.join(", ") +
|
|
68
|
+
". Call list_repos to see them, then select_repo with one of its `path` or `name` " +
|
|
69
|
+
"values (or set REPOSKEIN_REPO_PATH) to use this tool.");
|
|
70
|
+
}
|
|
71
|
+
return ("No RepoSkein repo found (checked the current directory, its ancestors, and its " +
|
|
72
|
+
"immediate subdirectories for .reposkein/). Run `reposkein-mcp init` in the repository " +
|
|
73
|
+
"you want to work with, call list_repos to check what was discovered, or set " +
|
|
74
|
+
"REPOSKEIN_REPO_PATH to its root.");
|
|
75
|
+
}
|
|
76
|
+
/** A repo resolved but has no committed `meta.json` (never indexed). */
|
|
77
|
+
export function repoUnindexedMessage(repoPath) {
|
|
78
|
+
if (existsSync(join(repoPath, ".reposkein"))) {
|
|
79
|
+
return (`Found .reposkein/ at ${repoPath}, but it has no meta.json (not indexed yet). ` +
|
|
80
|
+
`Run \`reposkein-mcp index ${repoPath}\` (or the init_cpg_skeleton tool) to build it, ` +
|
|
81
|
+
"then retry this call.");
|
|
82
|
+
}
|
|
83
|
+
return (`${repoPath} has no .reposkein/ directory. Run \`reposkein-mcp init ${repoPath}\` there, ` +
|
|
84
|
+
"or point REPOSKEIN_REPO_PATH / select_repo at a repo that already has one.");
|
|
85
|
+
}
|
|
86
|
+
/** Whether a graph is available to READ at `repoPath` without building one.
|
|
87
|
+
*
|
|
88
|
+
* Mirrors `buildStore`'s backend choice exactly (same env, same order), so
|
|
89
|
+
* "we can serve reads" and "we picked a real store" can never disagree:
|
|
90
|
+
* explicit neo4j mode trusts the DB, otherwise the committed-derived JSONL
|
|
91
|
+
* decides, and `auto` falls back to Neo4j when a password is configured. */
|
|
92
|
+
export function graphAvailable(repoPath, env = process.env) {
|
|
93
|
+
const mode = (env.REPOSKEIN_STORE ?? "auto").toLowerCase();
|
|
94
|
+
if (mode === "neo4j")
|
|
95
|
+
return true;
|
|
96
|
+
if (existsSync(join(repoPath, ".reposkein", "nodes.jsonl")))
|
|
97
|
+
return true;
|
|
98
|
+
return mode === "auto" && !!env.NEO4J_PASSWORD;
|
|
99
|
+
}
|
|
100
|
+
/** A read-only connection resolved a repo whose derived graph isn't built.
|
|
101
|
+
*
|
|
102
|
+
* Building it means spawning the indexer and writing `.reposkein/*.jsonl` —
|
|
103
|
+
* a write, and the LAST write a read-only token could still trigger, since
|
|
104
|
+
* `ensureGraph` used to run unconditionally on first touch of any repo. So a
|
|
105
|
+
* read-only caller gets this instead: an explanation and the exact command
|
|
106
|
+
* for whoever does hold write access, with nothing changed on disk. */
|
|
107
|
+
export function readOnlyUnindexedMessage(repoPath) {
|
|
108
|
+
return (`${repoPath} has no built graph (.reposkein/nodes.jsonl is derived from the working tree ` +
|
|
109
|
+
"and git-ignored, so a fresh clone has none), and this connection is read-only — the " +
|
|
110
|
+
"server will not build one for it. Ask the operator to run " +
|
|
111
|
+
`\`reposkein-mcp index ${repoPath}\`, or use a write-capable token. Nothing was changed.`);
|
|
112
|
+
}
|
|
113
|
+
/** Exported for schema tests. */
|
|
114
|
+
export const getContextProfileInputSchema = {
|
|
115
|
+
node_id: z.string().optional(),
|
|
116
|
+
file_path: z.string().optional(),
|
|
117
|
+
name: z.string().optional(),
|
|
118
|
+
hops: z.number().int().min(1).max(2).optional(),
|
|
119
|
+
federated: z.boolean().optional(),
|
|
120
|
+
};
|
|
121
|
+
/** Exported for schema tests. */
|
|
122
|
+
export const recordDecisionInputSchema = {
|
|
123
|
+
title: z.string(),
|
|
124
|
+
context: z.string(),
|
|
125
|
+
decision: z.string(),
|
|
126
|
+
consequences: z.string().optional(),
|
|
127
|
+
alternatives: z.string().optional(),
|
|
128
|
+
status: z.enum(["proposed", "accepted"]).optional(),
|
|
129
|
+
anchor_node_ids: z.array(z.string()).max(20).optional(),
|
|
130
|
+
anchor_paths: z.array(z.string()).max(20).optional(),
|
|
131
|
+
supersedes: z.array(z.string()).max(5).optional(),
|
|
132
|
+
};
|
|
133
|
+
export const setDecisionStatusInputSchema = {
|
|
134
|
+
decision_id: z.string(),
|
|
135
|
+
status: z.enum(["accepted", "rejected", "deprecated"]),
|
|
136
|
+
};
|
|
137
|
+
export const reaffirmDecisionInputSchema = {
|
|
138
|
+
decision_id: z.string(),
|
|
139
|
+
};
|
|
140
|
+
export const listDecisionsInputSchema = {
|
|
141
|
+
status: z.enum(["proposed", "accepted", "rejected", "deprecated", "superseded"]).optional(),
|
|
142
|
+
anchor: z.string().optional(),
|
|
143
|
+
q: z.string().optional(),
|
|
144
|
+
limit: z.number().int().min(1).max(50).optional(),
|
|
145
|
+
};
|
|
146
|
+
export const getDecisionInputSchema = {
|
|
147
|
+
decision_id: z.string(),
|
|
148
|
+
};
|
|
149
|
+
/** The tools that MUTATE the repo (sidecar prose, decision records, the
|
|
150
|
+
* derived graph). Gated behind the `write` capability in `serve --http`
|
|
151
|
+
* (REP-17); always available over stdio, where the caller already owns the
|
|
152
|
+
* checkout.
|
|
153
|
+
*
|
|
154
|
+
* `select_repo` is deliberately NOT here: it mutates only this connection's
|
|
155
|
+
* own `RepoSession`, which since REP-17 is per-connection state, so a
|
|
156
|
+
* read-only caller pointing itself at a different discovered repo affects
|
|
157
|
+
* nobody else. */
|
|
158
|
+
export const WRITE_TOOLS = [
|
|
159
|
+
"write_semantic_summary",
|
|
160
|
+
"record_decision",
|
|
161
|
+
"set_decision_status",
|
|
162
|
+
"reaffirm_decision",
|
|
163
|
+
"reindex_file",
|
|
164
|
+
"init_cpg_skeleton",
|
|
165
|
+
];
|
|
166
|
+
/** Builds ONE MCP server with its own session state.
|
|
167
|
+
*
|
|
168
|
+
* Everything a caller can move — the active repo (`select_repo`), the
|
|
169
|
+
* per-repoPath store/context cache, the tool-call logger — lives in this
|
|
170
|
+
* closure, so two connections into the same process cannot see each other's
|
|
171
|
+
* selection. That is what makes `serve --http` (REP-17) safe; over stdio
|
|
172
|
+
* there is exactly one of these per process, which is byte-for-byte the
|
|
173
|
+
* behaviour that existed before the extraction. */
|
|
174
|
+
export function createMcpServer(opts) {
|
|
175
|
+
const caps = opts.capabilities ?? { write: true };
|
|
176
|
+
const identity = opts.identity;
|
|
177
|
+
const ensureGraphFn = opts.ensureGraph ?? ensureGraph;
|
|
178
|
+
const session = new RepoSession({ cwd: opts.cwd, envRepoPath: opts.envRepoPath });
|
|
179
|
+
const sessionLogger = new SessionLogger(opts.sessionId ?? resolveSessionId(process.env));
|
|
180
|
+
const { withLog, cachedResolve } = createToolLogger(session, sessionLogger);
|
|
181
|
+
const getRepoContext = makeCache(async (path) => {
|
|
182
|
+
const id = resolveRepoId(path, process.env.REPOSKEIN_REPO_ID);
|
|
183
|
+
// REP-17: `ensureGraph` SPAWNS THE INDEXER and writes `.reposkein/*.jsonl`.
|
|
184
|
+
// That is a write, so a read-only connection must not reach it — it was
|
|
185
|
+
// the one mutation a read-only token could still cause, just by naming
|
|
186
|
+
// an unbuilt repo. Read-only callers get `readOnlyUnindexedMessage`
|
|
187
|
+
// below instead, and the repo is left exactly as it was found.
|
|
188
|
+
if (caps.write) {
|
|
189
|
+
await ensureGraphFn(path, id, {
|
|
190
|
+
mode: (process.env.REPOSKEIN_STORE ?? "auto").toLowerCase(),
|
|
191
|
+
neo4jConfigured: !!process.env.NEO4J_PASSWORD,
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
return { repoId: id, store: buildStore(path, id, identity), graphReady: graphAvailable(path) };
|
|
195
|
+
},
|
|
196
|
+
// Write connections: cache exactly as before (repoId resolved). Read-only
|
|
197
|
+
// connections additionally refuse to cache a graph-less resolution, so a
|
|
198
|
+
// graph built out of band (by the operator, or by the HEAD watcher) is
|
|
199
|
+
// picked up on the next call instead of sticking for the connection's life
|
|
200
|
+
// — they have no way to fix it themselves.
|
|
201
|
+
(ctx) => !!ctx.repoId && (caps.write || ctx.graphReady));
|
|
202
|
+
/** Resolves the session's current repo for a repo-scoped tool call.
|
|
203
|
+
* Re-evaluated on every call (not once at startup) so `select_repo`
|
|
204
|
+
* actually takes effect for calls made after it. Uses `cachedResolve`
|
|
205
|
+
* (not `session.resolve()` directly) so this and the REP-20 logging
|
|
206
|
+
* wrapper share one filesystem walk per call. */
|
|
207
|
+
async function resolveActiveRepo() {
|
|
208
|
+
const resolution = cachedResolve();
|
|
209
|
+
if (!resolution.repoPath)
|
|
210
|
+
return { ok: false, message: repoRequiredMessage(resolution) };
|
|
211
|
+
const ctx = await getRepoContext(resolution.repoPath);
|
|
212
|
+
if (!ctx.repoId)
|
|
213
|
+
return { ok: false, message: repoUnindexedMessage(resolution.repoPath) };
|
|
214
|
+
if (!ctx.graphReady) {
|
|
215
|
+
// Only reachable on a read-only connection: a write one already tried to
|
|
216
|
+
// build above, and if THAT failed ensureGraph explained why on stderr and
|
|
217
|
+
// the store degrades to Unconfigured (whose own error names the fix).
|
|
218
|
+
if (!caps.write)
|
|
219
|
+
return { ok: false, message: readOnlyUnindexedMessage(resolution.repoPath) };
|
|
220
|
+
}
|
|
221
|
+
return { ok: true, repoPath: resolution.repoPath, repoId: ctx.repoId, store: ctx.store };
|
|
222
|
+
}
|
|
223
|
+
const errResult = (message) => ({
|
|
224
|
+
content: [{ type: "text", text: message }],
|
|
225
|
+
isError: true,
|
|
226
|
+
});
|
|
227
|
+
/** The refusal a read-only connection gets from a mutating tool. Structured
|
|
228
|
+
* (JSON with a stable `error` code) so an agent can branch on it instead of
|
|
229
|
+
* parsing prose, and it names the identity so an operator reading the
|
|
230
|
+
* transcript knows WHICH token was short of capability. Never echoes the
|
|
231
|
+
* token value. */
|
|
232
|
+
const capabilityRefusal = (tool) => ({
|
|
233
|
+
content: [
|
|
234
|
+
{
|
|
235
|
+
type: "text",
|
|
236
|
+
text: JSON.stringify({
|
|
237
|
+
error: "write_capability_required",
|
|
238
|
+
tool,
|
|
239
|
+
required_capability: "write",
|
|
240
|
+
identity: identity ?? null,
|
|
241
|
+
detail: `This connection is read-only, so ${tool} was refused before it could change anything. ` +
|
|
242
|
+
"Ask the operator for a token declared with the `write` capability " +
|
|
243
|
+
"(`name:token:write`), or run the stdio server against your own checkout.",
|
|
244
|
+
}),
|
|
245
|
+
},
|
|
246
|
+
],
|
|
247
|
+
isError: true,
|
|
248
|
+
});
|
|
249
|
+
/** Registration-time note appended to a mutating tool's description on a
|
|
250
|
+
* read-only connection, so `tools/list` is honest about what will happen. */
|
|
251
|
+
const readOnlyNote = " NOTE: this connection's token is read-only — calling this tool returns a " +
|
|
252
|
+
"`write_capability_required` error and changes nothing.";
|
|
253
|
+
const describe = (text, tool) => caps.write || !WRITE_TOOLS.includes(tool) ? text : text + readOnlyNote;
|
|
254
|
+
/** `withLog` plus the write-capability gate. The refusal is logged like any
|
|
255
|
+
* other failed call (ok:false), which is what an operator wants to see. */
|
|
256
|
+
function withWrite(name, cb) {
|
|
257
|
+
return withLog(name, async (args) => {
|
|
258
|
+
if (!caps.write)
|
|
259
|
+
return capabilityRefusal(name);
|
|
260
|
+
return cb(args);
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
const server = new McpServer({ name: "@reposkein/mcp", version: "0.0.0" });
|
|
264
|
+
server.registerTool("list_repos", {
|
|
265
|
+
title: "List discovered repos",
|
|
266
|
+
description: "Enumerate the RepoSkein repos discovered from the server's working directory (walk-up: the nearest ancestor with .reposkein/; walk-down/workspace mode: subdirectories, when no ancestor has one). Single-repo setups return exactly one entry. In workspace mode (multiple sibling repos, no default selected), use this to see the candidates, then `select_repo` one before calling other repo-scoped tools.",
|
|
267
|
+
inputSchema: {},
|
|
268
|
+
}, withLog("list_repos", async () => {
|
|
269
|
+
const repos = session.list();
|
|
270
|
+
return {
|
|
271
|
+
content: [
|
|
272
|
+
{
|
|
273
|
+
type: "text",
|
|
274
|
+
text: JSON.stringify({
|
|
275
|
+
mode: repos.length > 1 ? "workspace" : "single",
|
|
276
|
+
repos,
|
|
277
|
+
}),
|
|
278
|
+
},
|
|
279
|
+
],
|
|
280
|
+
};
|
|
281
|
+
}));
|
|
282
|
+
server.registerTool("select_repo", {
|
|
283
|
+
title: "Select the active repo",
|
|
284
|
+
description: "Set the session-active repo for all subsequent repo-scoped tool calls (get_context_profile, semantic_find, impact, decisions, etc.) — the fix for workspace-mode ambiguity (list_repos returned more than one candidate). Pass a `repo` value from list_repos: its `path` or its `name`. Overrides REPOSKEIN_REPO_PATH and any earlier select_repo call for the rest of this connection; stays in effect until called again.",
|
|
285
|
+
inputSchema: { repo: z.string() },
|
|
286
|
+
}, withLog("select_repo", async (args) => {
|
|
287
|
+
const result = session.select(args.repo);
|
|
288
|
+
if (!result.ok)
|
|
289
|
+
return errResult(result.error);
|
|
290
|
+
return {
|
|
291
|
+
content: [{ type: "text", text: JSON.stringify({ ok: true, selected: result.repo }) }],
|
|
292
|
+
};
|
|
293
|
+
}));
|
|
294
|
+
server.registerTool("read_cypher", {
|
|
295
|
+
title: "Read-only Cypher query",
|
|
296
|
+
description: "Run a read-only Cypher query against the RepoSkein graph. Writes are rejected. Filter by `n.repo_id = $repo_id` (or `n.repo_id IN $repo_ids`); pass `federated: true` to span this repo and its nested repos via `$repo_ids`. Results are capped (200 rows / 64KB).",
|
|
297
|
+
inputSchema: {
|
|
298
|
+
query: z.string(),
|
|
299
|
+
params: z.record(z.string(), z.unknown()).optional(),
|
|
300
|
+
federated: z.boolean().optional(),
|
|
301
|
+
},
|
|
302
|
+
}, withLog("read_cypher", async (args) => {
|
|
303
|
+
// Cypher is store-level, not repo-scoped: a Neo4j-backed server answers
|
|
304
|
+
// even with no local checkout resolved.
|
|
305
|
+
const resolution = cachedResolve();
|
|
306
|
+
const ctx = resolution.repoPath
|
|
307
|
+
? await getRepoContext(resolution.repoPath)
|
|
308
|
+
: { repoId: undefined, store: buildStore(undefined, undefined, identity) };
|
|
309
|
+
return makeReadCypher(ctx.store, ctx.repoId)(args);
|
|
310
|
+
}));
|
|
311
|
+
server.registerTool("get_context_profile", {
|
|
312
|
+
title: "Get context profile",
|
|
313
|
+
description: "Resolve a function/class (by node_id, file_path+name, or name) and return its caller/callee neighborhood (hops 1-2) with inlined prose and an enrichment_needed list. Never guesses — returns candidates if a name is ambiguous. Pass federated:true to resolve and traverse across nested repos.",
|
|
314
|
+
inputSchema: getContextProfileInputSchema,
|
|
315
|
+
}, withLog("get_context_profile", async (args) => {
|
|
316
|
+
const active = await resolveActiveRepo();
|
|
317
|
+
if (!active.ok)
|
|
318
|
+
return errResult(active.message);
|
|
319
|
+
return makeGetContextProfile(active.store, active.repoId, active.repoPath)(args);
|
|
320
|
+
}));
|
|
321
|
+
server.registerTool("write_semantic_summary", {
|
|
322
|
+
title: "Write semantic summary",
|
|
323
|
+
description: describe("Attach a 1-3 sentence plain-text business-logic summary to a node, stamped with its current content hash for staleness tracking. Plain text only (no markdown links or code fences), max 1000 chars.", "write_semantic_summary"),
|
|
324
|
+
inputSchema: {
|
|
325
|
+
node_id: z.string(),
|
|
326
|
+
summary: z.string(),
|
|
327
|
+
model: z.string().optional(),
|
|
328
|
+
},
|
|
329
|
+
}, withWrite("write_semantic_summary", async (args) => {
|
|
330
|
+
const active = await resolveActiveRepo();
|
|
331
|
+
if (!active.ok)
|
|
332
|
+
return errResult(active.message);
|
|
333
|
+
return makeWriteSemanticSummary(active.store, active.repoId, identity)(args);
|
|
334
|
+
}));
|
|
335
|
+
server.registerTool("init_cpg_skeleton", {
|
|
336
|
+
title: "Build the code graph",
|
|
337
|
+
description: describe("Index the repository with the native indexer and load it into the graph database. Run once on a fresh repo (or to rebuild). Returns node/edge counts.", "init_cpg_skeleton"),
|
|
338
|
+
inputSchema: {
|
|
339
|
+
path: z.string().optional(),
|
|
340
|
+
full: z.boolean().optional(),
|
|
341
|
+
},
|
|
342
|
+
}, withWrite("init_cpg_skeleton", async (args) => {
|
|
343
|
+
const active = await resolveActiveRepo();
|
|
344
|
+
if (!active.ok)
|
|
345
|
+
return errResult(active.message);
|
|
346
|
+
return makeInitCpgSkeleton(active.repoId, active.repoPath)(args);
|
|
347
|
+
}));
|
|
348
|
+
server.registerTool("reindex_file", {
|
|
349
|
+
title: "Reindex after editing",
|
|
350
|
+
description: describe("Refresh the graph after editing a source file (pass its path). v1 performs a full reindex.", "reindex_file"),
|
|
351
|
+
inputSchema: { path: z.string() },
|
|
352
|
+
}, withWrite("reindex_file", async (args) => {
|
|
353
|
+
const active = await resolveActiveRepo();
|
|
354
|
+
if (!active.ok)
|
|
355
|
+
return errResult(active.message);
|
|
356
|
+
return makeReindexFile(active.repoId, active.repoPath)(args);
|
|
357
|
+
}));
|
|
358
|
+
server.registerTool("semantic_find", {
|
|
359
|
+
title: "Find code by meaning",
|
|
360
|
+
description: "Rank functions/classes by a lexical match over their qualified names, signatures, and agent-written summaries — the entry point to seed get_context_profile when you don't know where to start. Returns ranked node_ids. Architecture decisions are part of the corpus: \"why\" questions (why don't we X, what did we decide about Y) surface Decision rows — follow up with get_decision. federated:true spans nested repos.",
|
|
361
|
+
inputSchema: {
|
|
362
|
+
query: z.string(),
|
|
363
|
+
limit: z.number().int().min(1).max(25).optional(),
|
|
364
|
+
kind: z.enum(["Function", "Class", "Interface", "Enum", "Decision"]).optional(),
|
|
365
|
+
federated: z.boolean().optional(),
|
|
366
|
+
},
|
|
367
|
+
}, withLog("semantic_find", async (args) => {
|
|
368
|
+
const active = await resolveActiveRepo();
|
|
369
|
+
if (!active.ok)
|
|
370
|
+
return errResult(active.message);
|
|
371
|
+
return makeSemanticFind(active.store, active.repoId, active.repoPath, undefined, {
|
|
372
|
+
decisions: true,
|
|
373
|
+
})(args);
|
|
374
|
+
}));
|
|
375
|
+
server.registerTool("get_temporal_context", {
|
|
376
|
+
title: "Git temporal context",
|
|
377
|
+
description: "Git-derived signals for a file: how often/recently it changes, who owns it, and which files most often change together with it (co-change) — answers \"what else should I touch?\". Advisory (derived from git history, not the committed graph). Before a cross-cutting change, use this to find files that historically change together.",
|
|
378
|
+
inputSchema: { path: z.string() },
|
|
379
|
+
}, withLog("get_temporal_context", async (args) => {
|
|
380
|
+
// Git-derived, not graph-derived: needs a checkout, not an index.
|
|
381
|
+
const resolution = cachedResolve();
|
|
382
|
+
if (!resolution.repoPath)
|
|
383
|
+
return errResult(repoRequiredMessage(resolution));
|
|
384
|
+
return makeTemporalContext(resolution.repoPath)(args);
|
|
385
|
+
}));
|
|
386
|
+
server.registerTool("impact", {
|
|
387
|
+
title: "Change impact + covering tests",
|
|
388
|
+
description: "Given a function/class, return its transitive callers (what could break if you change it) split into impacted code vs the tests that cover it (what to run). Resolves by node_id, file_path+name, or name. federated:true spans nested repos.",
|
|
389
|
+
inputSchema: {
|
|
390
|
+
node_id: z.string().optional(),
|
|
391
|
+
file_path: z.string().optional(),
|
|
392
|
+
name: z.string().optional(),
|
|
393
|
+
depth: z.number().int().min(1).max(5).optional(),
|
|
394
|
+
federated: z.boolean().optional(),
|
|
395
|
+
},
|
|
396
|
+
}, withLog("impact", async (args) => {
|
|
397
|
+
const active = await resolveActiveRepo();
|
|
398
|
+
if (!active.ok)
|
|
399
|
+
return errResult(active.message);
|
|
400
|
+
return makeImpact(active.store, active.repoId, active.repoPath)(args);
|
|
401
|
+
}));
|
|
402
|
+
// --- Architecture Decision Records (ADRs) ---
|
|
403
|
+
server.registerTool("record_decision", {
|
|
404
|
+
title: "Record an architecture decision",
|
|
405
|
+
description: describe("Record an Architecture Decision Record (ADR): why a significant design choice was made, anchored to the graph nodes and paths it governs. Use for decisions that affect structure, dependencies, interfaces, or construction techniques — not renames, formatting, or routine fixes. Records land as status \"proposed\" (the user ratifies via set_decision_status); pass supersedes to replace an earlier decision. Plain text only; anchors are stamped with the current content hash for drift tracking.", "record_decision"),
|
|
406
|
+
inputSchema: recordDecisionInputSchema,
|
|
407
|
+
}, withWrite("record_decision", async (args) => {
|
|
408
|
+
const active = await resolveActiveRepo();
|
|
409
|
+
if (!active.ok)
|
|
410
|
+
return errResult(active.message);
|
|
411
|
+
// Refresh the graph before stamping anchors so a decision recorded
|
|
412
|
+
// right after an edit isn't born stale. Best-effort inside the tool.
|
|
413
|
+
const decisionRefresh = async () => {
|
|
414
|
+
const bin = await ensureIndexerBinary();
|
|
415
|
+
await spawnIndexer(bin, ["index", "--json", "--repo-id", active.repoId, active.repoPath]);
|
|
416
|
+
};
|
|
417
|
+
return makeRecordDecision(active.store, active.repoId, active.repoPath, {
|
|
418
|
+
refresh: decisionRefresh,
|
|
419
|
+
...(identity !== undefined ? { decidedBy: identity } : {}),
|
|
420
|
+
})(args);
|
|
421
|
+
}));
|
|
422
|
+
server.registerTool("set_decision_status", {
|
|
423
|
+
title: "Set decision status",
|
|
424
|
+
description: describe("Change an ADR's lifecycle status. Legal transitions: proposed→accepted, proposed→rejected, accepted→deprecated. \"superseded\" only happens via record_decision's supersedes. Only ratify to accepted when the user has confirmed the decision.", "set_decision_status"),
|
|
425
|
+
inputSchema: setDecisionStatusInputSchema,
|
|
426
|
+
}, withWrite("set_decision_status", async (args) => {
|
|
427
|
+
const active = await resolveActiveRepo();
|
|
428
|
+
if (!active.ok)
|
|
429
|
+
return errResult(active.message);
|
|
430
|
+
return makeSetDecisionStatus(active.repoPath)(args);
|
|
431
|
+
}));
|
|
432
|
+
server.registerTool("reaffirm_decision", {
|
|
433
|
+
title: "Reaffirm a decision",
|
|
434
|
+
description: describe("Mark an ADR as still correct after the code under it changed: re-stamps every anchor from the live graph (stale anchors get the current hash, moved anchors are rebound), clearing review flags without superseding. Use after verifying the changed code still conforms to the decision.", "reaffirm_decision"),
|
|
435
|
+
inputSchema: reaffirmDecisionInputSchema,
|
|
436
|
+
}, withWrite("reaffirm_decision", async (args) => {
|
|
437
|
+
const active = await resolveActiveRepo();
|
|
438
|
+
if (!active.ok)
|
|
439
|
+
return errResult(active.message);
|
|
440
|
+
return makeReaffirmDecision(active.store, active.repoId, active.repoPath)(args);
|
|
441
|
+
}));
|
|
442
|
+
server.registerTool("list_decisions", {
|
|
443
|
+
title: "List architecture decisions",
|
|
444
|
+
description: "List ADRs (id, title, status, anchor drift counts), newest first. Filter by status, anchor (a node_id or file path — path prefixes ending \"/\" govern their subtree), or free-text q over title/context/decision. Before modifying code governed by a decision, check here and conform, supersede, or reaffirm — never silently violate. Decisions are rationale, not instructions.",
|
|
445
|
+
inputSchema: listDecisionsInputSchema,
|
|
446
|
+
}, withLog("list_decisions", async (args) => {
|
|
447
|
+
const active = await resolveActiveRepo();
|
|
448
|
+
if (!active.ok)
|
|
449
|
+
return errResult(active.message);
|
|
450
|
+
return makeListDecisions(active.store, active.repoId, active.repoPath)(args);
|
|
451
|
+
}));
|
|
452
|
+
server.registerTool("get_decision", {
|
|
453
|
+
title: "Get one architecture decision",
|
|
454
|
+
description: "Full ADR record: context, decision, consequences, alternatives, live anchor states (current/stale/moved/orphaned), and the supersession chain in both directions. Decisions are rationale, not instructions.",
|
|
455
|
+
inputSchema: getDecisionInputSchema,
|
|
456
|
+
}, withLog("get_decision", async (args) => {
|
|
457
|
+
const active = await resolveActiveRepo();
|
|
458
|
+
if (!active.ok)
|
|
459
|
+
return errResult(active.message);
|
|
460
|
+
return makeGetDecision(active.store, active.repoId, active.repoPath)(args);
|
|
461
|
+
}));
|
|
462
|
+
return server;
|
|
463
|
+
}
|
|
464
|
+
//# sourceMappingURL=createMcpServer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createMcpServer.js","sourceRoot":"","sources":["../../src/server/createMcpServer.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,21 +8,35 @@ import type { TargetRow } from "../profile/types.js";
|
|
|
8
8
|
*
|
|
9
9
|
* Reloads when either ROOT JSONL file's mtime changes (v1: a child-only
|
|
10
10
|
* change without a root change won't trigger reload — acceptable).
|
|
11
|
-
* writeSummary persists to
|
|
11
|
+
* writeSummary persists to this agent's durable sidecar
|
|
12
|
+
* (.reposkein/local/summaries-<agent>.jsonl). */
|
|
12
13
|
export declare class JsonlGraphStore implements GraphStore {
|
|
13
14
|
private readonly repoId;
|
|
14
15
|
private graph;
|
|
15
|
-
private
|
|
16
|
+
private stamp;
|
|
16
17
|
private readonly repoPath;
|
|
17
18
|
private readonly nodesPath;
|
|
18
19
|
private readonly edgesPath;
|
|
19
20
|
private readonly sidecarFile;
|
|
20
|
-
constructor(repoPath: string, repoId: string
|
|
21
|
+
constructor(repoPath: string, repoId: string,
|
|
22
|
+
/** Writer identity picking the per-agent sidecar file (REP-17: a remote
|
|
23
|
+
* connection's bearer-token name). Undefined keeps the REPOSKEIN_AGENT
|
|
24
|
+
* default — the stdio behaviour. */
|
|
25
|
+
agent?: string);
|
|
21
26
|
/** Gathers committed JSONL for the root + all transitively federated
|
|
22
27
|
* children (guarded, cycle-safe). Each child's repo_id comes from the proxy
|
|
23
28
|
* Repository node's federated_repo_id in the parent's nodes.jsonl. */
|
|
24
29
|
private collectRepos;
|
|
25
|
-
/** Reloads the graph
|
|
30
|
+
/** Reloads the graph when anything it reads has changed on disk.
|
|
31
|
+
*
|
|
32
|
+
* The key covers the derived JSONL, the committed summary shards, AND every
|
|
33
|
+
* agent's sidecar. Keying on nodes/edges alone made a `git pull` that
|
|
34
|
+
* brought in only a teammate's shards invisible for the life of the process
|
|
35
|
+
* — the shards are committed and the derived graph is not, so that is the
|
|
36
|
+
* ordinary case. Leaving the sidecars out did the same to a second agent
|
|
37
|
+
* working the same checkout, which the overlay explicitly promises to
|
|
38
|
+
* surface. Stat calls only, O(shards + sidecars). */
|
|
39
|
+
private freshnessKey;
|
|
26
40
|
private ensureFresh;
|
|
27
41
|
getNode(repoIds: string[], id: string): Promise<TargetRow | null>;
|
|
28
42
|
findByContentHash(repoIds: string[], hash: string): Promise<TargetRow[]>;
|