Skip to content

Commit 930a331

Browse files
committed
Release v0.7.0: independent LSP, MCP for Cursor, npm publish support
Made-with: Cursor
1 parent 22d6784 commit 930a331

13 files changed

Lines changed: 469 additions & 26 deletions

.cursor/mcp.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
{
22
"mcpServers": {
3+
"sysmledgraph": {
4+
"command": "node",
5+
"args": ["dist/mcp/index.js"],
6+
"cwd": ".",
7+
"env": {}
8+
},
39
"sysml-v2": {
410
"command": "node",
511
"args": ["node_modules/sysml-v2-lsp/dist/server/mcpServer.js"]

README.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# sysmledgraph
2+
3+
Path-only SysML indexer: builds a knowledge graph from `.sysml` files and exposes it via **MCP** (for Cursor AI) and **CLI**. The LSP used for indexing lives in **`lsp/`** and is used only by this repo.
4+
5+
## Requirements
6+
7+
- **Node.js 20+**
8+
- **Kuzu** (built via `npm install` or `node node_modules/kuzu/install.js` if you use `--ignore-scripts`)
9+
- **LSP** for indexing: [sysml-v2-lsp](https://www.npmjs.com/package/sysml-v2-lsp), installed in **`lsp/`** (see below)
10+
11+
## Install
12+
13+
```bash
14+
npm install
15+
npm run build
16+
npm run setup-lsp
17+
```
18+
19+
- **setup-lsp** installs the SysML LSP in **`lsp/`** so the indexer can use it. No need to set `SYSMLLSP_SERVER_PATH` when using this default. See [docs/INSTALL.md](docs/INSTALL.md) and [docs/PLAN_INDEPENDENT_LSP.md](docs/PLAN_INDEPENDENT_LSP.md).
20+
21+
## Usage
22+
23+
### CLI
24+
25+
| Command | Description |
26+
|--------|-------------|
27+
| `npx sysmledgraph analyze <path>` | Index path(s); discover `.sysml`, build graph (uses LSP in `lsp/` by default) |
28+
| `npx sysmledgraph list` | List indexed root paths |
29+
| `npx sysmledgraph clean [path]` | Remove index for path or all |
30+
31+
**Scripts (from repo root):**
32+
33+
- `npm run index-and-map [path]` — Index path (default `test/fixtures/sysml`), then write **graph-map.md**
34+
- `npm run generate-map [out.md]` — Generate map from existing DB
35+
- `npm run setup-lsp` — Install LSP in `lsp/` (Option C, see plan)
36+
37+
### MCP (Cursor)
38+
39+
This repo runs as an **MCP server** so Cursor AI can query the graph (query, context, impact, generate_map, indexDbGraph, cypher, etc.). Add **sysmledgraph** to `.cursor/mcp.json`; see [docs/MCP_SERVER_FOR_CURSOR.md](docs/MCP_SERVER_FOR_CURSOR.md).
40+
41+
**Storage:** Default `~/.sysmledgraph`. Override with `SYSMEDGRAPH_STORAGE_ROOT`. Only one process should open the same DB at a time (see [docs/MCP_INTERACTION_GUIDE.md](docs/MCP_INTERACTION_GUIDE.md) §8).
42+
43+
## Docs
44+
45+
| Doc | Content |
46+
|-----|--------|
47+
| [docs/INSTALL.md](docs/INSTALL.md) | Install steps, LSP, Kuzu |
48+
| [docs/MCP_SERVER_FOR_CURSOR.md](docs/MCP_SERVER_FOR_CURSOR.md) | Enable sysmledgraph MCP in Cursor, tools, checklist |
49+
| [docs/MCP_INTERACTION_GUIDE.md](docs/MCP_INTERACTION_GUIDE.md) | LSP vs MCP, indexing, troubleshooting |
50+
| [docs/PLAN_INDEPENDENT_LSP.md](docs/PLAN_INDEPENDENT_LSP.md) | Why LSP is in `lsp/` only for sysmledgraph |
51+
| [lsp/README.md](lsp/README.md) | LSP folder setup and cwd |
52+
53+
## Publishing (npm)
54+
55+
You can publish this package to npm so others can install it with `npm install sysmledgraph` or `npx sysmledgraph analyze <path>`.
56+
57+
1. **Name:** The package name is **`sysmledgraph`**. If it is already taken, use a scoped name (e.g. `@yourusername/sysmledgraph`) and set it in `package.json` `"name"`.
58+
2. **Build:** `prepublishOnly` runs `npm run build` before packing, so **dist/** is included in the tarball.
59+
3. **Included files:** Only **dist**, **scripts**, **lsp**, **README.md**, and **docs** are published (see `package.json` `"files"`). Users run **`npm run setup-lsp`** after install to install the LSP in **lsp/**.
60+
4. **Publish:** From a clean build, run:
61+
```bash
62+
npm login
63+
npm publish
64+
```
65+
For a scoped package (e.g. `@user/sysmledgraph`), use `npm publish --access public` the first time.
66+
67+
After publish, users can install with `npm install sysmledgraph`, then run **`npm run setup-lsp`** from the installed package directory (e.g. `cd node_modules/sysmledgraph && npm run setup-lsp`) so the LSP is available. When using **npx sysmledgraph** from another project, the default LSP path is resolved from the **current working directory** (that project’s `lsp/` or `node_modules/sysml-v2-lsp`). So either run setup-lsp inside the sysmledgraph package and set **SYSMLLSP_SERVER_PATH** to that `lsp/node_modules/.../server.js`, or install **sysml-v2-lsp** in the consumer project so the fallback finds it.
68+
69+
## License
70+
71+
MIT

docs/INSTALL.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Install
2+
3+
## Quick start
4+
5+
1. **Root:** `npm install` then `npm run build`.
6+
2. **LSP (for indexing):** The canonical LSP for this repo is in **`lsp/`**. Run **`npm run setup-lsp`** (or `cd lsp && npm install`) so the indexer can use it. No need to set **`SYSMLLSP_SERVER_PATH`** when using this default.
7+
3. **Index:** `npx sysmledgraph analyze <path>` or use the MCP tool **indexDbGraph** after enabling the sysmledgraph MCP in Cursor (see docs/MCP_SERVER_FOR_CURSOR.md).
8+
9+
## LSP
10+
11+
- **Source:** [sysml-v2-lsp](https://www.npmjs.com/package/sysml-v2-lsp) (npm). The only copy used by sysmledgraph for indexing is in **`lsp/`** (see docs/PLAN_INDEPENDENT_LSP.md).
12+
- **Setup:** `npm run setup-lsp` installs it in `lsp/` with `--ignore-scripts` (recommended on Windows). If you prefer a manual install: `cd lsp && npm install`.
13+
14+
## Kuzu
15+
16+
If `npm install` fails or you use `--ignore-scripts`, build Kuzu manually: `node node_modules/kuzu/install.js`. See docs/INSTALL_NOTES.md if present.

docs/MCP_INTERACTION_GUIDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ When the MCP server is started from a Node script, it may not send the initializ
155155
Indexing and generating the graph map use the **LSP** server (`server.js`), not the MCP server. The CLI runs `analyze` (which spawns the LSP and uses documentSymbol), then you can run `generate-map` to produce a markdown map.
156156

157157
- **Kuzu:** The graph DB is backed by [kuzu](https://www.npmjs.com/package/kuzu). Ensure it is built: run `npm install` without `--ignore-scripts`, or `node node_modules/kuzu/install.js` so that `index.js` / `index.mjs` and the native addon are present. Without this, analyze and generate-map will fail with module-not-found.
158-
- **LSP path:** Set **`SYSMLLSP_SERVER_PATH`** to the absolute (or cwd-relative) path to `sysml-v2-lsp/dist/server/server.js`. If unset, **`scripts/index-and-map.mjs`** prefers **`lsp/node_modules/sysml-v2-lsp/dist/server/server.js`** (dedicated LSP init folder), then repo root `node_modules/...`. So you can run `cd lsp && npm install` (use `--ignore-scripts` on Windows if the package postinstall fails), then from repo root run index-and-map without setting the env var; the spawn cwd will be `lsp/`.
158+
- **LSP path:** The canonical LSP for this repo is in **`lsp/`**. Run **`npm run setup-lsp`** (or `cd lsp && npm install`) once; the indexer then uses `lsp/node_modules/sysml-v2-lsp/dist/server/server.js` by default (then root `node_modules/...` as fallback). No need to set **`SYSMLLSP_SERVER_PATH`** when using the default. See docs/PLAN_INDEPENDENT_LSP.md.
159159
- **Commands (from repo root, after `npm run build`):**
160160
- `npm run index-and-map` — Index default path `test/fixtures/sysml`, then write **graph-map.md**.
161161
- `npm run index-and-map <path>` — Index the given path, then generate the map.

docs/MCP_SERVER_FOR_CURSOR.md

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# MCP Server for Cursor AI
2+
3+
This repo works as an **MCP server** so Cursor (and other MCP clients) can use the SysML knowledge graph: query symbols, context, impact, generate map, index paths, and run Cypher.
4+
5+
## 1. What the server provides
6+
7+
- **Server name:** `sysmledgraph`
8+
- **Transport:** stdio (Cursor spawns the process and talks over stdin/stdout)
9+
- **Tools:** indexDbGraph, list_indexed, clean_index, cypher, query, context, impact, rename, generate_map
10+
- **Resources:** `sysmledgraph://context`, `sysmledgraph://schema` (and per-path variants when paths are indexed)
11+
12+
Cursor AI can call these tools when you ask about your SysML model (e.g. “what uses Modelbase?”, “show me the graph map”, “list symbols in the deploy model”).
13+
14+
## 2. Prerequisites
15+
16+
1. **Index at least one path** so the graph has data. Either:
17+
- **CLI:** `npx sysmledgraph analyze <path>` (e.g. `modelbase-development/models`), or
18+
- **MCP tool:** After the server is running in Cursor, use the **indexDbGraph** tool with the same path(s).
19+
2. **Kuzu:** Built (e.g. `npm install` without `--ignore-scripts`). See docs/INSTALL_NOTES.md if needed.
20+
3. **LSP:** For indexing, the LSP is in **`lsp/`**. Run **`npm run setup-lsp`** (or `cd lsp && npm install`) once; it is then picked automatically. No need to set **SYSMLLSP_SERVER_PATH** if the server isn’t in the default location (see docs/PLAN_INDEPENDENT_LSP.md).
21+
22+
## 3. Enable in Cursor
23+
24+
Add the sysmledgraph MCP server to Cursor’s MCP config.
25+
26+
**Option A — Project-local (this repo as workspace)**
27+
28+
Create or edit **`.cursor/mcp.json`** in the project root:
29+
30+
```json
31+
{
32+
"mcpServers": {
33+
"sysmledgraph": {
34+
"command": "node",
35+
"args": ["dist/mcp/index.js"],
36+
"cwd": ".",
37+
"env": {
38+
"SYSMEDGRAPH_STORAGE_ROOT": "C:/Users/YOU/.sysmledgraph"
39+
}
40+
}
41+
}
42+
}
43+
```
44+
45+
- **cwd** must be the **workspace root** (where `dist/` and the indexed paths live). Use `"."` when opening this repo as the workspace.
46+
- **SYSMEDGRAPH_STORAGE_ROOT:** Default is `~/.sysmledgraph`. Set to a custom path if you use one for the CLI.
47+
- **SYSMLLSP_SERVER_PATH (optional):** Only if not using the default. When running from this repo, the LSP in **`lsp/`** is used automatically after **`npm run setup-lsp`**.
48+
49+
**Option B — Absolute path to built server**
50+
51+
If the built server lives elsewhere (e.g. a global tools folder):
52+
53+
```json
54+
{
55+
"mcpServers": {
56+
"sysmledgraph": {
57+
"command": "node",
58+
"args": ["C:/path/to/sysmledgraph/dist/mcp/index.js"],
59+
"env": {
60+
"SYSMEDGRAPH_STORAGE_ROOT": "C:/Users/YOU/.sysmledgraph"
61+
}
62+
}
63+
}
64+
}
65+
```
66+
67+
**Option C — npx (when published)**
68+
69+
```json
70+
{
71+
"mcpServers": {
72+
"sysmledgraph": {
73+
"command": "npx",
74+
"args": ["-y", "sysmledgraph-mcp"]
75+
}
76+
}
77+
}
78+
```
79+
80+
After saving, (re)start Cursor or reload MCP so it picks up the new server.
81+
82+
## 4. Tools Cursor AI can use
83+
84+
| Tool | Purpose |
85+
|------|--------|
86+
| **list_indexed** | List indexed root paths (so AI knows what’s in the graph). |
87+
| **query** | Concept search over symbol names/labels; optional `kind` filter (e.g. PartDef, Package). |
88+
| **context** | 360° view for one symbol: node + edges (IN_DOCUMENT, IN_PACKAGE, etc.). |
89+
| **impact** | Blast radius: upstream (what references this) or downstream (what this references). |
90+
| **generate_map** | Get Markdown of the graph (documents, nodes by label, interconnection edges). |
91+
| **cypher** | Run a Cypher query on the graph (advanced). |
92+
| **indexDbGraph** | Index path(s) (same as CLI analyze). Use when the graph is empty or you add a new folder. |
93+
| **clean_index** | Remove index for one path or all. |
94+
| **rename** | Preview or perform a symbol rename across the graph. |
95+
96+
For “show the map of this file” or “what depends on X”, the AI can call **generate_map** or **context** / **impact** after **list_indexed** to see what’s available.
97+
98+
## 5. Storage and LSP
99+
100+
- **Storage:** Same as CLI. Default `~/.sysmledgraph`; override with **SYSMEDGRAPH_STORAGE_ROOT**. The MCP server uses the same DB as `sysmledgraph analyze` and `scripts/generate-map.mjs`.
101+
- **LSP:** Used by **indexDbGraph** and CLI analyze. The canonical LSP is in **`lsp/`**. Run **`npm run setup-lsp`** once; the indexer then uses it by default (no **SYSMLLSP_SERVER_PATH** needed). If unset and lsp/ not installed, indexing falls back to MCP getSymbols.
102+
103+
## 6. Kuzu lock
104+
105+
Only one process can open the same Kuzu DB at a time. If the sysmledgraph MCP is running in Cursor, it holds the DB open. To run **CLI** analyze or **scripts/export-graph.mjs** / **generate-map.mjs** without “Could not set lock on file”, either:
106+
107+
- Close Cursor (or disable the sysmledgraph MCP), run the CLI/script, then reopen Cursor, or
108+
- Use a **different** **SYSMEDGRAPH_STORAGE_ROOT** for the CLI run (e.g. a temp folder), then point the MCP at the same root if you want Cursor to see that data.
109+
110+
See **docs/MCP_INTERACTION_GUIDE.md** §8 Troubleshooting and **docs/MCP-AND-KUZU.md** (if present).
111+
112+
## 7. Checklist
113+
114+
1. `npm install` and `npm run build` in this repo.
115+
2. Run **`npm run setup-lsp`** (or `cd lsp && npm install`) so the LSP used for indexing is installed in **`lsp/`**.
116+
3. Index at least one path: `npx sysmledgraph analyze modelbase-development/models` (or use **indexDbGraph** after MCP is on).
117+
4. Add **sysmledgraph** to `.cursor/mcp.json` with `command`/`args`/`cwd`/`env` as above.
118+
5. Restart Cursor or reload MCP; confirm the server appears (e.g. in Cursor MCP settings).
119+
6. In chat, ask e.g. “List indexed paths for sysmledgraph”, “Show the graph map”, “What is the context of Modelbase?” to confirm tools work.
120+
121+
## 8. Next (optional)
122+
123+
- **Prompts:** Add a Cursor rule or AGENTS.md note so the AI knows to use sysmledgraph tools for SysML/graph questions.
124+
- **Resources:** Expose `sysmledgraph://context` or `sysmledgraph://schema` in Cursor so the AI can pull index stats and schema when relevant.

0 commit comments

Comments
 (0)