@artyfacts/mcp-server 1.0.1 → 1.0.3

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,536 @@
1
+ // src/server.ts
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import {
5
+ CallToolRequestSchema,
6
+ ListToolsRequestSchema
7
+ } from "@modelcontextprotocol/sdk/types.js";
8
+ var ARTYFACTS_TOOLS = [
9
+ // Organization tools
10
+ {
11
+ name: "get_organization",
12
+ description: "Get details about the current organization",
13
+ inputSchema: {
14
+ type: "object",
15
+ properties: {},
16
+ required: []
17
+ }
18
+ },
19
+ // Project tools
20
+ {
21
+ name: "list_projects",
22
+ description: "List all projects in the organization",
23
+ inputSchema: {
24
+ type: "object",
25
+ properties: {
26
+ limit: { type: "number", description: "Max results (default 50)" },
27
+ offset: { type: "number", description: "Pagination offset" }
28
+ },
29
+ required: []
30
+ }
31
+ },
32
+ {
33
+ name: "get_project",
34
+ description: "Get details about a specific project",
35
+ inputSchema: {
36
+ type: "object",
37
+ properties: {
38
+ project_id: { type: "string", description: "Project ID" }
39
+ },
40
+ required: ["project_id"]
41
+ }
42
+ },
43
+ // Artifact tools
44
+ {
45
+ name: "list_artifacts",
46
+ description: "List artifacts, optionally filtered by project",
47
+ inputSchema: {
48
+ type: "object",
49
+ properties: {
50
+ project_id: { type: "string", description: "Filter by project" },
51
+ type: { type: "string", description: "Filter by type (goal, spec, research, etc.)" },
52
+ status: { type: "string", description: "Filter by status" },
53
+ limit: { type: "number", description: "Max results" }
54
+ },
55
+ required: []
56
+ }
57
+ },
58
+ {
59
+ name: "get_artifact",
60
+ description: "Get a specific artifact by ID",
61
+ inputSchema: {
62
+ type: "object",
63
+ properties: {
64
+ artifact_id: { type: "string", description: "Artifact ID" }
65
+ },
66
+ required: ["artifact_id"]
67
+ }
68
+ },
69
+ {
70
+ name: "create_artifact",
71
+ description: "Create a new artifact",
72
+ inputSchema: {
73
+ type: "object",
74
+ properties: {
75
+ title: { type: "string", description: "Artifact title" },
76
+ type: { type: "string", description: "Type: goal, spec, research, report, experiment, decision" },
77
+ content: { type: "string", description: "Markdown content" },
78
+ project_id: { type: "string", description: "Project ID" },
79
+ parent_id: { type: "string", description: "Parent artifact ID" },
80
+ tags: { type: "array", items: { type: "string" }, description: "Tags" }
81
+ },
82
+ required: ["title"]
83
+ }
84
+ },
85
+ {
86
+ name: "update_artifact",
87
+ description: "Update an existing artifact",
88
+ inputSchema: {
89
+ type: "object",
90
+ properties: {
91
+ artifact_id: { type: "string", description: "Artifact ID" },
92
+ title: { type: "string", description: "New title" },
93
+ content: { type: "string", description: "New content" },
94
+ status: { type: "string", description: "New status" }
95
+ },
96
+ required: ["artifact_id"]
97
+ }
98
+ },
99
+ // Section tools
100
+ {
101
+ name: "list_sections",
102
+ description: "List sections of an artifact",
103
+ inputSchema: {
104
+ type: "object",
105
+ properties: {
106
+ artifact_id: { type: "string", description: "Artifact ID" }
107
+ },
108
+ required: ["artifact_id"]
109
+ }
110
+ },
111
+ {
112
+ name: "get_section",
113
+ description: "Get a specific section",
114
+ inputSchema: {
115
+ type: "object",
116
+ properties: {
117
+ artifact_id: { type: "string", description: "Artifact ID" },
118
+ section_id: { type: "string", description: "Section ID" }
119
+ },
120
+ required: ["artifact_id", "section_id"]
121
+ }
122
+ },
123
+ {
124
+ name: "create_section",
125
+ description: "Create a new section on an artifact",
126
+ inputSchema: {
127
+ type: "object",
128
+ properties: {
129
+ artifact_id: { type: "string", description: "Artifact ID" },
130
+ section_id: { type: "string", description: "Section identifier (slug)" },
131
+ heading: { type: "string", description: "Section heading" },
132
+ content: { type: "string", description: "Markdown content" },
133
+ type: { type: "string", description: "Type: content, task, decision, blocker" },
134
+ position: { type: "number", description: "Order position" }
135
+ },
136
+ required: ["artifact_id", "section_id", "heading"]
137
+ }
138
+ },
139
+ {
140
+ name: "update_section",
141
+ description: "Update an existing section",
142
+ inputSchema: {
143
+ type: "object",
144
+ properties: {
145
+ artifact_id: { type: "string", description: "Artifact ID" },
146
+ section_id: { type: "string", description: "Section ID" },
147
+ heading: { type: "string", description: "New heading" },
148
+ content: { type: "string", description: "New content" },
149
+ task_status: { type: "string", description: "Task status if type=task" }
150
+ },
151
+ required: ["artifact_id", "section_id"]
152
+ }
153
+ },
154
+ {
155
+ name: "delete_section",
156
+ description: "Delete a section",
157
+ inputSchema: {
158
+ type: "object",
159
+ properties: {
160
+ artifact_id: { type: "string", description: "Artifact ID" },
161
+ section_id: { type: "string", description: "Section ID" }
162
+ },
163
+ required: ["artifact_id", "section_id"]
164
+ }
165
+ },
166
+ // Task tools
167
+ {
168
+ name: "list_tasks",
169
+ description: "List tasks (sections with type=task)",
170
+ inputSchema: {
171
+ type: "object",
172
+ properties: {
173
+ artifact_id: { type: "string", description: "Filter by artifact" },
174
+ status: { type: "string", description: "Filter by status: pending, in_progress, done, blocked" },
175
+ assignee: { type: "string", description: "Filter by assignee agent" }
176
+ },
177
+ required: []
178
+ }
179
+ },
180
+ {
181
+ name: "claim_task",
182
+ description: "Claim a task for the current agent",
183
+ inputSchema: {
184
+ type: "object",
185
+ properties: {
186
+ task_id: { type: "string", description: "Task ID (section UUID)" }
187
+ },
188
+ required: ["task_id"]
189
+ }
190
+ },
191
+ {
192
+ name: "complete_task",
193
+ description: "Mark a task as complete",
194
+ inputSchema: {
195
+ type: "object",
196
+ properties: {
197
+ task_id: { type: "string", description: "Task ID" },
198
+ output_url: { type: "string", description: "URL to deliverable (PR, doc, etc.)" },
199
+ summary: { type: "string", description: "Completion summary" }
200
+ },
201
+ required: ["task_id"]
202
+ }
203
+ },
204
+ {
205
+ name: "block_task",
206
+ description: "Mark a task as blocked",
207
+ inputSchema: {
208
+ type: "object",
209
+ properties: {
210
+ task_id: { type: "string", description: "Task ID" },
211
+ reason: { type: "string", description: "Why it is blocked" },
212
+ blocker_type: { type: "string", description: "Type: decision, dependency, resource, external" }
213
+ },
214
+ required: ["task_id", "reason"]
215
+ }
216
+ },
217
+ // Agent tools
218
+ {
219
+ name: "list_agents",
220
+ description: "List all agents in the organization",
221
+ inputSchema: {
222
+ type: "object",
223
+ properties: {
224
+ status: { type: "string", description: "Filter by status: active, inactive" }
225
+ },
226
+ required: []
227
+ }
228
+ },
229
+ {
230
+ name: "get_agent",
231
+ description: "Get details about an agent",
232
+ inputSchema: {
233
+ type: "object",
234
+ properties: {
235
+ agent_id: { type: "string", description: "Agent ID" }
236
+ },
237
+ required: ["agent_id"]
238
+ }
239
+ },
240
+ {
241
+ name: "create_agent",
242
+ description: "Register a new agent",
243
+ inputSchema: {
244
+ type: "object",
245
+ properties: {
246
+ agentId: { type: "string", description: 'Unique agent ID (e.g., "engineering-agent", "qa-agent")' },
247
+ name: { type: "string", description: "Agent display name" },
248
+ type: { type: "string", description: "Type: pm, engineering, qa, research, content, design" },
249
+ description: { type: "string", description: "What this agent does" },
250
+ capabilities: { type: "array", items: { type: "string" }, description: "Agent capabilities" },
251
+ config: { type: "object", description: "Agent configuration" }
252
+ },
253
+ required: ["agentId", "name", "type"]
254
+ }
255
+ },
256
+ {
257
+ name: "update_agent",
258
+ description: "Update an agent",
259
+ inputSchema: {
260
+ type: "object",
261
+ properties: {
262
+ agent_id: { type: "string", description: "Agent ID" },
263
+ name: { type: "string", description: "New name" },
264
+ status: { type: "string", description: "New status" },
265
+ config: { type: "object", description: "Updated config" }
266
+ },
267
+ required: ["agent_id"]
268
+ }
269
+ },
270
+ // Blocker tools
271
+ {
272
+ name: "list_blockers",
273
+ description: "List blockers (decisions, dependencies needing resolution)",
274
+ inputSchema: {
275
+ type: "object",
276
+ properties: {
277
+ artifact_id: { type: "string", description: "Filter by artifact" },
278
+ status: { type: "string", description: "Filter by status: open, resolved" }
279
+ },
280
+ required: []
281
+ }
282
+ },
283
+ {
284
+ name: "create_blocker",
285
+ description: "Create a blocker (decision request, dependency, etc.)",
286
+ inputSchema: {
287
+ type: "object",
288
+ properties: {
289
+ artifact_id: { type: "string", description: "Artifact ID" },
290
+ kind: { type: "string", description: "Kind: decision, dependency, resource, external" },
291
+ title: { type: "string", description: "Blocker title" },
292
+ description: { type: "string", description: "Details" },
293
+ options: { type: "array", description: "Options for decisions" },
294
+ blocked_tasks: { type: "array", items: { type: "string" }, description: "Task IDs blocked by this" }
295
+ },
296
+ required: ["artifact_id", "kind", "title"]
297
+ }
298
+ },
299
+ {
300
+ name: "resolve_blocker",
301
+ description: "Resolve a blocker",
302
+ inputSchema: {
303
+ type: "object",
304
+ properties: {
305
+ blocker_id: { type: "string", description: "Blocker ID" },
306
+ resolution: { type: "string", description: "How it was resolved" },
307
+ selected_option: { type: "string", description: "Selected option (for decisions)" }
308
+ },
309
+ required: ["blocker_id", "resolution"]
310
+ }
311
+ },
312
+ // Search tools
313
+ {
314
+ name: "search_artifacts",
315
+ description: "Search artifacts by text query",
316
+ inputSchema: {
317
+ type: "object",
318
+ properties: {
319
+ query: { type: "string", description: "Search query" },
320
+ type: { type: "string", description: "Filter by type" },
321
+ limit: { type: "number", description: "Max results" }
322
+ },
323
+ required: ["query"]
324
+ }
325
+ },
326
+ // Context tools
327
+ {
328
+ name: "get_task_context",
329
+ description: "Get full context for a task (org, project, artifact, related sections)",
330
+ inputSchema: {
331
+ type: "object",
332
+ properties: {
333
+ task_id: { type: "string", description: "Task ID" }
334
+ },
335
+ required: ["task_id"]
336
+ }
337
+ }
338
+ ];
339
+ var ArtyfactsApiClient = class {
340
+ constructor(baseUrl, apiKey) {
341
+ this.baseUrl = baseUrl;
342
+ this.apiKey = apiKey;
343
+ }
344
+ async request(method, path, body) {
345
+ const url = `${this.baseUrl}${path}`;
346
+ const response = await fetch(url, {
347
+ method,
348
+ headers: {
349
+ "Authorization": `Bearer ${this.apiKey}`,
350
+ "Content-Type": "application/json"
351
+ },
352
+ body: body ? JSON.stringify(body) : void 0
353
+ });
354
+ if (!response.ok) {
355
+ const error = await response.json().catch(() => ({ error: "Request failed" }));
356
+ throw new Error(error.error || `HTTP ${response.status}: ${response.statusText}`);
357
+ }
358
+ return response.json();
359
+ }
360
+ get(path) {
361
+ return this.request("GET", path);
362
+ }
363
+ post(path, body) {
364
+ return this.request("POST", path, body);
365
+ }
366
+ patch(path, body) {
367
+ return this.request("PATCH", path, body);
368
+ }
369
+ delete(path) {
370
+ return this.request("DELETE", path);
371
+ }
372
+ };
373
+ var toolHandlers = {
374
+ // Organization
375
+ get_organization: (client) => client.get("/org"),
376
+ // Projects
377
+ list_projects: (client, args) => {
378
+ const params = new URLSearchParams();
379
+ if (args.limit) params.set("limit", String(args.limit));
380
+ if (args.offset) params.set("offset", String(args.offset));
381
+ return client.get(`/projects?${params}`);
382
+ },
383
+ get_project: (client, args) => client.get(`/projects/${args.project_id}`),
384
+ // Artifacts
385
+ list_artifacts: (client, args) => {
386
+ const params = new URLSearchParams();
387
+ if (args.project_id) params.set("project_id", String(args.project_id));
388
+ if (args.type) params.set("type", String(args.type));
389
+ if (args.status) params.set("status", String(args.status));
390
+ if (args.limit) params.set("limit", String(args.limit));
391
+ return client.get(`/artifacts?${params}`);
392
+ },
393
+ get_artifact: (client, args) => client.get(`/artifacts/${args.artifact_id}`),
394
+ create_artifact: (client, args) => client.post("/artifacts", args),
395
+ update_artifact: (client, args) => {
396
+ const { artifact_id, ...body } = args;
397
+ return client.patch(`/artifacts/${artifact_id}`, body);
398
+ },
399
+ // Sections
400
+ list_sections: (client, args) => client.get(`/artifacts/${args.artifact_id}/sections`),
401
+ get_section: (client, args) => client.get(`/artifacts/${args.artifact_id}/sections/${args.section_id}`),
402
+ create_section: (client, args) => {
403
+ const { artifact_id, ...body } = args;
404
+ return client.post(`/artifacts/${artifact_id}/sections`, body);
405
+ },
406
+ update_section: (client, args) => {
407
+ const { artifact_id, section_id, ...body } = args;
408
+ return client.patch(`/artifacts/${artifact_id}/sections/${section_id}`, body);
409
+ },
410
+ delete_section: (client, args) => client.delete(`/artifacts/${args.artifact_id}/sections/${args.section_id}`),
411
+ // Tasks
412
+ list_tasks: (client, args) => {
413
+ const params = new URLSearchParams();
414
+ if (args.artifact_id) params.set("artifact_id", String(args.artifact_id));
415
+ if (args.status) params.set("status", String(args.status));
416
+ if (args.assignee) params.set("assignee", String(args.assignee));
417
+ return client.get(`/tasks?${params}`);
418
+ },
419
+ claim_task: (client, args) => client.post(`/tasks/${args.task_id}/claim`),
420
+ complete_task: (client, args) => {
421
+ const { task_id, ...body } = args;
422
+ return client.post(`/tasks/${task_id}/complete`, body);
423
+ },
424
+ block_task: (client, args) => {
425
+ const { task_id, ...body } = args;
426
+ return client.post(`/tasks/${task_id}/block`, body);
427
+ },
428
+ // Agents
429
+ list_agents: (client, args) => {
430
+ const params = new URLSearchParams();
431
+ if (args.status) params.set("status", String(args.status));
432
+ return client.get(`/agents?${params}`);
433
+ },
434
+ get_agent: (client, args) => client.get(`/agents/${args.agent_id}`),
435
+ create_agent: (client, args) => client.post("/agents", args),
436
+ update_agent: (client, args) => {
437
+ const { agent_id, ...body } = args;
438
+ return client.patch(`/agents/${agent_id}`, body);
439
+ },
440
+ // Blockers
441
+ list_blockers: (client, args) => {
442
+ const params = new URLSearchParams();
443
+ if (args.artifact_id) params.set("artifact_id", String(args.artifact_id));
444
+ if (args.status) params.set("status", String(args.status));
445
+ return client.get(`/blockers?${params}`);
446
+ },
447
+ create_blocker: (client, args) => {
448
+ const { artifact_id, ...body } = args;
449
+ return client.post(`/artifacts/${artifact_id}/blockers`, body);
450
+ },
451
+ resolve_blocker: (client, args) => {
452
+ const { blocker_id, ...body } = args;
453
+ return client.post(`/blockers/${blocker_id}/resolve`, body);
454
+ },
455
+ // Search
456
+ search_artifacts: (client, args) => {
457
+ const params = new URLSearchParams();
458
+ params.set("q", String(args.query));
459
+ if (args.type) params.set("type", String(args.type));
460
+ if (args.limit) params.set("limit", String(args.limit));
461
+ return client.get(`/search?${params}`);
462
+ },
463
+ // Context
464
+ get_task_context: (client, args) => client.get(`/tasks/${args.task_id}/context`)
465
+ };
466
+ var ArtyfactsMcpServer = class {
467
+ server;
468
+ client;
469
+ config;
470
+ constructor(config) {
471
+ this.config = config;
472
+ this.client = new ArtyfactsApiClient(
473
+ config.baseUrl || "https://artyfacts.dev/api/v1",
474
+ config.apiKey
475
+ );
476
+ this.server = new Server(
477
+ {
478
+ name: config.name || "artyfacts-mcp",
479
+ version: config.version || "1.0.0"
480
+ },
481
+ {
482
+ capabilities: {
483
+ tools: {}
484
+ }
485
+ }
486
+ );
487
+ this.setupHandlers();
488
+ }
489
+ setupHandlers() {
490
+ this.server.setRequestHandler(ListToolsRequestSchema, async () => {
491
+ return { tools: ARTYFACTS_TOOLS };
492
+ });
493
+ this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
494
+ const { name, arguments: args } = request.params;
495
+ const handler = toolHandlers[name];
496
+ if (!handler) {
497
+ return {
498
+ content: [{ type: "text", text: `Unknown tool: ${name}` }],
499
+ isError: true
500
+ };
501
+ }
502
+ try {
503
+ const result = await handler(this.client, args || {});
504
+ return {
505
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
506
+ };
507
+ } catch (error) {
508
+ const message = error instanceof Error ? error.message : String(error);
509
+ return {
510
+ content: [{ type: "text", text: `Error: ${message}` }],
511
+ isError: true
512
+ };
513
+ }
514
+ });
515
+ }
516
+ async start() {
517
+ const transport = new StdioServerTransport();
518
+ await this.server.connect(transport);
519
+ console.error(`Artyfacts MCP server running (${ARTYFACTS_TOOLS.length} tools)`);
520
+ }
521
+ getServer() {
522
+ return this.server;
523
+ }
524
+ };
525
+ function createMcpServer(config) {
526
+ return new ArtyfactsMcpServer(config);
527
+ }
528
+ async function startServer(server) {
529
+ await server.start();
530
+ }
531
+
532
+ export {
533
+ ArtyfactsMcpServer,
534
+ createMcpServer,
535
+ startServer
536
+ };
@@ -0,0 +1,556 @@
1
+ // src/server.ts
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import {
5
+ CallToolRequestSchema,
6
+ ListToolsRequestSchema
7
+ } from "@modelcontextprotocol/sdk/types.js";
8
+ var ARTYFACTS_TOOLS = [
9
+ // Organization tools
10
+ {
11
+ name: "get_organization",
12
+ description: "Get details about the current organization",
13
+ inputSchema: {
14
+ type: "object",
15
+ properties: {},
16
+ required: []
17
+ }
18
+ },
19
+ // Project tools
20
+ {
21
+ name: "list_projects",
22
+ description: "List all projects in the organization",
23
+ inputSchema: {
24
+ type: "object",
25
+ properties: {
26
+ limit: { type: "number", description: "Max results (default 50)" },
27
+ offset: { type: "number", description: "Pagination offset" }
28
+ },
29
+ required: []
30
+ }
31
+ },
32
+ {
33
+ name: "get_project",
34
+ description: "Get details about a specific project",
35
+ inputSchema: {
36
+ type: "object",
37
+ properties: {
38
+ project_id: { type: "string", description: "Project ID" }
39
+ },
40
+ required: ["project_id"]
41
+ }
42
+ },
43
+ // Artifact tools
44
+ {
45
+ name: "list_artifacts",
46
+ description: "List artifacts, optionally filtered by project",
47
+ inputSchema: {
48
+ type: "object",
49
+ properties: {
50
+ project_id: { type: "string", description: "Filter by project" },
51
+ type: { type: "string", description: "Filter by type (goal, spec, research, etc.)" },
52
+ status: { type: "string", description: "Filter by status" },
53
+ limit: { type: "number", description: "Max results" }
54
+ },
55
+ required: []
56
+ }
57
+ },
58
+ {
59
+ name: "get_artifact",
60
+ description: "Get a specific artifact by ID",
61
+ inputSchema: {
62
+ type: "object",
63
+ properties: {
64
+ artifact_id: { type: "string", description: "Artifact ID" }
65
+ },
66
+ required: ["artifact_id"]
67
+ }
68
+ },
69
+ {
70
+ name: "create_artifact",
71
+ description: "Create a new artifact (document, goal, spec, etc.)",
72
+ inputSchema: {
73
+ type: "object",
74
+ properties: {
75
+ title: { type: "string", description: "Artifact title" },
76
+ type: { type: "string", description: "Artifact type: goal, spec, research, report, experiment, decision, doc" },
77
+ content: { type: "string", description: "Markdown content" },
78
+ parent_id: { type: "string", description: "Parent artifact ID for nested artifacts" },
79
+ tags: { type: "array", items: { type: "string" }, description: "Tags for categorization" }
80
+ },
81
+ required: ["title", "type"]
82
+ }
83
+ },
84
+ {
85
+ name: "update_artifact",
86
+ description: "Update an existing artifact",
87
+ inputSchema: {
88
+ type: "object",
89
+ properties: {
90
+ artifact_id: { type: "string", description: "Artifact ID" },
91
+ title: { type: "string", description: "New title" },
92
+ content: { type: "string", description: "New content" },
93
+ status: { type: "string", description: "New status" }
94
+ },
95
+ required: ["artifact_id"]
96
+ }
97
+ },
98
+ // Section tools
99
+ {
100
+ name: "list_sections",
101
+ description: "List sections of an artifact",
102
+ inputSchema: {
103
+ type: "object",
104
+ properties: {
105
+ artifact_id: { type: "string", description: "Artifact ID" }
106
+ },
107
+ required: ["artifact_id"]
108
+ }
109
+ },
110
+ {
111
+ name: "get_section",
112
+ description: "Get a specific section",
113
+ inputSchema: {
114
+ type: "object",
115
+ properties: {
116
+ artifact_id: { type: "string", description: "Artifact ID" },
117
+ section_id: { type: "string", description: "Section ID" }
118
+ },
119
+ required: ["artifact_id", "section_id"]
120
+ }
121
+ },
122
+ {
123
+ name: "create_section",
124
+ description: "Create a new section on an artifact",
125
+ inputSchema: {
126
+ type: "object",
127
+ properties: {
128
+ artifact_id: { type: "string", description: "Artifact ID" },
129
+ section_id: { type: "string", description: "Section identifier (slug)" },
130
+ heading: { type: "string", description: "Section heading" },
131
+ content: { type: "string", description: "Markdown content" },
132
+ type: { type: "string", description: "Type: content, task, decision, blocker" },
133
+ position: { type: "number", description: "Order position" }
134
+ },
135
+ required: ["artifact_id", "section_id", "heading", "content"]
136
+ }
137
+ },
138
+ {
139
+ name: "update_section",
140
+ description: "Update an existing section",
141
+ inputSchema: {
142
+ type: "object",
143
+ properties: {
144
+ artifact_id: { type: "string", description: "Artifact ID" },
145
+ section_id: { type: "string", description: "Section ID" },
146
+ heading: { type: "string", description: "New heading" },
147
+ content: { type: "string", description: "New content" },
148
+ task_status: { type: "string", description: "Task status if type=task" }
149
+ },
150
+ required: ["artifact_id", "section_id"]
151
+ }
152
+ },
153
+ {
154
+ name: "delete_section",
155
+ description: "Delete a section",
156
+ inputSchema: {
157
+ type: "object",
158
+ properties: {
159
+ artifact_id: { type: "string", description: "Artifact ID" },
160
+ section_id: { type: "string", description: "Section ID" }
161
+ },
162
+ required: ["artifact_id", "section_id"]
163
+ }
164
+ },
165
+ // Task tools
166
+ {
167
+ name: "list_tasks",
168
+ description: "List tasks (sections with type=task)",
169
+ inputSchema: {
170
+ type: "object",
171
+ properties: {
172
+ artifact_id: { type: "string", description: "Filter by artifact" },
173
+ status: { type: "string", description: "Filter by status: pending, in_progress, done, blocked" },
174
+ assignee: { type: "string", description: "Filter by assignee agent" }
175
+ },
176
+ required: []
177
+ }
178
+ },
179
+ {
180
+ name: "claim_task",
181
+ description: "Claim a task for the current agent",
182
+ inputSchema: {
183
+ type: "object",
184
+ properties: {
185
+ task_id: { type: "string", description: "Task ID (section UUID)" }
186
+ },
187
+ required: ["task_id"]
188
+ }
189
+ },
190
+ {
191
+ name: "complete_task",
192
+ description: "Mark a task as complete",
193
+ inputSchema: {
194
+ type: "object",
195
+ properties: {
196
+ task_id: { type: "string", description: "Task ID" },
197
+ output_url: { type: "string", description: "URL to deliverable (PR, doc, etc.)" },
198
+ summary: { type: "string", description: "Completion summary" }
199
+ },
200
+ required: ["task_id"]
201
+ }
202
+ },
203
+ {
204
+ name: "block_task",
205
+ description: "Mark a task as blocked",
206
+ inputSchema: {
207
+ type: "object",
208
+ properties: {
209
+ task_id: { type: "string", description: "Task ID" },
210
+ reason: { type: "string", description: "Why it is blocked" },
211
+ blocker_type: { type: "string", description: "Type: decision, dependency, resource, external" }
212
+ },
213
+ required: ["task_id", "reason"]
214
+ }
215
+ },
216
+ // Agent tools
217
+ {
218
+ name: "list_agents",
219
+ description: "List all agents in the organization",
220
+ inputSchema: {
221
+ type: "object",
222
+ properties: {
223
+ status: { type: "string", description: "Filter by status: active, inactive" }
224
+ },
225
+ required: []
226
+ }
227
+ },
228
+ {
229
+ name: "get_agent",
230
+ description: "Get details about an agent",
231
+ inputSchema: {
232
+ type: "object",
233
+ properties: {
234
+ agent_id: { type: "string", description: "Agent ID" }
235
+ },
236
+ required: ["agent_id"]
237
+ }
238
+ },
239
+ {
240
+ name: "create_agent",
241
+ description: "Register a new agent",
242
+ inputSchema: {
243
+ type: "object",
244
+ properties: {
245
+ agentId: { type: "string", description: 'Unique agent ID (e.g., "engineering-agent", "qa-agent")' },
246
+ name: { type: "string", description: "Agent display name" },
247
+ type: { type: "string", description: "Type: pm, engineering, qa, research, content, design" },
248
+ description: { type: "string", description: "What this agent does" },
249
+ capabilities: { type: "array", items: { type: "string" }, description: "Agent capabilities" },
250
+ config: { type: "object", description: "Agent configuration" }
251
+ },
252
+ required: ["agentId", "name", "type"]
253
+ }
254
+ },
255
+ {
256
+ name: "update_agent",
257
+ description: "Update an agent",
258
+ inputSchema: {
259
+ type: "object",
260
+ properties: {
261
+ agent_id: { type: "string", description: "Agent ID" },
262
+ name: { type: "string", description: "New name" },
263
+ status: { type: "string", description: "New status" },
264
+ config: { type: "object", description: "Updated config" }
265
+ },
266
+ required: ["agent_id"]
267
+ }
268
+ },
269
+ // Blocker tools
270
+ {
271
+ name: "list_blockers",
272
+ description: "List blockers (decisions, dependencies needing resolution)",
273
+ inputSchema: {
274
+ type: "object",
275
+ properties: {
276
+ artifact_id: { type: "string", description: "Filter by artifact" },
277
+ status: { type: "string", description: "Filter by status: open, resolved" }
278
+ },
279
+ required: []
280
+ }
281
+ },
282
+ {
283
+ name: "create_blocker",
284
+ description: "Create a blocker (decision request, dependency, etc.)",
285
+ inputSchema: {
286
+ type: "object",
287
+ properties: {
288
+ artifact_id: { type: "string", description: "Artifact ID" },
289
+ kind: { type: "string", description: "Kind: decision, dependency, resource, external" },
290
+ title: { type: "string", description: "Blocker title" },
291
+ description: { type: "string", description: "Details" },
292
+ options: { type: "array", description: "Options for decisions" },
293
+ blocked_tasks: { type: "array", items: { type: "string" }, description: "Task IDs blocked by this" }
294
+ },
295
+ required: ["artifact_id", "kind", "title"]
296
+ }
297
+ },
298
+ {
299
+ name: "resolve_blocker",
300
+ description: "Resolve a blocker",
301
+ inputSchema: {
302
+ type: "object",
303
+ properties: {
304
+ blocker_id: { type: "string", description: "Blocker ID" },
305
+ resolution: { type: "string", description: "How it was resolved" },
306
+ selected_option: { type: "string", description: "Selected option (for decisions)" }
307
+ },
308
+ required: ["blocker_id", "resolution"]
309
+ }
310
+ },
311
+ // Search tools
312
+ {
313
+ name: "search_artifacts",
314
+ description: "Search artifacts by text query",
315
+ inputSchema: {
316
+ type: "object",
317
+ properties: {
318
+ query: { type: "string", description: "Search query" },
319
+ type: { type: "string", description: "Filter by type" },
320
+ limit: { type: "number", description: "Max results" }
321
+ },
322
+ required: ["query"]
323
+ }
324
+ },
325
+ // Context tools
326
+ {
327
+ name: "get_task_context",
328
+ description: "Get full context for a task (org, project, artifact, related sections)",
329
+ inputSchema: {
330
+ type: "object",
331
+ properties: {
332
+ task_id: { type: "string", description: "Task ID" }
333
+ },
334
+ required: ["task_id"]
335
+ }
336
+ }
337
+ ];
338
+ var ArtyfactsApiClient = class {
339
+ constructor(baseUrl, apiKey) {
340
+ this.baseUrl = baseUrl;
341
+ this.apiKey = apiKey;
342
+ }
343
+ async request(method, path, body) {
344
+ const url = `${this.baseUrl}${path}`;
345
+ const response = await fetch(url, {
346
+ method,
347
+ headers: {
348
+ "Authorization": `Bearer ${this.apiKey}`,
349
+ "Content-Type": "application/json"
350
+ },
351
+ body: body ? JSON.stringify(body) : void 0
352
+ });
353
+ if (!response.ok) {
354
+ const error = await response.json().catch(() => ({ error: "Request failed" }));
355
+ throw new Error(error.error || `HTTP ${response.status}: ${response.statusText}`);
356
+ }
357
+ return response.json();
358
+ }
359
+ get(path) {
360
+ return this.request("GET", path);
361
+ }
362
+ post(path, body) {
363
+ return this.request("POST", path, body);
364
+ }
365
+ patch(path, body) {
366
+ return this.request("PATCH", path, body);
367
+ }
368
+ delete(path) {
369
+ return this.request("DELETE", path);
370
+ }
371
+ };
372
+ var toolHandlers = {
373
+ // Organization
374
+ get_organization: (client) => client.get("/org"),
375
+ // Projects
376
+ list_projects: (client, args) => {
377
+ const params = new URLSearchParams();
378
+ if (args.limit) params.set("limit", String(args.limit));
379
+ if (args.offset) params.set("offset", String(args.offset));
380
+ return client.get(`/projects?${params}`);
381
+ },
382
+ get_project: (client, args) => client.get(`/projects/${args.project_id}`),
383
+ // Artifacts
384
+ list_artifacts: (client, args) => {
385
+ const params = new URLSearchParams();
386
+ if (args.project_id) params.set("project_id", String(args.project_id));
387
+ if (args.type) params.set("type", String(args.type));
388
+ if (args.status) params.set("status", String(args.status));
389
+ if (args.limit) params.set("limit", String(args.limit));
390
+ return client.get(`/artifacts?${params}`);
391
+ },
392
+ get_artifact: (client, args) => client.get(`/artifacts/${args.artifact_id}`),
393
+ create_artifact: (client, args) => {
394
+ const envelope = {
395
+ aah_version: "0.3",
396
+ artifact: {
397
+ id: args.id || `artifact-${Date.now()}`,
398
+ title: args.title,
399
+ type: args.type || "document/sectioned",
400
+ artifact_type: args.artifact_type || args.type || "doc",
401
+ parent_id: args.parent_id,
402
+ tags: args.tags
403
+ },
404
+ content: args.content ? {
405
+ media_type: "text/markdown",
406
+ body: args.content
407
+ } : void 0,
408
+ source: {
409
+ agent_id: "mcp-agent"
410
+ }
411
+ };
412
+ return client.post("/artifacts", envelope);
413
+ },
414
+ update_artifact: (client, args) => {
415
+ const { artifact_id, ...body } = args;
416
+ return client.patch(`/artifacts/${artifact_id}`, body);
417
+ },
418
+ // Sections
419
+ list_sections: (client, args) => client.get(`/artifacts/${args.artifact_id}/sections`),
420
+ get_section: (client, args) => client.get(`/artifacts/${args.artifact_id}/sections/${args.section_id}`),
421
+ create_section: (client, args) => {
422
+ const { artifact_id, section_id, ...rest } = args;
423
+ const body = { id: section_id, ...rest };
424
+ return client.post(`/artifacts/${artifact_id}/sections`, body);
425
+ },
426
+ update_section: (client, args) => {
427
+ const { artifact_id, section_id, ...body } = args;
428
+ return client.patch(`/artifacts/${artifact_id}/sections/${section_id}`, body);
429
+ },
430
+ delete_section: (client, args) => client.delete(`/artifacts/${args.artifact_id}/sections/${args.section_id}`),
431
+ // Tasks
432
+ list_tasks: (client, args) => {
433
+ const params = new URLSearchParams();
434
+ if (args.artifact_id) params.set("artifact_id", String(args.artifact_id));
435
+ if (args.status) params.set("status", String(args.status));
436
+ if (args.assignee) params.set("assignee", String(args.assignee));
437
+ return client.get(`/tasks?${params}`);
438
+ },
439
+ claim_task: (client, args) => client.post(`/tasks/${args.task_id}/claim`),
440
+ complete_task: (client, args) => {
441
+ const { task_id, ...body } = args;
442
+ return client.post(`/tasks/${task_id}/complete`, body);
443
+ },
444
+ block_task: (client, args) => {
445
+ const { task_id, ...body } = args;
446
+ return client.post(`/tasks/${task_id}/block`, body);
447
+ },
448
+ // Agents
449
+ list_agents: (client, args) => {
450
+ const params = new URLSearchParams();
451
+ if (args.status) params.set("status", String(args.status));
452
+ return client.get(`/agents?${params}`);
453
+ },
454
+ get_agent: (client, args) => client.get(`/agents/${args.agent_id}`),
455
+ create_agent: (client, args) => client.post("/agents", args),
456
+ update_agent: (client, args) => {
457
+ const { agent_id, ...body } = args;
458
+ return client.patch(`/agents/${agent_id}`, body);
459
+ },
460
+ // Blockers
461
+ list_blockers: (client, args) => {
462
+ const params = new URLSearchParams();
463
+ if (args.artifact_id) params.set("artifact_id", String(args.artifact_id));
464
+ if (args.status) params.set("status", String(args.status));
465
+ return client.get(`/blockers?${params}`);
466
+ },
467
+ create_blocker: (client, args) => {
468
+ const { artifact_id, ...body } = args;
469
+ return client.post(`/artifacts/${artifact_id}/blockers`, body);
470
+ },
471
+ resolve_blocker: (client, args) => {
472
+ const { blocker_id, ...body } = args;
473
+ return client.post(`/blockers/${blocker_id}/resolve`, body);
474
+ },
475
+ // Search
476
+ search_artifacts: (client, args) => {
477
+ const params = new URLSearchParams();
478
+ params.set("q", String(args.query));
479
+ if (args.type) params.set("type", String(args.type));
480
+ if (args.limit) params.set("limit", String(args.limit));
481
+ return client.get(`/search?${params}`);
482
+ },
483
+ // Context
484
+ get_task_context: (client, args) => client.get(`/tasks/${args.task_id}/context`)
485
+ };
486
+ var ArtyfactsMcpServer = class {
487
+ server;
488
+ client;
489
+ config;
490
+ constructor(config) {
491
+ this.config = config;
492
+ this.client = new ArtyfactsApiClient(
493
+ config.baseUrl || "https://artyfacts.dev/api/v1",
494
+ config.apiKey
495
+ );
496
+ this.server = new Server(
497
+ {
498
+ name: config.name || "artyfacts-mcp",
499
+ version: config.version || "1.0.0"
500
+ },
501
+ {
502
+ capabilities: {
503
+ tools: {}
504
+ }
505
+ }
506
+ );
507
+ this.setupHandlers();
508
+ }
509
+ setupHandlers() {
510
+ this.server.setRequestHandler(ListToolsRequestSchema, async () => {
511
+ return { tools: ARTYFACTS_TOOLS };
512
+ });
513
+ this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
514
+ const { name, arguments: args } = request.params;
515
+ const handler = toolHandlers[name];
516
+ if (!handler) {
517
+ return {
518
+ content: [{ type: "text", text: `Unknown tool: ${name}` }],
519
+ isError: true
520
+ };
521
+ }
522
+ try {
523
+ const result = await handler(this.client, args || {});
524
+ return {
525
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
526
+ };
527
+ } catch (error) {
528
+ const message = error instanceof Error ? error.message : String(error);
529
+ return {
530
+ content: [{ type: "text", text: `Error: ${message}` }],
531
+ isError: true
532
+ };
533
+ }
534
+ });
535
+ }
536
+ async start() {
537
+ const transport = new StdioServerTransport();
538
+ await this.server.connect(transport);
539
+ console.error(`Artyfacts MCP server running (${ARTYFACTS_TOOLS.length} tools)`);
540
+ }
541
+ getServer() {
542
+ return this.server;
543
+ }
544
+ };
545
+ function createMcpServer(config) {
546
+ return new ArtyfactsMcpServer(config);
547
+ }
548
+ async function startServer(server) {
549
+ await server.start();
550
+ }
551
+
552
+ export {
553
+ ArtyfactsMcpServer,
554
+ createMcpServer,
555
+ startServer
556
+ };
package/dist/index.cjs CHANGED
@@ -93,18 +93,17 @@ var ARTYFACTS_TOOLS = [
93
93
  },
