Skip to main content
Glama
README.md
# @cocrates/elk-mcp

[elkjs](https://github.com/kieler/elkjs) 기반 **그래프 레이아웃**을 [MCP](https://modelcontextprotocol.io)로 제공하는 TypeScript 패키지입니다.

에이전트는 노드/엣지 구조만 넘기고, 좌표·엣지 경로는 이 서버가 계산합니다. 렌더링은 포함하지 않습니다.

| | |
|---|---|
| **패키지** | `@cocrates/elk-mcp` |
| **바이너리** | `elk-mcp` |
| **런타임** | Node.js 18+ |
| **전송** | MCP stdio (JSON-RPC) |

---

## MCP 도구

| Tool | 설명 |
|------|------|
| `layout_graph` | `graph` + `options`로 레이아웃 → 노드 좌표·엣지 sections |
| `validate_graph` | 레이아웃 전 검증 (중복 id, parent, endpoint 등) |
| `list_algorithms` | 등록된 ELK 알고리즘 목록 |
| `list_layout_options` | 알려진 레이아웃 옵션 (`query`로 필터) |
| `list_layout_categories` | 레이아웃 카테고리 |

### `layout_graph` 입력

- **`graph`**: 구조만 (`nodes`, `edges`)
- **`options`**: `algorithm`, `direction`, `layoutOptions` 등 (그래프와 분리)

`options.algorithm`은 ELK layout algorithm id(예: `layered`, `mrtree`, `force`)이고, `options.direction`은 `RIGHT/LEFT/UP/DOWN` 형태 문자열입니다.

계층은 둘 중 하나:

- flat: `node.parent`
- nested: `node.children`  
  (같은 노드에 둘 다 쓰지 말 것)

- leaf 노드(자식이 없는 노드)의 `width/height`는 가능하면 제공하세요. 미제공이면 서버에서 기본값 `80x40`을 사용합니다.
- `edges`의 엔드포인트는 **노드 id 또는 포트 id**가 될 수 있습니다(노드의 `ports[]`로 포트를 선언한 경우).
- `edges[]`는 `graph.edges`에 모두 모아도 됩니다. 서버가 엣지 양끝의 **LCA(최저 공통 조상) 노드** 아래에 배치합니다.
- `edges[]`는 `id`가 필요합니다. 또한 `source/target` 또는 `sources/targets` 형태로 엔드포인트를 줄 수 있습니다.

```json
{
  "graph": {
    "nodes": [
      { "id": "svc", "label": "Service" },
      { "id": "A", "parent": "svc", "label": "API", "width": 120, "height": 40 },
      { "id": "B", "parent": "svc", "label": "DB", "width": 100, "height": 40 },
      { "id": "C", "label": "Client", "width": 90, "height": 40 }
    ],
    "edges": [
      { "id": "e1", "source": "A", "target": "B" },
      { "id": "e2", "source": "C", "target": "A" }
    ]
  },
  "options": {
    "algorithm": "layered",
    "direction": "RIGHT"
  }
}
```

### 출력

출력은 `options.absoluteCoordinates`에 따라 좌표계가 달라집니다.

- `options.absoluteCoordinates`가 `true`(기본): `nodes[].x/y`와 `edges[].sections[].startPoint/endPoint/bendPoints`가 모두 **단일(전역) 좌표계** 기준입니다.
- `options.absoluteCoordinates`가 `false`: 값들은 렌더링 프레임에서 바로 쓰기 어렵습니다(노드/엣지의 **로컬 좌표계** 기준으로 내려옵니다). 일반적인 캔버스 렌더링에는 기본값인 `true`를 권장합니다.

절대좌표(기본) 기준 flat JSON의 주요 필드:

- `nodes[]`: `id`, `label?`, `x`, `y`, `width`, `height`, `parent?`, `children?`
  - `x,y`: 노드 바운딩박스의 좌상단 기준 좌표(ELK 결과 기준)
  - `ports?`: 각 포트의 `id`, `x,y`, `width,height`
  - `labels?`: 각 라벨의 `id?`, `text?`, `x,y`, `width,height`
- `edges[]`: `id`, `sources`, `targets`, `sections[]`, `junctionPoints?`
  - `sections[]`는 ELK extended edge 라우팅이 분해된 구간 목록입니다.
  - 각 `sections[]` 항목은 `startPoint`, `endPoint`, `bendPoints[]`로 구성되며,
    `bendPoints`는 폴리라인 중간 정점(순서대로 연결)입니다.
  - `junctionPoints`는 하이퍼엣지 등에서 분기/합류점이 계산된 경우에만 내려옵니다.

---

## 클라이언트 설정

```json
{
  "mcpServers": {
    "elk": {
      "command": "npx",
      "args": ["-y", "@cocrates/elk-mcp"]
    }
  }
}
```

로컬 빌드:

```json
{
  "mcpServers": {
    "elk": {
      "command": "node",
      "args": ["/path/to/elk-mcp/dist/mcp/index.js"]
    }
  }
}
```

---

## 개발

```bash
npm install
npm run build
npm test
npm run start:mcp
```

프로그램에서 코어 API를 직접 쓸 수도 있습니다:

```ts
import { layoutGraph } from "@cocrates/elk-mcp";

const result = await layoutGraph(
  {
    nodes: [
      { id: "A", width: 120, height: 40 },
      { id: "B", width: 100, height: 40 },
    ],
    edges: [{ id: "e1", source: "A", target: "B" }],
  },
  { algorithm: "layered", direction: "RIGHT" },
);
```

---

## GitHub Release · npm 배포

패키지 이름: **`@cocrates/elk-mcp`** (scoped). npm에 퍼블리시하려면 해당 scope 권한이 필요합니다.

### 1. 버전 올리기

```bash
npm version patch   # 0.1.0 → 0.1.1
# 또는 minor / major
npm run build
```

### 2. npm 배포

```bash
npm login
npm publish --access public
```

`files` 필드에 `dist`, `README.md`, `LICENSE`만 포함되므로 **publish 전에 반드시 `npm run build`** 하세요. (`dist/`는 gitignore일 수 있습니다.)

### 3. GitHub Release

```bash
git push origin main --follow-tags

gh release create v0.1.1 \
  --title "v0.1.1" \
  --notes "$(cat <<'EOF'
## Changes
- …

## Install
npm install -g @cocrates/elk-mcp@0.1.1
EOF
)"
```

태그/릴리스는 `npm version`이 만든 git tag와 버전을 맞추면 됩니다.

### 권장 순서

1. PR 머지 → `main`  
2. `npm version` + `npm run build` + `npm publish`  
3. `git push --follow-tags` + `gh release create`  

CI에서 publish하려면 Node 18+, `NPM_TOKEN`, (선택) `GITHUB_TOKEN`을 시크릿으로 두면 됩니다.

---

## 참고

- elkjs 인터페이스: [`docs/elkjs.md`](./docs/elkjs.md)
- [ELK JSON Format](https://eclipse.dev/elk/documentation/tooldevelopers/graphdatastructure/jsonformat.html)
- [ELK Layout Options](https://www.eclipse.org/elk/reference.html)

TDQS

A4.2/5.0

Scored across 5 tools

Disambiguation5/5

Each tool has a distinct purpose: layout_graph computes layout, validate_graph checks validity, list_algorithms lists algorithms, list_layout_options lists options, and list_layout_categories lists categories. No overlap in functionality.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern in snake_case (e.g., layout_graph, list_algorithms). No mixing of conventions.

Tool Count5/5

5 tools is well-scoped for an ELK layout server. It covers layout computation, validation, and exploration of algorithms/options without being excessive or insufficient.

Completeness4/5

The set covers core layout operations (validation, layout computation) and discovery (algorithms, options, categories). Minor gap: no tool to retrieve default options for a specific algorithm, but not critical.

Maintenance

ActivityStale
ResponsivenessNo issues