What is Wassette?

Overview

Wassette is a secure, open-source Model Context Protocol (MCP) server that leverages WebAssembly (Wasm) to provide a trusted execution environment for untrusted tools. MCP is a standard how LLMs access and share data with external tools. By embedding a WebAssembly runtime and applying fine-grained security policies, Wassette enables safe execution of third-party MCP tools without compromising the host system.

Key Features

Wassette provides the following key features:

  • Sandboxed tools using the WebAssembly Component Model
  • Fine-grained permissions for file system, network, and system resources
  • Developer-friendly approach that simplifies tool development by focusing on business logic rather than infrastructure complexity

Note: The name “Wassette” is a portmanteau of “Wasm” and “Cassette” (referring to magnetic tape storage), and is pronounced “Wass-ette”.

Problem Statement

The current landscape of MCP server deployment presents significant security challenges. Today’s common deployment patterns include standalone processes communicating via stdio or sockets, direct binary execution using package managers like npx or uvx, and container-based isolation providing basic security boundaries.

These approaches expose users to various security risks including unrestricted file system access where tools can read and write arbitrary files, network vulnerabilities through uncontrolled outbound connections to external services, code execution risks from malicious or vulnerable tools, and limited visibility making it difficult to monitor and audit tool behavior.

The fundamental issue is that current MCP servers run with the same privileges as the host process, creating an unacceptable attack surface for untrusted code execution.

Target Audience

Wassette serves four primary user groups:

  • Application Developers who want to focus on business logic implementation with reduced infrastructure complexity and simplified deployment
  • DevOps Engineers who benefit from platform-agnostic deployment capabilities, comprehensive observability and monitoring, and security-by-design architecture
  • End Users who gain a trusted execution environment for third-party tools with transparent security policies and protection against malicious or vulnerable tools
  • Platform Providers who can leverage Wassette’s serverless-ready architecture, consistent runtime environment, and scalable multi-tenant capabilities

Current Solutions Analysis

  1. Container-based isolation. This is perhaps the most common way to run MCP servers securely today, because it works with existing tooling and infrastructure and requires no changes to the server code. One could argue that containers are not a secure boundary, but they are a good starting point. The harder problem is how to apply security policies to the container like “how do I know what HTTP domain is this tool calling to?”. The Docker MCP Catalog runs each MCP server as a container - providing isolation and portability.
  2. Direct binary execution. Running binaries directly using npx or uvx. This is a simple way to run MCP servers (and often the default way MCP servers document how to use it), but it is not secure. It is easy to run a tool that has a vulnerability or malicious code that can read/write files on your machine, open sockets, or even execute arbitrary code.
  3. WebAssembly platforms. Centralized MCP server that runs WebAssembly-based tools locally (think tools like mcp.run). This has the advantage of running tools in tiny sandboxes which incur less memory overhead than containers. However, most of these tools still require custom ABIs and libraries and are not compatible with each other.

Wassette Solution

Design Philosophy

Wassette addresses the security and interoperability challenges of current MCP deployments by leveraging the WebAssembly Component Model. This approach provides strong security boundaries through WebAssembly’s sandboxed execution environment, capability-based access control with fine-grained permission management, tool interoperability via standardized component interfaces, transparent security through explicit capability declarations, and low resource overhead with efficient memory usage compared to containers.

Architecture Goals

Wassette implements a centralized trusted computing base (TCB) through a single, open-source MCP server implementation built with memory-safe, high-performance runtimes like Wasmtime, maintaining a minimal attack surface through reduced complexity.

The system enforces capability-based security with allow/deny lists for file system paths, network endpoint access control, system call restrictions, and a policy engine similar to policy-mcp-rs.

For secure distribution, WebAssembly components are distributed as OCI artifacts with cryptographic signature verification, registry-based tool distribution, and granular capability declarations per tool.

Example Permission Policy

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"

Developer Experience

