Skip to main content
Glama
theSharque
by theSharque
README.md
# MCP Architector

[![npm version](https://img.shields.io/npm/v/mcp-architector.svg)](https://www.npmjs.com/package/mcp-architector)
[![GitHub](https://img.shields.io/github/license/theSharque/mcp-architect)](https://github.com/theSharque/mcp-architect)

> Model Context Protocol (MCP) server for architecture and system design

**Local-first MCP server** that stores and manages project architecture information. All data is stored locally in `~/.mcp-architector` for maximum privacy and confidentiality.

πŸ“¦ **Install**: `npm install -g mcp-architector` or use via npx
🌐 **npm**: https://www.npmjs.com/package/mcp-architector
πŸ”— **GitHub**: https://github.com/theSharque/mcp-architect

## How to connect to Claude Desktop / IDE

Add the server to your MCP config. Example for **claude_desktop_config.json**:

**macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
**Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
**Linux:** `~/.config/Claude/claude_desktop_config.json`

```json
{
  "mcpServers": {
    "architector": {
      "command": "npx",
      "args": ["-y", "mcp-architector"],
      "env": {
        "MCP_PROJECT_ID": "${workspaceFolder}"
      }
    }
  }
}
```

For **Cursor IDE**: Settings β†’ Features β†’ Model Context Protocol β†’ Edit Config, then add the same block inside `mcpServers`. See the [Integration](#integration) section for more options.

## Cursor rule (recommended)

For **Cursor IDE** and **Cursor Cloud Agents**, use a phased onboarding rule so the agent does not dump the whole repo into context in one shot.

1. Copy [`.cursor/rules/architector-onboarding.mdc`](.cursor/rules/architector-onboarding.mdc) into **your project** (the repo you are documenting):

   ```bash
   mkdir -p /path/to/your-app/.cursor/rules
   cp /path/to/mcp-architector/.cursor/rules/architector-onboarding.mdc /path/to/your-app/.cursor/rules/
   ```

2. Ensure MCP Architector is connected. The agent must call `list-projects` and pass `projectId` on every write β€” do not rely on omitting it.

3. Ask in chat, for example: *"Onboard this repo into architector β€” phase 0 plan first"* or *"Import architecture module by module"*.

The rule is **`alwaysApply: false`** β€” Cursor attaches it when the task matches architecture import/onboarding. It enforces: structure β†’ one module per step β†’ `validate` after each step β†’ compact tools only.

If you develop **this** server repo, keep the same file here so contributors and Cloud Agents follow the same workflow when updating `~/.mcp-architector/_qs_mcp-architector/`.

## Overview

Store and manage project architecture, modules, scripts, data flow, and usage examples - all locally with complete privacy.

## Features

- **Local Storage**: All data stored in `~/.mcp-architector` (privacy-first)
- **Project Architecture**: Store and retrieve overall project architecture
- **Module Details**: Detailed information about each module
- **Resources**: Access architecture data via resources

## Storage Structure

```
~/.mcp-architector/
└── {projectId}/
    β”œβ”€β”€ architecture.json      # Modules + dataFlow (vertical structure)
    β”œβ”€β”€ modules/
    β”‚   β”œβ”€β”€ {moduleId}.json
    β”‚   └── ...
    β”œβ”€β”€ entries/
    β”‚   β”œβ”€β”€ index.json         # Catalog (no duplicate bodies)
    β”‚   └── {entryId}.json     # Canonical facts (API, domain, flows, …)
    β”œβ”€β”€ slices/
    β”‚   └── {sliceId}.json     # Custom filters only (no items)
```

## Data model

| Layer | Purpose | Tools |
|-------|---------|-------|
| **Modules** | Vertical structure: components, dependencies, dataFlow | `set-project-architecture`, `set-module-details`, `set-module-data-flow`, `rebuild-data-flow`, `validate-architecture` |
| **Entries** | Single source of truth for horizontal facts (one fact = one file) | `set-entry`, `set-entries`, `get-entry`, `list-entries` |
| **Slices** | Read-only views over entries (built-in or custom filters) | `list-slices`, `get-slice` |

**Anti-patterns (no duplication):** Do not copy `module.description` into `entry.summary`. Link with `refs.moduleName`. Slices never store item copiesβ€”only filters in `slices/*.json`.

**Do not edit `~/.mcp-architector` directly** β€” always use MCP tools so timestamps, merge semantics, and dataFlow inverse sync stay consistent.

## Agent workflow

1. `list-projects` β€” find `projectId` for this workspace (query by folder name). Pass it to every other tool. Never omit. Never use `default-project`.
2. **Structure task** β†’ `get-project-architecture` / `set-project-architecture`.
3. **Each module** β†’ `set-module-details` with `files` + **`facts[]`** (endpoints, entities, glossary) in the same call, or `set-entries` / `set-entry` with `refs.moduleName`.
4. **Single module graph edge** β†’ `set-module-data-flow`.
5. **Bulk rebuild flow (many modules)** β†’ `rebuild-data-flow`.
6. **After edits, verify everything** β†’ `validate` (summary + `issues[]`; no full project load).
7. **Need a category** (all APIs, all domain terms) β†’ `list-slices` β†’ `get-slice` with `format=compact` or `table`; use `offset` when `hasMore` is true.
8. **Find by name** β†’ `search-entries` β†’ `get-entry` for full payload.
9. **After code refactor (same modules)** β†’ `refactor-architecture`: `scan` β†’ dryRun preview β†’ apply with `confirm=true`.

| Scenario | Tool |
|----------|------|
| Update one module + its APIs/facts | `set-module-details` with `facts[]` |
| Bulk facts for a domain | `set-entries` with `moduleName` |
| Patch dataFlow for one module | `set-module-data-flow` |
| Rebuild all module edges | `rebuild-data-flow` |
| Diagnose graph + empty slices | `validate` (or `validate-architecture`) |
| Catalog JSON corrupt (extra data after JSON) | `fix-data` |
| Sync paths/names after refactor | `refactor-architecture` (dryRun, then confirm) |
| Index out of sync | `rebuild-entry-index` |
| Create project from scratch | `set-project-architecture` with `replaceModules: true` |
| Onboard a fresh git clone (phased) | Copy [`.cursor/rules/architector-onboarding.mdc`](.cursor/rules/architector-onboarding.mdc) β†’ ask agent to onboard phase by phase |

**Full project picture:** modules alone do not populate slices β€” without `http-endpoint` (and other kinds) entries, slice `api` stays empty. New module β†’ add `facts` or entries in the same step.

Example: `set-module-details` with `facts: [{ kind: "http-endpoint", title: "POST /orders", ... }]`, then `get-slice` `sliceId=api` `format=table`.

## Quick Start

### For Users (using npm package)

```bash
# No installation needed - use directly in Cursor/Claude Desktop
# Just configure it as described in Integration section below
```

### For Developers

1. Clone the repository:
```bash
git clone https://github.com/theSharque/mcp-architect.git
cd mcp-architect
```

2. Install dependencies:
```bash
npm install
```

3. Build the project:
```bash
npm run build
```

## Usage

### Development Mode

Run with hot reload:
```bash
npm run dev
```

### Production Mode

Start the server:
```bash
npm start
```

### MCP Inspector

Debug and test your server with the MCP Inspector:
```bash
npm run inspector
```

## Integration

### Cursor IDE

1. Open Cursor Settings β†’ Features β†’ Model Context Protocol
2. Click "Edit Config" button
3. Add one of the configurations below

#### Option 1: Via npm (Recommended)

Installs from npm registry automatically:

```json
{
  "mcpServers": {
    "architector": {
      "command": "npx",
      "args": ["-y", "mcp-architector"],
      "env": {
        "MCP_PROJECT_ID": "${workspaceFolder}"
      }
    }
  }
}
```

#### Option 2: Via npm link (Development)

For local development with live changes:

```json
{
  "mcpServers": {
    "architector": {
      "command": "mcp-architector",
      "env": {
        "MCP_PROJECT_ID": "${workspaceFolder}"
      }
    }
  }
}
```

Requires: `cd /path/to/mcp-architector && npm link -g`

#### Option 3: Direct path

```json
{
  "mcpServers": {
    "architector": {
      "command": "node",
      "args": ["/path/to/mcp-architector/dist/index.js"],
      "env": {
        "MCP_PROJECT_ID": "${workspaceFolder}"
      }
    }
  }
}
```

### Claude Desktop

Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):

```json
{
  "mcpServers": {
    "architector": {
      "command": "npx",
      "args": ["-y", "mcp-architector"],
      "env": {
        "MCP_PROJECT_ID": "${workspaceFolder}"
      }
    }
  }
}
```

### Continue.dev

Edit `.continue/config.json`:

```json
{
  "mcpServers": {
    "architector": {
      "command": "npx",
      "args": ["-y", "mcp-architector"],
      "env": {
        "MCP_PROJECT_ID": "${workspaceFolder}"
      }
    }
  }
}
```

### Using Project ID

`projectId` is **required** on every tool except `list-projects`. There is no default dump project.

1. **Call `list-projects` first** (optionally with `query` = workspace folder name)
2. **Pass the matching `projectId`** to every other tool
3. If none matches, create one with `set-project-architecture` using a stable id from the workspace path (e.g. `_qs_my-app`)

`MCP_PROJECT_ID` is only a hint (`isCurrent` / `suggestedProjectId`). It is **not** used as a silent write target. `default-project` and unsubstituted `${workspaceFolder}` ids are forbidden.

## Tools

### set-project-architecture

Creates or updates the overall architecture for a project. **By default merges** modules and dataFlow by name; omit `dataFlow` to preserve existing flow. `dependsOn` is canonical; `providesTo` is recomputed on save.

**Input:**
- `projectId` (required): Project ID from `list-projects`. Never omit. `default-project` is forbidden.
- `description`: Overall project description
- `modules`: Array of module objects with:
  - `name`: Module name
  - `description`: Brief description of the module
  - `inputs` (optional): What this module requires to work
  - `outputs` (optional): What this module produces or generates
- `dataFlow` (optional): Object describing data flow between modules (omit to keep existing):
  - Key: module name
  - Value: object with:
    - `dependsOn` (optional): Array of module names this module depends on
    - `providesTo` (optional): Derived on save from all `dependsOn` edges
    - `dataTransformation` (optional): How data is transformed between modules
- `replaceModules` (optional): Replace entire modules list (default `false` = merge by name)
- `replaceDataFlow` (optional): Replace entire dataFlow (default `false` = merge by module name)

**Output:**
- Project ID and success message

### get-project-architecture

Retrieves the overall architecture of the project.

**Input:**
- `projectId` (required): Project ID from `list-projects`. Never omit. `default-project` is forbidden.

**Output:**
- Complete project architecture

### list-projects

Lists all projects in local storage (`~/.mcp-architector`). **Call this first.** Match the current workspace by folder name, then pass `projectId` to every other tool.

**Input:**
- `query` (optional): Filter by substring in projectId or description (case-insensitive)

**Output:**
- `projects[]`: `projectId`, `description`, `moduleCount`, `updatedAt`, `isCurrent` (hint from `MCP_PROJECT_ID`), `forbidden` (`default-project` and unsubstituted workspaceFolder dumps)
- `suggestedProjectId`: current `MCP_PROJECT_ID` when it is a valid id, else `null`
- `reminder`: always pass `projectId`; never use `default-project`

### Entries and slices

| Tool | Purpose |
|------|---------|
| `set-entry` | Upsert one fact; response may include `reminder` if modules missing or unlinked |
| `set-entries` | Bulk upsert (max 200); optional `moduleName` sets `refs.moduleName` on all |
| `get-entry` | Full entry by `id` |
| `delete-entry` | Remove entry |
| `list-entries` | Catalog without payload; filter by `kind`, `tags`, `query` |
| `search-entries` | Compact text search with `snippet`, `slices`, `moduleName`, pagination; filters: `moduleName`, `kind`, `tags` |
| `list-slices` | Built-in + custom slices with entry counts |
| `get-slice` | Filtered view: `sliceId`, `format`, `query`, `limit`, `offset`, `hasMore` |
| `set-slice` | Save custom filter (`kinds`, `tags`) β€” no items |
| `delete-slice` | Remove custom slice |
| `rebuild-entry-index` | Rebuild `entries/index.json` from entry files |
| `fix-data` | Repair leftover/corrupt catalog JSON; rebuild index |

**Built-in `sliceId` values:** `api`, `persistence`, `events`, `domain`, `flows`, `integrations`, `config`, `runtime`, `decisions`, `scripts`.

### search-entries

Compact navigation searchβ€”returns enough context to pick a hit, then call `get-entry` for full payload.

**Input:** `query` (required), `moduleName`, `kind`, `tags`, `limit` (default 10, max 50), `offset` (default 0)

**Output:** `summary`, `total`, `returned`, `offset`, `hasMore`, `results[]` with `snippet`, `matchedIn`, `slices`, `moduleName` plus legacy `summary`, `tags`, `refs`

**Recommended `kind` examples (any string allowed):**

| sliceId | kinds |
|---------|-------|
| api | `http-endpoint`, `grpc-method`, `mcp-tool`, `cli-command`, … |
| persistence | `db-table`, `entity`, `repository` |
| domain | `glossary`, `invariant`, `lifecycle` |
| scripts | `script` β€” use `set-entry` / `get-slice sliceId=scripts` |

### set-module-details

Creates or updates detailed information about a module. **Slices read entries, not module text** β€” pass `facts[]` to create linked entries in one call.

**Input:**
- `projectId` (required): Project ID from `list-projects`
- `name`: Module name
- `description`: Detailed description of the module
- `inputs`: What the module accepts as input
- `outputs`: What the module produces as output
- `dependencies` (optional): List of module dependencies (syncs to `dataFlow.dependsOn` when provided)
- `files` (optional): List of files belonging to this module
- `facts` (optional): Array of horizontal facts (`kind`, `title`, `summary`, …) β€” each upserted as entry with `refs.moduleName` = module name
- `usageExamples` (optional): Array of usage examples with fields:
  - `title`: Example title
  - `description` (optional): Description of the example
  - `command` (optional): Command or code snippet
  - `input` (optional): Input data
  - `output` (optional): Expected output
  - `notes` (optional): Additional notes about the example
- `notes` (optional): Additional notes

**Output:**
- Module ID and success message

### set-module-data-flow

Patches `dataFlow` for a single module without sending the full architecture.

**Input:**
- `projectId` (required): Project ID from `list-projects`
- `moduleName`: Module name
- `dependsOn` (optional): Modules this module depends on (canonical)
- `dataTransformation` (optional): How data is transformed
- `syncInverse` (optional): Recompute `providesTo` (default `true`)

**Output:**
- Module name and success message

### rebuild-data-flow

Rebuilds `dataFlow` for all modules from module file `dependencies` or existing `dependsOn` edges. Replaces bulk manual edits to `architecture.json`.

**Input:**
- `projectId` (required): Project ID from `list-projects`
- `source` (optional): `module-dependencies` (default) or `dataFlow-dependsOn`
- `syncInverse` (optional): Recompute `providesTo` (default `true`)
- `pruneOrphans` (optional): Remove invalid module references (default `true`)

**Output:**
- `edgesAdded`, `edgesRemoved`, `modulesUpdated`, message

### validate

**Primary post-edit check.** Read-only validation with a compact agent-friendly report. Does not modify data.

**Checks (only rules we can verify from stored JSON):**
- dataFlow: inverse drift, dangling `dependsOn`/`providesTo`, orphan flow keys
- `module.dependencies` vs `dataFlow.dependsOn`
- entries: `entries-without-modules`, `entry-unlinked`, `orphan-entry-module`, `module-no-entries`, `module-missing-api` / `module-missing-persistence`, `entry-slice-orphan`, `module-too-many-entries`, `module-too-few-entries`
- storage: missing `modules/{id}.json`, orphan module files, entry index drift
- slices: empty built-in `api` / `domain` / `persistence` when modules exist

**Input:** `projectId`, `checkInverse`, `checkModuleDeps`, `checkEntryCoverage`, `checkStorage`, `checkEmptySlices`, `checkSliceCoverage`, `checkModuleEntryCounts`, `moduleEntryMax` (default `50`), `moduleEntryMin` (optional; omit to disable min check) β€” all boolean flags default `true` unless noted

**Output:** `valid`, `issueCount`, `summary`, `stats`, `issuesByKind`, `issues[]`, `coverage`, `checksRun`

### fix-data

Run when catalog JSON is corrupt (for example `list-modules` / `validate` fail with extra data after JSON). Trims leftover bytes after the first valid JSON object in `architecture.json`, `modules/`, `entries/`, and `slices/`; removes leftover `.tmp` files; rebuilds the entry index. Does not delete facts. Catalog writes use temp+rename so this leftover cannot recur.

**Input:** `projectId`, `dryRun` (optional, default `false`)

**Output:** `summary`, `scanned`, `repaired`, `unreadable`, `tmpRemoved`, `indexItemCount`, `files[]` (repaired/unreadable only)

### refactor-architecture

Preview or apply in-architector sync after a code refactor when module boundaries stay the same. Agent is the source of truth β€” no workspace or git access. Default `dryRun=true`.

**Workflow:** (1) `scan` with `file` or `text` β†’ compact hits, (2) build mutation ops, (3) dryRun preview, (4) apply with `dryRun=false` and `confirm=true`.

**Operations (max 10 per call):** `scan`, `move-file`, `replace-path-prefix`, `rename-text`, `patch-entry`, `merge-files`, `remove-file-ref`.

**Scope (optional):** `moduleName`, `kinds`, `tags` β€” limits which entries/modules are touched.

Orphan entries with empty `refs.files` and no `refs.entryIds` are deleted after file operations.

**Input:** `projectId`, `operations[]`, `scope`, `dryRun` (default `true`), `confirm` (required when applying), `limit`, `offset`

**Output:** `summary`, `stats`, `hits` (scan) or paginated `changes`, `warnings`, `hasMore`

### validate-architecture

Same as `validate` (legacy alias). Prefer `validate` after edits.

**Output:**
- `valid` (boolean), `issues` array

### get-module-details

Retrieves detailed information about a specific module.

**Input:**
- `projectId` (required): Project ID from `list-projects`
- `moduleName`: Name of the module to retrieve

**Output:**
- Complete module details

### list-modules

Lists all modules in the project architecture.

**Input:**
- `projectId` (required): Project ID from `list-projects`

**Output:**
- Array of module summaries

### delete-module

Deletes a module from the project architecture.

**Input:**
- `projectId` (required): Project ID from `list-projects`
- `moduleName`: Name of the module to delete

**Output:**
- Success message

## Resources

### architecture

Provides access to project architecture as a resource.

**Usage:**
Access via URI: `arch://{projectId}`

### module

Provides access to module details as a resource.

**Usage:**
Access via URI: `module://{projectId}/{moduleId}`

## Development

### Project Structure

```
mcp-architector/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ index.ts          # Main server implementation
β”‚   β”œβ”€β”€ types.ts          # Type definitions
β”‚   └── storage.ts        # Storage utilities
β”œβ”€β”€ dist/                 # Compiled output (generated)
β”œβ”€β”€ package.json
β”œβ”€β”€ tsconfig.json
└── README.md
```

## Project ID

The server stores each project in `~/.mcp-architector/{projectId}/`. `projectId` must be passed explicitly on every tool except `list-projects`.

- Call `list-projects` (with `query` = workspace folder name) to find the id
- `MCP_PROJECT_ID` is only a listing hint (`isCurrent` / `suggestedProjectId`), not a silent write target
- `default-project` and unsubstituted `${workspaceFolder}` ids are forbidden

To start a new project, pass a stable id derived from the workspace path (e.g. `_qs_my-app`) to `set-project-architecture`.

### Extending the Server

To add new tools, resources, or prompts, edit `src/index.ts`:

```typescript
// Add a tool
server.registerTool(
  "tool-name",
  { /* tool config */ },
  async (params) => { /* handler */ }
);

// Add a resource
server.registerResource(
  "resource-name",
  new ResourceTemplate("uri-template", { /* options */ }),
  { /* resource config */ },
  async (uri, params) => { /* handler */ }
);

// Add a prompt
server.registerPrompt(
  "prompt-name",
  { /* prompt config */ },
  (args) => { /* handler */ }
);
```

## License

MIT

TDQS

A4.1/5.0

Scored across 28 tools

Disambiguation4/5

Tools are well-described with distinct purposes, but the large number of entry manipulation tools (set-entry, set-entries, replace-entries, import-entries, delete-entry, delete-entries) could lead to confusion. However, descriptions clearly specify when to use each, making disambiguation possible with careful reading.

Naming Consistency5/5

All tools use a consistent verb_noun pattern in snake_case (e.g., list-entries, set-module-details, delete-slice). Related operations share prefixes (set-*, delete-*, list-*, get-*, validate-*), making the API predictable and easy to navigate.

Tool Count4/5

With 28 tools, the count is high but justified by the complexity of the domain (managing entries, modules, slices, projects, imports, validation, and bulk operations). Some redundancy (e.g., import-entries as alias for replace-entries) could be trimmed, but overall the tool set is well-scoped for a comprehensive architecture management server.

Completeness5/5

The tool set covers all essential operations: CRUD for entries, modules, slices, and projects; listing, searching, validation, bulk imports, data flow management, and refactoring. No obvious gaps are apparent; even edge cases like index drift and slice definition are addressed.

Maintenance

ActivityMaintained
ResponsivenessNo issues