token-goat 2.6.36 → 2.8.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.
Files changed (34) hide show
  1. package/README.md +36 -8
  2. package/SECURITY.md +46 -17
  3. package/dist/{token-goat-chunk-UFOVM7ZN.mjs → token-goat-chunk-2G6RAB4G.mjs} +1391 -378
  4. package/dist/token-goat-chunk-324QOJYZ.mjs +91 -0
  5. package/dist/token-goat-chunk-5CVKO3DA.mjs +185 -0
  6. package/dist/{token-goat-chunk-65BKISIS.mjs → token-goat-chunk-73MF6YWW.mjs} +4 -4
  7. package/dist/{token-goat-chunk-MGOUYAA2.mjs → token-goat-chunk-7JDXDERZ.mjs} +1 -1
  8. package/dist/{token-goat-hook-chunk-BDR6C6IE.mjs → token-goat-chunk-AOBZUFNJ.mjs} +318 -51
  9. package/dist/{token-goat-chunk-V465YKOR.mjs → token-goat-chunk-ELDJRLHZ.mjs} +492 -28
  10. package/dist/{token-goat-chunk-CNDOJ3ZP.mjs → token-goat-chunk-I6TOUPLP.mjs} +2 -2
  11. package/dist/token-goat-chunk-R4SR7MQY.mjs +486 -0
  12. package/dist/{token-goat-chunk-IYTVE6KN.mjs → token-goat-chunk-RMDQFTQD.mjs} +226 -150
  13. package/dist/{token-goat-chunk-KYFJC37X.mjs → token-goat-chunk-VBXBLGTO.mjs} +792 -144
  14. package/dist/{token-goat-chunk-DG53MVNJ.mjs → token-goat-chunk-WN5T5EW5.mjs} +212 -212
  15. package/dist/{token-goat-chunk-VYMGEVZS.mjs → token-goat-chunk-XEDQH5DA.mjs} +317 -11
  16. package/dist/{token-goat-chunk-LN6OUHTV.mjs → token-goat-chunk-Y2SYNH3S.mjs} +5 -5
  17. package/dist/token-goat-chunk-YUGNM3KL.mjs +23 -0
  18. package/dist/token-goat-hook.mjs +7 -7
  19. package/dist/token-goat.core.mjs +5 -5
  20. package/package.json +12 -8
  21. package/dist/token-goat-chunk-FRTBMRP7.mjs +0 -10048
  22. package/dist/token-goat-hook-chunk-3QYSN4QV.mjs +0 -14764
  23. package/dist/token-goat-hook-chunk-3ZDBWJDF.mjs +0 -13659
  24. package/dist/token-goat-hook-chunk-5UH54CW6.mjs +0 -912
  25. package/dist/token-goat-hook-chunk-6ODM3MP7.mjs +0 -706
  26. package/dist/token-goat-hook-chunk-A77A26A7.mjs +0 -18184
  27. package/dist/token-goat-hook-chunk-BUOCULAM.mjs +0 -29
  28. package/dist/token-goat-hook-chunk-C6GIABOX.mjs +0 -15971
  29. package/dist/token-goat-hook-chunk-E257IGSN.mjs +0 -153
  30. package/dist/token-goat-hook-chunk-MW5HPEGD.mjs +0 -10411
  31. package/dist/token-goat-hook-chunk-QSCYNJ2B.mjs +0 -23
  32. package/dist/token-goat-hook-chunk-RFRLWOQH.mjs +0 -11
  33. package/dist/token-goat-hook-chunk-XUMIVYEN.mjs +0 -109
  34. package/dist/token-goat-hook-chunk-Y2WHX2P3.mjs +0 -6463