Developers will write MCP tools as functions that can be compiled to WebAssembly Components, instead of developing servers. This is a significant paradigm shift and offers a completely different experience than writing MCP servers as it currently stands. We are fully aware that current MCP server code would need to be rewritten for retargeting to Wasm but the security benefits and flexibility of the Component Model are worth it.

We are exploring AI tools that make porting existing MCP servers to Wasm easier, removing the biggest barrier to adoption.

Language Support

Wassette supports tools written in any language that can compile to WebAssembly Components. For current language support, see the WebAssembly Language Support Guide.

Wassette provides examples in JavaScript and Python, which are the most popular languages for MCP server development, see examples.

Install Wassette with Homebrew

This guide explains how to install wassette using Homebrew.

This uses the Formula in Formula/wassette.rb, which is setup to download and install the latest release of wassette from GitHub.

You must have Homebrew installed on your macOS or Linux system. If you don’t, you can install it by following the instructions on the official Homebrew website.

Installation

You can install wassette with a single command:

brew tap microsoft/wassette https://github.com/microsoft/wassette
brew install wassette

This command will automatically tap the microsoft/wassette repository and install the wassette formula.

Verifying the Installation

To make sure everything worked, you can run:

wassette --version

Upgrading

To upgrade wassette to the latest version, first update Homebrew’s package list and then upgrade the wassette package.

brew update
brew upgrade wassette

Nix

You can install Wassette using Nix flakes:

# Run directly without installation
nix run github:microsoft/wassette -- serve --stdio

# Install to your profile
nix profile install github:microsoft/wassette

# Or in a development shell
nix develop github:microsoft/wassette

This provides a reproducible environment for using and developing Wassette. The flake provides a wassette package and a development shell with all the necessary dependencies.

Installing Wassette with WinGet

Wassette provides a WinGet package manifest for easy installation on Windows systems.

Installation

Since WinGet doesn’t support installing directly from URLs, you need to download the manifest first:

# Download the manifest
Invoke-WebRequest -Uri https://raw.githubusercontent.com/microsoft/wassette/main/winget/Microsoft.Wassette.yaml -OutFile Microsoft.Wassette.yaml

# Install from the downloaded manifest
winget install --manifest Microsoft.Wassette.yaml

If the installation fails, it is probably because the local installation feature is not enabled. You can activate it with the following command in an administrator shell:

winget settings --enable LocalManifestFiles

Verification

After installation, verify that Wassette is available:

wassette --version

Uninstall

To uninstall Wassette, use one of these commands:

# Try the simple name first
winget uninstall Wassette

If that doesn’t work, list installed packages to get the exact ID:

# List to find the exact package ID
winget list Wassette

# Use the exact ID (example output may vary)
winget uninstall "Wassette ARP\User\Arm64\Microsoft.Wassette__DefaultSource"

Next Steps

After installation, follow the MCP clients setup guide to configure Wassette with your AI agent of choice.

Model Context Protocol (MCP) Clients

If you haven’t installed Wassette yet, follow the installation instructions first.

Visual Studio Code

Add the Wassette MCP Server to GitHub Copilot in Visual Studio Code by clicking the Install in VS Code or Install in VS Code Insiders badge below:

Install in VS Code Install in VS Code Insiders

Alternatively, you can add the Wassete MCP server to VS Code from the command line using the code command in a bash/zsh or PowerShell terminal:

bash/zsh

code --add-mcp '{"name":"Wassette","command":"wassette","args":["serve","--stdio"]}'

PowerShell

 code --% --add-mcp "{\"name\":\"wassette\",\"command\":\"wassette\",\"args\":[\"serve\",\"--stdio\"]}"

You can list and configure MCP servers in VS Code by running the command MCP: List Servers in the command palette (Ctrl+Shift+P or Cmd+Shift+P).

Cursor

Click the below button to use the one-click installation to add Wassette to Cursor.

Install MCP Server

Claude Code

