mcpField
T
Type Atlas

Type Atlas

ローカル
github.com/tyler-mitchell開発ツール29 週間前に更新

Type Atlas について

Type Atlas は、TypeScript と JavaScript のコードベースを意味的にナビゲートし、診断情報を提供する MCP サーバーです。シンボルの関係、自然言語によるコード検索、プロジェクト範囲を組み合わせ、大規模リポジトリやモノレポでの作業を支援します。

主な機能

  1. 01定義・参照・呼び出し元・型のナビゲーション
  2. 02自然言語の動作説明によるコード検索
  3. 03レスポンスへの関連診断の追加
  4. 04プロジェクト範囲とソース位置の保持
  5. 05コンテキストを考慮した構造化結果

活用シーン

  1. 01モノレポで呼び出し元と実装を追跡
  2. 02動作の説明から既存ヘルパーを検索
  3. 03コード調査中に型診断を確認

MCP 対応

Type Atlas は MCP サーバーとして動作し、コーディングエージェントは MCP クライアント設定から接続します。ツールはコードナビゲーション、検索、診断を提供し、意味インデックスを使う4つのツールには uv が必要です。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

mcp.json · 共通設定
{
"mcpServers": {
"tyler-mitchell-type-atlas": {
"command": "npx",
"args": [
"-y",
"@type-atlas/mcp"
]
}
}
}
起動コマンドnpx -y @type-atlas/mcp

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
npm@type-atlas/mcp1.0.0

ツール

40

掲載時のツール一覧 · 3 週間前に更新

パラメーター型必須説明
filearrayはいまとめて読み取る 1 つ以上のファイル。パス、または単一ファイルの範囲を指定する { path, startLine, endLine, fold } を指定できます。両方を混在させることもできます。例:["a.ts", { "path": "b.ts", "startLine": 1, "endLine": 40 }]。
foldbooleanいいえ個別に指定されていない項目では、関数本体をシグネチャに折りたたみます。
endLineintegerいいえ最後の行。行番号は 1 から始まり、この行を含みます。個別に指定されていない項目に適用されます。
startLineintegerいいえ最初の行。行番号は 1 から始まります。個別に指定されていない項目に適用されます。
workspacestringはいリポジトリのルート。言語サーバーのセッションを選択するため、サブディレクトリではなく、リポジトリごとに同じルートを使用してください。相対パスは MCP プロセスの作業ディレクトリを基準に解決されます。
includeDiagnosticsenumいいえ指定できる値:summary(完全な診断情報 1 件とファイル合計)、verbose(完全なレポート)、off(診断情報を省略)。off | summary | verbose

詳細

Type Atlas — TypeScript のコードインテリジェンス

npm node license

Type Atlas は、私がすべての TypeScript プロジェクトで、コードナビゲーションのあらゆる用途に使わせているコードエージェント向けツールです。これらのプロジェクトのほとんどはモノレポです。なかには大規模で複雑なため、変更がシステム全体のなかでどのように位置づけられるかを理解することが、作業の重要な一部となっているものもあります。このツールは、エージェントのデフォルトのコードナビゲーション手法を完全に置き換えることを目的に設計しました。

自分のプロジェクトでコーディングエージェントが実際にどう動作するかをもとに、数か月にわたってこのツールを改良してきました。Type Atlas の機能の多くは、同じ問題を何度も目にしたことから生まれています。

  • エージェントはシステムの不完全な像をもとに推論します。 見つけたファイルの内容は理解していても、そのコードがどう使われるべきかを決める周辺コードを見落とすことがあります。
  • エージェントはすでに存在するものを作り直します。 必要な機能はリポジトリ内にすでにあるのに、その名前を知らないためにエージェントが見つけられないことがあります。
  • エージェントは、コードを読み取る量が少なすぎる(Claude)か、多すぎる(Codex)ことがよくあります。 少なすぎると、周辺の文脈が十分でないまま判断することになります。多すぎると、タスクに関係のないファイル全体や実装の詳細でコンテキストウィンドウが埋まります。
  • エージェントは、IDE ならすでに表示されているエラーを見つけるためだけに、繰り返し作業を止めて型チェックを実行します。 そのたびに実装全体の遅延が増え、フィードバックを必要以上に遅らせます。
  • エージェントは根本的に、何も見えない状態で作業しています。 文字列検索によるナビゲーションでは、コードベースの確かな内部マップを得られません。取得できたファイルの断片や検索結果だけを頼りに実装を判断せざるを得ず、重要な構造やコンパイラーが把握している情報が欠けたままです。

