@programinglive/dev-workflow-mcp-server 1.0.8 → 1.0.11

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/CONTRIBUTING.md CHANGED
@@ -1,60 +1,60 @@
1
- # Contributing to dev-workflow-mcp-server
2
-
3
- Thanks for your interest in contributing! Follow the guidelines below to keep the development process smooth and aligned with the workflow enforced by this project.
4
-
5
- ## Development Workflow
6
-
7
- 1. **Start a task** using the MCP server's `start_task` tool with a clear description and task type.
8
- 2. **Implement the change** following the single flow rules documented in the README.
9
- 3. **Write or update tests**. All code changes must include tests when applicable.
10
- 4. **Run tests** with `npm test` and ensure they pass.
11
- 5. **Document changes**. Update `README.md` or other docs as needed.
12
- 6. **Commit** following conventional commits (e.g., `feat: add new tool`).
13
- 7. **Push** your branch and open a pull request using the provided template.
14
-
15
- ## Getting Started
16
-
17
- - Fork the repository and clone it locally.
18
- - Install dependencies:
19
-
20
- ```bash
21
- npm install
22
- ```
23
-
24
- - Run the test suite to verify your setup:
25
-
26
- ```bash
27
- npm test
28
- ```
29
-
30
- ## Pull Requests
31
-
32
- - Use a descriptive branch name (e.g., `feat/new-tool` or `fix/workflow-reset`).
33
- - Fill out the pull request template completely, including tests and documentation details.
34
- - Link related issues in the PR description.
35
- - Ensure CI checks pass before requesting review.
36
-
37
- ## Coding Standards
38
-
39
- - Use TypeScript-friendly patterns even in JavaScript (avoid dynamic typing pitfalls).
40
- - Remove unused imports and variables before committing.
41
- - Follow existing code style and formatting.
42
-
43
- ## Commit Messages
44
-
45
- - Follow [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/).
46
- - Example: `feat: enforce documentation reminder before commit`.
47
-
48
- ## Reporting Issues
49
-
50
- - Search open issues to avoid duplicates.
51
- - When filing a bug, include reproduction steps, expected behavior, and environment details.
52
- - Feature requests should explain the problem being solved and potential benefits.
53
-
54
- ## Code of Conduct
55
-
56
- By participating, you agree to abide by the [Code of Conduct](./CODE_OF_CONDUCT.md).
57
-
58
- ## Contact
59
-
60
- Questions? Reach out at `opensource@programinglive.com`.
1
+ # Contributing to dev-workflow-mcp-server
2
+
3
+ Thanks for your interest in contributing! Follow the guidelines below to keep the development process smooth and aligned with the workflow enforced by this project.
4
+
5
+ ## Development Workflow
6
+
7
+ 1. **Start a task** using the MCP server's `start_task` tool with a clear description and task type.
8
+ 2. **Implement the change** following the single flow rules documented in the README.
9
+ 3. **Write or update tests**. All code changes must include tests when applicable.
10
+ 4. **Run tests** with `npm test` and ensure they pass.
11
+ 5. **Document changes**. Update `README.md` or other docs as needed.
12
+ 6. **Commit** following conventional commits (e.g., `feat: add new tool`).
13
+ 7. **Push** your branch and open a pull request using the provided template.
14
+
15
+ ## Getting Started
16
+
17
+ - Fork the repository and clone it locally.
18
+ - Install dependencies:
19
+
20
+ ```bash
21
+ npm install
22
+ ```
23
+
24
+ - Run the test suite to verify your setup:
25
+
26
+ ```bash
27
+ npm test
28
+ ```
29
+
30
+ ## Pull Requests
31
+
32
+ - Use a descriptive branch name (e.g., `feat/new-tool` or `fix/workflow-reset`).
33
+ - Fill out the pull request template completely, including tests and documentation details.
34
+ - Link related issues in the PR description.
35
+ - Ensure CI checks pass before requesting review.
36
+
37
+ ## Coding Standards
38
+
39
+ - Use TypeScript-friendly patterns even in JavaScript (avoid dynamic typing pitfalls).
40
+ - Remove unused imports and variables before committing.
41
+ - Follow existing code style and formatting.
42
+
43
+ ## Commit Messages
44
+
45
+ - Follow [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/).
46
+ - Example: `feat: enforce documentation reminder before commit`.
47
+
48
+ ## Reporting Issues
49
+
50
+ - Search open issues to avoid duplicates.
51
+ - When filing a bug, include reproduction steps, expected behavior, and environment details.
52
+ - Feature requests should explain the problem being solved and potential benefits.
53
+
54
+ ## Code of Conduct
55
+
56
+ By participating, you agree to abide by the [Code of Conduct](./CODE_OF_CONDUCT.md).
57
+
58
+ ## Contact
59
+
60
+ Questions? Reach out at `opensource@programinglive.com`.
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 programinglive
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2025 programinglive
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,66 +1,66 @@
1
- # Development Workflow MCP Server
2
-
3
- An MCP (Model Context Protocol) server that helps enforce development discipline and workflow best practices. This server acts as your coding conscience, reminding you to follow proper development workflows.
4
-
5
- ## 🎯 Purpose
6
-
7
- This MCP server guides you through a disciplined development workflow:
8
-
9
- 1. **Start Conscious** - Be clear about what you're coding
10
- 2. **Fix/Implement** - Write your code
11
- 3. **Create Tests** - Always test your changes
12
- 4. **Run Tests** - Tests must pass (GREEN)
13
- 5. **Document** - Update documentation
14
- 6. **Commit & Push** - Let the server drive the git commands once verification passes
15
- 7. **Release** - Record the release details before closing out the task
16
-
17
- ## 🚀 Installation
18
-
19
- ### 1. Install Dependencies
20
-
21
- ```bash
22
- npm install
23
- ```
24
-
25
- ### 2. Configure in Windsurf/Claude Desktop
26
-
27
- Point your MCP client to the server entry point. Replace `<PROJECT_ROOT>` with the absolute path to this repository on your machine.
28
-
29
- #### macOS
30
-
31
- - **Windsurf** (`~/Library/Application Support/Windsurf/config.json`):
32
-
33
- ```json
34
- {
35
- "mcpServers": {
36
- "dev-workflow": {
37
- "command": "node",
38
- "args": ["<PROJECT_ROOT>/index.js"]
39
- }
40
- }
41
- }
42
- ```
43
-
44
- - **Claude Desktop** (`~/Library/Application Support/Claude/claude_desktop_config.json`):
45
-
46
- ```json
47
- {
48
- "mcpServers": {
49
- "dev-workflow": {
50
- "command": "node",
51
- "args": ["<PROJECT_ROOT>/index.js"]
52
- }
53
- }
54
- }
55
- ```
56
-
57
- #### Windows
58
-
59
- - **Windsurf** (`%APPDATA%\Windsurf\config.json`):
60
-
61
- ```json
62
- {
63
- "mcpServers": {
1
+ # Development Workflow MCP Server
2
+
3
+ An MCP (Model Context Protocol) server that helps enforce development discipline and workflow best practices. This server acts as your coding conscience, reminding you to follow proper development workflows.
4
+
5
+ ## 🎯 Purpose
6
+
7
+ This MCP server guides you through a disciplined development workflow:
8
+
9
+ 1. **Start Conscious** - Be clear about what you're coding
10
+ 2. **Fix/Implement** - Write your code
11
+ 3. **Create Tests** - Always test your changes
12
+ 4. **Run Tests** - Tests must pass (GREEN)
13
+ 5. **Document** - Update documentation
14
+ 6. **Commit & Push** - Let the server drive the git commands once verification passes
15
+ 7. **Release** - Record the release details before closing out the task
16
+
17
+ ## 🚀 Installation
18
+
19
+ ### 1. Install Dependencies
20
+
21
+ ```bash
22
+ npm install
23
+ ```
24
+
25
+ ### 2. Configure in Windsurf/Claude Desktop
26
+
27
+ Point your MCP client to the server entry point. Replace `<PROJECT_ROOT>` with the absolute path to this repository on your machine.
28
+
29
+ #### macOS
30
+
31
+ - **Windsurf** (`~/Library/Application Support/Windsurf/config.json`):
32
+
33
+ ```json
34
+ {
35
+ "mcpServers": {
36
+ "dev-workflow": {
37
+ "command": "node",
38
+ "args": ["<PROJECT_ROOT>/index.js"]
39
+ }
40
+ }
41
+ }
42
+ ```
43
+
44
+ - **Claude Desktop** (`~/Library/Application Support/Claude/claude_desktop_config.json`):
45
+
46
+ ```json
47
+ {
48
+ "mcpServers": {
49
+ "dev-workflow": {
50
+ "command": "node",
51
+ "args": ["<PROJECT_ROOT>/index.js"]
52
+ }
53
+ }
54
+ }
55
+ ```
56
+
57
+ #### Windows
58
+
59
+ - **Windsurf** (`%APPDATA%\Windsurf\config.json`):
60
+
61
+ ```json
62
+ {
63
+ "mcpServers": {
64
64
  "dev-workflow": {
65
65
  "command": "node",
66
66
  "args": ["<PROJECT_ROOT>\\index.js"]
@@ -333,6 +333,7 @@ The server maintains state in `.workflow-state.json`:
333
333
  - History of completed tasks
334
334
 
335
335
  This file is automatically created and managed by the server.
336
+ It contains local, machine-specific progress and is ignored by git so each environment can manage its own workflow history without cross-contamination.
336
337
 
337
338
  ## 🤝 Integration with Your Rules
338
339
 
package/SECURITY.md CHANGED
@@ -1,20 +1,20 @@
1
- # Security Policy
2
-
3
- ## Supported Versions
4
-
5
- We release patches for security vulnerabilities under new minor or patch versions. Always use the latest release.
6
-
7
- ## Reporting a Vulnerability
8
-
9
- If you discover a vulnerability, please email `security@programinglive.com` with:
10
-
11
- - Description of the issue
12
- - Steps to reproduce
13
- - Potential impact
14
- - Suggested remediation (if known)
15
-
16
- We aim to acknowledge reports within 72 hours and will keep you informed as we work on a fix. Please do not disclose the vulnerability publicly until we have released an update.
17
-
18
- ## Disclosure Policy
19
-
20
- Once a fix is available, we will publish a security advisory in the repository releases and notify contributors via the README.
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ We release patches for security vulnerabilities under new minor or patch versions. Always use the latest release.
6
+
7
+ ## Reporting a Vulnerability
8
+
9
+ If you discover a vulnerability, please email `security@programinglive.com` with:
10
+
11
+ - Description of the issue
12
+ - Steps to reproduce
13
+ - Potential impact
14
+ - Suggested remediation (if known)
15
+
16
+ We aim to acknowledge reports within 72 hours and will keep you informed as we work on a fix. Please do not disclose the vulnerability publicly until we have released an update.
17
+
18
+ ## Disclosure Policy
19
+
20
+ Once a fix is available, we will publish a security advisory in the repository releases and notify contributors via the README.
@@ -0,0 +1,166 @@
1
+ function formatFileList(paths) {
2
+ const uniquePaths = [...new Set(paths.filter(Boolean))];
3
+
4
+ if (uniquePaths.length === 0) {
5
+ return "updates";
6
+ }
7
+
8
+ if (uniquePaths.length === 1) {
9
+ return uniquePaths[0];
10
+ }
11
+
12
+ if (uniquePaths.length === 2) {
13
+ return `${uniquePaths[0]} and ${uniquePaths[1]}`;
14
+ }
15
+
16
+ if (uniquePaths.length === 3) {
17
+ return `${uniquePaths[0]}, ${uniquePaths[1]}, and ${uniquePaths[2]}`;
18
+ }
19
+
20
+ const remaining = uniquePaths.length - 3;
21
+ return `${uniquePaths[0]}, ${uniquePaths[1]}, ${uniquePaths[2]} +${remaining} more`;
22
+ }
23
+
24
+ function determineCommitType(changes) {
25
+ const hasTestChange = changes.some((change) =>
26
+ [change.path, change.originalPath].some((p) => isTestFilePath(p))
27
+ );
28
+ const hasDocsChange = changes.some((change) =>
29
+ [change.path, change.originalPath].some((p) => isDocumentationFilePath(p))
30
+ );
31
+
32
+ if (hasTestChange) {
33
+ return "test";
34
+ }
35
+
36
+ if (hasDocsChange) {
37
+ return "docs";
38
+ }
39
+
40
+ return "chore";
41
+ }
42
+
43
+ function isTestFilePath(filePath) {
44
+ if (!filePath) {
45
+ return false;
46
+ }
47
+
48
+ if (/\.(test|spec)\.[^.]+$/i.test(filePath)) {
49
+ return true;
50
+ }
51
+
52
+ return /(\/|^)(__tests__|tests?|spec)\//i.test(filePath);
53
+ }
54
+
55
+ function isDocumentationFilePath(filePath) {
56
+ if (!filePath) {
57
+ return false;
58
+ }
59
+
60
+ const normalized = filePath.toLowerCase();
61
+ return (
62
+ normalized.startsWith("docs/") ||
63
+ normalized.startsWith("documentation/") ||
64
+ normalized.endsWith(".md") ||
65
+ normalized.endsWith(".rst") ||
66
+ normalized.endsWith(".adoc") ||
67
+ normalized.includes("readme")
68
+ );
69
+ }
70
+
71
+ function describeChange(change) {
72
+ const statusCode = change.status || "";
73
+ const path = change.path || change.originalPath || "";
74
+
75
+ if (statusCode.startsWith("R")) {
76
+ return `renamed ${change.originalPath} -> ${change.path}`;
77
+ }
78
+
79
+ if (statusCode.startsWith("C")) {
80
+ return `copied ${change.originalPath} -> ${change.path}`;
81
+ }
82
+
83
+ switch (statusCode[0]) {
84
+ case "A":
85
+ return `added ${path}`;
86
+ case "M":
87
+ return `modified ${path}`;
88
+ case "D":
89
+ return `removed ${path}`;
90
+ case "U":
91
+ return `updated ${path}`;
92
+ default:
93
+ return `${statusCode} ${path}`.trim();
94
+ }
95
+ }
96
+
97
+ export function createCommitMessageParts(changes, providedSummary = "") {
98
+ const summaryInput = typeof providedSummary === "string" ? providedSummary.trim() : "";
99
+
100
+ if (!Array.isArray(changes) || changes.length === 0) {
101
+ return {
102
+ summary: summaryInput,
103
+ body: "",
104
+ };
105
+ }
106
+
107
+ const commitType = determineCommitType(changes);
108
+ const summaryPaths = changes
109
+ .map((change) => change.path || change.originalPath)
110
+ .filter(Boolean);
111
+ const generatedSummary = `${commitType}: update ${formatFileList(summaryPaths)}`;
112
+ const summary = summaryInput || generatedSummary;
113
+
114
+ const detailLines = changes
115
+ .map((change) => describeChange(change))
116
+ .filter((line) => line && line.trim().length > 0)
117
+ .map((line) => `- ${line}`);
118
+
119
+ return {
120
+ summary,
121
+ body: detailLines.join("\n"),
122
+ };
123
+ }
124
+
125
+ function normalizeCommitHeader(message) {
126
+ if (typeof message !== "string") {
127
+ return "";
128
+ }
129
+
130
+ const header = message.split("\n")[0] || "";
131
+ return header.trim();
132
+ }
133
+
134
+ function containsBreakingChange(message) {
135
+ if (typeof message !== "string") {
136
+ return false;
137
+ }
138
+
139
+ return /breaking change/i.test(message);
140
+ }
141
+
142
+ export function determineReleaseTypeFromCommit(message) {
143
+ const header = normalizeCommitHeader(message).toLowerCase();
144
+ const hasBreaking = containsBreakingChange(message) || /!/.test(header.split(":")[0] || "");
145
+
146
+ if (hasBreaking) {
147
+ return "major";
148
+ }
149
+
150
+ const typeMatch = header.match(/^([a-z]+)(\(|:)/i);
151
+ const commitType = typeMatch ? typeMatch[1] : "";
152
+
153
+ if (commitType === "feat") {
154
+ return "minor";
155
+ }
156
+
157
+ if (commitType === "fix" || commitType === "perf") {
158
+ return "patch";
159
+ }
160
+
161
+ if (!commitType && containsBreakingChange(message)) {
162
+ return "major";
163
+ }
164
+
165
+ return "patch";
166
+ }
@@ -1,3 +1,3 @@
1
- export default {
2
- extends: ["@commitlint/config-conventional"],
3
- };
1
+ export default {
2
+ extends: ["@commitlint/config-conventional"],
3
+ };
package/exec.js ADDED
@@ -0,0 +1,4 @@
1
+ import { exec as execCallback } from "child_process";
2
+ import { promisify } from "util";
3
+
4
+ export const exec = promisify(execCallback);
package/git-helpers.js ADDED
@@ -0,0 +1,152 @@
1
+ import { exec } from "./exec.js";
2
+
3
+ export async function hasStagedChanges() {
4
+ try {
5
+ const { stdout } = await exec("git status --porcelain");
6
+ return stdout
7
+ .split("\n")
8
+ .filter(Boolean)
9
+ .some((line) => {
10
+ const indexStatus = line[0];
11
+ return indexStatus && indexStatus !== " " && indexStatus !== "?";
12
+ });
13
+ } catch (error) {
14
+ return false;
15
+ }
16
+ }
17
+
18
+ export async function hasWorkingChanges() {
19
+ try {
20
+ const { stdout } = await exec("git status --porcelain");
21
+ return stdout.split("\n").some((line) => line && line.trim().length > 0);
22
+ } catch (error) {
23
+ return false;
24
+ }
25
+ }
26
+
27
+ export function workingTreeSummary(statusOutput) {
28
+ if (typeof statusOutput !== "string" || statusOutput.trim() === "") {
29
+ return {
30
+ hasChanges: false,
31
+ lines: [],
32
+ };
33
+ }
34
+
35
+ const lines = statusOutput
36
+ .split("\n")
37
+ .map((line) => line.replace(/\s+/g, " ").trim())
38
+ .filter(Boolean);
39
+
40
+ return {
41
+ hasChanges: lines.length > 0,
42
+ lines,
43
+ };
44
+ }
45
+
46
+ function isTestFilePath(filePath) {
47
+ if (!filePath) {
48
+ return false;
49
+ }
50
+
51
+ if (/\.(test|spec)\.[^.]+$/i.test(filePath)) {
52
+ return true;
53
+ }
54
+
55
+ return /(\/|^)(__tests__|tests?|spec)\//i.test(filePath);
56
+ }
57
+
58
+ function extractPathFromStatusLine(line) {
59
+ if (!line || line.length < 4) {
60
+ return "";
61
+ }
62
+
63
+ const rawPath = line.slice(3).trim();
64
+ if (!rawPath) {
65
+ return "";
66
+ }
67
+
68
+ if (rawPath.includes(" -> ")) {
69
+ const parts = rawPath.split(" -> ");
70
+ return parts[parts.length - 1].trim();
71
+ }
72
+
73
+ return rawPath;
74
+ }
75
+
76
+ export function containsTestFilesInStatus(statusOutput) {
77
+ if (typeof statusOutput !== "string" || statusOutput.trim() === "") {
78
+ return false;
79
+ }
80
+
81
+ return statusOutput
82
+ .split("\n")
83
+ .map((line) => extractPathFromStatusLine(line))
84
+ .some((path) => isTestFilePath(path));
85
+ }
86
+
87
+ function parseNameStatusLine(line) {
88
+ if (!line) {
89
+ return null;
90
+ }
91
+
92
+ const parts = line.split("\t").map((part) => part.trim());
93
+ const status = parts[0];
94
+ if (!status) {
95
+ return null;
96
+ }
97
+
98
+ if (status.startsWith("R") || status.startsWith("C")) {
99
+ const originalPath = parts[1] || "";
100
+ const newPath = parts[2] || originalPath;
101
+ return {
102
+ status,
103
+ path: newPath,
104
+ originalPath,
105
+ };
106
+ }
107
+
108
+ return {
109
+ status,
110
+ path: parts[1] || "",
111
+ originalPath: "",
112
+ };
113
+ }
114
+
115
+ export async function getStagedChanges() {
116
+ try {
117
+ const { stdout } = await exec("git diff --cached --name-status");
118
+ return stdout
119
+ .split("\n")
120
+ .map((line) => parseNameStatusLine(line))
121
+ .filter(Boolean);
122
+ } catch (error) {
123
+ return [];
124
+ }
125
+ }
126
+
127
+ export async function hasTestChanges() {
128
+ try {
129
+ const { stdout } = await exec("git status --porcelain");
130
+ return containsTestFilesInStatus(stdout);
131
+ } catch (error) {
132
+ return false;
133
+ }
134
+ }
135
+
136
+ export async function getLastCommitMessage() {
137
+ try {
138
+ const { stdout } = await exec("git log -1 --pretty=%B");
139
+ return stdout.trim();
140
+ } catch (error) {
141
+ return "";
142
+ }
143
+ }
144
+
145
+ export async function getCurrentBranch() {
146
+ try {
147
+ const { stdout } = await exec("git rev-parse --abbrev-ref HEAD");
148
+ return stdout.trim();
149
+ } catch (error) {
150
+ return "";
151
+ }
152
+ }