First, install Claude Code (requires Node.js 18 or higher):

npm install -g @anthropic-ai/claude-code

Add the Wassette MCP server to Claude Code using the following command:

claude mcp add -- wassette wassette serve --stdio

This will configure the Wassette MCP server as a local stdio server that Claude Code can use to execute Wassette commands and interact with your data infrastructure.

You can verify the installation by running:

claude mcp list

To remove the server if needed:

claude mcp remove wassette

Gemini CLI

First, install Gemini CLI (requires Node.js 20 or higher):

npm install -g @google/gemini-cli

To add the Wassette MCP server to Gemini CLI, you need to configure it in your settings file at ~/.gemini/settings.json. Create or edit this file to include:

{
  "mcpServers": {
    "wassette": {
      "command": "wassette",
      "args": ["serve", "--stdio"]
    }
  }
}

Quit the Gemini CLI and reopen it.

Open Gemini CLI and verify the installation by running /mcp inside of Gemini CLI.

Wassette CLI Reference

The Wassette command-line interface provides comprehensive tools for managing WebAssembly components, policies, and permissions both locally and through the MCP server. This document covers all CLI functionality and usage patterns.

Overview

Wassette offers two primary modes of operation:

  1. Server Mode: Run as an MCP server that responds to client requests
  2. CLI Mode: Direct command-line management of components and permissions

The CLI mode allows you to perform administrative tasks without requiring a running MCP server, making it ideal for automation, scripting, and local development workflows.

Installation

For installation instructions, see the main README. Once installed, the wassette command will be available in your PATH.

Quick Start

# Check available commands
wassette --help

# List currently loaded components
wassette component list

# Load a component from an OCI registry
wassette component load oci://ghcr.io/yoshuawuyts/time:latest

# Load a component from a local file
wassette component load file:///path/to/component.wasm

# Start the MCP server (traditional mode)
wassette serve --stdio

Command Structure

Wassette uses a hierarchical command structure organized around functional areas:

wassette
├── serve          # Start MCP server
├── component      # Component lifecycle management
│   ├── load       # Load components
│   ├── unload     # Remove components
│   └── list       # Show loaded components
├── policy         # Policy information
│   └── get        # Retrieve component policies
└── permission     # Permission management
    ├── grant      # Add permissions
    ├── revoke     # Remove permissions
    └── reset      # Clear all permissions

Server Commands

wassette serve

Start the Wassette MCP server to handle client requests.

Stdio Transport (recommended for MCP clients):

# Start server with stdio transport
wassette serve --stdio

# Use with specific configuration directory
wassette serve --stdio --plugin-dir /custom/components

HTTP Transport (for development and debugging):

# Start server with HTTP transport
wassette serve --http

# Use Server-Sent Events (SSE) transport
wassette serve --sse

Options:

  • --stdio: Use stdio transport (recommended for MCP clients)
  • --http: Use HTTP transport on 127.0.0.1:9001
  • --sse: Use Server-Sent Events transport
  • --plugin-dir <PATH>: Set component storage directory (default: $XDG_DATA_HOME/wassette/components)

Component Management

wassette component load

Load a WebAssembly component from various sources.

Load from OCI registry:

# Load a component from GitHub Container Registry
wassette component load oci://ghcr.io/yoshuawuyts/time:latest

# Load with custom plugin directory
wassette component load oci://ghcr.io/microsoft/gomodule:latest --plugin-dir /custom/components

Load from local file:

# Load a local component file
wassette component load file:///path/to/component.wasm

# Load with relative path
wassette component load file://./my-component.wasm

Options:

  • --plugin-dir <PATH>: Component storage directory

wassette component unload

Remove a loaded component by its ID.

# Unload a component
wassette component unload my-component-id

# Unload with custom plugin directory
wassette component unload my-component-id --plugin-dir /custom/components

Options:

  • --plugin-dir <PATH>: Component storage directory

wassette component list

