praxis-mcp 1.0.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/README.md +103 -0
- package/build/index.d.ts +3 -0
- package/build/index.js +22 -0
- package/build/index.js.map +1 -0
- package/build/lib/constants.d.ts +16 -0
- package/build/lib/constants.js +88 -0
- package/build/lib/constants.js.map +1 -0
- package/build/lib/detection.d.ts +43 -0
- package/build/lib/detection.js +123 -0
- package/build/lib/detection.js.map +1 -0
- package/build/lib/fs-helpers.d.ts +59 -0
- package/build/lib/fs-helpers.js +151 -0
- package/build/lib/fs-helpers.js.map +1 -0
- package/build/lib/naming.d.ts +36 -0
- package/build/lib/naming.js +68 -0
- package/build/lib/naming.js.map +1 -0
- package/build/lib/parsers.d.ts +102 -0
- package/build/lib/parsers.js +144 -0
- package/build/lib/parsers.js.map +1 -0
- package/build/tools/context.d.ts +10 -0
- package/build/tools/context.js +214 -0
- package/build/tools/context.js.map +1 -0
- package/build/tools/lint.d.ts +8 -0
- package/build/tools/lint.js +115 -0
- package/build/tools/lint.js.map +1 -0
- package/build/tools/scaffold.d.ts +8 -0
- package/build/tools/scaffold.js +146 -0
- package/build/tools/scaffold.js.map +1 -0
- package/build/tools/session.d.ts +10 -0
- package/build/tools/session.js +203 -0
- package/build/tools/session.js.map +1 -0
- package/build/tools/work-orders.d.ts +11 -0
- package/build/tools/work-orders.js +308 -0
- package/build/tools/work-orders.js.map +1 -0
- package/package.json +57 -0
package/README.md
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Praxis MCP Server
|
|
2
|
+
|
|
3
|
+
MCP (Model Context Protocol) server for the [Praxis](https://github.com/LuisFaxas/praxis) AI development methodology. Gives any MCP-compatible AI agent structured tools for session management, work order lifecycle, context chain operations, validation, and project scaffolding.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
cd praxis-mcp
|
|
9
|
+
npm install
|
|
10
|
+
npm run build
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Register with Claude Code
|
|
14
|
+
|
|
15
|
+
Add to `.mcp.json` at your project root:
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"mcpServers": {
|
|
20
|
+
"praxis": {
|
|
21
|
+
"command": "node",
|
|
22
|
+
"args": ["/absolute/path/to/praxis-mcp/build/index.js"],
|
|
23
|
+
"env": {
|
|
24
|
+
"PRAXIS_PROJECT_DIR": "/absolute/path/to/your/project"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Register with Codex
|
|
32
|
+
|
|
33
|
+
Add to `~/.codex/config.toml`:
|
|
34
|
+
|
|
35
|
+
```toml
|
|
36
|
+
[mcp_servers.praxis]
|
|
37
|
+
command = "node"
|
|
38
|
+
args = ["/absolute/path/to/praxis-mcp/build/index.js"]
|
|
39
|
+
|
|
40
|
+
[mcp_servers.praxis.env]
|
|
41
|
+
PRAXIS_PROJECT_DIR = "/absolute/path/to/your/project"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Test with MCP Inspector
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npx @modelcontextprotocol/inspector node build/index.js
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Tools (12)
|
|
51
|
+
|
|
52
|
+
All tools are prefixed as `mcp__praxis__<tool>` by the MCP protocol.
|
|
53
|
+
|
|
54
|
+
### Session Lifecycle
|
|
55
|
+
|
|
56
|
+
| Tool | Description |
|
|
57
|
+
|------|-------------|
|
|
58
|
+
| `session_start` | Read the full context chain + pending work orders in canonical Praxis order. Returns a complete project state snapshot. |
|
|
59
|
+
| `session_end` | Validate that context documents were updated during this session. Returns a compliance report. |
|
|
60
|
+
| `detect_project` | Detect adoption tier, operational mode, configured providers, and structural completeness. |
|
|
61
|
+
|
|
62
|
+
### Context Chain
|
|
63
|
+
|
|
64
|
+
| Tool | Description |
|
|
65
|
+
|------|-------------|
|
|
66
|
+
| `read_context` | Read one or all context documents (SOT, capsule, checkpoint) with metadata. |
|
|
67
|
+
| `update_capsule` | Patch the Context Capsule with structured fields (active task, session summary, next steps). |
|
|
68
|
+
| `update_checkpoint` | Append a milestone to the Checkpoint document. Auto-numbers the entry. |
|
|
69
|
+
|
|
70
|
+
### Work Orders
|
|
71
|
+
|
|
72
|
+
| Tool | Description |
|
|
73
|
+
|------|-------------|
|
|
74
|
+
| `list_work_orders` | List work orders with status/agent filters. Handles solo and triangle modes. |
|
|
75
|
+
| `read_work_order` | Read and parse a specific work order by number or filename. |
|
|
76
|
+
| `create_work_order` | Create a new work order with naming convention enforcement and auto-numbering. |
|
|
77
|
+
| `complete_work_order` | Validate all acceptance criteria are checked, then move WO to executed/. |
|
|
78
|
+
|
|
79
|
+
### Validation
|
|
80
|
+
|
|
81
|
+
| Tool | Description |
|
|
82
|
+
|------|-------------|
|
|
83
|
+
| `lint` | Run praxis-lint.sh (50 checks, 7 categories) and return structured JSON findings. |
|
|
84
|
+
|
|
85
|
+
### Scaffolding
|
|
86
|
+
|
|
87
|
+
| Tool | Description |
|
|
88
|
+
|------|-------------|
|
|
89
|
+
| `scaffold` | Create the Praxis dev/ folder structure based on tier and mode. Safe to run multiple times. |
|
|
90
|
+
|
|
91
|
+
## Configuration
|
|
92
|
+
|
|
93
|
+
The server reads `PRAXIS_PROJECT_DIR` from the environment to determine the project root. All tools accept an optional `project_path` parameter to override this default.
|
|
94
|
+
|
|
95
|
+
## Architecture
|
|
96
|
+
|
|
97
|
+
- **Stateless**: No in-memory state between calls. The filesystem is the state.
|
|
98
|
+
- **Provider-agnostic**: Uses `*_INIT.md` globs and `wo_*/` patterns, never hardcoded provider names.
|
|
99
|
+
- **Zero dependencies**: Beyond the MCP SDK and Zod (both required by the protocol).
|
|
100
|
+
|
|
101
|
+
## License
|
|
102
|
+
|
|
103
|
+
MIT
|
package/build/index.d.ts
ADDED
package/build/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { registerSessionTools } from "./tools/session.js";
|
|
5
|
+
import { registerContextTools } from "./tools/context.js";
|
|
6
|
+
import { registerWorkOrderTools } from "./tools/work-orders.js";
|
|
7
|
+
import { registerLintTool } from "./tools/lint.js";
|
|
8
|
+
import { registerScaffoldTool } from "./tools/scaffold.js";
|
|
9
|
+
const server = new McpServer({
|
|
10
|
+
name: "praxis",
|
|
11
|
+
version: "1.0.0",
|
|
12
|
+
});
|
|
13
|
+
// Register all tool categories
|
|
14
|
+
registerSessionTools(server);
|
|
15
|
+
registerContextTools(server);
|
|
16
|
+
registerWorkOrderTools(server);
|
|
17
|
+
registerLintTool(server);
|
|
18
|
+
registerScaffoldTool(server);
|
|
19
|
+
// Start the server with stdio transport
|
|
20
|
+
const transport = new StdioServerTransport();
|
|
21
|
+
await server.connect(transport);
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,QAAQ;IACd,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,+BAA+B;AAC/B,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAC7B,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAC7B,sBAAsB,CAAC,MAAM,CAAC,CAAC;AAC/B,gBAAgB,CAAC,MAAM,CAAC,CAAC;AACzB,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAE7B,wCAAwC;AACxC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Praxis MCP — Constants
|
|
3
|
+
*
|
|
4
|
+
* Tier folder maps, core document paths, WO template, naming patterns.
|
|
5
|
+
* All paths are relative to the project's dev/ folder.
|
|
6
|
+
*/
|
|
7
|
+
export declare const CORE_DOCS: readonly ["source_of_truth.md", "context_capsule.md", "checkpoint.md"];
|
|
8
|
+
export declare const TIER_FOLDERS: Record<string, string[]>;
|
|
9
|
+
export declare const PRAXIS_INIT_FILENAME = "PRAXIS_INIT.md";
|
|
10
|
+
export declare const INIT_FILE_SUFFIX = "_INIT.md";
|
|
11
|
+
export declare const NAMING_REGEX: RegExp;
|
|
12
|
+
export declare const WO_TEMPLATE = "# Work Order: {TITLE}\n\n- **WO#:** {NUMBER}\n- **Date Created:** {DATE}\n- **Status:** Pending\n- **Assigned To:** {ASSIGNED_TO}\n- **Priority:** {PRIORITY}\n\n## Description\n\n{DESCRIPTION}\n\n## Acceptance Criteria\n\n{CRITERIA}\n\n## Notes\n\n";
|
|
13
|
+
export declare const CAPSULE_SECTIONS: readonly ["Active Task", "In-Progress Notes", "Critical Rules", "Key Workspace Paths", "Last Session Summary"];
|
|
14
|
+
export declare const CHECKPOINT_TABLE_HEADER = "| # | Milestone | Date | Status |";
|
|
15
|
+
export declare const CHECKPOINT_TABLE_SEPARATOR = "|---|-----------|------|--------|";
|
|
16
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Praxis MCP — Constants
|
|
3
|
+
*
|
|
4
|
+
* Tier folder maps, core document paths, WO template, naming patterns.
|
|
5
|
+
* All paths are relative to the project's dev/ folder.
|
|
6
|
+
*/
|
|
7
|
+
// Core context documents (always required, regardless of tier)
|
|
8
|
+
export const CORE_DOCS = [
|
|
9
|
+
"source_of_truth.md",
|
|
10
|
+
"context_capsule.md",
|
|
11
|
+
"checkpoint.md",
|
|
12
|
+
];
|
|
13
|
+
// Folders required at each tier level
|
|
14
|
+
export const TIER_FOLDERS = {
|
|
15
|
+
starter: [
|
|
16
|
+
"work-orders",
|
|
17
|
+
"work-orders/executed",
|
|
18
|
+
],
|
|
19
|
+
standard: [
|
|
20
|
+
"work-orders",
|
|
21
|
+
"work-orders/executed",
|
|
22
|
+
"research/active",
|
|
23
|
+
"research/archive",
|
|
24
|
+
"planning/master-plan/draft",
|
|
25
|
+
"planning/master-plan/approved",
|
|
26
|
+
"commands/active",
|
|
27
|
+
"commands/executed",
|
|
28
|
+
],
|
|
29
|
+
full: [
|
|
30
|
+
"work-orders",
|
|
31
|
+
"work-orders/executed",
|
|
32
|
+
"research/active",
|
|
33
|
+
"research/archive",
|
|
34
|
+
"planning/master-plan/draft",
|
|
35
|
+
"planning/master-plan/approved",
|
|
36
|
+
"commands/active",
|
|
37
|
+
"commands/executed",
|
|
38
|
+
"audit/current",
|
|
39
|
+
"audit/legacy",
|
|
40
|
+
"reports/draft/html",
|
|
41
|
+
"reports/draft/written",
|
|
42
|
+
"reports/published/html",
|
|
43
|
+
"reports/published/written",
|
|
44
|
+
"design/audit/screenshots",
|
|
45
|
+
"design/language",
|
|
46
|
+
"design/resources",
|
|
47
|
+
"archive",
|
|
48
|
+
"private",
|
|
49
|
+
],
|
|
50
|
+
};
|
|
51
|
+
// The generic init file name (excluded from provider counting)
|
|
52
|
+
export const PRAXIS_INIT_FILENAME = "PRAXIS_INIT.md";
|
|
53
|
+
// Init file suffix for detecting provider-specific inits
|
|
54
|
+
export const INIT_FILE_SUFFIX = "_INIT.md";
|
|
55
|
+
// Work order file naming pattern: {number}_{YYYY-MM-DD}_{DESCRIPTION}.md
|
|
56
|
+
export const NAMING_REGEX = /^(\d+)_(\d{4}-\d{2}-\d{2})_(.+)\.md$/;
|
|
57
|
+
// Work order template used by create_work_order
|
|
58
|
+
export const WO_TEMPLATE = `# Work Order: {TITLE}
|
|
59
|
+
|
|
60
|
+
- **WO#:** {NUMBER}
|
|
61
|
+
- **Date Created:** {DATE}
|
|
62
|
+
- **Status:** Pending
|
|
63
|
+
- **Assigned To:** {ASSIGNED_TO}
|
|
64
|
+
- **Priority:** {PRIORITY}
|
|
65
|
+
|
|
66
|
+
## Description
|
|
67
|
+
|
|
68
|
+
{DESCRIPTION}
|
|
69
|
+
|
|
70
|
+
## Acceptance Criteria
|
|
71
|
+
|
|
72
|
+
{CRITERIA}
|
|
73
|
+
|
|
74
|
+
## Notes
|
|
75
|
+
|
|
76
|
+
`;
|
|
77
|
+
// Context capsule section headers (used for section-aware updates)
|
|
78
|
+
export const CAPSULE_SECTIONS = [
|
|
79
|
+
"Active Task",
|
|
80
|
+
"In-Progress Notes",
|
|
81
|
+
"Critical Rules",
|
|
82
|
+
"Key Workspace Paths",
|
|
83
|
+
"Last Session Summary",
|
|
84
|
+
];
|
|
85
|
+
// Checkpoint milestone table header
|
|
86
|
+
export const CHECKPOINT_TABLE_HEADER = "| # | Milestone | Date | Status |";
|
|
87
|
+
export const CHECKPOINT_TABLE_SEPARATOR = "|---|-----------|------|--------|";
|
|
88
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,+DAA+D;AAC/D,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,oBAAoB;IACpB,oBAAoB;IACpB,eAAe;CACP,CAAC;AAEX,sCAAsC;AACtC,MAAM,CAAC,MAAM,YAAY,GAA6B;IACpD,OAAO,EAAE;QACP,aAAa;QACb,sBAAsB;KACvB;IACD,QAAQ,EAAE;QACR,aAAa;QACb,sBAAsB;QACtB,iBAAiB;QACjB,kBAAkB;QAClB,4BAA4B;QAC5B,+BAA+B;QAC/B,iBAAiB;QACjB,mBAAmB;KACpB;IACD,IAAI,EAAE;QACJ,aAAa;QACb,sBAAsB;QACtB,iBAAiB;QACjB,kBAAkB;QAClB,4BAA4B;QAC5B,+BAA+B;QAC/B,iBAAiB;QACjB,mBAAmB;QACnB,eAAe;QACf,cAAc;QACd,oBAAoB;QACpB,uBAAuB;QACvB,wBAAwB;QACxB,2BAA2B;QAC3B,0BAA0B;QAC1B,iBAAiB;QACjB,kBAAkB;QAClB,SAAS;QACT,SAAS;KACV;CACF,CAAC;AAEF,+DAA+D;AAC/D,MAAM,CAAC,MAAM,oBAAoB,GAAG,gBAAgB,CAAC;AAErD,yDAAyD;AACzD,MAAM,CAAC,MAAM,gBAAgB,GAAG,UAAU,CAAC;AAE3C,yEAAyE;AACzE,MAAM,CAAC,MAAM,YAAY,GAAG,sCAAsC,CAAC;AAEnE,gDAAgD;AAChD,MAAM,CAAC,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;CAkB1B,CAAC;AAEF,mEAAmE;AACnE,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,aAAa;IACb,mBAAmB;IACnB,gBAAgB;IAChB,qBAAqB;IACrB,sBAAsB;CACd,CAAC;AAEX,oCAAoC;AACpC,MAAM,CAAC,MAAM,uBAAuB,GAAG,mCAAmC,CAAC;AAC3E,MAAM,CAAC,MAAM,0BAA0B,GAAG,mCAAmC,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Praxis MCP — Project Detection
|
|
3
|
+
*
|
|
4
|
+
* Detects adoption tier, operational mode, and configured providers.
|
|
5
|
+
* Ports the detection logic from praxis-lint.sh (lines 212-245) to TypeScript.
|
|
6
|
+
*/
|
|
7
|
+
export type Tier = "starter" | "standard" | "full" | "none";
|
|
8
|
+
export type Mode = "solo" | "triangle";
|
|
9
|
+
export interface ProjectDetection {
|
|
10
|
+
hasDevFolder: boolean;
|
|
11
|
+
tier: Tier;
|
|
12
|
+
mode: Mode;
|
|
13
|
+
providers: string[];
|
|
14
|
+
coreDocs: {
|
|
15
|
+
sourceOfTruth: boolean;
|
|
16
|
+
contextCapsule: boolean;
|
|
17
|
+
checkpoint: boolean;
|
|
18
|
+
};
|
|
19
|
+
hasLinter: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Detect the project's adoption tier based on which folders exist.
|
|
23
|
+
* Matches praxis-lint.sh detect_tier() exactly.
|
|
24
|
+
*/
|
|
25
|
+
export declare function detectTier(projectPath: string): Promise<Tier>;
|
|
26
|
+
/**
|
|
27
|
+
* Detect solo vs triangle mode by counting provider init files.
|
|
28
|
+
* Matches praxis-lint.sh detect_triangle_mode() exactly.
|
|
29
|
+
*
|
|
30
|
+
* Logic: count *_INIT.md files in dev/init/, excluding PRAXIS_INIT.md.
|
|
31
|
+
* 2+ provider init files = triangle mode.
|
|
32
|
+
*/
|
|
33
|
+
export declare function detectMode(projectPath: string): Promise<Mode>;
|
|
34
|
+
/**
|
|
35
|
+
* Detect which AI providers are configured by reading init file names.
|
|
36
|
+
* Extracts the provider name from the filename pattern: {PROVIDER}_INIT.md
|
|
37
|
+
*/
|
|
38
|
+
export declare function detectProviders(projectPath: string): Promise<string[]>;
|
|
39
|
+
/**
|
|
40
|
+
* Full project detection — combines tier, mode, providers, and core doc checks.
|
|
41
|
+
*/
|
|
42
|
+
export declare function detectProject(projectPath: string): Promise<ProjectDetection>;
|
|
43
|
+
//# sourceMappingURL=detection.d.ts.map
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Praxis MCP — Project Detection
|
|
3
|
+
*
|
|
4
|
+
* Detects adoption tier, operational mode, and configured providers.
|
|
5
|
+
* Ports the detection logic from praxis-lint.sh (lines 212-245) to TypeScript.
|
|
6
|
+
*/
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { readdir } from "node:fs/promises";
|
|
9
|
+
import { isDirectory, fileExists, resolveDevPath } from "./fs-helpers.js";
|
|
10
|
+
import { PRAXIS_INIT_FILENAME, INIT_FILE_SUFFIX } from "./constants.js";
|
|
11
|
+
/**
|
|
12
|
+
* Detect the project's adoption tier based on which folders exist.
|
|
13
|
+
* Matches praxis-lint.sh detect_tier() exactly.
|
|
14
|
+
*/
|
|
15
|
+
export async function detectTier(projectPath) {
|
|
16
|
+
const dev = resolveDevPath(projectPath);
|
|
17
|
+
if (!(await isDirectory(dev)))
|
|
18
|
+
return "none";
|
|
19
|
+
const hasAudit = await isDirectory(join(dev, "audit"));
|
|
20
|
+
const hasReports = await isDirectory(join(dev, "reports"));
|
|
21
|
+
const hasDesign = await isDirectory(join(dev, "design"));
|
|
22
|
+
const hasResearch = await isDirectory(join(dev, "research"));
|
|
23
|
+
const hasPlanning = await isDirectory(join(dev, "planning"));
|
|
24
|
+
if (hasAudit && hasReports && hasDesign)
|
|
25
|
+
return "full";
|
|
26
|
+
if (hasResearch && hasPlanning)
|
|
27
|
+
return "standard";
|
|
28
|
+
return "starter";
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Detect solo vs triangle mode by counting provider init files.
|
|
32
|
+
* Matches praxis-lint.sh detect_triangle_mode() exactly.
|
|
33
|
+
*
|
|
34
|
+
* Logic: count *_INIT.md files in dev/init/, excluding PRAXIS_INIT.md.
|
|
35
|
+
* 2+ provider init files = triangle mode.
|
|
36
|
+
*/
|
|
37
|
+
export async function detectMode(projectPath) {
|
|
38
|
+
const initDir = join(resolveDevPath(projectPath), "init");
|
|
39
|
+
if (!(await isDirectory(initDir)))
|
|
40
|
+
return "solo";
|
|
41
|
+
let providerCount = 0;
|
|
42
|
+
try {
|
|
43
|
+
const entries = await readdir(initDir);
|
|
44
|
+
for (const entry of entries) {
|
|
45
|
+
if (!entry.endsWith(INIT_FILE_SUFFIX))
|
|
46
|
+
continue;
|
|
47
|
+
if (entry === PRAXIS_INIT_FILENAME)
|
|
48
|
+
continue;
|
|
49
|
+
providerCount++;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return "solo";
|
|
54
|
+
}
|
|
55
|
+
return providerCount >= 2 ? "triangle" : "solo";
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Detect which AI providers are configured by reading init file names.
|
|
59
|
+
* Extracts the provider name from the filename pattern: {PROVIDER}_INIT.md
|
|
60
|
+
*/
|
|
61
|
+
export async function detectProviders(projectPath) {
|
|
62
|
+
const initDir = join(resolveDevPath(projectPath), "init");
|
|
63
|
+
if (!(await isDirectory(initDir)))
|
|
64
|
+
return [];
|
|
65
|
+
const providers = [];
|
|
66
|
+
try {
|
|
67
|
+
const entries = await readdir(initDir);
|
|
68
|
+
for (const entry of entries) {
|
|
69
|
+
if (!entry.endsWith(INIT_FILE_SUFFIX))
|
|
70
|
+
continue;
|
|
71
|
+
if (entry === PRAXIS_INIT_FILENAME)
|
|
72
|
+
continue;
|
|
73
|
+
// Extract provider name: "CLAUDE_INIT.md" -> "claude"
|
|
74
|
+
const name = entry.replace(INIT_FILE_SUFFIX, "").toLowerCase();
|
|
75
|
+
providers.push(name);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
// Return empty on error
|
|
80
|
+
}
|
|
81
|
+
return providers;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Full project detection — combines tier, mode, providers, and core doc checks.
|
|
85
|
+
*/
|
|
86
|
+
export async function detectProject(projectPath) {
|
|
87
|
+
const dev = resolveDevPath(projectPath);
|
|
88
|
+
const hasDevFolder = await isDirectory(dev);
|
|
89
|
+
if (!hasDevFolder) {
|
|
90
|
+
return {
|
|
91
|
+
hasDevFolder: false,
|
|
92
|
+
tier: "none",
|
|
93
|
+
mode: "solo",
|
|
94
|
+
providers: [],
|
|
95
|
+
coreDocs: { sourceOfTruth: false, contextCapsule: false, checkpoint: false },
|
|
96
|
+
hasLinter: false,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
const [tier, mode, providers] = await Promise.all([
|
|
100
|
+
detectTier(projectPath),
|
|
101
|
+
detectMode(projectPath),
|
|
102
|
+
detectProviders(projectPath),
|
|
103
|
+
]);
|
|
104
|
+
const [sotExists, capsuleExists, checkpointExists, linterExists] = await Promise.all([
|
|
105
|
+
fileExists(join(dev, "source_of_truth.md")),
|
|
106
|
+
fileExists(join(dev, "context_capsule.md")),
|
|
107
|
+
fileExists(join(dev, "checkpoint.md")),
|
|
108
|
+
fileExists(join(projectPath, ".praxis", "praxis-lint.sh")),
|
|
109
|
+
]);
|
|
110
|
+
return {
|
|
111
|
+
hasDevFolder: true,
|
|
112
|
+
tier,
|
|
113
|
+
mode,
|
|
114
|
+
providers,
|
|
115
|
+
coreDocs: {
|
|
116
|
+
sourceOfTruth: sotExists,
|
|
117
|
+
contextCapsule: capsuleExists,
|
|
118
|
+
checkpoint: checkpointExists,
|
|
119
|
+
},
|
|
120
|
+
hasLinter: linterExists,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=detection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detection.js","sourceRoot":"","sources":["../../src/lib/detection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Praxis MCP — Filesystem Helpers
|
|
3
|
+
*
|
|
4
|
+
* Safe file operations that never throw on missing files.
|
|
5
|
+
* All functions are stateless and work with absolute paths.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Read a file safely. Returns null if the file doesn't exist or can't be read.
|
|
9
|
+
*/
|
|
10
|
+
export declare function readFileSafe(filePath: string): Promise<string | null>;
|
|
11
|
+
/**
|
|
12
|
+
* Write a file safely, creating parent directories if needed.
|
|
13
|
+
*/
|
|
14
|
+
export declare function writeFileSafe(filePath: string, content: string): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Get file age in days. Returns null if the file doesn't exist.
|
|
17
|
+
*/
|
|
18
|
+
export declare function getFileAgeDays(filePath: string): Promise<number | null>;
|
|
19
|
+
/**
|
|
20
|
+
* Check if a file or directory exists.
|
|
21
|
+
*/
|
|
22
|
+
export declare function fileExists(filePath: string): Promise<boolean>;
|
|
23
|
+
/**
|
|
24
|
+
* Check if a path is a directory.
|
|
25
|
+
*/
|
|
26
|
+
export declare function isDirectory(filePath: string): Promise<boolean>;
|
|
27
|
+
/**
|
|
28
|
+
* List markdown files in a directory. Returns empty array if dir doesn't exist.
|
|
29
|
+
* Skips files starting with "0_" (reserved for READMEs/examples).
|
|
30
|
+
*/
|
|
31
|
+
export declare function listMarkdownFiles(dirPath: string, options?: {
|
|
32
|
+
includeExamples?: boolean;
|
|
33
|
+
}): Promise<string[]>;
|
|
34
|
+
/**
|
|
35
|
+
* List subdirectories matching a pattern in a directory.
|
|
36
|
+
*/
|
|
37
|
+
export declare function listSubdirectories(dirPath: string, prefix?: string): Promise<string[]>;
|
|
38
|
+
/**
|
|
39
|
+
* Ensure a directory exists, creating it recursively if needed.
|
|
40
|
+
* Returns true if the directory was created, false if it already existed.
|
|
41
|
+
*/
|
|
42
|
+
export declare function ensureDir(dirPath: string): Promise<boolean>;
|
|
43
|
+
/**
|
|
44
|
+
* Move a file from one path to another. Creates target directory if needed.
|
|
45
|
+
*/
|
|
46
|
+
export declare function moveFile(fromPath: string, toPath: string): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Get file size in bytes. Returns 0 if file doesn't exist.
|
|
49
|
+
*/
|
|
50
|
+
export declare function getFileSize(filePath: string): Promise<number>;
|
|
51
|
+
/**
|
|
52
|
+
* Check if a file was modified today (local timezone).
|
|
53
|
+
*/
|
|
54
|
+
export declare function wasModifiedToday(filePath: string): Promise<boolean>;
|
|
55
|
+
/**
|
|
56
|
+
* Resolve the dev/ folder path from a project root.
|
|
57
|
+
*/
|
|
58
|
+
export declare function resolveDevPath(projectPath: string): string;
|
|
59
|
+
//# sourceMappingURL=fs-helpers.d.ts.map
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Praxis MCP — Filesystem Helpers
|
|
3
|
+
*
|
|
4
|
+
* Safe file operations that never throw on missing files.
|
|
5
|
+
* All functions are stateless and work with absolute paths.
|
|
6
|
+
*/
|
|
7
|
+
import { readFile, writeFile, stat, readdir, mkdir, rename } from "node:fs/promises";
|
|
8
|
+
import { join, dirname } from "node:path";
|
|
9
|
+
/**
|
|
10
|
+
* Read a file safely. Returns null if the file doesn't exist or can't be read.
|
|
11
|
+
*/
|
|
12
|
+
export async function readFileSafe(filePath) {
|
|
13
|
+
try {
|
|
14
|
+
return await readFile(filePath, "utf-8");
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Write a file safely, creating parent directories if needed.
|
|
22
|
+
*/
|
|
23
|
+
export async function writeFileSafe(filePath, content) {
|
|
24
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
25
|
+
await writeFile(filePath, content, "utf-8");
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Get file age in days. Returns null if the file doesn't exist.
|
|
29
|
+
*/
|
|
30
|
+
export async function getFileAgeDays(filePath) {
|
|
31
|
+
try {
|
|
32
|
+
const stats = await stat(filePath);
|
|
33
|
+
const now = Date.now();
|
|
34
|
+
const mtime = stats.mtimeMs;
|
|
35
|
+
return Math.floor((now - mtime) / (1000 * 60 * 60 * 24));
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Check if a file or directory exists.
|
|
43
|
+
*/
|
|
44
|
+
export async function fileExists(filePath) {
|
|
45
|
+
try {
|
|
46
|
+
await stat(filePath);
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Check if a path is a directory.
|
|
55
|
+
*/
|
|
56
|
+
export async function isDirectory(filePath) {
|
|
57
|
+
try {
|
|
58
|
+
const stats = await stat(filePath);
|
|
59
|
+
return stats.isDirectory();
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* List markdown files in a directory. Returns empty array if dir doesn't exist.
|
|
67
|
+
* Skips files starting with "0_" (reserved for READMEs/examples).
|
|
68
|
+
*/
|
|
69
|
+
export async function listMarkdownFiles(dirPath, options = {}) {
|
|
70
|
+
try {
|
|
71
|
+
const entries = await readdir(dirPath);
|
|
72
|
+
return entries.filter((f) => {
|
|
73
|
+
if (!f.endsWith(".md"))
|
|
74
|
+
return false;
|
|
75
|
+
if (!options.includeExamples && f.startsWith("0_"))
|
|
76
|
+
return false;
|
|
77
|
+
return true;
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* List subdirectories matching a pattern in a directory.
|
|
86
|
+
*/
|
|
87
|
+
export async function listSubdirectories(dirPath, prefix) {
|
|
88
|
+
try {
|
|
89
|
+
const entries = await readdir(dirPath, { withFileTypes: true });
|
|
90
|
+
return entries
|
|
91
|
+
.filter((e) => e.isDirectory() && (!prefix || e.name.startsWith(prefix)))
|
|
92
|
+
.map((e) => e.name);
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return [];
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Ensure a directory exists, creating it recursively if needed.
|
|
100
|
+
* Returns true if the directory was created, false if it already existed.
|
|
101
|
+
*/
|
|
102
|
+
export async function ensureDir(dirPath) {
|
|
103
|
+
const existed = await isDirectory(dirPath);
|
|
104
|
+
if (!existed) {
|
|
105
|
+
await mkdir(dirPath, { recursive: true });
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Move a file from one path to another. Creates target directory if needed.
|
|
112
|
+
*/
|
|
113
|
+
export async function moveFile(fromPath, toPath) {
|
|
114
|
+
await mkdir(dirname(toPath), { recursive: true });
|
|
115
|
+
await rename(fromPath, toPath);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Get file size in bytes. Returns 0 if file doesn't exist.
|
|
119
|
+
*/
|
|
120
|
+
export async function getFileSize(filePath) {
|
|
121
|
+
try {
|
|
122
|
+
const stats = await stat(filePath);
|
|
123
|
+
return stats.size;
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
return 0;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Check if a file was modified today (local timezone).
|
|
131
|
+
*/
|
|
132
|
+
export async function wasModifiedToday(filePath) {
|
|
133
|
+
try {
|
|
134
|
+
const stats = await stat(filePath);
|
|
135
|
+
const mtime = new Date(stats.mtimeMs);
|
|
136
|
+
const today = new Date();
|
|
137
|
+
return (mtime.getFullYear() === today.getFullYear() &&
|
|
138
|
+
mtime.getMonth() === today.getMonth() &&
|
|
139
|
+
mtime.getDate() === today.getDate());
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Resolve the dev/ folder path from a project root.
|
|
147
|
+
*/
|
|
148
|
+
export function resolveDevPath(projectPath) {
|
|
149
|
+
return join(projectPath, "dev");
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=fs-helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs-helpers.js","sourceRoot":"","sources":["../../src/lib/fs-helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Praxis MCP — Naming Utilities
|
|
3
|
+
*
|
|
4
|
+
* File naming convention enforcement and work order numbering.
|
|
5
|
+
* Convention: {number}_{YYYY-MM-DD}_{DESCRIPTION}.{ext}
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Get today's date in ISO format (YYYY-MM-DD).
|
|
9
|
+
*/
|
|
10
|
+
export declare function todayISO(): string;
|
|
11
|
+
/**
|
|
12
|
+
* Convert a title string to UPPER_SNAKE_CASE.
|
|
13
|
+
* "Fix the authentication bug" -> "FIX_THE_AUTHENTICATION_BUG"
|
|
14
|
+
*/
|
|
15
|
+
export declare function toUpperSnakeCase(title: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Determine the next work order number from a list of existing filenames.
|
|
18
|
+
* Scans for the highest number prefix and returns highest + 1.
|
|
19
|
+
* Skips 0 (reserved for READMEs/examples). Minimum return is 1.
|
|
20
|
+
*/
|
|
21
|
+
export declare function nextWoNumber(existingFiles: string[]): number;
|
|
22
|
+
/**
|
|
23
|
+
* Format a filename per Praxis naming convention.
|
|
24
|
+
* Returns: "{number}_{YYYY-MM-DD}_{DESCRIPTION}.md"
|
|
25
|
+
*/
|
|
26
|
+
export declare function formatFilename(number: number, date: string, description: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* Validate whether a filename matches the Praxis naming convention.
|
|
29
|
+
*/
|
|
30
|
+
export declare function isValidPraxisFilename(filename: string): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Extract the number from a Praxis-convention filename.
|
|
33
|
+
* Returns null if the filename doesn't match the convention.
|
|
34
|
+
*/
|
|
35
|
+
export declare function extractNumber(filename: string): number | null;
|
|
36
|
+
//# sourceMappingURL=naming.d.ts.map
|