WASMコンポーネントを作成しMCPサーバから呼び出してみる
TL;DR
- 以下の構成でMCPサーバとしてWassetteを活用し、WASMコンポーネントをGithub Copilotから使ってみます。
- 呼び出すWASMコンポーネントも作ってみます。
Wassette とは? WASM × MCP がもたらす強力なセキュリティ
Wassetteは、WebAssembly (Wasm) を活用し、信頼できないツールに信頼できる実行環境を提供する、オープンソースのMCPサーバです。
WebAssemblyランタイムを組み込み、きめ細かなセキュリティポリシーを適用することで、Wassetteはホストシステムに悪影響を与えることなく、サードパーティ製のMCPツールを安全に実行できます。
生殺与奪の権をAgentに握らせるな!
事前準備
すでにインストールされていたらスキップで大丈夫です。
rustup target add wasm32-wasip1
cargo install cargo-component --locked
cargo install wkg
手順
コンポーネント作成
今回は文字数をカウントするToolとしてcharcountを作成します。
cargo component new --lib charcount
WITおよびコンポーネントのロジックの定義
まずはWITでWasmコンポーネントのインターフェースを定義します
package tools:charcount@0.1.0;
interface counter {
/// Return the number of Unicode scalar values in the string.
count: func(text: string) -> u32;
}
world component {
export counter;
}
今回はシンプルな文字数カウンタを作成します
#[allow(warnings)]
mod bindings;
use bindings::exports::tools::charcount::counter::Guest;
struct Component;
impl Guest for Component {
fn count(text: String) -> u32 {
// Unicodeスカラ値(.chars())の個数を返す
text.chars().count() as u32
}
}
bindings::export!(Component with_types_in bindings);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ascii() { assert_eq!(Component::count("Hello".into()), 5); }
#[test]
fn jp() { assert_eq!(Component::count("こんにちは".into()), 5); }
#[test]
fn emoji() { assert_eq!(Component::count("👍".into()), 1); } // 絵文字は1カウント
}
Buildします
cargo component check
cargo component build --release
Generating bindings for charcount (src/bindings.rs)
Compiling wit-bindgen-rt v0.44.0
Compiling bitflags v2.9.4
Compiling charcount v0.1.0
Finished `release` profile [optimized] target(s) in 1.96s
Creating component target/wasm32-wasip1/release/charcount.wasm
charcount.wasmが生成されました!
作成したwasmコンポーネントをghcr.ioにpush
まずはGithubにてPATを作成します。
write:packages権限が付与されてることを確認してください。

その後作成したPATとusernameでdocker loginします。
echo YOUR_GITHUB_PAT | docker login ghcr.io -u YOUR_GITHUB_USERNAME --password-stdin
ghcr.ioにpushします!
wkg oci push ghcr.io/<YOUR_GITHUB_USERNAME>/charcount:0.1.0 target/wasm32-wasip1/release/charcount.wasm
pushed: ghcr.io/<YOUR_GITHUB_USERNAME>/charcount:0.1.0
digest: sha256:458ad93f9914d56a10971ab5948640e095a7a5bcb2d2a782e2627dce8cc5f3f9
PushしたPackageを確認
確認できたら、wassetteから読み込めるようにPackage settings -> Change package visibility -> Publicにします。

Publicになりました。

Copilotからwassetteを使ってWASMコンポーネントを呼び出す
VScodeでCopilotを開き、以下に設定します
-
Agentモードになっている - Tool🛠️ -> MCPサーバとして
wassetteにチェック
CopilotのチャットでまずはWASMコンポーネントをロードします。以下で指示してみます。
以下をロードして
oci://ghcr.io/<YOUR_GITHUB_USERNAME>/charcount:0.1.0

確認されるのでContinueをクリックします。
ロードできました。

続いて、以下を聞いてみます。
次の文字列の文字数を教えて
"hello wasm mcp"
先ほど同様Continueをクリックすると、Toolとして作成した文字数カウンタのWASMコンポーネントcharcountを使って答えが返ってきました!

Wassetteの機能の補足
- ファイルシステムやネットワークエンドポイントに対し厳密にポリシーを定義し、機能ベースのセキュリティを適用できます。
version: "1.0"
description: "An example policy"
permissions:
storage:
allow:
- uri: "fs://workspace/**"
access: ["read", "write"]
- uri: "fs://config/app.yaml"
access: ["read"]
network:
allow:
- host: "api.openai.com"
- TL;DRに簡易的な構成を示しましたが、正確には以下のようなシーケンスで動いているようです。
まとめ
個人レベルでAgentを使う場合にはそこまで気にならないセキュリティですが、規模が大きくなると気にしていかなければならないポイントだと思ってます。
WASM × MCP に期待してます!
Discussion