Display all currently loaded components.

Basic JSON output:

wassette component list
# Output: {"components":[...],"total":1}

Formatted output options:

# Pretty-printed JSON
wassette component list --output-format json

# YAML format
wassette component list --output-format yaml

# Table format (human-readable)
wassette component list --output-format table

Example outputs:

JSON format:

{
  "components": [
    {
      "id": "time-component",
      "schema": {
        "tools": [
          {
            "name": "get-current-time",
            "description": "Get the current time",
            "inputSchema": {
              "type": "object",
              "properties": {}
            }
          }
        ]
      },
      "tools_count": 1
    }
  ],
  "total": 1
}

Table format:

ID             | Tools | Description
---------------|-------|----------------------------------
time-component | 1     | Provides time-related functions

Options:

  • --output-format <FORMAT>: Output format (json, yaml, table) [default: json]
  • --plugin-dir <PATH>: Component storage directory

Policy Management

wassette policy get

Retrieve policy information for a specific component.

# Get policy for a component
wassette policy get my-component-id

# Get policy with pretty formatting
wassette policy get my-component-id --output-format json

# Get in YAML format
wassette policy get my-component-id --output-format yaml

Example output:

{
  "component_id": "my-component",
  "permissions": {
    "storage": [
      {
        "uri": "fs://workspace/**",
        "access": ["read", "write"]
      }
    ],
    "network": [
      {
        "host": "api.openai.com"
      }
    ]
  }
}

Options:

  • --output-format <FORMAT>: Output format (json, yaml, table) [default: json]
  • --plugin-dir <PATH>: Component storage directory

Permission Management

wassette permission grant

Grant specific permissions to a component.

Storage permissions:

# Grant read access to a directory
wassette permission grant storage my-component fs://workspace/ --access read

# Grant read and write access
wassette permission grant storage my-component fs://workspace/ --access read,write

# Grant access to a specific file
wassette permission grant storage my-component fs://config/app.yaml --access read

Network permissions:

# Grant access to a specific host
wassette permission grant network my-component api.openai.com

# Grant access to a localhost service
wassette permission grant network my-component localhost:8080

Environment variable permissions:

# Grant access to an environment variable
wassette permission grant environment-variable my-component API_KEY

# Grant access to multiple variables
wassette permission grant environment-variable my-component HOME
wassette permission grant environment-variable my-component PATH

Memory permissions:

# Grant memory limit to a component (using Kubernetes format)
wassette permission grant memory my-component 512Mi

# Grant larger memory limit
wassette permission grant memory my-component 1Gi

# Grant memory limit with different units
wassette permission grant memory my-component 2048Ki

Options:

  • --access <ACCESS>: For storage permissions, comma-separated list of access types (read, write)
  • --plugin-dir <PATH>: Component storage directory

wassette permission revoke

Remove specific permissions from a component.

Storage permissions:

# Revoke storage access
wassette permission revoke storage my-component fs://workspace/

# Revoke with custom plugin directory
wassette permission revoke storage my-component fs://config/ --plugin-dir /custom/components

Network permissions:

# Revoke network access
wassette permission revoke network my-component api.openai.com

Environment variable permissions:

# Revoke environment variable access
wassette permission revoke environment-variable my-component API_KEY

Options:

  • --plugin-dir <PATH>: Component storage directory

wassette permission reset

Remove all permissions for a component, resetting it to default state.

# Reset all permissions for a component
wassette permission reset my-component

# Reset with custom plugin directory
wassette permission reset my-component --plugin-dir /custom/components

Options:

  • --plugin-dir <PATH>: Component storage directory

Common Workflows

Local Development

# 1. Build and load a local component
wassette component load file://./target/wasm32-wasi/debug/my-tool.wasm

# 2. Check it loaded correctly
wassette component list --output-format table

# 3. Grant necessary permissions
wassette permission grant storage my-tool fs://$(pwd)/workspace --access read,write
wassette permission grant network my-tool api.example.com
wassette permission grant memory my-tool 512Mi

