@1medium/cli 1.1.0 → 1.3.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1medium/cli",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "CLI and MCP server for 1Medium AI task management",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/api.js CHANGED
@@ -23,12 +23,30 @@ function getToken() {
23
23
  return token;
24
24
  }
25
25
 
26
+ /**
27
+ * Get configured org ID (if any)
28
+ */
29
+ function getOrgId() {
30
+ return config.get("orgId") || null;
31
+ }
32
+
26
33
  /**
27
34
  * Make an authenticated API request
35
+ * Automatically includes org_id if configured
28
36
  */
29
37
  async function request(method, path, body = null, params = null) {
30
38
  const baseUrl = getApiUrl();
31
39
  const token = getToken();
40
+ const orgId = getOrgId();
41
+
42
+ // Add org_id to params for GET requests, or to body for POST/PATCH
43
+ if (orgId) {
44
+ if (method === "GET" || method === "DELETE") {
45
+ params = { ...params, org_id: orgId };
46
+ } else if (method === "POST" || method === "PATCH" || method === "PUT") {
47
+ body = { ...(body || {}), org_id: orgId };
48
+ }
49
+ }
32
50
 
33
51
  let url = `${baseUrl}/v1/agent${path}`;
34
52
  if (params) {
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.",
@@ -169,6 +203,32 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
169
203
  properties: {},
170
204
  },
171
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
+ },
172
232
  {
173
233
  name: "space_create",
174
234
  description: "Create a new space (top-level group) in 1Medium",
@@ -228,6 +288,32 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
228
288
  },
229
289
  },
230
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
+ },
231
317
  {
232
318
  name: "project_create",
233
319
  description: "Create a new project in 1Medium",
@@ -308,6 +394,70 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
308
394
  let result;
309
395
 
310
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
+
311
461
  case "task_create": {
312
462
  // Use provided project_id or fall back to configured default
313
463
  const projectId = args.project_id || config.get("projectId") || null;
@@ -436,6 +586,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
436
586
  case "space_list": {
437
587
  result = await api.listSpaces();
438
588
  const spaces = result.spaces || [];
589
+ const currentSpaceId = config.get("spaceId");
439
590
 
440
591
  if (spaces.length === 0) {
441
592
  return {
@@ -444,7 +595,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
444
595
  }
445
596
 
446
597
  const spaceList = spaces
447
- .map((s) => `- ${s.name}\n ID: ${s.id}`)
598
+ .map((s) => {
599
+ const current = s.id === currentSpaceId ? " (active)" : "";
600
+ return `- ${s.name}${current}\n ID: ${s.id}`;
601
+ })
448
602
  .join("\n\n");
449
603
 
450
604
  return {
@@ -457,12 +611,48 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
457
611
  };
458
612
  }
459
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
+
460
649
  case "project_list": {
461
650
  const params = {};
462
651
  if (args.space_id) params.space_id = args.space_id;
463
652
 
464
653
  result = await api.listProjects(params);
465
654
  const projects = result.projects || [];
655
+ const currentProjectId = config.get("projectId");
466
656
 
467
657
  if (projects.length === 0) {
468
658
  return {
@@ -472,7 +662,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
472
662
 
473
663
  const projectList = projects
474
664
  .map((p) => {
475
- let text = `- ${p.name}\n ID: ${p.id}`;
665
+ const current = p.id === currentProjectId ? " (active)" : "";
666
+ let text = `- ${p.name}${current}\n ID: ${p.id}`;
476
667
  if (p.space_name) {
477
668
  text += `\n Space: ${p.space_name}`;
478
669
  }
@@ -490,6 +681,41 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
490
681
  };
491
682
  }
492
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
+
493
719
  case "space_create": {
494
720
  result = await api.createSpace({ name: args.name });
495
721
  return {