プロジェクトが成長するにつれて、こうした問題は積み重なり、エージェントが書くコードの品質に直接表れるようになります。

セマンティックなコードナビゲーション

コーディングエージェントは、デフォルトではファイルの読み取りや文字列検索を通じてコードをナビゲートします。これではソーステキストを取得できるだけで、TypeScript の言語サービスがすでに把握している関係をモデルが再構築しなければなりません。

Type Atlas を使うと、エージェントはそのセマンティック情報に直接アクセスできます。

  • シンボルから、同じ文字列の出現箇所すべてではなく、実際の定義や参照を特定できます。
  • 呼び出し元や実装は、シンボルとの関係に基づいて識別されます。
  • 推論された型は、近くのソースから再構築するのではなく、言語サービスから取得されます。
  • 結果には、ソース範囲と、それを所有する TypeScript プロジェクトの情報が保持されます。

エージェントが探しているものがテキストである場合は、テキスト検索も依然として有用です。しかし、プログラム自体についての問いに対して、セマンティックなナビゲーションの代わりとして使うには力不足です。

すでにあるものを見つける

大規模なコードベースには、エージェントが名前を知らない便利なコードが含まれています。文字列検索が最も効果を発揮するのは、エージェントが検索語を組み立てられるだけの語彙をすでに知っている場合です。

Type Atlas を使えば、ほかの方法でもコードにたどり着けます。

  • エージェントは自然言語で動作を説明し、それに基づいてコードを見つけられます。
  • 見つかった結果から、実際のシンボルと正確なソース範囲にたどり着けます。
  • そのシンボルから、別の識別子を推測して検索するのではなく、コードベース内の実際の関係をたどれます。

これは大規模なモノレポで特に役立ちます。既存のヘルパーや確立された実装を見つけやすくなるため、エージェントが別のものを作る必要があると判断する前に、それらを発見できます。

通常の作業中の診断

IDE を使う開発者は、作業中にコンパイラーのフィードバックを確認できます。コーディングエージェントは通常、実装を中断して型チェックコマンドを実行し、結果を待つことでフィードバックを得ます。

Type Atlas は、エージェントがすでに行っている作業の中に、そのフィードバックの多くを取り込みます。

  • 通常のコードインテリジェンス応答とともに、関連する診断が届きます。
  • 問題のあるコードがエージェントの現在の作業コンテキストに含まれている間に、エラーが表示されます。
  • 誤った型の想定が、依存する編集をいくつも行う前に見つかります。

検証には引き続き完全な型チェックを使います。ただし、エージェントが作業中にエラーを把握する主な手段にする必要はありません。

モデルコンテキストに適した応答

応答を小さくすることが有用なのは、取り除いた情報が不要な場合に限ります。モデルは、残った情報の構成も利用します。

Type Atlas は、構造も情報の一部として扱います。

  • ラベルによって、結果の役割が明確になります。
  • グループ化によって、関連する事実がまとまります。
  • ファイルの境界によって、無関係なソースが混ざるのを防ぎます。
  • ソース位置は、それが説明する対象に結び付いたままです。
  • ツリーは、平坦な列に変わることなく階層を保ちます。
  • 診断には、内容を理解するために必要なソースが含まれます。

何を省くかも、同じ原則に基づいて決まります。シグネチャで十分な場合は、関数本体を折りたたんだままにできます。利用可能だからといって、繰り返しのシリアライズ情報や無関係なソースをコンテキストウィンドウに含める必要はありません。

目標は、有用な情報密度です。トークン数を減らすことも重要ですが、そのトークンをモデルが理解するのに役立つ構造を取り除いてしまっては本末転倒です。

次の判断に役立つ情報

ツール呼び出しはすべて、エージェントの推論プロセスの一部です。優れた応答は、現在の問いに答えると同時に、次に何を調べるべきか判断しやすい状態をエージェントにもたらします。

Type Atlas は、結果を明らかにした情報の近くに、有用な追加調査の情報を保ちます。

  • シンボルには、コードベース内での関わり方を理解するために必要な関連情報を添えられます。
  • リポジトリの構造には、ファイルとともに行数や作業ツリーの状態を含められます。
  • 検索結果には、そのまま追跡できる具体的なソース範囲が含まれます。
  • エージェントが結果から結果へと移動しても、プロジェクトのコンテキストは引き継がれます。