# 4. Verify permissions
wassette policy get my-tool --output-format yaml

# 5. Test via MCP server
wassette serve --stdio

Component Distribution

# 1. Load component from OCI registry
wassette component load oci://ghcr.io/myorg/my-tool:v1.0.0

# 2. Configure permissions based on component needs
wassette permission grant storage my-tool fs://workspace/** --access read,write
wassette permission grant network my-tool api.myservice.com
wassette permission grant memory my-tool 1Gi

# 3. Start server for clients
wassette serve --sse

Permission Auditing

# List all components and their tool counts
wassette component list --output-format table

# Check permissions for each component
for component in $(wassette component list | jq -r '.components[].id'); do
  echo "=== $component ==="
  wassette policy get $component --output-format yaml
done

Cleanup Operations

# Reset permissions for a component
wassette permission reset problematic-component

# Remove a component entirely
wassette component unload problematic-component

# List remaining components
wassette component list --output-format table

Configuration

Wassette can be configured using configuration files, environment variables, and command-line options. The configuration sources are merged with the following order of precedence:

  1. Command-line options (highest priority)
  2. Environment variables prefixed with WASSETTE_
  3. Configuration file (lowest priority)

Configuration File

By default, Wassette looks for a configuration file at:

  • Linux/macOS: $XDG_CONFIG_HOME/wassette/config.toml (typically ~/.config/wassette/config.toml)
  • Windows: %APPDATA%\wassette\config.toml

You can override the default configuration file location using the WASSETTE_CONFIG_FILE environment variable:

export WASSETTE_CONFIG_FILE=/custom/path/to/config.toml
wassette component list

Example configuration file (config.toml):

# Directory where components are stored
plugin_dir = "/opt/wassette/components"

Environment Variables

  • WASSETTE_CONFIG_FILE: Override the default configuration file location
  • WASSETTE_PLUGIN_DIR: Override the default component storage location
  • XDG_CONFIG_HOME: Base directory for configuration files (Linux/macOS)
  • XDG_DATA_HOME: Base directory for data storage (Linux/macOS)

Component Storage

By default, Wassette stores components in $XDG_DATA_HOME/wassette/components (typically ~/.local/share/wassette/components on Linux/macOS). You can override this with the --plugin-dir option:

# Use custom storage directory
export WASSETTE_PLUGIN_DIR=/opt/wassette/components
wassette component load oci://example.com/tool:latest --plugin-dir $WASSETTE_PLUGIN_DIR

Integration with MCP Clients

The CLI commands complement the MCP server functionality. You can:

  1. Use CLI commands to pre-configure components and permissions
  2. Start the MCP server with wassette serve
  3. Connect MCP clients to the running server
  4. Use CLI commands for administrative tasks while the server runs

Example VS Code configuration:

{
  "name": "wassette",
  "command": "wassette",
  "args": ["serve", "--stdio"]
}

Error Handling

The CLI provides clear error messages for common issues:

# Component not found
$ wassette component unload nonexistent
Error: Component 'nonexistent' not found

# Invalid path
$ wassette component load invalid://path
Error: Unsupported URI scheme 'invalid'. Use 'file://' or 'oci://'

# Permission denied
$ wassette permission grant storage my-component /restricted --access write
Error: Permission denied: cannot grant write access to /restricted

Output Formats

All commands that return structured data support multiple output formats:

  • JSON (default): Machine-readable, suitable for scripting
  • YAML: Human-readable structured format
  • Table: Formatted for terminal display

Use the --output-format or -o flag to specify the desired format:

wassette component list -o table
wassette policy get my-component -o yaml

See Also

Frequently Asked Questions (FAQ)

General Questions

What is Wassette?

