@1medium/cli 1.0.0 → 1.2.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/package.json +1 -1
- package/src/api.js +64 -0
- package/src/config.js +24 -0
- package/src/index.js +358 -3
- package/src/mcp-server.js +505 -3
package/package.json
CHANGED
package/src/api.js
CHANGED
|
@@ -127,6 +127,62 @@ async function listOrgs() {
|
|
|
127
127
|
return request("GET", "/orgs");
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
+
/**
|
|
131
|
+
* List spaces (top-level priority groups)
|
|
132
|
+
*/
|
|
133
|
+
async function listSpaces() {
|
|
134
|
+
return request("GET", "/spaces");
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Create a space
|
|
139
|
+
*/
|
|
140
|
+
async function createSpace(payload) {
|
|
141
|
+
return request("POST", "/spaces", payload);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Update a space
|
|
146
|
+
*/
|
|
147
|
+
async function updateSpace(id, payload) {
|
|
148
|
+
return request("PATCH", `/spaces/${id}`, payload);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Delete a space
|
|
153
|
+
*/
|
|
154
|
+
async function deleteSpace(id) {
|
|
155
|
+
return request("DELETE", `/spaces/${id}`);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* List projects (optionally filtered by space)
|
|
160
|
+
*/
|
|
161
|
+
async function listProjects(params = {}) {
|
|
162
|
+
return request("GET", "/projects", null, params);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Create a project
|
|
167
|
+
*/
|
|
168
|
+
async function createProject(payload) {
|
|
169
|
+
return request("POST", "/projects", payload);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Update a project
|
|
174
|
+
*/
|
|
175
|
+
async function updateProject(id, payload) {
|
|
176
|
+
return request("PATCH", `/projects/${id}`, payload);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Delete a project
|
|
181
|
+
*/
|
|
182
|
+
async function deleteProject(id) {
|
|
183
|
+
return request("DELETE", `/projects/${id}`);
|
|
184
|
+
}
|
|
185
|
+
|
|
130
186
|
module.exports = {
|
|
131
187
|
whoami,
|
|
132
188
|
createTask,
|
|
@@ -136,4 +192,12 @@ module.exports = {
|
|
|
136
192
|
addComment,
|
|
137
193
|
completeTask,
|
|
138
194
|
listOrgs,
|
|
195
|
+
listSpaces,
|
|
196
|
+
createSpace,
|
|
197
|
+
updateSpace,
|
|
198
|
+
deleteSpace,
|
|
199
|
+
listProjects,
|
|
200
|
+
createProject,
|
|
201
|
+
updateProject,
|
|
202
|
+
deleteProject,
|
|
139
203
|
};
|
package/src/config.js
CHANGED
|
@@ -21,6 +21,22 @@ const config = new Conf({
|
|
|
21
21
|
type: "string",
|
|
22
22
|
default: "",
|
|
23
23
|
},
|
|
24
|
+
spaceId: {
|
|
25
|
+
type: "string",
|
|
26
|
+
default: "",
|
|
27
|
+
},
|
|
28
|
+
spaceName: {
|
|
29
|
+
type: "string",
|
|
30
|
+
default: "",
|
|
31
|
+
},
|
|
32
|
+
projectId: {
|
|
33
|
+
type: "string",
|
|
34
|
+
default: "",
|
|
35
|
+
},
|
|
36
|
+
projectName: {
|
|
37
|
+
type: "string",
|
|
38
|
+
default: "",
|
|
39
|
+
},
|
|
24
40
|
},
|
|
25
41
|
});
|
|
26
42
|
|
|
@@ -37,4 +53,12 @@ if (process.env.ONEMEDIUM_ORG_ID) {
|
|
|
37
53
|
config.set("orgId", process.env.ONEMEDIUM_ORG_ID);
|
|
38
54
|
}
|
|
39
55
|
|
|
56
|
+
if (process.env.ONEMEDIUM_SPACE_ID) {
|
|
57
|
+
config.set("spaceId", process.env.ONEMEDIUM_SPACE_ID);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (process.env.ONEMEDIUM_PROJECT_ID) {
|
|
61
|
+
config.set("projectId", process.env.ONEMEDIUM_PROJECT_ID);
|
|
62
|
+
}
|
|
63
|
+
|
|
40
64
|
module.exports = config;
|
package/src/index.js
CHANGED
|
@@ -110,6 +110,7 @@ taskCmd
|
|
|
110
110
|
.option("-b, --body <body>", "Task body (markdown)")
|
|
111
111
|
.option("-p, --priority <priority>", "Priority: P0, P1, P2, P3", "P2")
|
|
112
112
|
.option("-s, --status <status>", "Status: inbox, open, doing, blocked, done", "inbox")
|
|
113
|
+
.option("--project <project-id>", "Project ID to associate the task with (uses default if not specified)")
|
|
113
114
|
.option("--tag <tags...>", "Tags to add")
|
|
114
115
|
.option("--repo <repo>", "Repository context (owner/repo)")
|
|
115
116
|
.option("--branch <branch>", "Branch context")
|
|
@@ -132,6 +133,9 @@ taskCmd
|
|
|
132
133
|
if (options.pr) context.pr_url = options.pr;
|
|
133
134
|
if (options.issue) context.issue_url = options.issue;
|
|
134
135
|
|
|
136
|
+
// Use provided project_id or fall back to configured default
|
|
137
|
+
const projectId = options.project || config.get("projectId") || null;
|
|
138
|
+
|
|
135
139
|
const payload = {
|
|
136
140
|
title: options.title,
|
|
137
141
|
body_md: options.body,
|
|
@@ -142,6 +146,7 @@ taskCmd
|
|
|
142
146
|
source: options.source,
|
|
143
147
|
estimate_minutes: options.estimate,
|
|
144
148
|
due_at: options.due,
|
|
149
|
+
project_id: projectId,
|
|
145
150
|
dedupe: {
|
|
146
151
|
mode: options.dedupe === false ? "none" : "auto",
|
|
147
152
|
},
|
|
@@ -161,6 +166,9 @@ taskCmd
|
|
|
161
166
|
console.log(` Title: ${data.task.title}`);
|
|
162
167
|
console.log(` Status: ${data.task.status}`);
|
|
163
168
|
console.log(` Priority: ${data.task.priority}`);
|
|
169
|
+
if (data.task.project_name) {
|
|
170
|
+
console.log(` Project: ${data.task.project_name}`);
|
|
171
|
+
}
|
|
164
172
|
}
|
|
165
173
|
} catch (error) {
|
|
166
174
|
console.error(chalk.red(`Error: ${error.message}`));
|
|
@@ -406,6 +414,306 @@ program
|
|
|
406
414
|
}
|
|
407
415
|
});
|
|
408
416
|
|
|
417
|
+
// ============================================================================
|
|
418
|
+
// Space Commands
|
|
419
|
+
// ============================================================================
|
|
420
|
+
|
|
421
|
+
const spaceCmd = program.command("space").description("Manage spaces");
|
|
422
|
+
|
|
423
|
+
spaceCmd
|
|
424
|
+
.command("list")
|
|
425
|
+
.description("List your spaces (top-level groups)")
|
|
426
|
+
.option("-j, --json", "Output as JSON")
|
|
427
|
+
.action(async (options) => {
|
|
428
|
+
try {
|
|
429
|
+
const data = await api.listSpaces();
|
|
430
|
+
const currentSpaceId = config.get("spaceId");
|
|
431
|
+
|
|
432
|
+
if (options.json) {
|
|
433
|
+
console.log(JSON.stringify(data, null, 2));
|
|
434
|
+
} else {
|
|
435
|
+
console.log(chalk.bold("\nSpaces:\n"));
|
|
436
|
+
if (data.spaces.length === 0) {
|
|
437
|
+
console.log(" No spaces found.");
|
|
438
|
+
} else {
|
|
439
|
+
for (const space of data.spaces) {
|
|
440
|
+
const current = space.id === currentSpaceId ? chalk.green(" (current)") : "";
|
|
441
|
+
console.log(` ${space.name}${current}`);
|
|
442
|
+
console.log(chalk.gray(` ID: ${space.id}`));
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
console.log("");
|
|
446
|
+
if (!currentSpaceId) {
|
|
447
|
+
console.log(chalk.yellow("No default space set. Use: 1m config set space <space-id>"));
|
|
448
|
+
console.log("");
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
} catch (error) {
|
|
452
|
+
console.error(chalk.red(`Error: ${error.message}`));
|
|
453
|
+
process.exit(1);
|
|
454
|
+
}
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
spaceCmd
|
|
458
|
+
.command("add")
|
|
459
|
+
.description("Create a new space")
|
|
460
|
+
.requiredOption("-n, --name <name>", "Space name (min 2 characters)")
|
|
461
|
+
.option("-j, --json", "Output as JSON")
|
|
462
|
+
.action(async (options) => {
|
|
463
|
+
try {
|
|
464
|
+
const data = await api.createSpace({ name: options.name });
|
|
465
|
+
|
|
466
|
+
if (options.json) {
|
|
467
|
+
console.log(JSON.stringify(data, null, 2));
|
|
468
|
+
} else {
|
|
469
|
+
console.log(chalk.green("Space created:"));
|
|
470
|
+
console.log(` ID: ${data.space.id}`);
|
|
471
|
+
console.log(` Name: ${data.space.name}`);
|
|
472
|
+
}
|
|
473
|
+
} catch (error) {
|
|
474
|
+
console.error(chalk.red(`Error: ${error.message}`));
|
|
475
|
+
process.exit(1);
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
spaceCmd
|
|
480
|
+
.command("update <id>")
|
|
481
|
+
.description("Update a space")
|
|
482
|
+
.option("-n, --name <name>", "New space name")
|
|
483
|
+
.option("-j, --json", "Output as JSON")
|
|
484
|
+
.action(async (id, options) => {
|
|
485
|
+
try {
|
|
486
|
+
const payload = {};
|
|
487
|
+
if (options.name) payload.name = options.name;
|
|
488
|
+
|
|
489
|
+
const data = await api.updateSpace(id, payload);
|
|
490
|
+
|
|
491
|
+
if (options.json) {
|
|
492
|
+
console.log(JSON.stringify(data, null, 2));
|
|
493
|
+
} else {
|
|
494
|
+
console.log(chalk.green("Space updated:"));
|
|
495
|
+
console.log(` ID: ${data.space.id}`);
|
|
496
|
+
console.log(` Name: ${data.space.name}`);
|
|
497
|
+
}
|
|
498
|
+
} catch (error) {
|
|
499
|
+
console.error(chalk.red(`Error: ${error.message}`));
|
|
500
|
+
process.exit(1);
|
|
501
|
+
}
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
spaceCmd
|
|
505
|
+
.command("delete <id>")
|
|
506
|
+
.description("Delete a space (must be empty)")
|
|
507
|
+
.option("-j, --json", "Output as JSON")
|
|
508
|
+
.action(async (id, options) => {
|
|
509
|
+
try {
|
|
510
|
+
const data = await api.deleteSpace(id);
|
|
511
|
+
|
|
512
|
+
if (options.json) {
|
|
513
|
+
console.log(JSON.stringify(data, null, 2));
|
|
514
|
+
} else {
|
|
515
|
+
console.log(chalk.green(`Space deleted: ${id}`));
|
|
516
|
+
}
|
|
517
|
+
} catch (error) {
|
|
518
|
+
console.error(chalk.red(`Error: ${error.message}`));
|
|
519
|
+
process.exit(1);
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
// Alias: `1m spaces` -> `1m space list`
|
|
524
|
+
program
|
|
525
|
+
.command("spaces")
|
|
526
|
+
.description("List your spaces (alias for 'space list')")
|
|
527
|
+
.option("-j, --json", "Output as JSON")
|
|
528
|
+
.action(async (options) => {
|
|
529
|
+
try {
|
|
530
|
+
const data = await api.listSpaces();
|
|
531
|
+
const currentSpaceId = config.get("spaceId");
|
|
532
|
+
|
|
533
|
+
if (options.json) {
|
|
534
|
+
console.log(JSON.stringify(data, null, 2));
|
|
535
|
+
} else {
|
|
536
|
+
console.log(chalk.bold("\nSpaces:\n"));
|
|
537
|
+
if (data.spaces.length === 0) {
|
|
538
|
+
console.log(" No spaces found.");
|
|
539
|
+
} else {
|
|
540
|
+
for (const space of data.spaces) {
|
|
541
|
+
const current = space.id === currentSpaceId ? chalk.green(" (current)") : "";
|
|
542
|
+
console.log(` ${space.name}${current}`);
|
|
543
|
+
console.log(chalk.gray(` ID: ${space.id}`));
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
console.log("");
|
|
547
|
+
}
|
|
548
|
+
} catch (error) {
|
|
549
|
+
console.error(chalk.red(`Error: ${error.message}`));
|
|
550
|
+
process.exit(1);
|
|
551
|
+
}
|
|
552
|
+
});
|
|
553
|
+
|
|
554
|
+
// ============================================================================
|
|
555
|
+
// Project Commands
|
|
556
|
+
// ============================================================================
|
|
557
|
+
|
|
558
|
+
const projectCmd = program.command("project").description("Manage projects");
|
|
559
|
+
|
|
560
|
+
projectCmd
|
|
561
|
+
.command("list")
|
|
562
|
+
.description("List your projects")
|
|
563
|
+
.option("-s, --space <space-id>", "Filter by space ID")
|
|
564
|
+
.option("-j, --json", "Output as JSON")
|
|
565
|
+
.action(async (options) => {
|
|
566
|
+
try {
|
|
567
|
+
const params = {};
|
|
568
|
+
if (options.space) params.space_id = options.space;
|
|
569
|
+
|
|
570
|
+
const data = await api.listProjects(params);
|
|
571
|
+
const currentProjectId = config.get("projectId");
|
|
572
|
+
|
|
573
|
+
if (options.json) {
|
|
574
|
+
console.log(JSON.stringify(data, null, 2));
|
|
575
|
+
} else {
|
|
576
|
+
console.log(chalk.bold("\nProjects:\n"));
|
|
577
|
+
if (data.projects.length === 0) {
|
|
578
|
+
console.log(" No projects found.");
|
|
579
|
+
} else {
|
|
580
|
+
for (const project of data.projects) {
|
|
581
|
+
const current = project.id === currentProjectId ? chalk.green(" (current)") : "";
|
|
582
|
+
console.log(` ${project.name}${current}`);
|
|
583
|
+
console.log(chalk.gray(` ID: ${project.id}`));
|
|
584
|
+
if (project.space_name) {
|
|
585
|
+
console.log(chalk.gray(` Space: ${project.space_name}`));
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
console.log("");
|
|
590
|
+
if (!currentProjectId) {
|
|
591
|
+
console.log(chalk.yellow("No default project set. Use: 1m config set project <project-id>"));
|
|
592
|
+
console.log("");
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
} catch (error) {
|
|
596
|
+
console.error(chalk.red(`Error: ${error.message}`));
|
|
597
|
+
process.exit(1);
|
|
598
|
+
}
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
projectCmd
|
|
602
|
+
.command("add")
|
|
603
|
+
.description("Create a new project")
|
|
604
|
+
.requiredOption("-n, --name <name>", "Project name (min 2 characters)")
|
|
605
|
+
.option("-s, --space <space-id>", "Space ID to put the project in")
|
|
606
|
+
.option("-j, --json", "Output as JSON")
|
|
607
|
+
.action(async (options) => {
|
|
608
|
+
try {
|
|
609
|
+
const payload = { name: options.name };
|
|
610
|
+
if (options.space) payload.space_id = options.space;
|
|
611
|
+
|
|
612
|
+
const data = await api.createProject(payload);
|
|
613
|
+
|
|
614
|
+
if (options.json) {
|
|
615
|
+
console.log(JSON.stringify(data, null, 2));
|
|
616
|
+
} else {
|
|
617
|
+
console.log(chalk.green("Project created:"));
|
|
618
|
+
console.log(` ID: ${data.project.id}`);
|
|
619
|
+
console.log(` Name: ${data.project.name}`);
|
|
620
|
+
if (data.project.space_name) {
|
|
621
|
+
console.log(` Space: ${data.project.space_name}`);
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
} catch (error) {
|
|
625
|
+
console.error(chalk.red(`Error: ${error.message}`));
|
|
626
|
+
process.exit(1);
|
|
627
|
+
}
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
projectCmd
|
|
631
|
+
.command("update <id>")
|
|
632
|
+
.description("Update a project")
|
|
633
|
+
.option("-n, --name <name>", "New project name")
|
|
634
|
+
.option("-s, --space <space-id>", "Move to a different space")
|
|
635
|
+
.option("-j, --json", "Output as JSON")
|
|
636
|
+
.action(async (id, options) => {
|
|
637
|
+
try {
|
|
638
|
+
const payload = {};
|
|
639
|
+
if (options.name) payload.name = options.name;
|
|
640
|
+
if (options.space !== undefined) payload.space_id = options.space;
|
|
641
|
+
|
|
642
|
+
const data = await api.updateProject(id, payload);
|
|
643
|
+
|
|
644
|
+
if (options.json) {
|
|
645
|
+
console.log(JSON.stringify(data, null, 2));
|
|
646
|
+
} else {
|
|
647
|
+
console.log(chalk.green("Project updated:"));
|
|
648
|
+
console.log(` ID: ${data.project.id}`);
|
|
649
|
+
console.log(` Name: ${data.project.name}`);
|
|
650
|
+
if (data.project.space_name) {
|
|
651
|
+
console.log(` Space: ${data.project.space_name}`);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
} catch (error) {
|
|
655
|
+
console.error(chalk.red(`Error: ${error.message}`));
|
|
656
|
+
process.exit(1);
|
|
657
|
+
}
|
|
658
|
+
});
|
|
659
|
+
|
|
660
|
+
projectCmd
|
|
661
|
+
.command("delete <id>")
|
|
662
|
+
.description("Delete a project (must be empty)")
|
|
663
|
+
.option("-j, --json", "Output as JSON")
|
|
664
|
+
.action(async (id, options) => {
|
|
665
|
+
try {
|
|
666
|
+
const data = await api.deleteProject(id);
|
|
667
|
+
|
|
668
|
+
if (options.json) {
|
|
669
|
+
console.log(JSON.stringify(data, null, 2));
|
|
670
|
+
} else {
|
|
671
|
+
console.log(chalk.green(`Project deleted: ${id}`));
|
|
672
|
+
}
|
|
673
|
+
} catch (error) {
|
|
674
|
+
console.error(chalk.red(`Error: ${error.message}`));
|
|
675
|
+
process.exit(1);
|
|
676
|
+
}
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
// Alias: `1m projects` -> `1m project list`
|
|
680
|
+
program
|
|
681
|
+
.command("projects")
|
|
682
|
+
.description("List your projects (alias for 'project list')")
|
|
683
|
+
.option("-s, --space <space-id>", "Filter by space ID")
|
|
684
|
+
.option("-j, --json", "Output as JSON")
|
|
685
|
+
.action(async (options) => {
|
|
686
|
+
try {
|
|
687
|
+
const params = {};
|
|
688
|
+
if (options.space) params.space_id = options.space;
|
|
689
|
+
|
|
690
|
+
const data = await api.listProjects(params);
|
|
691
|
+
const currentProjectId = config.get("projectId");
|
|
692
|
+
|
|
693
|
+
if (options.json) {
|
|
694
|
+
console.log(JSON.stringify(data, null, 2));
|
|
695
|
+
} else {
|
|
696
|
+
console.log(chalk.bold("\nProjects:\n"));
|
|
697
|
+
if (data.projects.length === 0) {
|
|
698
|
+
console.log(" No projects found.");
|
|
699
|
+
} else {
|
|
700
|
+
for (const project of data.projects) {
|
|
701
|
+
const current = project.id === currentProjectId ? chalk.green(" (current)") : "";
|
|
702
|
+
console.log(` ${project.name}${current}`);
|
|
703
|
+
console.log(chalk.gray(` ID: ${project.id}`));
|
|
704
|
+
if (project.space_name) {
|
|
705
|
+
console.log(chalk.gray(` Space: ${project.space_name}`));
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
console.log("");
|
|
710
|
+
}
|
|
711
|
+
} catch (error) {
|
|
712
|
+
console.error(chalk.red(`Error: ${error.message}`));
|
|
713
|
+
process.exit(1);
|
|
714
|
+
}
|
|
715
|
+
});
|
|
716
|
+
|
|
409
717
|
// ============================================================================
|
|
410
718
|
// Config Commands
|
|
411
719
|
// ============================================================================
|
|
@@ -420,11 +728,17 @@ configCmd
|
|
|
420
728
|
const apiUrl = config.get("apiUrl");
|
|
421
729
|
const orgId = config.get("orgId");
|
|
422
730
|
const orgName = config.get("orgName");
|
|
731
|
+
const spaceId = config.get("spaceId");
|
|
732
|
+
const spaceName = config.get("spaceName");
|
|
733
|
+
const projectId = config.get("projectId");
|
|
734
|
+
const projectName = config.get("projectName");
|
|
423
735
|
|
|
424
736
|
console.log(chalk.bold("\nConfiguration:\n"));
|
|
425
737
|
console.log(` API URL: ${apiUrl || "https://1medium.ai/api (default)"}`);
|
|
426
738
|
console.log(` Token: ${token ? token.substring(0, 12) + "..." : chalk.yellow("Not set")}`);
|
|
427
739
|
console.log(` Org: ${orgName || chalk.yellow("Not set")}${orgId ? chalk.gray(` (${orgId})`) : ""}`);
|
|
740
|
+
console.log(` Space: ${spaceName || chalk.yellow("Not set")}${spaceId ? chalk.gray(` (${spaceId})`) : ""}`);
|
|
741
|
+
console.log(` Project: ${projectName || chalk.yellow("Not set")}${projectId ? chalk.gray(` (${projectId})`) : ""}`);
|
|
428
742
|
console.log(` Config: ${config.path}`);
|
|
429
743
|
console.log("");
|
|
430
744
|
});
|
|
@@ -432,12 +746,12 @@ configCmd
|
|
|
432
746
|
configCmd
|
|
433
747
|
.command("set")
|
|
434
748
|
.description("Set a configuration value")
|
|
435
|
-
.argument("<key>", "Configuration key (org, url)")
|
|
749
|
+
.argument("<key>", "Configuration key (org, space, project, url)")
|
|
436
750
|
.argument("<value>", "Configuration value")
|
|
437
751
|
.action(async (key, value) => {
|
|
438
752
|
try {
|
|
439
753
|
switch (key) {
|
|
440
|
-
case "org":
|
|
754
|
+
case "org": {
|
|
441
755
|
// Validate org exists and user has access
|
|
442
756
|
const data = await api.listOrgs();
|
|
443
757
|
const org = data.orgs.find((o) => o.id === value || o.name.toLowerCase() === value.toLowerCase());
|
|
@@ -453,13 +767,48 @@ configCmd
|
|
|
453
767
|
config.set("orgName", org.name);
|
|
454
768
|
console.log(chalk.green(`Default org set to: ${org.name}`));
|
|
455
769
|
break;
|
|
770
|
+
}
|
|
771
|
+
case "space": {
|
|
772
|
+
// Validate space exists and user has access
|
|
773
|
+
const spaceData = await api.listSpaces();
|
|
774
|
+
const space = spaceData.spaces.find((s) => s.id === value || s.name.toLowerCase() === value.toLowerCase());
|
|
775
|
+
if (!space) {
|
|
776
|
+
console.error(chalk.red(`Error: Space not found: ${value}`));
|
|
777
|
+
console.log("\nAvailable spaces:");
|
|
778
|
+
for (const s of spaceData.spaces) {
|
|
779
|
+
console.log(` ${s.name} (${s.id})`);
|
|
780
|
+
}
|
|
781
|
+
process.exit(1);
|
|
782
|
+
}
|
|
783
|
+
config.set("spaceId", space.id);
|
|
784
|
+
config.set("spaceName", space.name);
|
|
785
|
+
console.log(chalk.green(`Default space set to: ${space.name}`));
|
|
786
|
+
break;
|
|
787
|
+
}
|
|
788
|
+
case "project": {
|
|
789
|
+
// Validate project exists and user has access
|
|
790
|
+
const projectData = await api.listProjects();
|
|
791
|
+
const project = projectData.projects.find((p) => p.id === value || p.name.toLowerCase() === value.toLowerCase());
|
|
792
|
+
if (!project) {
|
|
793
|
+
console.error(chalk.red(`Error: Project not found: ${value}`));
|
|
794
|
+
console.log("\nAvailable projects:");
|
|
795
|
+
for (const p of projectData.projects) {
|
|
796
|
+
console.log(` ${p.name} (${p.id})`);
|
|
797
|
+
}
|
|
798
|
+
process.exit(1);
|
|
799
|
+
}
|
|
800
|
+
config.set("projectId", project.id);
|
|
801
|
+
config.set("projectName", project.name);
|
|
802
|
+
console.log(chalk.green(`Default project set to: ${project.name}`));
|
|
803
|
+
break;
|
|
804
|
+
}
|
|
456
805
|
case "url":
|
|
457
806
|
config.set("apiUrl", value);
|
|
458
807
|
console.log(chalk.green(`API URL set to: ${value}`));
|
|
459
808
|
break;
|
|
460
809
|
default:
|
|
461
810
|
console.error(chalk.red(`Unknown config key: ${key}`));
|
|
462
|
-
console.log("Available keys: org, url");
|
|
811
|
+
console.log("Available keys: org, space, project, url");
|
|
463
812
|
process.exit(1);
|
|
464
813
|
}
|
|
465
814
|
} catch (error) {
|
|
@@ -474,11 +823,17 @@ configCmd.action(() => {
|
|
|
474
823
|
const apiUrl = config.get("apiUrl");
|
|
475
824
|
const orgId = config.get("orgId");
|
|
476
825
|
const orgName = config.get("orgName");
|
|
826
|
+
const spaceId = config.get("spaceId");
|
|
827
|
+
const spaceName = config.get("spaceName");
|
|
828
|
+
const projectId = config.get("projectId");
|
|
829
|
+
const projectName = config.get("projectName");
|
|
477
830
|
|
|
478
831
|
console.log(chalk.bold("\nConfiguration:\n"));
|
|
479
832
|
console.log(` API URL: ${apiUrl || "https://1medium.ai/api (default)"}`);
|
|
480
833
|
console.log(` Token: ${token ? token.substring(0, 12) + "..." : chalk.yellow("Not set")}`);
|
|
481
834
|
console.log(` Org: ${orgName || chalk.yellow("Not set")}${orgId ? chalk.gray(` (${orgId})`) : ""}`);
|
|
835
|
+
console.log(` Space: ${spaceName || chalk.yellow("Not set")}${spaceId ? chalk.gray(` (${spaceId})`) : ""}`);
|
|
836
|
+
console.log(` Project: ${projectName || chalk.yellow("Not set")}${projectId ? chalk.gray(` (${projectId})`) : ""}`);
|
|
482
837
|
console.log(` Config: ${config.path}`);
|
|
483
838
|
console.log("");
|
|
484
839
|
});
|
package/src/mcp-server.js
CHANGED
|
@@ -26,6 +26,40 @@ const server = new Server(
|
|
|
26
26
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
27
27
|
return {
|
|
28
28
|
tools: [
|
|
29
|
+
{
|
|
30
|
+
name: "org_list",
|
|
31
|
+
description: "List available organizations. Use this to see which orgs you can switch to.",
|
|
32
|
+
inputSchema: {
|
|
33
|
+
type: "object",
|
|
34
|
+
properties: {},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: "org_set",
|
|
39
|
+
description: "Set the active organization for subsequent operations. Use org_list to see available orgs.",
|
|
40
|
+
inputSchema: {
|
|
41
|
+
type: "object",
|
|
42
|
+
properties: {
|
|
43
|
+
id: {
|
|
44
|
+
type: "string",
|
|
45
|
+
description: "Organization ID to set as active",
|
|
46
|
+
},
|
|
47
|
+
name: {
|
|
48
|
+
type: "string",
|
|
49
|
+
description: "Organization name (for display purposes)",
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
required: ["id"],
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: "org_get",
|
|
57
|
+
description: "Get the currently active organization",
|
|
58
|
+
inputSchema: {
|
|
59
|
+
type: "object",
|
|
60
|
+
properties: {},
|
|
61
|
+
},
|
|
62
|
+
},
|
|
29
63
|
{
|
|
30
64
|
name: "task_create",
|
|
31
65
|
description: "Create a new task in 1Medium. Use this to track work items, todos, or any actionable items.",
|
|
@@ -45,6 +79,10 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
45
79
|
enum: ["P1", "P2", "P3", "P4"],
|
|
46
80
|
description: "Task priority (P1=urgent, P4=low)",
|
|
47
81
|
},
|
|
82
|
+
project_id: {
|
|
83
|
+
type: "string",
|
|
84
|
+
description: "Project ID to associate the task with. Uses configured default if not specified.",
|
|
85
|
+
},
|
|
48
86
|
source: {
|
|
49
87
|
type: "string",
|
|
50
88
|
description: "Source identifier (e.g., 'claude-code', 'github')",
|
|
@@ -157,6 +195,179 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
157
195
|
required: ["id", "message"],
|
|
158
196
|
},
|
|
159
197
|
},
|
|
198
|
+
{
|
|
199
|
+
name: "space_list",
|
|
200
|
+
description: "List available spaces (top-level groups) in 1Medium",
|
|
201
|
+
inputSchema: {
|
|
202
|
+
type: "object",
|
|
203
|
+
properties: {},
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
name: "space_set",
|
|
208
|
+
description: "Set the active space for subsequent operations. Use space_list to see available spaces.",
|
|
209
|
+
inputSchema: {
|
|
210
|
+
type: "object",
|
|
211
|
+
properties: {
|
|
212
|
+
id: {
|
|
213
|
+
type: "string",
|
|
214
|
+
description: "Space ID to set as active",
|
|
215
|
+
},
|
|
216
|
+
name: {
|
|
217
|
+
type: "string",
|
|
218
|
+
description: "Space name (for display purposes)",
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
required: ["id"],
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
name: "space_get",
|
|
226
|
+
description: "Get the currently active space",
|
|
227
|
+
inputSchema: {
|
|
228
|
+
type: "object",
|
|
229
|
+
properties: {},
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
name: "space_create",
|
|
234
|
+
description: "Create a new space (top-level group) in 1Medium",
|
|
235
|
+
inputSchema: {
|
|
236
|
+
type: "object",
|
|
237
|
+
properties: {
|
|
238
|
+
name: {
|
|
239
|
+
type: "string",
|
|
240
|
+
description: "Name for the new space (min 2 characters)",
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
required: ["name"],
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
name: "space_update",
|
|
248
|
+
description: "Update an existing space",
|
|
249
|
+
inputSchema: {
|
|
250
|
+
type: "object",
|
|
251
|
+
properties: {
|
|
252
|
+
id: {
|
|
253
|
+
type: "string",
|
|
254
|
+
description: "Space ID to update",
|
|
255
|
+
},
|
|
256
|
+
name: {
|
|
257
|
+
type: "string",
|
|
258
|
+
description: "New name for the space",
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
required: ["id"],
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
name: "space_delete",
|
|
266
|
+
description: "Delete a space (must be empty)",
|
|
267
|
+
inputSchema: {
|
|
268
|
+
type: "object",
|
|
269
|
+
properties: {
|
|
270
|
+
id: {
|
|
271
|
+
type: "string",
|
|
272
|
+
description: "Space ID to delete",
|
|
273
|
+
},
|
|
274
|
+
},
|
|
275
|
+
required: ["id"],
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
name: "project_list",
|
|
280
|
+
description: "List available projects in 1Medium, optionally filtered by space",
|
|
281
|
+
inputSchema: {
|
|
282
|
+
type: "object",
|
|
283
|
+
properties: {
|
|
284
|
+
space_id: {
|
|
285
|
+
type: "string",
|
|
286
|
+
description: "Optional space ID to filter projects",
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
name: "project_set",
|
|
293
|
+
description: "Set the active project for subsequent task operations. New tasks will be created in this project by default.",
|
|
294
|
+
inputSchema: {
|
|
295
|
+
type: "object",
|
|
296
|
+
properties: {
|
|
297
|
+
id: {
|
|
298
|
+
type: "string",
|
|
299
|
+
description: "Project ID to set as active",
|
|
300
|
+
},
|
|
301
|
+
name: {
|
|
302
|
+
type: "string",
|
|
303
|
+
description: "Project name (for display purposes)",
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
required: ["id"],
|
|
307
|
+
},
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
name: "project_get",
|
|
311
|
+
description: "Get the currently active project",
|
|
312
|
+
inputSchema: {
|
|
313
|
+
type: "object",
|
|
314
|
+
properties: {},
|
|
315
|
+
},
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
name: "project_create",
|
|
319
|
+
description: "Create a new project in 1Medium",
|
|
320
|
+
inputSchema: {
|
|
321
|
+
type: "object",
|
|
322
|
+
properties: {
|
|
323
|
+
name: {
|
|
324
|
+
type: "string",
|
|
325
|
+
description: "Name for the new project (min 2 characters)",
|
|
326
|
+
},
|
|
327
|
+
space_id: {
|
|
328
|
+
type: "string",
|
|
329
|
+
description: "Optional space ID to put the project in",
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
required: ["name"],
|
|
333
|
+
},
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
name: "project_update",
|
|
337
|
+
description: "Update an existing project",
|
|
338
|
+
inputSchema: {
|
|
339
|
+
type: "object",
|
|
340
|
+
properties: {
|
|
341
|
+
id: {
|
|
342
|
+
type: "string",
|
|
343
|
+
description: "Project ID to update",
|
|
344
|
+
},
|
|
345
|
+
name: {
|
|
346
|
+
type: "string",
|
|
347
|
+
description: "New name for the project",
|
|
348
|
+
},
|
|
349
|
+
space_id: {
|
|
350
|
+
type: "string",
|
|
351
|
+
description: "Move project to a different space (or null to remove from space)",
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
required: ["id"],
|
|
355
|
+
},
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
name: "project_delete",
|
|
359
|
+
description: "Delete a project (must be empty)",
|
|
360
|
+
inputSchema: {
|
|
361
|
+
type: "object",
|
|
362
|
+
properties: {
|
|
363
|
+
id: {
|
|
364
|
+
type: "string",
|
|
365
|
+
description: "Project ID to delete",
|
|
366
|
+
},
|
|
367
|
+
},
|
|
368
|
+
required: ["id"],
|
|
369
|
+
},
|
|
370
|
+
},
|
|
160
371
|
],
|
|
161
372
|
};
|
|
162
373
|
});
|
|
@@ -183,20 +394,91 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
183
394
|
let result;
|
|
184
395
|
|
|
185
396
|
switch (name) {
|
|
397
|
+
case "org_list": {
|
|
398
|
+
result = await api.listOrgs();
|
|
399
|
+
const orgs = result.orgs || [];
|
|
400
|
+
const currentOrgId = config.get("orgId");
|
|
401
|
+
|
|
402
|
+
if (orgs.length === 0) {
|
|
403
|
+
return {
|
|
404
|
+
content: [{ type: "text", text: "No organizations found." }],
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
const orgList = orgs
|
|
409
|
+
.map((o) => {
|
|
410
|
+
const current = o.id === currentOrgId ? " (active)" : "";
|
|
411
|
+
const personal = o.is_personal ? " [personal]" : "";
|
|
412
|
+
return `- ${o.name}${personal}${current}\n ID: ${o.id}`;
|
|
413
|
+
})
|
|
414
|
+
.join("\n\n");
|
|
415
|
+
|
|
416
|
+
return {
|
|
417
|
+
content: [
|
|
418
|
+
{
|
|
419
|
+
type: "text",
|
|
420
|
+
text: `Organizations:\n\n${orgList}`,
|
|
421
|
+
},
|
|
422
|
+
],
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
case "org_set": {
|
|
427
|
+
config.set("orgId", args.id);
|
|
428
|
+
if (args.name) {
|
|
429
|
+
config.set("orgName", args.name);
|
|
430
|
+
}
|
|
431
|
+
return {
|
|
432
|
+
content: [
|
|
433
|
+
{
|
|
434
|
+
type: "text",
|
|
435
|
+
text: `Active organization set:\n ID: ${args.id}${args.name ? `\n Name: ${args.name}` : ""}`,
|
|
436
|
+
},
|
|
437
|
+
],
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
case "org_get": {
|
|
442
|
+
const orgId = config.get("orgId");
|
|
443
|
+
const orgName = config.get("orgName");
|
|
444
|
+
|
|
445
|
+
if (!orgId) {
|
|
446
|
+
return {
|
|
447
|
+
content: [{ type: "text", text: "No active organization set. Use org_list and org_set to configure." }],
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
return {
|
|
452
|
+
content: [
|
|
453
|
+
{
|
|
454
|
+
type: "text",
|
|
455
|
+
text: `Active organization:\n ID: ${orgId}${orgName ? `\n Name: ${orgName}` : ""}`,
|
|
456
|
+
},
|
|
457
|
+
],
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
|
|
186
461
|
case "task_create": {
|
|
462
|
+
// Use provided project_id or fall back to configured default
|
|
463
|
+
const projectId = args.project_id || config.get("projectId") || null;
|
|
187
464
|
const payload = {
|
|
188
465
|
title: args.title,
|
|
189
466
|
body_md: args.body,
|
|
190
467
|
priority: args.priority || "P2",
|
|
191
468
|
source: args.source || "claude-code",
|
|
192
469
|
context: args.context || {},
|
|
470
|
+
project_id: projectId,
|
|
193
471
|
};
|
|
194
472
|
result = await api.createTask(payload);
|
|
473
|
+
let text = `Task created:\n ID: ${result.task.id}\n Title: ${result.task.title}\n Priority: ${result.task.priority}`;
|
|
474
|
+
if (result.task.project_name) {
|
|
475
|
+
text += `\n Project: ${result.task.project_name}`;
|
|
476
|
+
}
|
|
195
477
|
return {
|
|
196
478
|
content: [
|
|
197
479
|
{
|
|
198
480
|
type: "text",
|
|
199
|
-
text
|
|
481
|
+
text,
|
|
200
482
|
},
|
|
201
483
|
],
|
|
202
484
|
};
|
|
@@ -276,7 +558,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
276
558
|
|
|
277
559
|
case "task_complete": {
|
|
278
560
|
const payload = {};
|
|
279
|
-
if (args.summary) payload.
|
|
561
|
+
if (args.summary) payload.summary_md = args.summary;
|
|
280
562
|
|
|
281
563
|
result = await api.completeTask(args.id, payload);
|
|
282
564
|
return {
|
|
@@ -290,7 +572,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
290
572
|
}
|
|
291
573
|
|
|
292
574
|
case "task_comment": {
|
|
293
|
-
result = await api.addComment(args.id, {
|
|
575
|
+
result = await api.addComment(args.id, { comment_md: args.message });
|
|
294
576
|
return {
|
|
295
577
|
content: [
|
|
296
578
|
{
|
|
@@ -301,6 +583,226 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
301
583
|
};
|
|
302
584
|
}
|
|
303
585
|
|
|
586
|
+
case "space_list": {
|
|
587
|
+
result = await api.listSpaces();
|
|
588
|
+
const spaces = result.spaces || [];
|
|
589
|
+
const currentSpaceId = config.get("spaceId");
|
|
590
|
+
|
|
591
|
+
if (spaces.length === 0) {
|
|
592
|
+
return {
|
|
593
|
+
content: [{ type: "text", text: "No spaces found." }],
|
|
594
|
+
};
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
const spaceList = spaces
|
|
598
|
+
.map((s) => {
|
|
599
|
+
const current = s.id === currentSpaceId ? " (active)" : "";
|
|
600
|
+
return `- ${s.name}${current}\n ID: ${s.id}`;
|
|
601
|
+
})
|
|
602
|
+
.join("\n\n");
|
|
603
|
+
|
|
604
|
+
return {
|
|
605
|
+
content: [
|
|
606
|
+
{
|
|
607
|
+
type: "text",
|
|
608
|
+
text: `Spaces:\n\n${spaceList}`,
|
|
609
|
+
},
|
|
610
|
+
],
|
|
611
|
+
};
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
case "space_set": {
|
|
615
|
+
config.set("spaceId", args.id);
|
|
616
|
+
if (args.name) {
|
|
617
|
+
config.set("spaceName", args.name);
|
|
618
|
+
}
|
|
619
|
+
return {
|
|
620
|
+
content: [
|
|
621
|
+
{
|
|
622
|
+
type: "text",
|
|
623
|
+
text: `Active space set:\n ID: ${args.id}${args.name ? `\n Name: ${args.name}` : ""}`,
|
|
624
|
+
},
|
|
625
|
+
],
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
case "space_get": {
|
|
630
|
+
const spaceId = config.get("spaceId");
|
|
631
|
+
const spaceName = config.get("spaceName");
|
|
632
|
+
|
|
633
|
+
if (!spaceId) {
|
|
634
|
+
return {
|
|
635
|
+
content: [{ type: "text", text: "No active space set. Use space_list and space_set to configure." }],
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
return {
|
|
640
|
+
content: [
|
|
641
|
+
{
|
|
642
|
+
type: "text",
|
|
643
|
+
text: `Active space:\n ID: ${spaceId}${spaceName ? `\n Name: ${spaceName}` : ""}`,
|
|
644
|
+
},
|
|
645
|
+
],
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
case "project_list": {
|
|
650
|
+
const params = {};
|
|
651
|
+
if (args.space_id) params.space_id = args.space_id;
|
|
652
|
+
|
|
653
|
+
result = await api.listProjects(params);
|
|
654
|
+
const projects = result.projects || [];
|
|
655
|
+
const currentProjectId = config.get("projectId");
|
|
656
|
+
|
|
657
|
+
if (projects.length === 0) {
|
|
658
|
+
return {
|
|
659
|
+
content: [{ type: "text", text: "No projects found." }],
|
|
660
|
+
};
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
const projectList = projects
|
|
664
|
+
.map((p) => {
|
|
665
|
+
const current = p.id === currentProjectId ? " (active)" : "";
|
|
666
|
+
let text = `- ${p.name}${current}\n ID: ${p.id}`;
|
|
667
|
+
if (p.space_name) {
|
|
668
|
+
text += `\n Space: ${p.space_name}`;
|
|
669
|
+
}
|
|
670
|
+
return text;
|
|
671
|
+
})
|
|
672
|
+
.join("\n\n");
|
|
673
|
+
|
|
674
|
+
return {
|
|
675
|
+
content: [
|
|
676
|
+
{
|
|
677
|
+
type: "text",
|
|
678
|
+
text: `Projects:\n\n${projectList}`,
|
|
679
|
+
},
|
|
680
|
+
],
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
case "project_set": {
|
|
685
|
+
config.set("projectId", args.id);
|
|
686
|
+
if (args.name) {
|
|
687
|
+
config.set("projectName", args.name);
|
|
688
|
+
}
|
|
689
|
+
return {
|
|
690
|
+
content: [
|
|
691
|
+
{
|
|
692
|
+
type: "text",
|
|
693
|
+
text: `Active project set:\n ID: ${args.id}${args.name ? `\n Name: ${args.name}` : ""}\n\nNew tasks will be created in this project by default.`,
|
|
694
|
+
},
|
|
695
|
+
],
|
|
696
|
+
};
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
case "project_get": {
|
|
700
|
+
const projectId = config.get("projectId");
|
|
701
|
+
const projectName = config.get("projectName");
|
|
702
|
+
|
|
703
|
+
if (!projectId) {
|
|
704
|
+
return {
|
|
705
|
+
content: [{ type: "text", text: "No active project set. Use project_list and project_set to configure." }],
|
|
706
|
+
};
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
return {
|
|
710
|
+
content: [
|
|
711
|
+
{
|
|
712
|
+
type: "text",
|
|
713
|
+
text: `Active project:\n ID: ${projectId}${projectName ? `\n Name: ${projectName}` : ""}`,
|
|
714
|
+
},
|
|
715
|
+
],
|
|
716
|
+
};
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
case "space_create": {
|
|
720
|
+
result = await api.createSpace({ name: args.name });
|
|
721
|
+
return {
|
|
722
|
+
content: [
|
|
723
|
+
{
|
|
724
|
+
type: "text",
|
|
725
|
+
text: `Space created:\n ID: ${result.space.id}\n Name: ${result.space.name}`,
|
|
726
|
+
},
|
|
727
|
+
],
|
|
728
|
+
};
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
case "space_update": {
|
|
732
|
+
const payload = {};
|
|
733
|
+
if (args.name) payload.name = args.name;
|
|
734
|
+
result = await api.updateSpace(args.id, payload);
|
|
735
|
+
return {
|
|
736
|
+
content: [
|
|
737
|
+
{
|
|
738
|
+
type: "text",
|
|
739
|
+
text: `Space updated:\n ID: ${result.space.id}\n Name: ${result.space.name}`,
|
|
740
|
+
},
|
|
741
|
+
],
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
case "space_delete": {
|
|
746
|
+
result = await api.deleteSpace(args.id);
|
|
747
|
+
return {
|
|
748
|
+
content: [
|
|
749
|
+
{
|
|
750
|
+
type: "text",
|
|
751
|
+
text: `Space deleted: ${args.id}`,
|
|
752
|
+
},
|
|
753
|
+
],
|
|
754
|
+
};
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
case "project_create": {
|
|
758
|
+
const payload = { name: args.name };
|
|
759
|
+
if (args.space_id) payload.space_id = args.space_id;
|
|
760
|
+
result = await api.createProject(payload);
|
|
761
|
+
let text = `Project created:\n ID: ${result.project.id}\n Name: ${result.project.name}`;
|
|
762
|
+
if (result.project.space_name) {
|
|
763
|
+
text += `\n Space: ${result.project.space_name}`;
|
|
764
|
+
}
|
|
765
|
+
return {
|
|
766
|
+
content: [
|
|
767
|
+
{
|
|
768
|
+
type: "text",
|
|
769
|
+
text,
|
|
770
|
+
},
|
|
771
|
+
],
|
|
772
|
+
};
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
case "project_update": {
|
|
776
|
+
const payload = {};
|
|
777
|
+
if (args.name) payload.name = args.name;
|
|
778
|
+
if (args.space_id !== undefined) payload.space_id = args.space_id;
|
|
779
|
+
result = await api.updateProject(args.id, payload);
|
|
780
|
+
let text = `Project updated:\n ID: ${result.project.id}\n Name: ${result.project.name}`;
|
|
781
|
+
if (result.project.space_name) {
|
|
782
|
+
text += `\n Space: ${result.project.space_name}`;
|
|
783
|
+
}
|
|
784
|
+
return {
|
|
785
|
+
content: [
|
|
786
|
+
{
|
|
787
|
+
type: "text",
|
|
788
|
+
text,
|
|
789
|
+
},
|
|
790
|
+
],
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
case "project_delete": {
|
|
795
|
+
result = await api.deleteProject(args.id);
|
|
796
|
+
return {
|
|
797
|
+
content: [
|
|
798
|
+
{
|
|
799
|
+
type: "text",
|
|
800
|
+
text: `Project deleted: ${args.id}`,
|
|
801
|
+
},
|
|
802
|
+
],
|
|
803
|
+
};
|
|
804
|
+
}
|
|
805
|
+
|
|
304
806
|
default:
|
|
305
807
|
return {
|
|
306
808
|
content: [{ type: "text", text: `Unknown tool: ${name}` }],
|