@@ -0,0 +1,91 @@
1
+ import { createRequire as __cjsRequire } from 'node:module';
2
+ const require = __cjsRequire(import.meta.url);
3
+ import "./token-goat-chunk-AEX54RUZ.mjs";
4
+
5
+ // src/mcp_stdio.ts
6
+ import process from "node:process";
7
+ var STDIO_MAX_BUFFER_BYTES = 10 * 1024 * 1024;
8
+ var StdioServerTransport = class {
9
+ stdin;
10
+ stdout;
11
+ buffer;
12
+ started = false;
13
+ onmessage;
14
+ onclose;
15
+ onerror;
16
+ // Arrow properties rather than bound methods so `off()` can remove the exact same function
17
+ // reference `on()` added -- a fresh `.bind(this)` at removal time would leave the listener
18
+ // attached, and a second `mcp-serve` in the same process would then see every message twice.
19
+ ondata = (chunk) => {
20
+ const size = (this.buffer?.length ?? 0) + chunk.length;
21
+ if (size > STDIO_MAX_BUFFER_BYTES) {
22
+ this.buffer = void 0;
23
+ this.onerror?.(new Error(`MCP stdio read buffer exceeded ${STDIO_MAX_BUFFER_BYTES} bytes`));
24
+ void this.close();
25
+ return;
26
+ }
27
+ this.buffer = this.buffer === void 0 ? chunk : Buffer.concat([this.buffer, chunk]);
28
+ this.drain();
29
+ };
30
+ onstreamerror = (error) => {
31
+ this.onerror?.(error);
32
+ };
33
+ constructor(stdin = process.stdin, stdout = process.stdout) {
34
+ this.stdin = stdin;
35
+ this.stdout = stdout;
36
+ }
37
+ async start() {
38
+ if (this.started) throw new Error("StdioServerTransport already started");
39
+ this.started = true;
40
+ this.stdin.on("data", this.ondata);
41
+ this.stdin.on("error", this.onstreamerror);
42
+ return Promise.resolve();
43
+ }
44
+ /**
45
+ * Consumes every complete line currently buffered. A line that is not valid JSON is reported and
46
+ * skipped rather than closing the connection: one malformed message is not a reason to drop a
47
+ * working session, and the next line may well be fine.
48
+ */
49
+ drain() {
50
+ for (; ; ) {
51
+ const buffer = this.buffer;
52
+ if (buffer === void 0) return;
53
+ const index = buffer.indexOf("\n");
54
+ if (index === -1) return;
55
+ const line = buffer.toString("utf8", 0, index).replace(/\r$/, "");
56
+ this.buffer = buffer.subarray(index + 1);
57
+ if (line.trim().length === 0) continue;
58
+ let message;
59
+ try {
60
+ message = JSON.parse(line);
61
+ } catch (err) {
62
+ this.onerror?.(err instanceof Error ? err : new Error(String(err)));
63
+ continue;
64
+ }
65
+ this.onmessage?.(message);
66
+ }
67
+ }
68
+ /**
69
+ * Resolves once the message is handed off. Waiting for `drain` when the stream says it is full
70
+ * is what keeps a long reply from being silently truncated on a slow or small pipe.
71
+ */
72
+ send(message) {
73
+ return new Promise((resolve) => {
74
+ if (this.stdout.write(`${JSON.stringify(message)}
75
+ `)) resolve();
76
+ else this.stdout.once("drain", resolve);
77
+ });
78
+ }
79
+ async close() {
80
+ this.stdin.off("data", this.ondata);
81
+ this.stdin.off("error", this.onstreamerror);
82
+ if (this.stdin.listenerCount("data") === 0) this.stdin.pause();
83
+ this.buffer = void 0;
84
+ this.onclose?.();
85
+ return Promise.resolve();
86
+ }
87
+ };
88
+ export {
89
+ STDIO_MAX_BUFFER_BYTES,
90
+ StdioServerTransport
91
+ };
@@ -0,0 +1,185 @@
1
+ import { createRequire as __cjsRequire } from 'node:module';
2
+ const require = __cjsRequire(import.meta.url);
3
+ import {
4
+ external_exports
5
+ } from "./token-goat-chunk-WN5T5EW5.mjs";
6
+ import "./token-goat-chunk-AEX54RUZ.mjs";
7
+
8
+ // src/mcp_jsonrpc.ts
9
+ var LATEST_PROTOCOL_VERSION = "2025-11-25";
10
+ var SUPPORTED_PROTOCOL_VERSIONS = [
11
+ LATEST_PROTOCOL_VERSION,
12
+ "2025-06-18",
13
+ "2025-03-26",
14
+ "2024-11-05",
15
+ "2024-10-07"
16
+ ];
17
+ var JSONRPC_INVALID_REQUEST = -32600;
18
+ var JSONRPC_METHOD_NOT_FOUND = -32601;
19
+ var JSONRPC_INVALID_PARAMS = -32602;
20
+ var DRAFT_07_SCHEMA_ID = "http://json-schema.org/draft-07/schema#";
21
+ var MCP_INVALID_PARAMS_PREFIX = `MCP error ${JSONRPC_INVALID_PARAMS}: `;
22
+ var EMPTY_OBJECT_JSON_SCHEMA = { type: "object", properties: {} };
23
+ function buildJsonSchema(shape) {
24
+ if (shape === void 0 || Object.keys(shape).length === 0) return { ...EMPTY_OBJECT_JSON_SCHEMA };
25
+ const schema = external_exports.toJSONSchema(external_exports.object(shape), { io: "input" });
26
+ return { ...schema, $schema: DRAFT_07_SCHEMA_ID };
27
+ }
28
+ function describeParseError(error) {
29
+ return error.issues.map((issue) => {
30
+ if (issue.path.length === 0) return issue.message;
31
+ const dotted = issue.path.reduce(
32
+ (acc, seg, i) => i === 0 ? String(seg) : typeof seg === "number" ? `${acc}[${seg}]` : `${acc}.${String(seg)}`,
33
+ ""
34
+ );
35
+ return `${issue.message} at ${dotted}`;
36
+ }).join("\n");
37
+ }
38
+ function errorText(message) {
39
+ return { content: [{ type: "text", text: message }], isError: true };
40
+ }
41
+ function isRequest(message) {
42
+ return "method" in message && "id" in message && message.id !== void 0 && message.id !== null;
43
+ }
44
+ var McpServer = class {
45
+ info;
46
+ tools = /* @__PURE__ */ new Map();
47
+ handlers = /* @__PURE__ */ new Map();
48
+ transport;
49
+ /** Set by the caller to learn when the peer hung up; `mcp-serve` waits on exactly this. */
50
+ onclose;
51
+ constructor(info) {
52
+ this.info = info;
53
+ }
54
+ /**
55
+ * Registers a tool. Schema generation happens here rather than at `tools/list` time, which also
56
+ * means a malformed shape fails loudly at startup instead of on a client's first listing.
57
+ */
58
+ registerTool(name, definition, handler) {
59
+ if (this.tools.has(name)) throw new Error(`MCP tool registered twice: ${name}`);
60
+ const shape = definition.inputSchema;
61
+ this.tools.set(name, {
62
+ name,
63
+ description: definition.description,
64
+ jsonSchema: buildJsonSchema(shape),
65
+ // An absent shape still needs a validator, so an argumentless tool called with arguments is
66
+ // not silently handed them.
67
+ validator: external_exports.object(shape ?? {})
68
+ });
69
+ this.handlers.set(name, handler);
70
+ }
71
+ /**
72
+ * Wires this server to a transport and starts it.
73
+ *
74
+ * `onmessage` is assigned before `start()` on purpose: a transport may have buffered messages
75
+ * that arrive the moment it starts (the SDK's in-memory transport queues anything sent before a
76
+ * handler exists and drains the queue inside `start()`), so a server that started first would
77
+ * drop the client's `initialize`.
78
+ */
79
+ async connect(transport) {
80
+ this.transport = transport;
81
+ transport.onmessage = (message) => {
82
+ void this.handleMessage(message);
83
+ };
84
+ transport.onclose = () => {
85
+ this.transport = void 0;
86
+ this.onclose?.();
87
+ };
88
+ await transport.start();
89
+ }
90
+ async close() {
91
+ const transport = this.transport;
92
+ this.transport = void 0;
93
+ await transport?.close();
94
+ }
95
+ async send(message) {
96
+ try {
97
+ await this.transport?.send(message);
98
+ } catch {
99
+ }
100
+ }
101
+ async handleMessage(message) {
102
+ if (!isRequest(message)) return;
103
+ const { id, method } = message;
104
+ const params = message.params ?? {};
105
+ try {
106
+ switch (method) {
107
+ case "initialize":
108
+ await this.send({ jsonrpc: "2.0", id, result: this.initializeResult(params) });
109
+ return;
110
+ case "ping":
111
+ await this.send({ jsonrpc: "2.0", id, result: {} });
112
+ return;
113
+ case "tools/list":
114
+ await this.send({ jsonrpc: "2.0", id, result: { tools: this.listTools() } });
115
+ return;
116
+ case "tools/call":
117
+ await this.send({ jsonrpc: "2.0", id, result: await this.callTool(params) });
118
+ return;
119
+ default:
120
+ await this.sendError(id, JSONRPC_METHOD_NOT_FOUND, `Method not found: ${method}`);
121
+ return;
122
+ }
123
+ } catch (err) {
124
+ await this.sendError(id, JSONRPC_INVALID_REQUEST, err instanceof Error ? err.message : String(err));
125
+ }
126
+ }
127
+ async sendError(id, code, message) {
128
+ await this.send({ jsonrpc: "2.0", id, error: { code, message } });
129
+ }
130
+ initializeResult(params) {
131
+ const requested = params["protocolVersion"];
132
+ const protocolVersion = typeof requested === "string" && SUPPORTED_PROTOCOL_VERSIONS.includes(requested) ? requested : LATEST_PROTOCOL_VERSION;
133
+ return {
134
+ protocolVersion,
135
+ // Tools only, and they never change after startup, so no `listChanged`. This is the one
136
+ // place we deliberately do not copy the SDK, which declares `listChanged: true` because its
137
+ // McpServer is *able* to send that notification. Token-goat registers every tool before it
138
+ // connects and never adds or removes one, so we would be promising a notification we can
139
+ // never have cause to send. No client behaviour turns on it either way -- a subscription
140
+ // that never fires and an absent subscription are the same thing when the list is fixed --
141
+ // so the honest declaration wins. Contrast the tool-error text below, which a model reads as
142
+ // content and is therefore matched to the SDK exactly.
143
+ capabilities: { tools: {} },
144
+ serverInfo: { name: this.info.name, version: this.info.version }
145
+ };
146
+ }
147
+ listTools() {
148
+ return [...this.tools.values()].map((tool) => ({
149
+ name: tool.name,
150
+ ...tool.description !== void 0 ? { description: tool.description } : {},
151
+ inputSchema: tool.jsonSchema,
152
+ // The SDK emits this for every tool it registers, and it is literally true of ours: we do
153
+ // not implement task augmentation, so a client that asks for it gets refused. Emitting the
154
+ // same thing keeps `tools/list` byte-identical to what token-goat sent before, which is what
155
+ // the differential test in tests/mcp_jsonrpc.test.ts pins.
156
+ execution: { taskSupport: "forbidden" }
157
+ }));
158
+ }
159
+ async callTool(params) {
160
+ const name = params["name"];
161
+ if (typeof name !== "string") return errorText('Invalid params: tools/call requires a string "name"');
162
+ const tool = this.tools.get(name);
163
+ const handler = this.handlers.get(name);
164
+ if (tool === void 0 || handler === void 0) return errorText(`${MCP_INVALID_PARAMS_PREFIX}Tool ${name} not found`);
165
+ const parsed = tool.validator.safeParse(params["arguments"] ?? {});
166
+ if (!parsed.success) {
167
+ return errorText(
168
+ `${MCP_INVALID_PARAMS_PREFIX}Input validation error: Invalid arguments for tool ${name}: ${describeParseError(parsed.error)}`
169
+ );
170
+ }
171
+ try {
172
+ return await handler(parsed.data);
173
+ } catch (err) {
174
+ return errorText(err instanceof Error ? err.message : String(err));
175
+ }
176
+ }
177
+ };
178
+ export {
179
+ JSONRPC_INVALID_PARAMS,
180
+ JSONRPC_INVALID_REQUEST,
181
+ JSONRPC_METHOD_NOT_FOUND,
182
+ LATEST_PROTOCOL_VERSION,
183
+ McpServer,
184
+ SUPPORTED_PROTOCOL_VERSIONS
185
+ };
@@ -25,7 +25,7 @@ import {
25
25
  runSkeleton,
26
26
  runSymbol,
27
27
  withPinnedReads
28
- } from "./token-goat-chunk-IYTVE6KN.mjs";
28
+ } from "./token-goat-chunk-RMDQFTQD.mjs";
29
29
  import {
30
30
  buildProjectMap,
31
31
  embeddingsDepsAvailable,
@@ -34,7 +34,7 @@ import {
34
34
  getProjectIndexCounts,
35
35
  isWorkerRunning,
36
36
  mapLookupBytesSaved
37
- } from "./token-goat-chunk-UFOVM7ZN.mjs";
37
+ } from "./token-goat-chunk-2G6RAB4G.mjs";
38
38
  import {
39
39
  VERSION,
40
40
  dataDir,
@@ -45,7 +45,7 @@ import {
45
45
  normalizePath,
46
46
  recordStat,
47
47
  resolveProjectRoot
48
- } from "./token-goat-chunk-V465YKOR.mjs";
48
+ } from "./token-goat-chunk-ELDJRLHZ.mjs";
49
49
  import "./token-goat-chunk-AO2QD2AG.mjs";
