Content
# Oh-My-OOP
**MCP Server for Responsibility-Driven Design (RDD) workshops.**
Guides the flow from use cases to responsibilities, collaborations, and class diagrams, presenting **N alternatives with trade-offs for every design decision**, rather than a single answer. Based on teachings from *Objects* and *The Facts and Misconceptions of Object-Oriented Programming* by Cho Youngho.
- Target Language: **Kotlin** (no code generation, modeling only)
- Storage: `.oop/*.md` in the user's project root (Markdown + YAML frontmatter + Mermaid)
- Change Visualization: Before/After Mermaid `classDiagram` vertical stack with color emphasis
- Validation: Responsibility appropriateness / coupling / testability (all recommendations, no changes blocked)
- 📚 **References:**
- [lessons/woowacourse-racingcar](lessons/woowacourse-racingcar/) — `woowacourse/kotlin-racingcar` 133 PR reviews ([SUMMARY](lessons/woowacourse-racingcar/SUMMARY.md))
- [lessons/woowacourse-kotlin-lotto](lessons/woowacourse-kotlin-lotto/) — `woowacourse/kotlin-lotto` 141 PR reviews (including code snippets) ([SUMMARY](lessons/woowacourse-kotlin-lotto/SUMMARY.md))
---
## Quick Installation — Guide for AI Assistants
> **To AI:** If a user asks you to "install this MCP," follow these steps exactly. All commands are non-interactive, and `<...>` placeholders should be replaced with actual paths/names.
### 0. Prerequisites
- **Node.js 18.17 or higher** (`node --version`)
- **git** (`git --version`)
If either is missing, inform the user and stop.
### 1. Clone & Build
```bash
git clone https://github.com/<OWNER>/Oh-My-OOP.git
cd Oh-My-OOP
npm install
npm run build
npm test
```
- `npm test` must pass all 38 tests.
- The build output is `dist/index.js`. **Use this file's absolute path in all subsequent configurations**.
To get the absolute path after installation:
```bash
# From the cloned directory:
echo "$(pwd)/dist/index.js"
```
Use this output value as `<ABSOLUTE_PATH_TO_dist/index.js>` in client-specific settings below.
---
## Client-Specific Registration
### Claude Code (CLI) — User scope (for all projects)
```bash
claude mcp add --scope user oh-my-oop -- node <ABSOLUTE_PATH_TO_dist/index.js>
```
Verification:
```bash
claude mcp get oh-my-oop
# Status: ✓ Connected indicates success
```
Removal: `claude mcp remove oh-my-oop -s user`
### Claude Desktop (Mac/Windows)
Settings file location:
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
Add the following to the `mcpServers` key (preserve existing entries):
```json
{
"mcpServers": {
"oh-my-oop": {
"command": "node",
"args": ["<ABSOLUTE_PATH_TO_dist/index.js>"]
}
}
}
```
Restart Claude Desktop after making changes.
### Codex CLI (OpenAI)
Add the following section to `~/.codex/config.toml`:
```toml
[mcp_servers.oh-my-oop]
command = "node"
args = ["<ABSOLUTE_PATH_TO_dist/index.js>"]
```
Restart Codex CLI and verify registration with `/mcp`.
### Cursor / Other MCP Hosts
Supports the same JSON structure (`command` + `args`) as Claude Desktop. Add the same entry to the host's MCP server settings.
---
## Workspace Location — Where `.oop/` is created
The server determines the project root in the following order:
1. If the `OOP_PROJECT_ROOT` environment variable is set, use its path.
2. Otherwise, use the server process's current working directory (determined by the host).
**To fix per project:**
Client settings can specify this via environment variables:
**Claude Desktop / Cursor (JSON):**
```json
{
"oh-my-oop": {
"command": "node",
"args": ["<ABSOLUTE_PATH_TO_dist/index.js>"],
"env": {
"OOP_PROJECT_ROOT": "<ABSOLUTE_PATH_TO_USER_PROJECT>"
}
}
}
```
**Codex (TOML):**
```toml
[mcp_servers.oh-my-oop]
command = "node"
args = ["<ABSOLUTE_PATH_TO_dist/index.js>"]
env = { OOP_PROJECT_ROOT = "<ABSOLUTE_PATH_TO_USER_PROJECT>" }
```
**Claude Code (CLI):**
```bash
claude mcp add --scope user oh-my-oop -e OOP_PROJECT_ROOT=<ABSOLUTE_PATH_TO_USER_PROJECT> -- node <ABSOLUTE_PATH_TO_dist/index.js>
```
---
## Starting the Workshop
Call the `rdd-workshop-intro` prompt on the host to begin the guide.
Direct tool invocation sequence:
```
1. oop_init({ project: "<project_name>" })
2. oop_use_case_add({ title, actor, main_flow: [...] })
3. oop_propose_responsibilities({ use_case_id, n: 3 }) # 3 alternatives + trade-offs
4. oop_class_upsert({ name, stereotype, responsibilities, collaborators })
5. oop_collaboration_define({ from, to, message })
6. oop_diagram_generate({}) # Current Mermaid classDiagram
7. oop_propose_alternatives({ question, context, n }) # Trade-off engine (general-purpose)
8. oop_design_compare({ before, after }) # Before/After color emphasis
9. oop_design_validate({}) # Always recommended, with ≥2 remedies
```
---
## Exposed MCP Interface
### Tools (13)
| Tool | Side effects | Avoids single answer |
|---|---|---|
| `oop_init` | `.oop/` bootstrap | — |
| `oop_use_case_add` | `.oop/use-cases/<id>.md` | — |
| `oop_use_case_list` | None | — |
| `oop_propose_responsibilities` | None | ✅ N alternatives |
| `oop_assign_responsibility` | CRC update | — |
| `oop_class_upsert` | `.oop/classes/<id>.md` | — |
| `oop_class_list` | None | — |
| `oop_collaboration_define` | `.oop/collaborations/...md` | — |
| `oop_propose_alternatives` | None | ✅ Trade-off engine |
| `oop_diagram_generate` | `.oop/diagrams/current.mmd` | — |
| `oop_design_compare` | None | — |
| `oop_design_validate` | None | ✅ remedies ≥ 2 |
| `oop_state_read` | None | — |
### Resources
- `oop://design/index`, `oop://design/diagram`
- `oop://design/classes`, `oop://design/classes/{id}`
- `oop://design/use-cases`, `oop://design/use-cases/{id}`
- `oop://design/collaborations`
- `oop://design/history`, `oop://design/history/{file}`
### Prompts
- `rdd-workshop-intro` — Workshop introduction + Stereotype overview
- `responsibility-discovery` — Use case → CRC sketch N alternatives
- `design-review-cho-younghos-lens` — Design review with Cho Youngho's lens
---
## Validation Rules (15, all with ≥2 remedies)
**Basic 10:** `god-object`, `mixed-stereotype`, `low-cohesion`, `too-many-collaborators`, `feature-envy`, `non-newable`, `side-effect-in-holder`, `mocking-pressure`, `cycle`, `orphan-class`.
**Additional 5** (extracted from 133 PR analysis of Woowacourse racingcar):
- `vague-class-name` — Detection of ambiguous general terms like Manager/Helper/Util/Validator
- `validation-misplacement` — Validation responsibility distribution between UI/Coordinator/Domain
- `dependency-direction` — Domain→Interfacer reverse dependency (only Coordinator allowed)
- `data-source-duplication` — Two cards knowing the same domain information from different sources (distributed truth)
- `function-not-object` — Classes with only one behavior and no members are essentially functions
Thresholds can be overridden in `.oop/design.md` frontmatter:
```yaml
thresholds:
god_object_responsibilities: 7
god_object_collaborators: 6
cohesion_min_overlap: 0.2
too_many_collaborators: 4
mocking_pressure_max: 2
data_duplication_overlap: 0.5
```
See [lessons/STYLE_GUIDE.md](lessons/STYLE_GUIDE.md) for detailed design principles.
---
## Core Philosophy (from Cho Youngho's lectures)
Principles embedded in the tool's behavior:
- **"Design is finding answers under constraints, not finding the correct answer."**
→ All `propose_*` tools return N alternatives + trade-offs + Cho Youngho's lens (cohesion/coupling/testability).
- **"Code control belongs to developers."**
→ `oop_design_validate` always recommends, never blocks changes.
- **"Testability is the criterion for good code."**
→ Measured by `non-newable`, `side-effect-in-holder`, `mocking-pressure` rules.
- **"Excessive mocking indicates bad code."**
→ Detected by `mocking-pressure` rule, suggests seam introduction alternatives.
- **"Tell-Don't-Ask"**
→ `collaboration_shape` seed's first option, recommended mode for collaboration definition.
---
## Directory Structure (generated `.oop/`)
```
<project-root>/.oop/
├── design.md # Index (frontmatter cross-ref)
├── use-cases/<id>.md
├── classes/<id>.md # CRC cards (knowing/doing + collaborators)
├── collaborations/<from>__<verb>__<to>.md
├── diagrams/current.mmd # Current Mermaid classDiagram
└── history/<ISO>__<label>.mmd # Snapshots of previous changes
```
Each file is Markdown + YAML frontmatter, **reviewable directly by humans**. Committing `.oop/` to git preserves design evolution in the history.
---
## Troubleshooting
| Symptom | Cause / Action |
|---|---|
| `Status: ✗ Failed to connect` | Verify `node <path>` executes directly. Ensure `dist/index.js` exists (has been built). |
| `OOP_PROJECT_ROOT does not exist` | Environment variable path must exist. Use absolute paths. |
| "Design index not found" on tool invocation | Call `oop_init` first to create `.oop/`. |
| Empty Mermaid diagram | Call `oop_diagram_generate` after adding classes to update `current.mmd`. |
| Corrupted Korean IDs | May be due to macOS NFC/NFD differences. Tool input is normalized to NFC. |
---
## Development
```bash
npm run dev # Execute ts directly with tsx (during development)
npm run build # Compile to dist/
npm test # Run vitest
npm run test:watch # Watch mode for vitest
```
When contributing, ensure all `propose_*` / `validate` changes **do not provide a single answer** (enforced by `assertHasMultipleRemedies`, verified by tests).
---
## License
MIT.