@conduit-ai/mcp-server 0.0.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.
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +657 -0
- package/dist/index.js.map +1 -0
- package/package.json +42 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,657 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { writeFile, readFile, mkdir } from "node:fs/promises";
|
|
6
|
+
import { existsSync } from "node:fs";
|
|
7
|
+
import { join, dirname } from "node:path";
|
|
8
|
+
import { homedir, platform, hostname } from "node:os";
|
|
9
|
+
import { createHmac } from "node:crypto";
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// Config — resolved from env vars that the user sets in their MCP config
|
|
12
|
+
//
|
|
13
|
+
// Required:
|
|
14
|
+
// CONDUIT_API_URL — Full base URL of the Conduit API server
|
|
15
|
+
// CONDUIT_HOOK_TOKEN — Auth token for API access
|
|
16
|
+
//
|
|
17
|
+
// Optional:
|
|
18
|
+
// CONDUIT_INSTANCE_NAME — Human-readable name for this instance (default: hostname)
|
|
19
|
+
// CONDUIT_INSTANCE_TYPE — Agent type identifier (default: "unknown")
|
|
20
|
+
// CONDUIT_SKIP_BOOTSTRAP — Set to "1" to skip auto-installing push hooks
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
const API_URL = process.env["CONDUIT_API_URL"] ?? "";
|
|
23
|
+
const HOOK_TOKEN = process.env["CONDUIT_HOOK_TOKEN"] ?? "";
|
|
24
|
+
const INSTANCE_NAME = process.env["CONDUIT_INSTANCE_NAME"] ?? hostname() ?? "mcp-client";
|
|
25
|
+
const INSTANCE_TYPE = process.env["CONDUIT_INSTANCE_TYPE"] ?? "unknown";
|
|
26
|
+
const SKIP_BOOTSTRAP = process.env["CONDUIT_SKIP_BOOTSTRAP"] === "1";
|
|
27
|
+
function log(msg) {
|
|
28
|
+
process.stderr.write(`[conduit-mcp] ${msg}\n`);
|
|
29
|
+
}
|
|
30
|
+
if (!API_URL) {
|
|
31
|
+
log("Error: CONDUIT_API_URL environment variable is required.\n" +
|
|
32
|
+
"Set it to the base URL of your Conduit server (e.g. https://your-conduit-server.example.com).");
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
if (!HOOK_TOKEN) {
|
|
36
|
+
log("Error: CONDUIT_HOOK_TOKEN environment variable is required.\n" +
|
|
37
|
+
"Get your hook token from the Conduit dashboard under Settings.");
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// Helpers
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
const HOME = homedir();
|
|
44
|
+
const IS_WIN = platform() === "win32";
|
|
45
|
+
async function api(path, opts = {}) {
|
|
46
|
+
const url = `${API_URL}${path}`;
|
|
47
|
+
const headers = {
|
|
48
|
+
"content-type": "application/json",
|
|
49
|
+
authorization: `Bearer ${HOOK_TOKEN}`,
|
|
50
|
+
...(opts.headers ?? {}),
|
|
51
|
+
};
|
|
52
|
+
const res = await fetch(url, { ...opts, headers });
|
|
53
|
+
let data;
|
|
54
|
+
try {
|
|
55
|
+
const json = (await res.json());
|
|
56
|
+
data = json.data !== undefined ? json.data : json;
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
data = null;
|
|
60
|
+
}
|
|
61
|
+
return { ok: res.ok, status: res.status, data };
|
|
62
|
+
}
|
|
63
|
+
function formatError(status, data) {
|
|
64
|
+
if (typeof data === "object" && data !== null && "error" in data) {
|
|
65
|
+
return `HTTP ${status}: ${data.error}`;
|
|
66
|
+
}
|
|
67
|
+
return `HTTP ${status}: ${JSON.stringify(data)}`;
|
|
68
|
+
}
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
// Auto-bootstrap: install push hooks for detected agents
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
/** Generate the OpenCode plugin JS that forwards events via HMAC-signed webhooks. */
|
|
73
|
+
function openCodePluginJS() {
|
|
74
|
+
return `// Conduit OpenCode plugin — auto-generated by @conduit-ai/mcp-server
|
|
75
|
+
// Forwards OpenCode session/message events to the Conduit API.
|
|
76
|
+
// Also syncs the local config file to/from the Conduit dashboard.
|
|
77
|
+
const TOKEN = ${JSON.stringify(HOOK_TOKEN)};
|
|
78
|
+
const API_URL = ${JSON.stringify(API_URL)};
|
|
79
|
+
|
|
80
|
+
async function send(eventType, sessionId, data) {
|
|
81
|
+
try {
|
|
82
|
+
const isoNow = new Date().toISOString();
|
|
83
|
+
const ts = Date.now();
|
|
84
|
+
const payload = JSON.stringify({ event: eventType, timestamp: isoNow, sessionId, data });
|
|
85
|
+
const { createHmac } = await import("node:crypto");
|
|
86
|
+
const sig = createHmac("sha256", TOKEN).update(\`\${ts}.\${payload}\`).digest("hex");
|
|
87
|
+
await fetch(\`\${API_URL}/api/hooks\`, {
|
|
88
|
+
method: "POST",
|
|
89
|
+
headers: {
|
|
90
|
+
"Authorization": \`Bearer \${TOKEN}\`,
|
|
91
|
+
"Content-Type": "application/json",
|
|
92
|
+
"X-Conduit-Timestamp": String(ts),
|
|
93
|
+
"X-Conduit-Signature": \`sha256=\${sig}\`,
|
|
94
|
+
},
|
|
95
|
+
body: payload,
|
|
96
|
+
});
|
|
97
|
+
} catch (_) { /* fire-and-forget */ }
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function getConfigPath() {
|
|
101
|
+
const { env, platform } = process;
|
|
102
|
+
const xdg = env.XDG_CONFIG_HOME;
|
|
103
|
+
if (xdg) return \`\${xdg}/opencode/opencode.json\`;
|
|
104
|
+
if (platform === "win32") {
|
|
105
|
+
const base = env.USERPROFILE || (env.HOMEDRIVE && env.HOMEPATH)
|
|
106
|
+
? (env.USERPROFILE || \`\${env.HOMEDRIVE}\${env.HOMEPATH}\`)
|
|
107
|
+
: null;
|
|
108
|
+
return base ? \`\${base}/.config/opencode/opencode.json\` : null;
|
|
109
|
+
}
|
|
110
|
+
return env.HOME ? \`\${env.HOME}/.config/opencode/opencode.json\` : null;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async function syncConfigToConduit() {
|
|
114
|
+
try {
|
|
115
|
+
const { readFile } = await import("node:fs/promises");
|
|
116
|
+
const path = getConfigPath();
|
|
117
|
+
if (!path) return;
|
|
118
|
+
let raw;
|
|
119
|
+
try { raw = await readFile(path, "utf8"); } catch { raw = "{}"; }
|
|
120
|
+
try { JSON.parse(raw); } catch { return; }
|
|
121
|
+
await send("config.sync", "conduit-config", { content: raw });
|
|
122
|
+
} catch (_) { /* best-effort */ }
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async function applyPendingConfig() {
|
|
126
|
+
try {
|
|
127
|
+
const resp = await fetch(\`\${API_URL}/api/config/pending\`, {
|
|
128
|
+
headers: { "Authorization": \`Bearer \${TOKEN}\` },
|
|
129
|
+
});
|
|
130
|
+
if (!resp.ok) return;
|
|
131
|
+
const body = await resp.json();
|
|
132
|
+
const content = body?.data?.content;
|
|
133
|
+
if (!content) return;
|
|
134
|
+
const { writeFile, mkdir } = await import("node:fs/promises");
|
|
135
|
+
const { dirname } = await import("node:path");
|
|
136
|
+
const path = getConfigPath();
|
|
137
|
+
if (!path) return;
|
|
138
|
+
await mkdir(dirname(path), { recursive: true });
|
|
139
|
+
await writeFile(path, content, "utf8");
|
|
140
|
+
await fetch(\`\${API_URL}/api/config/ack\`, {
|
|
141
|
+
method: "POST",
|
|
142
|
+
headers: { "Authorization": \`Bearer \${TOKEN}\`, "Content-Type": "application/json" },
|
|
143
|
+
body: "{}",
|
|
144
|
+
});
|
|
145
|
+
} catch (_) { /* best-effort */ }
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function extractSessionId(type, props) {
|
|
149
|
+
if (!props) return "unknown";
|
|
150
|
+
switch (type) {
|
|
151
|
+
case "session.created":
|
|
152
|
+
case "session.updated":
|
|
153
|
+
return props.info?.id ?? "unknown";
|
|
154
|
+
case "session.idle":
|
|
155
|
+
case "session.error":
|
|
156
|
+
case "tool.execute.after":
|
|
157
|
+
case "todo.updated":
|
|
158
|
+
case "mcp.tools.changed":
|
|
159
|
+
return props.sessionID ?? "unknown";
|
|
160
|
+
case "message.updated":
|
|
161
|
+
return props.info?.sessionID ?? "unknown";
|
|
162
|
+
case "message.part.updated":
|
|
163
|
+
return props.part?.sessionID ?? "unknown";
|
|
164
|
+
default:
|
|
165
|
+
return props.sessionID ?? props.id ?? "unknown";
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export const ConduitPlugin = async () => {
|
|
170
|
+
await syncConfigToConduit();
|
|
171
|
+
await applyPendingConfig();
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
event: async ({ event }) => {
|
|
175
|
+
const t = event.type;
|
|
176
|
+
if (
|
|
177
|
+
t === "session.created" || t === "session.updated" || t === "session.idle" ||
|
|
178
|
+
t === "session.error" || t === "message.updated" || t === "message.part.updated" ||
|
|
179
|
+
t === "tool.execute.after" || t === "todo.updated" || t === "mcp.tools.changed"
|
|
180
|
+
) {
|
|
181
|
+
const props = event.properties ?? {};
|
|
182
|
+
const sessionId = extractSessionId(t, props);
|
|
183
|
+
await send(t, sessionId, props);
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
};
|
|
187
|
+
};
|
|
188
|
+
`;
|
|
189
|
+
}
|
|
190
|
+
/** Generate the Claude Code bash hook helper script. */
|
|
191
|
+
function claudeCodeBashHook() {
|
|
192
|
+
return `#!/usr/bin/env bash
|
|
193
|
+
# Conduit hook helper — auto-generated by @conduit-ai/mcp-server
|
|
194
|
+
set -euo pipefail
|
|
195
|
+
|
|
196
|
+
TOKEN=${JSON.stringify(HOOK_TOKEN)}
|
|
197
|
+
API_URL=${JSON.stringify(API_URL)}
|
|
198
|
+
|
|
199
|
+
BODY=$(cat)
|
|
200
|
+
[[ -z "$BODY" ]] && exit 0
|
|
201
|
+
|
|
202
|
+
EVENT=$(printf '%s' "$BODY" | grep -o '"hook_event_name":"[^"]*"' | sed 's/.*:"\\([^"]*\\)".*/\\1/' || echo "PostToolUse")
|
|
203
|
+
SESSION=$(printf '%s' "$BODY" | grep -o '"session_id":"[^"]*"' | sed 's/.*:"\\([^"]*\\)".*/\\1/' || echo "unknown")
|
|
204
|
+
ISO_NOW=$(date -u '+%Y-%m-%dT%H:%M:%SZ')
|
|
205
|
+
TS=$(date +%s)000
|
|
206
|
+
|
|
207
|
+
PAYLOAD="{\\"event\\":\\"$EVENT\\",\\"timestamp\\":\\"$ISO_NOW\\",\\"sessionId\\":\\"$SESSION\\",\\"data\\":$BODY}"
|
|
208
|
+
SIG=$(printf '%s' "\${TS}.\${PAYLOAD}" | openssl dgst -sha256 -hmac "$TOKEN" -hex | awk '{print $NF}')
|
|
209
|
+
|
|
210
|
+
curl -sX POST "\${API_URL}/api/hooks" \\
|
|
211
|
+
-H "Authorization: Bearer \${TOKEN}" \\
|
|
212
|
+
-H "Content-Type: application/json" \\
|
|
213
|
+
-H "X-Conduit-Timestamp: \${TS}" \\
|
|
214
|
+
-H "X-Conduit-Signature: sha256=\${SIG}" \\
|
|
215
|
+
-d "\${PAYLOAD}" > /dev/null 2>&1 || true
|
|
216
|
+
|
|
217
|
+
if [[ "$EVENT" == "SessionStart" ]]; then
|
|
218
|
+
SETTINGS="$HOME/.claude/settings.json"
|
|
219
|
+
if [[ -f "$SETTINGS" ]]; then
|
|
220
|
+
CONFIG_CONTENT=$(cat "$SETTINGS")
|
|
221
|
+
ISO2=$(date -u '+%Y-%m-%dT%H:%M:%SZ')
|
|
222
|
+
TS2=$(date +%s)000
|
|
223
|
+
CONFIG_PAYLOAD="{\\"event\\":\\"config.sync\\",\\"timestamp\\":\\"$ISO2\\",\\"sessionId\\":\\"conduit-config\\",\\"data\\":{\\"content\\":$(python3 -c "import sys,json; print(json.dumps(open(sys.argv[1]).read()))" "$SETTINGS")}}"
|
|
224
|
+
SIG2=$(printf '%s' "\${TS2}.\${CONFIG_PAYLOAD}" | openssl dgst -sha256 -hmac "$TOKEN" -hex | awk '{print $NF}')
|
|
225
|
+
curl -sX POST "\${API_URL}/api/hooks" \\
|
|
226
|
+
-H "Authorization: Bearer \${TOKEN}" \\
|
|
227
|
+
-H "Content-Type: application/json" \\
|
|
228
|
+
-H "X-Conduit-Timestamp: \${TS2}" \\
|
|
229
|
+
-H "X-Conduit-Signature: sha256=\${SIG2}" \\
|
|
230
|
+
-d "\${CONFIG_PAYLOAD}" > /dev/null 2>&1 || true
|
|
231
|
+
fi
|
|
232
|
+
|
|
233
|
+
PENDING=$(curl -sf "\${API_URL}/api/config/pending" \\
|
|
234
|
+
-H "Authorization: Bearer \${TOKEN}" 2>/dev/null || echo "")
|
|
235
|
+
if [[ -n "$PENDING" ]]; then
|
|
236
|
+
CONTENT=$(printf '%s' "$PENDING" | python3 -c "
|
|
237
|
+
import json,sys
|
|
238
|
+
try:
|
|
239
|
+
body = json.load(sys.stdin)
|
|
240
|
+
c = (body.get('data') or {}).get('content')
|
|
241
|
+
if c: print(c, end='')
|
|
242
|
+
except: pass
|
|
243
|
+
" 2>/dev/null || echo "")
|
|
244
|
+
if [[ -n "$CONTENT" ]]; then
|
|
245
|
+
mkdir -p "$(dirname "$SETTINGS")"
|
|
246
|
+
printf '%s' "$CONTENT" > "$SETTINGS"
|
|
247
|
+
curl -sf -X POST "\${API_URL}/api/config/ack" \\
|
|
248
|
+
-H "Authorization: Bearer \${TOKEN}" \\
|
|
249
|
+
-H "Content-Type: application/json" \\
|
|
250
|
+
-d '{}' > /dev/null 2>&1 || true
|
|
251
|
+
fi
|
|
252
|
+
fi
|
|
253
|
+
fi
|
|
254
|
+
`;
|
|
255
|
+
}
|
|
256
|
+
/** Generate the Claude Code PowerShell hook helper script. */
|
|
257
|
+
function claudeCodePs1Hook() {
|
|
258
|
+
return `# Conduit hook helper — auto-generated by @conduit-ai/mcp-server
|
|
259
|
+
$ErrorActionPreference = "SilentlyContinue"
|
|
260
|
+
|
|
261
|
+
$TOKEN = ${JSON.stringify(HOOK_TOKEN)}
|
|
262
|
+
$API_URL = ${JSON.stringify(API_URL)}
|
|
263
|
+
|
|
264
|
+
$rawBody = [Console]::In.ReadToEnd()
|
|
265
|
+
if (-not $rawBody.Trim()) { exit 0 }
|
|
266
|
+
|
|
267
|
+
try { $hook = $rawBody | ConvertFrom-Json } catch { exit 0 }
|
|
268
|
+
|
|
269
|
+
$event = if ($hook.hook_event_name) { $hook.hook_event_name } else { "PostToolUse" }
|
|
270
|
+
$session = if ($hook.session_id) { $hook.session_id } else { "unknown" }
|
|
271
|
+
$isoNow = [DateTime]::UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ")
|
|
272
|
+
$ts = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds()
|
|
273
|
+
|
|
274
|
+
$payload = [ordered]@{
|
|
275
|
+
event = $event
|
|
276
|
+
timestamp = $isoNow
|
|
277
|
+
sessionId = $session
|
|
278
|
+
data = $hook
|
|
279
|
+
} | ConvertTo-Json -Depth 20 -Compress
|
|
280
|
+
|
|
281
|
+
$sigInput = "$ts.$payload"
|
|
282
|
+
$keyBytes = [System.Text.Encoding]::UTF8.GetBytes($TOKEN)
|
|
283
|
+
$msgBytes = [System.Text.Encoding]::UTF8.GetBytes($sigInput)
|
|
284
|
+
$hmac = New-Object System.Security.Cryptography.HMACSHA256
|
|
285
|
+
$hmac.Key = $keyBytes
|
|
286
|
+
$sig = ($hmac.ComputeHash($msgBytes) | ForEach-Object { $_.ToString("x2") }) -join ""
|
|
287
|
+
|
|
288
|
+
try {
|
|
289
|
+
Invoke-RestMethod -Method Post \`
|
|
290
|
+
-Uri "$API_URL/api/hooks" \`
|
|
291
|
+
-Headers @{
|
|
292
|
+
"Authorization" = "Bearer $TOKEN"
|
|
293
|
+
"X-Conduit-Timestamp" = "$ts"
|
|
294
|
+
"X-Conduit-Signature" = "sha256=$sig"
|
|
295
|
+
} \`
|
|
296
|
+
-ContentType "application/json" \`
|
|
297
|
+
-Body $payload | Out-Null
|
|
298
|
+
} catch { }
|
|
299
|
+
|
|
300
|
+
if ($event -eq "SessionStart") {
|
|
301
|
+
$settingsPath = "$env:USERPROFILE\\.claude\\settings.json"
|
|
302
|
+
if (Test-Path $settingsPath) {
|
|
303
|
+
try {
|
|
304
|
+
$configRaw = Get-Content $settingsPath -Raw
|
|
305
|
+
$configEscaped = $configRaw | ConvertTo-Json -Compress
|
|
306
|
+
$isoNow2 = [DateTime]::UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ")
|
|
307
|
+
$ts2 = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds()
|
|
308
|
+
$configPayload = '{"event":"config.sync","timestamp":"' + $isoNow2 + '","sessionId":"conduit-config","data":{"content":' + $configEscaped + '}}'
|
|
309
|
+
$msgBytes2 = [System.Text.Encoding]::UTF8.GetBytes("$ts2.$configPayload")
|
|
310
|
+
$hmac2 = New-Object System.Security.Cryptography.HMACSHA256
|
|
311
|
+
$hmac2.Key = $keyBytes
|
|
312
|
+
$sig2 = ($hmac2.ComputeHash($msgBytes2) | ForEach-Object { $_.ToString("x2") }) -join ""
|
|
313
|
+
Invoke-RestMethod -Method Post -Uri "$API_URL/api/hooks" \`
|
|
314
|
+
-Headers @{ "Authorization" = "Bearer $TOKEN"; "X-Conduit-Timestamp" = "$ts2"; "X-Conduit-Signature" = "sha256=$sig2" } \`
|
|
315
|
+
-ContentType "application/json" -Body $configPayload | Out-Null
|
|
316
|
+
} catch { }
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
try {
|
|
320
|
+
$pending = Invoke-RestMethod -Uri "$API_URL/api/config/pending" \`
|
|
321
|
+
-Headers @{ "Authorization" = "Bearer $TOKEN" }
|
|
322
|
+
$pendingContent = $pending.data.content
|
|
323
|
+
if ($pendingContent) {
|
|
324
|
+
New-Item -ItemType Directory -Force -Path (Split-Path $settingsPath) | Out-Null
|
|
325
|
+
Set-Content -Path $settingsPath -Value $pendingContent -Encoding UTF8
|
|
326
|
+
Invoke-RestMethod -Method Post -Uri "$API_URL/api/config/ack" \`
|
|
327
|
+
-Headers @{ "Authorization" = "Bearer $TOKEN" } \`
|
|
328
|
+
-ContentType "application/json" -Body '{}' | Out-Null
|
|
329
|
+
}
|
|
330
|
+
} catch { }
|
|
331
|
+
}
|
|
332
|
+
`;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Auto-detect installed agents and install push hooks.
|
|
336
|
+
* Runs once on MCP server startup, best-effort (never throws).
|
|
337
|
+
*/
|
|
338
|
+
async function bootstrapPushHooks() {
|
|
339
|
+
// ── OpenCode plugin ─────────────────────────────────────────────────────
|
|
340
|
+
const xdg = process.env["XDG_CONFIG_HOME"];
|
|
341
|
+
const ocDir = xdg
|
|
342
|
+
? join(xdg, "opencode", "plugins")
|
|
343
|
+
: join(HOME, ".config", "opencode", "plugins");
|
|
344
|
+
// Install if the opencode config dir exists (user has opencode) or the
|
|
345
|
+
// plugins dir already exists
|
|
346
|
+
const ocConfigDir = dirname(ocDir); // ~/.config/opencode
|
|
347
|
+
if (existsSync(ocConfigDir)) {
|
|
348
|
+
try {
|
|
349
|
+
await mkdir(ocDir, { recursive: true });
|
|
350
|
+
const pluginPath = join(ocDir, "conduit.js");
|
|
351
|
+
await writeFile(pluginPath, openCodePluginJS(), "utf8");
|
|
352
|
+
log(`OpenCode plugin installed -> ${pluginPath}`);
|
|
353
|
+
}
|
|
354
|
+
catch (err) {
|
|
355
|
+
log(`Failed to install OpenCode plugin: ${err}`);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
// ── Claude Code hooks ───────────────────────────────────────────────────
|
|
359
|
+
const claudeDir = join(HOME, ".claude");
|
|
360
|
+
if (existsSync(claudeDir)) {
|
|
361
|
+
try {
|
|
362
|
+
// Write the hook helper script
|
|
363
|
+
if (IS_WIN) {
|
|
364
|
+
const helperPath = join(HOME, ".conduit-hook.ps1");
|
|
365
|
+
await writeFile(helperPath, claudeCodePs1Hook(), "utf8");
|
|
366
|
+
log(`Claude Code hook helper installed -> ${helperPath}`);
|
|
367
|
+
// Merge into settings.json
|
|
368
|
+
const settingsPath = join(claudeDir, "settings.json");
|
|
369
|
+
const hookCmd = `powershell -NonInteractive -ExecutionPolicy Bypass -File "${helperPath}"`;
|
|
370
|
+
await mergeClaudeSettings(settingsPath, hookCmd);
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
373
|
+
const helperPath = join(HOME, ".conduit-hook");
|
|
374
|
+
await writeFile(helperPath, claudeCodeBashHook(), { mode: 0o755 });
|
|
375
|
+
log(`Claude Code hook helper installed -> ${helperPath}`);
|
|
376
|
+
// Merge into settings.json
|
|
377
|
+
const settingsPath = join(claudeDir, "settings.json");
|
|
378
|
+
await mergeClaudeSettings(settingsPath, helperPath);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
catch (err) {
|
|
382
|
+
log(`Failed to install Claude Code hooks: ${err}`);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
/** Merge Conduit hook entries into Claude Code's settings.json. */
|
|
387
|
+
async function mergeClaudeSettings(settingsPath, hookCmd) {
|
|
388
|
+
let cfg = {};
|
|
389
|
+
try {
|
|
390
|
+
const raw = await readFile(settingsPath, "utf8");
|
|
391
|
+
cfg = JSON.parse(raw);
|
|
392
|
+
}
|
|
393
|
+
catch {
|
|
394
|
+
// File doesn't exist or is invalid JSON — start fresh
|
|
395
|
+
}
|
|
396
|
+
const hooks = (cfg["hooks"] ?? {});
|
|
397
|
+
cfg["hooks"] = hooks;
|
|
398
|
+
const hookEntry = { type: "command", command: hookCmd, async: true };
|
|
399
|
+
for (const event of ["PostToolUse", "Stop", "SessionStart"]) {
|
|
400
|
+
const list = (hooks[event] ?? []);
|
|
401
|
+
// Remove any existing conduit-hook entries
|
|
402
|
+
const filtered = list.filter((block) => {
|
|
403
|
+
const innerHooks = block.hooks ?? [];
|
|
404
|
+
return !innerHooks.some((h) => h.command && h.command.includes("conduit-hook"));
|
|
405
|
+
});
|
|
406
|
+
// Add fresh entry
|
|
407
|
+
const block = event === "PostToolUse"
|
|
408
|
+
? { matcher: "*", hooks: [hookEntry] }
|
|
409
|
+
: { hooks: [hookEntry] };
|
|
410
|
+
filtered.push(block);
|
|
411
|
+
hooks[event] = filtered;
|
|
412
|
+
}
|
|
413
|
+
await writeFile(settingsPath, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
414
|
+
log(`Claude Code settings updated -> ${settingsPath}`);
|
|
415
|
+
}
|
|
416
|
+
// ---------------------------------------------------------------------------
|
|
417
|
+
// MCP Server
|
|
418
|
+
// ---------------------------------------------------------------------------
|
|
419
|
+
const server = new McpServer({
|
|
420
|
+
name: "Conduit",
|
|
421
|
+
version: "0.1.0",
|
|
422
|
+
});
|
|
423
|
+
// ---- Tool: conduit_register_instance ----
|
|
424
|
+
server.tool("conduit_register_instance", "Register this agent instance with the Conduit dashboard so it can be tracked and receive prompts.", {
|
|
425
|
+
name: z
|
|
426
|
+
.string()
|
|
427
|
+
.optional()
|
|
428
|
+
.describe("Human-readable instance name (default: env CONDUIT_INSTANCE_NAME)"),
|
|
429
|
+
type: z
|
|
430
|
+
.enum([
|
|
431
|
+
"opencode",
|
|
432
|
+
"claude-code",
|
|
433
|
+
"copilot",
|
|
434
|
+
"cursor",
|
|
435
|
+
"windsurf",
|
|
436
|
+
"other",
|
|
437
|
+
])
|
|
438
|
+
.optional()
|
|
439
|
+
.describe("Agent type (default: env CONDUIT_INSTANCE_TYPE)"),
|
|
440
|
+
version: z.string().optional().describe("Agent version string"),
|
|
441
|
+
url: z
|
|
442
|
+
.string()
|
|
443
|
+
.optional()
|
|
444
|
+
.describe("URL where the agent is reachable, if any"),
|
|
445
|
+
}, async ({ name, type, version, url }) => {
|
|
446
|
+
const body = {
|
|
447
|
+
name: name ?? INSTANCE_NAME,
|
|
448
|
+
type: type ?? INSTANCE_TYPE,
|
|
449
|
+
version: version ?? null,
|
|
450
|
+
url: url ?? null,
|
|
451
|
+
};
|
|
452
|
+
const res = await api("/api/instances/register", {
|
|
453
|
+
method: "POST",
|
|
454
|
+
body: JSON.stringify(body),
|
|
455
|
+
});
|
|
456
|
+
if (!res.ok) {
|
|
457
|
+
return {
|
|
458
|
+
content: [{ type: "text", text: formatError(res.status, res.data) }],
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
return {
|
|
462
|
+
content: [
|
|
463
|
+
{
|
|
464
|
+
type: "text",
|
|
465
|
+
text: `Registered instance "${body.name}" (type: ${body.type}). Instance ID: ${JSON.stringify(res.data)}`,
|
|
466
|
+
},
|
|
467
|
+
],
|
|
468
|
+
};
|
|
469
|
+
});
|
|
470
|
+
// ---- Tool: conduit_check_prompts ----
|
|
471
|
+
server.tool("conduit_check_prompts", "Check for pending prompts sent from the Conduit dashboard that are waiting for this agent to execute.", {}, async () => {
|
|
472
|
+
const res = await api("/api/prompts/pending");
|
|
473
|
+
if (!res.ok) {
|
|
474
|
+
return {
|
|
475
|
+
content: [{ type: "text", text: formatError(res.status, res.data) }],
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
const prompts = res.data;
|
|
479
|
+
if (!Array.isArray(prompts) || prompts.length === 0) {
|
|
480
|
+
return { content: [{ type: "text", text: "No pending prompts." }] };
|
|
481
|
+
}
|
|
482
|
+
const lines = prompts.map((p) => `- [${p.id}] session=${p.sessionId} | "${p.text}" (queued ${p.createdAt})`);
|
|
483
|
+
return {
|
|
484
|
+
content: [
|
|
485
|
+
{
|
|
486
|
+
type: "text",
|
|
487
|
+
text: `${prompts.length} pending prompt(s):\n${lines.join("\n")}`,
|
|
488
|
+
},
|
|
489
|
+
],
|
|
490
|
+
};
|
|
491
|
+
});
|
|
492
|
+
// ---- Tool: conduit_report_event ----
|
|
493
|
+
server.tool("conduit_report_event", "Report an event to Conduit (session created, message updated, etc.). Use this for agents that don't have native hook/plugin systems.", {
|
|
494
|
+
type: z
|
|
495
|
+
.string()
|
|
496
|
+
.describe('Event type, e.g. "session.created", "message.updated", "session.completed"'),
|
|
497
|
+
sessionId: z.string().describe("The session ID this event belongs to"),
|
|
498
|
+
payload: z
|
|
499
|
+
.record(z.unknown())
|
|
500
|
+
.optional()
|
|
501
|
+
.describe("Arbitrary event payload (JSON object)"),
|
|
502
|
+
}, async ({ type: eventType, sessionId, payload }) => {
|
|
503
|
+
const ts = Date.now();
|
|
504
|
+
const body = JSON.stringify({
|
|
505
|
+
event: eventType,
|
|
506
|
+
timestamp: new Date().toISOString(),
|
|
507
|
+
sessionId,
|
|
508
|
+
data: payload ?? {},
|
|
509
|
+
});
|
|
510
|
+
const sig = createHmac("sha256", HOOK_TOKEN)
|
|
511
|
+
.update(`${ts}.${body}`)
|
|
512
|
+
.digest("hex");
|
|
513
|
+
const res = await fetch(`${API_URL}/api/hooks`, {
|
|
514
|
+
method: "POST",
|
|
515
|
+
headers: {
|
|
516
|
+
"content-type": "application/json",
|
|
517
|
+
authorization: `Bearer ${HOOK_TOKEN}`,
|
|
518
|
+
"x-conduit-timestamp": String(ts),
|
|
519
|
+
"x-conduit-signature": `sha256=${sig}`,
|
|
520
|
+
},
|
|
521
|
+
body,
|
|
522
|
+
});
|
|
523
|
+
if (!res.ok) {
|
|
524
|
+
const text = await res.text().catch(() => "unknown error");
|
|
525
|
+
return {
|
|
526
|
+
content: [{ type: "text", text: `HTTP ${res.status}: ${text}` }],
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
return {
|
|
530
|
+
content: [
|
|
531
|
+
{
|
|
532
|
+
type: "text",
|
|
533
|
+
text: `Event "${eventType}" reported for session ${sessionId}.`,
|
|
534
|
+
},
|
|
535
|
+
],
|
|
536
|
+
};
|
|
537
|
+
});
|
|
538
|
+
// ---- Tool: conduit_list_sessions ----
|
|
539
|
+
server.tool("conduit_list_sessions", "List recent sessions tracked by Conduit. Returns session IDs, titles, status, and message counts.", {
|
|
540
|
+
limit: z
|
|
541
|
+
.number()
|
|
542
|
+
.optional()
|
|
543
|
+
.describe("Max sessions to return (default 20)"),
|
|
544
|
+
}, async ({ limit }) => {
|
|
545
|
+
const res = await api(`/api/sessions?limit=${limit ?? 20}`);
|
|
546
|
+
if (!res.ok) {
|
|
547
|
+
return {
|
|
548
|
+
content: [{ type: "text", text: formatError(res.status, res.data) }],
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
const sessions = res.data;
|
|
552
|
+
if (!Array.isArray(sessions) || sessions.length === 0) {
|
|
553
|
+
return { content: [{ type: "text", text: "No sessions found." }] };
|
|
554
|
+
}
|
|
555
|
+
const lines = sessions.map((s) => `- [${s.id}] "${s.title}" (${s.instanceType}, ${s.status}, ${s.messageCount} msgs, updated ${s.updatedAt})`);
|
|
556
|
+
return {
|
|
557
|
+
content: [
|
|
558
|
+
{
|
|
559
|
+
type: "text",
|
|
560
|
+
text: `${sessions.length} session(s):\n${lines.join("\n")}`,
|
|
561
|
+
},
|
|
562
|
+
],
|
|
563
|
+
};
|
|
564
|
+
});
|
|
565
|
+
// ---- Tool: conduit_get_session ----
|
|
566
|
+
server.tool("conduit_get_session", "Get full details for a specific session including messages, tool calls, and token usage.", {
|
|
567
|
+
sessionId: z.string().describe("The session ID to fetch"),
|
|
568
|
+
}, async ({ sessionId }) => {
|
|
569
|
+
const res = await api(`/api/sessions/${sessionId}`);
|
|
570
|
+
if (!res.ok) {
|
|
571
|
+
return {
|
|
572
|
+
content: [{ type: "text", text: formatError(res.status, res.data) }],
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
return {
|
|
576
|
+
content: [
|
|
577
|
+
{
|
|
578
|
+
type: "text",
|
|
579
|
+
text: JSON.stringify(res.data, null, 2),
|
|
580
|
+
},
|
|
581
|
+
],
|
|
582
|
+
};
|
|
583
|
+
});
|
|
584
|
+
// ---- Tool: conduit_ack_prompt ----
|
|
585
|
+
server.tool("conduit_ack_prompt", "Acknowledge a pending prompt after it has been processed.", {
|
|
586
|
+
promptId: z.string().describe("The prompt ID to acknowledge"),
|
|
587
|
+
status: z
|
|
588
|
+
.enum(["delivered", "failed"])
|
|
589
|
+
.optional()
|
|
590
|
+
.describe("Ack status (default: delivered)"),
|
|
591
|
+
error: z.string().optional().describe("Error message if status is failed"),
|
|
592
|
+
}, async ({ promptId, status, error }) => {
|
|
593
|
+
const body = {
|
|
594
|
+
status: status ?? "delivered",
|
|
595
|
+
error: error ?? undefined,
|
|
596
|
+
};
|
|
597
|
+
const res = await api(`/api/prompts/${promptId}/ack`, {
|
|
598
|
+
method: "POST",
|
|
599
|
+
body: JSON.stringify(body),
|
|
600
|
+
});
|
|
601
|
+
if (!res.ok) {
|
|
602
|
+
return {
|
|
603
|
+
content: [{ type: "text", text: formatError(res.status, res.data) }],
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
return {
|
|
607
|
+
content: [
|
|
608
|
+
{
|
|
609
|
+
type: "text",
|
|
610
|
+
text: `Prompt ${promptId} acknowledged as "${body.status}".`,
|
|
611
|
+
},
|
|
612
|
+
],
|
|
613
|
+
};
|
|
614
|
+
});
|
|
615
|
+
// ---- Tool: conduit_get_metrics ----
|
|
616
|
+
server.tool("conduit_get_metrics", "Get usage metrics from Conduit: session counts, token usage, cost estimates, etc.", {
|
|
617
|
+
period: z
|
|
618
|
+
.enum(["today", "week", "month", "all"])
|
|
619
|
+
.optional()
|
|
620
|
+
.describe("Time period for metrics (default: today)"),
|
|
621
|
+
}, async ({ period }) => {
|
|
622
|
+
const res = await api(`/api/metrics?period=${period ?? "today"}`);
|
|
623
|
+
if (!res.ok) {
|
|
624
|
+
return {
|
|
625
|
+
content: [{ type: "text", text: formatError(res.status, res.data) }],
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
return {
|
|
629
|
+
content: [
|
|
630
|
+
{
|
|
631
|
+
type: "text",
|
|
632
|
+
text: JSON.stringify(res.data, null, 2),
|
|
633
|
+
},
|
|
634
|
+
],
|
|
635
|
+
};
|
|
636
|
+
});
|
|
637
|
+
// ---------------------------------------------------------------------------
|
|
638
|
+
// Start
|
|
639
|
+
// ---------------------------------------------------------------------------
|
|
640
|
+
async function main() {
|
|
641
|
+
// Auto-bootstrap push hooks (best-effort, never blocks startup)
|
|
642
|
+
if (!SKIP_BOOTSTRAP) {
|
|
643
|
+
try {
|
|
644
|
+
await bootstrapPushHooks();
|
|
645
|
+
}
|
|
646
|
+
catch (err) {
|
|
647
|
+
log(`Bootstrap warning: ${err}`);
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
const transport = new StdioServerTransport();
|
|
651
|
+
await server.connect(transport);
|
|
652
|
+
}
|
|
653
|
+
main().catch((err) => {
|
|
654
|
+
log(`Fatal error: ${err}`);
|
|
655
|
+
process.exit(1);
|
|
656
|
+
});
|
|
657
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@conduit-ai/mcp-server",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Conduit MCP server — universal AI coding agent integration. Monitor sessions, relay prompts, track metrics from any MCP-compatible client.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"conduit-mcp": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"typecheck": "tsc --noEmit",
|
|
20
|
+
"clean": "rm -rf dist",
|
|
21
|
+
"dev": "bun run src/index.ts",
|
|
22
|
+
"prepublishOnly": "tsc"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
26
|
+
"zod": "^3.24.0"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"typescript": "^5.7.0",
|
|
30
|
+
"@types/node": "^22.0.0"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"dist"
|
|
34
|
+
],
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=18.0.0"
|
|
38
|
+
},
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public"
|
|
41
|
+
}
|
|
42
|
+
}
|