@mekareteriker/opencode-mcp 1.10.2-mekareteriker.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.
Files changed (55) hide show
  1. package/CHANGELOG.md +204 -0
  2. package/LICENSE +22 -0
  3. package/README.md +174 -0
  4. package/dist/client.d.ts +60 -0
  5. package/dist/client.js +282 -0
  6. package/dist/client.js.map +1 -0
  7. package/dist/helpers.d.ts +150 -0
  8. package/dist/helpers.js +575 -0
  9. package/dist/helpers.js.map +1 -0
  10. package/dist/index.d.ts +30 -0
  11. package/dist/index.js +198 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/prompts.d.ts +9 -0
  14. package/dist/prompts.js +210 -0
  15. package/dist/prompts.js.map +1 -0
  16. package/dist/resources.d.ts +10 -0
  17. package/dist/resources.js +197 -0
  18. package/dist/resources.js.map +1 -0
  19. package/dist/server-manager.d.ts +72 -0
  20. package/dist/server-manager.js +264 -0
  21. package/dist/server-manager.js.map +1 -0
  22. package/dist/tools/config.d.ts +3 -0
  23. package/dist/tools/config.js +105 -0
  24. package/dist/tools/config.js.map +1 -0
  25. package/dist/tools/events.d.ts +6 -0
  26. package/dist/tools/events.js +63 -0
  27. package/dist/tools/events.js.map +1 -0
  28. package/dist/tools/file.d.ts +3 -0
  29. package/dist/tools/file.js +153 -0
  30. package/dist/tools/file.js.map +1 -0
  31. package/dist/tools/global.d.ts +3 -0
  32. package/dist/tools/global.js +17 -0
  33. package/dist/tools/global.js.map +1 -0
  34. package/dist/tools/message.d.ts +3 -0
  35. package/dist/tools/message.js +169 -0
  36. package/dist/tools/message.js.map +1 -0
  37. package/dist/tools/misc.d.ts +3 -0
  38. package/dist/tools/misc.js +298 -0
  39. package/dist/tools/misc.js.map +1 -0
  40. package/dist/tools/project.d.ts +3 -0
  41. package/dist/tools/project.js +62 -0
  42. package/dist/tools/project.js.map +1 -0
  43. package/dist/tools/provider.d.ts +3 -0
  44. package/dist/tools/provider.js +175 -0
  45. package/dist/tools/provider.js.map +1 -0
  46. package/dist/tools/session.d.ts +3 -0
  47. package/dist/tools/session.js +392 -0
  48. package/dist/tools/session.js.map +1 -0
  49. package/dist/tools/tui.d.ts +7 -0
  50. package/dist/tools/tui.js +121 -0
  51. package/dist/tools/tui.js.map +1 -0
  52. package/dist/tools/workflow.d.ts +7 -0
  53. package/dist/tools/workflow.js +775 -0
  54. package/dist/tools/workflow.js.map +1 -0
  55. package/package.json +68 -0
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Auto-detection and auto-start of the OpenCode headless server.
3
+ *
4
+ * This module handles:
5
+ * 1. Checking if `opencode serve` is already running (health check)
6
+ * 2. Finding the `opencode` binary on the system
7
+ * 3. Spawning `opencode serve` as a child process if needed
8
+ * 4. Graceful shutdown of the child process on exit
9
+ *
10
+ * Controlled via environment variables:
11
+ * OPENCODE_AUTO_SERVE - Set to "false" to disable auto-start (default: true)
12
+ * OPENCODE_BASE_URL - Base URL of the server (default: http://127.0.0.1:4096)
13
+ */
14
+ export interface ServerManagerOptions {
15
+ baseUrl: string;
16
+ /** Disable auto-start entirely. */
17
+ autoServe?: boolean;
18
+ /** Max time (ms) to wait for the server to become healthy after spawning. */
19
+ startupTimeoutMs?: number;
20
+ /** Username for HTTP basic auth (optional) */
21
+ username?: string;
22
+ /** Password for HTTP basic auth (optional) */
23
+ password?: string;
24
+ }
25
+ export interface ServerStatus {
26
+ running: boolean;
27
+ version?: string;
28
+ managedByUs: boolean;
29
+ }
30
+ /**
31
+ * Check if the OpenCode server is already running by hitting the health endpoint.
32
+ * Returns `{ healthy: true, version }` or `{ healthy: false }`.
33
+ */
34
+ export declare function isServerRunning(baseUrl: string, username?: string, password?: string): Promise<{
35
+ healthy: boolean;
36
+ version?: string;
37
+ }>;
38
+ /**
39
+ * Attempt to find the `opencode` binary on the system.
40
+ * Returns the full path or null if not found.
41
+ */
42
+ export declare function findBinary(): Promise<string | null>;
43
+ /**
44
+ * Get the installed OpenCode version. Returns null if not installed.
45
+ */
46
+ export declare function getInstalledVersion(binaryPath: string): Promise<string | null>;
47
+ /**
48
+ * Build installation instructions for when the binary is not found.
49
+ */
50
+ export declare function getInstallInstructions(): string;
51
+ /**
52
+ * Spawn `opencode serve` as a background child process.
53
+ * Waits until the health endpoint responds or the timeout elapses.
54
+ *
55
+ * @throws Error if the binary is not found or the server fails to start.
56
+ */
57
+ export declare function startServer(binaryPath: string, baseUrl: string, timeoutMs?: number, username?: string, password?: string): Promise<{
58
+ version?: string;
59
+ }>;
60
+ /**
61
+ * Stop the managed child process (if we started one).
62
+ */
63
+ export declare function stopServer(): void;
64
+ /**
65
+ * Main entry point: ensure the OpenCode server is available.
66
+ *
67
+ * Returns a status object describing the result.
68
+ * Logs progress to stderr (MCP servers use stdout for the transport).
69
+ *
70
+ * @throws Error if the server cannot be reached and auto-start fails.
71
+ */
72
+ export declare function ensureServer(opts: ServerManagerOptions): Promise<ServerStatus>;
@@ -0,0 +1,264 @@
1
+ /**
2
+ * Auto-detection and auto-start of the OpenCode headless server.
3
+ *
4
+ * This module handles:
5
+ * 1. Checking if `opencode serve` is already running (health check)
6
+ * 2. Finding the `opencode` binary on the system
7
+ * 3. Spawning `opencode serve` as a child process if needed
8
+ * 4. Graceful shutdown of the child process on exit
9
+ *
10
+ * Controlled via environment variables:
11
+ * OPENCODE_AUTO_SERVE - Set to "false" to disable auto-start (default: true)
12
+ * OPENCODE_BASE_URL - Base URL of the server (default: http://127.0.0.1:4096)
13
+ */
14
+ import { execFile, spawn } from "node:child_process";
15
+ import { promisify } from "node:util";
16
+ const execFileAsync = promisify(execFile);
17
+ const DEFAULT_STARTUP_TIMEOUT_MS = 30_000;
18
+ const HEALTH_POLL_INTERVAL_MS = 500;
19
+ /** Singleton child process reference so we can clean up on exit. */
20
+ let managedProcess = null;
21
+ let shutdownRegistered = false;
22
+ /**
23
+ * Check if the OpenCode server is already running by hitting the health endpoint.
24
+ * Returns `{ healthy: true, version }` or `{ healthy: false }`.
25
+ */
26
+ export async function isServerRunning(baseUrl, username, password) {
27
+ try {
28
+ const url = `${baseUrl.replace(/\/$/, "")}/global/health`;
29
+ const controller = new AbortController();
30
+ const timeout = setTimeout(() => controller.abort(), 3_000);
31
+ const headers = {};
32
+ if (password) {
33
+ const user = username ?? "opencode";
34
+ headers["Authorization"] = "Basic " + Buffer.from(`${user}:${password}`).toString("base64");
35
+ }
36
+ const res = await fetch(url, {
37
+ method: "GET",
38
+ headers,
39
+ signal: controller.signal,
40
+ });
41
+ clearTimeout(timeout);
42
+ if (res.ok) {
43
+ const body = (await res.json());
44
+ return {
45
+ healthy: body.healthy === true,
46
+ version: typeof body.version === "string" ? body.version : undefined,
47
+ };
48
+ }
49
+ return { healthy: false };
50
+ }
51
+ catch {
52
+ return { healthy: false };
53
+ }
54
+ }
55
+ /**
56
+ * Attempt to find the `opencode` binary on the system.
57
+ * Returns the full path or null if not found.
58
+ */
59
+ export async function findBinary() {
60
+ const cmd = process.platform === "win32" ? "where" : "which";
61
+ try {
62
+ const { stdout } = await execFileAsync(cmd, ["opencode"]);
63
+ const path = stdout.trim().split("\n")[0]?.trim();
64
+ return path || null;
65
+ }
66
+ catch {
67
+ return null;
68
+ }
69
+ }
70
+ /**
71
+ * Get the installed OpenCode version. Returns null if not installed.
72
+ */
73
+ export async function getInstalledVersion(binaryPath) {
74
+ try {
75
+ const { stdout } = await execFileAsync(binaryPath, ["--version"]);
76
+ return stdout.trim() || null;
77
+ }
78
+ catch {
79
+ return null;
80
+ }
81
+ }
82
+ /**
83
+ * Build installation instructions for when the binary is not found.
84
+ */
85
+ export function getInstallInstructions() {
86
+ return [
87
+ "OpenCode is not installed on this system.",
88
+ "",
89
+ "Install it using one of these methods:",
90
+ " curl -fsSL https://opencode.ai/install | bash",
91
+ " npm i -g opencode-ai",
92
+ " brew install sst/tap/opencode",
93
+ "",
94
+ "For more options: https://opencode.ai",
95
+ "",
96
+ "After installing, restart the MCP server.",
97
+ "To disable auto-start: set OPENCODE_AUTO_SERVE=false",
98
+ ].join("\n");
99
+ }
100
+ /**
101
+ * Parse host and port from a base URL.
102
+ */
103
+ function parseBaseUrl(baseUrl) {
104
+ const url = new URL(baseUrl);
105
+ return {
106
+ hostname: url.hostname,
107
+ port: url.port ? parseInt(url.port, 10) : 4096,
108
+ };
109
+ }
110
+ /**
111
+ * Poll the health endpoint until the server responds or timeout elapses.
112
+ */
113
+ async function waitForHealthy(baseUrl, timeoutMs, username, password) {
114
+ const deadline = Date.now() + timeoutMs;
115
+ while (Date.now() < deadline) {
116
+ const { healthy } = await isServerRunning(baseUrl, username, password);
117
+ if (healthy)
118
+ return true;
119
+ await new Promise((r) => setTimeout(r, HEALTH_POLL_INTERVAL_MS));
120
+ }
121
+ return false;
122
+ }
123
+ /**
124
+ * Register process-exit handlers to kill the managed child process.
125
+ * Only registers once even if called multiple times.
126
+ */
127
+ function registerShutdownHandlers() {
128
+ if (shutdownRegistered)
129
+ return;
130
+ shutdownRegistered = true;
131
+ const cleanup = () => {
132
+ if (managedProcess && !managedProcess.killed) {
133
+ managedProcess.kill("SIGTERM");
134
+ managedProcess = null;
135
+ }
136
+ };
137
+ process.on("exit", cleanup);
138
+ process.on("SIGINT", () => {
139
+ cleanup();
140
+ process.exit(0);
141
+ });
142
+ process.on("SIGTERM", () => {
143
+ cleanup();
144
+ process.exit(0);
145
+ });
146
+ }
147
+ /**
148
+ * Spawn `opencode serve` as a background child process.
149
+ * Waits until the health endpoint responds or the timeout elapses.
150
+ *
151
+ * @throws Error if the binary is not found or the server fails to start.
152
+ */
153
+ export async function startServer(binaryPath, baseUrl, timeoutMs = DEFAULT_STARTUP_TIMEOUT_MS, username, password) {
154
+ const { hostname, port } = parseBaseUrl(baseUrl);
155
+ const args = ["serve", "--port", String(port)];
156
+ if (hostname !== "127.0.0.1" && hostname !== "localhost") {
157
+ args.push("--hostname", hostname);
158
+ }
159
+ // Allow passing custom parameters to `opencode serve`
160
+ if (process.env.OPENCODE_SERVE_ARGS) {
161
+ const extraArgs = process.env.OPENCODE_SERVE_ARGS.match(/[^\s"']+|"([^"]*)"|'([^']*)'/g) || [];
162
+ for (const arg of extraArgs) {
163
+ args.push(arg.replace(/^['"]|['"]$/g, ""));
164
+ }
165
+ }
166
+ const child = spawn(binaryPath, args, {
167
+ stdio: ["ignore", "pipe", "pipe"],
168
+ detached: false,
169
+ });
170
+ managedProcess = child;
171
+ registerShutdownHandlers();
172
+ // Collect stderr for diagnostics if the process exits early.
173
+ let stderrOutput = "";
174
+ child.stderr?.on("data", (chunk) => {
175
+ stderrOutput += chunk.toString();
176
+ });
177
+ // Also watch stdout for the "listening" line (informational).
178
+ let stdoutOutput = "";
179
+ child.stdout?.on("data", (chunk) => {
180
+ stdoutOutput += chunk.toString();
181
+ });
182
+ // Reject early if the child process exits before becoming healthy.
183
+ const earlyExit = new Promise((_, reject) => {
184
+ child.on("error", (err) => {
185
+ reject(new Error(`Failed to start opencode serve: ${err.message}`));
186
+ });
187
+ child.on("exit", (code) => {
188
+ if (code !== null && code !== 0) {
189
+ reject(new Error(`opencode serve exited with code ${code}.\n${stderrOutput || stdoutOutput}`));
190
+ }
191
+ });
192
+ });
193
+ // Race: either the server becomes healthy or the child crashes.
194
+ const healthy = await Promise.race([
195
+ waitForHealthy(baseUrl, timeoutMs, username, password),
196
+ earlyExit.catch(() => false),
197
+ ]);
198
+ if (!healthy) {
199
+ // Kill the child if it's still around.
200
+ if (!child.killed)
201
+ child.kill("SIGTERM");
202
+ managedProcess = null;
203
+ throw new Error(`opencode serve did not become healthy within ${timeoutMs / 1000}s.\n` +
204
+ `stderr: ${stderrOutput}\nstdout: ${stdoutOutput}`);
205
+ }
206
+ // Grab the version from the now-running server.
207
+ const status = await isServerRunning(baseUrl, username, password);
208
+ return { version: status.version };
209
+ }
210
+ /**
211
+ * Stop the managed child process (if we started one).
212
+ */
213
+ export function stopServer() {
214
+ if (managedProcess && !managedProcess.killed) {
215
+ managedProcess.kill("SIGTERM");
216
+ managedProcess = null;
217
+ }
218
+ }
219
+ /**
220
+ * Main entry point: ensure the OpenCode server is available.
221
+ *
222
+ * Returns a status object describing the result.
223
+ * Logs progress to stderr (MCP servers use stdout for the transport).
224
+ *
225
+ * @throws Error if the server cannot be reached and auto-start fails.
226
+ */
227
+ export async function ensureServer(opts) {
228
+ const baseUrl = opts.baseUrl;
229
+ const autoServe = opts.autoServe !== false;
230
+ const timeoutMs = opts.startupTimeoutMs ?? DEFAULT_STARTUP_TIMEOUT_MS;
231
+ // Step 1: Check if server is already running.
232
+ const existing = await isServerRunning(baseUrl, opts.username, opts.password);
233
+ if (existing.healthy) {
234
+ console.error(`OpenCode server already running at ${baseUrl} (v${existing.version ?? "unknown"})`);
235
+ return {
236
+ running: true,
237
+ version: existing.version,
238
+ managedByUs: false,
239
+ };
240
+ }
241
+ // If auto-serve is disabled, just report that the server isn't running.
242
+ if (!autoServe) {
243
+ throw new Error(`OpenCode server is not running at ${baseUrl} and OPENCODE_AUTO_SERVE=false.\n` +
244
+ `Start it manually: opencode serve`);
245
+ }
246
+ // Step 2: Find the opencode binary.
247
+ console.error("OpenCode server not detected, attempting auto-start...");
248
+ const binaryPath = await findBinary();
249
+ if (!binaryPath) {
250
+ throw new Error(getInstallInstructions());
251
+ }
252
+ const version = await getInstalledVersion(binaryPath);
253
+ console.error(`Found opencode binary at ${binaryPath}${version ? ` (${version})` : ""}`);
254
+ // Step 3: Start the server.
255
+ console.error(`Starting: opencode serve --port ${parseBaseUrl(baseUrl).port}`);
256
+ const result = await startServer(binaryPath, baseUrl, timeoutMs, opts.username, opts.password);
257
+ console.error(`OpenCode server started successfully (v${result.version ?? "unknown"})`);
258
+ return {
259
+ running: true,
260
+ version: result.version,
261
+ managedByUs: true,
262
+ };
263
+ }
264
+ //# sourceMappingURL=server-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-manager.js","sourceRoot":"","sources":["../src/server-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { OpenCodeClient } from "../client.js";
3
+ export declare function registerConfigTools(server: McpServer, client: OpenCodeClient): void;
@@ -0,0 +1,105 @@
1
+ import { z } from "zod";
2
+ import { toolJson, toolError, toolResult, redactSecrets, directoryParam } from "../helpers.js";
3
+ export function registerConfigTools(server, client) {
4
+ server.tool("opencode_config_get", "Get the current opencode configuration", {
5
+ directory: directoryParam,
6
+ }, async ({ directory }) => {
7
+ try {
8
+ const config = await client.get("/config", undefined, directory);
9
+ const c = redactSecrets(config);
10
+ // Build a compact summary instead of dumping entire config
11
+ const lines = [];
12
+ for (const [k, v] of Object.entries(c)) {
13
+ if (v && typeof v === "object" && !Array.isArray(v)) {
14
+ const keys = Object.keys(v);
15
+ if (keys.length <= 5) {
16
+ // Small objects: show inline
17
+ const inner = Object.entries(v)
18
+ .map(([sk, sv]) => {
19
+ if (sv && typeof sv === "object")
20
+ return `${sk}: {..}`;
21
+ return `${sk}: ${sv}`;
22
+ })
23
+ .join(", ");
24
+ lines.push(`${k}: { ${inner} }`);
25
+ }
26
+ else {
27
+ lines.push(`${k}: {${keys.length} entries}`);
28
+ }
29
+ }
30
+ else if (Array.isArray(v)) {
31
+ if (v.length <= 3) {
32
+ lines.push(`${k}: ${JSON.stringify(v)}`);
33
+ }
34
+ else {
35
+ lines.push(`${k}: [${v.length} items]`);
36
+ }
37
+ }
38
+ else {
39
+ lines.push(`${k}: ${v}`);
40
+ }
41
+ }
42
+ return toolResult(`## OpenCode Config\n${lines.join("\n")}\n\nUse \`opencode_config_update\` to modify specific settings.`);
43
+ }
44
+ catch (e) {
45
+ return toolError(e);
46
+ }
47
+ });
48
+ server.tool("opencode_config_update", "Update the opencode configuration. Pass a partial config object with fields to update.", {
49
+ config: z
50
+ .record(z.string(), z.unknown())
51
+ .describe("Partial config object with fields to update"),
52
+ directory: directoryParam,
53
+ }, async ({ config, directory }) => {
54
+ try {
55
+ return toolJson(await client.patch("/config", config, directory));
56
+ }
57
+ catch (e) {
58
+ return toolError(e);
59
+ }
60
+ });
61
+ server.tool("opencode_config_providers", "List all configured providers and their default models", {
62
+ directory: directoryParam,
63
+ }, async ({ directory }) => {
64
+ try {
65
+ const raw = await client.get("/config/providers", undefined, directory);
66
+ const wrapper = raw;
67
+ // API returns { providers: [...], default: { providerId: modelId, ... } }
68
+ const providerList = Array.isArray(wrapper?.providers)
69
+ ? wrapper.providers
70
+ : Array.isArray(raw)
71
+ ? raw
72
+ : [];
73
+ const defaults = (wrapper?.default ?? {});
74
+ if (providerList.length === 0) {
75
+ return toolResult("No configured providers found.");
76
+ }
77
+ const lines = providerList.map((p) => {
78
+ const id = (p.id ?? "?");
79
+ const name = (p.name ?? id);
80
+ const models = p.models;
81
+ const modelCount = Array.isArray(models)
82
+ ? models.length
83
+ : models && typeof models === "object"
84
+ ? Object.keys(models).length
85
+ : 0;
86
+ const defaultModel = defaults[id] ?? "";
87
+ const defaultStr = defaultModel ? ` (default: ${defaultModel})` : "";
88
+ return `- ${id} (${name}): ${modelCount} model${modelCount !== 1 ? "s" : ""}${defaultStr}`;
89
+ });
90
+ // Show defaults summary if there are entries not in the provider list
91
+ const extraDefaults = Object.entries(defaults).filter(([id]) => !providerList.some((p) => p.id === id));
92
+ const extraLines = extraDefaults.map(([id, model]) => `- ${id}: ${model}`);
93
+ let output = `## Configured Providers (${providerList.length})\n${lines.join("\n")}`;
94
+ if (extraLines.length > 0) {
95
+ output += `\n\n## Additional Default Models\n${extraLines.join("\n")}`;
96
+ }
97
+ output += `\n\nUse \`opencode_provider_models\` with a provider ID to see full model details.`;
98
+ return toolResult(output);
99
+ }
100
+ catch (e) {
101
+ return toolError(e);
102
+ }
103
+ });
104
+ }
105
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/tools/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Event streaming tools — subscribe to real-time events from OpenCode.
3
+ */
4
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
+ import { OpenCodeClient } from "../client.js";
6
+ export declare function registerEventTools(server: McpServer, client: OpenCodeClient): void;
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Event streaming tools — subscribe to real-time events from OpenCode.
3
+ */
4
+ import { z } from "zod";
5
+ import { toolResult, toolError, directoryParam } from "../helpers.js";
6
+ export function registerEventTools(server, client) {
7
+ server.tool("opencode_events_poll", "Poll for recent events from the OpenCode server. Collects events for the specified duration and returns them. Useful for monitoring session activity, deployments, and system changes.", {
8
+ durationMs: z
9
+ .number()
10
+ .optional()
11
+ .describe("How long to collect events in milliseconds (default: 3000, max: 30000)"),
12
+ maxEvents: z
13
+ .number()
14
+ .optional()
15
+ .describe("Maximum number of events to collect (default: 50)"),
16
+ directory: directoryParam,
17
+ }, async ({ durationMs, maxEvents, directory: _directory }) => {
18
+ try {
19
+ const duration = Math.min(durationMs ?? 3000, 30000);
20
+ const max = maxEvents ?? 50;
21
+ const events = [];
22
+ // Note: SSE subscribeSSE does not currently support the directory
23
+ // header. The event stream is server-wide. The directory param is
24
+ // accepted for API consistency but not forwarded to SSE.
25
+ const controller = new AbortController();
26
+ const timeout = setTimeout(() => controller.abort(), duration);
27
+ try {
28
+ for await (const evt of client.subscribeSSE("/event", { signal: controller.signal })) {
29
+ events.push(evt);
30
+ if (events.length >= max)
31
+ break;
32
+ if (controller.signal.aborted)
33
+ break;
34
+ }
35
+ }
36
+ catch {
37
+ // SSE connection will error when aborted — that's expected
38
+ }
39
+ finally {
40
+ clearTimeout(timeout);
41
+ }
42
+ if (events.length === 0) {
43
+ return toolResult("No events received during the polling period.");
44
+ }
45
+ const formatted = events
46
+ .map((e) => {
47
+ try {
48
+ const parsed = JSON.parse(e.data);
49
+ return `[${e.event}] ${JSON.stringify(parsed, null, 2)}`;
50
+ }
51
+ catch {
52
+ return `[${e.event}] ${e.data}`;
53
+ }
54
+ })
55
+ .join("\n\n");
56
+ return toolResult(`Collected ${events.length} event(s):\n\n${formatted}`);
57
+ }
58
+ catch (e) {
59
+ return toolError(e);
60
+ }
61
+ });
62
+ }
63
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/tools/events.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEtE,MAAM,UAAU,kBAAkB,CAChC,MAAiB,EACjB,MAAsB;IAEtB,MAAM,CAAC,IAAI,CACT,sBAAsB,EACtB,wLAAwL,EACxL;QACE,UAAU,EAAE,CAAC;aACV,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,wEAAwE,CACzE;QACH,SAAS,EAAE,CAAC;aACT,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,mDAAmD,CAAC;QAChE,SAAS,EAAE,cAAc;KAC1B,EACD,KAAK,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,EAAE,EAAE;QACzD,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,IAAI,IAAI,EAAE,KAAK,CAAC,CAAC;YACrD,MAAM,GAAG,GAAG,SAAS,IAAI,EAAE,CAAC;YAC5B,MAAM,MAAM,GAA2C,EAAE,CAAC;YAE1D,kEAAkE;YAClE,kEAAkE;YAClE,yDAAyD;YAEzD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;YACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,QAAQ,CAAC,CAAC;YAE/D,IAAI,CAAC;gBACH,IAAI,KAAK,EAAE,MAAM,GAAG,IAAI,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;oBACrF,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;oBACjB,IAAI,MAAM,CAAC,MAAM,IAAI,GAAG;wBAAE,MAAM;oBAChC,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO;wBAAE,MAAM;gBACvC,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,2DAA2D;YAC7D,CAAC;oBAAS,CAAC;gBACT,YAAY,CAAC,OAAO,CAAC,CAAC;YACxB,CAAC;YAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxB,OAAO,UAAU,CAAC,+CAA+C,CAAC,CAAC;YACrE,CAAC;YAED,MAAM,SAAS,GAAG,MAAM;iBACrB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBACT,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;oBAClC,OAAO,IAAI,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;gBAC3D,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;gBAClC,CAAC;YACH,CAAC,CAAC;iBACD,IAAI,CAAC,MAAM,CAAC,CAAC;YAEhB,OAAO,UAAU,CACf,aAAa,MAAM,CAAC,MAAM,iBAAiB,SAAS,EAAE,CACvD,CAAC;QACJ,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { OpenCodeClient } from "../client.js";
3
+ export declare function registerFileTools(server: McpServer, client: OpenCodeClient): void;