@1medium/cli 1.4.0 → 1.7.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.4.0",
3
+ "version": "1.7.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
@@ -145,6 +145,13 @@ async function listOrgs() {
145
145
  return request("GET", "/orgs");
146
146
  }
147
147
 
148
+ /**
149
+ * Update an organization
150
+ */
151
+ async function updateOrg(id, payload) {
152
+ return request("PATCH", `/orgs/${id}`, payload);
153
+ }
154
+
148
155
  /**
149
156
  * List spaces (top-level priority groups)
150
157
  */
@@ -210,6 +217,7 @@ module.exports = {
210
217
  addComment,
211
218
  completeTask,
212
219
  listOrgs,
220
+ updateOrg,
213
221
  listSpaces,
214
222
  createSpace,
215
223
  updateSpace,
package/src/mcp-server.js CHANGED
@@ -54,12 +54,30 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
54
54
  },
55
55
  {
56
56
  name: "org_get",
57
- description: "Get the currently active organization",
57
+ description: "Get the currently active organization. NOTE: Sessions start with NO org selected to prevent cross-contamination between terminals. Use org_list and org_set first, or config_reset to load saved defaults.",
58
58
  inputSchema: {
59
59
  type: "object",
60
60
  properties: {},
61
61
  },
62
62
  },
63
+ {
64
+ name: "org_update",
65
+ description: "Rename an organization",
66
+ inputSchema: {
67
+ type: "object",
68
+ properties: {
69
+ id: {
70
+ type: "string",
71
+ description: "Organization ID to update",
72
+ },
73
+ name: {
74
+ type: "string",
75
+ description: "New name for the organization",
76
+ },
77
+ },
78
+ required: ["id", "name"],
79
+ },
80
+ },
63
81
  {
64
82
  name: "task_create",
65
83
  description: "Create a new task in 1Medium. Use this to track work items, todos, or any actionable items.",
@@ -142,7 +160,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
142
160
  },
143
161
  {
144
162
  name: "task_update",
145
- description: "Update an existing task",
163
+ description: "Update an existing task. Can also move task to a different project.",
146
164
  inputSchema: {
147
165
  type: "object",
148
166
  properties: {
@@ -163,6 +181,10 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
163
181
  enum: ["P1", "P2", "P3", "P4"],
164
182
  description: "New priority",
165
183
  },
184
+ project_id: {
185
+ type: "string",
186
+ description: "Move task to a different project (provide project ID)",
187
+ },
166
188
  },
167
189
  required: ["id"],
168
190
  },
@@ -482,6 +504,22 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
482
504
  };
483
505
  }
484
506
 
507
+ case "org_update": {
508
+ result = await api.updateOrg(args.id, { name: args.name });
509
+ // Update session state if this is the active org
510
+ if (sessionState.get("orgId") === args.id) {
511
+ sessionState.set("orgName", result.org.name);
512
+ }
513
+ return {
514
+ content: [
515
+ {
516
+ type: "text",
517
+ text: `Organization renamed:\n ID: ${result.org.id}\n Name: ${result.org.name}`,
518
+ },
519
+ ],
520
+ };
521
+ }
522
+
485
523
  case "task_create": {
486
524
  // Use provided project_id or fall back to configured default
487
525
  const projectId = args.project_id || sessionState.get("projectId") || null;
@@ -584,13 +622,15 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
584
622
  if (args.title) payload.title = args.title;
585
623
  if (args.body) payload.body_md = args.body;
586
624
  if (args.priority) payload.priority = args.priority;
625
+ if (args.project_id) payload.project_id = args.project_id;
587
626
 
588
627
  result = await api.updateTask(args.id, payload);
628
+ const movedMsg = args.project_id ? `\n Moved to project: ${args.project_id}` : "";
589
629
  return {
590
630
  content: [
591
631
  {
592
632
  type: "text",
593
- text: `Task updated:\n ID: ${result.task.id}\n Title: ${result.task.title}\n Priority: ${result.task.priority}`,
633
+ text: `Task updated:\n ID: ${result.task.id}\n Title: ${result.task.title}\n Priority: ${result.task.priority}${movedMsg}`,
594
634
  },
595
635
  ],
596
636
  };
@@ -4,10 +4,13 @@
4
4
  * Session-scoped state for MCP server
5
5
  *
6
6
  * This module wraps the persistent config with an in-memory layer for session-scoped keys.
7
- * Multiple Claude Code tabs can run separate MCP server processes without affecting each other's
8
- * org/space/project selections.
7
+ * Each Claude Code tab runs its own MCP server process with ISOLATED session state.
9
8
  *
10
- * Session-scoped keys (in-memory only):
9
+ * IMPORTANT: Session state starts EMPTY - no org/space/project is pre-selected.
10
+ * This prevents cross-contamination when working on multiple projects in different terminals.
11
+ * Use config_reset to load from persistent config if you want the saved defaults.
12
+ *
13
+ * Session-scoped keys (in-memory only, start empty):
11
14
  * - orgId, orgName, spaceId, spaceName, projectId, projectName
12
15
  *
13
16
  * Persistent keys (always read/write from config file):
@@ -26,14 +29,11 @@ const SESSION_KEYS = [
26
29
  "projectName",
27
30
  ];
28
31
 
29
- // In-memory session state, initialized from config
32
+ // In-memory session state - starts empty, NOT initialized from config
33
+ // Each MCP server process (each Claude Code tab) starts with no org/project context
34
+ // User must explicitly set org/project or call config_reset to load from persistent config
30
35
  const sessionState = {};
31
36
 
32
- // Initialize session state from config on module load
33
- for (const key of SESSION_KEYS) {
34
- sessionState[key] = config.get(key);
35
- }
36
-
37
37
  /**
38
38
  * Get a config value
39
39
  * Session-scoped keys return from memory; others fall through to persistent config