Model Context Protocol (MCP) server for TypeScript tooling via vtsls, Prettier, ESLint, and oxlint
Project description
jons-mcp-typescript
Model Context Protocol (MCP) server for TypeScript tooling via vtsls, Prettier, ESLint, and oxlint.
Features
- TypeScript Language Server Integration - Full LSP support via vtsls for code navigation, symbol information, and type checking
- Prettier Formatting - Code formatting with automatic config resolution
- Configured Linting - ESLint or oxlint linting with auto-fix support
- Unified Operations - Combined check and fix tools for efficient workflows
Installation
Install or run from PyPI:
uvx jons-mcp-typescript /path/to/typescript/project
To run the latest source from GitHub instead of the published package:
uvx --from git+https://github.com/jonmmease/jons-mcp-typescript.git \
jons-mcp-typescript /path/to/typescript/project
Prerequisites
- Python 3.10+ with
uv - Node.js 18.18+, Node.js 20.9+, or a newer supported Node.js release. If your target project uses oxlint, use a Node.js version supported by that project-local oxlint release.
- vtsls - TypeScript language server, installed globally or in the TypeScript project:
# Global install npm install -g @vtsls/language-server # Or project-local install cd /path/to/typescript/project npm install -D @vtsls/language-server
- Project-local Prettier and configured linter dependencies in the TypeScript project you run the server against:
cd /path/to/typescript/project npm install -D prettier eslint # Or, for oxlint-only projects: npm install -D prettier oxlint
The Python package includes the small Node daemon source. The daemon intentionally uses Prettier, ESLint, and oxlint from your target project's node_modules so formatting and linting match that project.
Usage
Running the Server
# Run from PyPI against the current directory
uvx jons-mcp-typescript .
# Run from PyPI against a specific project root
uvx jons-mcp-typescript /path/to/typescript/project
# Run unreleased source from GitHub
uvx --from git+https://github.com/jonmmease/jons-mcp-typescript.git \
jons-mcp-typescript .
Local Development (Running from Source)
To run the server locally during development:
# Clone and setup
git clone https://github.com/jonmmease/jons-mcp-typescript.git
cd jons-mcp-typescript
uv sync --group dev
# Install TypeScript project dependencies used by the server
cd /path/to/your/typescript/project
npm install -D @vtsls/language-server prettier eslint
# Or replace eslint with oxlint for oxlint-only projects
# Run against current directory
uv run jons-mcp-typescript
# Run against a specific TypeScript project
uv run jons-mcp-typescript /path/to/your/typescript/project
# Run from anywhere using uv's --project flag (uses cwd as TypeScript project)
cd /path/to/your/typescript/project
uv run --project /path/to/jons-mcp-typescript jons-mcp-typescript .
MCP Client Configuration
Claude Code
From the TypeScript project root, add the server to Claude Code:
cd /path/to/typescript/project
claude mcp add typescript --scope local -- \
uvx jons-mcp-typescript .
Use --scope project instead of --scope local if you want Claude Code to write a shared .mcp.json file in the project. A shared project config should look like this:
{
"mcpServers": {
"typescript": {
"command": "uvx",
"args": [
"jons-mcp-typescript",
"."
]
}
}
}
Verify it with:
claude mcp get typescript
Codex CLI
From the TypeScript project root, add the server to Codex:
cd /path/to/typescript/project
codex mcp add typescript -- \
uvx jons-mcp-typescript .
This writes an MCP server entry to Codex's config. The equivalent TOML is:
[mcp_servers.typescript]
command = "uvx"
args = [
"jons-mcp-typescript",
".",
]
Verify it with:
codex mcp get typescript
If you want the MCP server to always target one specific TypeScript project, replace the final "." with an absolute project path in the CLI command or config.
Local Checkout Configuration
For active development on this MCP server, clone the repo and point your MCP client at the checkout:
git clone https://github.com/jonmmease/jons-mcp-typescript.git
cd jons-mcp-typescript
uv sync --group dev
Then configure your MCP client to run:
{
"mcpServers": {
"typescript": {
"command": "uv",
"args": [
"run",
"--project", "/path/to/jons-mcp-typescript",
"jons-mcp-typescript",
"."
]
}
}
}
This tells uv to use the Python environment from /path/to/jons-mcp-typescript and run jons-mcp-typescript against the current working directory, which should be your TypeScript project.
Available Tools
Navigation & Discovery
| Tool | Purpose |
|---|---|
document_symbols |
List all symbols defined in a file |
definition |
Jump to where a symbol is defined |
type_definition |
Jump to the type definition of a symbol |
implementation |
Find implementations of interfaces/abstract classes |
references |
Find all usages of a symbol |
Understanding Code
| Tool | Purpose |
|---|---|
type_info_of_reference |
Get TypeScript display info and accessible members for a value reference |
symbol_info |
Get type signature and docs for any symbol |
Type Checking
| Tool | Purpose |
|---|---|
diagnostics |
Get fresh type errors and warnings for one file |
Refactoring
| Tool | Purpose |
|---|---|
preview_rename |
Preview a symbol rename across the project without writing files |
Formatting & Linting
| Tool | Purpose |
|---|---|
format_code |
Format code using Prettier |
check_formatting |
Check if code is formatted correctly |
lint_code |
Lint code using the configured ESLint or oxlint runner |
get_prettier_config |
Get resolved Prettier configuration |
get_eslint_config |
Get selected linter config information; ESLint projects return resolved config, oxlint projects return config-file metadata |
Unified Operations
| Tool | Purpose |
|---|---|
check_all |
Run all checks (formatting, linting, types) on a file |
fix_all |
Apply all automatic fixes to a file |
Server Management
| Tool | Purpose |
|---|---|
restart_server |
Restart TypeScript language server and formatter/linter daemon |
Tool Examples
Recommended Workflow
For most single-file quality checks, start with check_all. It runs TypeScript
diagnostics, Prettier, and the configured lint runner together and returns one
combined summary. The lint step uses ESLint when an ESLint config is nearest,
uses oxlint when an oxlint config is nearest and no ESLint config applies, and
skips cleanly when no linter config exists. Use fix_all when you want
automatic linter fixes followed by Prettier formatting, optionally writing the
result back to disk.
format_code, check_formatting, and lint_code remain available as lower
level tools when you need only one formatter or linter operation. For
project-wide symbol-name discovery, start with text search to find candidate
files, then use document_symbols or the semantic position-based tools.
preview_rename is safe to inspect: it returns edits, a flat list of file
URI, one-based replacement range, and newText values, plus totalEdits. It
does not write to disk by itself.
In monorepos, semantic tools such as references, implementation, and
preview_rename are limited to the TypeScript project scope that vtsls can see
for the probed file. A root solution tsconfig.json or editor-equivalent
project setup can make more packages visible, but the server does not
auto-index or preload every workspace package. Without that TypeScript project
coverage, sibling or downstream packages may be omitted from semantic results.
TypeScript project loading is lazy, so the first call against a newly probed
package can occasionally report that the project is not ready; retrying the
same tool shortly is usually enough once vtsls finishes loading that project.
Position Inputs And Results
Tools such as definition, references, symbol_info,
type_info_of_reference, and preview_rename use one-based positions for both
inputs and returned ranges. If
your editor, terminal listing, or agent Read output shows line 28, pass
line=28; returned ranges also use line 28 for that same source line. When you
do not already know a position, document_symbols returns one-based ranges for
the symbols in a file.
Navigate to Definition
# Find where a function is defined
result = await definition(
file_path="/project/src/index.ts",
line=10,
character=15,
)
# Returns: {"items": [{"uri": "file:///project/src/utils.ts", "range": {...}}], "totalItems": 1}
Get Type Information
# Get TypeScript display info plus fields and methods of a value reference
result = await type_info_of_reference(
file_path="/project/src/app.ts",
line=5,
character=8,
)
# Returns: {"displayString": "const user: User", "kind": "const", "fields": [...], "methods": {...}}
Check Everything
# Run TypeScript, Prettier, and configured linter checks for one file
result = await check_all(
file_path="/project/src/app.ts"
)
# Returns: {"overallPassed": false, "checks": {...}, "summary": "..."}
Fix Everything
# Run configured linter fixes, then Prettier formatting
result = await fix_all(
file_path="/project/src/app.ts",
write=True,
)
# Returns: {"finalCode": "...", "totalChanges": 2, "written": true}
Preview Rename
# Preview a project-scoped symbol rename without writing files
result = await preview_rename(
file_path="/project/src/app.ts",
line=12,
character=8,
new_name="newName",
)
# Returns:
# {
# "edits": [{"uri": "file:///project/src/app.ts", "range": {...}, "newText": "newName"}],
# "totalEdits": 1,
# }
Architecture
┌─────────────────────────────────────────────────────────────────┐
│ MCP Client │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ FastMCP Server (Python) │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Tool Handlers │ │
│ │ language.py intelligence.py formatting.py linting.py │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────┐ ┌─────────────────────────────────┐ │
│ │ VtslsClient │ │ FormatterLinterDaemon │ │
│ │ (LSP over stdio) │ │ (JSON Lines over stdio) │ │
│ └─────────────────────┘ └─────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│ │
▼ ▼
┌─────────────────────┐ ┌─────────────────────────────────────┐
│ vtsls │ │ Node.js Daemon │
│ (TypeScript LSP) │ │ ┌─────────────────────────────┐ │
│ │ │ │ PrettierManager │ │
│ │ │ │ LinterManager │ │
│ │ │ │ ESLint / oxlint │ │
│ │ │ └─────────────────────────────┘ │
└─────────────────────┘ └─────────────────────────────────────┘
Configuration
Environment Variables
| Variable | Description | Default |
|---|---|---|
VTSLS_PATH |
Path to vtsls executable | Auto-detected |
LOG_LEVEL |
Logging level (DEBUG, INFO, etc.) | INFO |
Config Resolution
- Prettier: Resolves
.prettierrc,.prettierrc.json,.prettierrc.js, etc. - Linting: Walks from the file directory to the project root. At each
directory, ESLint configs (
eslint.config.*,.eslintrc*, orpackage.jsoneslintConfig) win over oxlint configs (.oxlintrc.json,.oxlintrc.jsonc, oroxlint.config.*). If no lint config exists, lint tools return a skipped result instead of failing. - TypeScript: Uses vtsls and the TypeScript project that vtsls associates
with the probed file. In monorepos, cross-package semantic coverage depends
on your
tsconfig.json/project-reference setup rather than server-side workspace preloading.
Development
Setup
git clone https://github.com/jonmmease/jons-mcp-typescript.git
cd jons-mcp-typescript
uv sync --group dev
Running Tests
# Run all tests
uv run pytest
# Run with coverage
uv run pytest --cov=src/jons_mcp_typescript
# Run specific test file
uv run pytest tests/test_utils.py -v
Test Requirements
Integration tests require:
- Node.js 18.18+, Node.js 20.9+, or a newer supported Node.js release
- Node.js 20.19+ for oxlint integration tests when using current oxlint releases
- vtsls installed globally or in the temporary test project
- Prettier plus ESLint or oxlint available to the temporary test project
Tests will skip gracefully if dependencies are missing.
License
MIT. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file jons_mcp_typescript-0.0.2-py3-none-any.whl.
File metadata
- Download URL: jons_mcp_typescript-0.0.2-py3-none-any.whl
- Upload date:
- Size: 71.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0c84d0a6bfedc9ec2f8792bb5b136ab2d1aeaa6fe755b05989746775a7791693
|
|
| MD5 |
52e8654c87689c0ae5a3cbc169e4995e
|
|
| BLAKE2b-256 |
e15b1b5394eb0f41ac12238e15095432540827579087817cdf17cfd025a08cf9
|
Provenance
The following attestation bundles were made for jons_mcp_typescript-0.0.2-py3-none-any.whl:
Publisher:
release.yml on jonmmease/jons-mcp-typescript
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
jons_mcp_typescript-0.0.2-py3-none-any.whl -
Subject digest:
0c84d0a6bfedc9ec2f8792bb5b136ab2d1aeaa6fe755b05989746775a7791693 - Sigstore transparency entry: 1704830731
- Sigstore integration time:
-
Permalink:
jonmmease/jons-mcp-typescript@40b6392ad5377ca40cb84c99058425d911775e81 -
Branch / Tag:
refs/tags/v0.0.2 - Owner: https://github.com/jonmmease
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@40b6392ad5377ca40cb84c99058425d911775e81 -
Trigger Event:
release
-
Statement type: