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