これにより、エージェントは調査の各分岐点で、より確かな根拠を得られます。すべてのテキスト一致を同等に重要な手掛かりとして扱うのではなく、プログラム内に実際に存在する関係をたどることができます。

利点は、ナビゲーションの品質が向上することです。各ステップで、次のステップを選ぶために必要な情報がより多く保たれます。

プロジェクトとスコープの把握

TypeScript に関する問いへの回答は、プロジェクトのコンテキストに左右されます。モノレポでは特に重要です。あるプロジェクト内では正しい回答でも、リポジトリ全体としては不完全なことがあるためです。

Type Atlas は、こうした境界を明確に保ちます。

  • ファイルは、そのファイルを所有する TypeScript プロジェクトを通じて解決されます。
  • スコープが重要な場合は、結果にその対象プロジェクトが明記されます。
  • 件数によって、結果の規模が明確になります。
  • 回答がリポジトリ全体を対象としていない場合は、その制限が示されます。
  • ソース位置は、後続の呼び出しに直接渡せます。

これによりエージェントは、回答に依拠する前に、その回答が実際にどこまでを対象としているのかを理解するのに十分な情報を得られます。

日々のエージェント利用から生まれました

私はすべての TypeScript プロジェクトで、毎日自分のコーディングエージェントと Type Atlas を使っています。現在の動作は、繰り返し使う中で生まれました。

設計の多くは、エージェントに繰り返し見られる行動に直接由来しています。

  • エージェントが不要な本体にコンテキストを割いていたため、読み取り結果を折りたたみます。
  • 型チェックコマンドを繰り返し実行して実装時間を浪費していたため、診断情報を通常の応答に含めます。
  • エージェントが別々の呼び出しで同じ情報を再構成していたため、意味的な関連情報をまとめます。
  • エージェントがタスクから名前を推測できない便利なコードも多いため、自然言語によるコード検索を用意しています。

Type Atlas での私の仕事の進め方は今も変わりません。エージェントが同じナビゲーションの問題で時間を浪費したり、同じ種類の情報を繰り返し見落としたりするのを目にしたら、ツールを変更します。

以下の例は、フィクスチャ用モノレポに対して実行中のサーバーから取得し、実装との回帰チェックを行ったものです。

インストール

codex mcp add type-atlas -- npx --yes @type-atlas/mcp@latest

claude mcp add --scope user type-atlas -- npx --yes @type-atlas/mcp@latest

code --add-mcp '{"name":"type-atlas","command":"npx","args":["--yes","@type-atlas/mcp@latest"]}'

それ以外のクライアントでは、標準的な形式を使います。

{
  "mcpServers": {
    "type-atlas": {
      "command": "npx",
      "args": ["--yes", "@type-atlas/mcp@latest"]
    }
  }
}

シェルの PATH を使わずにサーバーを起動するクライアントは、名前だけでは npx を見つけられません。その場合は、which npx で確認した絶対パスを指定してください。Windows で npx.cmd シムを起動できないクライアントでは、"command": "cmd" と "args": ["/c", "npx", "--yes", "@type-atlas/mcp@latest"] が必要です。

クライアントは起動時に MCP 設定を読み込むため、その後に再起動してください。@latest はプロセスを起動するたびに解決されます。ツールの動作が意図せず変わらないようにするには、バージョンを固定してください。

search_code、related_code、investigate_code、search_dependency_code は uvx 経由でセマンティックインデックスを実行するため、uv が必要です。uv がない場合、これら 4 つのツールは uv が見つからないと報告し、explore_symbol は関連コードのセクションを省略します。それ以外には影響しません。

推奨

サーバーをインストールしても、エージェントが何を選ぶかは変わりません。Claude など一部のエージェントは、シェルで許可されているものを何でも組み合わせて実行し、そのたびに新しい正当化を作り出します。そのため、避けるべきコマンドをいくつか指定しても効果はありません。指示ではカテゴリ全体を禁止し、例外を明示する必要があります。これを AGENTS.md または CLAUDE.md に追加してください。

Type Atlas MCP は、TypeScript および JavaScript のコードを読み取り、ナビゲートするために必須のツールです。これは好みの問題ではありません。どのように組み合わせたものであっても、シェルコマンドで代用することは認められません。単純なファイル読み取りも同様です。有効な代替手段は、サーバーが停止している場合、呼び出しでエラーが発生した場合、または対象ファイルが TS でも JS でもない場合に限られます。

--require-intent

このオプトインフラグを有効にすると、リポジトリ検索やワークスペースシンボルなど、広範な探索ツールで判断を示す一文が必須になります。対象を絞った読み取りやセマンティック検索には影響せず、意図がツールの応答に含まれることもありません。

ツール呼び出しの結果

パスはワークスペースを基準とし、座標は 1 始まりです。そのため、ある回答に含まれる場所を次の呼び出しへの入力として使用できます。編集ツールはパッチを返します。こちらでファイルに書き込むことはありません。

以下の内容はすべて、fixtures/ledger に対して実行中のサーバーから取得したものです。シナリオスイート は同じ呼び出しを再実行し、差異があれば失敗します。ここに手書きの内容はなく、ツールの応答が変わると、同じコミットでこのファイルも変更されます。ソースは README.mdoc です。各ツールの詳しい例は docs/tools にあります。

list_files

エディターで使われているバッジ文字を使って、構造、行数、git status をひとつのツリーにまとめます。削除されたファイルも、git の結果にだけ存在するものとして行に表示します。折りたたまれたディレクトリは、消えるのではなく、何を含んでいるかを示します。

エージェントの入力

tool: List files
workspace: fixtures/ledger
# working tree arranged: currency.ts edited · rounding.ts created · index.ts deleted
directory: packages/money
depth: 2

# answered in 57ms

応答

packages/money/
├  src/ · 3 changed
│  ├  currency.ts · 21 loc · M +2
│  ├  index.ts · D -12
│  ├  money.ts · 58 loc
│  ├  rounding-mode.ts · 15 loc
│  └  rounding.ts · 11 loc · U
├  tests/
│  ├  money.test.ts · 15 loc
│  └  rounding-parity.ts · 15 loc
├  package.json · 19 loc
└  tsconfig.json · 20 loc
inspect_symbol

ホバー、定義、型定義、実装、呼び出し元、呼び出し、参照を1回の呼び出しで確認できます。参照は呼び出し元と定義を考慮した残りなので、同じ使用箇所が重複して表示されることはありません。これらのツールを個別に呼び出す場合と比べて、文字数は4分の1、ラウンドトリップは7分の1になります。

エージェントの入力

tool: Inspect symbol
workspace: fixtures/ledger
file: packages/accounts/src/journal.ts
symbol: Journal

# answered in 49ms

レスポンス

Journal [class] · packages/accounts/src/journal.ts:24:14-24:21 · range 24:1-73:2 · packages/accounts/tsconfig.json

```typescript
class Journal<TMeta = undefined>
```

An append-only journal of balanced entries. `TMeta` carries whatever a
consumer attaches to each entry — an import batch id, an approval trail —
without the journal knowing its shape.

## Callers (4)

packages/accounts/tests/journal.test.ts
├  test("posts a balanced transfer through the overload") callback [function] 5:56-14:2 · calls 6:23-6:30
└  test("refuses an unbalanced entry") callback [function] 16:37-29:2 · calls 17:23-17:30
packages/reports/src/balance.ts
└  balancesAsOf [variable] 23:14-23:26 · range 23:14-51:2 · calls 24:12-24:19
packages/importers/src/csv.ts
└  importStatement [variable] 28:14-28:29 · range 28:14-47:2 · calls 29:12-29:19

## Mentions that are not calls (4 of 9 references · 5 relevant projects searched)

packages/accounts/tests/journal.test.ts:3:25-3:32:  import { credit, debit, Journal, UnbalancedEntryError } from "../src/index.ts";
packages/accounts/src/index.ts:11:22-11:29:  export { type Entry, Journal, UnbalancedEntryError } from "./journal.ts";
packages/reports/src/balance.ts:4:8-4:15:  type Journal,
packages/importers/src/csv.ts:1:10-1:17:  import { Journal, type Entry, credit, debit, type AccountPath } from "@ledger/accounts";

references lists all 9, with paging.
read_file

引数は配列なので、複数のファイルを1回の呼び出しで取得できます。デフォルトでは本文がシグネチャに折りたたまれ、ヘッダーに節約できた行数が表示されます。fold: false を指定すると本文が返されます。

