Math board について
Math board は、エージェントが段階的なビジュアル教材を作る、ローカルで閲覧専用のブラウザ黒板です。ターミナルで学習や指導を行う人向けで、数式やグラフから分子、図解まで扱えます。
主な機能
- 01数式と化学表記の描画
- 02関数グラフと媒介変数曲線の作成
- 03SMILES による分子表示
- 04オフライン Bioicons と Mermaid 図
- 05パンとズームに対応した段階的な教材
活用シーン
- 01導出やグラフを使った物理の説明
- 02分子構造と反応による化学の指導
- 03生物学や医学のトピックの可視化
- 04アルゴリズム、年表、論証マップの提示
MCP 対応
stdio MCP サーバーは pi 拡張と同じ教材作成ツールを公開し、黒板の操作や描画に対応します。MCP クライアントはローカルの黒板を開き、画像形式のスナップショットを受け取れます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
npx -y pi-math-boardMATH_BOARD_NO_BROWSERSet to 1 and board_open only returns the board's URL instead of opening it in the default browser.MATH_BOARD_DATA_DIRFolder for this board's autosave and named saves, used as given (PI_MATH_BOARD_DATA_DIR, the old name, also works). Default: the mcp/ subfolder of the board's data folder. A plain checkout keeps lessons in <package>/.data; an npm or npx install uses a per-user folder: ~/Library/Application Support/math-board on macOS, $XDG_STATE_HOME/math-board or ~/.local/state/math-board on Linux, %LOCALAPPDATA%\math-board on Windows.ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
math-board
ターミナルのチューターが説明しながら描き込む、ブラウザー上の黒板です。黒板の前に立つ教授のように描いていきます。会話はターミナル内で続きます。ボードは閲覧専用です。モデルがツールを使って、数式、グラフ、分子、図、科学のイラストを一度に一段階ずつ描き、私はそれを見たり、レッスンをさかのぼったり、パンやズームをしたりします。私がボードに描き込むことはありません。描くのはモデルです。(ページにある、動作を変えるボタンは2つだけです。確認後にボードを消去する「Clear」と「Save」です。)
私は物理学、MRI 物理学(k-space、スピン、信号)、神経科学、化学、生物学を医学のために学んでいます。pi(ターミナルのコーディングエージェント)を使い、Eero Alvar の learn セットアップに沿って、自分自身をチューターとして学んでいます。質問ベースで、一度に1つの概念を学ぶスタイルです。ターミナルのチューターには視覚的な伝達手段がなく、私が学ぶ内容のほとんどには図が必要なので、これを作りました。ローカルで無料です(クラウドも追加の API キーも不要です)。独立した拡張機能なので、Eero のツールは元のまま使えます。同じツールは MCP サーバーとしても動作するため、Claude Code も同じ種類のボードを使って教えられます。作成の前後に、既存のツールを約100個調べました(調査)。閲覧専用で、ローカルで、レッスン形式で、エージェント主導のものをすべて兼ね備えたツールはありませんでした。

