MCP wrapper for Metals (Scala language server) that adds file editing and refactoring tools.
- Node.js 22+
metals-mcpbinary on PATH (or setMETALS_MCP_PATH)
npm installAdd to your project's .mcp.json:
{
"mcpServers": {
"metals": {
"command": "npx",
"args": ["tsx", "src/index.ts", "--workspace", "/path/to/scala/project"]
}
}
}Or globally in ~/.claude.json:
{
"mcpServers": {
"metals": {
"command": "npx",
"args": ["--prefix", "/path/to/metals-mcp", "tsx", "src/index.ts", "--workspace", "/path/to/scala/project"]
}
}
}npx tsx src/index.ts --workspace /path/to/scala/projectFile operations: read-file, write-file, edit-file, list-files
Refactoring: rename-symbol, add-import, remove-unused-imports
All Metals tools are also proxied transparently when Metals connects.
| Option | Description |
|---|---|
--workspace <path> |
Scala project root (required) |
METALS_MCP_PATH |
Custom path to metals-mcp binary |
If the MCP server is configured in .mcp.json with a relative path for the entry point:
{
"mcpServers": {
"metals": {
"command": "npx",
"args": ["--prefix", "/path/to/metals-lsp", "tsx", "src/index.ts"]
}
}
}The npx --prefix flag sets the package lookup directory, but the working directory remains the project being edited. The relative src/index.ts resolves against the workspace, not the plugin directory, causing the module-not-found error.
Fix: Use an absolute path for the entry point:
{
"mcpServers": {
"metals": {
"command": "npx",
"args": ["--prefix", "/path/to/metals-lsp", "tsx", "/path/to/metals-lsp/src/index.ts"]
}
}
}