エージェントの入力

tool: Read files
workspace: fixtures/ledger
file: ["packages/accounts/src/posting.ts","packages/money/src/rounding-mode.ts"]

# answered in 7ms

レスポンス

2 files · 42 lines · 6 folded to signatures, pass fold: false for the bodies

=== packages/accounts/src/posting.ts · 32 lines ===

 1 | import { type Money, negate } from "@ledger/money";
 2 | import type { AccountPath } from "./account.ts";
 3 |
 4 | /**
 5 |  * One side of a journal entry. The discriminant is the bookkeeping side, so
 6 |  * every consumer's switch is checked for exhaustiveness by the compiler.
 7 |  */
 8 | export type Posting =
 9 |   | { readonly side: "debit"; readonly account: AccountPath; readonly amount: Money }
10 |   | { readonly side: "credit"; readonly account: AccountPath; readonly amount: Money };
11 |
12 | export const debit = (account: AccountPath, amount: Money): Posting => ({
13 |   side: "debit",
14 |   account,
15 |   amount,
16 | });
17 |
18 | export const credit = (account: AccountPath, amount: Money): Posting => ({
19 |   side: "credit",
20 |   account,
21 |   amount,
22 | });
23 |
24 | /** A posting's effect on a debit-normal running balance. */
25 | export const signedAmount = (posting: Posting): Money => {
   |   ... 26-31 folded
32 | };

=== packages/money/src/rounding-mode.ts · 15 lines ===

 1 | /** How sub-minor precision resolves when a statement and the books disagree. */
 2 | export enum RoundingMode {
 3 |   HalfUp = "half-up",
 4 |   HalfEven = "half-even",
 5 |   Truncate = "truncate",
 6 | }
 7 |
 8 | /** Per-institution conventions, as observed in their exports. */
 9 | const bankRounding: Readonly<Record<string, RoundingMode>> = {
10 |   "first-national": RoundingMode.HalfEven,
11 |   "harbor-credit": RoundingMode.HalfUp,
12 | };
13 |
14 | export const roundingModeOf = (bank: string): RoundingMode =>
15 |   bankRounding[bank] ?? RoundingMode.HalfEven;
occurrences

エージェントが識別子の名前は知っていても、ファイルがわからない場合に、正確な識別子から検索を開始します。識別子の構文ノードによって関連プロジェクトが有効になり、TypeScript が正規の宣言と意味上の参照を解決します。同じ名前のシンボルは個別に扱われ、オーバーロードは統合されます。また、解決できない識別子は参照リストに混ぜず、明示されます。

エージェントの入力

tool: Occurrences
workspace: fixtures/ledger
query: money
limit: 12

# answered in 244ms

レスポンス

Identifiers: "money"

Scope: workspace · 33 project files

Showing 1–12 of 22 references · next offset: 12

=== money [function] · packages/money/src/money.ts:27:14 · 12/22 references shown ===

24 exact-name locations across 8 files · 1 without a workspace declaration

Locations without a workspace declaration (1):

packages/reconcile/src/matching.ts:24:37 — inside emptyRemainder · export const emptyRemainder = () => money(0, "USD");

packages/importers/src/csv.ts
├  2:37  — at module level · import { type Currency, isCurrency, money, zero, format } from "@ledger/money";
└  34:20 — inside amount · const amount = money(Math.abs(row.amountMinor), row.currency);
packages/money/src/index.ts
└  8:3 — at module level · money,
packages/money/src/money.ts
├  30:52 — inside zero · export const zero = (currency: Currency): Money => money(0n, currency);
├  42:10 — inside add · return money(left.minorUnits + right.minorUnits, left.currency);
└  45:48 — inside negate · export const negate = (value: Money): Money => money(-value.minorUnits, value.currency);
packages/reconcile/src/drift.ts
├  5:18  — at module level · import { format, money, type Money } from "@ledger/money";
└  21:17 — inside drift · return format(money(journalTotal - statementTotal(statement), "usd"));
packages/accounts/tests/journal.test.ts
├  1:10  — at module level · import { money } from "@ledger/money";
├  9:71  — inside test("posts a balanced transfer through the overload") callback · { from: "assets:bank:checking", to: "expenses:furniture", amount: money(24900, "USD") },
├  23:34 — inside expect() callback · debit("expenses:travel", money(5000, "USD")),
└  24:40 — inside expect() callback · credit("assets:bank:checking", money(500, "USD")),
search_code

名前を推測できない場合に、コードの動作を手がかりに検索します。検索結果はランク順に返され、それぞれに該当するファイル範囲が含まれるため、次の呼び出し先がわかります。リアルタイムの回答には各検索結果の関連性の割合も含まれますが、その背後にある埋め込みスコアはマシンによって異なり、以下のケースはバイト単位で比較されるため、ここでは省略しています。

エージェントの入力

tool: Search code
workspace: fixtures/ledger
query: walking an account up through each of its ancestor accounts
snippetLines: 6

# answered in 20ms

レスポンス

Search: walking an account up through each of its ancestor accounts

5 matches · no identifier to anchor on, so these are ranked by meaning alone

=== 1 · packages/accounts/src/account.ts:21-35 ===

Structure: parentPath
Symbol: parentPath [variable] · selection 21:14-21:24 · range 21:14-24:2

21 | export const parentPath = (path: AccountPath): AccountPath | undefined => {
22 |   const at = path.lastIndexOf(":");
23 |   return at === -1 ? undefined : path.slice(0, at);
24 | };
25 |
26 | /** Every ancestor from root to the account itself: `a`, `a:b`, `a:b:c`. */

=== 2 · packages/reports/src/balance.ts:1-23 ===

Structure: BalanceLine
Symbol: BalanceLine [interface] · selection 11:18-11:29 · range 11:1-16:2

