project-mcp 3.2.3 → 3.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": "project-mcp",
3
- "version": "3.2.3",
3
+ "version": "3.3.0",
4
4
  "description": "Intent-based MCP server for project documentation search. Maps natural language queries to the right sources automatically—no configuration needed. The standard for AI agent documentation search.",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -19,15 +19,24 @@ export const THOUGHTS_ARCHIVE_DIR = join(THOUGHTS_TODOS_DIR, '.archive');
19
19
  /**
20
20
  * Intent to source mapping.
21
21
  * Maps user intent to which directories should be searched.
22
+ *
23
+ * IMPORTANT DISTINCTION:
24
+ * - "project" (operational) → .project/ management files (status, todos, roadmap, backlog)
25
+ * - "project_docs" (documentation) → docs/ folder + DECISIONS.md (application documentation)
26
+ *
27
+ * When users say "project docs" or "project documentation", they mean APPLICATION
28
+ * documentation (how the system works), NOT project management (tracking work).
22
29
  */
23
30
  export const INTENT_SOURCES = {
24
31
  project: ['project', 'root', 'docs'], // .project/, root files, docs/
25
32
  docs: ['docs'], // Only docs/
33
+ project_docs: ['docs', 'decisions'], // Application documentation: docs/ + DECISIONS.md
26
34
  plan: ['project'], // Only .project/
27
35
  todos: ['project'],
28
36
  roadmap: ['project'],
29
37
  status: ['project'],
30
38
  operational: ['project'],
39
+ decisions: ['decisions'], // Architecture decisions only (DECISIONS.md)
31
40
  };
32
41
 
33
42
  /**
package/src/lib/search.js CHANGED
@@ -31,12 +31,28 @@ export function detectIntent(query, explicitIntent) {
31
31
 
32
32
  const queryLower = query.toLowerCase();
33
33
 
34
- // Check for operational keywords
35
- if (/\b(plan|plans|todo|todos|roadmap|status|operational|current state|decisions)\b/.test(queryLower)) {
34
+ // Check for "project docs/documents/documentation" - this means APPLICATION documentation
35
+ // NOT project management. Routes to docs/ folder + DECISIONS.md
36
+ if (
37
+ /\b(project\s+doc(s|ument(s|ation)?)?|update\s+(project\s+)?doc(s|ument(s|ation)?)?|application\s+doc(s|ument(s|ation)?)?)\b/.test(
38
+ queryLower
39
+ )
40
+ ) {
41
+ return 'project_docs';
42
+ }
43
+
44
+ // Check for architecture decisions specifically
45
+ if (/\b(decision(s)?|adr|architecture\s+decision(s)?|technical\s+decision(s)?)\b/.test(queryLower)) {
46
+ return 'decisions';
47
+ }
48
+
49
+ // Check for operational/project management keywords (status, todos, roadmap, backlog)
50
+ // This is DIFFERENT from "project docs" - this is about tracking work, not documenting the system
51
+ if (/\b(plan|plans|todo|todos|roadmap|status|operational|current state|backlog)\b/.test(queryLower)) {
36
52
  return 'plan';
37
53
  }
38
54
 
39
- // Check for docs-specific keywords
55
+ // Check for docs-only keywords (just "docs" or "documentation" without "project")
40
56
  if (/\b(docs|documentation|reference|guide|guides|api docs)\b/.test(queryLower)) {
41
57
  return 'docs';
42
58
  }
@@ -51,7 +67,12 @@ export function detectIntent(query, explicitIntent) {
51
67
  * @returns {string[]} Array of source names
52
68
  */
53
69
  export function getSourcesForIntent(intent) {
54
- return INTENT_SOURCES[intent] || INTENT_SOURCES.project;
70
+ const sources = INTENT_SOURCES[intent] || INTENT_SOURCES.project;
71
+
72
+ // 'decisions' is a virtual source that maps to DECISIONS.md in .project/
73
+ // When we see 'decisions' in the sources, we need to include it for filtering
74
+ // The actual loading happens in loadAllFiles() which tags DECISIONS.md with source='decisions'
75
+ return sources;
55
76
  }
56
77
 
