@reposkein/mcp 0.4.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 +3 -0
- package/binary-digests.json +4 -4
- package/dist/cli/view.js +27 -6
- package/dist/cli/view.js.map +1 -1
- package/dist/index.d.ts +8 -56
- package/dist/index.js +38 -402
- package/dist/index.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 -0
- package/dist/indexer/runIndexer.js +12 -0
- 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 +5 -1
- package/dist/store/JsonlGraphStore.js +6 -2
- package/dist/store/JsonlGraphStore.js.map +1 -1
- package/dist/store/teamConfig.d.ts +10 -6
- package/dist/store/teamConfig.js +23 -17
- package/dist/store/teamConfig.js.map +1 -1
- package/dist/tools/recordDecision.d.ts +3 -0
- package/dist/tools/recordDecision.js +1 -1
- 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/index-BnqIVYFE.css +1 -0
- package/dist/viz/assets/index-IhtszTp0.js +5 -0
- package/dist/viz/assets/{r3f-BZY3QR6_.js → r3f-Bn9htB92.js} +1 -1
- package/dist/viz/assets/{tanstack-CjXr-L-s.js → tanstack-CSzx6NDA.js} +7 -7
- package/dist/viz/index.html +4 -4
- package/package.json +1 -1
- package/dist/viz/assets/index-CxqeGuRS.css +0 -1
- package/dist/viz/assets/index-DiNZyrXx.js +0 -9
|
@@ -3,6 +3,14 @@ export interface SpawnResult {
|
|
|
3
3
|
stdout: string;
|
|
4
4
|
stderr: string;
|
|
5
5
|
}
|
|
6
|
+
/** Runs the indexer binary, capped and timed out.
|
|
7
|
+
*
|
|
8
|
+
* Serialized process-wide by `withIndexLock`: every invocation writes into
|
|
9
|
+
* the target checkout's `.reposkein/`, and since REP-17 two callers (a
|
|
10
|
+
* write-capable tool call on one connection, the HEAD watcher on another) can
|
|
11
|
+
* arrive concurrently with no shared call stack to order them. The lock lives
|
|
12
|
+
* HERE rather than at each call site so a new call site cannot forget it —
|
|
13
|
+
* see `indexLock.ts`. */
|
|
6
14
|
export declare function spawnIndexer(bin: string, args: string[]): Promise<SpawnResult>;
|
|
7
15
|
export interface IndexJsonStats {
|
|
8
16
|
repo_id: string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
|
+
import { withIndexLock } from "./indexLock.js";
|
|
2
3
|
const ALLOWED_KEYS = new Set(["PATH", "HOME", "TMPDIR", "LANG", "LC_ALL", "NEO4J_URI", "NEO4J_USER", "NEO4J_PASSWORD"]);
|
|
3
4
|
/** Indexer spawn timeout (~10 minutes). Large repos can be slow but shouldn't hang forever. */
|
|
4
5
|
const INDEXER_TIMEOUT_MS = 600_000;
|
|
@@ -21,7 +22,18 @@ function buildChildEnv() {
|
|
|
21
22
|
// sourced from mcp/src/store/repoSession.ts. Don't reintroduce an
|
|
22
23
|
// env/cwd-based resolver here — see mcp/src/store/resolveRepoPath.ts for the
|
|
23
24
|
// one central resolution algorithm.
|
|
25
|
+
/** Runs the indexer binary, capped and timed out.
|
|
26
|
+
*
|
|
27
|
+
* Serialized process-wide by `withIndexLock`: every invocation writes into
|
|
28
|
+
* the target checkout's `.reposkein/`, and since REP-17 two callers (a
|
|
29
|
+
* write-capable tool call on one connection, the HEAD watcher on another) can
|
|
30
|
+
* arrive concurrently with no shared call stack to order them. The lock lives
|
|
31
|
+
* HERE rather than at each call site so a new call site cannot forget it —
|
|
32
|
+
* see `indexLock.ts`. */
|
|
24
33
|
export function spawnIndexer(bin, args) {
|
|
34
|
+
return withIndexLock(() => spawnIndexerUnlocked(bin, args));
|
|
35
|
+
}
|
|
36
|
+
function spawnIndexerUnlocked(bin, args) {
|
|
25
37
|
return new Promise((resolve, reject) => {
|
|
26
38
|
const child = spawn(bin, args, { env: buildChildEnv() });
|
|
27
39
|
let stdout = "";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runIndexer.js","sourceRoot":"","sources":["../../src/indexer/runIndexer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"runIndexer.js","sourceRoot":"","sources":["../../src/indexer/runIndexer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { type IncomingMessage, type ServerResponse } from "node:http";
|
|
2
|
+
import { type CreateMcpServerOptions } from "../server/createMcpServer.js";
|
|
3
|
+
import { type ServeToken } from "./tokens.js";
|
|
4
|
+
/** The one path the MCP Streamable HTTP transport answers on. Everything else
|
|
5
|
+
* is the viewer + `/api/*`, served by view.ts's own handler. */
|
|
6
|
+
export declare const MCP_PATH = "/mcp";
|
|
7
|
+
export interface ServeOptions {
|
|
8
|
+
port: number;
|
|
9
|
+
host: string;
|
|
10
|
+
/** `git rev-parse HEAD` poll interval. 0 disables the watcher. */
|
|
11
|
+
watchIntervalMs: number;
|
|
12
|
+
}
|
|
13
|
+
/** Default bind host. NOT 0.0.0.0: even in the mode that exists to be
|
|
14
|
+
* reachable, exposure is an explicit `--host` decision by the operator. */
|
|
15
|
+
export declare const DEFAULT_SERVE_HOST = "127.0.0.1";
|
|
16
|
+
export declare const DEFAULT_SERVE_PORT = 4318;
|
|
17
|
+
export declare const DEFAULT_WATCH_INTERVAL_MS = 30000;
|
|
18
|
+
export declare function parseServeArgs(argv: string[]): {
|
|
19
|
+
repoPath: string;
|
|
20
|
+
opts: ServeOptions;
|
|
21
|
+
http: boolean;
|
|
22
|
+
};
|
|
23
|
+
type NodeHandler = (req: IncomingMessage, res: ServerResponse) => void;
|
|
24
|
+
export interface CreateServeAppOptions {
|
|
25
|
+
repoPath: string;
|
|
26
|
+
repoId: string;
|
|
27
|
+
tokens: readonly ServeToken[];
|
|
28
|
+
log?: (message: string) => void;
|
|
29
|
+
/** Test seam: replaces `makeViewHandler` (which reads the repo's JSONL and
|
|
30
|
+
* shells out to git at construction time). */
|
|
31
|
+
viewHandlerFactory?: (repoPath: string, repoId: string) => NodeHandler;
|
|
32
|
+
/** Test seam: passed through to every per-connection `createMcpServer`. */
|
|
33
|
+
ensureGraph?: CreateMcpServerOptions["ensureGraph"];
|
|
34
|
+
/** Concurrent-session cap. Defaults to `MAX_SESSIONS` (64); lowered in
|
|
35
|
+
* tests so the cap and the reaper-then-retry path are cheap to exercise. */
|
|
36
|
+
maxSessions?: number;
|
|
37
|
+
/** Idle-session reap threshold. Defaults to `SESSION_IDLE_MS` (5 min). */
|
|
38
|
+
idleMs?: number;
|
|
39
|
+
/** Clock. Injectable so the reaper can be tested without waiting minutes. */
|
|
40
|
+
now?: () => number;
|
|
41
|
+
}
|
|
42
|
+
export interface ServeApp {
|
|
43
|
+
handler: NodeHandler;
|
|
44
|
+
/** Rebuilds the `/api/*` handler. The view handler snapshots node/edge
|
|
45
|
+
* counts and git metadata once per construction, so after a re-index the
|
|
46
|
+
* hosted viewer would otherwise keep reporting the old graph — this is the
|
|
47
|
+
* watcher's `onReindexed` hook, and it is why the MCP tools and the viewer
|
|
48
|
+
* cannot drift apart: they are refreshed by the same event. */
|
|
49
|
+
refresh: () => void;
|
|
50
|
+
/** Closes every session idle past `idleMs` with no request in flight, and
|
|
51
|
+
* returns how many it closed. Called automatically before each new-session
|
|
52
|
+
* attempt (so a server wedged at the cap by dead clients frees itself on
|
|
53
|
+
* the next connect); exposed for tests. */
|
|
54
|
+
sweepIdleSessions: () => number;
|
|
55
|
+
close: () => Promise<void>;
|
|
56
|
+
sessionCount: () => number;
|
|
57
|
+
}
|
|
58
|
+
/** Builds the one request handler that answers both the MCP endpoint and the
|
|
59
|
+
* viewer/`/api/*` surface (REP-17 requirement: one process, one graph).
|
|
60
|
+
*
|
|
61
|
+
* URL layout:
|
|
62
|
+
* POST/GET/DELETE `/mcp` — MCP Streamable HTTP transport
|
|
63
|
+
* GET `/api/graph`, `/api/jsonl/*`, `/api/source`, `/api/temporal`
|
|
64
|
+
* — byte-identical to `reposkein-mcp view`, because
|
|
65
|
+
* it IS view.ts's handler, not a copy
|
|
66
|
+
* GET everything else — the prebuilt viewer SPA
|
|
67
|
+
*
|
|
68
|
+
* Auth applies to every route. `/mcp` accepts ONLY
|
|
69
|
+
* `Authorization: Bearer <token>`; the viewer routes additionally accept
|
|
70
|
+
* `?token=` (which is immediately traded for an HttpOnly cookie and
|
|
71
|
+
* redirected away, so it appears once) because a static SPA in a browser
|
|
72
|
+
* cannot attach an Authorization header to its own page load. */
|
|
73
|
+
export declare function createServeApp(opts: CreateServeAppOptions): ServeApp;
|
|
74
|
+
/** `git status --porcelain` for the served checkout, or null when git is
|
|
75
|
+
* unavailable / the path isn't a repo. Never throws. */
|
|
76
|
+
export declare function gitPorcelainStatus(repoPath: string): string[] | null;
|
|
77
|
+
/** The startup warning for serving a checkout with local modifications, or
|
|
78
|
+
* null when the tree is clean (or git can't tell us).
|
|
79
|
+
*
|
|
80
|
+
* Serving a dirty checkout is legal and sometimes exactly what an operator
|
|
81
|
+
* wants, so this WARNS and never refuses. But it is worth saying loudly:
|
|
82
|
+
* `serve`'s own re-index writes into `.reposkein/` (the committed summary
|
|
83
|
+
* shards absorb every `local/summaries-*.jsonl` sidecar), so a checkout that
|
|
84
|
+
* someone also works in will accumulate diffs that look like the server's
|
|
85
|
+
* fault — and a re-index landing on top of half-finished local edits indexes
|
|
86
|
+
* those edits. A dedicated deploy clone has neither problem. */
|
|
87
|
+
export declare function dirtyCheckoutWarning(repoPath: string, statusFn?: (p: string) => string[] | null): string | null;
|
|
88
|
+
/** `reposkein-mcp serve --http [path] [--port N] [--host H] [--watch-interval S]`.
|
|
89
|
+
*
|
|
90
|
+
* Strictly optional (REP-17 / adr:2026-08-21-optional-shared-remote-mcp-server-…):
|
|
91
|
+
* stdio is still the default transport and nothing binds a socket unless this
|
|
92
|
+
* runs. Refuses to start without at least one configured token — an
|
|
93
|
+
* unauthenticated remote MCP server would hand write access to the network. */
|
|
94
|
+
export declare function runServe(repoPath: string, repoId: string, opts: ServeOptions): Promise<number>;
|
|
95
|
+
export {};
|