@agent-workspace/mcp-server 0.2.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +42 -5
  2. package/dist/index.d.ts +6 -0
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +30 -568
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.test.d.ts +2 -0
  7. package/dist/index.test.d.ts.map +1 -0
  8. package/dist/index.test.js +726 -0
  9. package/dist/index.test.js.map +1 -0
  10. package/dist/tools/artifact.d.ts +6 -0
  11. package/dist/tools/artifact.d.ts.map +1 -0
  12. package/dist/tools/artifact.js +428 -0
  13. package/dist/tools/artifact.js.map +1 -0
  14. package/dist/tools/config.d.ts +6 -0
  15. package/dist/tools/config.d.ts.map +1 -0
  16. package/dist/tools/config.js +91 -0
  17. package/dist/tools/config.js.map +1 -0
  18. package/dist/tools/contract.d.ts +6 -0
  19. package/dist/tools/contract.d.ts.map +1 -0
  20. package/dist/tools/contract.js +233 -0
  21. package/dist/tools/contract.js.map +1 -0
  22. package/dist/tools/identity.d.ts +6 -0
  23. package/dist/tools/identity.d.ts.map +1 -0
  24. package/dist/tools/identity.js +91 -0
  25. package/dist/tools/identity.js.map +1 -0
  26. package/dist/tools/memory.d.ts +6 -0
  27. package/dist/tools/memory.d.ts.map +1 -0
  28. package/dist/tools/memory.js +145 -0
  29. package/dist/tools/memory.js.map +1 -0
  30. package/dist/tools/project.d.ts +6 -0
  31. package/dist/tools/project.d.ts.map +1 -0
  32. package/dist/tools/project.js +184 -0
  33. package/dist/tools/project.js.map +1 -0
  34. package/dist/tools/reputation.d.ts +6 -0
  35. package/dist/tools/reputation.d.ts.map +1 -0
  36. package/dist/tools/reputation.js +206 -0
  37. package/dist/tools/reputation.js.map +1 -0
  38. package/dist/tools/status.d.ts +6 -0
  39. package/dist/tools/status.d.ts.map +1 -0
  40. package/dist/tools/status.js +223 -0
  41. package/dist/tools/status.js.map +1 -0
  42. package/dist/tools/swarm.d.ts +6 -0
  43. package/dist/tools/swarm.d.ts.map +1 -0
  44. package/dist/tools/swarm.js +483 -0
  45. package/dist/tools/swarm.js.map +1 -0
  46. package/dist/tools/task.d.ts +6 -0
  47. package/dist/tools/task.d.ts.map +1 -0
  48. package/dist/tools/task.js +347 -0
  49. package/dist/tools/task.js.map +1 -0
  50. package/dist/utils.d.ts +23 -0
  51. package/dist/utils.d.ts.map +1 -0
  52. package/dist/utils.js +56 -0
  53. package/dist/utils.js.map +1 -0
  54. package/package.json +8 -2
