ResoniteLink MCP
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ResoniteLink MCPadd a red box at position 0, 1, 0"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ResoniteLink MCP
ResoniteLink WebSocket プロトコルを使用して Resonite VR ワールドを操作するための MCP サーバ & CLI ツール。
インストール
npm install
npm run buildRelated MCP server: Minecraft Bedrock Education MCP
MCP サーバとして使用
Claude Code 設定
プロジェクトルートの .mcp.json に設定済み。Claude Code を再起動すると自動的にMCPサーバーが利用可能になります。
Claude Desktop 設定
claude_desktop_config.json に以下を追加:
{
"mcpServers": {
"resonitelink": {
"command": "node",
"args": ["C:/Users/neo/GitHub/resolink_mcp/dist/mcp-server.js"],
"env": {
"RESONITE_WS_URL": "ws://localhost:29551"
}
}
}
}利用可能なツール
ツール | 説明 |
| Resonite に接続 |
| 接続を切断 |
| スロット情報を取得 |
| 名前でスロットを検索 |
| スロットを追加 |
| スロットを削除 |
| スロットを更新 |
| コンポーネントを追加 |
| コンポーネント情報を取得 |
| コンポーネントを更新 |
| コンポーネントを削除 |
| テクスチャをファイルからインポート |
| コンポーネントを検索 |
| コンポーネント詳細を取得 |
| カテゴリ一覧 |
| カテゴリで検索 |
| メンバー名で検索 |
| ソースコードを取得 |
| ソースを全文検索 |
CLI として使用
WebSocket URL の指定方法
CLI は WebSocket URL を以下の優先順位で決定します:
コマンドライン引数
--url(最優先)環境変数
RESONITELINK_URLデフォルト値:
ws://localhost:29551
環境変数で設定する例:
# Windows (PowerShell)
$env:RESONITELINK_URL = "ws://localhost:29469"
# Windows (コマンドプロンプト)
set RESONITELINK_URL=ws://localhost:29469
# Linux/Mac
export RESONITELINK_URL=ws://localhost:29469環境変数を設定すれば、毎回 --url オプションを指定する必要がなくなります。
基本的なコマンド
# Rootスロット情報を取得
node dist/cli.js root --depth 1
# 特定のスロット情報を取得
node dist/cli.js get-slot --id <slotId> --depth 1
# コンポーネント情報も含めて取得
node dist/cli.js get-slot --id <slotId> --components
# 名前でスロットを検索
node dist/cli.js find --name MyObject
# スロットを追加
node dist/cli.js add-slot --name NewSlot --position 0,1,0
# 親スロットを指定してスロットを追加
node dist/cli.js add-slot --parent <parentId> --name MySlot --position 0,1,0 --scale 1,1,1
# コンポーネントを追加
node dist/cli.js add-component --slot <slotId> --type "[FrooxEngine]FrooxEngine.BoxMesh"
# スロットを更新
node dist/cli.js update-slot --id <slotId> --name NewName --position 0,2,0
# スロットを削除
node dist/cli.js remove-slot --id <slotId>
# コンポーネントを取得
node dist/cli.js get-component --id <componentId>
# コンポーネントを削除
node dist/cli.js remove-component --id <componentId>
# スロット階層をツリー表示
node dist/cli.js tree --depth 3
# WebSocket URLを指定(異なるポートの場合)
node dist/cli.js root --url ws://localhost:9422 --depth 2ライブラリとして使用
import { ResoniteLinkClient } from './src/index.js';
const client = new ResoniteLinkClient({ url: 'ws://localhost:29551' });
await client.connect();
// スロットを追加
await client.addSlot({ name: 'MyObject', position: { x: 0, y: 1, z: 0 } });
// コンポーネントを追加
await client.addComponent({
containerSlotId: slotId,
componentType: '[FrooxEngine]FrooxEngine.BoxMesh'
});
client.disconnect();クライアントオプション
const client = new ResoniteLinkClient({
url: 'ws://localhost:29551', // WebSocket URL(必須)
debug: true, // コンソールにログ出力
logFile: 'debug.log', // ファイルにログ出力
requestTimeout: 30000, // リクエストタイムアウト(ミリ秒、デフォルト: 30000)
autoReconnect: false, // 自動再接続
reconnectInterval: 5000, // 再接続間隔(ミリ秒)
});デバッグログ
問題が発生した場合、デバッグログを有効にすると SEND/RECV メッセージを確認できます:
const client = new ResoniteLinkClient({
url: 'ws://localhost:29551',
debug: true, // コンソール出力
logFile: 'debug.log', // ファイル出力
});ログ例:
[2026-01-08T06:10:24.504Z] SEND: { "$type": "addSlot", "messageId": "..." }
[2026-01-08T06:10:24.506Z] RECV: { "success": true, "messageId": "...", "error": null }リクエストタイムアウト
レスポンスが返らない場合(不正な形式のデータ送信時など)、タイムアウトでエラーが発生します:
const client = new ResoniteLinkClient({
url: 'ws://localhost:29551',
requestTimeout: 10000, // 10秒でタイムアウト
});タイムアウト発生時は Error: Request timeout after 10000ms: updateComponent (...) のようなエラーがスローされます。
テクスチャインポート
ResoniteLink のアセットインポートAPIを使用して、テクスチャをインポートできます。
ファイルからインポート
// Resoniteホストのローカルファイルからテクスチャをインポート
const result = await client.importTexture2DFile({
filePath: 'C:/path/to/texture.png'
});
if (result.success) {
console.log('Asset URL:', result.assetURL);
// assetURL を StaticTexture2D などに設定可能
}生データからインポート
// RGBAピクセルデータからテクスチャをインポート
const width = 256;
const height = 256;
const rawData = Buffer.alloc(width * height * 4); // RGBA, 4 bytes per pixel
// ピクセルデータを生成(例: グラデーション)
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const offset = (y * width + x) * 4;
rawData[offset] = x; // R
rawData[offset + 1] = y; // G
rawData[offset + 2] = 128; // B
rawData[offset + 3] = 255; // A
}
}
const result = await client.importTexture2DRawData({
width,
height,
colorProfile: 'sRGB', // 'sRGB' または 'Linear'
rawData
});
if (result.success) {
console.log('Asset URL:', result.assetURL);
}注意事項
filePathは Resonite が動作しているホストのローカルパスassetURLはセッション内でのみ有効(一時的なURL)サポートされる形式: PNG, JPG など一般的な画像形式
生データは RGBA フォーマット(1ピクセル4バイト)
重要: ワールドシステムオブジェクト
Resonite ワールドの Root 以下には、削除してはいけないシステムオブジェクトがあります。
削除禁止オブジェクト
オブジェクト名 | 説明 |
| コントローラー入力システム |
| ユーザーロール管理 |
| ユーザーのスポーン位置 |
| ワールドの照明 |
| 空・背景 |
| 接続中のユーザー(削除するとキックされる) |
| 一時オブジェクト管理 |
| アンドゥ履歴 |
| 共有アセット |
| クリップボードインポート機能 |
安全な削除方法
const SYSTEM_OBJECTS = [
'Controllers', 'Roles', 'SpawnArea', 'Light', 'Skybox',
'__TEMP', 'Undo Manager', 'Assets', 'Clipboard Importer'
];
// システムオブジェクトとUserはスキップ
if (SYSTEM_OBJECTS.includes(name) || name.startsWith('User ')) {
continue;
}コンポーネントタイプの書式
[FrooxEngine]FrooxEngine.ComponentNameよく使うコンポーネント
コンポーネント | 用途 |
| 直方体メッシュ |
| 球体メッシュ |
| 円柱メッシュ |
| 円錐メッシュ |
| 角丸直方体 |
| スロープ |
| フレーム |
| トーラス |
| カプセル |
| メッシュ描画 |
| PBRマテリアル |
| ライト |
マテリアルの設定例
await client.updateComponent({
id: materialId,
members: {
AlbedoColor: { $type: 'colorX', value: { r: 1, g: 0, b: 0, a: 1, profile: 'sRGB' } },
Smoothness: { $type: 'float', value: 0.5 },
Metallic: { $type: 'float', value: 0.2 },
}
});Enum型の設定(BlendMode, LightType など)
Enum 型のメンバーを更新する場合、以下の形式を使用する必要があります:
{
$type: 'enum', // 小文字の 'enum'
value: 'Alpha', // 文字列で値を指定(数値ではない)
enumType: 'BlendMode' // Enum の型名
}BlendMode の値
値 | 説明 |
| 不透明(デフォルト) |
| カットアウト(アルファテスト) |
| 半透明(アルファブレンド) |
半透明マテリアルの例
await client.updateComponent({
id: materialId,
members: {
BlendMode: { $type: 'enum', value: 'Alpha', enumType: 'BlendMode' },
AlbedoColor: { $type: 'colorX', value: { r: 0.6, g: 0.75, b: 0.9, a: 0.3, profile: 'sRGB' } },
}
});LightType の値
値 | 説明 |
| ディレクショナルライト |
| ポイントライト |
| スポットライト |
await client.updateComponent({
id: lightId,
members: {
LightType: { $type: 'enum', value: 'Point', enumType: 'LightType' },
Intensity: { $type: 'float', value: 2.0 },
Range: { $type: 'float', value: 10.0 },
}
});注意事項
$typeは必ず小文字の'enum'('Enum'ではない)valueは数値ではなく文字列で指定enumTypeを省略すると動作しない場合がある正しくない形式を送信するとレスポンスが返らずタイムアウトする
メンバーの型一覧
$type | 説明 | 例 |
| 浮動小数点 |
|
| 整数 |
|
| 真偽値 |
|
| 2Dベクトル |
|
| 3Dベクトル |
|
| クォータニオン |
|
| 色 |
|
| 列挙型 |
|
| 参照 |
|
| リスト |
|
| 出力メンバー |
|
empty 型(ProtoFlux 出力メンバー)
ResoniteLink の更新により、ProtoFlux ノードの出力メンバーが $type: "empty" として返されるようになりました。
背景
ProtoFlux ノードには入力(SyncRef)と出力(NodeValueOutput)があります:
入力: 値を受け取る(reference型で返される)
出力: 値を出力する(以前は返されなかった → 今は empty 型で返される)
例: GlobalTransform ノード
{
"componentType": "...GlobalTransform",
"members": {
"Instance": { "$type": "reference", "targetId": null, ... },
"GlobalPosition": { "$type": "empty", "id": "Reso_82E" },
"GlobalRotation": { "$type": "empty", "id": "Reso_82F" },
"GlobalScale": { "$type": "empty", "id": "Reso_830" }
}
}出力メンバーの参照方法
出力メンバーの id を使って、他のノードの入力に接続できます:
// GlobalTransform の GlobalPosition 出力を取得
const globalTransformComp = slotData.data?.components?.find(c =>
c.componentType?.includes('GlobalTransform')
);
const globalPositionId = globalTransformComp.members.GlobalPosition.id; // "Reso_82E"
// ValueSub の A 入力に GlobalPosition を接続
await client.updateComponent({
id: subComp.id,
members: {
A: { $type: 'reference', targetId: globalPositionId }, // 出力IDを直接参照!
}
});以前との違い
項目 | 以前 | 現在 |
出力メンバー | JSONに含まれない |
|
複数出力ノードの参照 | コンポーネントID全体を参照 → エラー | 出力IDを個別に参照 → 成功 |
これにより、GlobalTransform のような複数出力を持つノードも正しく接続できるようになりました。
Materials リストの更新(2段階)
MeshRenderer の Materials リストを更新するには2段階の操作が必要です。
なぜ2段階必要か
ResoniteLink の制限により、リスト要素への参照設定は以下の動作をします:
1回目の更新: リストに新しい要素が追加されるが、
targetIdは null になる2回目の更新: 要素の
idを指定することで、既存要素のtargetIdを設定できる
つまり、要素の追加と参照の設定は別々の操作として行う必要があります。
コード例
// 1. まずリストに要素を追加(この時点では targetId は null になる)
await client.updateComponent({
id: rendererId,
members: {
Materials: {
$type: 'list',
elements: [{ $type: 'reference', targetId: materialId }]
}
}
});
// 2. 追加された要素のIDを取得
const rendererData = await client.getComponent(rendererId);
const elementId = rendererData.data.members.Materials.elements[0].id;
// 3. 要素のIDを指定して、参照を設定
await client.updateComponent({
id: rendererId,
members: {
Materials: {
$type: 'list',
elements: [{ $type: 'reference', id: elementId, targetId: materialId }]
}
}
});重要なポイント
idフィールドを省略すると、新しい要素が追加される(既存要素は更新されない)idフィールドを指定すると、その ID を持つ既存要素が更新される1回目で
targetIdを指定しても無視され、null になる
ProtoFlux コンポーネントの追加
ProtoFlux ノード(ジェネリック型コンポーネント)を追加するには、特定の形式が必要です。
正しい形式
[ProtoFluxBindings]FrooxEngine.FrooxEngine.ProtoFlux.CoreNodes.<コンポーネント名><型>ポイント
項目 | 正しい形式 | 間違った形式 |
アセンブリ名 |
|
|
名前空間 |
|
|
ジェネリック型 |
|
|
名前空間:
FrooxEngineが2回繰り返される型指定: C# エイリアス(
bool,int,float)を使用する(System.Booleanではない)記法:
<>形式を使用する(.NET のバッククォート記法`1[...]ではない)
複合型パラメータ(Slot, User など)
スロットやユーザーなどの複合型を型パラメータに使う場合は、アセンブリ名付きの完全修飾名を使用する:
[ProtoFluxBindings]...RefObjectInput<[FrooxEngine]FrooxEngine.Slot>型 | 正しい形式 | 間違った形式 |
Slot |
|
|
User |
|
|
IButton |
|
|
重要: プリミティブ型(int, float, bool など)はエイリアスをそのまま使い、複合型(Slot, User など)は [FrooxEngine]FrooxEngine.TypeName 形式を使う。
動作確認済みコンポーネント
ノード | componentType |
ValueInput<int> |
|
ValueAdd<int> |
|
ValueDisplay<int> |
|
WorldTimeFloat |
|
AxisAngle_floatQ |
|
HSV_ToColorX |
|
ValueFieldDrive<floatQ> |
|
ValueFieldDrive<colorX> |
|
ValueFieldDrive<bool> |
|
コード例
// ValueFieldDrive<floatQ> を追加(回転ドライブ用)
await client.addComponent({
containerSlotId: slotId,
componentType: '[ProtoFluxBindings]FrooxEngine.FrooxEngine.ProtoFlux.CoreNodes.ValueFieldDrive<floatQ>'
});
// WorldTimeFloat を追加(時間取得用)
await client.addComponent({
containerSlotId: slotId,
componentType: '[ProtoFluxBindings]FrooxEngine.ProtoFlux.Runtimes.Execution.Nodes.FrooxEngine.Time.WorldTimeFloat'
});
// HSV_ToColorX を追加(色変換用)
await client.addComponent({
containerSlotId: slotId,
componentType: '[ProtoFluxBindings]FrooxEngine.ProtoFlux.Runtimes.Execution.Nodes.Color.HSV_ToColorX'
});ProtoFlux ノード間の接続
// ValueAdd の A, B 入力に ValueInput ノードを接続
await client.updateComponent({
id: addCompId,
members: {
A: { $type: 'reference', targetId: input1CompId },
B: { $type: 'reference', targetId: input2CompId },
}
});
// ValueDisplay の Input に ValueAdd の出力を接続
await client.updateComponent({
id: displayCompId,
members: {
Input: { $type: 'reference', targetId: addCompId },
}
});よく使う ProtoFlux ノード
コンポーネント | 用途 |
| フィールドをドライブ |
| 参照フィールドをドライブ |
| グローバル値 |
| グローバル参照 |
ProtoFlux ノードの配置
ProtoFlux ノードを追加する際は、各ノードを別々のスロットに配置し、適切な位置に並べることで視認性が向上します。
座標系
Resonite の座標系:
X軸: 左右(右が正)
Y軸: 上下(上が正)
Z軸: 前後(手前が正)
ProtoFlux ノードは**左から右(X軸方向)**に配置するのが一般的です。
配置の基本パターン
左 ────────────────────────────────────────────→ 右 (X軸)
[入力ノード群] → [処理ノード] → [出力ノード] → [ドライブノード]
x=-1.5 x=-1.0 x=-0.5 x=0複数入力がある場合
Y軸で上下にずらして配置:
// 入力1(上側)
await client.addSlot({ name: 'Input1', position: { x: -1.5, y: 0.15, z: 0 } });
// 入力2(下側)
await client.addSlot({ name: 'Input2', position: { x: -1.5, y: -0.15, z: 0 } });
// 処理ノード(中央)
await client.addSlot({ name: 'Process', position: { x: -1.0, y: 0, z: 0 } });実践例: 回転するボックス
// 親スロット
const fluxSlot = await client.addSlot({ name: 'Flux', position: { x: 0, y: 2, z: 0 } });
// 各ノードを左から右に配置
const nodes = [
{ name: 'AxisInput', x: -0.6, y: 0.15 }, // 回転軸入力
{ name: 'TimeNode', x: -0.6, y: -0.15 }, // 時間取得
{ name: 'AxisAngleNode', x: -0.3, y: 0 }, // 軸角度→クォータニオン変換
{ name: 'DriveNode', x: 0, y: 0 }, // 回転ドライブ
];
for (const node of nodes) {
await client.addSlot({
name: node.name,
parentId: fluxSlot.data.id,
position: { x: node.x, y: node.y, z: 0 }
});
}配置のコツ
項目 | 推奨値 |
ノード間の水平間隔 | 0.3〜0.5 |
分岐時の垂直間隔 | 0.15〜0.3 |
親スロットからの相対座標 | 使用する |
親スロット(例:
Flux)を作成し、その下に各ノードを配置位置は親スロットからの相対座標になる
データフローが左から右に流れるように配置
分岐がある場合は Y軸で上下にずらす
制限事項
一部の ProtoFlux ノードは追加できない場合があります:
複雑なジェネリック制約を持つノード
特殊な初期化が必要なノード
回避策:
Resonite 内で手動で ProtoFlux を作成
既存の ProtoFlux をテンプレートとして複製
PackedObject として保存したものをインポート
デコンパイル検索 (CLI)
# コンポーネント名で検索
node dist/cli.js search --query Mesh
# コンポーネント詳細を表示
node dist/cli.js info --name PBS_Metallic
# カテゴリ一覧
node dist/cli.js categories
# カテゴリで検索
node dist/cli.js category --query "Materials"
# メンバー名で検索
node dist/cli.js member --query Smoothness
# ソースコード全文検索
node dist/cli.js grep --query "SyncPlayback"
# ソースコード表示
node dist/cli.js source --name BoxMeshサンプルスクリプト
# ProtoFlux 1+1 を作成(ValueInput → ValueAdd → ValueDisplay)
node dist/scripts/create-flux-add.js ws://localhost:58971
# 東京タワー(詳細版)を作成
node dist/scripts/create-tokyo-tower-detailed.js ws://localhost:58971
# 東京スカイツリーを作成
node dist/scripts/create-skytree.js ws://localhost:58971
# 東京タワーを削除
node dist/scripts/delete-tokyo-tower.js ws://localhost:58971
# モダンハウス(内装付き)を作成
node dist/scripts/create-house3.js
# 街を作成
node dist/scripts/create-town.js
# 雲を作成
node dist/scripts/create-clouds.js
# すべて削除して床だけにする
node dist/scripts/reset-to-floor.jsLicense
MIT
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- -license-quality-maintenanceEnables AI agents to create and modify Unreal Engine blueprints using natural language commands. Supports blueprint creation, property modification, and real-time communication with Unreal Editor through WebSocket integration.Last updated
- Alicense-qualityDmaintenanceEnables controlling Minecraft Bedrock and Education Edition through natural language commands via WebSocket connection. Provides tools for player actions, world manipulation, building structures, camera control, and wiki integration for automated gameplay and educational scenarios.Last updated13MIT
- FlicenseBquality-maintenanceEnables AI assistants to interact with running Roblox game instances by inspecting the game hierarchy, reading client-side scripts, and executing Lua code directly within the Roblox client through a WebSocket bridge.Last updated439
- AlicenseAquality-maintenanceEnables AI agents to fully control the Forge Engine (Godot fork) by manipulating scene trees, modifying node properties, and managing game scripts. It allows agents to perform development tasks such as running projects, capturing screenshots, and executing GDScript through a WebSocket connection.Last updated21
Related MCP Connectors
Control Unreal Engine to browse assets, import content, and manage levels and sequences. Automate…
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to control Unreal E…
Build, deploy, and operate hosted web apps on VibeKit (vibekit.bot) from any MCP client.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/rassi0429/resolink-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server