mcp-software-design 0.1.1 → 0.1.3

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 CHANGED
@@ -1,14 +1,41 @@
1
1
  # mcp-software-design
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/mcp-software-design)](https://www.npmjs.com/package/mcp-software-design)
4
+ [![npm downloads](https://img.shields.io/npm/dm/mcp-software-design)](https://www.npmjs.com/package/mcp-software-design)
5
+ [![License: MIT](https://img.shields.io/npm/l/mcp-software-design)](./LICENSE)
6
+ [![MCP](https://img.shields.io/badge/MCP-server-blue)](https://modelcontextprotocol.io)
7
+
3
8
  An [MCP](https://modelcontextprotocol.io) server that teaches and helps apply
4
9
  **software-design guidance** — the SOLID principles, the OOP pillars, DRY /
5
- KISS / YAGNI, and the 23 Gang-of-Four design patterns — plus pattern
6
- scaffolding and heuristic code-smell detection.
10
+ KISS / YAGNI / meaningful naming / clean code, and the 23 Gang-of-Four design
11
+ patterns
12
+ plus pattern scaffolding and heuristic code-smell detection.
7
13
 
8
14
  It's the companion to
9
- [`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
10
16
  SDK, stdio transport), same shape (pure logic modules + thin server wiring).
11
17
 
18
+ ## Install
19
+
20
+ Register it with Claude Code — one line, nothing to clone:
21
+
22
+ ```bash
23
+ claude mcp add software-design -- npx -y mcp-software-design
24
+ ```
25
+
26
+ Or in an MCP client config:
27
+
28
+ ```json
29
+ {
30
+ "mcpServers": {
31
+ "software-design": {
32
+ "command": "npx",
33
+ "args": ["-y", "mcp-software-design"]
34
+ }
35
+ }
36
+ }
37
+ ```
38
+
12
39
  ## Why this exists — and its one honest caveat
13
40
 
14
41
  The commit server can *lint*: "subject ≤ 50 chars" is objectively checkable.
@@ -33,7 +60,8 @@ pretending to understand your snippet.
33
60
  ## Tools
34
61
 
35
62
  - **`list_catalog`** `{ kind? }` — list concepts, optionally filtered
36
- (`principle` | `pattern` | `creational` | `structural` | `behavioral`).
63
+ (`principle` | `solid` | `oop` | `pattern` | `creational` | `structural` |
64
+ `behavioral`). `solid` / `oop` narrow to the SOLID five / the four OOP pillars.
37
65
  - **`explain_concept`** `{ name }` — full guidance for one principle or
38
66
  pattern (intent, when-to-use, trade-offs, participants). Accepts a slug,
39
67
  name, or alias (`"SRP"`, `"open-closed"`, `"pubsub"`).
@@ -47,7 +75,8 @@ pretending to understand your snippet.
47
75
 
48
76
  ## Resources
49
77
 
50
- - **`design://principles`** — SOLID, OOP pillars, DRY, KISS, YAGNI, and more.
78
+ - **`design://principles`** — SOLID, OOP pillars, DRY, KISS, YAGNI, meaningful
79
+ naming, and more.
51
80
  - **`design://patterns`** — the 23 GoF patterns, grouped creational /
52
81
  structural / behavioral.
53
82
  - **`design://smells`** — what `check_smells` detects, its thresholds, and its
@@ -60,7 +89,10 @@ pretending to understand your snippet.
60
89
  - **`apply_pattern`** `{ pattern, code }` — refactor a snippet to apply a named
61
90
  pattern (and first judge whether it even fits).
62
91
 
63
- ## Install & run
92
+ ## Build from source
93
+
94
+ For local development, or to run a local checkout instead of the published
95
+ package:
64
96
 
65
97
  ```bash
66
98
  npm install
@@ -70,25 +102,14 @@ npm test # builds, then runs the unit tests
70
102
  npm run test:client # end-to-end check against the built server
71
103
  ```
72
104
 
73
- ### Register 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`:
74
108
 
75
109
  ```bash
76
110
  claude mcp add software-design -- node /absolute/path/to/mcp-software-design/build/index.js
77
111
  ```
78
112
 
79
- Or in an MCP client config:
80
-
81
- ```json
82
- {
83
- "mcpServers": {
84
- "software-design": {
85
- "command": "node",
86
- "args": ["/absolute/path/to/mcp-software-design/build/index.js"]
87
- }
88
- }
89
- }
90
- ```
91
-
92
113
  ## Layout
93
114
 
94
115
  ```
package/build/catalog.js CHANGED
@@ -166,6 +166,52 @@ export const PRINCIPLES = [
166
166
  ],
167
167
  related: ["kiss", "open-closed"],
168
168
  },
169
+ {
170
+ slug: "meaningful-names",
171
+ name: "Meaningful Names",
172
+ category: "principle",
173
+ aka: ["intention-revealing-names", "naming", "self-documenting-code"],
174
+ summary: "Names should reveal intent — reach for a word before a comment.",
175
+ intent: "A name is the first documentation a reader meets. Prefer intention-" +
176
+ "revealing names that state what a value is or what a function does, so " +
177
+ "the code explains itself without a comment. Single-letter names are fine " +
178
+ "in tiny scopes — loop counters, short lambda parameters, coordinates/math " +
179
+ "— but hide meaning the moment a value outlives a line or two.",
180
+ whenToUse: [
181
+ "A variable needs a comment to explain what it holds.",
182
+ "You reach for `data`, `tmp`, `mgr`, or `x2` because the real name is hard.",
183
+ "A single-letter name is used far from where it was declared.",
184
+ ],
185
+ tradeoffs: [
186
+ "Over-long names (userAccountRepositoryFactoryInstance) hurt readability as much as cryptic ones.",
187
+ "Conventional short names beat forced verbosity — `i` in a for-loop, `e` for an event.",
188
+ "Renaming for clarity is cheap; keep established public/API names stable to avoid churn.",
189
+ ],
190
+ related: ["kiss", "single-responsibility", "separation-of-concerns"],
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
+ },
169
215
  {
170
216
  slug: "composition-over-inheritance",
171
217
  name: "Composition Over Inheritance",
@@ -854,6 +900,34 @@ export const PATTERNS = [
854
900
  * Lookup + rendering
855
901
  * ------------------------------------------------------------------ */
856
902
  export const ALL = [...PRINCIPLES, ...PATTERNS];
903
+ /** The five SOLID principles, by slug. */
904
+ const SOLID_SLUGS = new Set([
905
+ "single-responsibility",
906
+ "open-closed",
907
+ "liskov-substitution",
908
+ "interface-segregation",
909
+ "dependency-inversion",
910
+ ]);
911
+ /** The four classic OOP pillars, by slug. */
912
+ const OOP_SLUGS = new Set([
913
+ "encapsulation",
914
+ "abstraction",
915
+ "inheritance",
916
+ "polymorphism",
917
+ ]);
918
+ /**
919
+ * Which sub-group a concept belongs to. Patterns and the remaining principles
920
+ * (DRY, KISS, YAGNI, composition-over-inheritance, law-of-demeter,
921
+ * separation-of-concerns) are "general". Drives the "solid"/"oop" filters on
922
+ * the list_catalog tool.
923
+ */
924
+ export function principleGroup(concept) {
925
+ if (SOLID_SLUGS.has(concept.slug))
926
+ return "solid";
927
+ if (OOP_SLUGS.has(concept.slug))
928
+ return "oop";
929
+ return "general";
930
+ }
857
931
  /** Normalize a query for fuzzy matching: lowercase, strip non-alphanumerics. */
858
932
  function normalize(text) {
859
933
  return text.toLowerCase().replace(/[^a-z0-9]+/g, "");
package/build/index.js CHANGED
@@ -1,11 +1,18 @@
1
1
  #!/usr/bin/env node
2
+ import { readFileSync } from "node:fs";
2
3
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
4
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
5
  import { z } from "zod";
5
- import { ALL, CATEGORY_LABEL, conceptLine, conceptToMarkdown, findConcept, principlesMarkdown, patternsMarkdown, } from "./catalog.js";
6
+ import { ALL, CATEGORY_LABEL, conceptLine, conceptToMarkdown, findConcept, principleGroup, principlesMarkdown, patternsMarkdown, } from "./catalog.js";
6
7
  import { detectSmells, DEFAULTS } from "./smells.js";
7
8
  import { scaffoldPattern } from "./scaffold.js";
8
- const VERSION = "0.1.0";
9
+ /**
10
+ * Single source of truth: read the version from package.json at startup so it
11
+ * can never drift from the published package. Resolved relative to this module,
12
+ * so it works both from `build/` in the repo and from the installed package
13
+ * (npm ships package.json alongside build/).
14
+ */
15
+ const VERSION = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")).version;
9
16
  /** Human-readable summary of what the smell checker looks for. */
10
17
  const SMELLS_GUIDE = `# Code-smell heuristics (design://smells)
11
18
 
@@ -65,9 +72,11 @@ export function createServer() {
65
72
  "kind. Returns each concept's slug, name, category, and one-line summary.",
66
73
  inputSchema: {
67
74
  kind: z
68
- .enum(["all", "principle", "pattern", "creational", "structural", "behavioral"])
75
+ .enum(["all", "principle", "solid", "oop", "pattern", "creational", "structural", "behavioral"])
69
76
  .optional()
70
- .describe('Filter by kind. "pattern" = all GoF patterns. Default "all".'),
77
+ .describe('Filter by kind. "principle" = all principles; "solid"/"oop" narrow ' +
78
+ 'to the SOLID five / the four OOP pillars; "pattern" = all GoF ' +
79
+ 'patterns. Default "all".'),
71
80
  },
72
81
  outputSchema: {
73
82
  count: z.number(),
@@ -85,6 +94,10 @@ export function createServer() {
85
94
  return true;
86
95
  if (selectedKind === "principle")
87
96
  return concept.category === "principle";
97
+ if (selectedKind === "solid")
98
+ return principleGroup(concept) === "solid";
99
+ if (selectedKind === "oop")
100
+ return principleGroup(concept) === "oop";
88
101
  if (selectedKind === "pattern")
89
102
  return concept.category !== "principle";
90
103
  return concept.category === selectedKind;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-software-design",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
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",
@@ -12,13 +12,21 @@
12
12
  },
13
13
  "keywords": [
14
14
  "mcp",
15
+ "mcp-server",
15
16
  "modelcontextprotocol",
17
+ "model-context-protocol",
18
+ "claude",
19
+ "developer-tools",
20
+ "software-design",
16
21
  "design-patterns",
22
+ "design-principles",
17
23
  "solid",
18
24
  "oop",
19
25
  "gof",
26
+ "gang-of-four",
20
27
  "refactoring",
21
- "claude"
28
+ "clean-code",
29
+ "code-smells"
22
30
  ],
23
31
  "bin": {
24
32
  "mcp-software-design": "build/index.js"