Skip to content

Commit 3e0ec05

Browse files
authored
cleanup/0.1.0 (#26)
* move snapshots * update readme * update formatting in readme * fmt * fmt * update readme * Fix type for apply_text_edit * gitignore * gitignore * rename tools and remove codelens * remove showLineNumbers * fix typescript-language-server * fix tests * update readme * add demo * update readme * readme * update workflow * update snap * update ts hover test * fix typescript test
1 parent 4cafa51 commit 3e0ec05

File tree

167 files changed

+459
-280
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

167 files changed

+459
-280
lines changed

.github/workflows/go.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ jobs:
5353
run: go install golang.org/x/tools/gopls@latest
5454

5555
- name: Run Go integration tests
56-
run: go test ./integrationtests/languages/go/...
56+
run: go test ./integrationtests/tests/go/...
5757

5858
python-integration-tests:
5959
name: Python Integration Tests
@@ -77,7 +77,7 @@ jobs:
7777
run: npm install -g pyright
7878

7979
- name: Run Python integration tests
80-
run: go test ./integrationtests/languages/python/...
80+
run: go test ./integrationtests/tests/python/...
8181

8282
rust-integration-tests:
8383
name: Rust Integration Tests
@@ -106,7 +106,7 @@ jobs:
106106
- run: rust-analyzer --version
107107

108108
- name: Run Rust integration tests
109-
run: go test ./integrationtests/languages/rust/...
109+
run: go test ./integrationtests/tests/rust/...
110110

111111
typescript-integration-tests:
112112
name: TypeScript Integration Tests
@@ -130,4 +130,4 @@ jobs:
130130
run: npm install -g typescript typescript-language-server
131131

132132
- name: Run TypeScript integration tests
133-
run: go test ./integrationtests/languages/typescript/...
133+
run: go test ./integrationtests/tests/typescript/...

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@ test-output/
88
# Temporary files
99
*~
1010

11-
CLAUDE.md
11+
CLAUDE.md*
12+
.mcp.json
13+
.goosehints

README.md

Lines changed: 160 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -5,130 +5,180 @@
55
[![GoDoc](https://pkg.go.dev/badge/github.com/isaacphi/mcp-language-server)](https://pkg.go.dev/github.com/isaacphi/mcp-language-server)
66
[![Go Version](https://img.shields.io/github/go-mod/go-version/isaacphi/mcp-language-server)](https://github.com/isaacphi/mcp-language-server/blob/main/go.mod)
77

8-
A Model Context Protocol (MCP) server that runs a language server and provides tools for communicating with it.
8+
This is an [MCP](https://modelcontextprotocol.io/introduction) server that runs and exposes a [language server](https://microsoft.github.io/language-server-protocol/) to LLMs. Not a language server for MCP, whatever that would be.
99

10-
## Motivation
10+
## Demo
1111

12-
Claude desktop with the [filesystem](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem) server feels like magic when working on small projects. This starts to fall apart after you add a few files and imports. With this project, I want to create that experience when working with large projects.
12+
`mcp-language-server` helps MCP enabled clients navigate codebases more easily by giving them access semantic tools like get definition, references, rename, and diagnostics.
1313

14-
Language servers excel at tasks that LLMs often struggle with, such as precisely understanding types, understanding relationships, and providing accurate symbol references. This project aims to makes bring those tools to LLMs. LSP also seems like a clear inspiration for MCP so why not jam them together?
15-
16-
## Status
17-
18-
⚠️ Pre-beta Quality ⚠️
19-
20-
I have tested this server with the following language servers
21-
22-
- gopls (Go)
23-
- pyright (Python)
24-
- typescript-language-server (TypeScript)
25-
- rust-analyzer (Rust)
26-
27-
But it should be compatible with many more.
28-
29-
## Tools
30-
31-
- `read_definition`: Retrieves the complete source code definition of any symbol (function, type, constant, etc.) from your codebase.
32-
- `find_references`: Locates all usages and references of a symbol throughout the codebase.
33-
- `get_diagnostics`: Provides diagnostic information for a specific file, including warnings and errors.
34-
- `get_codelens`: Retrieves code lens hints for additional context and actions on your code.
35-
- `execute_codelens`: Runs a code lens action.
36-
- `apply_text_edit`: Allows making multiple text edits to a file programmatically.
37-
- `hover`: Display documentation, type hints, or other hover information for a given location.
38-
- `rename_symbol`: Rename a symbol across a project.
39-
40-
Behind the scenes, this MCP server can act on `workspace/applyEdit` requests from the language server, so it can apply things like refactor requests, adding imports, formatting code, etc.
41-
42-
Each tool supports various options for customizing output, such as including line numbers or additional context. See the tool documentation for detailed usage. Line numbers are necessary for `apply_text_edit` to be able to make accurate edits.
43-
44-
## About
45-
46-
This codebase makes use of edited code from [gopls](https://go.googlesource.com/tools/+/refs/heads/master/gopls/internal/protocol) to handle LSP communication. See ATTRIBUTION for details.
47-
48-
[mcp-go](https://github.com/mark3labs/mcp-go) is used for MCP communication.
49-
50-
## Prerequisites
51-
52-
Install Go: Follow instructions at <https://golang.org/doc/install>
53-
54-
Fetch or update this server:
55-
56-
```bash
57-
go install github.com/isaacphi/mcp-language-server@latest
58-
```
59-
60-
Install a language server for your codebase:
61-
62-
- Python (pyright): `npm install -g pyright`
63-
- TypeScript (typescript-language-server): `npm install -g typescript typescript-language-server`
64-
- Go (gopls): `go install golang.org/x/tools/gopls@latest`
65-
- Rust (rust-analyzer): `rustup component add rust-analyzer`
66-
- Or use any language server
14+
![Demo](demo.gif)
6715

6816
## Setup
6917

70-
Add something like the following configuration to your Claude Desktop settings (or similar MCP-enabled client):
18+
1. **Install Go**: Follow instructions at <https://golang.org/doc/install>
19+
2. **Install or update this server**: `go install github.com/isaacphi/mcp-language-server@latest`
20+
3. **Install a language server**: _follow one of the guides below_
21+
4. **Configure your MCP client**: _follow one of the guides below_
7122

72-
```json
23+
<details>
24+
<summary>Go (gopls)</summary>
25+
<div>
26+
<p><strong>Install gopls</strong>: <code>go install golang.org/x/tools/gopls@latest</code></p>
27+
<p><strong>Configure your MCP client</strong>: This will be different but similar for each client. For Claude Desktop, add the following to <code>~/Library/Application\ Support/Claude/claude_desktop_config.json</code></p>
28+
29+
<pre>
30+
{
31+
"mcpServers": {
32+
"language-server": {
33+
"command": "mcp-language-server",
34+
"args": ["--workspace", "/Users/you/dev/yourproject/", "--lsp", "gopls"],
35+
"env": {
36+
"PATH": "/opt/homebrew/bin:/Users/you/go/bin",
37+
"GOPATH": "/users/you/go",
38+
"GOCACHE": "/users/you/Library/Caches/go-build",
39+
"GOMODCACHE": "/Users/you/go/pkg/mod"
40+
}
41+
}
42+
}
43+
}
44+
</pre>
45+
46+
<p><strong>Note</strong>: Not all clients will need these environment variables. For Claude Desktop you will need to update the environment variables above based on your machine and username:</p>
47+
<ul>
48+
<li><code>PATH</code> needs to contain the path to <code>go</code> and to <code>gopls</code>. Get this with <code>echo $(which go):$(which gopls)</code></li>
49+
<li><code>GOPATH</code>, <code>GOCACHE</code>, and <code>GOMODCACHE</code> may be different on your machine. These are the defaults.</li>
50+
</ul>
51+
52+
</div>
53+
</details>
54+
<details>
55+
<summary>Rust (rust-analyzer)</summary>
56+
<div>
57+
<p><strong>Install rust-analyzer</strong>: <code>rustup component add rust-analyzer</code></p>
58+
<p><strong>Configure your MCP client</strong>: This will be different but similar for each client. For Claude Desktop, add the following to <code>~/Library/Application\ Support/Claude/claude_desktop_config.json</code></p>
59+
60+
<pre>
7361
{
7462
"mcpServers": {
7563
"language-server": {
7664
"command": "mcp-language-server",
7765
"args": [
7866
"--workspace",
79-
"/Users/you/dev/yourcodebase",
67+
"/Users/you/dev/yourproject/",
8068
"--lsp",
81-
"/opt/homebrew/bin/pyright-langserver",
69+
"rust-analyzer"
70+
]
71+
}
72+
}
73+
}
74+
</pre>
75+
</div>
76+
</details>
77+
<details>
78+
<summary>Python (pyright)</summary>
79+
<div>
80+
<p><strong>Install pyright</strong>: <code>npm install -g pyright</code></p>
81+
<p><strong>Configure your MCP client</strong>: This will be different but similar for each client. For Claude Desktop, add the following to <code>~/Library/Application\ Support/Claude/claude_desktop_config.json</code></p>
82+
83+
<pre>
84+
{
85+
"mcpServers": {
86+
"language-server": {
87+
"command": "mcp-language-server",
88+
"args": [
89+
"--workspace",
90+
"/Users/you/dev/yourproject/",
91+
"--lsp",
92+
"pyright-langserver",
8293
"--",
8394
"--stdio"
84-
],
85-
"env": {
86-
"LOG_LEVEL": "INFO"
87-
}
95+
]
8896
}
8997
}
9098
}
91-
```
99+
</pre>
100+
</div>
101+
</details>
102+
<details>
103+
<summary>Typescript (typescript-language-server)</summary>
104+
<div>
105+
<p><strong>Install typescript-language-server</strong>: <code>npm install -g typescript typescript-language-server</code></p>
106+
<p><strong>Configure your MCP client</strong>: This will be different but similar for each client. For Claude Desktop, add the following to <code>~/Library/Application\ Support/Claude/claude_desktop_config.json</code></p>
107+
108+
<pre>
109+
{
110+
"mcpServers": {
111+
"language-server": {
112+
"command": "mcp-language-server",
113+
"args": [
114+
"--workspace",
115+
"/Users/you/dev/yourproject/",
116+
"--lsp",
117+
"typescript-language-server",
118+
"--",
119+
"--stdio"
120+
]
121+
}
122+
}
123+
}
124+
</pre>
125+
</div>
126+
</details>
127+
<details>
128+
<summary>Other</summary>
129+
<div>
130+
<p>I have only tested this repo with the servers above but it should be compatible with many more. Note:</p>
131+
<ul>
132+
<li>The language server must communicate over stdio.</li>
133+
<li>Any aruments after <code>--</code> are sent as arguments to the language server.</li>
134+
<li>Any env variables are passed on to the language server.</li>
135+
</ul>
136+
</div>
137+
</details>
92138

93-
Replace:
139+
## Tools
94140

95-
- `/Users/you/dev/yourcodebase` with the absolute path to your project
96-
- `/opt/homebrew/bin/pyright-langserver` with the path to your language server (found using `which` command e.g. `which pyright-langserver`)
97-
- Any aruments after `--` are sent as arguments to your language server.
98-
- Any env variables are passed on to the language server. Some may be necessary for you language server. For example, `gopls` required `GOPATH` and `GOCACHE` in order for me to get it working properly.
99-
- `LOG_LEVEL` is optional. See below.
141+
- `definition`: Retrieves the complete source code definition of any symbol (function, type, constant, etc.) from your codebase.
142+
- `references`: Locates all usages and references of a symbol throughout the codebase.
143+
- `diagnostics`: Provides diagnostic information for a specific file, including warnings and errors.
144+
- `hover`: Display documentation, type hints, or other hover information for a given location.
145+
- `rename_symbol`: Rename a symbol across a project.
146+
- `edit_file`: Allows making multiple text edits to a file based on line numbers. Provides a more reliable and context-economical way to edit files compared to search and replace based edit tools.
100147

101-
## Development
148+
## About
102149

103-
Clone the repository:
150+
This codebase makes use of edited code from [gopls](https://go.googlesource.com/tools/+/refs/heads/master/gopls/internal/protocol) to handle LSP communication. See ATTRIBUTION for details. Everything here is covered by a permissive BSD style license.
104151

105-
```bash
106-
git clone https://github.com/isaacphi/mcp-language-server.git
107-
cd mcp-language-server
108-
```
152+
[mcp-go](https://github.com/mark3labs/mcp-go) is used for MCP communication. Thank you for your service.
109153

110-
Install dev dependencies:
154+
This is beta software. Please let me know by creating an issue if you run into any problems or have suggestions of any kind.
111155

112-
```bash
113-
go mod download
114-
```
156+
## Contributing
115157

116-
Build:
158+
Please keep PRs small and open Issues first for anything substantial. AI slop OK as long as it is tested, passes checks, and doesn't smell too bad.
117159

118-
```bash
119-
go build
120-
```
160+
### Setup
121161

122-
Run tests:
162+
Clone the repo:
123163

124164
```bash
125-
go test ./...
165+
git clone https://github.com/isaacphi/mcp-language-server.git
166+
cd mcp-language-server
126167
```
127168

128-
Update test snapshots:
169+
A [justfile](https://just.systems/man/en/) is included for convenience:
129170

130171
```bash
131-
UPDATE_SNAPSHOTS=true go test ./integrationtests/...
172+
just -l
173+
Available recipes:
174+
build # Build
175+
check # Run code audit checks
176+
fmt # Format code
177+
generate # Generate LSP types and methods
178+
help # Help
179+
install # Install locally
180+
snapshot # Update snapshot tests
181+
test # Run tests
132182
```
133183

134184
Configure your Claude Desktop (or similar) to use the local binary:
@@ -142,7 +192,7 @@ Configure your Claude Desktop (or similar) to use the local binary:
142192
"--workspace",
143193
"/path/to/workspace",
144194
"--lsp",
145-
"/path/to/language/server"
195+
"language-server-executable"
146196
],
147197
"env": {
148198
"LOG_LEVEL": "DEBUG"
@@ -154,28 +204,28 @@ Configure your Claude Desktop (or similar) to use the local binary:
154204

155205
Rebuild after making changes.
156206

157-
## Feedback
207+
### Logging
208+
209+
Setting the `LOG_LEVEL` environment variable to DEBUG enables verbose logging to stderr for all components including messages to and from the language server and the language server's logs.
158210

159-
Include
211+
### LSP interaction
212+
213+
- `internal/lsp/methods.go` contains generated code to make calls to the connected language server.
214+
- `internal/protocol/tsprotocol.go` contains generated code for LSP types. I borrowed this from `gopls`'s source code. Thank you for your service.
215+
- LSP allows language servers to return different types for the same methods. Go doesn't like this so there are some ugly workarounds in `internal/protocol/interfaces.go`.
216+
217+
### Local Development and Snapshot Tests
218+
219+
There is a snapshot test suite that makes it a lot easier to try out changes to tools. These run actual language servers on mock workspaces and capture output and logs.
220+
221+
You will need the language servers installed locally to run them. There are tests for go, rust, python, and typescript.
160222

161223
```
162-
env: {
163-
"LOG_LEVEL": "DEBUG",
164-
}
224+
integrationtests/
225+
├── tests/ # Tests are in this folder
226+
├── snapshots/ # Snapshots of tool outputs
227+
├── test-output/ # Gitignored folder showing the final state of each workspace and logs after each test run
228+
└── workspaces/ # Mock workspaces that the tools run on
165229
```
166230

167-
To get detailed LSP and application logs. Setting `LOG_LEVEL` to DEBUG enables verbose logging for all components. Adding `LOG_COMPONENT_LEVELS` with `wire:DEBUG` shows raw LSP JSON messages. Please include as much information as possible when opening issues.
168-
169-
The following features are on my radar:
170-
171-
- [x] Read definition
172-
- [x] Get references
173-
- [x] Apply edit
174-
- [x] Get diagnostics
175-
- [x] Code lens
176-
- [x] Hover info
177-
- [x] Rename symbol
178-
- [ ] Code actions
179-
- [ ] Better handling of context and cancellation
180-
- [ ] Add LSP server configuration options and presets for common languages
181-
- [ ] Create tools at a higher level of abstraction, combining diagnostics, code lens, hover, and code actions when reading definitions or references.
231+
To update snapshots, run `UPDATE_SNAPSHOTS=true go test ./integrationtests/...`

0 commit comments

Comments
 (0)