Wassette is a secure, open-source Model Context Protocol (MCP) server that leverages WebAssembly (Wasm) to provide a trusted execution environment for untrusted tools. It enables safe execution of third-party MCP tools without compromising the host system by using WebAssembly’s sandboxed execution environment and fine-grained security policies.

Note: The name “Wassette” is a portmanteau of “Wasm” and “Cassette” (referring to magnetic tape storage), and is pronounced “Wass-ette”.

How is Wassette different from other MCP servers?

Traditional MCP servers run with the same privileges as the host process, creating security risks. Wassette addresses this by:

  • Sandboxed execution: Tools run in WebAssembly’s secure sandbox, not directly on the host
  • Fine-grained permissions: Explicit control over file system, network, and system resource access
  • Component-based architecture: Uses the standardized WebAssembly Component Model for tool interoperability
  • Centralized security: Single trusted computing base instead of multiple potentially vulnerable servers

What are WebAssembly Components?

WebAssembly Components are a standardized way to build portable, secure, and interoperable software modules. Unlike traditional WebAssembly modules, Components use the WebAssembly Component Model which provides:

  • Standardized interfaces defined using WebAssembly Interface Types (WIT)
  • Language interoperability - components can be written in any language that compiles to Wasm
  • Composability - components can be combined and reused across different environments

Language and Development

What programming languages are supported?

Wassette supports tools written in any language that can compile to WebAssembly Components. For current language support, see the WebAssembly Language Support Guide.

The project includes examples in several popular languages:

Can I use existing WebAssembly modules with Wassette?

Wassette specifically requires WebAssembly Components (not just modules) that follow the Component Model. Existing Wasm modules would need to be adapted to use the Component Model’s interface system.

How do I create a Wasm component?

  1. Define your interface using WebAssembly Interface Types (WIT)
  2. Implement the functionality in your preferred supported language
  3. Compile to a Component using appropriate tooling for your language
  4. Test with Wassette by loading the component

See the examples directory for complete working examples in different languages.

Do I need to rewrite existing MCP servers?

Yes, existing MCP servers would need to be rewritten to target wasip2 (WebAssembly Components). This is a significant paradigm shift from writing servers to writing functions that compile to Wasm Components. However, the security benefits and flexibility of the Component Model make this worthwhile.

The project is exploring AI tools to help port existing MCP servers to Wasm, which should reduce the migration effort.

Security and Permissions

How does Wassette’s security model work?

Wassette implements a capability-based security model with:

  • Sandbox isolation: All tools run in WebAssembly’s secure sandbox
  • Explicit permissions: Components must declare what resources they need access to
  • Allow/deny lists: Fine-grained control over file system paths, network endpoints, etc.
  • Principle of least privilege: Components only get the permissions they explicitly need

What is a policy file?

A policy file (policy.yaml) defines what permissions a component has. Example:

version: "1.0"
description: "Permission policy for filesystem access"
permissions:
  storage:
    allow:
      - uri: "fs://workspace/**"
        access: ["read", "write"]
      - uri: "fs://config/app.yaml"
        access: ["read"]
  network:
    allow:
      - host: "api.openai.com"

Can I grant permissions at runtime?

Yes, Wassette provides built-in tools for dynamic permission management:

  • grant-storage-permission: Grant file system access
  • grant-network-permission: Grant network access
  • grant-environment-variable-permission: Grant environment variable access

What happens if a component tries to access unauthorized resources?

The WebAssembly sandbox will block the access attempt. Wassette enforces permissions at the runtime level, so unauthorized access attempts are prevented rather than just logged.

Installation and Setup

What platforms does Wassette support?

Wassette supports:

  • Linux (including Windows Subsystem for Linux)
  • macOS
  • Windows (via WinGet package)

How do I install Wassette?

Linux/macOS:

curl -fsSL https://raw.githubusercontent.com/microsoft/wassette/main/install.sh | bash

macOS (Homebrew): See the Homebrew installation guide

Windows (WinGet): See the WinGet installation guide

