@descryy/mcp 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/LICENSE +21 -0
- package/dist/action-handshake.d.ts +86 -0
- package/dist/action-handshake.d.ts.map +1 -0
- package/dist/action-handshake.js +144 -0
- package/dist/action-handshake.js.map +1 -0
- package/dist/bin/descry-mcp.d.ts +18 -0
- package/dist/bin/descry-mcp.d.ts.map +1 -0
- package/dist/bin/descry-mcp.js +54 -0
- package/dist/bin/descry-mcp.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/language-guess.d.ts +17 -0
- package/dist/language-guess.d.ts.map +1 -0
- package/dist/language-guess.js +43 -0
- package/dist/language-guess.js.map +1 -0
- package/dist/protocol.d.ts +91 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +127 -0
- package/dist/protocol.js.map +1 -0
- package/dist/registry.d.ts +72 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +136 -0
- package/dist/registry.js.map +1 -0
- package/dist/render.d.ts +275 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +333 -0
- package/dist/render.js.map +1 -0
- package/dist/server.d.ts +42 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +263 -0
- package/dist/server.js.map +1 -0
- package/dist/session.d.ts +164 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +302 -0
- package/dist/session.js.map +1 -0
- package/dist/tools/analyze.d.ts +124 -0
- package/dist/tools/analyze.d.ts.map +1 -0
- package/dist/tools/analyze.js +411 -0
- package/dist/tools/analyze.js.map +1 -0
- package/dist/tools/contracts.d.ts +105 -0
- package/dist/tools/contracts.d.ts.map +1 -0
- package/dist/tools/contracts.js +141 -0
- package/dist/tools/contracts.js.map +1 -0
- package/dist/tools/cross-pr.d.ts +137 -0
- package/dist/tools/cross-pr.d.ts.map +1 -0
- package/dist/tools/cross-pr.js +216 -0
- package/dist/tools/cross-pr.js.map +1 -0
- package/dist/tools/git-diff.d.ts +29 -0
- package/dist/tools/git-diff.d.ts.map +1 -0
- package/dist/tools/git-diff.js +117 -0
- package/dist/tools/git-diff.js.map +1 -0
- package/dist/tools/git-history.d.ts +27 -0
- package/dist/tools/git-history.d.ts.map +1 -0
- package/dist/tools/git-history.js +91 -0
- package/dist/tools/git-history.js.map +1 -0
- package/dist/tools/history.d.ts +63 -0
- package/dist/tools/history.d.ts.map +1 -0
- package/dist/tools/history.js +114 -0
- package/dist/tools/history.js.map +1 -0
- package/dist/tools/impact.d.ts +81 -0
- package/dist/tools/impact.d.ts.map +1 -0
- package/dist/tools/impact.js +229 -0
- package/dist/tools/impact.js.map +1 -0
- package/dist/tools/index.d.ts +33 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +47 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/kit.d.ts +183 -0
- package/dist/tools/kit.d.ts.map +1 -0
- package/dist/tools/kit.js +117 -0
- package/dist/tools/kit.js.map +1 -0
- package/dist/tools/link-workspace.d.ts +62 -0
- package/dist/tools/link-workspace.d.ts.map +1 -0
- package/dist/tools/link-workspace.js +156 -0
- package/dist/tools/link-workspace.js.map +1 -0
- package/dist/tools/lookup.d.ts +29 -0
- package/dist/tools/lookup.d.ts.map +1 -0
- package/dist/tools/lookup.js +73 -0
- package/dist/tools/lookup.js.map +1 -0
- package/dist/tools/pr-analysis.d.ts +89 -0
- package/dist/tools/pr-analysis.d.ts.map +1 -0
- package/dist/tools/pr-analysis.js +169 -0
- package/dist/tools/pr-analysis.js.map +1 -0
- package/dist/tools/propagation.d.ts +74 -0
- package/dist/tools/propagation.d.ts.map +1 -0
- package/dist/tools/propagation.js +194 -0
- package/dist/tools/propagation.js.map +1 -0
- package/dist/tools/questions.d.ts +80 -0
- package/dist/tools/questions.d.ts.map +1 -0
- package/dist/tools/questions.js +213 -0
- package/dist/tools/questions.js.map +1 -0
- package/dist/tools/refusal-fetch.d.ts +71 -0
- package/dist/tools/refusal-fetch.d.ts.map +1 -0
- package/dist/tools/refusal-fetch.js +137 -0
- package/dist/tools/refusal-fetch.js.map +1 -0
- package/dist/tools/scope.d.ts +60 -0
- package/dist/tools/scope.d.ts.map +1 -0
- package/dist/tools/scope.js +160 -0
- package/dist/tools/scope.js.map +1 -0
- package/dist/tools/similar-incidents.d.ts +105 -0
- package/dist/tools/similar-incidents.d.ts.map +1 -0
- package/dist/tools/similar-incidents.js +228 -0
- package/dist/tools/similar-incidents.js.map +1 -0
- package/dist/tools/validate.d.ts +103 -0
- package/dist/tools/validate.d.ts.map +1 -0
- package/dist/tools/validate.js +176 -0
- package/dist/tools/validate.js.map +1 -0
- package/dist/tools/verification-status.d.ts +68 -0
- package/dist/tools/verification-status.d.ts.map +1 -0
- package/dist/tools/verification-status.js +179 -0
- package/dist/tools/verification-status.js.map +1 -0
- package/dist/transport.d.ts +58 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +115 -0
- package/dist/transport.js.map +1 -0
- package/package.json +33 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `verification_status` — §4 technique 6: *"Coverage is a separate axis and
|
|
3
|
+
* a separate call. Appending it everywhere pays on every call; a tool pays
|
|
4
|
+
* once, when the client is actually reporting."*
|
|
5
|
+
*
|
|
6
|
+
* Wraps `packages/core/src/query/verification-status.ts`'s
|
|
7
|
+
* `computeVerificationStatus` — the module's own header calls itself "the
|
|
8
|
+
* static half only" and says building the `ScopeItem[]` from a caller's refs
|
|
9
|
+
* is "the caller's job, done above this boundary." This tool is that caller.
|
|
10
|
+
*
|
|
11
|
+
* ## Real capability lookup, without ever naming a language up here
|
|
12
|
+
*
|
|
13
|
+
* `computeVerificationStatus`'s `ScopeItem.capabilities`, when supplied,
|
|
14
|
+
* lets a `notExercised` reason describe a real declared gap rather than a
|
|
15
|
+
* generic absence. The first design attempted here guessed a language from
|
|
16
|
+
* a ref's file extension and matched it against a `language` tag on a
|
|
17
|
+
* configured source — and `npm run lint` caught it immediately:
|
|
18
|
+
* `descry-boundary/no-language-vocabulary` and `no-language-branch` both
|
|
19
|
+
* fired, because `packages/*\/src/**` (this file included, not just
|
|
20
|
+
* `packages/core`) is bound by architecture principle 7 — nothing above the
|
|
21
|
+
* Canonical IR may name or dispatch on a language, full stop. A hardcoded
|
|
22
|
+
* extension table and a `.get(guessedLanguage)` lookup are exactly the
|
|
23
|
+
* "lookup dispatch" shape that rule exists to catch, not a false positive.
|
|
24
|
+
*
|
|
25
|
+
* The fix moves the decision below the boundary, where it belongs:
|
|
26
|
+
* `LanguageAdapter` (`@descryy/ir`) gained an optional
|
|
27
|
+
* `ownsPath(path): boolean` — the adapter decides, using whatever
|
|
28
|
+
* language-specific logic it wants, entirely inside `descry-adapters`,
|
|
29
|
+
* which is not bound by this repo's lint. This tool never sees or compares
|
|
30
|
+
* a language string; it just asks every loaded, configured adapter "do you
|
|
31
|
+
* own this path," and attaches whichever one says yes. An unresolved ref's
|
|
32
|
+
* `language` therefore stays `null` here always — this tool does not
|
|
33
|
+
* determine one, and does not need to: `computeVerificationStatus`'s reason
|
|
34
|
+
* text already reads correctly either way (see its own module header),
|
|
35
|
+
* naming an adapter as registered without ever naming which language it is
|
|
36
|
+
* for.
|
|
37
|
+
*
|
|
38
|
+
* A configured source that fails to import cannot be asked at all — this
|
|
39
|
+
* tool's own `notes` disclose that plainly, the same register `analyze.ts`
|
|
40
|
+
* already uses for a source that will not import.
|
|
41
|
+
*
|
|
42
|
+
* ## Resolving a ref: node id first, then file
|
|
43
|
+
*
|
|
44
|
+
* A ref that is a real node id resolves directly (`getNode`). Otherwise it
|
|
45
|
+
* is tried as a file path (`findNodes({ file: ref })`, the same reader
|
|
46
|
+
* `lookup.ts`'s `resolveOneNode` already uses for symbol/file matching): the
|
|
47
|
+
* file's own `FILE`-typed node stands in when one exists, else the node
|
|
48
|
+
* with the *weakest* resolution in that file — the same "report the
|
|
49
|
+
* weakest link" convention `resolutionFloor` uses elsewhere in this
|
|
50
|
+
* package, since a file is only as verified as its least-resolved member.
|
|
51
|
+
* A ref that resolves neither way is `notExercised`.
|
|
52
|
+
*/
|
|
53
|
+
import { getNode, findNodes, computeVerificationStatus, resolutionOfExercised } from "@descryy/core";
|
|
54
|
+
import { answer, optionalStringArray, ToolInputError, } from "./kit.js";
|
|
55
|
+
import { loadSources } from "../registry.js";
|
|
56
|
+
const SCHEMA = {
|
|
57
|
+
type: "object",
|
|
58
|
+
properties: {
|
|
59
|
+
refs: {
|
|
60
|
+
type: "array",
|
|
61
|
+
items: { type: "string" },
|
|
62
|
+
minItems: 1,
|
|
63
|
+
description: "Node ids and/or repository-relative file paths to check coverage for — typically ids " +
|
|
64
|
+
"already returned by an earlier call (impact, scope, contracts) that you now want to know " +
|
|
65
|
+
"whether the graph actually reached.",
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
required: ["refs"],
|
|
69
|
+
additionalProperties: false,
|
|
70
|
+
};
|
|
71
|
+
/** The file's own `FILE` node when present, else the node with the weakest resolution — never picked at random. */
|
|
72
|
+
function representativeForFile(nodes) {
|
|
73
|
+
const fileNode = nodes.find((n) => n.type === "FILE");
|
|
74
|
+
if (fileNode !== undefined)
|
|
75
|
+
return fileNode;
|
|
76
|
+
return nodes.reduce((weakest, n) => (n.resolution < weakest.resolution ? n : weakest));
|
|
77
|
+
}
|
|
78
|
+
function resolveRef(driver, ref) {
|
|
79
|
+
const byId = getNode(driver, ref);
|
|
80
|
+
if (byId !== undefined)
|
|
81
|
+
return { ref, language: byId.language, node: byId };
|
|
82
|
+
const inFile = findNodes(driver, { file: ref });
|
|
83
|
+
if (inFile.length > 0) {
|
|
84
|
+
const node = representativeForFile(inFile);
|
|
85
|
+
return { ref, language: node.language, node };
|
|
86
|
+
}
|
|
87
|
+
return { ref, language: null, node: null };
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Real capabilities for whichever configured, loaded adapter owns each
|
|
91
|
+
* unresolved ref — decided entirely by the adapter's own `ownsPath`, never
|
|
92
|
+
* by a language name compared up here. See the module header.
|
|
93
|
+
*/
|
|
94
|
+
async function capabilitiesForUnresolvedRefs(sources, unresolvedRefs) {
|
|
95
|
+
const capabilitiesByRef = new Map();
|
|
96
|
+
const failedNotes = [];
|
|
97
|
+
if (unresolvedRefs.length === 0 || sources.length === 0)
|
|
98
|
+
return { capabilitiesByRef, failedNotes };
|
|
99
|
+
const { loaded, failed } = await loadSources(sources);
|
|
100
|
+
try {
|
|
101
|
+
for (const ref of unresolvedRefs) {
|
|
102
|
+
const owner = loaded.find((entry) => entry.adapter?.ownsPath?.(ref) === true);
|
|
103
|
+
if (owner?.adapter !== undefined && owner?.adapter !== null) {
|
|
104
|
+
capabilitiesByRef.set(ref, owner.adapter.capabilities());
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
finally {
|
|
109
|
+
await Promise.all(loaded.map((entry) => entry.adapter?.dispose()));
|
|
110
|
+
}
|
|
111
|
+
for (const failure of failed) {
|
|
112
|
+
failedNotes.push(`A configured source (${failure.spec.module}) did not import (${failure.reason}), so it could ` +
|
|
113
|
+
"not be asked whether it owns any of this call's unresolved refs.");
|
|
114
|
+
}
|
|
115
|
+
return { capabilitiesByRef, failedNotes };
|
|
116
|
+
}
|
|
117
|
+
async function run(args, ctx) {
|
|
118
|
+
const refs = optionalStringArray(args, "refs") ?? [];
|
|
119
|
+
if (refs.length === 0) {
|
|
120
|
+
throw new ToolInputError('"refs" must name at least one node id or file path — with none, there is nothing to report ' +
|
|
121
|
+
"coverage for, and an empty answer would look like a check that ran");
|
|
122
|
+
}
|
|
123
|
+
const driver = ctx.session.store().driver;
|
|
124
|
+
const base = ctx.session.provider().baseStamp();
|
|
125
|
+
ctx.progress(`Checking coverage for ${refs.length} ref(s)`);
|
|
126
|
+
const resolved = refs.map((ref) => resolveRef(driver, ref));
|
|
127
|
+
const unresolvedRefs = resolved.filter((r) => r.node === null).map((r) => r.ref);
|
|
128
|
+
const { capabilitiesByRef, failedNotes } = await capabilitiesForUnresolvedRefs(ctx.session.config.sources, unresolvedRefs);
|
|
129
|
+
const scope = resolved.map((r) => ({
|
|
130
|
+
ref: r.ref,
|
|
131
|
+
language: r.language,
|
|
132
|
+
node: r.node,
|
|
133
|
+
capabilities: r.node === null ? capabilitiesByRef.get(r.ref) : undefined,
|
|
134
|
+
}));
|
|
135
|
+
const status = computeVerificationStatus(scope);
|
|
136
|
+
const exercised = status.exercised.map((entry) => resolutionOfExercised(entry));
|
|
137
|
+
return answer({
|
|
138
|
+
headline: exercised.length === refs.length
|
|
139
|
+
? `All ${refs.length} ref(s) were reached by the graph.`
|
|
140
|
+
: `${exercised.length} of ${refs.length} ref(s) were reached by the graph; ` +
|
|
141
|
+
`${status.notExercised.length} were not — see notExercised for why.`,
|
|
142
|
+
data: { checked: refs, exercised, notExercised: status.notExercised },
|
|
143
|
+
resolutionFloor: exercised.length === 0 ? 0 : Math.min(...exercised.map((e) => e.resolution)),
|
|
144
|
+
commitSha: base.commitSha,
|
|
145
|
+
graphBuiltAt: base.graphBuiltAt,
|
|
146
|
+
irSchemaVersion: base.irSchemaVersion,
|
|
147
|
+
// A presence/coverage claim ("was this ref reached, and at what resolution")
|
|
148
|
+
// is about identity, not shape — the same class impact/history/similar_incidents
|
|
149
|
+
// already use.
|
|
150
|
+
nameLevel: true,
|
|
151
|
+
notes: [
|
|
152
|
+
...(status.notExercised.length === 0
|
|
153
|
+
? []
|
|
154
|
+
: [
|
|
155
|
+
"This tool never names a language for an absent ref — it only asks each configured, " +
|
|
156
|
+
"loaded adapter whether it owns that path. See each notExercised reason for exactly " +
|
|
157
|
+
"what was determined.",
|
|
158
|
+
]),
|
|
159
|
+
...failedNotes,
|
|
160
|
+
],
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
export const verificationStatusTool = {
|
|
164
|
+
name: "verification_status",
|
|
165
|
+
class: "read",
|
|
166
|
+
tier: "evidence",
|
|
167
|
+
version: "1.0.0",
|
|
168
|
+
title: "Was this actually checked, and at what resolution?",
|
|
169
|
+
description: "Given a list of node ids and/or file paths, report which were actually reached by the graph " +
|
|
170
|
+
"and at what resolution, and which were not — with why, where determinable. Coverage is a " +
|
|
171
|
+
"separate axis from any finding's confidence (§19/§20): use this after another call to learn " +
|
|
172
|
+
"what that call's answer does and does not actually cover, rather than trusting silence as " +
|
|
173
|
+
"coverage. When a session's configured adapters can say whether they own an unreached file, " +
|
|
174
|
+
"real declared capabilities are attached to explain the gap more precisely — see the tool's own " +
|
|
175
|
+
"notes when some refs are not exercised.",
|
|
176
|
+
inputSchema: SCHEMA,
|
|
177
|
+
run,
|
|
178
|
+
};
|
|
179
|
+
//# sourceMappingURL=verification-status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verification-status.js","sourceRoot":"","sources":["../../src/tools/verification-status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* stdio transport: newline-delimited JSON over stdin/stdout.
|
|
3
|
+
*
|
|
4
|
+
* ## The one rule that breaks everything when broken
|
|
5
|
+
*
|
|
6
|
+
* **stdout is the protocol channel and nothing else may write to it.** A single
|
|
7
|
+
* `console.log` anywhere in the process — in the engine, in a loaded adapter, in
|
|
8
|
+
* a dependency — emits a line the client tries to parse as a frame, and the
|
|
9
|
+
* session dies with an error that names the parser rather than the culprit.
|
|
10
|
+
*
|
|
11
|
+
* This is not a comment asking people to be careful. `guardStdout()` replaces
|
|
12
|
+
* `console.log` and friends with writers onto **stderr**, which the MCP host
|
|
13
|
+
* shows as server logs, so a stray print stays visible and stops being fatal.
|
|
14
|
+
* The transport keeps the one real handle to stdout for itself.
|
|
15
|
+
*
|
|
16
|
+
* ## Framing
|
|
17
|
+
*
|
|
18
|
+
* MCP's stdio transport is one JSON object per line, UTF-8, with no embedded
|
|
19
|
+
* newlines. `JSON.stringify` never emits a raw newline, so writing is a
|
|
20
|
+
* stringify plus `"\n"`. Reading needs a buffer because a chunk boundary can
|
|
21
|
+
* land anywhere, including mid-multibyte-character — hence `StringDecoder`
|
|
22
|
+
* rather than `chunk.toString()`, which would corrupt any non-ASCII payload
|
|
23
|
+
* split across two chunks.
|
|
24
|
+
*/
|
|
25
|
+
import type { Readable, Writable } from "node:stream";
|
|
26
|
+
export interface Transport {
|
|
27
|
+
/** Write one frame. Must never be called with anything but a JSON-RPC message. */
|
|
28
|
+
send(frame: unknown): void;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Redirect every console channel to stderr and return the real stdout writer.
|
|
32
|
+
*
|
|
33
|
+
* Called once, by the stdio runner, before any handler can run. The returned
|
|
34
|
+
* function is the only sanctioned path to stdout in the process.
|
|
35
|
+
*/
|
|
36
|
+
export declare function guardStdout(stdout: Writable, stderr: Writable): (line: string) => void;
|
|
37
|
+
/**
|
|
38
|
+
* Split a byte stream into lines, decoding correctly across chunk boundaries.
|
|
39
|
+
*
|
|
40
|
+
* Returned as a function rather than a class because the buffer is the entire
|
|
41
|
+
* state and there is nothing else to hang on an object.
|
|
42
|
+
*/
|
|
43
|
+
export declare function createLineReader(onLine: (line: string) => void): (chunk: Buffer) => void;
|
|
44
|
+
export interface StdioOptions {
|
|
45
|
+
readonly stdin: Readable;
|
|
46
|
+
readonly stdout: Writable;
|
|
47
|
+
readonly stderr: Writable;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Run a dispatcher over stdio until stdin closes.
|
|
51
|
+
*
|
|
52
|
+
* Resolves on end-of-input, which is how an MCP host asks a stdio server to shut
|
|
53
|
+
* down — it closes the pipe. Anything the server holds open (a database handle,
|
|
54
|
+
* a worker pool) is disposed by the caller after this resolves, not here: this
|
|
55
|
+
* function knows about bytes and nothing else.
|
|
56
|
+
*/
|
|
57
|
+
export declare function serveStdio(options: StdioOptions, dispatch: (line: string, transport: Transport) => Promise<void>): Promise<void>;
|
|
58
|
+
//# sourceMappingURL=transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEtD,MAAM,WAAW,SAAS;IACxB,kFAAkF;IAClF,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;CAC5B;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,QAAQ,EAChB,MAAM,EAAE,QAAQ,GACf,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAiBxB;AAWD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAcxF;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,OAAO,EAAE,YAAY,EACrB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,GAC9D,OAAO,CAAC,IAAI,CAAC,CA+Bf"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* stdio transport: newline-delimited JSON over stdin/stdout.
|
|
3
|
+
*
|
|
4
|
+
* ## The one rule that breaks everything when broken
|
|
5
|
+
*
|
|
6
|
+
* **stdout is the protocol channel and nothing else may write to it.** A single
|
|
7
|
+
* `console.log` anywhere in the process — in the engine, in a loaded adapter, in
|
|
8
|
+
* a dependency — emits a line the client tries to parse as a frame, and the
|
|
9
|
+
* session dies with an error that names the parser rather than the culprit.
|
|
10
|
+
*
|
|
11
|
+
* This is not a comment asking people to be careful. `guardStdout()` replaces
|
|
12
|
+
* `console.log` and friends with writers onto **stderr**, which the MCP host
|
|
13
|
+
* shows as server logs, so a stray print stays visible and stops being fatal.
|
|
14
|
+
* The transport keeps the one real handle to stdout for itself.
|
|
15
|
+
*
|
|
16
|
+
* ## Framing
|
|
17
|
+
*
|
|
18
|
+
* MCP's stdio transport is one JSON object per line, UTF-8, with no embedded
|
|
19
|
+
* newlines. `JSON.stringify` never emits a raw newline, so writing is a
|
|
20
|
+
* stringify plus `"\n"`. Reading needs a buffer because a chunk boundary can
|
|
21
|
+
* land anywhere, including mid-multibyte-character — hence `StringDecoder`
|
|
22
|
+
* rather than `chunk.toString()`, which would corrupt any non-ASCII payload
|
|
23
|
+
* split across two chunks.
|
|
24
|
+
*/
|
|
25
|
+
import { StringDecoder } from "node:string_decoder";
|
|
26
|
+
/**
|
|
27
|
+
* Redirect every console channel to stderr and return the real stdout writer.
|
|
28
|
+
*
|
|
29
|
+
* Called once, by the stdio runner, before any handler can run. The returned
|
|
30
|
+
* function is the only sanctioned path to stdout in the process.
|
|
31
|
+
*/
|
|
32
|
+
export function guardStdout(stdout, stderr) {
|
|
33
|
+
const toStderr = (...args) => {
|
|
34
|
+
stderr.write(`${args
|
|
35
|
+
.map((a) => (typeof a === "string" ? a : inspectish(a)))
|
|
36
|
+
.join(" ")}\n`);
|
|
37
|
+
};
|
|
38
|
+
console.log = toStderr;
|
|
39
|
+
console.info = toStderr;
|
|
40
|
+
console.warn = toStderr;
|
|
41
|
+
console.debug = toStderr;
|
|
42
|
+
console.error = toStderr;
|
|
43
|
+
return (line) => {
|
|
44
|
+
stdout.write(line);
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function inspectish(value) {
|
|
48
|
+
if (value instanceof Error)
|
|
49
|
+
return `${value.name}: ${value.message}`;
|
|
50
|
+
try {
|
|
51
|
+
return JSON.stringify(value) ?? String(value);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return String(value);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Split a byte stream into lines, decoding correctly across chunk boundaries.
|
|
59
|
+
*
|
|
60
|
+
* Returned as a function rather than a class because the buffer is the entire
|
|
61
|
+
* state and there is nothing else to hang on an object.
|
|
62
|
+
*/
|
|
63
|
+
export function createLineReader(onLine) {
|
|
64
|
+
const decoder = new StringDecoder("utf8");
|
|
65
|
+
let buffer = "";
|
|
66
|
+
return (chunk) => {
|
|
67
|
+
buffer += decoder.write(chunk);
|
|
68
|
+
let index = buffer.indexOf("\n");
|
|
69
|
+
while (index !== -1) {
|
|
70
|
+
const line = buffer.slice(0, index).replace(/\r$/, "");
|
|
71
|
+
buffer = buffer.slice(index + 1);
|
|
72
|
+
if (line.trim() !== "")
|
|
73
|
+
onLine(line);
|
|
74
|
+
index = buffer.indexOf("\n");
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Run a dispatcher over stdio until stdin closes.
|
|
80
|
+
*
|
|
81
|
+
* Resolves on end-of-input, which is how an MCP host asks a stdio server to shut
|
|
82
|
+
* down — it closes the pipe. Anything the server holds open (a database handle,
|
|
83
|
+
* a worker pool) is disposed by the caller after this resolves, not here: this
|
|
84
|
+
* function knows about bytes and nothing else.
|
|
85
|
+
*/
|
|
86
|
+
export function serveStdio(options, dispatch) {
|
|
87
|
+
const write = guardStdout(options.stdout, options.stderr);
|
|
88
|
+
const transport = {
|
|
89
|
+
send: (frame) => {
|
|
90
|
+
write(`${JSON.stringify(frame)}\n`);
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
// Frames are handled strictly in arrival order. Concurrency here would let a
|
|
94
|
+
// fast `tools/list` overtake a slow `analyze`, and while JSON-RPC permits
|
|
95
|
+
// out-of-order responses, an `analyze` that has not finished writing the graph
|
|
96
|
+
// must not be overtaken by a `scope` that would then read a half-built one.
|
|
97
|
+
let chain = Promise.resolve();
|
|
98
|
+
return new Promise((resolve, reject) => {
|
|
99
|
+
const feed = createLineReader((line) => {
|
|
100
|
+
chain = chain.then(() => dispatch(line, transport)).catch((error) => {
|
|
101
|
+
// A dispatcher that throws is a bug in this package: `dispatch` is
|
|
102
|
+
// supposed to turn every failure into an error frame. Report it on
|
|
103
|
+
// stderr and keep the session alive rather than killing a developer's
|
|
104
|
+
// editor integration over one bad request.
|
|
105
|
+
options.stderr.write(`descry-mcp: dispatch failed: ${inspectish(error)}\n`);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
options.stdin.on("data", feed);
|
|
109
|
+
options.stdin.on("error", reject);
|
|
110
|
+
options.stdin.on("end", () => {
|
|
111
|
+
chain.then(resolve, resolve);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAQpD;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CACzB,MAAgB,EAChB,MAAgB;IAEhB,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAe,EAAQ,EAAE;QAC5C,MAAM,CAAC,KAAK,CACV,GAAG,IAAI;aACJ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;aACvD,IAAI,CAAC,GAAG,CAAC,IAAI,CACjB,CAAC;IACJ,CAAC,CAAC;IACF,OAAO,CAAC,GAAG,GAAG,QAAQ,CAAC;IACvB,OAAO,CAAC,IAAI,GAAG,QAAQ,CAAC;IACxB,OAAO,CAAC,IAAI,GAAG,QAAQ,CAAC;IACxB,OAAO,CAAC,KAAK,GAAG,QAAQ,CAAC;IACzB,OAAO,CAAC,KAAK,GAAG,QAAQ,CAAC;IAEzB,OAAO,CAAC,IAAY,EAAQ,EAAE;QAC5B,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,KAAc;IAChC,IAAI,KAAK,YAAY,KAAK;QAAE,OAAO,GAAG,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;IACrE,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAA8B;IAC7D,MAAM,OAAO,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;IAC1C,IAAI,MAAM,GAAG,EAAE,CAAC;IAEhB,OAAO,CAAC,KAAa,EAAQ,EAAE;QAC7B,MAAM,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC/B,IAAI,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACjC,OAAO,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;YACpB,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACvD,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;YACjC,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;gBAAE,MAAM,CAAC,IAAI,CAAC,CAAC;YACrC,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAQD;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CACxB,OAAqB,EACrB,QAA+D;IAE/D,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1D,MAAM,SAAS,GAAc;QAC3B,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE;YACd,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACtC,CAAC;KACF,CAAC;IAEF,6EAA6E;IAC7E,0EAA0E;IAC1E,+EAA+E;IAC/E,4EAA4E;IAC5E,IAAI,KAAK,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;IAE7C,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC3C,MAAM,IAAI,GAAG,gBAAgB,CAAC,CAAC,IAAI,EAAE,EAAE;YACrC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;gBAC3E,mEAAmE;gBACnE,mEAAmE;gBACnE,sEAAsE;gBACtE,2CAA2C;gBAC3C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC9E,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAClC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YAC3B,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@descryy/mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Descry's MCP server: the agent-facing front door over the query layer. Zero runtime dependencies — the stdio transport is JSON-RPC 2.0 by hand rather than seventeen packages of HTTP and OAuth.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=22.5"
|
|
9
|
+
},
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"bin": {
|
|
17
|
+
"descry-mcp": "dist/bin/descry-mcp.js"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist"
|
|
21
|
+
],
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"registry": "https://registry.npmjs.org",
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsc -b"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@descryy/core": "0.1.0",
|
|
31
|
+
"@descryy/ir": "0.1.0"
|
|
32
|
+
}
|
|
33
|
+
}
|