package/README.md CHANGED
@@ -28,28 +28,65 @@ It will auto-discover the AWP workspace from the current directory (or use `AWP_
28
28
 
29
29
  ## Tools
30
30
 
31
+ ### Core Identity & Context
32
+
31
33
  | Tool | Description |
32
34
  |------|-------------|
33
35
  | `awp_read_identity` | Read agent identity (name, capabilities, DID) |
34
36
  | `awp_read_soul` | Read behavioral constraints (values, boundaries, governance) |
35
37
  | `awp_read_user` | Read human profile |
36
- | `awp_read_memory` | Read memory (daily or long-term) |
37
- | `awp_write_memory` | Log structured memory entries |
38
+ | `awp_read_agents` | Read operations config (AGENTS.md) |
39
+ | `awp_read_tools` | Read tools config (TOOLS.md) |
40
+ | `awp_read_heartbeat` | Read heartbeat config (HEARTBEAT.md) |
41
+
42
+ ### Memory Operations
43
+
44
+ | Tool | Description |
45
+ |------|-------------|
46
+ | `awp_read_memory` | Read memory (daily, longterm, or recent logs) |
47
+ | `awp_write_memory` | Log structured memory entries to daily log |
48
+
49
+ ### Knowledge Artifacts (SMP)
50
+
51
+ | Tool | Description |
52
+ |------|-------------|
38
53
  | `awp_artifact_read` | Read a knowledge artifact by slug |
39
- | `awp_artifact_write` | Create or update a knowledge artifact |
54
+ | `awp_artifact_write` | Create or update a knowledge artifact with versioning |
40
55
  | `awp_artifact_list` | List all artifacts (optional tag filter) |
41
56
  | `awp_artifact_search` | Search artifacts by content, title, or tags |
42
- | `awp_workspace_status` | Workspace summary (files present, memory count, artifact count) |
57
+
58
+ ### Reputation (RDP)
59
+
60
+ | Tool | Description |
61
+ |------|-------------|
62
+ | `awp_reputation_query` | Query reputation profiles with time-based decay applied |
63
+ | `awp_reputation_signal` | Log reputation signals (uses EWMA with decay) |
64
+
65
+ ### Delegation Contracts (RDP)
66
+
67
+ | Tool | Description |
68
+ |------|-------------|
69
+ | `awp_contract_create` | Create delegation contracts between agents |
70
+ | `awp_contract_evaluate` | Evaluate contracts and generate reputation signals |
71
+ | `awp_contract_list` | List all contracts with optional status filter |
72
+
73
+ ### Workspace Management
74
+
75
+ | Tool | Description |
76
+ |------|-------------|
77
+ | `awp_workspace_status` | Workspace health check (files present, stats) |
43
78
 
44
79
  ## How It Works
45
80
 
46
- The MCP server reads and writes AWP workspace files directly — no database, no daemon. Your agent's identity, memory, and knowledge artifacts are just Markdown files with YAML frontmatter, stored in a directory and compatible with Git.
81
+ The MCP server reads and writes AWP workspace files directly — no database, no daemon. Your agent's identity, memory, knowledge artifacts, and reputation profiles are just Markdown files with YAML frontmatter, stored in a directory and compatible with Git.
47
82
 
48
83
  When an AI agent connects via MCP, it can:
49
84
  - **Read** its identity, soul, and user context at the start of each session
50
85
  - **Write** memory entries as it works
51
86
  - **Create and update** knowledge artifacts with full provenance tracking
52
87
  - **Search** its accumulated knowledge
88
+ - **Query and update** reputation profiles for itself and other agents
89
+ - **Create and evaluate** delegation contracts for multi-agent coordination
53
90
 
54
91
  ## Part of AWP
55
92
 
package/dist/index.d.ts CHANGED
@@ -1,3 +1,9 @@
1
1
  #!/usr/bin/env node
2
+ /**
3
+ * AWP MCP Server
4
+ *
5
+ * MCP server exposing Agent Workspace Protocol operations.
6
+ * Plug any AWP workspace into any MCP client.
7
+ */
2
8
  export {};
3
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;GAKG"}
package/dist/index.js CHANGED
@@ -1,578 +1,40 @@
1
1
  #!/usr/bin/env node
2
+ /**
3
+ * AWP MCP Server
4
+ *
5
+ * MCP server exposing Agent Workspace Protocol operations.
6
+ * Plug any AWP workspace into any MCP client.
7
+ */
2
8
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
9
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
- import * as z from "zod";
5
- import { readFile, writeFile, readdir, mkdir, access } from "node:fs/promises";
6
- import { join } from "node:path";
7
- import matter from "gray-matter";
8
- import { AWP_VERSION, SMP_VERSION, MEMORY_DIR, ARTIFACTS_DIR } from "@agent-workspace/core";
10
+ import { AWP_VERSION } from "@agent-workspace/core";
11
+ // Tool registration modules
12
+ import { registerIdentityTools } from "./tools/identity.js";
13
+ import { registerMemoryTools } from "./tools/memory.js";
14
+ import { registerArtifactTools } from "./tools/artifact.js";
15
+ import { registerStatusTools } from "./tools/status.js";
16
+ import { registerReputationTools } from "./tools/reputation.js";
17
+ import { registerContractTools } from "./tools/contract.js";
18
+ import { registerProjectTools } from "./tools/project.js";
19
+ import { registerTaskTools } from "./tools/task.js";
20
+ import { registerConfigTools } from "./tools/config.js";
21
+ import { registerSwarmTools } from "./tools/swarm.js";
22
+ // Create MCP server
9
23
  const server = new McpServer({
10
24
  name: "awp-workspace",
11
25
  version: AWP_VERSION,
12
26
  });
13
- /**
14
- * Resolve workspace root from the AWP_WORKSPACE env var or cwd
15
- */
16
- function getWorkspaceRoot() {
17
- return process.env.AWP_WORKSPACE || process.cwd();
18
- }
19
- async function fileExists(path) {
20
- try {
21
- await access(path);
22
- return true;
23
- }
24
- catch {
25
- return false;
26
- }
27
- }
28
- /**
29
- * Get agent DID from workspace manifest, or "anonymous"
30
- */
31
- async function getAgentDid(root) {
32
- try {
33
- const raw = await readFile(join(root, ".awp", "workspace.json"), "utf-8");
34
- const manifest = JSON.parse(raw);
35
- return manifest.agent?.did || "anonymous";
36
- }
37
- catch {
38
- return "anonymous";
39
- }
40
- }
41
- // --- Tool: awp_read_identity ---
42
- server.registerTool("awp_read_identity", {
43
- title: "Read Agent Identity",
44
- description: "Read this agent's identity (name, creature, capabilities, DID) from the AWP workspace",
45
- inputSchema: {},
46
- }, async () => {
47
- const root = getWorkspaceRoot();
48
- const path = join(root, "IDENTITY.md");
49
- try {
50
- const raw = await readFile(path, "utf-8");
51
- const { data, content } = matter(raw);
52
- return {
53
- content: [
54
- {
55
- type: "text",
56
- text: JSON.stringify({ frontmatter: data, body: content.trim() }, null, 2),
57
- },
58
- ],
59
- };
60
- }
61
- catch {
62
- return {
63
- content: [{ type: "text", text: "Error: IDENTITY.md not found" }],
64
- isError: true,
65
- };
66
- }
67
- });
68
- // --- Tool: awp_read_soul ---
69
- server.registerTool("awp_read_soul", {
70
- title: "Read Agent Soul",
71
- description: "Read this agent's values, boundaries, and governance rules from the AWP workspace",
72
- inputSchema: {},
73
- }, async () => {
74
- const root = getWorkspaceRoot();
75
- const path = join(root, "SOUL.md");
76
- try {
77
- const raw = await readFile(path, "utf-8");
78
- const { data, content } = matter(raw);
79
- return {
80
- content: [
81
- {
82
- type: "text",
83
- text: JSON.stringify({ frontmatter: data, body: content.trim() }, null, 2),
84
- },
85
- ],
86
- };
87
- }
88
- catch {
89
- return {
90
- content: [{ type: "text", text: "Error: SOUL.md not found" }],
91
- isError: true,
92
- };
93
- }
94
- });
95
- // --- Tool: awp_read_user ---
96
- server.registerTool("awp_read_user", {
97
- title: "Read Human Profile",
98
- description: "Read the human user's profile from the AWP workspace",
99
- inputSchema: {},
100
- }, async () => {
101
- const root = getWorkspaceRoot();
102
- const path = join(root, "USER.md");
103
- try {
104
- const raw = await readFile(path, "utf-8");
105
- const { data, content } = matter(raw);
106
- return {
107
- content: [
108
- {
109
- type: "text",
110
- text: JSON.stringify({ frontmatter: data, body: content.trim() }, null, 2),
111
- },
112
- ],
113
- };
114
- }
115
- catch {
116
- return {
117
- content: [{ type: "text", text: "Error: USER.md not found" }],
118
- isError: true,
119
- };
120
- }
121
- });
122
- // --- Tool: awp_read_memory ---
123
- server.registerTool("awp_read_memory", {
124
- title: "Read Memory",
125
- description: "Read memory entries. Specify a date (YYYY-MM-DD) for daily logs, or 'longterm' for MEMORY.md, or 'recent' for the last 3 days",
126
- inputSchema: {
127
- target: z
128
- .string()
129
- .describe("Which memory to read: a date like '2026-01-30', 'longterm', or 'recent'"),
130
- },
131
- }, async ({ target }) => {
132
- const root = getWorkspaceRoot();
133
- if (target === "longterm") {
134
- const path = join(root, "MEMORY.md");
135
- try {
136
- const raw = await readFile(path, "utf-8");
137
- const { data, content } = matter(raw);
138
- return {
139
- content: [
140
- {
141
- type: "text",
142
- text: JSON.stringify({ frontmatter: data, body: content.trim() }, null, 2),
143
- },
144
- ],
145
- };
146
- }
147
- catch {
148
- return {
149
- content: [
150
- { type: "text", text: "No long-term memory file exists yet." },
151
- ],
152
- };
153
- }
154
- }
155
- if (target === "recent") {
156
- const memDir = join(root, MEMORY_DIR);
157
- try {
158
- const files = await readdir(memDir);
159
- const mdFiles = files
160
- .filter((f) => f.endsWith(".md"))
161
- .sort()
162
- .reverse()
163
- .slice(0, 3);
164
- const results = [];
165
- for (const f of mdFiles) {
166
- const raw = await readFile(join(memDir, f), "utf-8");
167
- const { data, content } = matter(raw);
168
- results.push(`--- ${f} ---\n${JSON.stringify(data, null, 2)}\n${content.trim()}`);
169
- }
170
- return {
171
- content: [
172
- {
173
- type: "text",
174
- text: results.length
175
- ? results.join("\n\n")
176
- : "No recent memory entries.",
177
- },
178
- ],
179
- };
180
- }
181
- catch {
182
- return {
183
- content: [{ type: "text", text: "No memory directory found." }],
184
- };
185
- }
186
- }
187
- // Specific date
188
- const path = join(root, MEMORY_DIR, `${target}.md`);
189
- try {
190
- const raw = await readFile(path, "utf-8");
191
- const { data, content } = matter(raw);
192
- return {
193
- content: [
194
- {
195
- type: "text",
196
- text: JSON.stringify({ frontmatter: data, body: content.trim() }, null, 2),
197
- },
198
- ],
199
- };
200
- }
201
- catch {
202
- return {
203
- content: [
204
- { type: "text", text: `No memory entry for ${target}.` },
205
- ],
206
- };
207
- }
208
- });
209
- // --- Tool: awp_write_memory ---
210
- server.registerTool("awp_write_memory", {
211
- title: "Write Memory",
212
- description: "Append an entry to today's memory log in the AWP workspace",
213
- inputSchema: {
214
- content: z.string().describe("The memory entry to log"),
215
- tags: z
216
- .array(z.string())
217
- .optional()
218
- .describe("Optional categorization tags"),
219
- },
220
- }, async ({ content: entryContent, tags }) => {
221
- const root = getWorkspaceRoot();
222
- const memDir = join(root, MEMORY_DIR);
223
- await mkdir(memDir, { recursive: true });
224
- const date = new Date().toISOString().split("T")[0];
225
- const time = new Date().toTimeString().slice(0, 5);
226
- const filePath = join(memDir, `${date}.md`);
227
- const entry = {
228
- time,
229
- content: entryContent,
230
- tags: tags?.length ? tags : undefined,
231
- };
232
- let fileData;
233
- try {
234
- const raw = await readFile(filePath, "utf-8");
235
- fileData = matter(raw);
236
- if (!fileData.data.entries)
237
- fileData.data.entries = [];
238
- fileData.data.entries.push(entry);
239
- }
240
- catch {
241
- fileData = {
242
- data: {
243
- awp: AWP_VERSION,
244
- type: "memory-daily",
245
- date,
246
- entries: [entry],
247
- },
248
- content: `\n# ${date}\n\n`,
249
- };
250
- }
251
- const tagStr = tags?.length ? ` [${tags.join(", ")}]` : "";
252
- fileData.content += `- **${time}** — ${entryContent}${tagStr}\n`;
253
- const output = matter.stringify(fileData.content, fileData.data);
254
- await writeFile(filePath, output, "utf-8");
255
- return {
256
- content: [
257
- {
258
- type: "text",
259
- text: `Logged to memory/${date}.md at ${time}`,
260
- },
261
- ],
262
- };
263
- });
264
- // --- Tool: awp_artifact_read ---
265
- server.registerTool("awp_artifact_read", {
266
- title: "Read Knowledge Artifact",
267
- description: "Read a knowledge artifact by slug. Returns metadata (title, version, confidence, provenance) and body content.",
268
- inputSchema: {
269
- slug: z.string().describe("Artifact slug (e.g., 'llm-context-research')"),
270
- },
271
- }, async ({ slug }) => {
272
- const root = getWorkspaceRoot();
273
- const path = join(root, ARTIFACTS_DIR, `${slug}.md`);
274
- try {
275
- const raw = await readFile(path, "utf-8");
276
- const { data, content } = matter(raw);
277
- return {
278
- content: [
279
- {
280
- type: "text",
281
- text: JSON.stringify({ frontmatter: data, body: content.trim() }, null, 2),
282
- },
283
- ],
284
- };
285
- }
286
- catch {
287
- return {
288
- content: [
289
- { type: "text", text: `Artifact "${slug}" not found.` },
290
- ],
291
- isError: true,
292
- };
293
- }
294
- });
295
- // --- Tool: awp_artifact_write ---
296
- server.registerTool("awp_artifact_write", {
297
- title: "Write Knowledge Artifact",
298
- description: "Create or update a knowledge artifact. If the artifact exists, increments version and appends provenance. If new, creates it with version 1.",
299
- inputSchema: {
300
- slug: z.string().describe("Artifact slug (lowercase, hyphens only)"),
301
- title: z.string().optional().describe("Title (required for new artifacts)"),
302
- content: z.string().describe("Markdown body content"),
303
- tags: z.array(z.string()).optional().describe("Categorization tags"),
304
- confidence: z
305
- .number()
306
- .min(0)
307
- .max(1)
308
- .optional()
309
- .describe("Confidence score (0.0-1.0)"),
310
- message: z.string().optional().describe("Commit message for provenance"),
311
- },
312
- }, async ({ slug, title, content: bodyContent, tags, confidence, message }) => {
313
- const root = getWorkspaceRoot();
314
- const artifactsDir = join(root, ARTIFACTS_DIR);
315
- await mkdir(artifactsDir, { recursive: true });
316
- const filePath = join(artifactsDir, `${slug}.md`);
317
- const did = await getAgentDid(root);
318
- const now = new Date().toISOString();
319
- let fileData;
320
- let version;
321
- let isNew = false;
322
- try {
323
- const raw = await readFile(filePath, "utf-8");
324
- fileData = matter(raw);
325
- // Update existing
326
- fileData.data.version = (fileData.data.version || 1) + 1;
327
- version = fileData.data.version;
328
- fileData.data.lastModified = now;
329
- fileData.data.modifiedBy = did;
330
- fileData.content = `\n${bodyContent}\n`;
331
- if (confidence !== undefined)
332
- fileData.data.confidence = confidence;
333
- if (tags)
334
- fileData.data.tags = tags;
335
- if (title)
336
- fileData.data.title = title;
337
- // Add author if new
338
- if (!fileData.data.authors?.includes(did)) {
339
- if (!fileData.data.authors)
340
- fileData.data.authors = [];
341
- fileData.data.authors.push(did);
342
- }
343
- // Append provenance
344
- if (!fileData.data.provenance)
345
- fileData.data.provenance = [];
346
- fileData.data.provenance.push({
347
- agent: did,
348
- action: "updated",
349
- timestamp: now,
350
- message,
351
- confidence,
352
- });
353
- }
354
- catch {
355
- // Create new
356
- isNew = true;
357
- version = 1;
358
- const artifactTitle = title ||
359
- slug
360
- .split("-")
361
- .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
362
- .join(" ");
363
- fileData = {
364
- data: {
365
- awp: AWP_VERSION,
366
- smp: SMP_VERSION,
367
- type: "knowledge-artifact",
368
- id: `artifact:${slug}`,
369
- title: artifactTitle,
370
- authors: [did],
371
- version: 1,
372
- confidence,
373
- tags: tags?.length ? tags : undefined,
374
- created: now,
375
- lastModified: now,
376
- modifiedBy: did,
377
- provenance: [
378
- {
379
- agent: did,
380
- action: "created",
381
- timestamp: now,
382
- message,
383
- },
384
- ],
385
- },
386
- content: `\n${bodyContent}\n`,
387
- };
388
- }
389
- const output = matter.stringify(fileData.content, fileData.data);
390
- await writeFile(filePath, output, "utf-8");
391
- return {
392
- content: [
393
- {
394
- type: "text",
395
- text: `${isNew ? "Created" : "Updated"} artifacts/${slug}.md (version ${version})`,
396
- },
397
- ],
398
- };
399
- });
400
- // --- Tool: awp_artifact_list ---
401
- server.registerTool("awp_artifact_list", {
402
- title: "List Knowledge Artifacts",
403
- description: "List all knowledge artifacts in the workspace with metadata",
404
- inputSchema: {
405
- tag: z.string().optional().describe("Filter by tag"),
406
- },
407
- }, async ({ tag }) => {
408
- const root = getWorkspaceRoot();
409
- const artifactsDir = join(root, ARTIFACTS_DIR);
410
- let files;
411
- try {
412
- files = await readdir(artifactsDir);
413
- }
414
- catch {
415
- return {
416
- content: [
417
- { type: "text", text: JSON.stringify({ artifacts: [] }, null, 2) },
418
- ],
419
- };
420
- }
421
- const mdFiles = files.filter((f) => f.endsWith(".md")).sort();
422
- const artifacts = [];
423
- for (const f of mdFiles) {
424
- try {
425
- const raw = await readFile(join(artifactsDir, f), "utf-8");
426
- const { data } = matter(raw);
427
- if (data.type !== "knowledge-artifact")
428
- continue;
429
- if (tag && !data.tags?.some((t) => t.toLowerCase() === tag.toLowerCase())) {
430
- continue;
431
- }
432
- artifacts.push({
433
- slug: f.replace(/\.md$/, ""),
434
- title: data.title,
435
- version: data.version,
436
- confidence: data.confidence,
437
- tags: data.tags,
438
- authors: data.authors,
439
- lastModified: data.lastModified,
440
- });
441
- }
442
- catch {
443
- // Skip unparseable
444
- }
445
- }
446
- return {
447
- content: [
448
- {
449
- type: "text",
450
- text: JSON.stringify({ artifacts }, null, 2),
451
- },
452
- ],
453
- };
454
- });
455
- // --- Tool: awp_artifact_search ---
456
- server.registerTool("awp_artifact_search", {
457
- title: "Search Knowledge Artifacts",
458
- description: "Search artifacts by title, tags, or body content",
459
- inputSchema: {
460
- query: z.string().describe("Search query"),
461
- },
462
- }, async ({ query }) => {
463
- const root = getWorkspaceRoot();
464
- const artifactsDir = join(root, ARTIFACTS_DIR);
465
- const queryLower = query.toLowerCase();
466
- let files;
467
- try {
468
- files = await readdir(artifactsDir);
469
- }
470
- catch {
471
- return {
472
- content: [
473
- { type: "text", text: JSON.stringify({ results: [] }, null, 2) },
474
- ],
475
- };
476
- }
477
- const mdFiles = files.filter((f) => f.endsWith(".md")).sort();
478
- const results = [];
479
- for (const f of mdFiles) {
480
- try {
481
- const raw = await readFile(join(artifactsDir, f), "utf-8");
482
- const { data, content } = matter(raw);
483
- if (data.type !== "knowledge-artifact")
484
- continue;
485
- const titleMatch = data.title?.toLowerCase().includes(queryLower);
486
- const tagMatch = data.tags?.some((t) => t.toLowerCase().includes(queryLower));
487
- const bodyMatch = content.toLowerCase().includes(queryLower);
488
- if (titleMatch || tagMatch || bodyMatch) {
489
- results.push({
490
- slug: f.replace(/\.md$/, ""),
491
- title: data.title,
492
- version: data.version,
493
- confidence: data.confidence,
494
- tags: data.tags,
495
- matchedIn: [
496
- titleMatch && "title",
497
- tagMatch && "tags",
498
- bodyMatch && "body",
499
- ].filter(Boolean),
500
- });
501
- }
502
- }
503
- catch {
504
- // Skip
505
- }
506
- }
507
- return {
508
- content: [
509
- {
510
- type: "text",
511
- text: JSON.stringify({ results }, null, 2),
512
- },
513
- ],
514
- };
515
- });
516
- // --- Tool: awp_workspace_status ---
517
- server.registerTool("awp_workspace_status", {
518
- title: "Workspace Status",
519
- description: "Get AWP workspace health status — manifest info, file presence, memory stats, artifact count",
520
- inputSchema: {},
521
- }, async () => {
522
- const root = getWorkspaceRoot();
523
- const status = { root };
524
- // Manifest
525
- try {
526
- const manifestRaw = await readFile(join(root, ".awp", "workspace.json"), "utf-8");
527
- status.manifest = JSON.parse(manifestRaw);
528
- }
529
- catch {
530
- status.manifest = null;
531
- status.error = "No .awp/workspace.json found";
532
- }
533
- // File presence
534
- const fileChecks = [
535
- "IDENTITY.md",
536
- "SOUL.md",
537
- "AGENTS.md",
538
- "USER.md",
539
- "TOOLS.md",
540
- "HEARTBEAT.md",
541
- "MEMORY.md",
542
- ];
543
- status.files = {};
544
- for (const f of fileChecks) {
545
- status.files[f] = await fileExists(join(root, f));
546
- }
547
- // Memory stats
548
- try {
549
- const memDir = join(root, MEMORY_DIR);
550
- const files = await readdir(memDir);
551
- const mdFiles = files.filter((f) => f.endsWith(".md"));
552
- status.memory = {
553
- logCount: mdFiles.length,
554
- latest: mdFiles.sort().reverse()[0] || null,
555
- };
556
- }
557
- catch {
558
- status.memory = { logCount: 0, latest: null };
559
- }
560
- // Artifact stats
561
- try {
562
- const artDir = join(root, ARTIFACTS_DIR);
563
- const files = await readdir(artDir);
564
- const mdFiles = files.filter((f) => f.endsWith(".md"));
565
- status.artifacts = { count: mdFiles.length };
566
- }
567
- catch {
568
- status.artifacts = { count: 0 };
569
- }
570
- return {
571
- content: [
572
- { type: "text", text: JSON.stringify(status, null, 2) },
573
- ],
574
- };
575
- });
27
+ // Register all tool groups
28
+ registerIdentityTools(server);
29
+ registerMemoryTools(server);
30
+ registerArtifactTools(server);
31
+ registerStatusTools(server);
32
+ registerReputationTools(server);
33
+ registerContractTools(server);
34
+ registerProjectTools(server);
35
+ registerTaskTools(server);
36
+ registerConfigTools(server);
37
+ registerSwarmTools(server);
576
38
  // Start the server
577
39
  const transport = new StdioServerTransport();
578
40
  await server.connect(transport);