@projitive/mcp 1.0.0-beta.3 → 1.0.0-beta.5

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/output/index.js +43 -12
  2. package/package.json +4 -2
package/output/index.js CHANGED
@@ -11,6 +11,8 @@ import { discoverProjects, resolveGovernanceDir } from "./projitive.js";
11
11
  import { isValidRoadmapId } from "./roadmap.js";
12
12
  import { isValidTaskId, loadTasks, parseTasksBlock, rankActionableTaskCandidates, taskPriority, toTaskUpdatedAtMs, } from "./tasks.js";
13
13
  const PROJITIVE_SPEC_VERSION = "1.0.0";
14
+ const DEFAULT_SCAN_DEPTH = 3;
15
+ const MAX_SCAN_DEPTH = 8;
14
16
  const server = new McpServer({
15
17
  name: "projitive-mcp",
16
18
  version: PROJITIVE_SPEC_VERSION,
@@ -35,6 +37,26 @@ function renderErrorMarkdown(toolName, cause, nextSteps) {
35
37
  function normalizePath(inputPath) {
36
38
  return inputPath ? path.resolve(inputPath) : process.cwd();
37
39
  }
40
+ function parseDepthFromEnv(rawDepth) {
41
+ if (typeof rawDepth !== "string" || rawDepth.trim().length === 0) {
42
+ return undefined;
43
+ }
44
+ const parsed = Number.parseInt(rawDepth, 10);
45
+ if (!Number.isFinite(parsed)) {
46
+ return undefined;
47
+ }
48
+ return Math.min(MAX_SCAN_DEPTH, Math.max(0, parsed));
49
+ }
50
+ function resolveScanRoot(inputPath) {
51
+ const fallback = process.env.PROJITIVE_SCAN_ROOT_PATH;
52
+ return normalizePath(inputPath ?? fallback);
53
+ }
54
+ function resolveScanDepth(inputDepth) {
55
+ if (typeof inputDepth === "number") {
56
+ return inputDepth;
57
+ }
58
+ return parseDepthFromEnv(process.env.PROJITIVE_SCAN_MAX_DEPTH) ?? DEFAULT_SCAN_DEPTH;
59
+ }
38
60
  function candidateFilesFromArtifacts(artifacts) {
39
61
  return artifacts
40
62
  .filter((item) => item.exists)
@@ -136,14 +158,15 @@ server.registerTool("project.scan", {
136
158
  maxDepth: z.number().int().min(0).max(8).optional(),
137
159
  },
138
160
  }, async ({ rootPath, maxDepth }) => {
139
- const root = normalizePath(rootPath);
140
- const projects = await discoverProjects(root, maxDepth ?? 3);
161
+ const root = resolveScanRoot(rootPath);
162
+ const depth = resolveScanDepth(maxDepth);
163
+ const projects = await discoverProjects(root, depth);
141
164
  const markdown = [
142
165
  "# project.scan",
143
166
  "",
144
167
  "## Summary",
145
168
  `- rootPath: ${root}`,
146
- `- maxDepth: ${maxDepth ?? 3}`,
169
+ `- maxDepth: ${depth}`,
147
170
  `- discoveredCount: ${projects.length}`,
148
171
  "",
149
172
  "## Evidence",
@@ -165,8 +188,9 @@ server.registerTool("project.next", {
165
188
  limit: z.number().int().min(1).max(50).optional(),
166
189
  },
167
190
  }, async ({ rootPath, maxDepth, limit }) => {
168
- const root = normalizePath(rootPath);
169
- const projects = await discoverProjects(root, maxDepth ?? 3);
191
+ const root = resolveScanRoot(rootPath);
192
+ const depth = resolveScanDepth(maxDepth);
193
+ const projects = await discoverProjects(root, depth);
170
194
  const snapshots = await Promise.all(projects.map(async (governanceDir) => {
171
195
  const snapshot = await readTasksSnapshot(governanceDir);
172
196
  const inProgress = snapshot.tasks.filter((task) => task.status === "IN_PROGRESS").length;
@@ -202,7 +226,7 @@ server.registerTool("project.next", {
202
226
  "",
203
227
  "## Summary",
204
228
  `- rootPath: ${root}`,
205
- `- maxDepth: ${maxDepth ?? 3}`,
229
+ `- maxDepth: ${depth}`,
206
230
  `- matchedProjects: ${projects.length}`,
207
231
  `- actionableProjects: ${ranked.length}`,
208
232
  `- limit: ${limit ?? 10}`,
@@ -329,8 +353,9 @@ server.registerTool("task.next", {
329
353
  topCandidates: z.number().int().min(1).max(20).optional(),
330
354
  },
331
355
  }, async ({ rootPath, maxDepth, topCandidates }) => {
332
- const root = normalizePath(rootPath);
333
- const projects = await discoverProjects(root, maxDepth ?? 3);
356
+ const root = resolveScanRoot(rootPath);
357
+ const depth = resolveScanDepth(maxDepth);
358
+ const projects = await discoverProjects(root, depth);
334
359
  const rankedCandidates = rankActionableTaskCandidates(await readActionableTaskCandidates(projects));
335
360
  if (rankedCandidates.length === 0) {
336
361
  const markdown = [
@@ -338,7 +363,7 @@ server.registerTool("task.next", {
338
363
  "",
339
364
  "## Summary",
340
365
  `- rootPath: ${root}`,
341
- `- maxDepth: ${maxDepth ?? 3}`,
366
+ `- maxDepth: ${depth}`,
342
367
  `- matchedProjects: ${projects.length}`,
343
368
  "- actionableTasks: 0",
344
369
  "",
@@ -365,7 +390,7 @@ server.registerTool("task.next", {
365
390
  "",
366
391
  "## Summary",
367
392
  `- rootPath: ${root}`,
368
- `- maxDepth: ${maxDepth ?? 3}`,
393
+ `- maxDepth: ${depth}`,
369
394
  `- matchedProjects: ${projects.length}`,
370
395
  `- actionableTasks: ${rankedCandidates.length}`,
371
396
  `- selectedProject: ${selected.governanceDir}`,
@@ -559,5 +584,11 @@ server.registerTool("roadmap.get", {
559
584
  ].join("\n");
560
585
  return asText(markdown);
561
586
  });
562
- const transport = new StdioServerTransport();
563
- await server.connect(transport);
587
+ async function main() {
588
+ const transport = new StdioServerTransport();
589
+ await server.connect(transport);
590
+ }
591
+ void main().catch((error) => {
592
+ console.error("Server error:", error);
593
+ process.exit(1);
594
+ });
package/package.json CHANGED
@@ -1,13 +1,15 @@
1
1
  {
2
2
  "name": "@projitive/mcp",
3
- "version": "1.0.0-beta.3",
3
+ "version": "1.0.0-beta.5",
4
4
  "description": "Projitive MCP Server for project and task discovery/update",
5
5
  "license": "ISC",
6
6
  "author": "",
7
7
  "type": "module",
8
+ "bin": {
9
+ "mcp": "output/index.js"
10
+ },
8
11
  "main": "./output/index.js",
9
12
  "types": "./output/index.d.ts",
10
- "bin": "./output/index.js",
11
13
  "publishConfig": {
12
14
  "access": "public"
13
15
  },