mcp-software-design 0.1.2 → 0.1.4
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/CHANGELOG.md +68 -0
- package/README.md +6 -16
- package/build/catalog.js +23 -0
- package/build/smells.js +26 -46
- package/package.json +8 -3
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- b3fc1f0: Releases are now automated with Changesets and published from GitHub Actions with provenance.
|
|
8
|
+
|
|
9
|
+
All notable changes to this project are documented here.
|
|
10
|
+
|
|
11
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
12
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
13
|
+
|
|
14
|
+
## [Unreleased]
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- Extracted an escape-aware `scanToUnescaped` scanner in the smell
|
|
19
|
+
tokenizer, collapsing three near-identical scan loops into one linear,
|
|
20
|
+
no-backtracking helper — internal refactor, no behavior change. (#13)
|
|
21
|
+
|
|
22
|
+
## [0.1.3] - 2026-07-31
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- `clean-code` umbrella concept in the catalog, tying the individual
|
|
27
|
+
cleanliness practices together. (#11)
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
|
|
31
|
+
- README: added badges and moved the install guide to the top, then
|
|
32
|
+
de-duplicated the install instructions so they live in one place.
|
|
33
|
+
(#9, #10)
|
|
34
|
+
|
|
35
|
+
## [0.1.2] - 2026-07-31
|
|
36
|
+
|
|
37
|
+
### Added
|
|
38
|
+
|
|
39
|
+
- `solid` and `oop` filters for the `list_catalog` tool. (#5)
|
|
40
|
+
- `meaningful-names` concept to the catalog, with refreshed docs. (#6)
|
|
41
|
+
|
|
42
|
+
### Changed
|
|
43
|
+
|
|
44
|
+
- Expanded the npm keywords for discoverability. (#7)
|
|
45
|
+
|
|
46
|
+
### Fixed
|
|
47
|
+
|
|
48
|
+
- Derive the server version from `package.json` so the reported version
|
|
49
|
+
always matches the published one. (#4)
|
|
50
|
+
|
|
51
|
+
## [0.1.1] - 2026-07-31
|
|
52
|
+
|
|
53
|
+
### Fixed
|
|
54
|
+
|
|
55
|
+
- Corrected the publish metadata so the package resolves cleanly on both
|
|
56
|
+
the npm and MCP registries. (#1)
|
|
57
|
+
|
|
58
|
+
## [0.1.0] - 2026-07-31
|
|
59
|
+
|
|
60
|
+
### Added
|
|
61
|
+
|
|
62
|
+
- Initial release: the software-design MCP server — a language-agnostic
|
|
63
|
+
catalog of SOLID / OOP / DRY principles and the 23 GoF design patterns,
|
|
64
|
+
the `list_catalog`, `explain_concept`, `scaffold_pattern`, and
|
|
65
|
+
`check_smells` tools, and the `design://` resources.
|
|
66
|
+
|
|
67
|
+
[Unreleased]: https://github.com/qwertymuzaffar/mcp-software-design/compare/v0.1.3...HEAD
|
|
68
|
+
[0.1.3]: https://github.com/qwertymuzaffar/mcp-software-design/releases/tag/v0.1.3
|
package/README.md
CHANGED
|
@@ -7,11 +7,12 @@
|
|
|
7
7
|
|
|
8
8
|
An [MCP](https://modelcontextprotocol.io) server that teaches and helps apply
|
|
9
9
|
**software-design guidance** — the SOLID principles, the OOP pillars, DRY /
|
|
10
|
-
KISS / YAGNI / meaningful naming, and the 23 Gang-of-Four design
|
|
10
|
+
KISS / YAGNI / meaningful naming / clean code, and the 23 Gang-of-Four design
|
|
11
|
+
patterns —
|
|
11
12
|
plus pattern scaffolding and heuristic code-smell detection.
|
|
12
13
|
|
|
13
14
|
It's the companion to
|
|
14
|
-
[`mcp-udacity-commit`](
|
|
15
|
+
[`mcp-udacity-commit`](https://github.com/qwertymuzaffar/mcp-udacity-commit): same stack (TypeScript, the MCP
|
|
15
16
|
SDK, stdio transport), same shape (pure logic modules + thin server wiring).
|
|
16
17
|
|
|
17
18
|
## Install
|
|
@@ -101,25 +102,14 @@ npm test # builds, then runs the unit tests
|
|
|
101
102
|
npm run test:client # end-to-end check against the built server
|
|
102
103
|
```
|
|
103
104
|
|
|
104
|
-
Then register the
|
|
105
|
+
Then register it the same way as [Install](#install) above — both the
|
|
106
|
+
`claude mcp add` command and the MCP-client-config form work — but point at
|
|
107
|
+
your local build instead of `npx`:
|
|
105
108
|
|
|
106
109
|
```bash
|
|
107
110
|
claude mcp add software-design -- node /absolute/path/to/mcp-software-design/build/index.js
|
|
108
111
|
```
|
|
109
112
|
|
|
110
|
-
Or in an MCP client config:
|
|
111
|
-
|
|
112
|
-
```json
|
|
113
|
-
{
|
|
114
|
-
"mcpServers": {
|
|
115
|
-
"software-design": {
|
|
116
|
-
"command": "node",
|
|
117
|
-
"args": ["/absolute/path/to/mcp-software-design/build/index.js"]
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
```
|
|
122
|
-
|
|
123
113
|
## Layout
|
|
124
114
|
|
|
125
115
|
```
|
package/build/catalog.js
CHANGED
|
@@ -189,6 +189,29 @@ export const PRINCIPLES = [
|
|
|
189
189
|
],
|
|
190
190
|
related: ["kiss", "single-responsibility", "separation-of-concerns"],
|
|
191
191
|
},
|
|
192
|
+
{
|
|
193
|
+
slug: "clean-code",
|
|
194
|
+
name: "Clean Code",
|
|
195
|
+
category: "principle",
|
|
196
|
+
aka: ["readability", "craftsmanship"],
|
|
197
|
+
summary: "Code is read far more than it's written — optimize for the reader.",
|
|
198
|
+
intent: "Clean Code is an umbrella habit, not a single rule: write code a later " +
|
|
199
|
+
"reader (usually you) can understand quickly and change safely. It's the " +
|
|
200
|
+
"sum of the concrete principles here — intention-revealing names, small " +
|
|
201
|
+
"single-purpose units, no duplication, and the simplest thing that works — " +
|
|
202
|
+
"rather than a separate technique of its own.",
|
|
203
|
+
whenToUse: [
|
|
204
|
+
"You hesitate to touch a file because you don't understand it.",
|
|
205
|
+
"Reviewers keep asking 'what does this do?' about the same code.",
|
|
206
|
+
"Reading the change takes longer than making it.",
|
|
207
|
+
],
|
|
208
|
+
tradeoffs: [
|
|
209
|
+
"'Clean' is contextual — a throwaway script and a core library deserve different bars.",
|
|
210
|
+
"Endless renaming/extracting has diminishing returns; stop once it reads clearly.",
|
|
211
|
+
"Cleanliness is not correctness — clean code can still be wrong; tests decide behavior.",
|
|
212
|
+
],
|
|
213
|
+
related: ["meaningful-names", "single-responsibility", "dry", "kiss"],
|
|
214
|
+
},
|
|
192
215
|
{
|
|
193
216
|
slug: "composition-over-inheritance",
|
|
194
217
|
name: "Composition Over Inheritance",
|
package/build/smells.js
CHANGED
|
@@ -31,6 +31,26 @@ const TYPE_KEYWORDS = new Set([
|
|
|
31
31
|
"class", "interface", "enum", "struct", "namespace", "module", "record",
|
|
32
32
|
"trait", "object", "protocol", "extension",
|
|
33
33
|
]);
|
|
34
|
+
/**
|
|
35
|
+
* From `start`, scan `line` for the next unescaped `delimiter`, treating `\x`
|
|
36
|
+
* as an escape pair (so `\"` or `` \` `` don't close the literal). Returns the
|
|
37
|
+
* delimiter's index with `closed: true` when found, otherwise the line length
|
|
38
|
+
* with `closed: false`. Single left-to-right scan — no backtracking, linear.
|
|
39
|
+
*/
|
|
40
|
+
function scanToUnescaped(line, start, delimiter) {
|
|
41
|
+
let scanIndex = start;
|
|
42
|
+
while (scanIndex < line.length) {
|
|
43
|
+
const char = line[scanIndex];
|
|
44
|
+
if (char === "\\") {
|
|
45
|
+
scanIndex += 2;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (char === delimiter)
|
|
49
|
+
return { end: scanIndex, closed: true };
|
|
50
|
+
scanIndex++;
|
|
51
|
+
}
|
|
52
|
+
return { end: line.length, closed: false };
|
|
53
|
+
}
|
|
34
54
|
/**
|
|
35
55
|
* Blank out string literals, line comments, and block comments so structural
|
|
36
56
|
* counters (braces, commas, numbers) don't trip over their contents. Returns
|
|
@@ -65,22 +85,9 @@ export function sanitize(lines) {
|
|
|
65
85
|
continue;
|
|
66
86
|
}
|
|
67
87
|
if (mode === "template") {
|
|
68
|
-
|
|
69
|
-
let closed = false;
|
|
70
|
-
while (scanIndex < lineLength) {
|
|
71
|
-
const char = rawLine[scanIndex];
|
|
72
|
-
if (char === "\\") {
|
|
73
|
-
scanIndex += 2;
|
|
74
|
-
continue;
|
|
75
|
-
}
|
|
76
|
-
if (char === "`") {
|
|
77
|
-
closed = true;
|
|
78
|
-
break;
|
|
79
|
-
}
|
|
80
|
-
scanIndex++;
|
|
81
|
-
}
|
|
88
|
+
const { end, closed } = scanToUnescaped(rawLine, cursor, "`");
|
|
82
89
|
if (closed) {
|
|
83
|
-
cursor =
|
|
90
|
+
cursor = end + 1;
|
|
84
91
|
mode = "code";
|
|
85
92
|
}
|
|
86
93
|
else {
|
|
@@ -115,41 +122,14 @@ export function sanitize(lines) {
|
|
|
115
122
|
continue;
|
|
116
123
|
}
|
|
117
124
|
if (char === '"' || char === "'") {
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
let closed = false;
|
|
121
|
-
while (scanIndex < lineLength) {
|
|
122
|
-
const stringChar = rawLine[scanIndex];
|
|
123
|
-
if (stringChar === "\\") {
|
|
124
|
-
scanIndex += 2;
|
|
125
|
-
continue;
|
|
126
|
-
}
|
|
127
|
-
if (stringChar === quote) {
|
|
128
|
-
closed = true;
|
|
129
|
-
break;
|
|
130
|
-
}
|
|
131
|
-
scanIndex++;
|
|
132
|
-
}
|
|
133
|
-
cursor = closed ? scanIndex + 1 : lineLength; // drop the string content
|
|
125
|
+
const { end, closed } = scanToUnescaped(rawLine, cursor + 1, char);
|
|
126
|
+
cursor = closed ? end + 1 : lineLength; // drop the string content
|
|
134
127
|
continue;
|
|
135
128
|
}
|
|
136
129
|
if (char === "`") {
|
|
137
|
-
|
|
138
|
-
let closed = false;
|
|
139
|
-
while (scanIndex < lineLength) {
|
|
140
|
-
const stringChar = rawLine[scanIndex];
|
|
141
|
-
if (stringChar === "\\") {
|
|
142
|
-
scanIndex += 2;
|
|
143
|
-
continue;
|
|
144
|
-
}
|
|
145
|
-
if (stringChar === "`") {
|
|
146
|
-
closed = true;
|
|
147
|
-
break;
|
|
148
|
-
}
|
|
149
|
-
scanIndex++;
|
|
150
|
-
}
|
|
130
|
+
const { end, closed } = scanToUnescaped(rawLine, cursor + 1, "`");
|
|
151
131
|
if (closed) {
|
|
152
|
-
cursor =
|
|
132
|
+
cursor = end + 1;
|
|
153
133
|
}
|
|
154
134
|
else {
|
|
155
135
|
mode = "template";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-software-design",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "MCP server that teaches and applies software-design guidance: SOLID/OOP/DRY principles, the 23 GoF design patterns, pattern scaffolding, and heuristic code-smell detection.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -33,7 +33,8 @@
|
|
|
33
33
|
},
|
|
34
34
|
"files": [
|
|
35
35
|
"build",
|
|
36
|
-
"README.md"
|
|
36
|
+
"README.md",
|
|
37
|
+
"CHANGELOG.md"
|
|
37
38
|
],
|
|
38
39
|
"engines": {
|
|
39
40
|
"node": ">=18"
|
|
@@ -44,13 +45,17 @@
|
|
|
44
45
|
"pretest": "npm run build",
|
|
45
46
|
"test": "node --test test/*.test.mjs",
|
|
46
47
|
"prepublishOnly": "npm test",
|
|
47
|
-
"test:client": "node test-client.mjs"
|
|
48
|
+
"test:client": "node test-client.mjs",
|
|
49
|
+
"changeset": "changeset",
|
|
50
|
+
"version-packages": "changeset version",
|
|
51
|
+
"release": "npm run build && changeset publish"
|
|
48
52
|
},
|
|
49
53
|
"dependencies": {
|
|
50
54
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
51
55
|
"zod": "^3.25.76"
|
|
52
56
|
},
|
|
53
57
|
"devDependencies": {
|
|
58
|
+
"@changesets/cli": "^3.0.2",
|
|
54
59
|
"@types/node": "^22.10.0",
|
|
55
60
|
"typescript": "^5.7.2"
|
|
56
61
|
}
|