GridPath について
GridPath は、実際の Excel ブックを編集するスプレッドシートエンジンです。アプリ開発者やコーディングエージェント向けに、数式を保持して元の .xlsx に変更を書き戻し、保存前の確認にも対応します。
主な機能
- 01実際の .xlsx ブックを編集
- 02数式をリアルタイムに再計算
- 03エージェントの変更を確認・承認・拒否
- 04元ファイルに変更を書き戻し
- 05埋め込み型スプレッドシート UI
- 06CSV と区切りテキストを読み込み
活用シーン
- 01コーディングエージェントでブックを編集・確認
- 02Web アプリにスプレッドシートを組み込む
- 03CSV データを編集可能なブックに変換
MCP 対応
Claude Code、Claude Desktop、Cursor、Codex などのクライアントからディスク上のブックを編集する MCP サーバーを提供します。保存前に変更を確認できます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
32掲載時のツール一覧 · 1 日前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| cell | string | はい | A1 アドレス。例:"A1"、"B17"、"AA42"。 |
| path | string | はい | 操作対象の .xlsx のパス(絶対パス、またはユーザーのホームディレクトリを示す ~/…)。 |
| sheet | string | はい | シート名(大文字と小文字を区別)。 |
| value | any | いいえ | リテラル値(文字列、数値、ブール値、または null)。`formula` を使用する場合は null のままにしてください。 |
| formula | string|null | いいえ | '=' で始まる Excel 形式の数式。参照には A1 表記を使用します。例:"=SUM(A1:A10)"。 |
詳細
gridpath
Web アプリとエージェントで、本物の Excel ファイルを扱えます。 ユーザーがすでに持っている .xlsx を開き、すべての数式を元のサイズで有効なまま保ち、AI にレビュー付きで編集させて、同じファイルに保存できます。
| Web アプリ内 | コーディングエージェント内 | |
|---|---|---|
| インストール | npm install gridpath | claude mcp add gridpath -- npx -y gridpath mcp |
| 利用できる機能 | Rust/WebAssembly エンジンを Web Worker 上で動かす、埋め込み可能なスプレッドシート。.xlsx の上書き保存と、独自のモデル向けエージェントツールを利用できます | Claude Code、Claude Desktop、Cursor、Codex 向けの MCP サーバーです。エージェントがディスク上のファイルを編集し、保存前にすべての変更を確認できます |
| ドキュメント | Web アプリ内 | コーディングエージェント内 |
どちらも同じエンジン(IronCalc のフォーク)を使用します。数式はプロセス内で実際に評価され、保存時には元のファイルにパッチを適用するため、変更していない部分はバイト単位で元の状態が保たれます。再計算された数式と、サポート対象のグラフデータキャッシュには最新の値が反映されます。グラフ定義はネイティブの Excel XML のまま維持されます。
Web アプリ内
- クイックスタート · Next.js · ユーザーが利用できる機能
- ブックとドキュメント · CSV とテキストファイル · 保存 · バックエンドへの保存
- エラー · Excel の保存値 · AI
- オプション · メソッド · バンドラー · 保存の仕組み
クイックスタート
npm install gridpath react react-dom
React と React DOM はピア依存関係です。アプリで React を使用する必要はありません。createSpreadsheet は、任意の要素にスプレッドシートをマウントします。
import { Spreadsheet } from "gridpath";
<div style={{ height: 600 }}>
<Spreadsheet
file={bytes} // an .xlsx as ArrayBuffer or Uint8Array; omit for a blank workbook
onReady={(sheet) => (sheetRef.current = sheet)}
onError={(err) => console.error(err.code, err.message, err.hint)}
/>
</div>;
React を使用しない場合:
import { createSpreadsheet } from "gridpath";
const sheet = await createSpreadsheet(document.getElementById("sheet")!, { file: await file.arrayBuffer() });
sheet.setCell("Sheet1", "B2", "=SUM(A1:A10)");
console.log(await sheet.getCell("Sheet1", "B2")); // { value: 55, formula: "=SUM(A1:A10)" }
const xlsx = await sheet.save(); // Uint8Array
createSpreadsheet は、ブックが開かれると解決されます。開けない場合は GridPathError でリジェクトされ、要素は空のままになります。
Next.js
設定は不要です。Next.js 16 と React 19 で、Turbopack および webpack を使用し、next dev と本番ビルドの両方でテスト済みです。
- クライアントコンポーネント(
"use client")からスプレッドシートをレンダリングします。その周囲のページはサーバーコンポーネントのままにできます。 gridpath/agentはルートハンドラーで動作します。
完全なアプリの例は examples/nextjs-demo です。各ユーザーは、アプリ独自の API に保存されたブックのリストを持ちます。app/api/books/[[...path]]/route.ts には、認証付きで httpStore が呼び出す REST ルートが含まれています。各ブックには専用の URL があります。この例では、次の方法を紹介しています。
- ブックをアップロードして新規作成する
- 読み込みインジケーターを表示する
- エラーコードごとの対処方法
- ブックを切り替える際に、離れるブックを保存する
コードなしでユーザーが利用できる機能
-
書式設定用のツールバー:
- 元に戻す、やり直す;
- フォントとサイズ;
- 太字、斜体、下線;
- フォントの色と塗りつぶしの色;
- 配置と折り返し;
- 通貨、パーセント、桁区切り、小数点以下の桁数の増減;
- 数値の表示形式;
- 行と列の挿入および削除;
- 並べ替え、フィルター、ウィンドウ枠の固定、クリア。
キーボードショートカット(⌘B、⌘Z、⌘S…)はグリッドで動作します。
toolbar={false}を指定すると、ツールバーが非表示になります。 -
保存先を示す保存ステータス:「このブラウザーに保存済み」、「アカウントに保存済み」、「保存中…」、「未保存の変更あり」、「保存できませんでした · 再試行」のいずれかが表示されます。
- 編集内容は、編集が止まってから2秒後に保存されます。⌘Sまたは保存ボタンを押すと、すぐに保存されます。
-
中断したところから再開:再読み込み後、ブックが復元され、ユーザーが最後に選択していたセルも復元されます。
-
「ファイル」メニュー:開く…、新規作成、最近使ったブックが表示されます。アプリに独自の一覧がある場合は、
fileMenu={false}を指定してこれらの項目を非表示にできます。 -
バージョン履歴:以前のバージョンを復元したり、ダウンロードしたりできます。復元によって置き換えられる状態も、バージョンとして保存されます。
-
.xlsx形式でダウンロード:保存とは別のボタンです。 -
エージェントが
sheet.aiを通じて操作するときの「AIによる変更」パネル:各変更について、実行内容(「D2:空欄 → =C2/B2-1」)と変更箇所が表示され、「承認」ボタンと「却下」ボタンが表示されます。変更をクリックすると、そのセルが表示されます。- アプリに独自のレビューUIがある場合は、
reviewPanel={false}を指定してパネルを無効にできます。
- アプリに独自のレビューUIがある場合は、
-
ファイルを開けない場合は、グリッドの代わりに平易な説明を表示します。たとえば、「旧形式の.xlsブック、またはパスワードで保護された.xlsx」などです。
-
Excelに保存された値を表示している数式の数がツールバーに表示され、該当する数式の一覧も確認できます。
-
データが失われる前に確認:保存できない変更がある状態で別のブックを開こうとすると、「未保存の変更を破棄しますか?」と確認されます。
ブックとドキュメント
スプレッドシートには、一度に1つのブックが表示されます。ブックはdocumentIdで識別し、既定値はfileNameです。ストアと組み合わせることで、このIDに基づいてブックが読み込まれます。
<Spreadsheet store={store} documentId={book.id} fileName={book.name} />
スプレッドシートには、そのIDに保存されている状態が表示されます。fileも渡す場合、保存済みの状態が優先されるのは、同じファイルから保存された場合のみです。それ以外の場合はfileが開きます。保存済みの状態がなく、fileもない場合、ブックは空の状態で始まります。
ブックの切り替えには、次の2つの方法があります。
- ドキュメントごとに再マウントする。
key={book.id}をコンポーネントに指定します。Next.jsの例では、ブックごとにページを用意しています。 - 同じスプレッドシートで
open()またはopenStored()を呼び出す。 どちらも同じルールに従います。
| 別のブックを開くとき… | |
|---|---|
| AIによる変更がレビュー待ち | PendingChangesErrorで拒否されます。先に変更を承認または却下してください。 |
未保存の編集があり、ストアまたはonSaveが設定されている | 先に保存されます。 |
| 保存に失敗するか、保存先が設定されていない | UnsavedChangesErrorで拒否されます。{ discardUnsaved: true }を渡すと、編集内容を破棄できます。リモートストアへの保存に失敗しても、ここでは失敗として扱われません。編集内容はこのブラウザーに保持されます。 |
| 新しいファイルを開けない | unsupported-fileまたはmalformed-fileで拒否され、前のブックは開いたままです。明らかに不正なファイル(空のファイル、旧形式の.xls、PDF、画像)は、何も変更される前に拒否されます。 |
「ファイル」メニューも同じルールに従い、何かを破棄する前にユーザーへ確認します。
後処理。
- コンポーネントをアンマウントするか、
destroy()を呼び出します(createSpreadsheetのみ)。まだ保存されていない編集内容がある場合は、先に保存されます。これにより、beforeunloadが発生しないクライアント側のページ遷移にも対応できます。その後、エンジンのワーカーが停止します。それ以降、古いsheetオブジェクトに対するすべての呼び出しはnot-readyで失敗します。 - 編集が未保存のままページを閉じると、ブラウザーの「サイトを離れますか?」という警告が表示されます。
CSV とテキストファイル
file、open()、および「ファイル」メニューでは、CSV やその他の区切りテキストも開けます。
新しいワークブックとして開かれ、.xlsx として保存されます。たとえば、sales.csv は sales.xlsx になり、sales という名前のシートが 1 つ作成され、ツールバーにもそのように表示されます。
- 区切り文字:カンマ、タブ、セミコロン、パイプのいずれかが使われます。先頭の数行で一致する区切り文字が選ばれます。Excel の
sep=;という先頭行にも対応しています。セミコロン区切りのファイルでは、カンマが小数点として扱われます(1.234,5は 1234.5 です)。 - エンコーディング:UTF-8(バイトオーダーマークの有無を問わず)、バイトオーダーマーク付き UTF-16(Excel の「Unicode テキスト」)、それ以外は Windows-1252 です。
- 値は、セルに直接入力された場合と同様に読み込まれます。数値、通貨、パーセンテージ、ISO 形式および米国形式の日付、
TRUE/FALSE、計算される=数式に対応しています。解析できない数式はテキストのままになります。 - Excel では失われる可能性のある値はテキストとして保持されます:先頭にゼロが付いた数字(郵便番号や ID)と、15 桁を超える数字の文字列(カード番号や口座番号)。
- 列幅はテキストに合わせて最大 60 文字まで広げられます。
テーブルではないテキスト(.json、.xml、.html、.md など)は、unsupported-file として拒否されます。17 MB の CSV(200 万セル)は、最近の Mac の Chromium で 7〜10 秒で開きます。
保存
保存は次の 3 つの方法で行われます。
- 自動保存:編集が止まってから 2 秒後に保存されます。
autosave(ミリ秒単位)で遅延を変更するか、falseにして無効にできます。 - ⌘S と保存ボタン。
- コードから
sheet.saveNow()を呼び出します。
保存のたびに、ワークブックが store に書き込まれ、onSave が呼び出されます。onStatusChange または getStatus() で状態を確認できます。
state | ツールバーの表示 | |
|---|---|---|
"saved" | 「このブラウザーに保存しました」/「アカウントに保存しました」 | savedAt と、where(store の label)。 |
"unsaved" | 「未保存の変更」 | 自動保存が予定されています。 |
"saving" | 「保存中…」 | |
"review" | 「保存する AI の変更を 2 件確認」 | pending。AI による変更をユーザーが承認または拒否するまで、保存は待機します。 |
"error" | 「保存できませんでした · 再試行」または「このブラウザーにのみ保存しました · 再試行」 | code、message、hint。このブラウザーで編集内容を安全に保持できる場合は keptLocally が設定され、自動保存の再試行時刻には retryAt が設定されます。 |
"idle" | (表示なし) | 新しいワークブック、または保存が設定されていません。 |
save() と saveBlob() は、独自のアップロードに使えるバイト列を返します。store にはアクセスしません。
バックエンドへの保存
デフォルトでは、browserStore() によってすべてがユーザーのブラウザー(IndexedDB)に保存されます。5 分以内に行われた保存は、同じバージョンにまとめられます。最新の 20 バージョンはそのまま保持され、その後は 30 日間、1 日につき 1 バージョンが保持されます。browserStore({ checkpointMinutes, keepRecent, keepDays }) で調整できます。
サインイン中のユーザーのアカウントに保存するには、httpStore を API に指定します。
import { httpStore } from "gridpath";
const store = httpStore({
url: "/api/books",
// Called before every request, so a refreshed token is picked up. Leave it
// out with cookie sessions.
headers: async () => ({ Authorization: `Bearer ${await getToken()}` }),
});
<Spreadsheet store={store} documentId={book.id} />;
以下は、すべて url を基準とする相対パスで呼び出されるルートです。ID は URL エンコードされます。
| リクエスト | レスポンス |
|---|---|
PUT /{id}?name=…&source=…[&checkpoint=1] を実行し、本文として .xlsx を送信 | 任意の 2xx。source は、ワークブックを開いた元のファイルを識別します。checkpoint は、復元の前後にそれぞれ独自のバージョンを作成するよう要求します。 |
GET /{id} | ヘッダー X-Workbook-Name(パーセントエンコード済み)、X-Workbook-Saved-At(ISO 形式の時刻)、X-Workbook-Source を含む .xlsx。該当するものがない場合は 404。 |
GET / | [{ id, name, savedAt, size }]。新しい順(最近使った項目の一覧)。 |
GET /{id}/versions | [{ id, savedAt, size }]。新しい順。履歴を保持していない場合は 404。 |
GET /{id}/versions/{versionId} | そのバージョンの .xlsx。 |
DELETE /{id} | 任意の 2xx。 |
バックエンドに接続できない場合や、エラーが返された場合でも、ユーザーの編集内容は失われません。
- ステータスには「このブラウザーにのみ保存済み · 再試行」と表示され、
keptLocally: trueになります。 - 自動保存は 2、5、15、30 秒後に再試行され、その後は 1 分ごとに再試行されます。
- 編集内容のコピーはこのブラウザーに保管されます。
- その前にページを閉じた場合、次回はコピーが再び開かれ、バックエンドの内容より新しい状態として保存されます。ステータスには「アカウントに保存されなかった変更を復元しました」と表示されます。
ワークブックを開くときにバックエンドに接続できない場合は、スプレッドシートにエラーと「再試行」が表示されます。自動保存によってユーザーの保存済みデータが上書きされるような、空のワークブックは開きません。
ほかの仕組みもストアとして使用できます。httpStore はこのインターフェースの実装の 1 つです。
interface WorkbookStore {
label?: string; // the status line's "Saved …" wording: "to your account"
local?: boolean; // true when it is in this browser (no extra drafts kept)
save(w: { id: string; name: string; bytes: Uint8Array; source?: string; checkpoint?: boolean }): Promise<void>;
load(id: string): Promise<{ id; name; bytes; savedAt: string; source?: string } | null>;
list(): Promise<Array<{ id; name; savedAt: string; size: number }>>;
versions(id: string): Promise<Array<{ id: string; savedAt: string; size: number }>>;
loadVersion(id: string, versionId: string): Promise<Uint8Array | null>;
remove?(id: string): Promise<void>;
}
よりシンプルな方法が 2 つあります。
onSave:保存のたびにバイトデータを受け取り、自分でアップロードします。拒否された Promise は保存失敗として扱われ、再試行されます。store={false}:保存しません。ユーザーは「ダウンロード」を引き続き使用でき、コードではsave()を引き続き使用できます。
エラー
スプレッドシートが報告する内容はすべて GridPathError です。それぞれに次の情報が含まれます。
code。コードで処理するためのものです。message。何が起きたかを示します。hint。何をすべきかを示す、表示可能な文です。
エラーは次の4つの方法で通知されます。
- メソッドがエラーを返します。 たとえば、
open()、openStored()、save()、getCell()です。 onErrorは、エンジンのエラーと、開けなかったワークブックを通知します。対象は最初のワークブック、または「ファイル」メニューから開いたワークブックです。onStatusChangeは、保存に失敗すると{ state: "error", code, message, hint }を通知します。自動保存で再試行されるため、保存の失敗はonErrorには通知されません。- スプレッドシート自体 がグリッドの代わりに問題を表示するため、ユーザーに空のボックスだけが表示されることはありません。
try {
await sheet.open(bytes, { name: file.name });
} catch (e) {
if (!(e instanceof GridPathError)) throw e;
if (e.code === "unsaved-changes" && confirm(`${e.message}. Discard them?`)) await sheet.open(bytes, { name: file.name, discardUnsaved: true });
else showToast(`${e.message}. ${e.hint}`);
}
code | 発生する状況 | 対処方法 |
|---|---|---|
unsupported-file | スプレッドシートではありません。空のファイル、旧形式の .xls、パスワードで保護されたワークブック、PDF、画像、JSON ファイルなどです。 | .xlsx または CSV を用意するよう依頼します(入手方法はヒントに記載されています)。 |
malformed-file | エンジンが読み込めない .xlsx(破損または途中で切り詰められている)、または表として読み込めない CSV です。 | Excel で開いて保存し直します。 |
engine-failed | エンジンのワーカーまたは .wasm の読み込みに失敗したか、エンジンが後から停止しました。停止した場合は、計算が停止したことを示すバナーが表示され、「ダウンロード」が提示されます。 | パッケージの engine.worker.js と .wasm を配信します(バンドラーを参照)。ページを再読み込みします。 |
storage-failed | ストアに失敗しました。httpStore を使用している場合、エラーの cause はレスポンスの status を含む HttpStoreError です。データの代わりにウェブページを返す URL の場合は、その旨が表示されます。 | 401/403 の場合は、ユーザーに再度サインインしてもらいます。それ以外の場合は、自動保存で再試行されます。 |
save-failed | セッションの変更をファイルに書き込めませんでした。 | 編集内容は画面に残っています。最後の変更を元に戻して、もう一度保存します。 |
calculation-timeout | getCell()(30 秒後)、whenCalculated(ms)、または save()(60 秒後)が、まだ実行中の再計算を待っていました。 | 計算が完了したら、もう一度試します。 |
pending-changes | AI による変更のレビュー待ちの状態で save() または open() を呼び出しました(pending を含む PendingChangesError)。 | 変更を承認または拒否する(sheet.ai.accept() / reject())、または save({ includePending: true }) を実行します。 |
unsaved-changes | 保存できなかった編集内容が失われるため、open() を実行できませんでした(UnsavedChangesError)。 | ユーザーに確認してから、{ discardUnsaved: true } を指定して再試行します。 |
not-found | openStored(id) で何も見つかりませんでした。 | |
not-ready | onReady の前、別のワークブックを開いている間、またはアンマウント後にメソッドが呼び出されました。 | onReady(または open() の Promise)を待ちます。 |
GridPath が計算できない数式
GridPath では計算できない数式があります。
- Excel アドインの関数(
_xll.…)。 - GridPath がまだサポートしていない関数。
- 別のワークブックへのリンク。
これらのセルでは、ファイルに Excel が保存した値が保持され、その値を参照する数式はその値を使って計算されます。ユーザーにはツールバーに件数が表示され、各セルの説明を一覧で確認できます。コードでも同じ情報を取得できます。
await sheet.getCell("Model", "C7");
// { value: 1250, formula: "=_xll.FDS(…)", fromFile: true,
// note: "Showing Excel's saved value because GridPath couldn't calculate this formula: it calls FDS, an Excel add-in function." }
await sheet.getCalcIssues(); // [{ sheet, ref, row, col, formula, value, calculated, note }]
オプション
| オプション | |
|---|---|
file | .xlsx のバイトデータ(ArrayBuffer または Uint8Array)です。指定しない場合、ワークブックは空の状態で開始するか、保存済みのものを再度開きます。コンポーネントのマウント時に読み込まれます。他のワークブックを開くには、open() を使用します。 |
sheets | 空のワークブックのシート名です(デフォルトは ["Sheet1"])。 |
fileName | ダウンロードおよび「最近使ったファイル」リストに表示される、ワークブックのファイル名です(デフォルトは "Untitled.xlsx")。 |
documentId | 保存済みワークブックの識別子です(デフォルトは fileName)。ワークブックとドキュメントを参照してください。 |
store | 保存データ、最近使ったワークブック、バージョンの保存先です。デフォルトは browserStore() です。httpStore({ url, headers })、独自の WorkbookStore、または false を指定できます。 |
autosave | true(デフォルト。編集が止まってから 2 秒後に保存)、ミリ秒単位の遅延時間、または false です。 |
onSave | ({ id, name, bytes }) => …。保存のたびに呼び出されます。拒否されたプロミスは保存失敗として扱われます。 |
onStatusChange | 保存ステータスが変わったときに呼び出されます。 |
onReady | (sheet) => …。最初のワークブックが開いたときに一度だけ呼び出されます(React の場合。createSpreadsheet は代わりに解決されます)。 |
onError | (error: GridPathError) => …。エンジンのエラーや、開けなかったワークブックに対して呼び出されます。 |
onDocumentChange | ({ id, name }) => …。ファイルメニュー、「最近使ったファイル」、復元、open()、openStored() から別のワークブックを開いたときに呼び出されます。 |
onEdit | グリッドでユーザーが編集するたびに呼び出されます。 |
onProgress | 読み込みインジケーター用の読み込みステージ(「ワークブックを読み込み中…」「グリッドを構築中…」)です。 |
toolbar | false にすると、ツールバーを非表示にします。 |
fileMenu | false にすると、ファイルメニューから「開く」「新規」「最近使ったファイル」を削除します。 |
reviewPanel | false にすると、「AI の変更」パネルを無効にします。sheet.ai.list()、accept()、reject() を使って独自のパネルを作成できます。 |
engine.worker | false にすると、Web Worker ではなくページ上でエンジンを実行します。 |
engine.workerUrl、engine.wasmUrl | バンドラーがパッケージの隣に配置されたファイルを配信しない場合に、ワーカースクリプトと .wasm の読み込み元を指定します。 |
メソッド
| メソッド | 契約 |
|---|---|
getSheetNames() | シート名を順番に返します。 |
getCell(sheet, "A1") | { value, display?, formula, fromFile?, note? } を返します。空のセルの場合は null を返します。保留中の書き込みが再計算されるまで待機します(最大30秒。超過すると calculation-timeout で拒否されます)。 |
getCalcIssues(limit?) | Excelに保存された値が表示されている数式(上記を参照)を返します。 |
setCell(sheet, "A1", value) | すぐに返ります。書き込みはキューに追加され、順番に再計算されるため、実行後に getCell を呼び出すと結果を取得できます。= で始まる文字列は数式として扱われます。 |
setCells(sheet, [{ row, col, value }]) | 複数のセルを1回で設定します(インデックスは0始まり)。 |
whenCalculated(ms = 30000) | 保留中の書き込みが再計算されると解決します。ms を超えると calculation-timeout で拒否されます。 |
select(sheet, "A1")、focus() | 選択範囲を移動し、グリッドにキーボードフォーカスを設定します。 |
undo()、redo() | ユーザーまたはエージェントによる直前の変更を元に戻す、またはやり直します。 |
save(options?)、saveBlob(options?) | ワークブックを .xlsx のバイト列(またはBlob)として返し、ストアは変更しません。再計算が完了するまで待機します(最大60秒)。AIによる変更の確認が保留中の場合、{ includePending: true } を渡さないと PendingChangesError で拒否されます。 |
saveNow() | 自動保存や ⌘S と同様に、今すぐストアに保存して onSave を呼び出します。新しいステータスで解決し、拒否されることはありません。失敗した場合は { state: "error", … } になります。 |
hasUnsavedChanges() | AIによる確認待ちの変更も含め、ストアにまだ反映されていない編集がある場合は true を返します。ページ遷移時の確認に便利です。 |
download(fileName?) | .xlsx をダウンロードします。 |
getStatus()、getDocument() | 保存ステータスと、開いているワークブックの { id, name } を返します。 |
open(bytes, { name?, id?, discardUnsaved? }) | これらのルールに従って、別のワークブックをここで開きます。開くと解決します。 |
openStored(id, { discardUnsaved? }) | IDを指定してストアからワークブックを開きます。該当するものがない場合は not-found で拒否されます。同じルールが適用されます。 |
destroy() | 未保存の内容を保存し、マウントを解除して、エンジンを停止します(createSpreadsheet のみ。Reactではコンポーネントをアンマウントしてください)。 |
ai | エージェントツールです。以下を参照してください。 |
AI:使用独立的模型和密钥
sheet.ai は GridPath のエージェントツール一式です(ツールと結果の形式は MCP サーバーと同じです)。ユーザーが表示しているグリッド上で動作します。ツールをモデルに渡し、ツール呼び出しを sheet.ai.run() で実行したら、ユーザーに確認してもらいます。すべての書き込みは即座に反映され、保留中のバッチとしてハイライト表示されるため、ユーザーは「AI changes」パネル(または独自の UI)で承認または拒否できます。
GridPath がキーを参照することはありません。モデルの呼び出しはサーバー上で行われ、ツール呼び出しはワークブックがあるブラウザー内で実行されます。
サーバー(任意の Node ルート。この例ではデモの server/agent.ts)。システムプロンプトとツールはここで固定されています。リクエストから受け取るようにすると、このルートがキーを使う汎用プロキシになってしまいます。独自の認証とレート制限を追加してください。
import Anthropic from "@anthropic-ai/sdk";
import { AGENT_INSTRUCTIONS, agentTools } from "gridpath/agent";
const client = new Anthropic(); // ANTHROPIC_API_KEY
const tools = agentTools() as Anthropic.Beta.BetaTool[];
export async function agentTurn(messages: Anthropic.Beta.BetaMessageParam[]) {
const response = await client.beta.messages.create({
model: "claude-opus-5-5",
max_tokens: 16000,
output_config: { effort: "high" },
system: AGENT_INSTRUCTIONS,
tools,
cache_control: { type: "ephemeral" }, // system + tools are identical every call
betas: ["server-side-fallback-2026-07-01"],
fallbacks: "default", // a declined request re-runs on a fallback model
messages,
});
return { content: response.content, stop_reason: response.stop_reason };
}
ブラウザー(デモの src/agentLoop.ts。短縮版):
const messages = [{ role: "user", content: [
{ type: "text", text: `The open workbook:\n${await sheet.ai.context()}` },
{ type: "text", text: prompt },
] }];
for (;;) {
const out = await (await fetch("/api/agent", { method: "POST", body: JSON.stringify({ messages }) })).json();
messages.push({ role: "assistant", content: out.content }); // unchanged, thinking blocks included
const calls = out.content.filter((b) => b.type === "tool_use");
if (out.stop_reason !== "tool_use" || calls.length === 0) break;
const results = [];
for (const c of calls) {
const r = await sheet.ai.run(c.name, c.input);
results.push({ type: "tool_result", tool_use_id: c.id, content: JSON.stringify(r), ...(r?.ok === false ? { is_error: true } : {}) });
}
messages.push({ role: "user", content: results }); // all results in one message
}
すでにエージェントフレームワークを使用している場合は、sheet.ai.tools()(Anthropic 形式)または sheet.ai.tools("openai") を使用し、ツール呼び出しを sheet.ai.run() に渡してください。
sheet.ai | |
|---|---|
tools(format?) | ツール定義:「"anthropic"」(デフォルト)または「"openai"」。gridpath/agent から agentTools() としてもエクスポートされています。 |
instructions() | システムプロンプト用の使用方法(AGENT_INSTRUCTIONS)。 |
context() | 最初のターンで使用するワークブックの概要。 |
run(name, input) | 1 つのツール呼び出しを実行し、モデル用の JSON を返します。例外はスローされません。 |
list(), onChange(fn) | 保留中または承認済みのバッチ。 |
accept(id?) | 1 つのバッチ、または保留中のすべてのバッチを保持します。 |
reject(id?) | バッチと、それ以降のすべてのバッチを新しいものから順に元に戻します。これにより、後続のバッチで移動した行や列の位置が保たれます。元に戻した ID を返します。 |
含まれるもの:describe_workbook、find_rows、query_rows、read_range、set_cell、set_range、copy_range、set_format、clear_range、run_script(ワーカー内でサンドボックス化)、行/列/シートの構造、固定、非表示、結合、メモ、サイズ、名前の定義。含まれないもの:デスクトップアプリやネットワークが必要なツール(fetch_web、edgar_lookup、参照ワークブック)。
保留中の変更がある間、save() は保存を拒否します。ユーザーが承認または拒否するまで、pending 件数を含む PendingChangesError をスローするため、未確認の内容が誤ってファイルに反映されることはありません。save({ includePending: true }) を使うと、保留中の変更も保存されます。
保存の仕組み
保存するたびに、セッションの変更(セル、書式、サイズ、行と列、シート、フィルター)が、ワークブックを開いたときのバイトデータに再適用されます。セッションで変更していない部分は、そのままコピーされます。数式には計算結果も保存されます。新しい数式と、セッションの編集によって再計算された数式はすべて、現在の計算結果をキャッシュ値として保存されます(数式のテキストはそのままです)。そのため、計算を行わないリーダー(pandas、data_only=True を指定した openpyxl、ファイルのプレビュー)でも最新の数値を確認できます。セッションの影響を受けなかった数式は、Excel が保存した値を保持します。また、ファイルには次回のオープン時に再計算するようマークが付けられ、Excel はこれに従います。
チャート
ブラウザーでは、インポートした標準的な折れ線グラフがワークシート上のアンカー位置に表示されます。描画には、別途読み込まれる Apache ECharts の SVG レンダラーを使用します。ソース値は計算エンジンから取得され、ビューポート外のセルも含まれます。編集や取り消しを行うと、再計算後にグラフが更新されます。await sheet.getCharts() は、表示用の記述子と現在の値を返します。sheet.getLastEditTimings() は、直近の編集における計算、シリアライズ、転送/適用の所要時間を報告します。
この初期バージョンでは、系列ごとに最大10,000ポイントまでのワークシートへの直接的な1次元参照、基本的なタイトルと凡例、RGBの線色、数値軸をサポートします。Excelの視覚的なスタイルを近似します。その他のグラフの種類、名前付き/外部データ参照、積み上げ線/平滑化線、日付/対数/第2軸、グラフの作成や編集用のコントロールはサポートされていません。サポート対象外のグラフはプレースホルダーを表示し、保存時にはネイティブ定義を保持します。
ブラウザーおよびヘッドレスでの保存時には、保存されたワークシートの値を使って、影響を受ける直接参照の数値/文字列グラフキャッシュが更新されます。ソース参照、スタイル、無関係なグラフ XML はそのまま保持されます。サポート対象外の参照では元のキャッシュが保持されます。Excelの再計算フラグは設定されたままです。
埋め込み可能な他のスプレッドシートとの比較
Webアプリに埋め込む他のスプレッドシートコンポーネントと、Chromiumで実際のモデルを使って比較した結果です(ワークブック、手法、全結果)。
| GridPath | SpreadJS 19.2 | Handsontable 18.1 + HyperFormula 3.5 + ExcelJS 4.4 | |
|---|---|---|---|
| 1.4 MB のアナリストモデル:開く、完全に再計算する | 0.6 s、0.8 s | 1.5 s、3.6 s | 1.9 s |
| … Excelの結果と一致 | 95.5% | 94.0% | 56.9% |
| … 保存時に失われたもの | なし(76個中75個のパーツがバイト単位で同一) | カスタム XML、プリンター設定 | カスタム XML、プリンター設定、コメント、3,418個中3,335個の名前 |
| 10 MB超のデータ集約型モデル(230万セル):開く、完全に再計算する | 4.2 s、10.9 s | タブがクラッシュ(遅延モード:6.5 s、3.7 min) | 10.8 min |
| … 編集 → 依存先の更新 | 2.7 s | —(遅延モードでは最初の編集時にクラッシュ) | 64 s |
バンドラー
このパッケージは new URL("…", import.meta.url) を使ってワーカーとエンジンを読み込みます。Next.js、Vite、webpack 5、Rollup では自動的にバンドルされます。
-
Next.js:設定不要です(Next.jsを参照)。
-
Vite:本番ビルドはそのまま動作します。開発サーバーでは、依存関係の事前バンドルからパッケージを除外してください。
// vite.config.ts export default defineConfig({ optimizeDeps: { exclude: ["gridpath"] } }); -
webpack 5(Next.js以外):設定不要です。
new URLを使うワーカーとアセットはビルドに含まれます。 -
その他:
engine.worker.js、そのチャンク、およびgridpath_engine_bg.wasmをdist/から静的ファイルにコピーし、engine: { workerUrl, wasmUrl }を渡してください。
ブラウザーでのサイズは、JavaScript が約 120 KB、エンジンが 1.3 MB です。gzip 圧縮時のサイズは合計で約 120 KB、brotli 圧縮時は 0.9 MB です。エンジンは一度だけダウンロードされ、ブラウザーにキャッシュされます。
ソースからビルド
crates/engine-wasm/build.sh # needs rustup target wasm32-unknown-unknown and wasm-bindgen-cli
cd packages/gridpath && npm install && npm pack
examples/embed-demo では、アプリと同じ方法でパック済みの tarball をインストールします。
コーディングエージェント内(MCP)
エージェントに Excel ファイルを編集させましょう。保存する前に確認できます。
Claude Code、Claude Desktop、Cursor、Codex、その他の MCP ホスト向けの MCP サーバーです。すでにお持ちの .xlsx / .xlsm ファイルを編集し、確認ステップを設けます。
- 保存前に確認できます。 書き込みのたびに
review_urlが返されます。これは、ワークブックと変更されたセルのハイライト、セルごとの変更前/変更後、バッチ単位またはセル単位での承認/拒否、保存または別名で保存(コピー)ができるローカルページです。--review-requiredを指定すると、そのページからのみファイルに書き込めます。エージェントはリンクを渡すだけです。 - Excel ファイルはそのまま保持されます。 ライブラリを介した再エクスポートや、別形式への変換はありません。保存時には元のバイト列にパッチを適用し、編集された部分のみを書き換えます。ピボット、VBA マクロ、アドインデータ、カスタム XML など、変更していない部分はバイト単位で同一のまま保持されます。参照されているグラフのキャッシュは、再計算されたワークシートの値に合わせて更新されます。
- プロセス内で実際の数式を計算します。 計算エンジン(IronCalc のフォークを WebAssembly にコンパイルしたもの)がサーバー内で動作します。エージェントは評価済みの値を読み取り、ファイルを Excel で開いたときに機能する数式を書き込めます。行や列を挿入・削除すると、参照も移動します。
- Node が動作する環境ならどこでも実行できます。 Python、openpyxl、LibreOffice、Excel のインストールは不要です。macOS、Windows、Linux に対応しています。
- スクリプトはサンドボックス内で実行されます。
run_scriptは、エージェントの JavaScript を厳格なタイムアウトを設定したワーカー内でワークブックに対して実行し、その結果を確認可能な 1 つのバッチとして適用します。

