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 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 patterns —
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`](../mcp-udacity-commit): same stack (TypeScript, the MCP
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 local build with Claude Code:
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
- let scanIndex = cursor;
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 = scanIndex + 1;
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 quote = char;
119
- let scanIndex = cursor + 1;
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
- let scanIndex = cursor + 1;
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 = scanIndex + 1;
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.2",
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
  }