Metadata-Version: 2.4
Name: jons-mcp-typescript
Version: 0.0.2
Summary: Model Context Protocol (MCP) server for TypeScript tooling via vtsls, Prettier, ESLint, and oxlint
Author: Jon Mease
License-Expression: MIT
Project-URL: Homepage, https://github.com/jonmmease/jons-mcp-typescript
Project-URL: Repository, https://github.com/jonmmease/jons-mcp-typescript
Project-URL: Issues, https://github.com/jonmmease/jons-mcp-typescript/issues
Project-URL: Changelog, https://github.com/jonmmease/jons-mcp-typescript/releases
Keywords: mcp,typescript,vtsls,lsp,prettier,eslint,oxlint,development
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Build Tools
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: fastmcp>=3.0.0
Requires-Dist: pydantic>=2.0.0
Provides-Extra: test
Requires-Dist: pytest>=7.0.0; extra == "test"
Requires-Dist: pytest-asyncio>=0.21.0; extra == "test"
Requires-Dist: pytest-timeout>=2.1.0; extra == "test"
Requires-Dist: pytest-mock>=3.10.0; extra == "test"
Requires-Dist: pytest-cov>=4.0.0; extra == "test"
Dynamic: license-file

# 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:

```bash
uvx jons-mcp-typescript /path/to/typescript/project
```

To run the latest source from GitHub instead of the published package:

```bash
uvx --from git+https://github.com/jonmmease/jons-mcp-typescript.git \
  jons-mcp-typescript /path/to/typescript/project
```

### Prerequisites

1. **Python 3.10+** with `uv`
2. **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.
3. **vtsls** - TypeScript language server, installed globally or in the TypeScript project:
   ```bash
   # Global install
   npm install -g @vtsls/language-server

   # Or project-local install
   cd /path/to/typescript/project
   npm install -D @vtsls/language-server
   ```
4. **Project-local Prettier and configured linter dependencies** in the TypeScript project you run the server against:
   ```bash
   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

```bash
# 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:

```bash
# 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:

```bash
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:

```json
{
  "mcpServers": {
    "typescript": {
      "command": "uvx",
      "args": [
        "jons-mcp-typescript",
        "."
      ]
    }
  }
}
```

Verify it with:

```bash
claude mcp get typescript
```

#### Codex CLI

From the TypeScript project root, add the server to Codex:

```bash
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:

```toml
[mcp_servers.typescript]
command = "uvx"
args = [
  "jons-mcp-typescript",
  ".",
]
```

Verify it with:

```bash
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:

```bash
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:

```json
{
  "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

```python
# 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

```python
# 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

```python
# 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

```python
# 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

```python
# 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*`, or
  `package.json` `eslintConfig`) win over oxlint configs
  (`.oxlintrc.json`, `.oxlintrc.jsonc`, or `oxlint.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

```bash
git clone https://github.com/jonmmease/jons-mcp-typescript.git
cd jons-mcp-typescript
uv sync --group dev
```

### Running Tests

```bash
# 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](LICENSE).
