@artyfacts/mcp-server 1.0.0 → 1.0.2

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
+ };
package/dist/index.cjs CHANGED
@@ -268,13 +268,14 @@ var ARTYFACTS_TOOLS = [
268
268
  inputSchema: {
269
269
  type: "object",
270
270
  properties: {
271
+ agentId: { type: "string", description: 'Unique agent ID (e.g., "engineering-agent", "qa-agent")' },
271
272
  name: { type: "string", description: "Agent display name" },
272
273
  type: { type: "string", description: "Type: pm, engineering, qa, research, content, design" },
273
274
  description: { type: "string", description: "What this agent does" },
274
275
  capabilities: { type: "array", items: { type: "string" }, description: "Agent capabilities" },
275
276
  config: { type: "object", description: "Agent configuration" }
276
277
  },
277
- required: ["name", "type"]
278
+ required: ["agentId", "name", "type"]
278
279
  }
279
280
  },
280
281
  {
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-OZZ4SOPK.js";
6
6
  export {
7
7
  ArtyfactsMcpServer,
8
8
  createMcpServer,
package/dist/server.cjs CHANGED
@@ -266,13 +266,14 @@ var ARTYFACTS_TOOLS = [
266
266
  inputSchema: {
267
267
  type: "object",
268
268
  properties: {
269
+ agentId: { type: "string", description: 'Unique agent ID (e.g., "engineering-agent", "qa-agent")' },
269
270
  name: { type: "string", description: "Agent display name" },
270
271
  type: { type: "string", description: "Type: pm, engineering, qa, research, content, design" },
271
272
  description: { type: "string", description: "What this agent does" },
272
273
  capabilities: { type: "array", items: { type: "string" }, description: "Agent capabilities" },
273
274
  config: { type: "object", description: "Agent configuration" }
274
275
  },
275
- required: ["name", "type"]
276
+ required: ["agentId", "name", "type"]
276
277
  }
277
278
  },
278
279
  {
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-OZZ4SOPK.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.0",
3
+ "version": "1.0.2",
4
4
  "description": "MCP server exposing Artyfacts tools for Claude Code",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -21,7 +21,13 @@
21
21
  "dev": "tsup src/index.ts src/server.ts --format cjs,esm --dts --watch",
22
22
  "prepublishOnly": "npm run build"
23
23
  },
24
- "keywords": ["artyfacts", "mcp", "claude", "ai", "tools"],
24
+ "keywords": [
25
+ "artyfacts",
26
+ "mcp",
27
+ "claude",
28
+ "ai",
29
+ "tools"
30
+ ],
25
31
  "author": "Artyfacts",
26
32
  "license": "MIT",
27
33
  "repository": {
package/src/server.ts CHANGED
@@ -275,13 +275,14 @@ const ARTYFACTS_TOOLS: Tool[] = [
275
275
  inputSchema: {
276
276
  type: 'object',
277
277
  properties: {
278
+ agentId: { type: 'string', description: 'Unique agent ID (e.g., "engineering-agent", "qa-agent")' },
278
279
  name: { type: 'string', description: 'Agent display name' },
279
280
  type: { type: 'string', description: 'Type: pm, engineering, qa, research, content, design' },
280
281
  description: { type: 'string', description: 'What this agent does' },
281
282
  capabilities: { type: 'array', items: { type: 'string' }, description: 'Agent capabilities' },
282
283
  config: { type: 'object', description: 'Agent configuration' },
283
284
  },
284
- required: ['name', 'type'],
285
+ required: ['agentId', 'name', 'type'],
285
286
  },
286
287
  },
287
288
  {