94
94
  {
95
95
  name: "create_artifact",
96
- description: "Create a new artifact",
96
+ description: "Create a new artifact (document, goal, spec, etc.)",
97
97
  inputSchema: {
98
98
  type: "object",
99
99
  properties: {
100
100
  title: { type: "string", description: "Artifact title" },
101
- type: { type: "string", description: "Type: goal, spec, research, report, experiment, decision" },
101
+ type: { type: "string", description: "Artifact type: goal, spec, research, report, experiment, decision, doc" },
102
102
  content: { type: "string", description: "Markdown content" },
103
- project_id: { type: "string", description: "Project ID" },
104
- parent_id: { type: "string", description: "Parent artifact ID" },
105
- tags: { type: "array", items: { type: "string" }, description: "Tags" }
103
+ parent_id: { type: "string", description: "Parent artifact ID for nested artifacts" },
104
+ tags: { type: "array", items: { type: "string" }, description: "Tags for categorization" }
106
105
  },
107
- required: ["title"]
106
+ required: ["title", "type"]
108
107
  }
109
108
  },
110
109
  {
@@ -158,7 +157,7 @@ var ARTYFACTS_TOOLS = [
158
157
  type: { type: "string", description: "Type: content, task, decision, blocker" },
159
158
  position: { type: "number", description: "Order position" }
160
159
  },
161
- required: ["artifact_id", "section_id", "heading"]
160
+ required: ["artifact_id", "section_id", "heading", "content"]
162
161
  }
