@qzoft/check-list 1.0.7 → 1.0.9

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.
Files changed (2) hide show
  1. package/dist/server.js +32 -14
  2. package/package.json +3 -2
package/dist/server.js CHANGED
@@ -44,31 +44,49 @@ registerAppResource(server, 'Task Checklist', uiResourceUri, { description: 'Int
44
44
  }],
45
45
  }));
46
46
  registerAppTool(server, 'list_tasks', {
47
- description: 'Discover and display checklists from markdown files in the project. When the user asks to see tasks in a specific file (e.g. "show my tasks in now.md"), pass the filename as the `file` parameter. When no file is specified, all markdown files are scanned.',
47
+ description: 'Discover and display checklists from markdown files in the project. When the user asks to see tasks in a specific file, pass its ABSOLUTE file path as the `file` parameter. IMPORTANT: Always use the full absolute path (e.g. "/Users/me/project/tasks.md" or "C:\\Users\\me\\project\\tasks.md"), never a relative or workspace-relative path. When no file is specified, all markdown files in the project directory are scanned.',
48
48
  inputSchema: {
49
- file: z.string().optional().describe('Optional path to a specific markdown file. Can be an absolute path (e.g. "C:/Users/me/project/tasks.md") or a relative path resolved against the project directory (e.g. "now.md"). Omit to show tasks from all markdown files.'),
49
+ file: z.string().optional().describe('ABSOLUTE path to a specific markdown file (e.g. "/Users/me/project/tasks.md" or "C:\\Users\\me\\project\\tasks.md"). Always use the full absolute path from the file reference. Omit to scan all markdown files in the project directory.'),
50
50
  },
51
51
  _meta: { ui: { resourceUri: uiResourceUri } },
52
52
  }, async ({ file }) => {
53
53
  let mdFiles;
54
54
  if (file) {
55
- // Single-file mode: resolve the path (absolute paths stay as-is, relative resolve against projectDir)
56
- let resolved = path.isAbsolute(file) ? path.resolve(file) : path.resolve(projectDir, file);
57
- // If the resolved path doesn't exist, try to find the file by name in the project
58
- if (!fs.existsSync(resolved)) {
55
+ // Build a list of candidate paths to try, in priority order
56
+ const candidates = [];
57
+ if (path.isAbsolute(file)) {
58
+ candidates.push(path.resolve(file));
59
+ }
60
+ else {
61
+ // 1. Relative to projectDir
62
+ candidates.push(path.resolve(projectDir, file));
63
+ // 2. Relative to cwd (if different from projectDir)
64
+ const cwd = process.cwd();
65
+ if (cwd !== projectDir) {
66
+ candidates.push(path.resolve(cwd, file));
67
+ }
68
+ }
69
+ // Find the first candidate that exists on disk
70
+ let resolved = candidates.find(c => fs.existsSync(c));
71
+ // If none found, search by filename/suffix in projectDir
72
+ if (!resolved) {
59
73
  const basename = path.basename(file);
74
+ const suffix = file.replace(/\//g, path.sep);
60
75
  try {
61
76
  const allMd = await discoverMarkdownFiles(projectDir);
62
- const match = allMd.find(f => path.basename(f) === basename)
63
- || allMd.find(f => f.endsWith(file.replace(/\//g, path.sep)));
64
- if (match) {
65
- resolved = match;
66
- }
77
+ resolved = allMd.find(f => f.endsWith(path.sep + suffix))
78
+ || allMd.find(f => path.basename(f) === basename);
67
79
  }
68
80
  catch {
69
- // ignore discovery errors, will fail on read below with original path
81
+ // ignore discovery errors
70
82
  }
71
83
  }
84
+ if (!resolved) {
85
+ return {
86
+ isError: true,
87
+ content: [{ type: 'text', text: `File not found: ${file}\nSearched in: ${candidates.join(', ')}` }],
88
+ };
89
+ }
72
90
  mdFiles = [resolved];
73
91
  }
74
92
  else {
@@ -99,7 +117,7 @@ registerAppTool(server, 'list_tasks', {
99
117
  if (file) {
100
118
  return {
101
119
  isError: true,
102
- content: [{ type: 'text', text: `Could not read file: ${file}\nResolved path: ${filePath}\nProject directory: ${projectDir}` }],
120
+ content: [{ type: 'text', text: `Could not read file: ${filePath}` }],
103
121
  };
104
122
  }
105
123
  continue; // skip files we can't read
@@ -125,7 +143,7 @@ registerAppTool(server, 'list_tasks', {
125
143
  registerAppTool(server, 'update_tasks', {
126
144
  description: 'Update checkbox states in a project markdown file (auto-saved on toggle)',
127
145
  inputSchema: {
128
- file: z.string().describe('Path to the markdown file. Can be absolute or relative to the project directory.'),
146
+ file: z.string().describe('ABSOLUTE path to the markdown file (e.g. "/Users/me/project/tasks.md"). Always use the full absolute path.'),
129
147
  updates: z.array(z.object({
130
148
  line: z.number().describe('0-indexed line number in the markdown file'),
131
149
  checked: z.boolean().describe('New checked state for the checkbox'),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qzoft/check-list",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "MCP App for interactive task management from markdown files",
5
5
  "type": "module",
6
6
  "main": "dist/server.js",
@@ -18,7 +18,8 @@
18
18
  },
19
19
  "dependencies": {
20
20
  "@modelcontextprotocol/ext-apps": "^1.2.0",
21
- "@modelcontextprotocol/sdk": "^1.27.1"
21
+ "@modelcontextprotocol/sdk": "^1.27.1",
22
+ "@qzoft/check-list": "^1.0.7"
22
23
  },
23
24
  "devDependencies": {
24
25
  "@types/node": "^22.0.0",