pi にインストールする
pi と Node 22.19 以降が必要です。私は macOS で使っていますが、Linux でも動作します。Windows でもボードは動作しますが、ブラウザーは自動で開かないため、/board に表示される URL を自分で開いてください。
npm からインストールする場合(公開後):
pi install npm:pi-math-board
チェックアウトからインストールする場合(私はこの方法で実行しています):
git clone https://github.com/smdesai27/math-board ~/math-board
cd ~/math-board && npm ci
pi install ~/math-board
pi はローカルパッケージをコピーせず、その場で読み込むため、チェックアウトしたものが実行されます。ローカルパッケージの依存関係はインストールされないので、最初に npm ci を実行します。その後、pi で /reload を実行するか、再起動してください。
事前に知っておくとよい点が2つあります。
- 各更新後のレイアウトチェック、
board_snapshot、および/board exportが出力する PNG には、ヘッドレス Chromium が必要です。Playwright 版またはシステムの Chrome を使えます。Playwright 版の場合は、パッケージが想定するビルドをnpx -y [email protected] install chromiumでインストールしてください(エラーメッセージに正確なコマンドが表示されます)。どちらもない場合でもボードは動作し、それらが使えない理由が報告されます。Chromium は OS のサンドボックスを使って実行されます。サンドボックスを起動できない環境(一部の Linux コンテナーなど)ではサンドボックスなしで実行され、その旨が結果に表示されます。 - ボードの保存場所:チェックアウト版では、コードの隣にある
.data/に保存されます(git で無視されます)。npm または pi の git インストールによるインストール版は、更新時に置き換えられたり削除されたりするため、代わりにユーザーごとのフォルダーに保存されます。macOS では~/Library/Application Support/math-board、Linux では$XDG_STATE_HOME/math-board(通常は~/.local/state/math-board)、Windows では%LOCALAPPDATA%\math-boardです。MATH_BOARD_DATA_DIRを設定すると、どちらの保存場所も変更できます(旧名のPI_MATH_BOARD_DATA_DIRも引き続き使えます)。現在使用中のフォルダーは/board statusで確認できます。
pi で使う
チューターに「ボードで」何かを説明するよう頼んでください。または:
/board open the board in your browser (also /board open)
/board status server URL, revision, data folder, viewers, autosave problems
/board save <name> named snapshot (several words become one name: my lesson -> my-lesson)
/board load <name> restore it
/board export [name] write the lesson to ./viz/: board.json, PNGs, lesson.md
/board clear clear everything (or /board clear equations|scene)
/board stop stop the server
サーバーは初回使用時に起動し、127.0.0.1 のみで接続を待ち受けます。URL には非公開の #token=… が含まれています。共有しないでください。/reload または /board stop の後、同じ pi セッションで次のボードを起動すると、ポートとトークンが再利用されるため、開いたままのタブは自動的に再接続します。サーバーが完全に停止した場合、約10秒後にページにその旨が表示され、バックグラウンドで再接続を試み続けます。
Claude Code やその他の MCP クライアントで使用する
同じツールが stdio MCP サーバー mcp/server.mjs として動作します。pi 拡張機能(index.ts)と MCP サーバーはどちらも、単一の実装 tools.mjs を薄くラップしたものです。そのため、どちらを使ってもモデルが受け取るツール名、説明、スキーマ、結果は同じであり、board_teaching のリズム(読む、1 ステップ描く、確認の質問を 1 つする)はサーバーの指示になっています。どのエージェントが教える場合でも、学習者のワークフローは 1 つです。
Claude Code に一度だけ登録します。
claude mcp add math-board -- npx -y pi-math-board # from npm, once published
claude mcp add math-board -- node ~/math-board/mcp/server.mjs # from a checkout, after npm ci
これは、実行したフォルダーに登録されます(スコープは local です)。私は学習用フォルダーで実行しているため、ボードとその指示は pi の board_teaching と同様に、そのフォルダー内だけに存在します。すべてのプロジェクトで使う場合は --scope user を追加してください。claude mcp list に ✔ Connected と表示されるはずです。また、コードを変更した後は、Claude Code 内で /mcp を実行すると再接続できます。pi では pi mcp add ではなく拡張機能を使ってください。両方を使うと、別々のボードが 2 つできてしまいます。
その他の MCP クライアントでは、同じコマンドを stdio サーバーとして指定します。
{
"mcpServers": {
"math-board": {
"command": "npx",
"args": ["-y", "pi-math-board"]
}
}
}
チェックアウトしたリポジトリでは、"command": "node" と "args": ["/absolute/path/to/math-board/mcp/server.mjs"] を使ってください。
- ツール:モデルツールにある 7 つです。MCP には pi のような遅延アクティベーションがないため、7 つすべてが最初から一覧に表示されます。モデルは
board_openを呼び出してボードを表示します。board_snapshotは、MCP の画像ブロックとして PNG を返し、その後にテキストの概要を返します。 - ブラウザー:ブラウザーにすでに表示されていない場合、
board_openはデフォルトのブラウザーでボードを開きます。トークン付きの URL がモデルのコンテキストに入るのは、ブラウザーを開けなかった場合だけです。その後、モデルが URL をあなたに渡します。MATH_BOARD_NO_BROWSER=1を指定すると、ブラウザーを開かず、常に URL を返します:claude mcp add math-board -e MATH_BOARD_NO_BROWSER=1 -- npx -y pi-math-board。 - ボードの分離:ツールは同じですが、ボードは別々です。MCP サーバーは独自のボードサーバーをホストします。このサーバーは、必要とする最初のツール呼び出し時に起動し、独自のトークンを使って
127.0.0.1で動作します。また、pi の保存データとは別に、データフォルダー内のmcp/サブフォルダーに保存します(pi 用のインストールを参照)。そのため、互いの自動保存データが上書きされることはありません。MATH_BOARD_DATA_DIRで保存先を変更できます。両方に設定する場合は、それぞれ別の保存先を指定してください。もう一方のエージェントでレッスンを続けるには、saves/<name>.jsonをコピーし、board_saveで読み込んでください。 - ライフサイクルとプライバシー:標準出力には JSON-RPC のみが出力され(診断情報は標準エラー出力に出力されます)、ループバック以外では待ち受けません。また、テレメトリーもありません。クライアントが切断されたとき、または SIGINT、SIGTERM、SIGHUP を受け取ったとき、サーバーは自動保存データを書き込み、ヘッドレスブラウザーを閉じて終了します。
/boardと/board exportは pi のコマンドです。MCP サーバーにはこれらに相当する機能はありません。
チューターが描けるもの
- 数学:KaTeX の数式(
\color、\boxed、\cancel、…)および\ce{…}を使った化学式(mhchem)。 - グラフ:関数グラフ、媒介変数表示の曲線、塗りつぶし領域、点、漸近線。式は小規模なパーサーを通して処理され、
evalは使われません。 - 分子:SMILES 文字列から作成する 2D 構造(SmilesDrawer)。
- 科学イラスト:オフラインで利用できる約 2000 点の Bioicons(解剖、臓器、細胞、細胞小器官、血液と免疫学、微生物、ウイルス、DNA、植物、動物、実験器具)。キーワードで検索できます。
- 図:手書きの SVG(マーカー、グラデーション、シンボル、CSS、SMIL アニメーション)および Mermaid(フローチャート、シーケンス図、クラス図、状態図、ER 図、ガントチャート、マインドマップ、グラフ。自動レイアウト)。
- 記号:線、矢印、曲線、長方形、楕円、テキスト(デフォルトでは LaTeX 風のセリフ体)。
数学だけではありません
名前には数学とありますが、ボードは何を教えているかを問いません。方程式、グラフ、分子、イラスト、図、テキストを表示し、ほとんどの教科ではそれらを組み合わせて使います。教科ごとの例を紹介します。
- 物理と数学:1行ずつ進める導出、関数グラフや媒介変数表示のグラフ、SVGによる物体の力の図やベクトル図。
- 化学:SMILESから作成する2D構造式、
\ce{…}による反応や平衡。 - 生物学と医学:オフラインライブラリの解剖図、器官や細胞のイラスト、フローチャートによる経路やメカニズム。
- コンピューターサイエンス:フローチャートによるアルゴリズム、状態機械、計算量グラフ、シーケンス図やクラス図。
- 歴史と人文科学:年表、原因と結果のマインドマップ、ボックスと矢印で作る論証マップ。
- 言語:Mermaidグラフによる構文木。
サンプルレッスンの5つの章から3つを紹介します(node scripts/demo-lessons.mjs <out-dir>ですべてレンダリングできます)。