インストール
Claude Desktop(ターミナル不要)
gridpath-0.5.1.mcpb
をダウンロードして開きます。Claude Desktop にインストールダイアログが表示され、Claude が編集できるフォルダーと、保存に確認を必須とするかどうかを選択できます。Node は同梱されているため、ほかにインストールするものはありません。ファイルからインストールした拡張機能については、Claude Desktop に標準の「未確認」という警告が表示されます。ソースは公開されています。確認ページで承認して保存するまで、何も書き込まれません。
Claude Code
claude mcp add gridpath -- npx -y gridpath mcp --review-required
Cursor
Cursor に追加
(ワンクリック)、または mcp.json に追加します。
{ "mcpServers": { "gridpath": { "command": "npx", "args": ["-y", "gridpath", "mcp", "--review-required"] } } }
Codex(~/.codex/config.toml)
[mcp_servers.gridpath]
command = "npx"
args = ["-y", "gridpath", "mcp", "--review-required"]
Gemini CLI、Windsurf、VS Code、その他
そのホストの MCP 設定で、Cursor の JSON と同じ command/args を使用します。サーバーは stdio で通信します。
オプション
| フラグ | 説明 |
|---|---|
--allow <dir> [<dir>...] | サーバーがアクセスできるフォルダーを指定します。デフォルトはホームディレクトリです。 |
--review-required | エージェントは保存できません。save_workbook は確認リンクを返し、そこで承認して保存します。GRIDPATH_REVIEW_REQUIRED=true も使用できます。 |
--port <n> | ローカル確認サーバーのポート(デフォルト:ランダム)。 |
gridpath review <file> | ワークブックに保留中のバッチがある場合、後から確認ページを再度開きます。 |
保留中の変更は保存または拒否されるまで、ワークブックと同じ場所の(.gridpath/<file>.batches.json)に保存されるため、エージェントのセッションが終了しても失われません。
ツール
すべてのツールで path が必要です。セルと範囲は A1 形式で指定します。
| ツール | 機能 |
|---|---|
describe_workbook (sheet?) | 構造マップを表示します。シート、使用範囲、ヘッダー行、セクション、名前付き範囲を確認できます。最初に呼び出してください。 |
find_rows (query, sheet?, max_results?) | シート全体からラベルに一致する行を検索し、評価済みのサンプルを表示します。 |
read_range (sheet, range) | 範囲(≤ 500 セル)の評価済みの値、数式、表示テキストを取得します。 |
set_cell (sheet, cell, value | formula) | 1 つのセルに書き込みます。 |
set_range (sheet, top_left, values[][]) | ブロックに書き込みます。= で始まる文字列は数式として扱われます。 |
copy_range (sheet, source, dest_sheet, dest, mode) | 参照をずらしながら Excel 形式でコピーします。all / values / formats を指定できます。 |
run_script (script) | サンドボックス内の JS を実行します。sheet(name).get/set/values/setValues/format/clear を使用でき、1 回のバッチで処理します。 |
set_format (sheet, range | operations[], format) | 数値形式、太字/斜体、色、配置、折り返しを設定します。 |
clear_range (sheet, range) | 書式を保持したまま、値と数式を消去します。 |
insert_rows / delete_rows / insert_columns / delete_columns | 行や列を構造的に編集します。参照、CF、入力規則の範囲も追従します。 |
create_sheet / rename_sheet / delete_sheet | シートを操作します。 |
set_column_width / set_row_height / freeze_panes / unfreeze_panes / hide_rows / show_rows / hide_columns / show_columns | レイアウトを設定します。 |
merge_cells / unmerge_cells / set_note / delete_note / define_name | セルの結合、メモ、名前付き範囲を操作します。 |
list_batches | 保留中のバッチとレビューリンクを表示します。 |
reject_batch (batch_id) | 保留中のバッチを破棄します。残りは新しいモデルに再適用されます。 |
save_workbook (as?) | 保留中の変更をファイルに反映します。または as を指定すると、元のファイルを変更せず、変更を反映したコピーを書き出します。書き込みを行う唯一のツールです。インプレース保存は --review-required によって制限されています。 |
書き込みによってファイルが変更されることはありません。変更は保留中のバッチとして蓄積され、書き込みのたびに、反映された内容(値、数式、ラベルの row_map)と review_url が返されます。
エージェントの評価
Cursor で GridPath を使って 1,400 行のセルサイドモデル(2,500 個以上の名前付き範囲、非表示シートあり)を編集した Claude は、組み込みの方法と比べてどうだったかを尋ねられ、次のように答えました。
リアルタイムで再計算されます。 58 行目を変更すると、新しい成長率(28.0%、28.0%、27.9%)をすぐに読み戻し、変更が機能したことを確認できました。普段使っている openpyxl という Python ライブラリでは、数式は計算されません。値を取得するにはファイルを LibreOffice で処理する必要があり、関数によっては Excel と異なる結果になることがあります。
すばやく検索できます。 数回の呼び出しで、行検索とワークブックマップを使って「Product revenue」と「Assumptions」の構造を見つけられました。そうでなければ、1,400 行のシートをセルごとに確認する必要があったでしょう。
ファイルの他の部分はそのまま保持されます。 変更したセルだけを書き換えます。openpyxl でこのような大規模なモデルを開いて保存し直すと、グラフ、データの入力規則、ピボットキャッシュ、一部の書式設定が気づかないうちに削除されたり破損したりすることがあります。これは、私が組み込みの方法を使う場合の最大のリスクです。
比較
| gridpath | ファイルライブラリ型 MCP(openpyxl など) | ライブ Excel 型 MCP(COM) | ブラウザベースのスプレッドシート SDK | |
|---|---|---|---|---|
| 既存のファイルを編集 | はい、パッチを適用してインプレースで編集 | ファイル全体を書き換え | はい、Excel 経由で編集 | 独自の形式に変換 |
| 数式を評価 | はい、プロセス内で評価 | いいえ | はい、Excel を開いておく必要あり | はい、ホストされたアプリで評価 |
| 書き込み前のレビュー | はい | いいえ | いいえ | ベンダーの UI で実施 |
| インストールが必要 | Node | Python | Windows + Excel | Web アプリ + アカウント |
| マクロ、ピボット、アドインデータの保持 | バイト単位で同一 | 多くの場合、削除される | はい | 保証されない |
ベンチマークと方法論(通常のコーディングエージェントが当方と同等の結果を出す実行例を含む)は、gridpath-evals リポジトリにあります。
対応ファイル
.xlsx と .xlsm に対応しています。実際のアナリストのモデルで検証済みです。1.4 MB、12 シート、数式 55,000 個のワークブック(編集後も 76 個のパッケージパーツのうち 75 個がバイト単位で同一)と、vbaProject.bin がバイト単位で同一のまま戻された 13 シートの .xlsm 銀行モデルで確認しています。
仕組み
エンジンは .xlsx をプロセス内モデルに解析します。編集はモデルに反映され、評価済みの結果を読み取ります。再計算するのは編集の影響を受ける箇所だけです。保存時には、セッションでの変更を読み込み時のファイルと比較し、zip パーツ単位で元のバイト列にパッチを適用します。変更されていないパーツはそのままコピーされ、パッケージが再生成されることはありません。ブラウザーではエンジンが Web Worker で動作し、グリッドは表示中の範囲だけを描画するため、大規模なモデルでも軽快に動作します。
ヘッドレス(Node)
gridpath/headless はグリッドを除いたエンジンです。サーバーまたはスクリプトからワークブックを開き、同じツール呼び出しを適用し、結果を読み取って保存できます。
import { WorkbookSession } from "gridpath/headless";
ステータス
v0.5。以下はまだサポートされていません。
- グリッド: 折れ線グラフ以外のグラフの種類、グラフの作成や編集、データ検証のドロップダウン、リアルタイムの共同作業。
- エージェント:
fetch_webおよびedgar_lookupの情報取得ツール、グラフやピボットテーブルの編集。
GridPath は同じエンジンとレビュー機能を備え、独自のエージェントを内蔵したデスクトップアプリでもあります。
ライセンス
Apache-2.0(LICENSE、NOTICE)。パッケージに含まれるサードパーティソフトウェアは THIRD_PARTY_NOTICES.md に記載されています。0.2.0 より前のリリースには FSL-1.1-Apache-2.0 が適用されていました。「GridPath」は Heelix Technologies Inc. の商標です。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。