MCP サーバ
コンパイラ本体を AI クライアントから呼べるようにするサーバです。パッケージに同梱されていて、クライアントが設定に従って起動します。
セットアップウィンドウ
Section titled “セットアップウィンドウ”Unity のメニューの TsukimiCode から Tsukimi MCP を開きます。使うクライアントにチェックを付けて主ボタンを押すと、チェックしたクライアントの設定・Skill・最終チェック(作業完了時のコンパイル検査)がまとめて書き込まれます。

| 場所 | 中身 |
|---|---|
| ツールバー | パッケージの版と、設定ファイルを読み直してマークを更新する Refresh |
| クライアントの行 | 8 行。チェック・設定ファイルの場所・マークが並ぶ。チェックはプロジェクトごとに UserSettings/TsukimiMcpClients.json に保存される。保存が無いうちは、Claude Code と、設定に tsukimi の項目が既にあるクライアントにチェックが付く |
| Server | 同梱のサーバ DLL が見つかるか |
| Skill | AI が参照する手順書の状態(Skills) |
| Final check | 作業完了の報告時にコンパイルを検査するフックの状態。Claude Code だけ |
| 主ボタン | チェックしたクライアントの設定・Skill・最終チェックをまとめて書き込む。文言は状態で変わる |
| More | 起動コマンド・AGENTS.md への注記・手で貼る設定・最終チェックの削除。最初は閉じている |
| 最下段 | Last check(最終チェックの最後の結果)と、導入のページを開く Open the guide |
| マーク | 意味 |
|---|---|
| ✓ | インストール済みで、最新 |
| 空の丸 | まだインストールしていない |
| ! | インストール済みだが古い。前の版が書き込んだ物か、別のサーバかプロジェクトを指している |
| ✕ | インストールできない。同梱のサーバか、Skill の元のファイルが見つからないときに出る |
| 行 | 文言 | 意味 |
|---|---|---|
| Server | found | 同梱のサーバが見つかっている |
| Server | not found · reinstall the package to restore it | サーバの DLL が見つからない。主ボタンも押せない。パッケージを導入し直すと戻る |
| Skill | up to date · shared by every client | 最新。どのクライアントからも同じ Skill を読む |
| Skill | out of date · shared by every client | 前の版の Skill がインストールされている |
| Skill | out of date (changed by hand) · shared by every client | 前の版の Skill がインストールされていて、インストール後に手で変えたファイルがある |
| Skill | not installed · shared by every client | インストールされていない |
| Skill | source not found | パッケージの中に Skill の元のファイルが無い |
| Final check | up to date · Claude Code only | 最新 |
| Final check | out of date · Claude Code only | 別のサーバかプロジェクトを指している |
| Final check | not installed · Claude Code only | インストールされていない |
| 文言 | 出る条件 | ボタンの下の注記 |
|---|---|---|
| Set Up (N clients) | チェックしたクライアント・Skill・最終チェックのどれかが、まだインストールされていないか、インストールできない | Writes the checked clients, the Skill and the final check. Restart your AI client afterwards. |
| Update (N clients) | 全部インストール済みで、どれかが古い | The package was updated. Restart your AI clients afterwards. |
| Set Up Again | 全部が最新 | Everything is in place. |
| 項目 | 内容 |
|---|---|
| N | チェックしたクライアントの数(1 つなら client) |
| 文言に入る対象 | チェックしたクライアント・Skill・最終チェック。最終チェックは Claude Code にチェックがあるときだけ |
| 押したときの動作 | どの文言でも同じ。チェックしたクライアントの設定と Skill を書き込み、Claude Code にチェックがあれば最終チェックも書き込む。Skill はチェックに関係なくインストールされる |
| 最新の物 | これも書き直す。Set Up Again は、書き方を今の版に揃えるときに使う |
| 押せないとき | Server が not found のとき |
| 押した後 | AI クライアントを再起動する。クライアントは設定と Skill を起動時にしか読まない |
書き込みの途中の確認
Section titled “書き込みの途中の確認”| 場合 | 文言 | 選んだときの動作 |
|---|---|---|
| 設定ファイルが JSON として読めない | ... could not be read as JSON. Replace it with a file that holds only the tsukimi entry? | Replace でファイルを tsukimi の項目だけにする。Cancel ならそのクライアントは書き込まない |
| Skill と同名で中身の違うファイルがある | These files already exist and differ. Replace them? と、そのファイルの一覧 | Replace で上書きする。Cancel なら Skill はインストールされない |
.claude/settings.local.json が JSON として読めない | ... could not be read as JSON, so it was left alone. | 最終チェックはインストールされない。ファイルはそのまま |
Server
Section titled “Server”| found | 同梱のサーバが見つかっています |
| not found | サーバの DLL が見つかっていません。主ボタンは押せず、マークは ✕ になります。パッケージを導入し直すと戻ります |
| 起動コマンド | More の Start command に、クライアントが実行するコマンドが出ます |
クライアントの設定
Section titled “クライアントの設定”設定ファイルもキーもクライアントごとに異なるため、8 種類のクライアントそれぞれに合わせた設定を生成します。
| クライアント | 設定ファイル | キー | 書式 | サーバの経路 | 補足 |
|---|---|---|---|---|---|
| Claude Code | .mcp.json | mcpServers | JSON | プロジェクトからの相対パス | |
| GitHub Copilot CLI | .mcp.json | mcpServers | JSON | プロジェクトからの相対パス | Claude Code と同じファイル。プロジェクトのフォルダで起動する |
| Visual Studio | .mcp.json | servers | JSON | 絶対パス(プロジェクトの場所も書く) | 同じファイルの別のキー |
| VS Code | .vscode/mcp.json | servers | JSON | ${workspaceFolder} で始まるパス | |
| Cursor | .cursor/mcp.json | mcpServers | JSON | ${workspaceFolder} で始まるパス | |
| Roo Code | .roo/mcp.json | mcpServers | JSON | プロジェクトからの相対パス | |
| Gemini CLI | .gemini/settings.json | mcpServers | JSON | 絶対パス(プロジェクトの場所も書く) | ほかの設定と同じファイル |
| Codex CLI | .codex/config.toml | mcp_servers | TOML | 絶対パス(プロジェクトの場所も書く) | プロジェクトの信頼が別に必要 |
| 項目 | 内容 |
|---|---|
相対パスと ${workspaceFolder} で書く相手 | サーバの経路だけを書き、プロジェクトの場所は書かない。サーバは自分のファイルの場所から上へたどり、Assets と ProjectSettings の両方を持つ最初のフォルダをプロジェクトとして使う。そのため、別のマシンや別のフォルダへ clone しても同じ設定で起動する |
| 絶対パスで書く相手 | サーバとプロジェクトの両方の絶対パスを書く |
| パッケージをプロジェクトの外に置いた場合 | どのクライアントにも絶対パスを書く |
| クライアントのマークの決め方 | 設定に書かれた経路が指す先で決める。書き方がウィンドウの書く形と違っても、今のサーバとこのプロジェクトを指していれば ✓ |
| 前の版のウィンドウが書いた絶対パス | 前の版はどのクライアントにも絶対パスを書いていた。今のサーバとプロジェクトを指していれば ✓ と出て、自動では書き直されない。相対パスか ${workspaceFolder} へ移すには、主ボタン(全部 ✓ なら Set Up Again)を押す |
手動で設定する場合
Section titled “手動で設定する場合”More を開き、Paste by hand のドロップダウンでクライアントを選ぶと、貼り付ける内容がそのまま出ます。
{ "mcpServers": { "tsukimi": { "command": "dotnet", "args": ["<プロジェクトから見たパッケージの場所>/Server~/TsukimiCode.Mcp.dll"] } }}{ "servers": { "tsukimi": { "command": "dotnet", "args": ["${workspaceFolder}/<プロジェクトから見たパッケージの場所>/Server~/TsukimiCode.Mcp.dll"] } }}[mcp_servers.tsukimi]command = "dotnet"args = ["<パッケージの場所>/Server~/TsukimiCode.Mcp.dll", "<プロジェクトの場所>"]| 項目 | 内容 |
|---|---|
| 出る内容 | ウィンドウが書き込む内容と同じ。パスにはそのプロジェクトでの値が入る |
| 上の例 | 順に Claude Code(相対パス)・VS Code(${workspaceFolder}・キーは servers)・Codex CLI(絶対パス・TOML) |
| 引数のプロジェクトの場所 | 絶対パスで書く相手にだけ入る。サーバが、そのプロジェクトに生成された実行環境の API のデータベースを読むために使う |
| 省略した場合 | サーバが自分のファイルの場所から上へたどってプロジェクトを探す。サーバがプロジェクトの外にあって見つからないときは、API の存在確認が行われない |
パッケージを更新した後の書き直し
Section titled “パッケージを更新した後の書き直し”| 対象 | どうなるか |
|---|---|
| 時機 | Unity がスクリプトを読み込むとき(起動やパッケージの更新の後)。ウィンドウでインストールした Skill の記録が前の版のときだけで、同じ版では何もしない |
| Skill | インストールしたときのまま手を付けていないファイルを書き直す(Skills) |
| 手で変えた Skill のファイル | 書き直さずに残し、Console の警告で名指しする。置き換えるには主ボタンを押し、同名のファイルの確認で Replace を選ぶ |
| クライアントの設定 | tsukimi の項目が別のサーバか別のプロジェクトを指しているものだけ書き直す |
| 最終チェック | インストール済みで古いときだけ書き直す |
| Skill の記録が無いプロジェクト | 何も書き直さない。0.9.0 より前のウィンドウでインストールした Skill には記録が無いので、最初の 1 回だけ主ボタンでインストールし直す |
| 書き直した後 | Console に Updated ... for TsukimiSharp <版>. Restart your AI client so that it reads them. の 1 行が出る。クライアントを再起動する |
| 書き直す物が無かった場合 | 版が前回このプロジェクトで読み込んだ版と違い、どれかのクライアントの設定に tsukimi の項目があれば、Console に TsukimiSharp <版> is loaded. If your AI client was already running, restart it, or reconnect its MCP servers, so that it uses this version. の 1 行が出る。クライアントを再起動するか、MCP サーバを接続し直す |
カードの下にある More を開くと、普段は使わない 4 つの欄が出ます。
| 欄 | ボタン | 中身 |
|---|---|---|
| Start command | Copy | Claude Code の設定に書く内容と同じ起動コマンド。パッケージがプロジェクトの中にあればサーバの経路は相対パスなので、手で起動するときはプロジェクトのフォルダで実行する |
| Note in AGENTS.md | Add | 常に読み込まれる AGENTS.md へ短い注記を追加する(Skills) |
| Paste by hand | Copy | ドロップダウンで選んだクライアントの設定に貼る内容 |
| Final check | Remove | 最終チェックのフックを削除する。インストールされていないときは押せない |