57
78
  /**
@@ -67,8 +88,21 @@ export async function loadAllFiles(force = false) {
67
88
  const allFiles = [];
68
89
 
69
90
  // Load .project/ directory
91
+ // DECISIONS.md gets special treatment - it's tagged as both 'project' and 'decisions'
92
+ // because it's application documentation (explains WHY the system is built this way)
93
+ // not just project management
70
94
  try {
71
- await scanDirectory(PROJECT_DIR, '.project', allFiles, 'project');
95
+ const projectFiles = [];
96
+ await scanDirectory(PROJECT_DIR, '.project', projectFiles, 'project');
97
+
98
+ // Tag DECISIONS.md with source='decisions' so it appears in project_docs queries
99
+ for (const file of projectFiles) {
100
+ if (file.path.endsWith('DECISIONS.md')) {
101
+ // DECISIONS.md is application documentation, not just project management
102
+ file.source = 'decisions';
103
+ }
104
+ allFiles.push(file);
105
+ }
72
106
  } catch (error) {
73
107
  // .project/ might not exist
74
108
  }
@@ -24,6 +24,7 @@ export const promptToolMapping = {
24
24
  get_backlog: ['get_backlog'],
25
25
  add_decision: ['add_decision'],
26
26
  update_status: ['update_project_status'],
27
+ update_project_docs: ['search_project', 'get_doc', 'add_decision', 'list_docs'],
27
28
  };
28
29
 
29
30
  /**
@@ -204,6 +205,25 @@ export const prompts = [
204
205
  },
205
206
  ],
206
207
  },
208
+ {
209
+ name: 'update_project_docs',
210
+ description:
211
+ 'Update project documentation - the APPLICATION documentation that explains how the system works. Use when user says "update project docs", "update project documents", "update project documentation", "update application docs", or "document this". This is DIFFERENT from project management (status, todos, roadmap) - this updates the docs/ folder and DECISIONS.md which contain reference documentation about the application itself.',
212
+ arguments: [
213
+ {
214
+ name: 'content',
215
+ description:
216
+ 'What to document or update. The model will determine whether this belongs in docs/ (application documentation) or DECISIONS.md (architecture decisions).',
217
+ required: true,
218
+ },
219
+ {
220
+ name: 'doc_type',
221
+ description:
222
+ 'Hint for documentation type: "decision" for architecture decisions (DECISIONS.md), "release" for release notes, "guide" for user guides, "api" for API docs, or "auto" to let the model decide based on content.',
223
+ required: false,
224
+ },
225
+ ],
226
+ },
207
227
  ];
208
228
 
209
229
  /**
@@ -203,6 +203,32 @@ This adds a timestamped status entry to STATUS.md.`,
203
203
  },
204
204
  },
205
205
  ],
206
+ update_project_docs: [
207
+ {
208
+ role: 'user',
209
+ content: {
210
+ type: 'text',
211
+ text: `Update project documentation with: "${args.content || '[CONTENT]'}".
212
+
213
+ IMPORTANT: This is about APPLICATION DOCUMENTATION (how the system works), NOT project management (status, todos, roadmap).
214
+
215
+ ${args.doc_type === 'decision' ? `This is an architecture decision. Use the \`add_decision\` tool to add it to DECISIONS.md.` : args.doc_type === 'release' ? `This is a release note. Look in docs/releases/ and update the appropriate file.` : `Based on the content, determine where this documentation belongs:
216
+
217
+ 1. **Architecture Decision?** (design choice, trade-off, technical rationale)
218
+ → Use \`add_decision\` tool to add to DECISIONS.md
219
+
220
+ 2. **Application Documentation?** (how-to, API docs, guides, reference)
221
+ → First use \`search_project\` with intent "project_docs" to find relevant existing docs
222
+ → Then use \`list_docs\` to see the docs/ structure
223
+ → Update the appropriate file in docs/
224
+
225
+ 3. **Release Notes?** (version changes, features, fixes)
226
+ → Check docs/releases/ for the right file
227
+
228
+ The model decides where this content best fits based on its nature.`}`,
229
+ },
230
+ },
231
+ ],
206
232
  };
207
233
 
208
234
  return (
@@ -236,6 +262,7 @@ export function getMessageHandlerKeys() {
236
262
  get_backlog: true,
237
263
  add_decision: true,
238
264
  update_status: true,
265
+ update_project_docs: true,
239
266
  };
240
267
  return Object.keys(messages);
241
268
  }
package/src/tools/lint.js CHANGED
@@ -378,42 +378,52 @@ ${project_description}
378
378
 
379
379
  ## Contract for AI Agents
380
380
 
381
- When a user says **"project"**, **"the project"**, or **"my project"**, the canonical sources of truth are:
381
+ ### Critical Distinction: Project Management vs Project Documentation
382
382
 
383
- 1. **\`.project/\`** Current state, plans, todos, decisions (operational truth)
384
- 2. **Root markdown files** — README.md, CONTRIBUTING.md, etc.
385
- 3. **\`docs/\`** Long-form reference documentation
383
+ | Term | Means | Sources |
384
+ |------|-------|---------|
385
+ | **"project docs"** / **"project documentation"** | Application documentation (HOW the system works) | \`docs/\` + \`DECISIONS.md\` |
386
+ | **"project status"** / **"todos"** / **"roadmap"** | Project management (WHAT we're doing) | \`.project/\` management files |
387
+
388
+ **DECISIONS.md is special**: It's application documentation (explains WHY decisions were made) even though it lives in \`.project/\`.
386
389
 
387
390
  ## Source Mappings
388
391
 
389
- ### "project" / "the project"
390
- Searches: \`.project/\` + root files + \`docs/\`
392
+ ### "project docs" / "project documents" / "project documentation"
393
+ APPLICATION documentation how the system works, why it was built this way.
394
+ Searches: \`docs/\` + \`DECISIONS.md\`
391
395
 
392
- ### "docs" / "documentation"
396
+ ### "docs" / "documentation" / "reference"
397
+ Reference documentation only.
393
398
  Searches: \`docs/\` only
394
399
 
395
- ### "plan" / "todos" / "roadmap" / "status"
396
- Searches: \`.project/\` only
400
+ ### "plan" / "todos" / "roadmap" / "status" / "backlog"
401
+ Project MANAGEMENT — tracking work, not documenting the system.
402
+ Searches: \`.project/\` (excluding DECISIONS.md)
403
+
404
+ ### "project" / "the project"
405
+ Everything (when intent is ambiguous).
406
+ Searches: \`.project/\` + root files + \`docs/\`
397
407
 
398
408
  ## File Structure
399
409
 
400
- | File | Purpose |
401
- |------|---------|
402
- | \`index.md\` | This file - contract and source mappings |
403
- | \`BACKLOG.md\` | Prioritized work queue (future tasks) |
404
- | \`TODO.md\` | Task dashboard (active work, auto-generated) |
405
- | \`ROADMAP.md\` | Project phases and milestones |
406
- | \`STATUS.md\` | Current project health and progress |
407
- | \`DECISIONS.md\` | Architecture decisions and rationale |
408
- | \`todos/\` | Active task files (10-30 items, not hundreds) |
409
- | \`archive/\` | Completed tasks (for history) |
410
+ | File | Type | Purpose |
411
+ |------|------|---------|
412
+ | \`index.md\` | Contract | This file - source mappings |
413
+ | \`DECISIONS.md\` | **Documentation** | Architecture decisions (WHY) |
414
+ | \`BACKLOG.md\` | Management | Prioritized work queue |
415
+ | \`TODO.md\` | Management | Task dashboard |
416
+ | \`ROADMAP.md\` | Management | Project phases/milestones |
417
+ | \`STATUS.md\` | Management | Project health/progress |
418
+ | \`todos/\` | Management | Active task files |
419
+ | \`archive/\` | Management | Completed tasks |
410
420
 
411
421
  ## Principles
412
422
 
413
- - **Natural language stays natural** — Users say "project" not ".project/"
423
+ - **"Project docs" "Project management"** — Users saying "update project docs" want application documentation updated, not task tracking
424
+ - **DECISIONS.md is documentation** — It explains the system, not tracks work
425
+ - **Natural language stays natural** — "Project docs" maps to docs/ + DECISIONS.md
414
426
  - **Agents don't guess** — Explicit mappings defined here
415
- - **Intent over structure** — Language maps to intent, not directory names
416
- - **Operational truth** — This directory is the source of truth for current state
417
427
 
418
428
  ---
419
429
  *Last Updated: ${date}*
@@ -16,7 +16,7 @@ export const definitions = [
16
16
  {
17
17
  name: 'search_project',
18
18
  description:
19
- 'Search across all project sources: .project/ (operational truth), root-level files, and docs/ (reference truth). Use this when the user says "project", "the project", or asks about project status, plans, todos, or roadmap. Maps natural language to appropriate sources automatically.',
19
+ 'Search across project sources with smart intent detection. IMPORTANT: "project docs" means APPLICATION documentation (docs/ + DECISIONS.md), NOT project management. Use intent "project_docs" when user says "project docs/documents/documentation" to search application documentation. Use intent "plan" for project management (status, todos, roadmap, backlog).',
20
20
  inputSchema: {
21
21
  type: 'object',
22
22
  properties: {
@@ -28,8 +28,19 @@ export const definitions = [
28
28
  intent: {
29
29
  type: 'string',
30
30
  description:
31
- 'Optional: Intent type to map to sources. Options: "project" (searches .project/, root, docs), "docs" (only docs/), "plan/todos/roadmap/status/operational" (only .project/). If not specified, automatically detects from query.',
32
- enum: ['project', 'docs', 'plan', 'todos', 'roadmap', 'status', 'operational', ''],
31
+ 'Intent type to map to sources. "project_docs" searches docs/ + DECISIONS.md (application documentation). "docs" searches only docs/. "plan/todos/roadmap/status/operational" searches .project/ (project management). "project" searches everything. "decisions" searches only DECISIONS.md.',
32
+ enum: [
33
+ 'project',
34
+ 'project_docs',
35
+ 'docs',
36
+ 'decisions',
37
+ 'plan',
38
+ 'todos',
39
+ 'roadmap',
40
+ 'status',
41
+ 'operational',
42
+ '',
43
+ ],
33
44
  },
34
45
  maxResults: {
35
46
  type: 'number',