50
50
  import "./token-goat-chunk-AEX54RUZ.mjs";
51
51
 
@@ -201,7 +201,7 @@ function withConfinedRead(pins, fn) {
201
201
  }
202
202
  }
203
203
  async function createMcpServer() {
204
- const [{ McpServer }, { z }] = await Promise.all([import("@modelcontextprotocol/sdk/server/mcp.js"), import("./token-goat-chunk-DG53MVNJ.mjs")]);
204
+ const [{ McpServer }, { z }] = await Promise.all([import("./token-goat-chunk-5CVKO3DA.mjs"), import("./token-goat-chunk-R4SR7MQY.mjs")]);
205
205
  const server = new McpServer({ name: "token-goat", version: VERSION });
206
206
  const makeProjectRootField = (verb) => z.string().optional().describe(
207
207
  `absolute path to the workspace root to scope this ${verb} to; defaults to the MCP server process's cwd, which is not always the actual workspace root for MCP clients -- pass this explicitly when it might differ`
@@ -4,7 +4,7 @@ import {
4
4
  loadConfig,
5
5
  redactSecrets,
6
6
  stripAnsiCodes
7
- } from "./token-goat-chunk-V465YKOR.mjs";
7
+ } from "./token-goat-chunk-ELDJRLHZ.mjs";
8
8
 
9
9
  // src/tool_filters/helpers.ts
10
10
  import * as fs from "node:fs";