化学:SMILESから描かれたサリチル酸からアスピリンへの変化と、\ce{…}で表した反応。

コンピューターサイエンス:フローチャートで表したバイナリーサーチと、バイナリーサーチを使う場合と使わない場合のn回の検索コスト。

歴史:長方形、テキスト、矢印で作成した論証マップ。
レッスンの構築方法
- 座標:各チャプターとホームボードは、原点を左上とする 1200×800 の領域です。テキストの
yはベースライン、数式のx,yはボックスの左上、rect、ellipse、artifact のx,yは左上の角を示します。 - チャプター:名前付きの 1200×800 の領域が、無制限のキャンバス上に左から右へ配置されます(
xのないチャプターは、最も右にあるチャプターの右側に配置されます。xまたはyのいずれかが指定されている場合、その値は維持されます)。chapter: idを持つアイテムはチャプター内の座標を使うため、チャプターを移動するとその内容も移動します。重なり合うチャプターは報告されます。チャプターを削除すると、keepItemsが指定されていない限り、そのアイテムも削除されます。 x,yのない数式は、各チャプターの左側に縦に並べられます(x は 88、間隔は 115 px)。位置は保存されるため、ほかの要素が変更されても移動しません。- カメラ:
camera: {chapter}(またはボードの rect、ホームを示すnull)を指定すると、なめらかなパンとズームで、以降のすべてのビューアーが講師の説明している場所へ移動します。 - ステップ:アイテムを追加する
board_updateは、それぞれ 1 つのレッスンステップになります。新しいステップはリアルタイムで描画されます。図は滑らかに表示され、ストロークは手書きのように描かれ、プロットは軸を描いてから曲線を描き、テキストと数式は左から右へ書かれます。アイテムにはstep、reveal(draw、write、wipe、fade、none)、duration、orderを設定できます。強調表示にも同じ仕組みを使います。たとえば、reveal: "draw"の ellipse で項を囲んだり、reveal: "wipe"の半透明の rect で項をハイライトしたりできます。 - レイヤー:
zであらゆる種類のアイテムの順序を指定します。また、opacity、dash、fill、テキストのfont(serif、sans、mono)、anchor、bold、italic、複数行のテキストも指定できます。
講師が scene.artifacts に書き込むアーティファクトは、次のようになります。
{ "type": "svg", "source": "<svg viewBox=…>…</svg>", "x": 40, "y": 90, "width": 680, "height": 520 }
{ "type": "mermaid", "source": "graph LR\n A[Input] --> B(Process) --> C[Output]", "x": 620, "y": 120, "width": 420, "height": 200 }
{ "type": "plot", "x": 40, "y": 40, "width": 560, "height": 360, "xRange": [-6.3, 6.3],
"functions": [{ "expr": "sin(x)", "label": "sin x" }, { "expr": "x^2/8 - 1", "dash": "7 5" }],
"areas": [{ "expr": "sin(x)", "from": 0, "to": 3.14159 }], "points": [{ "x": 0, "y": 0, "label": "O" }],
"parametric": [{ "x": "cos(t)", "y": "sin(t)", "t": [0, 6.283] }], "vlines": [{ "x": 3.14159 }],
"xLabel": "x", "yLabel": "y", "equalAspect": false }
{ "type": "molecule", "smiles": "CC(=O)Oc1ccccc1C(=O)O", "x": 640, "y": 40, "width": 260, "height": 200 }
{ "type": "icon", "icon": "heart-cross-section-2", "x": 700, "y": 100, "width": 220, "card": true }
すべてのアーティファクトは chapter、z、opacity、label、step、reveal、duration、order を受け付けます。card: true を指定すると、白い紙向けに作成された図を、淡い色のパネル上に表示します。プロットの式では、+ - * / ^、暗黙の乗算(2x、3(x+1))、pi、e、tau、sin cos tan asin acos atan sinh cosh tanh asinh acosh atanh sec csc cot exp ln log log2 log10 sqrt cbrt abs sign floor ceil round min max pow atan2 hypot mod step sinc gauss をサポートしています。board_docs を使うと、各形式の例を含む完全なリファレンスがモデルに渡されます。
レンダリングのデフォルト設定は、実際のレッスンを構築した後に設定します。Mermaid ではチョークテーマが使われます(セリフ体のテキスト、チョークの輪郭とエッジを持つ暗いノード、エッジがラベルと交差しないように不透明なラベル背景)。レイアウトチェックでは、図が縮小されてテキストが約 12 px 未満になると、必要なサイズとともに警告が表示されます。プロットでは、目盛り、軸、曲線、マーカーのラベル(vlines と hlines は label を受け取ります)が、細い黒の輪郭付きで曲線の上に描画され、y 軸ラベルはプロット領域の上に配置されます。分子は描画された構造に合わせて枠が設定され、ボックス内いっぱいに表示されます(ズームは約 2 倍を上限とします)。ズームアウト時は、概要と概要のスナップショットでも、チャプターのタイトルが読みやすいサイズに保たれます。
ビューアーの操作
| 操作 | キー/マウス |
|---|---|
| パン | スクロール/2 本指でスワイプ、ドラッグ、Shift+矢印キー |
| カーソル位置を中心にズーム | ⌘/Ctrl+スクロール、ピンチ、+/- |
| レッスンを前後に移動 | ←/→ |
| 表示中のチャプターを再生 | r(または Replay) |
| 現在のステップから再生/一時停止 | Space |
| ライブ表示(最新のステップ)に戻る | End |
| 前/次のチャプター | [/]、PageUp/PageDown |
| レッスン全体 | o(Overview) |
| 講師のカメラを再度フォロー | f、ダブルクリック、0(Follow) |
| 講師が指しているアイテムを確認 | ホバーすると step n · id · chapter が表示されます。クリックすると、端末に貼り付けられる step n, id (chapter c) がコピーされます |
ホバーすると、操作方法と step n / N のインジケーターが右上に表示されます。手動でパンするとカメラの追従が一時停止し、Follow を押すと再開します。
モデルツール
| ツール | 目的 |
|---|---|
board_open | ボードを開きます。サーバーを起動してブラウザーを開きます。ブラウザーを開けなかった場合のみ、URLを返します。再度呼び出しても安全です。piではインタラクティブモードでのみブラウザーを開き、ほかのボードツールも有効にします。それまでは無効のままです。未使用のボードがモデルに消費させるのは、1ターンあたり255文字(board_openのみ)で、7つすべてのツールを使う場合の12,197文字ではありません。/board openと/board loadでも有効になります。 |
board_read | リビジョン、タイトル、章の目次、カメラ、ステップ、および1章分のレイアウト(ID、種類、位置、サイズ)を読み取ります(chapterパラメーター。デフォルト:カメラの章。不明な章を指定するとエラーになります)。更新する前に読み取ってください。 |
board_update | 比較交換による更新(baseRevision):chapters、equations(追加、更新、削除)、scene(shapes、artifacts。追加または置換)、items(IDを指定して任意の項目を更新、移動、削除)、camera、title、clear。入力が不適切な場合(不明または誤記されたフィールド、文字列で指定された数値、空のテキスト、64文字を超えるID、または別の項目ですでに使われているID)は、理由とともに拒否され、何も適用されません。更新のたびにレンダリング後のレイアウトが測定され、テキストと数式の重なり、アーティファクトの重なり、章の外にはみ出した項目、レンダリングに失敗したアーティファクトが報告されます。この更新で発生した問題が最初に表示されます。 |
board_snapshot | 閲覧者に見えるボードのPNG(デフォルト:カメラに映る範囲。chapter、overview、region、widthも指定可能)に加え、各項目の測定済みバウンディングボックスとレイアウトの警告を返します。PlaywrightのChromiumまたはシステムのChromeを使用します。ヘッドレスページは5分間操作がないと閉じます。 |
board_library | オフラインのイラストライブラリーをキーワードまたはカテゴリで検索し、アイコンIDを返します。 |
board_save | 名前付きスナップショットをsave、list、loadします(loadにはbaseRevisionが必要です)。 |
board_docs | topic(overview、workflow、chapters、equations、marks、plot、svg、mermaid、molecule、icon、animation、layout、saves)でリファレンステキストを取得します。例を含むアーティファクト形式、SVGのルール、プロット式の文法、表示とアニメーションのオプション、章とカメラ、レイアウトの規則、保存について説明します。 |
学習フォルダー(~/Learn、またはMATH_BOARD_LEARN_DIRが指す場所)内で、サブエージェント(PI_SUBAGENT_NAMEを設定しているもの)ではない場合、pi拡張機能はシステムプロンプトに短く固定されたboard_teachingセクションを追加します。描画するタイミング、1つのステップの後に1つの確認質問をすること、1章につき1つの概念を扱うこと、「step 4, eq2」のような参照を解決するためにボードを読むことが記載されています。MATH_BOARD_TEACHING=alwaysを指定すると常に追加され、neverを指定するとどこにも追加されません。誰も見ていない場合、読み取り、更新、読み込みの結果は「ボードを表示しているブラウザーはありません」で終わるため、チューターはboard_openを呼び出す必要があるとわかります。
保存とエクスポート
- 自動保存:変更のたびに、データフォルダー内の
autosave.jsonへ、デバウンス処理とアトミックな書き込みで保存されます。古いコピーも3つ保持されます(autosave.1.jsonが最新です)。新しいボードサーバーは起動時にこれを復元するため、/reloadを実行したりpiを再起動したりしてもボードは保持されます。書き込みに失敗した場合(たとえば、フォルダーに書き込み権限がない場合)、次のツール結果と/board statusでその旨が通知されます。復元できない自動保存ファイルはautosave.corrupt-<time>.jsonとして別の場所に移され、その旨が報告されます。上書きされることはありません。同じデータフォルダーで2つのボードを使用することもできますが、最後の変更が自動保存に反映されるため、互いに警告が表示されます。 - 名前付きスナップショット:
/board save <name>、board_save、またはSaveボタンを使うと、saves/<name>.jsonに書き込まれます。読み込み時にはすべてが再検証され、使用できないアイテムは読み込みに失敗するのではなくスキップされ、スキップされたアイテムが結果に一覧表示されます。保存データにはフォーマットバージョンが記録されており、新しいバージョンで作成された保存データは、誤って読み込まないよう拒否されます。 - エクスポート:
/board export [name]を実行すると、piの現在のフォルダー内にあるviz/board-<name>-<YYYYMMDD-HHMM>/へ、実行中のボードが書き出されます。既存のファイルは上書きせず、代わりに-2、-3、…が追加されます。フォルダー内には、board.json(名前付き保存と同じ形式です。データフォルダー内のsaves/<name>.jsonにコピーすると、/board load <name>で開けます)、各チャプターのchapter-<id>.png(1600 px、board_snapshotと同様にレンダリング)、チャプター外のアイテム用のhome.png(チャプターがホームボードを覆っている場合を除く)、複数の領域がある場合のoverview.png、および標準的なMarkdown画像リンクを含むlesson.md(ObsidianとGitHubの両方で表示できます)が含まれます。ファイルは自分だけがアクセスできます(保存データと同様に、フォルダーは0700、ファイルは0600)。vizがシンボリックリンクの場合は、たどらずに処理を拒否します。エクスポートは手動でのみ実行されます。コマンドを入力したときだけ実行され、自動保存時、シャットダウン時、モデルのツールからは実行されず、ボードサーバーも起動しません。ヘッドレスブラウザーがない場合もboard.jsonとlesson.mdは書き込まれ、画像がない理由が通知されます。 - データフォルダー:チェックアウトでは
.data/(gitで無視されるため、ボードがコミットに含まれることはありません)、インストール済みコピーではユーザーごとのフォルダー、またはMATH_BOARD_DATA_DIRを使用します(piへのインストールを参照)。MCP サーバーはその配下のmcp/サブフォルダーを使うため、MCP サーバーのボードとpiのボードで自動保存が共有されることはありません。テストとスクリプトは常に一時フォルダーを使うため、実際の保存データに触れることはありません。 - 上限:チャプター200個、数式1,000個、図形とアーティファクトの合計5,000個、1回の更新あたり図形2,000個とアーティファクト100個、ボードあたり6 MiB、SVGあたり128 KiB。
安全性
要点は次のとおりです。SECURITY.md に脅威モデル、対象範囲外の項目、問題の報告方法を記載しています。
- ループバック専用サーバー、セッションごとにランダムなベアラートークンを発行、Host と Origin の厳密なチェック、リクエスト本文のサイズ制限、比較交換によるリビジョン管理、アトミックな保存を行います。
- ページは閲覧専用で、誰もページ上に描画しません。書き込みは Clear ボタン(その間にボードが変更されていた場合は再確認を求めます)と Save のみで、ページの操作によってモデルのターンが開始されることはありません。
- URL のトークンがモデルに渡されるのは、ブラウザーを開けなかった場合のみです。それ以外の場合、ツールの結果には
127.0.0.1:<port>だけが記載されます。 - KaTeX は
trust: false、strict モード、展開制限を適用してレンダリングします。ラベルとテキストは HTML ではなく、テキストとして挿入されます。 - SVG、Mermaid、分子、アイコンは、検証後にすべて
<image>(画像コンテキスト:スクリプトなし、外部読み込みなし)を通じて表示されます。Mermaid はsecurityLevel: "strict"で実行され、リンク、コールバック、埋め込みマークアップ、%%{init}%%ディレクティブを拒否します。SMILES 文字列には SMILES で使用する文字のみを許可します。プロット式は、算術演算、固定の関数テーブル、プロット変数のみを扱う小さなパーサー(shared/expr.mjs)でコンパイルされます。 - SVG は厳密な XML パーサー(
@rgrove/parse-xml)で解析し、解析済みのツリーを検査して、そのツリーから再出力するため、保存される内容は検査済みの内容と完全に一致します。図形、line、text/tspan/textPath、defs/symbol/use、マーカー、グラデーション、パターン、クリップパス、マスク、<style>ブロック、SMIL アニメーションを使用できます。拒否されるもの:整形式でない XML(パーサーのメッセージを表示)、DOCTYPE、CDATA、処理命令、スクリプト、foreignObject、image、イベント属性、外部 URL、data:URI、その他の名前空間、CSS エスケープ、および色、calc/var、変換、@keyframes、@media、url(#id)以外のすべての CSS アットルールと関数。url(…)とhrefは、同じ SVG 内の#idを参照する必要があり、文字参照のデコード後に検査されます。xmlnsがない場合は追加されます。エラーには、問題のある要素、属性、または構文が示されます。 - レイアウトチェックとスナップショットに使うヘッドレス Chromium は OS サンドボックスで実行されます。起動できない環境でのみ、サンドボックスなしで起動し、その旨を通知します。
- 静的ファイルは
public/からのみ配信され、ファイル拡張子に基づいて選択され、パスは厳密に検査されます。アイコンはビルド時に同じバリデーターでサニタイズされます。
ビルドとテスト
cd ~/math-board
npm ci # includes pi 1.4.0 and TypeScript, for the type check and loader tests
npm run build # bundle the browser app into public/, write mcp/schemas.json and THIRD_PARTY_NOTICES.md
npm run typecheck # index.ts against pi's types
npm run build:icons # (re)build the icon library (network)
npm test # unit, HTTP, hardening, validator and snapshotter tests, and the MCP server over stdio
npm run test:browser # Playwright browser tests
npm run test:load # real pi loader + /reload regression
node scripts/e2e-snapshot.mjs # end to end: update, layout check, snapshot, /board export
node scripts/demo-lessons.mjs <out-dir> [physics|mri|chem|cs|history] # visual QA on five sample lessons
test:load、e2e-snapshot.mjs、demo-lessons.mjsは、pi の実際のローダーを通じて拡張機能を読み込みます。PI_HOST_ROOTが設定されている場合はそれを使用します(インストール済みの@earendil-works/pi-coding-agentパッケージのディレクトリ)。設定されていない場合は、npm ciがnode_modulesに配置した pi を使用し、それもなければグローバルインストール(npm root -g)を使用します。npm testにはtest/mcp.test.mjsが含まれます。このテストは一時データフォルダーとMATH_BOARD_NO_BROWSER=1を指定してnode mcp/server.mjsを起動し、MCP SDK クライアントから操作します。ヘッドレスブラウザーが利用できない場合は、理由を示したうえでboard_snapshotのチェックをスキップします。- ブラウザーテストには Playwright の Chromium が必要です(
npx playwright install chromium)。スナップショットスクリプトはそれかシステムの Chrome を使用し、レイアウトチェックで重なりとボード外のアイテムが検出され、修正後に解消されることを確認します。パスが指定されていない場合は PNG を一時フォルダーに書き込み、エクスポート先にも一時フォルダーを使用します。demo-lessons.mjsはすべての章、カメラビュー、概要を 1200 px と 1600 px で書き出し、ツールが返したすべてのレイアウト警告をwarnings.jsonに記録します。 - CI(
.github/workflows/ci.yml)は、型チェックを実行し、再ビルド後にpublic/、mcp/schemas.json、THIRD_PARTY_NOTICES.mdがコミットと異なる場合は失敗します。その後、mainへのプッシュとプルリクエストごとに、Node 22 でnpm test、test:browser、test:load(pi 1.4.0 に対して)、エンドツーエンドスクリプトを実行します。そのため、browser/またはtools.mjsを変更した場合は、npm run buildを実行して生成されたファイルをコミットしてください。 - 開発中は、サーバーの起動後に拡張機能のファイルが変更されると、ツールの出力に警告が表示されます。
/reloadを実行すると、サーバーの変更が読み込まれます(サーバーコードはバージョンクエリ付きでインポートされます)。このチェックでは更新時刻を比較するため、古い時刻を維持するコピー方法(cp -p、rsync -a、一部の同期ツール)は検出されません。その場合も/reloadを実行してください。 - 依存関係:実行時の依存関係は、バージョンを固定した 3 つだけです。公式 MCP TypeScript SDK の現行安定メジャーバージョンである v2(
@modelcontextprotocol/serverとして公開されます。@modelcontextprotocol/sdkは v1 のメンテナンス系列です)、ヘッドレスページ用のplaywright-core、SVG チェック用の@rgrove/parse-xmlです。React、KaTeX、Mermaid、SmilesDrawer はビルド時にpublic/にバンドルされるため、devDependencies です。MCP サーバーはツールのスキーマをmcp/schemas.jsonから読み込みます。このファイルは、ビルド時に TypeBox を使ってtools.mjsから生成されます。pi も独自の TypeBox で同じスキーマを生成し、テストでは両者が一致することを確認します。テストでは@modelcontextprotocol/clientを使用します。
アイコンライブラリは npm run build:icons でビルドされます。このコマンドは Bioicons からダウンロードし、CC0、CC-BY 3.0/4.0、MIT、BSD のライセンスが付いた 128 KiB 以下のアイコンを採用します。CSS をインライン化し、エディターメタデータ、フィルター、ラスター画像、外部参照を削除したうえで、ボードの SVG バリデーターを使って各アイコンを検証します。
クレジット
- Eero Alvar の learn:このボードが併用されることを想定して作られた、質問を中心に一度に 1 つの概念を扱う学習環境です。
- この拡張機能が機能を追加するターミナルエージェント、pi。
- イラストを提供してくれた Bioicons。各アイコンには個別のライセンス(CC0、CC-BY 3.0、CC-BY 4.0、MIT)が適用されており、すべてのアイコンの作者とライセンスは public/icons/CREDITS.md に記載されています。CC-BY アイコンを使った素材を公開する場合は、作者を明記する必要があります。
- ページにバンドルされている KaTeX、Mermaid、SmilesDrawer、React。
このような構成にした理由と、未解決の課題(数式のモーフィング、レイアウトマップ、ベクター、クイズのミラーリング)については docs/design.md をご覧ください。先行事例(tldraw のエージェントキット、TheoremExplainAgent、Code2Video、HeyTutor、Manim 風のタイムラインなど)に関する調査メモは docs/prior-art.md にあります。
ライセンス
MITです。詳細はLICENSEをご覧ください。バンドルされているライブラリとアイコンには、それぞれ独自のライセンスがあります。THIRD_PARTY_NOTICES.mdにはライセンス全文が記載されています(ビルド時にバンドルから生成されます)。public/icons/CREDITS.mdには、各アイコンの作者とライセンスが記載されています。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。