1 | import {
2 |   type AccountPath,
3 |   type Entry,
4 |   type Journal,
5 |   lineage,
6 |   signedAmount,

=== 3 · packages/accounts/src/journal.ts:59-73 ===

Structure: Journal > history
Symbol: history [method] · selection 60:3-60:10 · range 60:3-64:4

59 |   /** Entries touching an account, oldest first. */
60 |   history(account: AccountPath): readonly Entry<TMeta>[] {
61 |     return this.entries.filter((entry) =>
62 |       entry.postings.some((posting) => posting.account === account),
63 |     );
64 |   }

=== 4 · packages/reports/src/statement.ts:1-11 ===

Structure: statementLine
Symbol: statementLine [variable] · selection 8:14-8:27 · range 8:14-11:2

1 | import { type Account, normalBalance } from "@ledger/accounts";
2 | import { format, type Money, negate } from "@ledger/money";
3 |
4 | /**
5 |  * One rendered statement line. The sign follows the account's normal side:
6 |  * a liability holding a credit balance reads as positive on its statement.

=== 5 · packages/accounts/src/posting.ts:1-24 ===

Structure: credit
Symbol: credit [variable] · selection 18:14-18:20 · range 18:14-22:3

1 | import { type Money, negate } from "@ledger/money";
2 | import type { AccountPath } from "./account.ts";
3 |
4 | /**
5 |  * One side of a journal entry. The discriminant is the bookkeeping side, so
6 |  * every consumer's switch is checked for exhaustiveness by the compiler.
diagnostics

プロジェクトごとに実行する、コンパイラー本来のプログラム全体のチェックであり、ファイル単位のチェックではありません。あるファイルの編集で別のファイルに問題が起きることはよくあります。そのファイルを見つけるのがこの呼び出しです。

エージェントの入力

tool: Diagnostics
workspace: fixtures/ledger
project: packages/reconcile
scope: project

# answered in 23ms

レスポンス

Whole project · 6 problems in 2 files · 11 files checked · packages/reconcile/tsconfig.json

=== packages/reconcile/src/drift.ts ===

error typescript(2365) 16:33-16:52 — inside lines.reduce() callback
  Operator '+' cannot be applied to types 'number' and 'Money'.
   14 | /** Statement total, computed by someone who forgot Money is not a number.…
   15 | export const statementTotal = (lines: readonly StatementLine[]): number =>
   16 |   lines.reduce((total, line) => total + line.amount, 0);
      |                                 ^^^^^^^^^^^^^^^^^^^
   17 |
   18 | /** Drift between the journal's view and the bank's view of one day. */

error typescript(2365) 20:77-20:91 — inside reduce() callback
  Operator '+' cannot be applied to types 'import("packages/money/src/money").Money' and 'import("packages/money/src/money").Money'.
   18 | /** Drift between the journal's view and the bank's view of one day. */
   19 | export const drift = (postings: readonly Posting[], statement: readonly St…
   20 |   const journalTotal = postings.map(signedAmount).reduce((total, amount) =…
      |                                                                             ^^^^^^^^^^^^^^
   21 |   return format(money(journalTotal - statementTotal(statement), "usd"));
   22 | };

error typescript(2362) 21:23-21:35 — inside drift
  The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.
   19 | export const drift = (postings: readonly Posting[], statement: readonly St…
   20 |   const journalTotal = postings.map(signedAmount).reduce((total, amount) =…
   21 |   return format(money(journalTotal - statementTotal(statement), "usd"));
      |                       ^^^^^^^^^^^^
   22 | };
   23 |

error typescript(2345) 21:65-21:70 — inside drift
  Argument of type '"usd"' is not assignable to parameter of type 'Currency'.
   19 | export const drift = (postings: readonly Posting[], statement: readonly St…
   20 |   const journalTotal = postings.map(signedAmount).reduce((total, amount) =…
   21 |   return format(money(journalTotal - statementTotal(statement), "usd"));
      |                                                                 ^^^^^
   22 | };
   23 |

=== packages/reconcile/src/matching.ts ===

error typescript(2304) 14:20-14:32 — inside amount
  Cannot find name 'signedAmount'.
   12 |   const matched = new Map<Posting, StatementLine>();
   13 |   for (const posting of postings) {
   14 |     const amount = signedAmount(posting);
      |                    ^^^^^^^^^^^^
   15 |     const line = lines.find(
   16 |       (candidate) => candidate.amount.minorUnits === amount.minorUnits,

error typescript(2304) 24:37-24:42 — inside emptyRemainder
  Cannot find name 'money'.
   22 |
   23 | /** The zero of a matching pass, for currencies the statement never names.…
   24 | export const emptyRemainder = () => money(0, "USD");
      |                                     ^^^^^
   25 |
workspace_symbols

セッションで読み込まれたすべてのプロジェクトを対象に、名前から宣言を検索します。おおよその名前はわかっているものの、どこにあるかがわからない場合に使います。

エージェントの入力

tool: Workspace symbols
workspace: fixtures/ledger
file: packages/importers/src/statement-parser.ts
query: Parser

# answered in 100ms

レスポンス

3 symbols matching Parser · 8 projects loaded · packages/importers/tsconfig.json

CsvStatementParser [class] · packages/importers/src/statement-parser.ts:25:1-35:2
FixedWidthStatementParser [class] · packages/importers/src/statement-parser.ts:41:1-64:2
StatementParser [class] · packages/importers/src/statement-parser.ts:7:1-23:2
file_references

このモジュールをインポートしているのはどのファイルか。モジュール内のシンボルを先に選ばずに、モジュール単位の質問に答えます。

エージェントの入力

tool: File references
workspace: fixtures/ledger
file: packages/money/src/money.ts

# answered in 134ms

レスポンス

packages/money/src/money.ts · referenced from 90 places · 6 relevant projects searched · packages/money/tsconfig.json

1-20 of 90 places · pass offset: 20 for the rest

packages/accounts/src/journal.ts
├  1:10  — at module level
└  53:15 — inside post
packages/money/src/index.ts
├  3:3 — at module level
├  4:3 — at module level
└  5:3 — at module level
packages/money/tests/money.test.ts
├  2:10  — at module level
├  2:15  — at module level
├  2:38  — at module level
├  5:10  — inside test("adds amounts of one currency exactly") callback
├  9:16  — inside expect() callback
├  9:67  — inside test("refuses to combine currencies") callback
├  13:10 — inside test("formats major and minor units per currency") callback
└  14:10 — inside test("formats major and minor units per currency") callback
packages/reports/src/balance.ts
├  8:10  — at module level
├  34:9  — inside balancesAsOf
└  41:28 — inside balancesAsOf
packages/reports/src/statement.ts
├  2:10  — at module level
└  10:40 — inside statementLine
packages/rules/src/builtin.ts
├  2:10  — at module level
└  28:58 — inside closedPeriodsBalance

パッケージ

パッケージ役割
@type-atlas/mcpMCP サーバー
@type-atlas/coreヘッドレスなコードインテリジェンス API
@type-atlas/language-servercore パッケージが駆動する Volar ベースの言語サーバー

開発

vp install
vp run check
vp run check:distribution

変更およびリリースの手順については、CONTRIBUTING.md をご覧ください。

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。