Nix: See the Nix installation guide

How do I configure Wassette with my AI agent?

Wassette works with any MCP-compatible AI agent. See the MCP clients setup guide for specific instructions for:

  • Visual Studio Code
  • Cursor
  • Claude Code
  • Gemini CLI

Usage and Troubleshooting

How do I load a component in Wassette?

You can load components from OCI registries or local files:

Please load the component from oci://ghcr.io/microsoft/time-server-js:latest

Or for local files:

Please load the component from ./path/to/component.wasm

What built-in tools does Wassette provide?

Wassette includes several built-in management tools:

  • load-component: Load WebAssembly components
  • unload-component: Unload components
  • list-components: List loaded components
  • search-components: Search available components from registry
  • get-policy: Get policy information
  • grant-storage-permission: Grant storage access
  • grant-network-permission: Grant network access
  • grant-environment-variable-permission: Grant environment variable access
  • revoke-storage-permission: Revoke storage access permissions
  • revoke-network-permission: Revoke network access permissions
  • revoke-environment-variable-permission: Revoke environment variable access permissions
  • reset-permission: Reset all permissions for a component

How do I debug component issues?

  1. Check the logs: Run Wassette with RUST_LOG=debug for detailed logging
  2. Verify permissions: Ensure your policy file grants necessary permissions
  3. Test component separately: Validate that your component works outside Wassette
  4. Check the interface: Ensure your WIT interface matches what Wassette expects

Are there performance implications of using WebAssembly?

WebAssembly Components in Wassette have:

  • Lower memory overhead compared to containers
  • Fast startup times due to efficient Wasm instantiation
  • Near-native performance for CPU-intensive tasks
  • Minimal runtime overhead thanks to Wasmtime’s optimizations

Can I use Wassette in production?

Wassette is actively developed and used by Microsoft. However, as with any software, you should:

  • Test thoroughly in your specific environment
  • Review the security model for your use case
  • Keep up with updates and security patches
  • Consider your specific requirements for stability and support

Getting Help

Where can I get support?

How can I contribute to Wassette?

See the Contributing Guide for information on:

  • Setting up the development environment
  • Submitting bug reports and feature requests
  • Contributing code and documentation
  • Following the project’s coding standards

Where can I find more examples?

The examples directory contains working examples in multiple languages:

sequenceDiagram
    participant Client as MCP Client
    participant Server as Wassette MCP Server
    participant LM as LifecycleManager
    participant Engine as Wasmtime Engine
    participant Registry as Component Registry
    participant Policy as Policy Engine
    
    Client->>Server: load-component(path)
    Server->>LM: load_component(uri)
    
    alt OCI Registry
        LM->>LM: Download from OCI
    else Local File
        LM->>LM: Load from filesystem
    else HTTP URL
        LM->>LM: Download from URL
    end
    
    LM->>Engine: Create Component
    Engine->>Engine: Compile WebAssembly
    Engine->>Engine: Extract WIT Interface
    
    LM->>Registry: Register Component
    Registry->>Registry: Generate JSON Schema
    Registry->>Registry: Map Tools to Component
    
    LM->>Policy: Apply Default Policy
    Policy->>Policy: Create WASI State Template
    
    LM-->>Server: Component ID + LoadResult
    Server-->>Client: Success with ID
    
    Note over Client,Policy: Component is now loaded and ready
    
    Client->>Server: call_tool(tool_name, args)
    Server->>LM: execute_component_call(id, func, params)
    
    LM->>Policy: Get WASI State for Component
    Policy->>Policy: Apply Security Policy
    Policy->>Engine: Create Store with WASI Context
    
    LM->>Engine: Instantiate Component
    Engine->>Engine: Call Function with Args
    Engine->>Engine: Execute in Sandbox
    
    Engine-->>LM: Results
    LM-->>Server: JSON Response
    Server-->>Client: Tool Result

Permission System Design

  • Author: @Mossaka
  • Date: 2025-07-11

