{"_id":"@0xdeafcafe/tslsp-mcp","_rev":"3-6cea0bed45bbbe5d03def1b2f0c231c5","name":"@0xdeafcafe/tslsp-mcp","dist-tags":{"setup":"0.0.1-setup.1","latest":"0.1.0"},"versions":{"0.0.1-setup.1":{"name":"@0xdeafcafe/tslsp-mcp","version":"0.0.1-setup.1","_id":"@0xdeafcafe/tslsp-mcp@0.0.1-setup.1","maintainers":[{"name":"0xdeafcafe","email":"npm@alex.forbes.red"}],"bin":{"tslsp-mcp":"dist/index.js"},"dist":{"shasum":"25a719d6cde395a590280dcd4433513fd19ff26b","tarball":"https://registry.npmjs.org/@0xdeafcafe/tslsp-mcp/-/tslsp-mcp-0.0.1-setup.1.tgz","fileCount":16,"integrity":"sha512-wqOZnHXG7BdHjn7c/UW2NNlQr9dQ5Zl5F+l/Ic3s5m9cSY0HuALnUMkSyn+a1X9z5dx9o7VAcHHsP6AERAn5IQ==","signatures":[{"sig":"MEQCIFt1jpLUpMHbk/1IXOmrh3bdgG+cCLD1TutAyjYDWDRuAiBGcw8m3MzqZYc4Ya7YPgiRgo0j6CFxE75lXw00L9o55Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":87143},"type":"module","_from":"file:0xdeafcafe-tslsp-mcp-0.0.1-setup.1.tgz","engines":{"node":">=22"},"scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc","start":"node dist/index.js","test:ui":"vitest --ui","test:watch":"vitest"},"_npmUser":{"name":"0xdeafcafe","email":"npm@alex.forbes.red"},"_resolved":"/private/var/folders/25/8k1gn9r12gz5hvy54p4glvj40000gn/T/49301fa978167197ce6ab487eabed8fe/0xdeafcafe-tslsp-mcp-0.0.1-setup.1.tgz","_integrity":"sha512-wqOZnHXG7BdHjn7c/UW2NNlQr9dQ5Zl5F+l/Ic3s5m9cSY0HuALnUMkSyn+a1X9z5dx9o7VAcHHsP6AERAn5IQ==","_npmVersion":"11.6.2","description":"MCP server exposing the TypeScript language server (tsgo) — rename, references, definitions, hover, symbols, diagnostics.","directories":{},"_nodeVersion":"24.13.0","dependencies":{"zod":"^4.4.3","@modelcontextprotocol/sdk":"^1.29.0","@typescript/native-preview":"7.0.0-dev.20260506.1"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.5","@vitest/ui":"^4.1.5","typescript":"^6.0.3","@types/node":"^22.19.17"},"_npmOperationalInternal":{"tmp":"tmp/tslsp-mcp_0.0.1-setup.1_1778146802359_0.5588482182073229","host":"s3://npm-registry-packages-npm-production"}},"0.0.1":{"name":"@0xdeafcafe/tslsp-mcp","version":"0.0.1","keywords":["mcp","model-context-protocol","typescript","tsgo","lsp","claude","claude-code","rename","refactor"],"license":"MIT","_id":"@0xdeafcafe/tslsp-mcp@0.0.1","maintainers":[{"name":"0xdeafcafe","email":"npm@alex.forbes.red"}],"homepage":"https://github.com/0xdeafcafe/tslsp-mcp#readme","bugs":{"url":"https://github.com/0xdeafcafe/tslsp-mcp/issues"},"bin":{"tslsp-mcp":"dist/index.js"},"dist":{"shasum":"a8390be82696a722d6c84992863d9d97a932b9c6","tarball":"https://registry.npmjs.org/@0xdeafcafe/tslsp-mcp/-/tslsp-mcp-0.0.1.tgz","fileCount":16,"integrity":"sha512-hrQbtVWgFckbXbENSknUf1XnV0/ZqsMH+9gsfWlNjRd8/pX3BQWMC/4l97V6ihsvmLb2wQix2CvbLNlJmPS8gA==","signatures":[{"sig":"MEUCIQD7T8GjfpQCOJn2ItN453rT6VYZVfVJP7ZI1gC90tkuZwIgKPoZ74RscFrF69z5MRp5mVCHrLNiuWUOimxWSkVMwyU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@0xdeafcafe%2ftslsp-mcp@0.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":87641},"type":"module","engines":{"node":">=22"},"gitHead":"418025697af92db8aee2d37690604b4d7970e39d","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc","start":"node dist/index.js","test:ui":"vitest --ui","test:watch":"vitest","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:5a26ccb6-5c55-4801-a097-e15c4ea5b3d2"}},"repository":{"url":"git+https://github.com/0xdeafcafe/tslsp-mcp.git","type":"git"},"_npmVersion":"11.14.0","description":"MCP server exposing the TypeScript language server (tsgo) — rename, references, definitions, hover, symbols, diagnostics.","directories":{},"_nodeVersion":"22.22.2","dependencies":{"zod":"^4.4.3","@modelcontextprotocol/sdk":"^1.29.0","@typescript/native-preview":"7.0.0-dev.20260506.1"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.29.3","devDependencies":{"vitest":"^4.1.5","@vitest/ui":"^4.1.5","typescript":"^6.0.3","@types/node":"^22.19.17"},"_npmOperationalInternal":{"tmp":"tmp/tslsp-mcp_0.0.1_1778163531655_0.5598612735281525","host":"s3://npm-registry-packages-npm-production"}},"0.1.0":{"name":"@0xdeafcafe/tslsp-mcp","version":"0.1.0","description":"MCP server exposing the TypeScript language server (tsgo) — rename, references, definitions, hover, symbols, diagnostics.","type":"module","repository":{"type":"git","url":"git+https://github.com/0xdeafcafe/tslsp-mcp.git"},"homepage":"https://github.com/0xdeafcafe/tslsp-mcp#readme","bugs":{"url":"https://github.com/0xdeafcafe/tslsp-mcp/issues"},"keywords":["mcp","model-context-protocol","typescript","tsgo","lsp","claude","claude-code","rename","refactor"],"license":"MIT","bin":{"tslsp-mcp":"dist/index.js","tslsp":"dist/cli.js"},"scripts":{"build":"tsc","dev":"tsc --watch","start":"node dist/index.js","test":"vitest run","test:watch":"vitest","test:ui":"vitest --ui","prepublishOnly":"pnpm run build"},"dependencies":{"@modelcontextprotocol/sdk":"^1.29.0","@typescript/native-preview":"7.0.0-dev.20260506.1","zod":"^4.4.3"},"devDependencies":{"@types/node":"^22.19.17","@vitest/ui":"^4.1.6","typescript":"^6.0.3","vitest":"^4.1.6"},"engines":{"node":">=22"},"packageManager":"pnpm@10.29.3","gitHead":"67d57f1e2d8049bd47987410acde4edcc302c668","_id":"@0xdeafcafe/tslsp-mcp@0.1.0","_nodeVersion":"22.22.2","_npmVersion":"11.14.1","dist":{"integrity":"sha512-PbLA7vSijpXkIlUlKuDlQgTfFz7t0+QAYDW1qnz703CYWs3oV6z7eaFoh0RWdhy5mOJ6FW32H8bIw/ZB8Nrt9g==","shasum":"4e0b0adb515314f6cd3931c9aa42bfc67e921a5b","tarball":"https://registry.npmjs.org/@0xdeafcafe/tslsp-mcp/-/tslsp-mcp-0.1.0.tgz","fileCount":27,"unpackedSize":172726,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@0xdeafcafe%2ftslsp-mcp@0.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCdZflyqRnhAaRqopgZUbgJ/JXsnbvsujfj89rsL2VxWgIga5t8J+8WEfu4P5I6w7Iab91skxZW5E1y5tG2etICLBU="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:5a26ccb6-5c55-4801-a097-e15c4ea5b3d2"}},"directories":{},"maintainers":[{"name":"0xdeafcafe","email":"npm@alex.forbes.red"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/tslsp-mcp_0.1.0_1778986480097_0.9385562763913555"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-07T09:40:02.257Z","modified":"2026-05-17T02:54:40.525Z","0.0.1-setup.1":"2026-05-07T09:40:02.524Z","0.0.1":"2026-05-07T14:18:51.808Z","0.1.0":"2026-05-17T02:54:40.245Z"},"bugs":{"url":"https://github.com/0xdeafcafe/tslsp-mcp/issues"},"license":"MIT","homepage":"https://github.com/0xdeafcafe/tslsp-mcp#readme","keywords":["mcp","model-context-protocol","typescript","tsgo","lsp","claude","claude-code","rename","refactor"],"repository":{"type":"git","url":"git+https://github.com/0xdeafcafe/tslsp-mcp.git"},"description":"MCP server exposing the TypeScript language server (tsgo) — rename, references, definitions, hover, symbols, diagnostics.","maintainers":[{"name":"0xdeafcafe","email":"npm@alex.forbes.red"}],"readme":"# tslsp-mcp\n\n[![npm](https://img.shields.io/npm/v/@0xdeafcafe/tslsp-mcp.svg?logo=npm&label=npm)](https://www.npmjs.com/package/@0xdeafcafe/tslsp-mcp)\n[![CI](https://github.com/0xdeafcafe/tslsp-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/0xdeafcafe/tslsp-mcp/actions/workflows/ci.yml)\n[![node](https://img.shields.io/node/v/@0xdeafcafe/tslsp-mcp.svg?logo=node.js)](https://github.com/0xdeafcafe/tslsp-mcp/blob/main/package.json)\n\nclaude finds references by grepping. claude renames things by find-and-replacing. this is fine until your symbol is called `User` or `get` or `value`, at which point it confidently rewrites half your codebase and tells you it's done. thanks, gas-lightyear.\n\nhow do real editors function? they ask the typescript language server, which actually understands what's a reference vs what's just a string. `tslsp-mcp` gives claude that same superpower over an MCP server or a regular CLI. rename is type-aware. references are real references. moving a file rewrites every import that pointed at it. `outline` is the LSP's structural view, not \"read 200 lines and hope.\"\n\nit spawns [tsgo](https://github.com/microsoft/typescript-go), microsoft's native go port of tsserver, per `tsconfig.json` it sees, keeps it warm, and routes tool calls to the right one. one process per project, lazy-spawned, not one per request.\n\ndesigned in my head, built by claudus, tested on your codebase, cheers.\n\n## you need\n\n- node 22+\n- a typescript project (anything with a `tsconfig.json`)\n- [claude code](https://claude.com/claude-code), or any other MCP / skill-aware host\n\n## install\n\ntwo flavours. pick whichever your agent likes — they expose the same tools.\n\n### CLI + skill\n\n```bash\nnpm install -g @0xdeafcafe/tslsp-mcp\ntslsp install --skills              # ~/.claude/skills/tslsp/SKILL.md\ntslsp install --skills --project    # ./.claude/skills/tslsp (commit it)\n```\n\nthe skill tells claude when to reach for `tslsp` instead of `Grep`/`Edit`/`mv`. `tslsp --help` lists every command; the agent can drive it raw from `--help` if you skip the skill.\n\n### MCP\n\n```bash\nclaude mcp add -s user tslsp -- npx -y @0xdeafcafe/tslsp-mcp\n```\n\n`-s user` makes it available in every project. drop it (and run from a project dir) to scope to one repo.\n\nprefer to run from source? clone, build, point claude at the built file:\n\n```bash\ngit clone https://github.com/0xdeafcafe/tslsp-mcp.git\ncd tslsp-mcp && pnpm install && pnpm run build\nclaude mcp add -s user tslsp node /absolute/path/to/tslsp-mcp/dist/index.js\n```\n\n## make claude actually use it\n\nclaude won't reach for an MCP tool just because it exists. you have to tell it, and you have to be explicit about which built-in tool it replaces. `tslsp install --skills` drops a ready-made SKILL.md that does exactly that. if you'd rather paste it yourself, here's the block — works in `~/.claude/CLAUDE.md` or a project's `CLAUDE.md`:\n\n```markdown\n## TypeScript code intelligence (tslsp)\n\nIn any TS/JS project with a `tsconfig.json`, the `tslsp` tools are type-aware\nand MUST be used instead of the built-in text tools for the operations below.\nText tools see strings; tslsp sees the program.\n\nNames below are the MCP shape (`tslsp:foo`). With the CLI, replace `tslsp:foo`\nwith `tslsp foo` — same arguments, same output.\n\n| Task                            | DO use                   | DO NOT use                              |\n| ------------------------------- | ------------------------ | --------------------------------------- |\n| Find every usage of a symbol    | `tslsp:references`       | `Grep`, `Glob`                          |\n| Search for a symbol by name     | `tslsp:find_symbol`      | `Grep`                                  |\n| Jump to a definition            | `tslsp:definition`       | `Grep` + `Read`                         |\n| Jump to a value's *type*        | `tslsp:type_definition`  | `Grep` + `Read`                         |\n| Find concrete implementations   | `tslsp:implementation`   | `Grep`                                  |\n| Rename a symbol                 | `tslsp:rename`           | `Edit`, `MultiEdit`, find-and-replace   |\n| Rename/move a file or folder    | `tslsp:rename_file`      | `mv` / `git mv` (won't update imports)  |\n| Type / JSDoc for a symbol       | `tslsp:hover`            | `Read`                                  |\n| Outline a file before reading   | `tslsp:outline`          | `Read` on the whole file                |\n| Type errors after an edit       | `tslsp:diagnostics`      | `Bash` running `tsc` ad-hoc             |\n| Trace callers / callees         | `tslsp:call_hierarchy`   | repeated `references` calls             |\n| Organize imports / quick-fix    | `tslsp:code_action`      | manual edit                             |\n\nHard rules:\n\n1. NEVER rename a TypeScript identifier with `Edit` or `MultiEdit`. Use\n   `tslsp:rename`. Pass `dry_run: true` first when the symbol has many call\n   sites; review the preview, then apply. This applies to every identifier —\n   slice keys (`features.fooUi`), property names, enum members, the lot. If\n   you find yourself string-editing a symbol \"just for a couple of files\"\n   you have already failed the rule. For bulk renames (e.g. renaming a whole\n   feature), enumerate symbols via `tslsp:outline` on each file in the folder\n   first, then call `tslsp:rename` once per symbol — cheaper in tokens than\n   grep+Read+Edit and safer (no false positives in comments / strings /\n   unrelated identifiers).\n2. NEVER `mv` or `git mv` a TypeScript file or folder. Use `tslsp:rename_file`\n   — it walks every import that references the file and rewrites them. After\n   the move you can still use `tslsp:rename` for any identifier inside.\n3. NEVER `Grep` for a symbol name to find usages or definitions. Use\n   `tslsp:references` or `tslsp:definition`. Grep matches strings in\n   comments, in unrelated identifiers, in `.md` files — it lies.\n4. Before reading a large file, call `tslsp:outline` first and use the line\n   numbers to `Read` only the slices you need.\n5. After non-trivial edits to a TS file, call `tslsp:diagnostics` on it to\n   confirm it still type-checks before claiming the change is done.\n\nLocator ergonomics: every position-taking tool accepts `{ symbol: \"name\" }`\n(workspace search), `{ file, line, symbol }` (line scan), or full\n`{ file, line, character }`. Use the cheapest form you have. Ambiguous\nname-only queries return the candidate list; pick by file or line and re-call.\n\nBatch: most read-only tools accept `symbols: [\"a\",\"b\",\"c\"]` (or `files: [...]`).\ntslsp fans the requests out in parallel and labels each block with\n`=== name ===`. One call beats N round-trips.\n\nFall back to the built-in text tools only for: string literals, comments,\nnon-TS files (Markdown, YAML, configs), or projects without a `tsconfig.json`.\n```\n\n## tools\n\n| tool              | what it does                                                                                          |\n| ----------------- | ----------------------------------------------------------------------------------------------------- |\n| `find_symbol`     | workspace symbol search by name. returns `path:line  kind name`.                                      |\n| `references`      | every reference to a symbol. takes a locator or a `symbols: [...]` batch.                             |\n| `definition`      | jump to where a symbol is defined. batches via `symbols`.                                             |\n| `type_definition` | jump to a value's *type* declaration (vs. its value declaration). batches via `symbols`.              |\n| `implementation`  | concrete implementations of an interface/abstract member. batches via `symbols`.                      |\n| `rename`          | type-aware rename across every file. `dry_run: true` previews without writing.                        |\n| `rename_file`     | move a file or folder; updates every import that referenced it. folders walked recursively.           |\n| `hover`           | type signature + JSDoc for a symbol. batches via `symbols`.                                           |\n| `outline`         | indented declaration outline. `files: [...]` batches.                                                 |\n| `diagnostics`     | type errors. `file`, `files: [...]`, or omit (aggregate across every open file).                      |\n| `call_hierarchy`  | callers and callees of a function. `direction: incoming` / `outgoing` / `both`.                       |\n| `code_action`     | list quick-fixes / refactors / organize-imports; pass `apply: N` to apply by index.                   |\n\n### symbol locator\n\nevery position-taking tool takes one of three shapes, in priority order:\n\n```js\n{ file, line, character }   // explicit LSP position\n{ file, line, symbol }      // server scans the line for the identifier\n{ symbol }                  // workspace symbol search; errors with candidates if ambiguous\n```\n\nLLMs know line numbers and symbol names but not character columns. modes 2 and 3 cover the gap.\n\n### batching\n\nmost read-only tools take an array variant. fanned out in parallel, results labeled:\n\n```js\ntslsp:hover         { symbols: [\"User\", \"Repository\", \"AuthService\"] }\ntslsp:outline       { files: [\"src/api.ts\", \"src/db.ts\"] }\ntslsp:diagnostics   { files: [\"src/a.ts\", \"src/b.ts\"] }\n```\n\n```bash\ntslsp hover       --symbols User,Repository,AuthService\ntslsp outline     src/api.ts src/db.ts\ntslsp diagnostics --files src/a.ts,src/b.ts\n```\n\none tool call, N parallel LSP queries, one return.\n\n## CLI\n\n```bash\ntslsp find-symbol User                          # positional == --query\ntslsp references --symbol User\ntslsp definition --symbol User\ntslsp rename --symbol oldName --new-name newName --dry-run\ntslsp rename-file src/old.ts src/new.ts --dry-run\ntslsp rename-file src/components src/widgets   # folders supported\ntslsp hover --symbol User\ntslsp outline src/api.ts\ntslsp diagnostics --file src/x.ts\ntslsp call-hierarchy --symbol handleRequest --direction incoming\ntslsp code-action --file src/x.ts --kind source.organizeImports\ntslsp code-action --file src/x.ts --kind source.organizeImports --apply 0\n\ntslsp --help                  # all commands\ntslsp <command> --help        # per-command flags\ntslsp install --skills        # drop SKILL.md into ~/.claude/skills/tslsp/\ntslsp mcp                     # start the MCP server over stdio\n```\n\n## how it works\n\n```\nclaude → stdio → tslsp-mcp → tsgo (project A)\n                           → tsgo (project B)\n                           → ...\n```\n\non first tool call against a file, it walks up to the nearest `tsconfig.json`, spawns tsgo there, opens a seed file so the workspace symbol index populates, and caches the process. subsequent calls reuse it. when you edit files via `rename` or `rename_file`, it pushes `didClose`/`didOpen` + `workspace/didChangeWatchedFiles` (and `didRenameFiles` for moves) so the index reprojects.\n\n## gotchas\n\n- pins `@typescript/native-preview` to a specific dev build. tsgo moves fast and dev builds shift. bump the version in `package.json` deliberately.\n- if you have an older homebrew-installed `tsgo` on your PATH, the MCP ignores it and uses the npm-pinned one. earlier versions had behavior we explicitly don't want.\n- `rename` and `rename_file` write to disk. `dry_run: true` previews first; `git diff` is your friend either way.\n- one tsgo process per `tsconfig.json` root. monorepos with many tsconfigs spawn many tsgos lazily; first hit per project pays project-load cost (~50ms on small, more on large).\n- the CLI spawns a fresh tsgo per invocation. fine for one-off calls; for a tight refactor loop, the MCP server (warm process) is faster.\n- set `TSLSP_VERBOSE=1` (or `TSLSP_MCP_VERBOSE=1`) to forward tsgo's stderr.\n","readmeFilename":"README.md"}