@mclawnet/mcp-server 0.1.2 → 0.1.4

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 ADDED
@@ -0,0 +1,44 @@
1
+ # @mclawnet/mcp-server
2
+
3
+ MCP server exposing ClawNet capabilities (skills, memory, evolution, tasks,
4
+ inbox) to any Model Context Protocol client.
5
+
6
+ The binary `clawnet-mcp` is registered in `package.json#bin` and launched by
7
+ the agent host (or any external MCP client).
8
+
9
+ ## Tool groups
10
+
11
+ - **Skill** — discover and execute skills from the local skill manager.
12
+ - **Memory** — read/write the agent memory store.
13
+ - **Evolution** — skill evolution telemetry helpers.
14
+ - **Task & Inbox** — first-class task graph + inter-instance messaging
15
+ (added in 0.1.4, see below).
16
+
17
+ ## Task & Inbox tools
18
+
19
+ Backed by `@mclawnet/task`. All tools are project-scoped via a required
20
+ `workDir` argument (absolute path to the project working directory). See
21
+ the design doc `docs/plans/2026-04-25-task-as-first-class-design.md`.
22
+
23
+ | Tool | Description |
24
+ | --- | --- |
25
+ | `task_create` | Create a task in the project task store. |
26
+ | `task_get` | Fetch a task by id. |
27
+ | `task_list` | List tasks with optional `swarmId` / `status` / `owner` filters. |
28
+ | `task_set_status` | Update status; cancel auto-unlinks edges and fans out inbox notifications to downstream owners. |
29
+ | `task_set_owner` | Set or clear (`null`) the owner instance id. |
30
+ | `task_add_comment` | Append an idempotent comment (auto-uuid if `id` omitted). |
31
+ | `task_link` | Add a `blockedBy` / `blocks` edge; rejects self-link, cycles, missing tasks. |
32
+ | `task_unlink` | Remove an edge in both directions; no-op if absent. |
33
+ | `task_create_from_message` | Spin a task off an inbox message; records `origin_message` system comment. |
34
+ | `task_briefing` | Per-instance situation summary (actionable / awareness / counters / warnings). |
35
+ | `lead_briefing` | Queen-facing buckets: `assign_owner`, `assign_reviewer`, `clarify`, `repair_dependencies`, `lead_owned`. |
36
+ | `member_briefing` | Boot briefing for a worker/queen with hardcoded boot rules + bootstrap context. |
37
+ | `message_send` | Durably write an inbox message between two instances within a swarm. |
38
+
39
+ ### Fan-out
40
+
41
+ When a task transitions to a terminal state (e.g. `done` or `cancelled`),
42
+ the server walks its `blocks` edges and delivers an inbox message via
43
+ `message_send` to each downstream task's owner — so newly unblocked work
44
+ surfaces without the recipient polling.
package/dist/server.js CHANGED
@@ -9,19 +9,29 @@ import { createEmbeddingProviders, EmbeddingService, initDatabase, MemoryStore,
9
9
  import { SkillStore, EvolutionPipeline } from "@mclawnet/skill-manager";
10
10
  import { getAllToolDefinitions, routeToolCall } from "./tools/index.js";
11
11
  const log = createLogger({ module: "mcp-server" });
12
- const dbPath = process.env.CLAWNET_MEMORY_DB ?? join(homedir(), ".clawnet", "memory.db");
12
+ // Two distinct roots:
13
+ // homeDir — user home (no `.clawnet` suffix). TaskStore/InboxStore append
14
+ // `.clawnet/projects/...` themselves via projectRoot(); double-
15
+ // appending here corrupts the layout (#…/.clawnet/.clawnet/…).
16
+ // Honour CLAWNET_HOME so tests and InboxStore stay in sync.
17
+ // clawnetDir — the `.clawnet` directory itself (skills, evolution, memory).
18
+ const homeDir = process.env.CLAWNET_HOME ?? homedir();
19
+ const clawnetDir = process.env.CLAWNET_DIR ?? join(homeDir, ".clawnet");
20
+ const dbPath = process.env.CLAWNET_MEMORY_DB ?? join(clawnetDir, "memory.db");
13
21
  const db = initDatabase(dbPath);
14
22
  log.info({ dbPath }, "ClawNet MCP server starting");
15
23
  const store = new MemoryStore(db);
16
24
  const providers = createEmbeddingProviders();
17
25
  const embeddingService = new EmbeddingService(db, providers);
18
- const clawnetDir = process.env.CLAWNET_DIR ?? join(homedir(), ".clawnet");
19
26
  const skillStore = new SkillStore(clawnetDir);
20
27
  const evolutionPipeline = new EvolutionPipeline(clawnetDir);
21
28
  const context = {
22
29
  memory: { store, embeddingService },
23
30
  skill: { store: skillStore },
24
31
  evolution: { pipeline: evolutionPipeline },
32
+ task: { rootDir: homeDir },
33
+ inbox: { rootDir: homeDir },
34
+ planReview: { rootDir: homeDir },
25
35
  };
26
36
  const server = new Server({ name: "clawnet-mcp", version: "0.1.0" }, { capabilities: { tools: {} } });
27
37
  server.setRequestHandler(ListToolsRequestSchema, async () => ({
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ export interface InboxRelayLike {
2
+ deliver(swarmId: string, instanceId: string): void | Promise<void>;
3
+ }
4
+ export interface InboxToolContext {
5
+ rootDir: string;
6
+ /**
7
+ * Optional task store root, used by `message_send` to validate the optional
8
+ * `expectedStatus` / `expectedOwner` pre-check fields. When unset, those
9
+ * fields are silently ignored (back-compat with callers that don't wire a
10
+ * task context). The router wires this to `context.task.rootDir`.
11
+ */
12
+ taskRootDir?: string;
13
+ /**
14
+ * Optional in-process relay. When present, message_send will call
15
+ * `relay.deliver(swarmId, to)` after writing to disk so the recipient
16
+ * agent is woken immediately. Failures are swallowed (best-effort).
17
+ */
18
+ relay?: InboxRelayLike;
19
+ }
20
+ export declare const INBOX_TOOL_NAMES: Set<string>;
21
+ export declare function getInboxToolDefinitions(): {
22
+ name: string;
23
+ description: string;
24
+ inputSchema: {
25
+ type: "object";
26
+ properties: {
27
+ workDir: {
28
+ type: string;
29
+ description: string;
30
+ };
31
+ swarmId: {
32
+ type: string;
33
+ description: string;
34
+ };
35
+ from: {
36
+ type: string;
37
+ description: string;
38
+ };
39
+ to: {
40
+ type: string;
41
+ description: string;
42
+ };
43
+ type: {
44
+ type: string;
45
+ description: string;
46
+ };
47
+ data: {
48
+ type: string;
49
+ description: string;
50
+ };
51
+ taskId: {
52
+ type: string;
53
+ description: string;
54
+ };
55
+ expectedStatus: {
56
+ type: string;
57
+ description: string;
58
+ };
59
+ expectedOwner: {
60
+ type: string[];
61
+ description: string;
62
+ };
63
+ };
64
+ required: string[];
65
+ };
66
+ }[];
67
+ export declare function handleInboxToolCall(name: string, args: Record<string, unknown>, context: InboxToolContext): Promise<{
68
+ content: Array<{
69
+ type: "text";
70
+ text: string;
71
+ }>;
72
+ isError?: boolean;
73
+ }>;
74
+ //# sourceMappingURL=inbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbox.d.ts","sourceRoot":"","sources":["../../src/tools/inbox.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpE;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,KAAK,CAAC,EAAE,cAAc,CAAC;CACxB;AAED,eAAO,MAAM,gBAAgB,aAA4B,CAAC;AAE1D,wBAAgB,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA+BtC;AAED,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAoBhF"}
@@ -0,0 +1,168 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { createLogger } from "@mclawnet/logger";
3
+ import { InboxStore } from "@mclawnet/swarm";
4
+ import { TaskStore } from "@mclawnet/task";
5
+ const log = createLogger({ module: "mcp-server/tools/inbox" });
6
+ export const INBOX_TOOL_NAMES = new Set(["message_send"]);
7
+ export function getInboxToolDefinitions() {
8
+ return [
9
+ {
10
+ name: "message_send",
11
+ description: "Send an inbox message from one agent instance to another within a swarm. Writes the message to the recipient's inbox file and (when an in-process relay is wired) signals immediate delivery. The swarm/recipient need not exist; the message is durably written and will be picked up later. Optional expectedStatus/expectedOwner act as an optimistic pre-check against the linked task — when the live task no longer matches the sender's view, the send is rejected with isError so the sender can re-read and re-decide rather than nudging based on a stale snapshot.",
12
+ inputSchema: {
13
+ type: "object",
14
+ properties: {
15
+ workDir: { type: "string", description: "Absolute path of the project working directory" },
16
+ swarmId: { type: "string", description: "Swarm id the recipient lives in" },
17
+ from: { type: "string", description: "Sender instance id (free-form, e.g. 'queen-0')" },
18
+ to: { type: "string", description: "Recipient instance id" },
19
+ type: { type: "string", description: "Application-defined message type" },
20
+ data: { type: "string", description: "Message payload as a string (callers serialise structured data themselves)" },
21
+ taskId: { type: "string", description: "Optional task id this message is associated with" },
22
+ expectedStatus: {
23
+ type: "string",
24
+ description: "Optional optimistic pre-check: requires the linked task's current status to equal this value, otherwise the send is rejected. Requires taskId.",
25
+ },
26
+ expectedOwner: {
27
+ type: ["string", "null"],
28
+ description: "Optional optimistic pre-check: requires the linked task's current owner to equal this value (use null to assert the task is unowned). Requires taskId.",
29
+ },
30
+ },
31
+ required: ["workDir", "swarmId", "from", "to", "type", "data"],
32
+ },
33
+ },
34
+ ];
35
+ }
36
+ export async function handleInboxToolCall(name, args, context) {
37
+ try {
38
+ log.info({ tool: name }, "MCP inbox tool called");
39
+ switch (name) {
40
+ case "message_send":
41
+ return await handleMessageSend(args, context);
42
+ default:
43
+ return {
44
+ content: [{ type: "text", text: JSON.stringify({ error: `Unknown tool: ${name}` }) }],
45
+ isError: true,
46
+ };
47
+ }
48
+ }
49
+ catch (err) {
50
+ const message = err instanceof Error ? err.message : String(err);
51
+ log.error({ tool: name, err }, "MCP inbox tool error");
52
+ return {
53
+ content: [{ type: "text", text: JSON.stringify({ error: message }) }],
54
+ isError: true,
55
+ };
56
+ }
57
+ }
58
+ /**
59
+ * All expected-state pre-check rejections share this envelope so callers can
60
+ * write a single parser. Returned directly (not thrown) because the wrapper
61
+ * at handleInboxToolCall would otherwise strip structured fields.
62
+ */
63
+ function rejectPrecheck(payload) {
64
+ return {
65
+ content: [{ type: "text", text: JSON.stringify(payload) }],
66
+ isError: true,
67
+ };
68
+ }
69
+ async function handleMessageSend(args, context) {
70
+ const workDir = args.workDir;
71
+ const swarmId = args.swarmId;
72
+ const from = args.from;
73
+ const to = args.to;
74
+ const type = args.type;
75
+ const data = args.data;
76
+ if (!workDir)
77
+ throw new Error("workDir is required");
78
+ if (!swarmId)
79
+ throw new Error("swarmId is required");
80
+ if (!from)
81
+ throw new Error("from is required");
82
+ if (!to)
83
+ throw new Error("to is required");
84
+ if (!type)
85
+ throw new Error("type is required");
86
+ if (data === undefined || data === null)
87
+ throw new Error("data is required");
88
+ const taskId = args.taskId;
89
+ const hasExpectedStatus = "expectedStatus" in args && args.expectedStatus !== undefined;
90
+ const hasExpectedOwner = "expectedOwner" in args && args.expectedOwner !== undefined;
91
+ // Optimistic pre-check: if the sender wants to assert the linked task is in
92
+ // a specific state (typical use: queen nudging a worker), verify the live
93
+ // task matches before writing the message. This prevents nudges based on a
94
+ // stale snapshot — the sender should re-read and re-decide instead.
95
+ //
96
+ // All rejections here return the same structured envelope:
97
+ // { error, taskId?, expected?, observed? }
98
+ // …so callers can write a single parser regardless of which precondition
99
+ // failed. (The wrapper at handleInboxToolCall catches throws and only
100
+ // serialises {error: message}, which would strip the extra fields — so we
101
+ // return directly with isError: true rather than throwing.)
102
+ if (hasExpectedStatus || hasExpectedOwner) {
103
+ const expected = {};
104
+ if (hasExpectedStatus)
105
+ expected.status = args.expectedStatus;
106
+ if (hasExpectedOwner)
107
+ expected.owner = args.expectedOwner;
108
+ if (!taskId) {
109
+ return rejectPrecheck({
110
+ error: "taskId is required when expectedStatus or expectedOwner is supplied",
111
+ expected,
112
+ });
113
+ }
114
+ if (!context.taskRootDir) {
115
+ // Wiring bug, not a caller error: surface it loudly so the operator can
116
+ // see that the router didn't pass through task.rootDir.
117
+ throw new Error("expected-state pre-check requested but inbox context has no taskRootDir wired");
118
+ }
119
+ const taskStore = new TaskStore({ workDir, home: context.taskRootDir });
120
+ const live = taskStore.tryGet(taskId);
121
+ if (!live) {
122
+ return rejectPrecheck({
123
+ error: `Task not found: ${taskId}`,
124
+ taskId,
125
+ expected,
126
+ });
127
+ }
128
+ const observed = {
129
+ status: live.status,
130
+ owner: live.owner,
131
+ };
132
+ const statusMismatch = hasExpectedStatus && observed.status !== expected.status;
133
+ const ownerMismatch = hasExpectedOwner && observed.owner !== expected.owner;
134
+ if (statusMismatch || ownerMismatch) {
135
+ return rejectPrecheck({
136
+ error: "stale snapshot: expected task state does not match observed state",
137
+ taskId,
138
+ expected,
139
+ observed,
140
+ });
141
+ }
142
+ }
143
+ const messageId = randomUUID();
144
+ const msg = {
145
+ id: messageId,
146
+ from,
147
+ type,
148
+ data,
149
+ ...(taskId ? { taskId } : {}),
150
+ timestamp: Date.now(),
151
+ delivered: false,
152
+ };
153
+ const store = new InboxStore(workDir, swarmId, context.rootDir);
154
+ await store.append(to, msg);
155
+ if (context.relay) {
156
+ try {
157
+ await context.relay.deliver(swarmId, to);
158
+ }
159
+ catch (err) {
160
+ // Best-effort: relay wake-up failures must not abort message_send.
161
+ log.warn({ err, swarmId, to }, "inbox relay deliver failed (best-effort)");
162
+ }
163
+ }
164
+ return {
165
+ content: [{ type: "text", text: JSON.stringify({ messageId }) }],
166
+ };
167
+ }
168
+ //# sourceMappingURL=inbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbox.js","sourceRoot":"","sources":["../../src/tools/inbox.ts"],"names":[],"mappings":"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"}