elk-mcp
# @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
Scored across 5 tools
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.
All tool names follow a consistent verb_noun pattern in snake_case (e.g., layout_graph, list_algorithms). No mixing of conventions.
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.
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.