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 +41 -20
- package/build/catalog.js +74 -0
- package/build/index.js +17 -4
- package/package.json +10 -2
package/README.md
CHANGED
|
@@ -1,14 +1,41 @@
|
|
|
1
1
|
# mcp-software-design
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/mcp-software-design)
|
|
4
|
+
[](https://www.npmjs.com/package/mcp-software-design)
|
|
5
|
+
[](./LICENSE)
|
|
6
|
+
[](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
|
|
6
|
-
|
|
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`](
|
|
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` |
|
|
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,
|
|
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
|
-
##
|
|
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
|
-
|
|
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
|
-
|
|
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. "
|
|
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.
|
|
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
|
-
"
|
|
28
|
+
"clean-code",
|
|
29
|
+
"code-smells"
|
|
22
30
|
],
|
|
23
31
|
"bin": {
|
|
24
32
|
"mcp-software-design": "build/index.js"
|