Overview

The permission system provides fine-grained, per-component capability controls in the Wassette MCP server. This document describes the architecture,implementation, and future development plans.

Architecture Overview

Core Components

graph TB
    Client[MCP Client] --> Server[Wassette MCP Server]
    Server --> LM[LifecycleManager]
    LM --> PR[PolicyRegistry]
    LM --> CR[ComponentRegistry]
    LM --> Engine[Wasmtime Engine]
    
    LM --> Resources[Resources]
    PR --> Permissions[Permissions]

    subgraph "Resources"
        PolicyFile[Component Policy Files]
        ComponentFile[Component.wasm]
    end
    
    subgraph "Permissions"
        Network[Network Permissions]
        Storage[Storage Permissions]
        Environment[Environment Permissions]
    end

Key Design Principles

  • Per-Component Policies: Each component has its own permission policy, co-located with the component binary under the plugin_dir directory
  • Principle of Least Privilege: Components only get permissions they need
  • Dynamic Control: Permissions can be granted at runtime using the grant-permission tool

Current Implementation Status

1. Per-Component Policy System

Status: ✅ Implemented

Each component can have its own policy file stored as {component_id}.policy.yaml co-located with the component binary.

#![allow(unused)]
fn main() {
// Current Implementation
struct PolicyRegistry {
    component_policies: HashMap<String, Arc<WasiStateTemplate>>,
}

impl LifecycleManager {
    async fn get_wasi_state_for_component(&self, component_id: &str) -> Result<WasiState> {
        // Returns component-specific WASI state or default restrictive policy
    }
}
}

2. Policy Lifecycle Management

Status: ✅ Implemented

Built-in tools for managing component policies:

  • attach-policy: Attach policy from file:// or https:// URI
  • detach-policy: Remove policy from component
  • get-policy: Get policy information for component

3. Granular Permission System

Status: ✅ Implemented

The grant_storage_permission method allows atomic permission grants:

#![allow(unused)]
fn main() {
pub async fn grant_storage_permission(
    &self,
    component_id: &str,
    details: &serde_json::Value,
) -> Result<()>
}

The grant_network_permission method allows atomic permission grants:

#![allow(unused)]
fn main() {
pub async fn grant_network_permission(
    &self,
    component_id: &str,
    details: &serde_json::Value,
) -> Result<()>
}

Supported permission types:

  • Network: {"host": "api.example.com"}
  • Storage: {"uri": "fs:///path", "access": ["read", "write"]}

4. Policy Persistence

Status: ✅ Implemented

  • Policies are stored co-located with components
  • Policy associations are restored on server restart
  • Metadata tracking for policy sources

Built-in Tools

  1. get-policy: Get policy information
  2. grant-storage-permission: Grant storage access
  3. grant-network-permission: Grant network access
  4. grant-environment-variable-permission: Grant environment variable access
  5. revoke-storage-permission: Revoke storage access permissions
  6. revoke-network-permission: Revoke network access permissions
  7. revoke-environment-variable-permission: Revoke environment variable access permissions
  8. reset-permission: Reset all permissions for a component
  9. load-component: Load WebAssembly component
  10. unload-component: Unload component
  11. list-components: List loaded components
  12. search-components: Search available components from registry

Permission Types and Structure

Policy File Format

version: "1.0"
description: "Component-specific security policy"
permissions:
  network:
    allow:
      - host: "api.example.com"
      - host: "cdn.example.com"
  environment:
    allow:
      - key: "API_KEY"
      - key: "CONFIG_URL"
  storage:
    allow:
      - uri: "fs:///tmp/workspace"
        access: ["read", "write"]
      - uri: "fs:///var/cache"
        access: ["read"]

Future Development Roadmap

  • Policy Signing: Verify policy integrity with signatures
  • Policy Checksums: Verify downloaded policy integrity
  • Policy Caching: Optimize policy loading and parsing