mcp-server-opencode 1.0.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 +129 -0
- package/build/src/index.d.ts +3 -0
- package/build/src/index.d.ts.map +1 -0
- package/build/src/index.js +35 -0
- package/build/src/index.js.map +1 -0
- package/build/src/modules/prompts/delegate_task.d.ts +3 -0
- package/build/src/modules/prompts/delegate_task.d.ts.map +1 -0
- package/build/src/modules/prompts/delegate_task.js +33 -0
- package/build/src/modules/prompts/delegate_task.js.map +1 -0
- package/build/src/modules/prompts/index.d.ts +3 -0
- package/build/src/modules/prompts/index.d.ts.map +1 -0
- package/build/src/modules/prompts/index.js +5 -0
- package/build/src/modules/prompts/index.js.map +1 -0
- package/build/src/modules/shared/config.d.ts +12 -0
- package/build/src/modules/shared/config.d.ts.map +1 -0
- package/build/src/modules/shared/config.js +33 -0
- package/build/src/modules/shared/config.js.map +1 -0
- package/build/src/modules/shared/mcp-result.d.ts +16 -0
- package/build/src/modules/shared/mcp-result.d.ts.map +1 -0
- package/build/src/modules/shared/mcp-result.js +14 -0
- package/build/src/modules/shared/mcp-result.js.map +1 -0
- package/build/src/modules/shared/opencode-client.d.ts +27 -0
- package/build/src/modules/shared/opencode-client.d.ts.map +1 -0
- package/build/src/modules/shared/opencode-client.js +58 -0
- package/build/src/modules/shared/opencode-client.js.map +1 -0
- package/build/src/modules/shared/server-registry.d.ts +10 -0
- package/build/src/modules/shared/server-registry.d.ts.map +1 -0
- package/build/src/modules/shared/server-registry.js +17 -0
- package/build/src/modules/shared/server-registry.js.map +1 -0
- package/build/src/modules/shared/task-registry.d.ts +9 -0
- package/build/src/modules/shared/task-registry.d.ts.map +1 -0
- package/build/src/modules/shared/task-registry.js +11 -0
- package/build/src/modules/shared/task-registry.js.map +1 -0
- package/build/src/modules/tools/get_task_result.d.ts +3 -0
- package/build/src/modules/tools/get_task_result.d.ts.map +1 -0
- package/build/src/modules/tools/get_task_result.js +47 -0
- package/build/src/modules/tools/get_task_result.js.map +1 -0
- package/build/src/modules/tools/get_task_status.d.ts +3 -0
- package/build/src/modules/tools/get_task_status.d.ts.map +1 -0
- package/build/src/modules/tools/get_task_status.js +29 -0
- package/build/src/modules/tools/get_task_status.js.map +1 -0
- package/build/src/modules/tools/index.d.ts +3 -0
- package/build/src/modules/tools/index.d.ts.map +1 -0
- package/build/src/modules/tools/index.js +18 -0
- package/build/src/modules/tools/index.js.map +1 -0
- package/build/src/modules/tools/list_agents.d.ts +3 -0
- package/build/src/modules/tools/list_agents.d.ts.map +1 -0
- package/build/src/modules/tools/list_agents.js +74 -0
- package/build/src/modules/tools/list_agents.js.map +1 -0
- package/build/src/modules/tools/start_server.d.ts +3 -0
- package/build/src/modules/tools/start_server.d.ts.map +1 -0
- package/build/src/modules/tools/start_server.js +51 -0
- package/build/src/modules/tools/start_server.js.map +1 -0
- package/build/src/modules/tools/start_task.d.ts +3 -0
- package/build/src/modules/tools/start_task.d.ts.map +1 -0
- package/build/src/modules/tools/start_task.js +75 -0
- package/build/src/modules/tools/start_task.js.map +1 -0
- package/build/src/modules/tools/stop_server.d.ts +3 -0
- package/build/src/modules/tools/stop_server.d.ts.map +1 -0
- package/build/src/modules/tools/stop_server.js +34 -0
- package/build/src/modules/tools/stop_server.js.map +1 -0
- package/build/src/modules/tools/wait_for_task.d.ts +3 -0
- package/build/src/modules/tools/wait_for_task.d.ts.map +1 -0
- package/build/src/modules/tools/wait_for_task.js +86 -0
- package/build/src/modules/tools/wait_for_task.js.map +1 -0
- package/build/src/test-utils/fake-mcp-server.d.ts +10 -0
- package/build/src/test-utils/fake-mcp-server.d.ts.map +1 -0
- package/build/src/test-utils/fake-mcp-server.js +33 -0
- package/build/src/test-utils/fake-mcp-server.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Tools
|
|
2
|
+
import { registerOpencodeGetTaskResult } from "./get_task_result.js";
|
|
3
|
+
import { registerOpencodeGetTaskStatus } from "./get_task_status.js";
|
|
4
|
+
import { registerOpencodeListAgents } from "./list_agents.js";
|
|
5
|
+
import { registerOpencodeStartServer } from "./start_server.js";
|
|
6
|
+
import { registerOpencodeStartTask } from "./start_task.js";
|
|
7
|
+
import { registerOpencodeStopServer } from "./stop_server.js";
|
|
8
|
+
import { registerOpencodeWaitForTask } from "./wait_for_task.js";
|
|
9
|
+
export function registerTools(server) {
|
|
10
|
+
registerOpencodeStartServer(server);
|
|
11
|
+
registerOpencodeStopServer(server);
|
|
12
|
+
registerOpencodeListAgents(server);
|
|
13
|
+
registerOpencodeStartTask(server);
|
|
14
|
+
registerOpencodeGetTaskStatus(server);
|
|
15
|
+
registerOpencodeGetTaskResult(server);
|
|
16
|
+
registerOpencodeWaitForTask(server);
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modules/tools/index.ts"],"names":[],"mappings":"AACA,QAAQ;AACR,OAAO,EAAE,6BAA6B,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,6BAA6B,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAC;AAEjE,MAAM,UAAU,aAAa,CAAC,MAAiB;IAC7C,2BAA2B,CAAC,MAAM,CAAC,CAAC;IACpC,0BAA0B,CAAC,MAAM,CAAC,CAAC;IACnC,0BAA0B,CAAC,MAAM,CAAC,CAAC;IACnC,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAClC,6BAA6B,CAAC,MAAM,CAAC,CAAC;IACtC,6BAA6B,CAAC,MAAM,CAAC,CAAC;IACtC,2BAA2B,CAAC,MAAM,CAAC,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list_agents.d.ts","sourceRoot":"","sources":["../../../../src/modules/tools/list_agents.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA8CzE,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,SAAS,QAgD3D"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { createOpencodeClient } from "@opencode-ai/sdk";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { jsonError, jsonResult } from "../shared/mcp-result.js";
|
|
4
|
+
import { getServer } from "../shared/server-registry.js";
|
|
5
|
+
// Current opencode servers report the built-in flag as `native`; the SDK types
|
|
6
|
+
// still declare the older `builtIn` field, so check both.
|
|
7
|
+
function isNativeAgent(agent) {
|
|
8
|
+
return agent.native ?? agent.builtIn ?? false;
|
|
9
|
+
}
|
|
10
|
+
function toAgentSummary(agent) {
|
|
11
|
+
return {
|
|
12
|
+
name: agent.name,
|
|
13
|
+
mode: agent.mode,
|
|
14
|
+
...(agent.description ? { description: agent.description } : {}),
|
|
15
|
+
...(agent.model ? { model: `${agent.model.providerID}/${agent.model.modelID}` } : {}),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function toProviderSummary(provider) {
|
|
19
|
+
return {
|
|
20
|
+
provider: provider.id,
|
|
21
|
+
name: provider.name,
|
|
22
|
+
models: Object.keys(provider.models),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function errorMessage(error) {
|
|
26
|
+
if (error instanceof Error)
|
|
27
|
+
return error.message;
|
|
28
|
+
if (typeof error === "object" && error !== null && "message" in error) {
|
|
29
|
+
return String(error.message);
|
|
30
|
+
}
|
|
31
|
+
return String(error);
|
|
32
|
+
}
|
|
33
|
+
export function registerOpencodeListAgents(server) {
|
|
34
|
+
server.registerTool("opencode_list_agents", {
|
|
35
|
+
description: "List agents (native and custom) and available models/providers on an OpenCode server instance",
|
|
36
|
+
inputSchema: {
|
|
37
|
+
server_id: z.string().describe("Id of the server instance to query"),
|
|
38
|
+
},
|
|
39
|
+
}, async ({ server_id }) => {
|
|
40
|
+
const instance = getServer(server_id);
|
|
41
|
+
if (!instance) {
|
|
42
|
+
return jsonError({ server_id, status: "not_found" });
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
const client = createOpencodeClient({ baseUrl: instance.baseUrl });
|
|
46
|
+
const [agentsResult, providersResult] = await Promise.all([
|
|
47
|
+
client.app.agents(),
|
|
48
|
+
client.config.providers(),
|
|
49
|
+
]);
|
|
50
|
+
const failure = agentsResult.error ?? providersResult.error;
|
|
51
|
+
if (failure) {
|
|
52
|
+
return jsonError({ server_id, status: "error", message: errorMessage(failure) });
|
|
53
|
+
}
|
|
54
|
+
const allAgents = agentsResult.data ?? [];
|
|
55
|
+
const providers = providersResult.data?.providers ?? [];
|
|
56
|
+
const defaults = providersResult.data?.default ?? {};
|
|
57
|
+
return jsonResult({
|
|
58
|
+
server_id,
|
|
59
|
+
agents: {
|
|
60
|
+
native: allAgents.filter(isNativeAgent).map(toAgentSummary),
|
|
61
|
+
custom: allAgents.filter((a) => !isNativeAgent(a)).map(toAgentSummary),
|
|
62
|
+
},
|
|
63
|
+
models: {
|
|
64
|
+
defaults,
|
|
65
|
+
providers: providers.map(toProviderSummary),
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
return jsonError({ server_id, status: "error", message: errorMessage(error) });
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=list_agents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list_agents.js","sourceRoot":"","sources":["../../../../src/modules/tools/list_agents.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start_server.d.ts","sourceRoot":"","sources":["../../../../src/modules/tools/start_server.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAOzE,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,SAAS,QAgD5D"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { createOpencodeServer } from "@opencode-ai/sdk";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { registerServer } from "../shared/server-registry.js";
|
|
5
|
+
const DEFAULT_PORT = 4096;
|
|
6
|
+
export function registerOpencodeStartServer(server) {
|
|
7
|
+
server.registerTool("opencode_start_server", {
|
|
8
|
+
description: "Start a headless OpenCode server instance in the current working directory",
|
|
9
|
+
inputSchema: {
|
|
10
|
+
port: z.number().optional().describe("Port to bind the server on (default 4096)"),
|
|
11
|
+
},
|
|
12
|
+
}, async ({ port }) => {
|
|
13
|
+
try {
|
|
14
|
+
// The server inherits this process' cwd, so its project worktree is the
|
|
15
|
+
// directory the MCP host was launched in — no cwd argument needed.
|
|
16
|
+
const instance = await createOpencodeServer({
|
|
17
|
+
hostname: "127.0.0.1",
|
|
18
|
+
port: port ?? DEFAULT_PORT,
|
|
19
|
+
});
|
|
20
|
+
const serverId = randomUUID();
|
|
21
|
+
registerServer({ serverId, baseUrl: instance.url, close: instance.close });
|
|
22
|
+
return {
|
|
23
|
+
content: [
|
|
24
|
+
{
|
|
25
|
+
type: "text",
|
|
26
|
+
text: JSON.stringify({
|
|
27
|
+
server_id: serverId,
|
|
28
|
+
baseUrl: instance.url,
|
|
29
|
+
status: "running",
|
|
30
|
+
}),
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
return {
|
|
37
|
+
isError: true,
|
|
38
|
+
content: [
|
|
39
|
+
{
|
|
40
|
+
type: "text",
|
|
41
|
+
text: JSON.stringify({
|
|
42
|
+
status: "error",
|
|
43
|
+
message: error instanceof Error ? error.message : String(error),
|
|
44
|
+
}),
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=start_server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start_server.js","sourceRoot":"","sources":["../../../../src/modules/tools/start_server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAE9D,MAAM,YAAY,GAAG,IAAI,CAAC;AAE1B,MAAM,UAAU,2BAA2B,CAAC,MAAiB;IAC3D,MAAM,CAAC,YAAY,CACjB,uBAAuB,EACvB;QACE,WAAW,EAAE,4EAA4E;QACzF,WAAW,EAAE;YACX,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2CAA2C,CAAC;SAClF;KACF,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QACjB,IAAI,CAAC;YACH,wEAAwE;YACxE,mEAAmE;YACnE,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC;gBAC1C,QAAQ,EAAE,WAAW;gBACrB,IAAI,EAAE,IAAI,IAAI,YAAY;aAC3B,CAAC,CAAC;YACH,MAAM,QAAQ,GAAG,UAAU,EAAE,CAAC;YAC9B,cAAc,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;YAE3E,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,SAAS,EAAE,QAAQ;4BACnB,OAAO,EAAE,QAAQ,CAAC,GAAG;4BACrB,MAAM,EAAE,SAAS;yBAClB,CAAC;qBACH;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,MAAM,EAAE,OAAO;4BACf,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;yBAChE,CAAC;qBACH;iBACF;aACF,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start_task.d.ts","sourceRoot":"","sources":["../../../../src/modules/tools/start_task.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAazE,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,QAsE1D"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { jsonError, jsonResult } from "../shared/mcp-result.js";
|
|
4
|
+
import { clientForServer } from "../shared/opencode-client.js";
|
|
5
|
+
import { registerTask } from "../shared/task-registry.js";
|
|
6
|
+
/** Parse a "providerID/modelID" string into the shape the SDK expects. */
|
|
7
|
+
function parseModel(model) {
|
|
8
|
+
const slash = model.indexOf("/");
|
|
9
|
+
if (slash <= 0 || slash === model.length - 1)
|
|
10
|
+
return undefined;
|
|
11
|
+
return { providerID: model.slice(0, slash), modelID: model.slice(slash + 1) };
|
|
12
|
+
}
|
|
13
|
+
export function registerOpencodeStartTask(server) {
|
|
14
|
+
server.registerTool("opencode_start_task", {
|
|
15
|
+
description: "Delegate a task to an OpenCode agent: create a session and start the prompt without waiting for it to finish",
|
|
16
|
+
inputSchema: {
|
|
17
|
+
server_id: z.string().describe("Id of the server instance to run the task on"),
|
|
18
|
+
prompt: z.string().describe("Prompt/instructions for the agent"),
|
|
19
|
+
agent: z.string().optional().describe("Agent name to delegate to (e.g. 'build')"),
|
|
20
|
+
model: z
|
|
21
|
+
.string()
|
|
22
|
+
.optional()
|
|
23
|
+
.describe("Model as 'providerID/modelID' (e.g. 'anthropic/claude-sonnet-4')"),
|
|
24
|
+
},
|
|
25
|
+
}, async ({ server_id, prompt, agent, model }) => {
|
|
26
|
+
const client = clientForServer(server_id);
|
|
27
|
+
if (!client) {
|
|
28
|
+
return jsonError({ server_id, status: "server_not_found" });
|
|
29
|
+
}
|
|
30
|
+
let parsedModel;
|
|
31
|
+
if (model !== undefined) {
|
|
32
|
+
parsedModel = parseModel(model);
|
|
33
|
+
if (!parsedModel) {
|
|
34
|
+
return jsonError({
|
|
35
|
+
server_id,
|
|
36
|
+
status: "invalid_model",
|
|
37
|
+
message: "model must be in 'providerID/modelID' format",
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
const created = await client.session.create({ body: { title: prompt.slice(0, 60) } });
|
|
43
|
+
const sessionId = created.data?.id;
|
|
44
|
+
if (!sessionId) {
|
|
45
|
+
return jsonError({ server_id, status: "error", message: "failed to create session" });
|
|
46
|
+
}
|
|
47
|
+
// Fire-and-forget: promptAsync returns as soon as the prompt is accepted,
|
|
48
|
+
// the agent keeps working in the background. Poll with get_task_status.
|
|
49
|
+
await client.session.promptAsync({
|
|
50
|
+
path: { id: sessionId },
|
|
51
|
+
body: {
|
|
52
|
+
parts: [{ type: "text", text: prompt }],
|
|
53
|
+
...(agent ? { agent } : {}),
|
|
54
|
+
...(parsedModel ? { model: parsedModel } : {}),
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
const taskId = randomUUID();
|
|
58
|
+
registerTask({ taskId, serverId: server_id, sessionId });
|
|
59
|
+
return jsonResult({
|
|
60
|
+
task_id: taskId,
|
|
61
|
+
server_id,
|
|
62
|
+
session_id: sessionId,
|
|
63
|
+
status: "pending",
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
return jsonError({
|
|
68
|
+
server_id,
|
|
69
|
+
status: "error",
|
|
70
|
+
message: error instanceof Error ? error.message : String(error),
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=start_task.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start_task.js","sourceRoot":"","sources":["../../../../src/modules/tools/start_task.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stop_server.d.ts","sourceRoot":"","sources":["../../../../src/modules/tools/stop_server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIzE,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,SAAS,QAoC3D"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { getServer, removeServer } from "../shared/server-registry.js";
|
|
3
|
+
export function registerOpencodeStopServer(server) {
|
|
4
|
+
server.registerTool("opencode_stop_server", {
|
|
5
|
+
description: "Stop a running OpenCode server instance",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
server_id: z.string().describe("Id of the server instance to stop"),
|
|
8
|
+
},
|
|
9
|
+
}, async ({ server_id }) => {
|
|
10
|
+
const instance = getServer(server_id);
|
|
11
|
+
if (!instance) {
|
|
12
|
+
return {
|
|
13
|
+
isError: true,
|
|
14
|
+
content: [
|
|
15
|
+
{
|
|
16
|
+
type: "text",
|
|
17
|
+
text: JSON.stringify({ server_id, status: "not_found" }),
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
instance.close();
|
|
23
|
+
removeServer(server_id);
|
|
24
|
+
return {
|
|
25
|
+
content: [
|
|
26
|
+
{
|
|
27
|
+
type: "text",
|
|
28
|
+
text: JSON.stringify({ server_id, status: "stopped" }),
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=stop_server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stop_server.js","sourceRoot":"","sources":["../../../../src/modules/tools/stop_server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAEvE,MAAM,UAAU,0BAA0B,CAAC,MAAiB;IAC1D,MAAM,CAAC,YAAY,CACjB,sBAAsB,EACtB;QACE,WAAW,EAAE,yCAAyC;QACtD,WAAW,EAAE;YACX,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;SACpE;KACF,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE;QACtB,MAAM,QAAQ,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;QACtC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;qBACzD;iBACF;aACF,CAAC;QACJ,CAAC;QAED,QAAQ,CAAC,KAAK,EAAE,CAAC;QACjB,YAAY,CAAC,SAAS,CAAC,CAAC;QAExB,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;iBACvD;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wait_for_task.d.ts","sourceRoot":"","sources":["../../../../src/modules/tools/wait_for_task.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA2BzE,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,SAAS,QA2F5D"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { getMaxToolTimeoutMs } from "../shared/config.js";
|
|
3
|
+
import { jsonError, jsonResult } from "../shared/mcp-result.js";
|
|
4
|
+
import { clientForTask, deriveTaskStatus, } from "../shared/opencode-client.js";
|
|
5
|
+
const DEFAULT_TIMEOUT_MS = 120_000;
|
|
6
|
+
const DEFAULT_POLL_INTERVAL_MS = 2_500;
|
|
7
|
+
const MIN_POLL_INTERVAL_MS = 500;
|
|
8
|
+
const FINISHED_STATUSES = new Set(["completed", "failed", "error"]);
|
|
9
|
+
function isFinished(result) {
|
|
10
|
+
return result !== undefined && FINISHED_STATUSES.has(result.status);
|
|
11
|
+
}
|
|
12
|
+
function sleep(ms) {
|
|
13
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
14
|
+
}
|
|
15
|
+
export function registerOpencodeWaitForTask(server) {
|
|
16
|
+
server.registerTool("opencode_wait_for_task", {
|
|
17
|
+
description: "Long-poll one or more delegated tasks until they finish or the timeout elapses. Use mode 'all' to wait for all tasks, or 'any' to return as soon as one completes.",
|
|
18
|
+
inputSchema: {
|
|
19
|
+
task_ids: z.string().array().min(1).describe("IDs of tasks to wait for"),
|
|
20
|
+
mode: z
|
|
21
|
+
.enum(["all", "any"])
|
|
22
|
+
.default("all")
|
|
23
|
+
.describe("'all': return when all tasks finish, 'any': return when one finishes"),
|
|
24
|
+
timeout_ms: z
|
|
25
|
+
.number()
|
|
26
|
+
.optional()
|
|
27
|
+
.describe(`Max time to wait in milliseconds (default ${DEFAULT_TIMEOUT_MS})`),
|
|
28
|
+
poll_interval_ms: z
|
|
29
|
+
.number()
|
|
30
|
+
.optional()
|
|
31
|
+
.describe(`Time between status checks in milliseconds (default ${DEFAULT_POLL_INTERVAL_MS})`),
|
|
32
|
+
},
|
|
33
|
+
}, async ({ task_ids, mode = "all", timeout_ms, poll_interval_ms }) => {
|
|
34
|
+
// Fail-fast: check for unknown task IDs before polling starts
|
|
35
|
+
const unknownIds = [];
|
|
36
|
+
const taskData = [];
|
|
37
|
+
for (const taskId of task_ids) {
|
|
38
|
+
const resolved = clientForTask(taskId);
|
|
39
|
+
if (!resolved) {
|
|
40
|
+
unknownIds.push(taskId);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
taskData.push({ task_id: taskId, client: resolved });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (unknownIds.length > 0) {
|
|
47
|
+
return jsonError({ task_ids: unknownIds, status: "not_found" });
|
|
48
|
+
}
|
|
49
|
+
const timeout = Math.min(timeout_ms ?? DEFAULT_TIMEOUT_MS, getMaxToolTimeoutMs());
|
|
50
|
+
const pollInterval = Math.max(poll_interval_ms ?? DEFAULT_POLL_INTERVAL_MS, MIN_POLL_INTERVAL_MS);
|
|
51
|
+
const deadline = Date.now() + timeout;
|
|
52
|
+
const statusMap = new Map();
|
|
53
|
+
while (true) {
|
|
54
|
+
// Poll all tasks that are not yet finished
|
|
55
|
+
for (const { task_id, client } of taskData) {
|
|
56
|
+
if (isFinished(statusMap.get(task_id)))
|
|
57
|
+
continue;
|
|
58
|
+
try {
|
|
59
|
+
const result = await deriveTaskStatus(client.client, client.sessionId, task_id);
|
|
60
|
+
statusMap.set(task_id, result);
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
// Per-task SDK error: mark as finished with error
|
|
64
|
+
statusMap.set(task_id, {
|
|
65
|
+
task_id,
|
|
66
|
+
status: "error",
|
|
67
|
+
error: error instanceof Error ? error.message : String(error),
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// biome-ignore lint/style/noNonNullAssertion: every task_id was just written to statusMap above
|
|
72
|
+
const tasks = task_ids.map((id) => statusMap.get(id));
|
|
73
|
+
if (mode === "all" && tasks.every(isFinished)) {
|
|
74
|
+
return jsonResult({ mode, tasks, timed_out: false });
|
|
75
|
+
}
|
|
76
|
+
if (mode === "any" && tasks.some(isFinished)) {
|
|
77
|
+
return jsonResult({ mode, tasks, timed_out: false });
|
|
78
|
+
}
|
|
79
|
+
if (Date.now() >= deadline) {
|
|
80
|
+
return jsonResult({ mode, tasks, timed_out: true });
|
|
81
|
+
}
|
|
82
|
+
await sleep(pollInterval);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=wait_for_task.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wait_for_task.js","sourceRoot":"","sources":["../../../../src/modules/tools/wait_for_task.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EACL,aAAa,EACb,gBAAgB,GAEjB,MAAM,8BAA8B,CAAC;AAEtC,MAAM,kBAAkB,GAAG,OAAO,CAAC;AACnC,MAAM,wBAAwB,GAAG,KAAK,CAAC;AACvC,MAAM,oBAAoB,GAAG,GAAG,CAAC;AAKjC,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AAEpE,SAAS,UAAU,CAAC,MAAkC;IACpD,OAAO,MAAM,KAAK,SAAS,IAAI,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AACtE,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,MAAiB;IAC3D,MAAM,CAAC,YAAY,CACjB,wBAAwB,EACxB;QACE,WAAW,EACT,oKAAoK;QACtK,WAAW,EAAE;YACX,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,0BAA0B,CAAC;YACxE,IAAI,EAAE,CAAC;iBACJ,IAAI,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;iBACpB,OAAO,CAAC,KAAK,CAAC;iBACd,QAAQ,CAAC,sEAAsE,CAAC;YACnF,UAAU,EAAE,CAAC;iBACV,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,6CAA6C,kBAAkB,GAAG,CAAC;YAC/E,gBAAgB,EAAE,CAAC;iBAChB,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CACP,uDAAuD,wBAAwB,GAAG,CACnF;SACJ;KACF,EACD,KAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,GAAG,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,EAAE,EAAE;QACjE,8DAA8D;QAC9D,MAAM,UAAU,GAAa,EAAE,CAAC;QAChC,MAAM,QAAQ,GAGT,EAAE,CAAC;QAER,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;YAC9B,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;YACvC,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC1B,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;YACvD,CAAC;QACH,CAAC;QAED,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,OAAO,SAAS,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;QAClE,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,IAAI,kBAAkB,EAAE,mBAAmB,EAAE,CAAC,CAAC;QAClF,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAC3B,gBAAgB,IAAI,wBAAwB,EAC5C,oBAAoB,CACrB,CAAC;QAEF,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC;QACtC,MAAM,SAAS,GAAG,IAAI,GAAG,EAA0B,CAAC;QAEpD,OAAO,IAAI,EAAE,CAAC;YACZ,2CAA2C;YAC3C,KAAK,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;gBAC3C,IAAI,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;oBAAE,SAAS;gBAEjD,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;oBAChF,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;gBACjC,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,kDAAkD;oBAClD,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE;wBACrB,OAAO;wBACP,MAAM,EAAE,OAAO;wBACf,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;qBAC9D,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YAED,gGAAgG;YAChG,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAE,CAAC,CAAC;YAEvD,IAAI,IAAI,KAAK,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC9C,OAAO,UAAU,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;YACvD,CAAC;YAED,IAAI,IAAI,KAAK,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC7C,OAAO,UAAU,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;YACvD,CAAC;YAED,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,QAAQ,EAAE,CAAC;gBAC3B,OAAO,UAAU,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACtD,CAAC;YAED,MAAM,KAAK,CAAC,YAAY,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
/** Minimal stand-in for McpServer that captures the registered tool/prompt handlers. */
|
|
3
|
+
export declare function createFakeMcpServer(): {
|
|
4
|
+
server: McpServer;
|
|
5
|
+
registerTool: import("vitest").Mock<(_name: string, _config: unknown, handler: ((...args: any[]) => unknown) | undefined) => void>;
|
|
6
|
+
registerPrompt: import("vitest").Mock<(_name: string, _config: unknown, handler: ((...args: any[]) => unknown) | undefined) => void>;
|
|
7
|
+
getHandler: <T extends (...args: any[]) => unknown>() => T;
|
|
8
|
+
getPromptHandler: <T extends (...args: any[]) => unknown>() => T;
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=fake-mcp-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fake-mcp-server.d.ts","sourceRoot":"","sources":["../../../src/test-utils/fake-mcp-server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,wFAAwF;AACxF,wBAAgB,mBAAmB;;gDAGE,MAAM,WAAW,OAAO,sBAD3B,GAAG,EAAE,KAAK,OAAO;kDAQvC,MAAM,WAAW,OAAO,sBAFI,GAAG,EAAE,KAAK,OAAO;iBAcxC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,OAEtB,CAAC;uBAGV,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,OAEtB,CAAC;EAGtC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { vi } from "vitest";
|
|
2
|
+
/** Minimal stand-in for McpServer that captures the registered tool/prompt handlers. */
|
|
3
|
+
export function createFakeMcpServer() {
|
|
4
|
+
// biome-ignore lint/suspicious/noExplicitAny: handler signature varies per tool
|
|
5
|
+
let capturedHandler;
|
|
6
|
+
const registerTool = vi.fn((_name, _config, handler) => {
|
|
7
|
+
capturedHandler = handler;
|
|
8
|
+
});
|
|
9
|
+
// biome-ignore lint/suspicious/noExplicitAny: handler signature varies per prompt
|
|
10
|
+
let capturedPromptHandler;
|
|
11
|
+
const registerPrompt = vi.fn((_name, _config, handler) => {
|
|
12
|
+
capturedPromptHandler = handler;
|
|
13
|
+
});
|
|
14
|
+
const server = { registerTool, registerPrompt };
|
|
15
|
+
return {
|
|
16
|
+
server,
|
|
17
|
+
registerTool,
|
|
18
|
+
registerPrompt,
|
|
19
|
+
// biome-ignore lint/suspicious/noExplicitAny: input shape varies per tool
|
|
20
|
+
getHandler: () => {
|
|
21
|
+
if (!capturedHandler)
|
|
22
|
+
throw new Error("registerTool was not called");
|
|
23
|
+
return capturedHandler;
|
|
24
|
+
},
|
|
25
|
+
// biome-ignore lint/suspicious/noExplicitAny: input shape varies per prompt
|
|
26
|
+
getPromptHandler: () => {
|
|
27
|
+
if (!capturedPromptHandler)
|
|
28
|
+
throw new Error("registerPrompt was not called");
|
|
29
|
+
return capturedPromptHandler;
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=fake-mcp-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fake-mcp-server.js","sourceRoot":"","sources":["../../../src/test-utils/fake-mcp-server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE5B,wFAAwF;AACxF,MAAM,UAAU,mBAAmB;IACjC,gFAAgF;IAChF,IAAI,eAA0D,CAAC;IAC/D,MAAM,YAAY,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,KAAa,EAAE,OAAgB,EAAE,OAA+B,EAAE,EAAE;QAC9F,eAAe,GAAG,OAAO,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,kFAAkF;IAClF,IAAI,qBAAgE,CAAC;IACrE,MAAM,cAAc,GAAG,EAAE,CAAC,EAAE,CAC1B,CAAC,KAAa,EAAE,OAAgB,EAAE,OAAqC,EAAE,EAAE;QACzE,qBAAqB,GAAG,OAAO,CAAC;IAClC,CAAC,CACF,CAAC;IAEF,MAAM,MAAM,GAAG,EAAE,YAAY,EAAE,cAAc,EAA0B,CAAC;IAExE,OAAO;QACL,MAAM;QACN,YAAY;QACZ,cAAc;QACd,0EAA0E;QAC1E,UAAU,EAAE,GAA0C,EAAE;YACtD,IAAI,CAAC,eAAe;gBAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;YACrE,OAAO,eAAoB,CAAC;QAC9B,CAAC;QACD,4EAA4E;QAC5E,gBAAgB,EAAE,GAA0C,EAAE;YAC5D,IAAI,CAAC,qBAAqB;gBAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;YAC7E,OAAO,qBAA0B,CAAC;QACpC,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mcp-server-opencode",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "./build/src/index.js",
|
|
6
|
+
"types": "./build/src/index.d.ts",
|
|
7
|
+
"keywords": [],
|
|
8
|
+
"author": "alejandro-technology",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/alejandro-technology/opencode-mcp.git"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/alejandro-technology/opencode-mcp/issues"
|
|
16
|
+
},
|
|
17
|
+
"homepage": "https://github.com/alejandro-technology/opencode-mcp",
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public"
|
|
20
|
+
},
|
|
21
|
+
"type": "module",
|
|
22
|
+
"bin": {
|
|
23
|
+
"opencode-mcp": "./build/src/index.js"
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"dev": "npx -y @modelcontextprotocol/inspector pnpx tsx src/index.ts",
|
|
27
|
+
"lint": "biome check .",
|
|
28
|
+
"lint:write": "biome check --write .",
|
|
29
|
+
"lint:format": "biome format --write .",
|
|
30
|
+
"test": "vitest run",
|
|
31
|
+
"test:coverage": "vitest run --coverage",
|
|
32
|
+
"build": "rm -rf build && npx tsc && chmod +x build/src/index.js",
|
|
33
|
+
"prepare": "npm run build",
|
|
34
|
+
"publish": "npm publish --access public"
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"build"
|
|
38
|
+
],
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
41
|
+
"@opencode-ai/sdk": "^1.17.20",
|
|
42
|
+
"zod": "^3.25.76"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@biomejs/biome": "^2.5.3",
|
|
46
|
+
"@types/node": "^26.1.1",
|
|
47
|
+
"@vitest/coverage-v8": "^4.1.10",
|
|
48
|
+
"typescript": "^7.0.2",
|
|
49
|
+
"vitest": "^4.1.10"
|
|
50
|
+
}
|
|
51
|
+
}
|