superproductivity-mcp 1.2.6.dev6__tar.gz → 1.2.6.dev8__tar.gz
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.
- {superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/PKG-INFO +1 -1
- {superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/plugin/manifest.json +1 -1
- {superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/plugin/plugin.js +33 -33
- {superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/pyproject.toml +1 -1
- {superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/.github/workflows/build.yml +0 -0
- {superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/.github/workflows/publish-dev.yml +0 -0
- {superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/.github/workflows/publish.yml +0 -0
- {superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/.github/workflows/release.yml +0 -0
- {superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/.github/workflows/version-gate.yml +0 -0
- {superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/.gitignore +0 -0
- {superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/.mcp.json.example +0 -0
- {superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/.mise.toml +0 -0
- {superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/LICENSE.txt +0 -0
- {superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/README.md +0 -0
- {superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/build-plugin.sh +0 -0
- {superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/docs/superpowers/plans/2026-04-29-packaging-distribution.md +0 -0
- {superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/docs/superpowers/plans/2026-04-30-gitflow-ci.md +0 -0
- {superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/docs/superpowers/specs/2026-04-29-gitflow-ci-design.md +0 -0
- {superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/docs/superpowers/specs/2026-04-29-packaging-distribution-design.md +0 -0
- {superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/plugin/index.html +0 -0
- {superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/src/superproductivity_mcp/__init__.py +0 -0
- {superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/src/superproductivity_mcp/__main__.py +0 -0
- {superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/src/superproductivity_mcp/server.py +0 -0
- {superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/tests/__init__.py +0 -0
- {superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/tests/test_mcp_logic.py +0 -0
- {superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: superproductivity-mcp
|
|
3
|
-
Version: 1.2.6.
|
|
3
|
+
Version: 1.2.6.dev8
|
|
4
4
|
Summary: Super Productivity MCP server for Claude Desktop integration
|
|
5
5
|
Project-URL: Homepage, https://github.com/ben-elliot-nice/superproductivity-mcp
|
|
6
6
|
License-File: LICENSE.txt
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "sp-mcp-bridge",
|
|
3
3
|
"name": "MCP Bridge",
|
|
4
4
|
"description": "Bridge between Super Productivity and MCP (Model Context Protocol) servers for Claude Desktop integration",
|
|
5
|
-
"version": "1.2.6.
|
|
5
|
+
"version": "1.2.6.dev8",
|
|
6
6
|
"manifestVersion": 1,
|
|
7
7
|
"author": "Super Productivity Team",
|
|
8
8
|
"homepage": "https://github.com/johannesjo/super-productivity",
|
|
@@ -485,32 +485,20 @@ class MCPBridgePlugin {
|
|
|
485
485
|
|
|
486
486
|
case 'addTask':
|
|
487
487
|
if (command.data.parentId) {
|
|
488
|
-
// SP's addTask double-writes when parentId is supplied at creation time.
|
|
489
|
-
// Strategy: create WITHOUT parentId, then set parentId via updateTask (hides
|
|
490
|
-
// child from root), then add to parent's subTaskIds (produces nested display).
|
|
491
488
|
const { parentId, title, ...rest } = command.data;
|
|
492
|
-
// Strip SP scheduling/tag syntax from title at creation
|
|
493
|
-
// SP
|
|
489
|
+
// Strip SP scheduling/tag syntax (@, #, +) from title at creation to prevent
|
|
490
|
+
// SP parsing it during addTask. Restore via a separate updateTask on title only.
|
|
494
491
|
const hasSyntax = /[@#+]/.test(title);
|
|
495
492
|
const createTitle = hasSyntax
|
|
496
493
|
? title.replace(/@\w+/g, '').replace(/#\w+/g, '').replace(/\+\w+/g, '').trim()
|
|
497
494
|
: title;
|
|
498
|
-
// Create without parentId to avoid SP's addTask double-write bug.
|
|
499
495
|
await this.log(`Creating subtask under ${parentId}`, 'debug');
|
|
500
|
-
|
|
501
|
-
//
|
|
502
|
-
//
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
// Step 2: add child to parent's subTaskIds so SP nests it correctly.
|
|
507
|
-
const allTasks = await PluginAPI.getTasks();
|
|
508
|
-
const parentTask = allTasks.find(t => t.id === parentId);
|
|
509
|
-
if (parentTask) {
|
|
510
|
-
const existing = parentTask.subTaskIds || [];
|
|
511
|
-
if (!existing.includes(subtaskId)) {
|
|
512
|
-
await PluginAPI.updateTask(parentId, { subTaskIds: [...existing, subtaskId] });
|
|
513
|
-
}
|
|
496
|
+
// Pass parentId to addTask directly — SP creates a true subtask at creation
|
|
497
|
+
// time and handles hierarchy correctly. updateTask({ parentId }) creates a
|
|
498
|
+
// root-level cross-reference label instead of a true nested subtask.
|
|
499
|
+
const subtaskId = await PluginAPI.addTask({ ...rest, title: createTitle, parentId });
|
|
500
|
+
if (hasSyntax) {
|
|
501
|
+
await PluginAPI.updateTask(subtaskId, { title });
|
|
514
502
|
}
|
|
515
503
|
result = subtaskId;
|
|
516
504
|
} else {
|
|
@@ -537,26 +525,38 @@ class MCPBridgePlugin {
|
|
|
537
525
|
const allTasks = await PluginAPI.getTasks();
|
|
538
526
|
const taskMap = new Map(allTasks.map(t => [t.id, t]));
|
|
539
527
|
const fixes = [];
|
|
528
|
+
const errors = [];
|
|
529
|
+
|
|
530
|
+
// Build a map of parentId → [childIds that have parentId set but are missing from parent's subTaskIds]
|
|
531
|
+
// Root cause: concurrent create_tasks calls race on subTaskIds updates — last write wins,
|
|
532
|
+
// leaving orphaned children with parentId set but not in parent's subTaskIds array.
|
|
533
|
+
const missingFromParent = new Map(); // parentId → Set of childIds to add
|
|
540
534
|
for (const task of allTasks) {
|
|
541
|
-
// Fix 1: child is in parent's subTaskIds but has no parentId set
|
|
542
|
-
for (const childId of (task.subTaskIds || [])) {
|
|
543
|
-
const child = taskMap.get(childId);
|
|
544
|
-
if (child && !child.parentId) {
|
|
545
|
-
await PluginAPI.updateTask(childId, { parentId: task.id });
|
|
546
|
-
fixes.push(`set parentId on "${child.title}" → parent "${task.title}"`);
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
// Fix 2: child has parentId set but is missing from parent's subTaskIds
|
|
550
535
|
if (task.parentId) {
|
|
551
536
|
const parent = taskMap.get(task.parentId);
|
|
552
537
|
if (parent && !(parent.subTaskIds || []).includes(task.id)) {
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
538
|
+
if (!missingFromParent.has(task.parentId)) {
|
|
539
|
+
missingFromParent.set(task.parentId, new Set());
|
|
540
|
+
}
|
|
541
|
+
missingFromParent.get(task.parentId).add(task.id);
|
|
556
542
|
}
|
|
557
543
|
}
|
|
558
544
|
}
|
|
559
|
-
|
|
545
|
+
|
|
546
|
+
// For each parent, do ONE update with ALL missing children at once to avoid race conditions
|
|
547
|
+
for (const [parentId, missingIds] of missingFromParent) {
|
|
548
|
+
const parent = taskMap.get(parentId);
|
|
549
|
+
try {
|
|
550
|
+
const updated = [...(parent.subTaskIds || []), ...missingIds];
|
|
551
|
+
await PluginAPI.updateTask(parentId, { subTaskIds: updated });
|
|
552
|
+
const childTitles = [...missingIds].map(id => taskMap.get(id)?.title || id);
|
|
553
|
+
fixes.push(`added ${missingIds.size} missing children to "${parent.title}": ${childTitles.join(', ')}`);
|
|
554
|
+
} catch (e) {
|
|
555
|
+
errors.push(`failed to fix parent "${parent?.title}": ${e.message}`);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
result = { fixed: fixes.length, fixes, errors };
|
|
560
560
|
break;
|
|
561
561
|
}
|
|
562
562
|
|
{superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/.github/workflows/build.yml
RENAMED
|
File without changes
|
|
File without changes
|
{superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/.github/workflows/publish.yml
RENAMED
|
File without changes
|
{superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/.github/workflows/release.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{superproductivity_mcp-1.2.6.dev6 → superproductivity_mcp-1.2.6.dev8}/tests/test_mcp_logic.py
RENAMED
|
File without changes
|
|
File without changes
|