@hivemindai/mcp-server 0.4.0 → 0.4.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.
@@ -0,0 +1,2 @@
1
+ export declare function guard(): Promise<void>;
2
+ //# sourceMappingURL=guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/guard.ts"],"names":[],"mappings":"AAkCA,wBAAsB,KAAK,kBAwG1B"}
@@ -0,0 +1,106 @@
1
+ import { readFileSync, existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ function loadCredentials() {
4
+ const credPath = join(process.env.HOME ?? process.env.USERPROFILE ?? ".", ".hivemind", "credentials.json");
5
+ if (!existsSync(credPath))
6
+ return null;
7
+ try {
8
+ const creds = JSON.parse(readFileSync(credPath, "utf-8"));
9
+ return { api_key: creds.api_key, api_url: creds.api_url };
10
+ }
11
+ catch {
12
+ return null;
13
+ }
14
+ }
15
+ function getAgentName() {
16
+ // Use session_id or a stable identifier
17
+ return process.env.HIVEMIND_AGENT ?? `claude-${process.pid}`;
18
+ }
19
+ export async function guard() {
20
+ // Read hook input from stdin
21
+ let input;
22
+ try {
23
+ const raw = readFileSync(0, "utf-8");
24
+ input = JSON.parse(raw);
25
+ }
26
+ catch {
27
+ // Can't parse stdin — allow the tool call (don't block on hook errors)
28
+ process.exit(0);
29
+ }
30
+ const filePath = input.tool_input?.file_path;
31
+ if (!filePath) {
32
+ // No file path (e.g. Bash tool) — allow
33
+ process.exit(0);
34
+ }
35
+ const creds = loadCredentials();
36
+ if (!creds) {
37
+ // No credentials — not in cloud mode, allow
38
+ process.exit(0);
39
+ }
40
+ const agent = getAgentName();
41
+ const headers = {
42
+ Authorization: `Bearer ${creds.api_key}`,
43
+ "Content-Type": "application/json",
44
+ };
45
+ // Make the file path relative to cwd for cleaner resource names
46
+ const cwd = input.cwd ?? process.cwd();
47
+ let resource = filePath;
48
+ if (resource.startsWith(cwd)) {
49
+ resource = resource.slice(cwd.length).replace(/^\//, "");
50
+ }
51
+ // 1. Check policies
52
+ try {
53
+ const policyRes = await fetch(`${creds.api_url}/v1/approvals/policies/check?resource=${encodeURIComponent(resource)}`, { headers });
54
+ if (policyRes.ok) {
55
+ const policyData = await policyRes.json();
56
+ if (policyData.requires_approval) {
57
+ const policies = policyData.matching_policies
58
+ .map((p) => ` - ${p.description} (pattern: ${p.resource_pattern})`)
59
+ .join("\n");
60
+ process.stderr.write(`BLOCKED: ${resource} requires approval.\n\nMatching policies:\n${policies}\n\n` +
61
+ `To proceed, request approval:\n` +
62
+ ` hivemind_approvals(action: "request", channel: "general", description: "Need to edit ${resource}")\n` +
63
+ `Then wait for approval before retrying.\n`);
64
+ process.exit(2);
65
+ }
66
+ }
67
+ }
68
+ catch {
69
+ // Policy check failed — don't block on network errors
70
+ }
71
+ // 2. Acquire lock
72
+ try {
73
+ const lockRes = await fetch(`${creds.api_url}/v1/locks/${encodeURIComponent(resource)}`, {
74
+ method: "POST",
75
+ headers,
76
+ body: JSON.stringify({ agent }),
77
+ });
78
+ if (lockRes.ok) {
79
+ const lockData = await lockRes.json();
80
+ if (lockData.locked) {
81
+ // Lock acquired — allow the edit
82
+ process.exit(0);
83
+ }
84
+ }
85
+ if (lockRes.status === 409) {
86
+ const lockData = await lockRes.json();
87
+ const holder = lockData.held_by?.agent ?? "unknown";
88
+ // Check if WE already hold this lock (same agent re-editing)
89
+ if (holder === agent) {
90
+ process.exit(0);
91
+ }
92
+ process.stderr.write(`BLOCKED: ${resource} is locked by ${holder}.\n\n` +
93
+ `Another agent is editing this file. To override:\n` +
94
+ `1. hivemind_approvals(action: "request", channel: "general", description: "Need to edit ${resource}, locked by ${holder}")\n` +
95
+ `2. Wait for approval\n` +
96
+ `3. hivemind_lock(action: "acquire", resource: "${resource}", force_correlation_id: "<correlation_id>")\n`);
97
+ process.exit(2);
98
+ }
99
+ }
100
+ catch {
101
+ // Lock request failed — don't block on network errors
102
+ }
103
+ // Default: allow
104
+ process.exit(0);
105
+ }
106
+ //# sourceMappingURL=guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard.js","sourceRoot":"","sources":["../../../src/cli/commands/guard.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAkDA,wBAAsB,IAAI,kBA6BzB"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAkEA,wBAAsB,IAAI,kBAuEzB"}
@@ -1,4 +1,4 @@
1
- import { existsSync, readFileSync, writeFileSync } from "node:fs";
1
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  const HIVEMIND_SECTION_START = "<!-- hivemind:start -->";
4
4
  const HIVEMIND_SECTION_END = "<!-- hivemind:end -->";
@@ -15,27 +15,14 @@ hivemind_publish(channel: "general", event_type: "task.created", data: {"descrip
15
15
  \`\`\`
16
16
  Also call \`hivemind_status()\` to see what other agents are working on.
17
17
 
18
- ### Rule 2: Lock before editing, release after
18
+ ### Rule 2: Locks and policies are enforced automatically
19
19
 
20
- BEFORE every file edit, you MUST acquire a lock. AFTER every file edit, you MUST release it. Locks are persistent they do NOT expire. Only you can release your own locks.
21
- \`\`\`
22
- hivemind_lock(action: "acquire", resource: "<file_path>")
23
- # If locked: false → STOP, another agent has this file. Do NOT edit it.
24
- # To override: request approval, then retry with force_correlation_id.
25
- # If locked: true → proceed with your edit.
26
- hivemind_lock(action: "release", resource: "<file_path>")
27
- \`\`\`
28
- NEVER skip this. NEVER edit a file without acquiring its lock first. You CANNOT release another agent's lock.
29
-
30
- ### Rule 3: Check policies before editing
20
+ File locks and approval policies are enforced by hooks. If your edit is blocked, you will see an error message explaining why and what to do. Follow those instructions.
31
21
 
32
- BEFORE editing any file, call:
33
- \`\`\`
34
- hivemind_approvals(action: "check-policies", resource: "<file_path>")
35
- \`\`\`
36
- If a policy matches: call \`hivemind_approvals(action: "request", channel: "general", description: "...")\`, then poll \`hivemind_approvals(action: "check", correlation_id: "...")\` until approved. Do NOT edit the file until approved.
22
+ If a lock blocks you: another agent is editing that file. Request approval to override, or work on a different file.
23
+ If a policy blocks you: the file requires human approval. Request approval and wait.
37
24
 
38
- ### Rule 4: Publish outcomes
25
+ ### Rule 3: Publish outcomes
39
26
 
40
27
  After completing work, publish what you did:
41
28
  \`\`\`
@@ -45,32 +32,95 @@ Also publish \`decision.made\` when choosing between approaches, \`task.blocked\
45
32
 
46
33
  Do NOT publish routine activity (file reads, retries, lint fixes). Only publish outcomes and decisions.
47
34
  ${HIVEMIND_SECTION_END}`;
35
+ const HOOKS_CONFIG = {
36
+ hooks: {
37
+ PreToolUse: [
38
+ {
39
+ matcher: "Edit|Write",
40
+ hooks: [
41
+ {
42
+ type: "command",
43
+ command: "hivemind guard",
44
+ timeout: 10,
45
+ },
46
+ ],
47
+ },
48
+ ],
49
+ PostToolUse: [
50
+ {
51
+ matcher: "Edit|Write",
52
+ hooks: [
53
+ {
54
+ type: "command",
55
+ command: "hivemind release",
56
+ timeout: 10,
57
+ },
58
+ ],
59
+ },
60
+ ],
61
+ },
62
+ };
48
63
  export async function init() {
49
64
  const cwd = process.cwd();
50
65
  const claudeMdPath = join(cwd, "CLAUDE.md");
51
- console.log("Hivemind Init — Add agent coordination instructions to CLAUDE.md\n");
66
+ console.log("Hivemind Init\n");
67
+ // --- 1. Update CLAUDE.md ---
52
68
  if (existsSync(claudeMdPath)) {
53
69
  const existing = readFileSync(claudeMdPath, "utf-8");
54
- // Check if Hivemind section already exists
55
70
  if (existing.includes(HIVEMIND_SECTION_START)) {
56
- // Replace existing section
57
71
  const before = existing.slice(0, existing.indexOf(HIVEMIND_SECTION_START));
58
72
  const after = existing.slice(existing.indexOf(HIVEMIND_SECTION_END) + HIVEMIND_SECTION_END.length);
59
73
  writeFileSync(claudeMdPath, before + HIVEMIND_CLAUDE_MD + after);
60
- console.log("Updated existing Hivemind section in CLAUDE.md");
74
+ console.log(" Updated Hivemind section in CLAUDE.md");
61
75
  }
62
76
  else {
63
- // Append to existing file
64
77
  writeFileSync(claudeMdPath, existing.trimEnd() + "\n\n" + HIVEMIND_CLAUDE_MD + "\n");
65
- console.log("Added Hivemind section to existing CLAUDE.md");
78
+ console.log(" Added Hivemind section to CLAUDE.md");
66
79
  }
67
80
  }
68
81
  else {
69
- // Create new CLAUDE.md
70
82
  writeFileSync(claudeMdPath, `# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n${HIVEMIND_CLAUDE_MD}\n`);
71
- console.log("Created CLAUDE.md with Hivemind instructions");
83
+ console.log(" Created CLAUDE.md with Hivemind instructions");
72
84
  }
73
- console.log(`\nDone! Agents will now auto-publish events to Hivemind.`);
74
- console.log(`Edit ${claudeMdPath} to customize channels and behavior.`);
85
+ // --- 2. Configure Claude Code hooks ---
86
+ const claudeDir = join(cwd, ".claude");
87
+ const settingsPath = join(claudeDir, "settings.local.json");
88
+ mkdirSync(claudeDir, { recursive: true });
89
+ let settings = {};
90
+ if (existsSync(settingsPath)) {
91
+ try {
92
+ settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
93
+ }
94
+ catch {
95
+ // If parse fails, start fresh
96
+ }
97
+ }
98
+ // Merge hooks — preserve existing hooks, add/replace hivemind ones
99
+ const existingHooks = (settings.hooks ?? {});
100
+ const newHooks = { ...existingHooks };
101
+ // Filter out any existing hivemind hooks, then add ours
102
+ for (const event of ["PreToolUse", "PostToolUse"]) {
103
+ const existing = (existingHooks[event] ?? []);
104
+ const filtered = existing.filter((h) => {
105
+ // Keep hooks that aren't hivemind
106
+ const cmds = h.hooks?.map((hh) => hh.command ?? "") ?? [];
107
+ return !cmds.some((c) => c.startsWith("hivemind "));
108
+ });
109
+ const hivemindHooks = HOOKS_CONFIG.hooks[event];
110
+ newHooks[event] = [...filtered, ...hivemindHooks];
111
+ }
112
+ settings.hooks = newHooks;
113
+ writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
114
+ console.log(" Configured Claude Code hooks in .claude/settings.local.json");
115
+ console.log(`
116
+ Done! Hivemind is now active in this project:
117
+
118
+ - CLAUDE.md: Agent instructions for publishing events
119
+ - Hooks: Auto-lock files before edit, auto-release after
120
+ - Hooks: Auto-check approval policies before edit
121
+
122
+ Locks and policies are now enforced automatically — agents don't need
123
+ to remember to call hivemind_lock or hivemind_approvals manually.
124
+ `);
75
125
  }
76
126
  //# sourceMappingURL=init.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,sBAAsB,GAAG,yBAAyB,CAAC;AACzD,MAAM,oBAAoB,GAAG,uBAAuB,CAAC;AAErD,MAAM,kBAAkB,GAAG,GAAG,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0ClD,oBAAoB,EAAE,CAAC;AAEzB,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IAE5C,OAAO,CAAC,GAAG,CAAC,oEAAoE,CAAC,CAAC;IAElF,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAErD,2CAA2C;QAC3C,IAAI,QAAQ,CAAC,QAAQ,CAAC,sBAAsB,CAAC,EAAE,CAAC;YAC9C,2BAA2B;YAC3B,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC,CAAC;YAC3E,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,oBAAoB,CAAC,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;YACnG,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,kBAAkB,GAAG,KAAK,CAAC,CAAC;YACjE,OAAO,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC;QAChE,CAAC;aAAM,CAAC;YACN,0BAA0B;YAC1B,aAAa,CAAC,YAAY,EAAE,QAAQ,CAAC,OAAO,EAAE,GAAG,MAAM,GAAG,kBAAkB,GAAG,IAAI,CAAC,CAAC;YACrF,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;SAAM,CAAC;QACN,uBAAuB;QACvB,aAAa,CAAC,YAAY,EAAE,4HAA4H,kBAAkB,IAAI,CAAC,CAAC;QAChL,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;IAC9D,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;IACxE,OAAO,CAAC,GAAG,CAAC,QAAQ,YAAY,sCAAsC,CAAC,CAAC;AAC1E,CAAC"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function release(): Promise<void>;
2
+ //# sourceMappingURL=release.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"release.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/release.ts"],"names":[],"mappings":"AA+BA,wBAAsB,OAAO,kBA0C5B"}
@@ -0,0 +1,54 @@
1
+ import { readFileSync, existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ function loadCredentials() {
4
+ const credPath = join(process.env.HOME ?? process.env.USERPROFILE ?? ".", ".hivemind", "credentials.json");
5
+ if (!existsSync(credPath))
6
+ return null;
7
+ try {
8
+ const creds = JSON.parse(readFileSync(credPath, "utf-8"));
9
+ return { api_key: creds.api_key, api_url: creds.api_url };
10
+ }
11
+ catch {
12
+ return null;
13
+ }
14
+ }
15
+ function getAgentName() {
16
+ return process.env.HIVEMIND_AGENT ?? `claude-${process.pid}`;
17
+ }
18
+ export async function release() {
19
+ let input;
20
+ try {
21
+ const raw = readFileSync(0, "utf-8");
22
+ input = JSON.parse(raw);
23
+ }
24
+ catch {
25
+ process.exit(0);
26
+ }
27
+ const filePath = input.tool_input?.file_path;
28
+ if (!filePath) {
29
+ process.exit(0);
30
+ }
31
+ const creds = loadCredentials();
32
+ if (!creds) {
33
+ process.exit(0);
34
+ }
35
+ const agent = getAgentName();
36
+ // Make path relative
37
+ const cwd = input.cwd ?? process.cwd();
38
+ let resource = filePath;
39
+ if (resource.startsWith(cwd)) {
40
+ resource = resource.slice(cwd.length).replace(/^\//, "");
41
+ }
42
+ // Release the lock
43
+ try {
44
+ await fetch(`${creds.api_url}/v1/locks/${encodeURIComponent(resource)}?agent=${encodeURIComponent(agent)}`, {
45
+ method: "DELETE",
46
+ headers: { Authorization: `Bearer ${creds.api_key}` },
47
+ });
48
+ }
49
+ catch {
50
+ // Don't fail on network errors
51
+ }
52
+ process.exit(0);
53
+ }
54
+ //# sourceMappingURL=release.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"release.js","sourceRoot":"","sources":["../../../src/cli/commands/release.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAWjC,SAAS,eAAe;IACtB,MAAM,QAAQ,GAAG,IAAI,CACnB,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,GAAG,EAClD,WAAW,EACX,kBAAkB,CACnB,CAAC;IACF,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;QAC1D,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,YAAY;IACnB,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,UAAU,OAAO,CAAC,GAAG,EAAE,CAAC;AAC/D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO;IAC3B,IAAI,KAAgB,CAAC;IACrB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACrC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,EAAE,SAAS,CAAC;IAC7C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,KAAK,GAAG,YAAY,EAAE,CAAC;IAE7B,qBAAqB;IACrB,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACvC,IAAI,QAAQ,GAAG,QAAQ,CAAC;IACxB,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7B,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,mBAAmB;IACnB,IAAI,CAAC;QACH,MAAM,KAAK,CACT,GAAG,KAAK,CAAC,OAAO,aAAa,kBAAkB,CAAC,QAAQ,CAAC,UAAU,kBAAkB,CAAC,KAAK,CAAC,EAAE,EAC9F;YACE,MAAM,EAAE,QAAQ;YAChB,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,CAAC,OAAO,EAAE,EAAE;SACtD,CACF,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,+BAA+B;IACjC,CAAC;IAED,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
package/dist/cli/index.js CHANGED
@@ -4,6 +4,8 @@ import { logout } from "./commands/logout.js";
4
4
  import { status } from "./commands/status.js";
5
5
  import { switchOrg } from "./commands/switch.js";
6
6
  import { init } from "./commands/init.js";
7
+ import { guard } from "./commands/guard.js";
8
+ import { release } from "./commands/release.js";
7
9
  const command = process.argv[2];
8
10
  const commands = {
9
11
  login,
@@ -12,6 +14,8 @@ const commands = {
12
14
  status,
13
15
  switch: switchOrg,
14
16
  init,
17
+ guard,
18
+ release,
15
19
  };
16
20
  async function main() {
17
21
  if (!command || command === "--help" || command === "-h") {
@@ -24,7 +28,7 @@ Commands:
24
28
  logout Remove stored credentials and editor configs
25
29
  status Show project status (active tasks, blockers)
26
30
  switch Switch to a different organization
27
- init Add Hivemind instructions to CLAUDE.md for auto-publishing
31
+ init Add Hivemind instructions to CLAUDE.md + set up hooks
28
32
 
29
33
  Options:
30
34
  --help Show this help message
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE1C,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAEhC,MAAM,QAAQ,GAAwC;IACpD,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM,EAAE,SAAS;IACjB,IAAI;CACL,CAAC;AAEF,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;CAaf,CAAC,IAAI,EAAE,CAAC,CAAC;QACN,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAClC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;QAC7C,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;QAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,EAAE,CAAC;AAClB,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAEhD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAEhC,MAAM,QAAQ,GAAwC;IACpD,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM,EAAE,SAAS;IACjB,IAAI;IACJ,KAAK;IACL,OAAO;CACR,CAAC;AAEF,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;CAaf,CAAC,IAAI,EAAE,CAAC,CAAC;QACN,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAClC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;QAC7C,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;QAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,EAAE,CAAC;AAClB,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hivemindai/mcp-server",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "MCP server for Hivemind — persistent event log for AI agent coordination",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -13,6 +13,12 @@
13
13
  "dist",
14
14
  "bin"
15
15
  ],
16
+ "scripts": {
17
+ "build": "tsc",
18
+ "test": "vitest run",
19
+ "lint": "eslint src/",
20
+ "dev": "node --watch dist/index.js"
21
+ },
16
22
  "keywords": [
17
23
  "mcp",
18
24
  "hivemind",
@@ -33,15 +39,9 @@
33
39
  "access": "public"
34
40
  },
35
41
  "dependencies": {
42
+ "@hivemindai/core": "workspace:*",
43
+ "@hivemindai/sdk-ts": "workspace:*",
36
44
  "@modelcontextprotocol/sdk": "^1.12.1",
37
- "zod": "^3.25.76",
38
- "@hivemindai/core": "0.1.7",
39
- "@hivemindai/sdk-ts": "0.2.0"
40
- },
41
- "scripts": {
42
- "build": "tsc",
43
- "test": "vitest run",
44
- "lint": "eslint src/",
45
- "dev": "node --watch dist/index.js"
45
+ "zod": "^3.25.76"
46
46
  }
47
- }
47
+ }