@artyfacts/mcp-server 1.1.2 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/artyfacts-mcp.js +2 -0
- package/dist/chunk-GOOQPNGV.js +631 -0
- package/dist/index.cjs +19 -8
- package/dist/index.js +1 -1
- package/dist/server.cjs +19 -8
- package/dist/server.d.cts +2 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +1 -1
- package/package.json +1 -1
- package/src/server.ts +20 -8
package/bin/artyfacts-mcp.js
CHANGED
|
@@ -5,6 +5,7 @@ import { createMcpServer, startServer } from '../dist/index.js';
|
|
|
5
5
|
// Get config from environment or args
|
|
6
6
|
const apiKey = process.env.ARTYFACTS_API_KEY;
|
|
7
7
|
const baseUrl = process.env.ARTYFACTS_BASE_URL || 'https://artyfacts.dev/api/v1';
|
|
8
|
+
const agentId = process.env.ARTYFACTS_AGENT_ID;
|
|
8
9
|
|
|
9
10
|
if (!apiKey) {
|
|
10
11
|
console.error('Error: ARTYFACTS_API_KEY environment variable is required');
|
|
@@ -20,6 +21,7 @@ if (!apiKey) {
|
|
|
20
21
|
const server = createMcpServer({
|
|
21
22
|
apiKey,
|
|
22
23
|
baseUrl,
|
|
24
|
+
agentId,
|
|
23
25
|
});
|
|
24
26
|
|
|
25
27
|
startServer(server).catch((error) => {
|
|
@@ -0,0 +1,631 @@
|
|
|
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. Always pass output_artifact_id if you created an artifact. Always pass output_references listing every entity you created or touched.",
|
|
193
|
+
inputSchema: {
|
|
194
|
+
type: "object",
|
|
195
|
+
properties: {
|
|
196
|
+
task_id: { type: "string", description: "Task ID" },
|
|
197
|
+
output_text: { type: "string", description: "Completion summary / what was done" },
|
|
198
|
+
output_url: { type: "string", description: "URL to deliverable (PR, doc, etc.)" },
|
|
199
|
+
output_artifact_id: { type: "string", description: "UUID of the primary artifact produced by this task" },
|
|
200
|
+
output_references: {
|
|
201
|
+
type: "array",
|
|
202
|
+
description: "All entities created or interacted with: artifacts, tasks, agents, goals",
|
|
203
|
+
items: {
|
|
204
|
+
type: "object",
|
|
205
|
+
properties: {
|
|
206
|
+
type: { type: "string", description: "artifact | task | agent | goal" },
|
|
207
|
+
id: { type: "string", description: "Entity UUID" },
|
|
208
|
+
title: { type: "string", description: "Display name for the reference card" },
|
|
209
|
+
subtitle: { type: "string", description: "Optional: type label, status, role, etc." }
|
|
210
|
+
},
|
|
211
|
+
required: ["type", "id", "title"]
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
required: ["task_id"]
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
name: "block_task",
|
|
220
|
+
description: "Mark a task as blocked",
|
|
221
|
+
inputSchema: {
|
|
222
|
+
type: "object",
|
|
223
|
+
properties: {
|
|
224
|
+
task_id: { type: "string", description: "Task ID" },
|
|
225
|
+
reason: { type: "string", description: "Why it is blocked" },
|
|
226
|
+
blocker_type: { type: "string", description: "Type: decision, dependency, resource, external" }
|
|
227
|
+
},
|
|
228
|
+
required: ["task_id", "reason"]
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
name: "create_task",
|
|
233
|
+
description: "Create a new task under a goal. Use this to create actionable tasks \u2014 NOT create_artifact or create_section.",
|
|
234
|
+
inputSchema: {
|
|
235
|
+
type: "object",
|
|
236
|
+
properties: {
|
|
237
|
+
goal_id: { type: "string", description: "The goal UUID this task belongs to (required)" },
|
|
238
|
+
title: { type: "string", description: "Task title" },
|
|
239
|
+
description: { type: "string", description: "Task description / what needs to be done" },
|
|
240
|
+
priority: { type: "string", description: "Priority: low, medium, high, urgent" },
|
|
241
|
+
assigned_to: { type: "string", description: "Agent UUID to assign the task to" },
|
|
242
|
+
depends_on: { type: "array", items: { type: "string" }, description: "List of task UUIDs this task depends on" },
|
|
243
|
+
estimated_minutes: { type: "number", description: "Estimated time in minutes" }
|
|
244
|
+
},
|
|
245
|
+
required: ["goal_id", "title"]
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
// Agent tools
|
|
249
|
+
{
|
|
250
|
+
name: "list_agents",
|
|
251
|
+
description: "List all agents in the organization",
|
|
252
|
+
inputSchema: {
|
|
253
|
+
type: "object",
|
|
254
|
+
properties: {
|
|
255
|
+
status: { type: "string", description: "Filter by status: active, inactive" }
|
|
256
|
+
},
|
|
257
|
+
required: []
|
|
258
|
+
}
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
name: "get_agent",
|
|
262
|
+
description: "Get details about an agent",
|
|
263
|
+
inputSchema: {
|
|
264
|
+
type: "object",
|
|
265
|
+
properties: {
|
|
266
|
+
agent_id: { type: "string", description: "Agent ID" }
|
|
267
|
+
},
|
|
268
|
+
required: ["agent_id"]
|
|
269
|
+
}
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
name: "create_agent",
|
|
273
|
+
description: "Register a new AI agent with role, capabilities, and permissions",
|
|
274
|
+
inputSchema: {
|
|
275
|
+
type: "object",
|
|
276
|
+
properties: {
|
|
277
|
+
agentId: { type: "string", description: 'Unique agent ID (e.g., "engineering-agent", "qa-agent")' },
|
|
278
|
+
name: { type: "string", description: "Agent display name" },
|
|
279
|
+
role: { type: "string", description: "Role: pm, engineering, qa, research, content, design" },
|
|
280
|
+
description: { type: "string", description: "What this agent does - detailed description" },
|
|
281
|
+
capabilities: { type: "array", items: { type: "string" }, description: 'List of capabilities (e.g., ["code-review", "testing", "debugging"])' },
|
|
282
|
+
permissions: {
|
|
283
|
+
type: "object",
|
|
284
|
+
description: "Permission settings",
|
|
285
|
+
properties: {
|
|
286
|
+
write: { type: "boolean", description: "Can create/edit artifacts" },
|
|
287
|
+
delete: { type: "boolean", description: "Can delete artifacts" },
|
|
288
|
+
delegate_tasks: { type: "boolean", description: "Can assign tasks to other agents" }
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
systemPrompt: { type: "string", description: "System prompt for the agent" },
|
|
292
|
+
reportsToAgentId: { type: "string", description: 'Agent ID or UUID of the parent agent this agent reports to. Use agent slugs like "chief-of-staff" for readability.' }
|
|
293
|
+
},
|
|
294
|
+
required: ["agentId", "name", "role", "description"]
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
name: "update_agent",
|
|
299
|
+
description: "Update an agent",
|
|
300
|
+
inputSchema: {
|
|
301
|
+
type: "object",
|
|
302
|
+
properties: {
|
|
303
|
+
agent_id: { type: "string", description: "Agent ID" },
|
|
304
|
+
name: { type: "string", description: "New name" },
|
|
305
|
+
status: { type: "string", description: "New status" },
|
|
306
|
+
config: { type: "object", description: "Updated config" }
|
|
307
|
+
},
|
|
308
|
+
required: ["agent_id"]
|
|
309
|
+
}
|
|
310
|
+
},
|
|
311
|
+
// Inbox tools (human-in-the-loop)
|
|
312
|
+
{
|
|
313
|
+
name: "create_inbox_item",
|
|
314
|
+
description: "Request human approval, a decision, or an answer before proceeding. Automatically blocks the task. Use for agent creation, risky actions, or anything requiring human sign-off.",
|
|
315
|
+
inputSchema: {
|
|
316
|
+
type: "object",
|
|
317
|
+
properties: {
|
|
318
|
+
task_id: { type: "string", description: "UUID of the task being blocked (required)" },
|
|
319
|
+
type: { type: "string", description: "Type: approval, decision, question" },
|
|
320
|
+
title: { type: "string", description: "Short summary shown to the human in the inbox" },
|
|
321
|
+
content: { type: "string", description: "Full context and details for the human" },
|
|
322
|
+
action: { type: "string", description: "Action to auto-execute if approved (e.g. agent.create)" },
|
|
323
|
+
action_payload: { type: "object", description: "Data for the action (e.g. full agent spec for agent.create)" },
|
|
324
|
+
options: { type: "array", description: "Options for decision type: [{id, label, description}]" }
|
|
325
|
+
},
|
|
326
|
+
required: ["task_id", "type", "title"]
|
|
327
|
+
}
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
name: "list_inbox",
|
|
331
|
+
description: "List pending inbox items (approvals, decisions, questions) waiting for human resolution.",
|
|
332
|
+
inputSchema: {
|
|
333
|
+
type: "object",
|
|
334
|
+
properties: {
|
|
335
|
+
status: { type: "string", description: "Filter by status: pending (default), resolved" },
|
|
336
|
+
type: { type: "string", description: "Filter by type: approval, decision, question" },
|
|
337
|
+
limit: { type: "number", description: "Max results (default 50)" }
|
|
338
|
+
},
|
|
339
|
+
required: []
|
|
340
|
+
}
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
name: "resolve_inbox",
|
|
344
|
+
description: "Resolve an inbox item from the agent side. Humans resolve via the UI \u2014 only use this for automated resolution.",
|
|
345
|
+
inputSchema: {
|
|
346
|
+
type: "object",
|
|
347
|
+
properties: {
|
|
348
|
+
item_id: { type: "string", description: "Inbox item UUID" },
|
|
349
|
+
approved: { type: "boolean", description: "For approvals: true to approve, false to deny" },
|
|
350
|
+
chosen_option: { type: "string", description: "For decisions: the selected option ID" },
|
|
351
|
+
answer: { type: "string", description: "For questions: the answer text" },
|
|
352
|
+
notes: { type: "string", description: "Optional notes" }
|
|
353
|
+
},
|
|
354
|
+
required: ["item_id"]
|
|
355
|
+
}
|
|
356
|
+
},
|
|
357
|
+
// Search tools
|
|
358
|
+
{
|
|
359
|
+
name: "search_artifacts",
|
|
360
|
+
description: "Search artifacts by text query",
|
|
361
|
+
inputSchema: {
|
|
362
|
+
type: "object",
|
|
363
|
+
properties: {
|
|
364
|
+
query: { type: "string", description: "Search query" },
|
|
365
|
+
type: { type: "string", description: "Filter by type" },
|
|
366
|
+
limit: { type: "number", description: "Max results" }
|
|
367
|
+
},
|
|
368
|
+
required: ["query"]
|
|
369
|
+
}
|
|
370
|
+
},
|
|
371
|
+
// Context tools
|
|
372
|
+
{
|
|
373
|
+
name: "get_task_context",
|
|
374
|
+
description: "Get full context for a task (org, project, artifact, related sections)",
|
|
375
|
+
inputSchema: {
|
|
376
|
+
type: "object",
|
|
377
|
+
properties: {
|
|
378
|
+
task_id: { type: "string", description: "Task ID" }
|
|
379
|
+
},
|
|
380
|
+
required: ["task_id"]
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
];
|
|
384
|
+
var ArtyfactsApiClient = class {
|
|
385
|
+
constructor(baseUrl, apiKey, agentId) {
|
|
386
|
+
this.baseUrl = baseUrl;
|
|
387
|
+
this.apiKey = apiKey;
|
|
388
|
+
this.agentId = agentId;
|
|
389
|
+
}
|
|
390
|
+
async request(method, path, body) {
|
|
391
|
+
const url = `${this.baseUrl}${path}`;
|
|
392
|
+
const headers = {
|
|
393
|
+
"Authorization": `Bearer ${this.apiKey}`,
|
|
394
|
+
"Content-Type": "application/json"
|
|
395
|
+
};
|
|
396
|
+
if (this.agentId) {
|
|
397
|
+
headers["X-Agent-Id"] = this.agentId;
|
|
398
|
+
}
|
|
399
|
+
const response = await fetch(url, {
|
|
400
|
+
method,
|
|
401
|
+
headers,
|
|
402
|
+
body: body ? JSON.stringify(body) : void 0
|
|
403
|
+
});
|
|
404
|
+
if (!response.ok) {
|
|
405
|
+
const error = await response.json().catch(() => ({ error: "Request failed" }));
|
|
406
|
+
throw new Error(error.error || `HTTP ${response.status}: ${response.statusText}`);
|
|
407
|
+
}
|
|
408
|
+
return response.json();
|
|
409
|
+
}
|
|
410
|
+
get(path) {
|
|
411
|
+
return this.request("GET", path);
|
|
412
|
+
}
|
|
413
|
+
getAgentId() {
|
|
414
|
+
return this.agentId;
|
|
415
|
+
}
|
|
416
|
+
post(path, body) {
|
|
417
|
+
return this.request("POST", path, body);
|
|
418
|
+
}
|
|
419
|
+
patch(path, body) {
|
|
420
|
+
return this.request("PATCH", path, body);
|
|
421
|
+
}
|
|
422
|
+
delete(path) {
|
|
423
|
+
return this.request("DELETE", path);
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
var toolHandlers = {
|
|
427
|
+
// Organization
|
|
428
|
+
get_organization: (client) => client.get("/org"),
|
|
429
|
+
// Projects
|
|
430
|
+
list_projects: (client, args) => {
|
|
431
|
+
const params = new URLSearchParams();
|
|
432
|
+
if (args.limit) params.set("limit", String(args.limit));
|
|
433
|
+
if (args.offset) params.set("offset", String(args.offset));
|
|
434
|
+
return client.get(`/projects?${params}`);
|
|
435
|
+
},
|
|
436
|
+
get_project: (client, args) => client.get(`/projects/${args.project_id}`),
|
|
437
|
+
// Artifacts
|
|
438
|
+
list_artifacts: (client, args) => {
|
|
439
|
+
const params = new URLSearchParams();
|
|
440
|
+
if (args.project_id) params.set("project_id", String(args.project_id));
|
|
441
|
+
if (args.type) params.set("type", String(args.type));
|
|
442
|
+
if (args.status) params.set("status", String(args.status));
|
|
443
|
+
if (args.limit) params.set("limit", String(args.limit));
|
|
444
|
+
return client.get(`/artifacts?${params}`);
|
|
445
|
+
},
|
|
446
|
+
get_artifact: (client, args) => client.get(`/artifacts/${args.artifact_id}`),
|
|
447
|
+
create_artifact: (client, args) => {
|
|
448
|
+
const envelope = {
|
|
449
|
+
aah_version: "0.3",
|
|
450
|
+
artifact: {
|
|
451
|
+
id: args.id || `artifact-${Date.now()}`,
|
|
452
|
+
title: args.title,
|
|
453
|
+
type: args.type || "document/sectioned",
|
|
454
|
+
artifact_type: args.artifact_type || args.type || "doc",
|
|
455
|
+
parent_id: args.parent_id,
|
|
456
|
+
tags: args.tags
|
|
457
|
+
},
|
|
458
|
+
content: args.content ? {
|
|
459
|
+
media_type: "text/markdown",
|
|
460
|
+
body: args.content
|
|
461
|
+
} : void 0,
|
|
462
|
+
source: {
|
|
463
|
+
agent_id: client.getAgentId() || "mcp-agent"
|
|
464
|
+
}
|
|
465
|
+
};
|
|
466
|
+
return client.post("/artifacts", envelope);
|
|
467
|
+
},
|
|
468
|
+
update_artifact: (client, args) => {
|
|
469
|
+
const { artifact_id, ...body } = args;
|
|
470
|
+
return client.patch(`/artifacts/${artifact_id}`, body);
|
|
471
|
+
},
|
|
472
|
+
// Sections
|
|
473
|
+
list_sections: (client, args) => client.get(`/artifacts/${args.artifact_id}/sections`),
|
|
474
|
+
get_section: (client, args) => client.get(`/artifacts/${args.artifact_id}/sections/${args.section_id}`),
|
|
475
|
+
create_section: (client, args) => {
|
|
476
|
+
const { artifact_id, section_id, ...rest } = args;
|
|
477
|
+
const body = { id: section_id, ...rest };
|
|
478
|
+
return client.post(`/artifacts/${artifact_id}/sections`, body);
|
|
479
|
+
},
|
|
480
|
+
update_section: (client, args) => {
|
|
481
|
+
const { artifact_id, section_id, ...body } = args;
|
|
482
|
+
return client.patch(`/artifacts/${artifact_id}/sections/${section_id}`, body);
|
|
483
|
+
},
|
|
484
|
+
delete_section: (client, args) => client.delete(`/artifacts/${args.artifact_id}/sections/${args.section_id}`),
|
|
485
|
+
// Tasks
|
|
486
|
+
list_tasks: (client, args) => {
|
|
487
|
+
const params = new URLSearchParams();
|
|
488
|
+
if (args.artifact_id) params.set("artifact_id", String(args.artifact_id));
|
|
489
|
+
if (args.status) params.set("status", String(args.status));
|
|
490
|
+
if (args.assignee) params.set("assignee", String(args.assignee));
|
|
491
|
+
return client.get(`/tasks?${params}`);
|
|
492
|
+
},
|
|
493
|
+
claim_task: (client, args) => client.post(`/tasks/${args.task_id}/claim`),
|
|
494
|
+
complete_task: (client, args) => {
|
|
495
|
+
const { task_id, ...body } = args;
|
|
496
|
+
return client.post(`/tasks/${task_id}/complete`, body);
|
|
497
|
+
},
|
|
498
|
+
block_task: (client, args) => {
|
|
499
|
+
const { task_id, ...body } = args;
|
|
500
|
+
return client.post(`/tasks/${task_id}/block`, body);
|
|
501
|
+
},
|
|
502
|
+
create_task: (client, args) => {
|
|
503
|
+
const { goal_id, title, description, priority, assigned_to, depends_on, estimated_minutes } = args;
|
|
504
|
+
return client.post("/tasks", { goal_id, title, description, priority, assigned_to, depends_on, estimated_minutes });
|
|
505
|
+
},
|
|
506
|
+
// Agents
|
|
507
|
+
list_agents: (client, args) => {
|
|
508
|
+
const params = new URLSearchParams();
|
|
509
|
+
if (args.status) params.set("status", String(args.status));
|
|
510
|
+
return client.get(`/agents?${params}`);
|
|
511
|
+
},
|
|
512
|
+
get_agent: (client, args) => client.get(`/agents/${args.agent_id}`),
|
|
513
|
+
create_agent: (client, args) => {
|
|
514
|
+
const body = {
|
|
515
|
+
agentId: args.agentId,
|
|
516
|
+
name: args.name,
|
|
517
|
+
role: args.role,
|
|
518
|
+
description: args.description,
|
|
519
|
+
reportsToAgentId: args.reportsToAgentId,
|
|
520
|
+
permissions: args.permissions || { write: true, delete: false, delegate_tasks: false },
|
|
521
|
+
metadata: {
|
|
522
|
+
capabilities: args.capabilities || [],
|
|
523
|
+
systemPrompt: args.systemPrompt,
|
|
524
|
+
createdVia: "mcp"
|
|
525
|
+
}
|
|
526
|
+
};
|
|
527
|
+
return client.post("/agents", body);
|
|
528
|
+
},
|
|
529
|
+
update_agent: (client, args) => {
|
|
530
|
+
const { agent_id, ...body } = args;
|
|
531
|
+
return client.patch(`/agents/${agent_id}`, body);
|
|
532
|
+
},
|
|
533
|
+
// Inbox (human-in-the-loop)
|
|
534
|
+
create_inbox_item: (client, args) => {
|
|
535
|
+
const { task_id, type, title, content, action, action_payload, options } = args;
|
|
536
|
+
return client.post("/inbox", { task_id, type, title, content, action, action_payload, options });
|
|
537
|
+
},
|
|
538
|
+
list_inbox: (client, args) => {
|
|
539
|
+
const params = new URLSearchParams();
|
|
540
|
+
if (args.status) params.set("status", String(args.status));
|
|
541
|
+
if (args.type) params.set("type", String(args.type));
|
|
542
|
+
if (args.limit) params.set("limit", String(args.limit));
|
|
543
|
+
return client.get(`/inbox?${params}`);
|
|
544
|
+
},
|
|
545
|
+
resolve_inbox: (client, args) => {
|
|
546
|
+
const { item_id, ...body } = args;
|
|
547
|
+
return client.post(`/inbox/${item_id}/resolve`, body);
|
|
548
|
+
},
|
|
549
|
+
// Search
|
|
550
|
+
search_artifacts: (client, args) => {
|
|
551
|
+
const params = new URLSearchParams();
|
|
552
|
+
params.set("q", String(args.query));
|
|
553
|
+
if (args.type) params.set("type", String(args.type));
|
|
554
|
+
if (args.limit) params.set("limit", String(args.limit));
|
|
555
|
+
return client.get(`/search?${params}`);
|
|
556
|
+
},
|
|
557
|
+
// Context
|
|
558
|
+
get_task_context: (client, args) => client.get(`/tasks/${args.task_id}/context`)
|
|
559
|
+
};
|
|
560
|
+
var ArtyfactsMcpServer = class {
|
|
561
|
+
server;
|
|
562
|
+
client;
|
|
563
|
+
config;
|
|
564
|
+
constructor(config) {
|
|
565
|
+
this.config = config;
|
|
566
|
+
this.client = new ArtyfactsApiClient(
|
|
567
|
+
config.baseUrl || "https://artyfacts.dev/api/v1",
|
|
568
|
+
config.apiKey,
|
|
569
|
+
config.agentId
|
|
570
|
+
);
|
|
571
|
+
this.server = new Server(
|
|
572
|
+
{
|
|
573
|
+
name: config.name || "artyfacts-mcp",
|
|
574
|
+
version: config.version || "1.0.0"
|
|
575
|
+
},
|
|
576
|
+
{
|
|
577
|
+
capabilities: {
|
|
578
|
+
tools: {}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
);
|
|
582
|
+
this.setupHandlers();
|
|
583
|
+
}
|
|
584
|
+
setupHandlers() {
|
|
585
|
+
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
586
|
+
return { tools: ARTYFACTS_TOOLS };
|
|
587
|
+
});
|
|
588
|
+
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
589
|
+
const { name, arguments: args } = request.params;
|
|
590
|
+
const handler = toolHandlers[name];
|
|
591
|
+
if (!handler) {
|
|
592
|
+
return {
|
|
593
|
+
content: [{ type: "text", text: `Unknown tool: ${name}` }],
|
|
594
|
+
isError: true
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
try {
|
|
598
|
+
const result = await handler(this.client, args || {});
|
|
599
|
+
return {
|
|
600
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
601
|
+
};
|
|
602
|
+
} catch (error) {
|
|
603
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
604
|
+
return {
|
|
605
|
+
content: [{ type: "text", text: `Error: ${message}` }],
|
|
606
|
+
isError: true
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
async start() {
|
|
612
|
+
const transport = new StdioServerTransport();
|
|
613
|
+
await this.server.connect(transport);
|
|
614
|
+
console.error(`Artyfacts MCP server running (${ARTYFACTS_TOOLS.length} tools)`);
|
|
615
|
+
}
|
|
616
|
+
getServer() {
|
|
617
|
+
return this.server;
|
|
618
|
+
}
|
|
619
|
+
};
|
|
620
|
+
function createMcpServer(config) {
|
|
621
|
+
return new ArtyfactsMcpServer(config);
|
|
622
|
+
}
|
|
623
|
+
async function startServer(server) {
|
|
624
|
+
await server.start();
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
export {
|
|
628
|
+
ArtyfactsMcpServer,
|
|
629
|
+
createMcpServer,
|
|
630
|
+
startServer
|
|
631
|
+
};
|
package/dist/index.cjs
CHANGED
|
@@ -313,7 +313,8 @@ var ARTYFACTS_TOOLS = [
|
|
|
313
313
|
delegate_tasks: { type: "boolean", description: "Can assign tasks to other agents" }
|
|
314
314
|
}
|
|
315
315
|
},
|
|
316
|
-
systemPrompt: { type: "string", description: "System prompt for the agent" }
|
|
316
|
+
systemPrompt: { type: "string", description: "System prompt for the agent" },
|
|
317
|
+
reportsToAgentId: { type: "string", description: 'Agent ID or UUID of the parent agent this agent reports to. Use agent slugs like "chief-of-staff" for readability.' }
|
|
317
318
|
},
|
|
318
319
|
required: ["agentId", "name", "role", "description"]
|
|
319
320
|
}
|
|
@@ -406,18 +407,23 @@ var ARTYFACTS_TOOLS = [
|
|
|
406
407
|
}
|
|
407
408
|
];
|
|
408
409
|
var ArtyfactsApiClient = class {
|
|
409
|
-
constructor(baseUrl, apiKey) {
|
|
410
|
+
constructor(baseUrl, apiKey, agentId) {
|
|
410
411
|
this.baseUrl = baseUrl;
|
|
411
412
|
this.apiKey = apiKey;
|
|
413
|
+
this.agentId = agentId;
|
|
412
414
|
}
|
|
413
415
|
async request(method, path, body) {
|
|
414
416
|
const url = `${this.baseUrl}${path}`;
|
|
417
|
+
const headers = {
|
|
418
|
+
"Authorization": `Bearer ${this.apiKey}`,
|
|
419
|
+
"Content-Type": "application/json"
|
|
420
|
+
};
|
|
421
|
+
if (this.agentId) {
|
|
422
|
+
headers["X-Agent-Id"] = this.agentId;
|
|
423
|
+
}
|
|
415
424
|
const response = await fetch(url, {
|
|
416
425
|
method,
|
|
417
|
-
headers
|
|
418
|
-
"Authorization": `Bearer ${this.apiKey}`,
|
|
419
|
-
"Content-Type": "application/json"
|
|
420
|
-
},
|
|
426
|
+
headers,
|
|
421
427
|
body: body ? JSON.stringify(body) : void 0
|
|
422
428
|
});
|
|
423
429
|
if (!response.ok) {
|
|
@@ -429,6 +435,9 @@ var ArtyfactsApiClient = class {
|
|
|
429
435
|
get(path) {
|
|
430
436
|
return this.request("GET", path);
|
|
431
437
|
}
|
|
438
|
+
getAgentId() {
|
|
439
|
+
return this.agentId;
|
|
440
|
+
}
|
|
432
441
|
post(path, body) {
|
|
433
442
|
return this.request("POST", path, body);
|
|
434
443
|
}
|
|
@@ -476,7 +485,7 @@ var toolHandlers = {
|
|
|
476
485
|
body: args.content
|
|
477
486
|
} : void 0,
|
|
478
487
|
source: {
|
|
479
|
-
agent_id: "mcp-agent"
|
|
488
|
+
agent_id: client.getAgentId() || "mcp-agent"
|
|
480
489
|
}
|
|
481
490
|
};
|
|
482
491
|
return client.post("/artifacts", envelope);
|
|
@@ -532,6 +541,7 @@ var toolHandlers = {
|
|
|
532
541
|
name: args.name,
|
|
533
542
|
role: args.role,
|
|
534
543
|
description: args.description,
|
|
544
|
+
reportsToAgentId: args.reportsToAgentId,
|
|
535
545
|
permissions: args.permissions || { write: true, delete: false, delegate_tasks: false },
|
|
536
546
|
metadata: {
|
|
537
547
|
capabilities: args.capabilities || [],
|
|
@@ -580,7 +590,8 @@ var ArtyfactsMcpServer = class {
|
|
|
580
590
|
this.config = config;
|
|
581
591
|
this.client = new ArtyfactsApiClient(
|
|
582
592
|
config.baseUrl || "https://artyfacts.dev/api/v1",
|
|
583
|
-
config.apiKey
|
|
593
|
+
config.apiKey,
|
|
594
|
+
config.agentId
|
|
584
595
|
);
|
|
585
596
|
this.server = new import_server.Server(
|
|
586
597
|
{
|
package/dist/index.js
CHANGED
package/dist/server.cjs
CHANGED
|
@@ -311,7 +311,8 @@ var ARTYFACTS_TOOLS = [
|
|
|
311
311
|
delegate_tasks: { type: "boolean", description: "Can assign tasks to other agents" }
|
|
312
312
|
}
|
|
313
313
|
},
|
|
314
|
-
systemPrompt: { type: "string", description: "System prompt for the agent" }
|
|
314
|
+
systemPrompt: { type: "string", description: "System prompt for the agent" },
|
|
315
|
+
reportsToAgentId: { type: "string", description: 'Agent ID or UUID of the parent agent this agent reports to. Use agent slugs like "chief-of-staff" for readability.' }
|
|
315
316
|
},
|
|
316
317
|
required: ["agentId", "name", "role", "description"]
|
|
317
318
|
}
|
|
@@ -404,18 +405,23 @@ var ARTYFACTS_TOOLS = [
|
|
|
404
405
|
}
|
|
405
406
|
];
|
|
406
407
|
var ArtyfactsApiClient = class {
|
|
407
|
-
constructor(baseUrl, apiKey) {
|
|
408
|
+
constructor(baseUrl, apiKey, agentId) {
|
|
408
409
|
this.baseUrl = baseUrl;
|
|
409
410
|
this.apiKey = apiKey;
|
|
411
|
+
this.agentId = agentId;
|
|
410
412
|
}
|
|
411
413
|
async request(method, path, body) {
|
|
412
414
|
const url = `${this.baseUrl}${path}`;
|
|
415
|
+
const headers = {
|
|
416
|
+
"Authorization": `Bearer ${this.apiKey}`,
|
|
417
|
+
"Content-Type": "application/json"
|
|
418
|
+
};
|
|
419
|
+
if (this.agentId) {
|
|
420
|
+
headers["X-Agent-Id"] = this.agentId;
|
|
421
|
+
}
|
|
413
422
|
const response = await fetch(url, {
|
|
414
423
|
method,
|
|
415
|
-
headers
|
|
416
|
-
"Authorization": `Bearer ${this.apiKey}`,
|
|
417
|
-
"Content-Type": "application/json"
|
|
418
|
-
},
|
|
424
|
+
headers,
|
|
419
425
|
body: body ? JSON.stringify(body) : void 0
|
|
420
426
|
});
|
|
421
427
|
if (!response.ok) {
|
|
@@ -427,6 +433,9 @@ var ArtyfactsApiClient = class {
|
|
|
427
433
|
get(path) {
|
|
428
434
|
return this.request("GET", path);
|
|
429
435
|
}
|
|
436
|
+
getAgentId() {
|
|
437
|
+
return this.agentId;
|
|
438
|
+
}
|
|
430
439
|
post(path, body) {
|
|
431
440
|
return this.request("POST", path, body);
|
|
432
441
|
}
|
|
@@ -474,7 +483,7 @@ var toolHandlers = {
|
|
|
474
483
|
body: args.content
|
|
475
484
|
} : void 0,
|
|
476
485
|
source: {
|
|
477
|
-
agent_id: "mcp-agent"
|
|
486
|
+
agent_id: client.getAgentId() || "mcp-agent"
|
|
478
487
|
}
|
|
479
488
|
};
|
|
480
489
|
return client.post("/artifacts", envelope);
|
|
@@ -530,6 +539,7 @@ var toolHandlers = {
|
|
|
530
539
|
name: args.name,
|
|
531
540
|
role: args.role,
|
|
532
541
|
description: args.description,
|
|
542
|
+
reportsToAgentId: args.reportsToAgentId,
|
|
533
543
|
permissions: args.permissions || { write: true, delete: false, delegate_tasks: false },
|
|
534
544
|
metadata: {
|
|
535
545
|
capabilities: args.capabilities || [],
|
|
@@ -578,7 +588,8 @@ var ArtyfactsMcpServer = class {
|
|
|
578
588
|
this.config = config;
|
|
579
589
|
this.client = new ArtyfactsApiClient(
|
|
580
590
|
config.baseUrl || "https://artyfacts.dev/api/v1",
|
|
581
|
-
config.apiKey
|
|
591
|
+
config.apiKey,
|
|
592
|
+
config.agentId
|
|
582
593
|
);
|
|
583
594
|
this.server = new import_server.Server(
|
|
584
595
|
{
|
package/dist/server.d.cts
CHANGED
|
@@ -12,6 +12,8 @@ interface McpServerConfig {
|
|
|
12
12
|
apiKey: string;
|
|
13
13
|
/** Artyfacts API base URL */
|
|
14
14
|
baseUrl?: string;
|
|
15
|
+
/** Agent slug (e.g. 'chief-of-staff') — used to attribute writes to the correct agent */
|
|
16
|
+
agentId?: string;
|
|
15
17
|
/** Server name */
|
|
16
18
|
name?: string;
|
|
17
19
|
/** Server version */
|
package/dist/server.d.ts
CHANGED
|
@@ -12,6 +12,8 @@ interface McpServerConfig {
|
|
|
12
12
|
apiKey: string;
|
|
13
13
|
/** Artyfacts API base URL */
|
|
14
14
|
baseUrl?: string;
|
|
15
|
+
/** Agent slug (e.g. 'chief-of-staff') — used to attribute writes to the correct agent */
|
|
16
|
+
agentId?: string;
|
|
15
17
|
/** Server name */
|
|
16
18
|
name?: string;
|
|
17
19
|
/** Server version */
|
package/dist/server.js
CHANGED
package/package.json
CHANGED
package/src/server.ts
CHANGED
|
@@ -22,6 +22,8 @@ export interface McpServerConfig {
|
|
|
22
22
|
apiKey: string;
|
|
23
23
|
/** Artyfacts API base URL */
|
|
24
24
|
baseUrl?: string;
|
|
25
|
+
/** Agent slug (e.g. 'chief-of-staff') — used to attribute writes to the correct agent */
|
|
26
|
+
agentId?: string;
|
|
25
27
|
/** Server name */
|
|
26
28
|
name?: string;
|
|
27
29
|
/** Server version */
|
|
@@ -321,6 +323,7 @@ const ARTYFACTS_TOOLS: Tool[] = [
|
|
|
321
323
|
}
|
|
322
324
|
},
|
|
323
325
|
systemPrompt: { type: 'string', description: 'System prompt for the agent' },
|
|
326
|
+
reportsToAgentId: { type: 'string', description: 'Agent ID or UUID of the parent agent this agent reports to. Use agent slugs like "chief-of-staff" for readability.' },
|
|
324
327
|
},
|
|
325
328
|
required: ['agentId', 'name', 'role', 'description'],
|
|
326
329
|
},
|
|
@@ -423,18 +426,24 @@ const ARTYFACTS_TOOLS: Tool[] = [
|
|
|
423
426
|
class ArtyfactsApiClient {
|
|
424
427
|
constructor(
|
|
425
428
|
private baseUrl: string,
|
|
426
|
-
private apiKey: string
|
|
429
|
+
private apiKey: string,
|
|
430
|
+
private agentId?: string
|
|
427
431
|
) {}
|
|
428
432
|
|
|
429
433
|
async request(method: string, path: string, body?: unknown): Promise<unknown> {
|
|
430
434
|
const url = `${this.baseUrl}${path}`;
|
|
431
|
-
|
|
435
|
+
|
|
436
|
+
const headers: Record<string, string> = {
|
|
437
|
+
'Authorization': `Bearer ${this.apiKey}`,
|
|
438
|
+
'Content-Type': 'application/json',
|
|
439
|
+
};
|
|
440
|
+
if (this.agentId) {
|
|
441
|
+
headers['X-Agent-Id'] = this.agentId;
|
|
442
|
+
}
|
|
443
|
+
|
|
432
444
|
const response = await fetch(url, {
|
|
433
445
|
method,
|
|
434
|
-
headers
|
|
435
|
-
'Authorization': `Bearer ${this.apiKey}`,
|
|
436
|
-
'Content-Type': 'application/json',
|
|
437
|
-
},
|
|
446
|
+
headers,
|
|
438
447
|
body: body ? JSON.stringify(body) : undefined,
|
|
439
448
|
});
|
|
440
449
|
|
|
@@ -447,6 +456,7 @@ class ArtyfactsApiClient {
|
|
|
447
456
|
}
|
|
448
457
|
|
|
449
458
|
get(path: string) { return this.request('GET', path); }
|
|
459
|
+
getAgentId() { return this.agentId; }
|
|
450
460
|
post(path: string, body?: unknown) { return this.request('POST', path, body); }
|
|
451
461
|
patch(path: string, body?: unknown) { return this.request('PATCH', path, body); }
|
|
452
462
|
delete(path: string) { return this.request('DELETE', path); }
|
|
@@ -498,7 +508,7 @@ const toolHandlers: Record<string, ToolHandler> = {
|
|
|
498
508
|
body: args.content,
|
|
499
509
|
} : undefined,
|
|
500
510
|
source: {
|
|
501
|
-
agent_id: 'mcp-agent',
|
|
511
|
+
agent_id: client.getAgentId() || 'mcp-agent',
|
|
502
512
|
},
|
|
503
513
|
};
|
|
504
514
|
return client.post('/artifacts', envelope);
|
|
@@ -559,6 +569,7 @@ const toolHandlers: Record<string, ToolHandler> = {
|
|
|
559
569
|
name: args.name,
|
|
560
570
|
role: args.role,
|
|
561
571
|
description: args.description,
|
|
572
|
+
reportsToAgentId: args.reportsToAgentId,
|
|
562
573
|
permissions: args.permissions || { write: true, delete: false, delegate_tasks: false },
|
|
563
574
|
metadata: {
|
|
564
575
|
capabilities: args.capabilities || [],
|
|
@@ -616,7 +627,8 @@ export class ArtyfactsMcpServer {
|
|
|
616
627
|
this.config = config;
|
|
617
628
|
this.client = new ArtyfactsApiClient(
|
|
618
629
|
config.baseUrl || 'https://artyfacts.dev/api/v1',
|
|
619
|
-
config.apiKey
|
|
630
|
+
config.apiKey,
|
|
631
|
+
config.agentId
|
|
620
632
|
);
|
|
621
633
|
|
|
622
634
|
this.server = new Server(
|