163
162
  },
164
163
  {
@@ -268,13 +267,14 @@ var ARTYFACTS_TOOLS = [
268
267
  inputSchema: {
269
268
  type: "object",
270
269
  properties: {
270
+ agentId: { type: "string", description: 'Unique agent ID (e.g., "engineering-agent", "qa-agent")' },
271
271
  name: { type: "string", description: "Agent display name" },
272
272
  type: { type: "string", description: "Type: pm, engineering, qa, research, content, design" },
273
273
  description: { type: "string", description: "What this agent does" },
274
274
  capabilities: { type: "array", items: { type: "string" }, description: "Agent capabilities" },
275
275
  config: { type: "object", description: "Agent configuration" }
276
276
  },
277
- required: ["name", "type"]
277
+ required: ["agentId", "name", "type"]
278
278
  }
279
279
  },
280
280
  {
@@ -415,7 +415,27 @@ var toolHandlers = {
415
415
  return client.get(`/artifacts?${params}`);
416
416
  },
417
417
  get_artifact: (client, args) => client.get(`/artifacts/${args.artifact_id}`),
418
- create_artifact: (client, args) => client.post("/artifacts", args),
418
+ create_artifact: (client, args) => {
419
+ const envelope = {
420
+ aah_version: "0.3",
421
+ artifact: {
422
+ id: args.id || `artifact-${Date.now()}`,
423
+ title: args.title,
424
+ type: args.type || "document/sectioned",
425
+ artifact_type: args.artifact_type || args.type || "doc",
426
+ parent_id: args.parent_id,
427
+ tags: args.tags
428
+ },
429
+ content: args.content ? {
430
+ media_type: "text/markdown",
431
+ body: args.content
432
+ } : void 0,
433
+ source: {
434
+ agent_id: "mcp-agent"
435
+ }
436
+ };
437
+ return client.post("/artifacts", envelope);
438
+ },
419
439
  update_artifact: (client, args) => {
420
440
  const { artifact_id, ...body } = args;
421
441
  return client.patch(`/artifacts/${artifact_id}`, body);
@@ -424,7 +444,8 @@ var toolHandlers = {
424
444
  list_sections: (client, args) => client.get(`/artifacts/${args.artifact_id}/sections`),
425
445
  get_section: (client, args) => client.get(`/artifacts/${args.artifact_id}/sections/${args.section_id}`),
426
446
  create_section: (client, args) => {
427
- const { artifact_id, ...body } = args;
447
+ const { artifact_id, section_id, ...rest } = args;
448
+ const body = { id: section_id, ...rest };
428
449
  return client.post(`/artifacts/${artifact_id}/sections`, body);
429
450
  },
430
451
  update_section: (client, args) => {
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  ArtyfactsMcpServer,
3
3
  createMcpServer,
4
4
  startServer
5
- } from "./chunk-ZGKINVWK.js";
5
+ } from "./chunk-VCIOVYRM.js";
6
6
  export {
7
7
  ArtyfactsMcpServer,
8
8
  createMcpServer,
package/dist/server.cjs CHANGED
@@ -91,18 +91,17 @@ var ARTYFACTS_TOOLS = [
91
91
  },
92
92
  {
93
93
  name: "create_artifact",
94
- description: "Create a new artifact",
94
+ description: "Create a new artifact (document, goal, spec, etc.)",
95
95
  inputSchema: {
96
96
  type: "object",
97
97
  properties: {
98
98
  title: { type: "string", description: "Artifact title" },
99
- type: { type: "string", description: "Type: goal, spec, research, report, experiment, decision" },
99
+ type: { type: "string", description: "Artifact type: goal, spec, research, report, experiment, decision, doc" },
100
100
  content: { type: "string", description: "Markdown content" },
101
- project_id: { type: "string", description: "Project ID" },
102
- parent_id: { type: "string", description: "Parent artifact ID" },
103
- tags: { type: "array", items: { type: "string" }, description: "Tags" }
101
+ parent_id: { type: "string", description: "Parent artifact ID for nested artifacts" },
102
+ tags: { type: "array", items: { type: "string" }, description: "Tags for categorization" }
104
103
  },
105
- required: ["title"]
104
+ required: ["title", "type"]
106
105
  }
107
106
  },
108
107
  {
@@ -156,7 +155,7 @@ var ARTYFACTS_TOOLS = [
156
155
  type: { type: "string", description: "Type: content, task, decision, blocker" },
157
156
  position: { type: "number", description: "Order position" }
158
157
  },
159
- required: ["artifact_id", "section_id", "heading"]
158
+ required: ["artifact_id", "section_id", "heading", "content"]
160
159
  }
161
160
  },
162
161
  {
@@ -266,13 +265,14 @@ var ARTYFACTS_TOOLS = [
266
265
  inputSchema: {
267
266
  type: "object",
268
267
  properties: {
268
+ agentId: { type: "string", description: 'Unique agent ID (e.g., "engineering-agent", "qa-agent")' },
269
269
  name: { type: "string", description: "Agent display name" },
270
270
  type: { type: "string", description: "Type: pm, engineering, qa, research, content, design" },
271
271
  description: { type: "string", description: "What this agent does" },
272
272
  capabilities: { type: "array", items: { type: "string" }, description: "Agent capabilities" },
273
273
  config: { type: "object", description: "Agent configuration" }
274
274
  },
275
- required: ["name", "type"]
275
+ required: ["agentId", "name", "type"]
276
276
  }
277
277
  },
278
278
  {
@@ -413,7 +413,27 @@ var toolHandlers = {
413
413
  return client.get(`/artifacts?${params}`);
414
414
  },
415
415
  get_artifact: (client, args) => client.get(`/artifacts/${args.artifact_id}`),
416
- create_artifact: (client, args) => client.post("/artifacts", args),
416
+ create_artifact: (client, args) => {
417
+ const envelope = {
418
+ aah_version: "0.3",
419
+ artifact: {
420
+ id: args.id || `artifact-${Date.now()}`,
421
+ title: args.title,
422
+ type: args.type || "document/sectioned",
423
+ artifact_type: args.artifact_type || args.type || "doc",
424
+ parent_id: args.parent_id,
425
+ tags: args.tags
426
+ },
427
+ content: args.content ? {
428
+ media_type: "text/markdown",
429
+ body: args.content
430
+ } : void 0,
431
+ source: {
432
+ agent_id: "mcp-agent"
433
+ }
434
+ };
435
+ return client.post("/artifacts", envelope);
436
+ },
417
437
  update_artifact: (client, args) => {
418
438
  const { artifact_id, ...body } = args;
419
439
  return client.patch(`/artifacts/${artifact_id}`, body);
@@ -422,7 +442,8 @@ var toolHandlers = {
422
442
  list_sections: (client, args) => client.get(`/artifacts/${args.artifact_id}/sections`),
423
443
  get_section: (client, args) => client.get(`/artifacts/${args.artifact_id}/sections/${args.section_id}`),
424
444
  create_section: (client, args) => {
425
- const { artifact_id, ...body } = args;
445
+ const { artifact_id, section_id, ...rest } = args;
446
+ const body = { id: section_id, ...rest };
426
447
  return client.post(`/artifacts/${artifact_id}/sections`, body);
427
448
  },
428
449
  update_section: (client, args) => {
package/dist/server.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  ArtyfactsMcpServer,
3
3
  createMcpServer,
4
4
  startServer
5
- } from "./chunk-ZGKINVWK.js";
5
+ } from "./chunk-VCIOVYRM.js";
6
6
  export {
7
7
  ArtyfactsMcpServer,
8
8
  createMcpServer,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@artyfacts/mcp-server",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "MCP server exposing Artyfacts tools for Claude Code",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/server.ts CHANGED
@@ -97,18 +97,17 @@ const ARTYFACTS_TOOLS: Tool[] = [
97
97
  },
98
98
  {
99
99
  name: 'create_artifact',
100
- description: 'Create a new artifact',
100
+ description: 'Create a new artifact (document, goal, spec, etc.)',
101
101
  inputSchema: {
102
102
  type: 'object',
103
103
  properties: {
104
104
  title: { type: 'string', description: 'Artifact title' },
105
- type: { type: 'string', description: 'Type: goal, spec, research, report, experiment, decision' },
105
+ type: { type: 'string', description: 'Artifact type: goal, spec, research, report, experiment, decision, doc' },
106
106
  content: { type: 'string', description: 'Markdown content' },
107
- project_id: { type: 'string', description: 'Project ID' },
108
- parent_id: { type: 'string', description: 'Parent artifact ID' },
109
- tags: { type: 'array', items: { type: 'string' }, description: 'Tags' },
107
+ parent_id: { type: 'string', description: 'Parent artifact ID for nested artifacts' },
108
+ tags: { type: 'array', items: { type: 'string' }, description: 'Tags for categorization' },
110
109
  },
111
- required: ['title'],
110
+ required: ['title', 'type'],
112
111
  },
113
112
  },
114
113
  {
@@ -163,7 +162,7 @@ const ARTYFACTS_TOOLS: Tool[] = [
163
162
  type: { type: 'string', description: 'Type: content, task, decision, blocker' },
164
163
  position: { type: 'number', description: 'Order position' },
165
164
  },
166
- required: ['artifact_id', 'section_id', 'heading'],
165
+ required: ['artifact_id', 'section_id', 'heading', 'content'],
167
166
  },
168
167
  },
169
168
  {
@@ -275,13 +274,14 @@ const ARTYFACTS_TOOLS: Tool[] = [
275
274
  inputSchema: {
276
275
  type: 'object',
277
276
  properties: {
277
+ agentId: { type: 'string', description: 'Unique agent ID (e.g., "engineering-agent", "qa-agent")' },
278
278
  name: { type: 'string', description: 'Agent display name' },
279
279
  type: { type: 'string', description: 'Type: pm, engineering, qa, research, content, design' },
280
280
  description: { type: 'string', description: 'What this agent does' },
281
281
  capabilities: { type: 'array', items: { type: 'string' }, description: 'Agent capabilities' },
282
282
  config: { type: 'object', description: 'Agent configuration' },
283
283
  },
284
- required: ['name', 'type'],
284
+ required: ['agentId', 'name', 'type'],
285
285
  },
286
286
  },
287
287
  {
@@ -436,7 +436,28 @@ const toolHandlers: Record<string, ToolHandler> = {
436
436
  return client.get(`/artifacts?${params}`);
437
437
  },
438
438
  get_artifact: (client, args) => client.get(`/artifacts/${args.artifact_id}`),
439
- create_artifact: (client, args) => client.post('/artifacts', args),
439
+ create_artifact: (client, args) => {
440
+ // API expects AAH envelope format
441
+ const envelope = {
442
+ aah_version: '0.3',
443
+ artifact: {
444
+ id: args.id || `artifact-${Date.now()}`,
445
+ title: args.title,
446
+ type: args.type || 'document/sectioned',
447
+ artifact_type: args.artifact_type || args.type || 'doc',
448
+ parent_id: args.parent_id,
449
+ tags: args.tags,
450
+ },
451
+ content: args.content ? {
452
+ media_type: 'text/markdown',
453
+ body: args.content,
454
+ } : undefined,
455
+ source: {
456
+ agent_id: 'mcp-agent',
457
+ },
458
+ };
459
+ return client.post('/artifacts', envelope);
460
+ },
440
461
  update_artifact: (client, args) => {
441
462
  const { artifact_id, ...body } = args;
442
463
  return client.patch(`/artifacts/${artifact_id}`, body);
@@ -446,7 +467,9 @@ const toolHandlers: Record<string, ToolHandler> = {
446
467
  list_sections: (client, args) => client.get(`/artifacts/${args.artifact_id}/sections`),
447
468
  get_section: (client, args) => client.get(`/artifacts/${args.artifact_id}/sections/${args.section_id}`),
448
469
  create_section: (client, args) => {
449
- const { artifact_id, ...body } = args;
470
+ const { artifact_id, section_id, ...rest } = args;
471
+ // API expects 'id' not 'section_id'
472
+ const body = { id: section_id, ...rest };
450
473
  return client.post(`/artifacts/${artifact_id}/sections`, body);
451
474
  },
452
475
  update_section: (client, args) => {