作業完了時のコンパイル検査
Section titled “作業完了時のコンパイル検査”Claude Code にチェックを付けて主ボタンを押すと、.claude/settings.local.json にフックが登録されます。このフックは、AI が作業完了を報告しようとした時点で、そのセッションで変更された T# のソースを 1 回だけコンパイルします。
| 場合 | どうなるか |
|---|---|
| コンパイルが通らなかった | 診断を提示して作業の続行を求めます |
| 警告だけが出た | 戻しません |
| コンパイルできた | 何も言いません。ウィンドウの Last check に最後の結果が出ます |
| 検査そのものが動かない | 止めずに通します。壊れた検査が作業を止め続けないためです |
| 同じ診断が 2 回続いた | 通します。修正できないと判断して打ち切ります |
| 対象のクライアント | Claude Code だけです。フック機能を持つクライアントが他に無いためです |
| 書き込み先 | 共有向けでない設定ファイルです。中身に絶対パスが入るためです |
| 最後の結果 | ウィンドウの最下段の Last check に出ます。一度も実行されていなければ not run yet です |
| 削除 | More の Final check の Remove で、このフックだけを削除します。同じファイルの他の設定は保持されます |
7 つあります。
| ツール | 内容 |
|---|---|
ping | サーバが起動しているかの確認 |
inspect | ソースのコンパイルと、診断・解析結果の返却 |
test | [TsukimiTest] を付けたメソッドの実行 |
diagnostics | エラー番号の一覧 |
spec | この言語の説明の生成 |
decompile | コンパイルされたアセンブリを読める形にする |
profile | Unity で開いているシーンのプログラムの命令と extern の数の読み出し |
中心になるのは inspect と test で、ping は接続の確認、diagnostics と spec は inspect が返した内容の解釈、decompile はすでにあるプログラムの確認に使います。
サーバが起動しているかどうかと、起動しているサーバの版を確認します。引数はありません。
"tsukimi-mcp ok (version x.y.z; static-analysis MCP; liveness check)"x.y.z の位置に、起動しているサーバの版が入ります。登録した直後に、設定が有効かどうかを切り分けるために使います。
パッケージを更新した後も更新の前に起動したサーバが動いていると、ping 以外のツールは実行されず、次の文がエラー(isError: true)として返ります(ping は上の 1 行の後ろに空白を 1 つ挟んで同じ文を続け、エラーにはしません)。
The TsukimiSharp package was updated after this MCP server started (running x.y.z, installed x.y.z). Restart your AI client, or reconnect its MCP servers, to use the new version.installed は更新後のパッケージの版で、読めないときは省かれます。クライアントを再起動するか、クライアントで MCP サーバを接続し直すと、更新後のサーバが起動します。
inspect
Section titled “inspect”ソースをコンパイルして、結果を構造化した JSON で返します。
| 引数 | 内容 |
|---|---|
source | ソース 1 ファイル分の全文 |
file | 診断の位置に使うファイル名。省略すると <inline> |
sources | 複数のファイル。{name, text} の配列。source より優先される |
path | Unity プロジェクトの中のファイルを、本文の代わりにパスで渡す。1 つか配列で、プロジェクトのフォルダからの相対パス(Assets/Lamp/Lamp.cs など)。.cs は、Unity がそのプログラムをコンパイルするときに集めるファイル(同じフォルダとその下のフォルダのファイル・TsukimiShared フォルダのファイル。Editor という名前のフォルダの下は除く)と一緒にコンパイルされる。プログラムのアセット(.asset)はそれがコンパイルする .cs と同じ扱いで、フォルダはその下の .cs を全部渡す。ディスクに保存された内容を読むので、保存していない変更のあるファイルは本文も渡す。名前が path で読んだファイルと一致する本文は、そのファイルの代わりに使われる |
mochi | .cs の代わりに MoCHI の .mochi.xml を確認する。中身は MoCHI の inspect |
cost | 命令数とヒープ使用量を測定するかどうか。省略すると測定しません。測定時はビルド時と同じ最適化を実行するため、この呼び出しの所要時間の大半はここに費やされます |
1 つのソースが宣言できる具象の Behaviour は 1 つだけなので、次のような形を確認したいときは sources にまとめて渡します。
- インタフェースを Behaviour で実装する
- 基底の Behaviour と派生の Behaviour に分ける
- ある Behaviour から別の Behaviour のメソッドを呼ぶ
- Behaviour の型でコンポーネントを受け取る
1 つの source に 2 つ書いてエラーになるのは渡し方の誤りであり、言語の制限ではありません(sources で渡した場合、結果は Behaviour ごとに分かれ、最上位ではなく programs の各要素に入ります)。
コンパイルできたときの返り値
Section titled “コンパイルできたときの返り値”次のソースを source に渡し、cost を真にした結果です。cost を指定しないと、heap と cost の 2 つはキー自体が出力されません。
using UnityEngine;using Tsukimi;
public class Lamp : TsukimiBehaviour{ [SerializeField] private Light target; [UdonSynced] private bool on;
public override void Interact() { on = !on; target.enabled = on; RequestSerialization(); }}{ "schemaVersion": 1, "compiles": true, "diagnostics": [], "facts": { "heap": { "slots": 11, "limit": 1048576, "remaining": 1048565 }, "cost": { "instructionCount": 12, "staticExternCount": 3, "nsPerExtern": 77, "nsPerNonExtern": 5.4, "isStraightLine": true }, "entries": [ "Interact" ], "recursiveMethods": [], "loopCount": 0, "methods": [ { "name": "Interact", "isEntry": true, "isRecursive": false, "params": 0, "locals": 1, "loops": 0, "externs": 3, "entryName": "_interact" } ], "runtimeRisk": [], "contract": { "synced": [ { "name": "on", "type": "SystemBoolean", "sync": "none" } ], "exportedFields": [], "syncMode": "any" }, "nullDerefRisks": [ { "kind": "unassignedFieldDeref", "severity": "warning", "origin": "runtime", "message": "The reference field 'target' (type UnityEngineLight) is shown in the Unity Inspector and is never assigned in code, so its value comes only from there. ...", "method": "Interact", "field": "target", "type": "UnityEngineLight", "deref": "UnityEngineLight.__set_enabled__SystemBoolean__SystemVoid" } ] }, "summary": { "total": 0, "bySeverity": {}, "byOrigin": {} }, "externDb": { "resolved": true, "unknownApiChecks": true, "externCount": 32898 }}| 読みどころ | |
|---|---|
diagnostics が空・compiles が真 | このソースは変換できています |
nullDerefRisks に 1 件 | target はコードのどこでも代入されておらず、値は Inspector からしか入りません。割り当てを忘れると実行時に null のままになり、target.enabled への代入でイベント全体が中断されます(Udon には例外処理がないので、ログにも何も出ません) |
cost の nsPerExtern と nsPerNonExtern | extern の呼び出し 1 回と、それ以外の命令 1 つのおおよその所要時間です。命令数そのものより、extern を何回呼ぶかのほうが影響することが、この 2 つの差から読み取れます |
エラーのときの返り値
Section titled “エラーのときの返り値”Udon に存在しない型を使った例です。
using System.Collections.Generic;using UnityEngine;using Tsukimi;
public class Bag : TsukimiBehaviour{ private List<int> items;
public override void Interact() { items = new List<int>(); items.Add(1); Debug.Log(items.Count); }}{ "schemaVersion": 1, "compiles": false, "diagnostics": [ { "code": "TUKI0102", "severity": "error", "message": "Variable type does not exist in Udon: field items has the type SystemCollectionsGenericList", "explain": "This type does not exist in Udon (outside the extern database).", "location": { "file": "Bag.cs", "startLine": 7, "startCol": 23, "endLine": 7, "endCol": 23 }, "fix": "This type cannot be used here (it is outside the usable Udon extern set). ... For lists and dictionaries, use the VRChat data containers DataList / DataDictionary (VRC.SDK3.Data) - generic List<T> / Dictionary<K,V> are not usable.", "witness": "SystemCollectionsGenericList", "origin": "subset", "path": null }, { "code": "TUKI0101", "severity": "error", "message": "Not exposed to Udon: SystemCollectionsGenericList.__ctor____SystemCollectionsGenericList", "explain": "This API is not exposed to Udon.", "location": { "file": "Bag.cs", "startLine": 11, "startCol": 17, "endLine": 11, "endCol": 17 }, "fix": "This API is not exposed to Udon. Use an API that exists in the Udon extern set (see the `spec` tool, topic \"api\").", "witness": "SystemCollectionsGenericList.__ctor____SystemCollectionsGenericList", "origin": "subset", "path": null } ], "facts": null, "summary": { "total": 4, "bySeverity": { "error": 4 }, "byOrigin": { "subset": 4 } }, "externDb": { "resolved": true, "unknownApiChecks": true, "externCount": 32898 }}| 読みどころ | |
|---|---|
facts が null | compiles が偽のときは常に null です。コンパイルできていない以上、ヒープ消費もコストも測定できないためです。facts は存在するのに heap と cost だけが無い場合は別で、cost を指定していないことを意味します |
diagnostics が 2 件 | 4 件のうち先頭の 2 件だけを載せています(残りは List のメソッド呼び出しに対する同種の指摘)。全体の件数は summary.total にあります |
witness | エラーと判定した根拠となった識別子が入ります。この例では型名 SystemCollectionsGenericList と、見つからなかった extern の署名で、メッセージを読み解かなくても何が無かったのか分かります |
返り値のキー
Section titled “返り値のキー”| キー | 内容 |
|---|---|
schemaVersion | この出力形式のバージョン。形式が変わると上がる |
compiles | Udon のバイトコードまで変換できたか。実行環境で動作することの保証ではない |
diagnostics | エラーと警告の配列。番号・重大度・位置・直し方・原因の区分が入る |
summary | diagnostics を重大度と原因の区分で数えたもの |
facts | 変換できたときだけ入る。エラーのときは null |
facts.heap | 使うヒープの数と、残り。limit は実行環境がヒープに許す最大の数です。cost を真で渡したときだけ入ります |
facts.cost | 命令数・extern の呼び出し数と、1 回あたりのおおよその所要時間。cost を真で渡したときだけ入ります。入っていないのは測っていないという意味で、費用が無いという意味ではありません |
facts.entries | 実行環境から呼ばれるエントリポイントの名前 |
facts.methods | メソッドごとの内訳。ローカル変数・ループ・extern の数 |
facts.recursiveMethods | 実行中にもう一度入りうるので、呼び出しの前後で引数とローカル変数を退避するメソッドの名前(実行中のメソッドへの入り直し) |
facts.contract | 同期するフィールドと、外へ公開しているフィールドと、その Behaviour 全体の同期方式。方式はフィールドごとの sync とは別の軸です |
facts.runtimeRisk | コンパイルは通るが実行時に停止しうる箇所 |
facts.nullDerefRisks | null になりうる参照をそのまま辿っている箇所 |
externDb | 実行環境の API のデータベースを参照できたか。参照できた API の総数 |
診断に付く原因の区分
Section titled “診断に付く原因の区分”diagnostics の各要素には origin が付き、4 つの区分によって修正すべき場所が変わります(runtime はこの表には含まれず、facts.runtimeRisk と facts.nullDerefRisks にのみ付きます)。
| 区分 | 意味 |
|---|---|
subset | この言語が対応していない構文。書き方を変えればコンパイルできる |
environment | 実行環境に存在しない。書き方を変えてもコンパイルできない |
cost | コンパイルはできるが、コストが上限を超える |
tool | コンパイラか静的解析の内部エラー。修正すべき場所は書いたコードではない |
tool だけは性質が異なり、コンパイラ側の失敗を示すため、コードを書き直しても結果は変わりません。
ソースをコンパイルして、[TsukimiTest] を付けたメソッドを Unity なしで実行します。
受け取るのは 5 つです。
| 引数 | 内容 |
|---|---|
sources | まとめてコンパイルするファイル。inspect と同じ形。テストは 名前.Tests.cs に書いて、確認したい Behaviour と一緒に渡します(書き方は テスト) |
path | inspect と同じです。.cs を渡すと、その 名前.Tests.cs も一緒に読みます。保存していない変更のあるファイルは sources にも渡します |
projectPath | Unity プロジェクトの場所。省略可。渡すと同じ内容がそのプロジェクトの中にも書かれ、Unity へ戻ってウィンドウを開き直すとそこに出ます。path もこのプロジェクトから読みます |
fast | 素の C# として実行するかどうか。省略すると既定の道で実行します。速いので書いている途中の確認に向きますが、答える問いが違います——書いた規則が正しいかを確認し、コンパイルした形が正しいかは確認しません(テスト) |
summary | 真なら、成功しなかったテストだけを cases に返します。省略すると全部を返します。passed・failed・notRunnable・allPassed は全部のテストから数え、省いた成功の数は passedOmitted に入ります。projectPath に書かれる結果は全部のテストのままです |
{ "schemaVersion": 1, "origin": "mcp", "ranAt": "2026-08-13T05:57:52.7817272Z", "passed": 2, "failed": 1, "notRunnable": 0, "allPassed": false, "cases": [ { "name": "OneBumpAddsOne", "source": "Counter.Tests.cs", "outcome": "passed" }, { "name": "TwoBumpsMakeTwo", "source": "Counter.Tests.cs", "outcome": "passed" }, { "name": "DeliberatelyWrong", "source": "Counter.Tests.cs", "expected": "99", "actual": "1", "location": "32:9", "outcome": "assertFailed" } ]}| キー | 読み方 |
|---|---|
outcome | 4 種類あります。passed は成功、assertFailed は Assert が成立しなかったもの、halted は実行環境でも同じ箇所で停止するもの、notRunnable は実行そのものができなかったものです。notRunnable はテストの失敗ではなく、コードを書き直しても結果は変わらないため、まず detail を読んでください |
allPassed | テストが 1 本も見つからなかった場合と、1 本でも実行不可があった場合も偽になります。どちらも成功と誤認されないようにするためです |
origin | どちらの道で実行したかが値で入ります。mcp は既定の道、mcp-fast は素の C# の道、editor は Unity のウィンドウからの実行です。失敗を読む前にここを見ます |
trace | 失敗したときだけ入ります。実行中に記録された事象が時系列で並びます |
passedOmitted | summary を真で渡したときだけ入ります。cases から省いた成功の数です |
diagnostics
Section titled “diagnostics”エラー番号の一覧を返します(引数はありません)。inspect が返した番号の意味を参照するために使います。
{ "code": "TUKI0101", "defaultSeverity": "error", "en": "This API is not exposed to Udon.", "fixTemplate": "This API is not exposed to Udon. Use an API that exists in the Udon extern set ...", "origin": "subset"}上は配列の 1 要素で、inspect が返す個々の診断と違って位置が入りません(番号そのものの定義を参照する表だからです)。
この言語の説明を Markdown で返します(topic で選べる話題は 4 つ)。
| 話題 | 内容 | 根拠 |
|---|---|---|
subset | 対応している形の規則。エラー番号ごとに、エラーになる条件と直し方が並ぶ | 診断の一覧から自動生成。コンパイラの版が変われば内容も変わる |
api | 実行環境が持っている型の名前の一覧。名前を参照できることと、その API が実際に使えることは別で、使えるかどうかは inspect に通して確認する | extern データベースから自動生成。同上 |
pitfalls | 通常の C# と挙動が違うところ。null の発生源、イベントが黙って終わるケースなど | 手書きの解説。コンパイラの定義からは自動生成できない内容 |
builtins | この言語固有の組み込み要素。属性・基底クラス・Assert・カーネル API。実行環境の API ではないので api には出ない | コンパイラが持つ型定義から自動生成 |
| (省略) | 全体の見取り図と話題の索引 | extern データベースを参照できているかどうかも書かれる。参照できていないと未知の API と未知の型の検査(TUKI0101・TUKI0102)が実行されないので、その状態でエラーになった形は、書き方ではなくデータベースが無いことが理由かもしれない |
| (知らない話題) | 使える話題を並べたメッセージ |
結果を読むときの注意
Section titled “結果を読むときの注意”compilesが真でも、実行環境で動作するとは限りません。バイトコードまで変換できたことだけを表しますruntimeRiskとnullDerefRisksが空でも安全ではありません。この検出は意図的に狭く、null を返しうる呼び出しの直後に連ねた形しか追っていません。いったんローカル変数へ代入すると、そこで追跡が切れます。コンポーネントの取得や実行環境から取る値は、結果の内容にかかわらず自分で確認してくださいexternDb.resolvedが偽のときは、未知の API と未知の型の検査が実行されていません。この状態では、データベースを参照できないせいでエラーになっている形が混ざります- 重大度が
infoの診断は止める理由になりません。compilesが真でも出ます
decompile
Section titled “decompile”コンパイルされた Udon のアセンブリを、C# に似た読める形にします。すでにワールドに置かれているプログラムの確認に使い、引数は 2 つです。
| 引数 | 内容 |
|---|---|
uasm | アセンブリのテキスト |
file | アセンブリファイルのパス。uasm を省略したときだけ読まれます |
{ "schemaVersion": 1, "file": "Lamp.uasm", "source": "public class Lamp\n{\n ...\n}", "fidelity": { "isOriginalSource": false, "isCompileChecked": false, "receiverIsInferred": true, "note": "This is a readable rendering of the assembly you passed in. ..." }, "externDb": { "resolved": true, "externCount": 32898 }, "warnings": [], "facts": { "heap": { "slots": 11, "limit": 1048576, "remaining": 1048565 }, "cost": { "instructionCount": 42, "staticExternCount": 6, "nsPerExtern": 77, "nsPerNonExtern": 5.4 }, "entries": ["_interact"], "externs": ["UnityEngineGameObject.__SetActive__SystemBoolean__SystemVoid"], "loopCount": 0 }}| キー | 読み方 |
|---|---|
source | 可読化した結果です。元のソースではありません。ローカル変数名・クラス名・ブロック構造は、アセンブリだけから再構成したものです(アセンブリはそれらを持っていません) |
fidelity | このツールの出力の性質を示す固定値です。入力ごとに判定するものではなく、常に同じ値です。source より先に読みます |
externDb | 呼び出しの受け手を、データベースを参照して決めたか、周囲の命令列から推定したかが分かります。推定は間違うことがあり、間違った結果は普通のコードに見えます |
warnings | 結果が信用できない箇所です。receiverNotResolved は、ドットの左側に置いた式がその呼び出しのレシーバとして成立しないもの、notRaisedToStatements は、スタックの操作のまま残した行です。空でも、すべてが正しく出たという意味にはなりません |
facts | 渡したアセンブリから測った値です。heap は inspect と同じ数え方で、cost は命令数と静的な外部呼び出しの数です |
facts.entries | アセンブリに定義されたエントリポイントの名前です。inspect の同じキーが C# の名前(Interact)を返すのに対し、こちらは実行環境が呼ぶ名前(_interact)を返します |
facts.cost.isStraightLine | ありません。アセンブリからはループが見えても再帰は見えないため、loopCount が数えるのは後ろ向きのジャンプだけです |
| 自分で書いたソース | inspect を使います。このツールの出力を inspect にかけ直す使い方は想定していません |
profile
Section titled “profile”| 返すもの | Unity で開いているシーンに置いたプログラムごとの命令と extern の数です。数は Unity が Library/Tsukimi/profile.json に書いた物で、このツールは数え直しません |
| 書かれる時点 | メニューの TsukimiCode > Tsukimi Profiler を選んだときと、保存した TsukimiSharp のスクリプトを Unity がコンパイルし終えたときです(プロファイラ) |
| 引数 | program だけです。プログラムの名前(programs[].name)を渡すと、その 1 本だけを返します。省略するとシーンの全部を返します |
| ファイルが無いとき | isError: true で、メニューを選ぶかスクリプトを保存するよう案内する文が返ります |
{ "schemaVersion": 1, "writtenAt": "2026-10-11T08:12:34.5678901Z", "scene": "SampleScene", "tsukimiVersion": "0.9.0", "programs": [ { "name": "ReactiveLamp", "asset": "Assets/ReactiveLamp.asset", "tsukimiSharp": true, "placed": 3, "instructions": 395, "externs": 45, "codeSizeBytes": 2944, "syncedCount": 0, "events": [ { "name": "_interact", "instructions": 129, "externs": 15, "perFrame": false, "measuredExterns": 7 }, { "name": "_start", "instructions": 49, "externs": 7, "perFrame": false, "measuredExterns": 4 } ], "stale": false } ]}| キー | 読み方 |
|---|---|
writtenAt・scene・tsukimiVersion | 要約を書いた時刻と、そのとき開いていたシーンと、パッケージの版です |
placed | シーンの中で、そのプログラムを使っている UdonBehaviour の数です |
instructions・externs | プログラム全体の命令と extern の数です。数え方は プロファイラ と同じです |
events[].instructions・events[].externs | そのエントリポイントから届く命令と extern の数です。呼び出したメソッドの本体は含みません |
events[].perFrame | 毎フレーム実行されるイベントかどうかです |
events[].measuredExterns | TsukimiSharp のプログラムだけに入ります。フィールドが既定値のままの状態でそのエントリポイントを 1 回実行したときに呼んだ extern の回数で、呼び出したメソッドの中で呼んだ回数も含みます。既定値では条件の早期 return を通ることが多いので、実際に遊んだときの回数ではありません |
events[].notMeasured | 実行できなかったエントリポイントに、数の代わりに理由が入ります |
stale | TsukimiSharp のプログラムだけに入ります。true は、数えた後でディスクのアセットが別のプログラムに変わったことを示します。メニューを選び直すと数え直されます |
| 数の単位 | どの数も回数であって、時間ではありません。Play 中の値も入りません |
ping を呼ぶと、次の 1 行が返ります。
"tsukimi-mcp ok (version x.y.z; static-analysis MCP; liveness check)"クライアント側にも、接続しているサーバの一覧があります。

