TypeScript type inference inspection tool for AI coding assistants
- ✓Open-source license (MIT)
- ✓Actively maintained (<30d)
- ✓Clear description
- ✓Topics declared
- ✓Documented (README)
claude mcp add typeprobe -- npx -y typeprobe{
"mcpServers": {
"typeprobe": {
"command": "npx",
"args": ["-y", "typeprobe"]
}
}
}MCP Servers overview
<p align="center">
<img src="typeprobe-logo.webp" alt="typeprobe logo" width="400">
</p>
# typeprobe
typeprobe asks the TypeScript compiler what it infers (types, completions, type errors) so that AI coding agents and tests don't have to guess. It comes as:
- an MCP server for coding agents (Claude Code, Codex, Cursor, VS Code, Gemini CLI, any stdio client),
- `typeprobe/testing`, which returns inferred types as strings for snapshot tests,
- a CLI and a synchronous library API.
typeprobe was called prinfer until 4.0.0. See [Migrating from prinfer](#migrating-from-prinfer).
## Quick start
Give your agent the compiler:
```bash
npx -y typeprobe setup claude # or codex, cursor, vscode, gemini; see Install
```
The agent can now call `hover_by_name(file: "src/utils.ts", name: "names")` and get `Type: string[]` back, or `diagnostics(file)` after an edit.
Lock the types your API infers in a test (Vitest, Jest, Bun, or any runner with snapshots):
```typescript
import { expect, test } from "vitest"; // or "bun:test"
import { inferredType } from "typeprobe/testing";
import { groupBy, type User } from "../src/users";
const users: User[] = [{ name: "Ada", role: "admin" }];
const byRole = groupBy(users, (user) => user.role);
test("groupBy keys the result by the callback's return type", () => {
expect(inferredType(import.meta.url, { name: "byRole" }))
.toMatchInlineSnapshot(`"Record<Role, User[]>"`);
});
```
Write the matcher empty (`toMatchInlineSnapshot()`) and the runner fills it in. A refactor that changes the type fails the test.
## Install
Every command runs through `npx`, so nothing needs installing first. After `npm i -g typeprobe`, drop the `npx -y` prefix: setup then registers the `typeprobe-mcp` binary, which skips npx's package check on each launch.
**Claude Code.** The plugin bundles the MCP server and a skill that tells Claude when to use it:
```text
/plugin marketplace add clockblocker/typeprobe
/plugin install typeprobe@typeprobe
```
**Other clients**, or Claude Code without the plugin:
| Client | Command | Writes |
| :- | :- | :- |
| Claude Code | `npx -y typeprobe setup claude` | `claude mcp add`; `--scope project` for a shared `.mcp.json` |
| Codex | `npx -y typeprobe setup codex` | `codex mcp add` (`~/.codex/config.toml`) |
| Cursor | `npx -y typeprobe setup cursor` | `~/.cursor/mcp.json`; `--scope project`: `.cursor/mcp.json` |
| VS Code | `npx -y typeprobe setup vscode` | `code --add-mcp`; `--scope project`: `.vscode/mcp.json` |
| Gemini CLI | `npx -y typeprobe setup gemini` | `~/.gemini/settings.json`; `--scope project`: `.gemini/settings.json` |
Any other MCP client: typeprobe is a stdio server started with `npx -y typeprobe mcp`.
```json
{
"mcpServers": {
"typeprobe": { "command": "npx", "args": ["-y", "typeprobe", "mcp"] }
}
}
```
It is also listed in the [MCP Registry](https://registry.modelcontextprotocol.io/v0/servers?search=io.github.clockblocker/typeprobe) as `io.github.clockblocker/typeprobe` and on [Smithery](https://smithery.ai/servers/clockblocker/typeprobe).
Setup options:
- `--print` shows the command or config change without applying it.
- `--npx` registers `npx -y typeprobe mcp` even when `typeprobe-mcp` is installed. Use it when the client can't find `typeprobe-mcp`; editors started outside a shell often miss nvm, fnm, or volta paths.
- Re-running setup updates the `typeprobe` entry's command and leaves other servers alone. JSON configs keep keys you added to the entry, such as `env`. A JSON config that doesn't parse is left untouched, and setup prints the entry to add by hand.
- A `prinfer` entry from before the rename is replaced rather than kept next to the new one: `claude` and `codex` remove it, and JSON configs swap it for `typeprobe` in place, keeping its other keys (with `PRINFER_*` env names renamed to `TYPEPROBE_*`).
- On Windows the server is registered as `cmd /c npx -y typeprobe mcp` (or `cmd /c typeprobe-mcp`), because clients launch it without a shell and can't run npm's `.cmd` shims.
### Tell the agent when to use it
Tool descriptions only go so far; agents still reach for `tsc` or write annotations by hand. Add a short usage block to your instructions file (the Claude Code plugin ships the same guidance as a skill):
```bash
npx -y typeprobe setup agents-md # ./AGENTS.md
npx -y typeprobe setup agents-md --file CLAUDE.md
```
The block sits between `<!-- typeprobe:start -->` and `<!-- typeprobe:end -->`; re-running updates it in place, and replaces a block prinfer wrote (`<!-- prinfer:start -->`).
## MCP tools
| Tool | Use it for |
| :- | :- |
| `hover_by_name` | The type of a named symbol. Start here. |
| `hover` | The type of a token on a line: callback parameters, expressions, repeated names. |
| `batch_hover` | Up to 100 lookups, across files, in one call. |
| `completions` | What TypeScript offers at a cursor, such as string-literal union members. |
| `diagnostics` | Type errors in one file, without checking the whole project. |
| `annotations` | Annotations TypeScript would infer anyway. |
Shared parameters:
- `file` is absolute or relative to the server's working directory. Lines and columns are 1-based.
- `project` is a `tsconfig.json` path; the default is the nearest one above the file.
- `backend` (`typescript7` by default, or `typescript6`) on the hover tools and `diagnostics`. If a call fails or looks wrong on TypeScript 7, retry it with `typescript6`. See [Backends and compilers](#backends-and-compilers).
- Hover tools take `include_docs` (JSDoc), `include_cost` (see [Type cost budgets](#type-cost-budgets)), `full`, and `max_chars`. Type text is capped at 4000 characters per type, and a cut type ends with a line like `… truncated: 187 chars total, union of 4 members. Pass max_chars: N to see more (0 for no limit).` `full: true` turns off TypeScript's own truncation (`{ ...; }`, `... 12 more ...`) and lists every overload. Structured content is never cut.
### hover_by_name
```text
hover_by_name(file: "src/utils.ts", name: "names")
hover_by_name(file: "src/utils.ts", name: "names", line: 11) # line picks among same-named symbols
```
```text
Type: string[]
Name: names
Kind: const
Position: 11:14
```
When a name is declared more than once, the lookup prefers declarations and says which it picked: `Matched line 8 of 2 declarations (also 12); pass line to choose.` The structured result lists the others as `alternatives: [{ line, column, kind }]`. A `line` that matches none fails with `SYMBOL_NOT_FOUND` and lists the declaration lines in `declaredAt`. A `line` where the name is used rather than declared, such as `box.value` in an `if`, gives the type there, narrowed by the code around it.
Overloaded functions show the first signature, then up to three more (`full: true` lists all; structured `overloads` always has every one):
```text
Type: (value: string): number (+1 overload)
Overloads:
(value: number): string
Returns: number
Name: parse
Kind: function
Position: 1:17
```
### hover
Pass `text` copied from the line and typeprobe finds the column. Whole identifiers match first: on `users.map((user) => user.name)`, `text: "user"` skips `users` and hits the callback parameter, and `occurrence: 2` picks the next `user`. Only when the line has no whole-identifier match is `text` matched as a substring. `column` works in place of `text`. Generic calls show their instantiated types, as in an editor.
```text
hover(file: "src/utils.ts", line: 11, text: "user")
```
```text
Type: { id: number; name: string; }
Name: user
Kind: parameter
Position: 11:33
Target: "user" at 11:33
```
If the text isn't on the line, the error quotes the line:
```text
Error [SYMBOL_NOT_FOUND]: Text "nope" not found on line 11 of /project/src/utils.ts
Nearby identifiers: name, names, map, user, users
Suggestion: Line 11 reads: "export const names = users.map((user) => user.name);". Copy text exactly from it, or give a column instead.
```
### batch_hover
Each item is `{name, line?}`, `{line, text, occurrence?}`, or `{line, column}`, with an optional `file` that overrides the shared top-level `file`. Failures are per item, including a missing file, so one bad lookup doesn't lose the rest.
```text
batch_hover(file: "src/utils.ts", positions: [
{name: "users"},
{line: 11, text: "user"},
{file: "src/missing.ts", line: 1, column: 1}
])
```
```text
Batch hover results: 2 succeeded, 1 failed
--- src/utils.ts:users:6 ---
Type: { id: number; name: string; }[]
...
--- src/missing.ts:1:1 ---
Error [FILE_NOT_FOUND]: File not found: /project/src/missing.ts
Suggestion: Check the path. Relative paths resolve against the MCP server's working directory (/project); pass an absolute path to be sure.
```
A line or column outside the file is an `INVALID_ARGUMENT` error that gives the valid range.
### Hover results
Every hover returns the same fields on every backend and surface:
- `signature`: the type text alone, on one line, without the declaration keyword or name an editor hover starts with. `string[]` for a variable, `(value: string): number` for a function, the instantiated signature for a call. Type aliases keep their name and type parameters (`type Event = { kind: "open"; ... } | ...`); interfaces and classes are their name (`Box<T>`). Optional members read as `tsc` writes them in declarations: `digits?: number`, with `| undefined` only where the source wrote it or the type isn't the annotation's (an instantiated generic, a `Partial<T>`).
- `display`: the editor's hover text (`const names: string[]`). Only the TypeScript 7 language server reports it.
- `kind`: the editor's label (`function`, `method`, `const`, `parameter`, `property`, `type`, `interface`, `class`, `enum`, ...), plus `call` for the callee of a call.
- `returnType`, `documentation`, `overloads`, `unionMembers`, and `alternatives` when they apply.
- `cost`: `{ instantiations, types }` with `include_cost: true`.
- `compiler`: `{ name, version, source }`, tWhat people ask about typeprobe
What is clockblocker/typeprobe?
+
clockblocker/typeprobe is mcp servers for the Claude AI ecosystem. TypeScript type inference inspection tool for AI coding assistants It has 1 GitHub stars and its last recorded update is dated 2026-10-10.
How do I install typeprobe?
+
You can install typeprobe by cloning the repository (https://github.com/clockblocker/typeprobe) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.
Is clockblocker/typeprobe safe to use?
+
Our security agent has analyzed clockblocker/typeprobe and assigned a Trust Score of 95/100 (tier: Verified). See the full breakdown of passed checks and flags on this page.
Who maintains clockblocker/typeprobe?
+
clockblocker/typeprobe is maintained by clockblocker. The last recorded GitHub activity is dated 2026-10-10, with 0 open issues.
Are there alternatives to typeprobe?
+
Yes. On ClaudeWave you can browse similar mcp servers at /categories/mcp, sorted by popularity or recent activity.
Deploy typeprobe to your cloud
Ship this repo to production in minutes. Each platform spins up its own environment with editable env vars.
Maintain this repo? Add a badge to your README
Drop the badge into your GitHub README to show it's tracked on ClaudeWave. Each badge links back to this page and reflects the live Trust Score.
[](https://claudewave.com/repo/clockblocker-typeprobe)<a href="https://claudewave.com/repo/clockblocker-typeprobe"><img src="https://claudewave.com/api/badge/clockblocker-typeprobe" alt="Featured on ClaudeWave: clockblocker/typeprobe" width="320" height="64" /></a>More MCP Servers
Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.
User-friendly AI Interface (Supports Ollama, OpenAI API, ...)
An open-source AI agent that brings the power of Gemini directly into your terminal.
Real-time global intelligence dashboard. AI-powered news aggregation, geopolitical monitoring, and infrastructure tracking in a unified situational awareness interface
🕷️ An adaptive Web Scraping framework that handles everything from a single request to a full-scale crawl! Don't be shy, join here: https://discord.gg/EMgGbDceNQ and follow here for daily tips and tricks: https://x.com/Scrapling_dev
The fastest path to AI-powered full stack observability, even for lean teams.