| 見えるツール | 7 つ(ping・inspect・test・diagnostics・spec・decompile・profile) |
| 1 つも見えないとき | 設定を書き込む前にクライアントを起動したか、プロジェクトの外で起動しています |
データベースの確認
Section titled “データベースの確認”短いソースを 1 つ inspect にかけると、externDb が返ります。
"externDb": { "resolved": true, "unknownApiChecks": true, "externCount": 32898 }resolved | 真なら参照できています。偽の間は、実在する API も未知として報告されます |
| 偽になる条件 | Unity でこのプロジェクトをまだ一度も開いていないときです |
externCount | 参照できた API の数。導入した SDK の版で変わるので、手元の値が上と違っていても構いません |
併用をおすすめする MCP サーバ
Section titled “併用をおすすめする MCP サーバ”シーンへの配置・Inspector での参照の割り当て・Play モードでの確認はこのサーバの対象外で、これらも AI に操作させたい場合は、Unity エディタを外部から操作する MCP サーバを併用します。
この種のサーバは第三者が公開しているもので、このパッケージには含まれません(MCP for Unity の場合は、Unity の Package Manager の Add package from git URL に次のアドレスを入力します)。
https://github.com/CoplayDev/unity-mcp.git?path=/MCPForUnity#mainうまくいかない場合
Section titled “うまくいかない場合”| 症状 | 原因 | 対処 |
|---|---|---|
| メニューに TsukimiCode が出ない | パッケージが入っていないか、プロジェクトのコンパイルが通っていない | Unity のコンソールを読む。コンパイルエラーが出ていれば、そちらが先 |
| クライアントに tsukimi のツールが出ない | 設定の前に起動していたか、プロジェクトの外で起動している | プロジェクトの直下で再起動する。ウィンドウで該当クライアントのマークが ✓ になっているかを見る |
| 主ボタンを押したのに変わらない | 起動中のクライアントは、設定を起動時にしか読まない | クライアントを再起動する |
| 主ボタンを押したのに AI が手順書を知らない | インストールした Skill も、クライアントは起動時にしか読まない | クライアントを再起動する |
| AI が Skill を参照せずにコードを書いている | Skill がクライアントに読み込まれていない | ウィンドウの Skill の行が up to date かを確認し、主ボタンを押してから再起動する |
| Codex CLI だけ接続できない | プロジェクトが信頼されていない | そのクライアントの手順で信頼させてから、再起動する |
| GitHub Copilot CLI だけ接続できない | 設定のサーバの経路がプロジェクトからの相対パスで、別のフォルダで起動している | プロジェクトのフォルダで起動し直す |
| パッケージの更新後に接続できない | 設定に書かれたサーバの場所が更新で変わり、自動の書き直しが実行されていない(ウィンドウで Skill をインストールした記録が無いプロジェクトでは実行されない) | ウィンドウを開き、! の付いた行があれば主ボタンを押して、クライアントを再起動する |
| 0.8.1 から上げたら Configure・Install Skill・Install Check のボタンが無い | 0.9.0 でウィンドウを作り直し、1 つの主ボタンにまとめた。0.8.1 でインストールした Skill には記録が無く、自動の書き直しの対象にならない | 使うクライアントにチェックを付けて主ボタンを 1 回押す(同名のファイルの確認が出たら Replace)。次の更新からは自動で書き直される |
| clone した先でサーバが起動しない | 0.8.1 のウィンドウは設定に絶対パスを書いていた。元のプロジェクトでは今のサーバとプロジェクトを指すので ✓ と出て、自動の書き直しの対象にもならない | 元のプロジェクトで主ボタン(全部 ✓ なら Set Up Again)を押すと、相対パスか ${workspaceFolder} で書き直す。Visual Studio・Gemini CLI・Codex CLI は絶対パスのまま |
パッケージの更新後、ツールが The TsukimiSharp package was updated after this MCP server started … を返す | クライアントが、更新の前に起動したサーバを動かしたまま。サーバは自分のファイルが更新されたことを検出すると、古いファイルと新しいファイルを混ぜて実行しないように、ツールを実行せずにこの文を返す | クライアントを再起動するか、クライアントで MCP サーバを接続し直す。コードやツールの不具合ではない |
パッケージの更新後、ツールが Method not found などのエラーで失敗する | 更新の前に起動したサーバが 0.9.0 以前の版で、更新を検出しない | クライアントを再起動するか、クライアントで MCP サーバを接続し直す |
| Server の行が not found | 同梱のサーバ DLL が見つからない。主ボタンも押せない | パッケージを導入し直す |
| 実在するはずの API が無いと言われ続ける | 実行環境の API のデータベースが生成されていない | Unity でこのプロジェクトを一度開く。externDb.resolved が偽の間はこの状態 |
| 完了時の検査が動作しているか分からない | コンパイルできたときは何も出ない | ウィンドウの最下段の Last check を見る。Final check の行が out of date なら、Claude Code にチェックを付けて主ボタンを押す |
| AI がファイルを置いたのに Unity で何も起きない | Unity は、フォーカスが戻るまで外で置かれたファイルをインポートしない | Unity のウィンドウを 1 度クリックする |
| シーンで触っても何も起きない | Inspector の参照が空 | UdonBehaviour の欄に割り当てる。Udon には例外処理がないので、ログには何も出ない |
どの行の対処でも解決しないときは、ウィンドウの Refresh を押してマークを上から順に確認し、最初に ✓ でない行から対処してください。