|
1 | | -# wassette |
| 1 | +<div align="center"> |
| 2 | + <h1 align="center">Wassette</h1> |
| 3 | + <p><b>A security-oriented runtime that runs WebAssembly Components via MCP</b></p> |
| 4 | + |
| 5 | + <!-- <a href="https://discord.gg/microsoft-open-source"> |
| 6 | + <img src="https://dcbadge.limes.pink/api/server/microsoft-open-source" alt="Discord" style="height: 25px;"> |
| 7 | + </a> --> |
2 | 8 |
|
3 | | -Wassette is a secure and open source MCP server that runs on top of WebAssembly (Wasm). It is designed to securely execute untrusted tools by embedding a Wasm runtime and applying capability-based policies to control access to system resources. It uses the sandboxing and abstraction provided by the Wasm [Component Model](https://github.com/WebAssembly/component-model) to ensure tools can be executed safely and easily without compromising the host system. |
| 9 | +[Getting started][setup guide] | [Releases] | [Contributing] | [Discord] |
4 | 10 |
|
5 | | -Please read the rest of the README for more background, but the TL;DR is this: |
| 11 | +</div> |
6 | 12 |
|
7 | | -`wassette` essentially acts as a _virtual MCP server_, with built-in observability, resource quotas, and handles infrastructure complexity automatically. |
| 13 | +## Why Wassette? |
8 | 14 |
|
9 | | -> Note: The name "Wassette" is a play on the word "Wasm" and "Cassette" - a magnetic tape used to store audio, and is pronounced "Wass-ette". |
| 15 | +- **Convenience**: Wassette makes it easy to extend AI agents with new tools, |
| 16 | + all without ever having to leave the chat window. |
| 17 | +- **Reusability**: Wasm Components built for Wassette are generic and reusable; |
| 18 | + there is nothing MCP-specific about them. |
| 19 | +- **Security**: Wassette is built on the Wasmtime security sandbox, providing |
| 20 | + browser-grade isolation of tools. |
10 | 21 |
|
11 | | -## 🚩 Purpose |
| 22 | +## Installation |
12 | 23 |
|
13 | | -### Problem Statement |
14 | | - |
15 | | -A popular use scenario for MCP today is to run the server as a standalone process on a machine that talks to clients over stdio or a socket. Running these servers natively poses security risks, such as "my mcp-client calls the tool to read a file, and for some reason the tool writes to a file on my machine", "the tool opens a socket to a remote machine and sends data to it", or "I downloaded this open source mcp-server, but it has a vulnerability that allows an attacker to execute arbitrary code on my machine". This is the same problem as running untrusted code on your machine, but mcp-clients make them much easier to install on your machine and run. |
16 | | - |
17 | | -### Who is the target audience? |
18 | | - |
19 | | -1. _Developers_ who want to focus on writing the business logic for MCP tools, instead of worrying about the infrastructure. |
20 | | - |
21 | | -2. _DevOps engineers_ who want the tools to be able to run everywhere and have a great observability story and tools are secured by design. |
22 | | - |
23 | | -3. _Users_ who want to run a trusted mcp-server on their machine that is proven to securely execute untrusted tools. |
24 | | - |
25 | | -4. _Platform providers_ who want to provide a serverless experience for their users. |
26 | | - |
27 | | -### What are the current solutions? |
28 | | - |
29 | | -1. Package and distribute the server as Docker images. 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](https://docs.docker.com/ai/mcp-catalog-and-toolkit/catalog/) runs each MCP server as a container - providing isolation and portability. |
30 | | -2. 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. |
31 | | -3. Centralized MCP server that runs WebAssembly-based tools locally (think tools like [mcp.run](https://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. |
32 | | - |
33 | | -### So why does this exist? |
34 | | - |
35 | | -We wanted to build an entirely open source tool that enables developers to define tools via the Component Model, which means they are easy to reuse and compose in addition to running with low memory requirements and in a secure sandbox. They also let anyone see exactly what features the tool is requesting and allows a server to fulfill those requests in a secure way. This is a significant improvement over the current state of MCP servers, which are either arbitrary code or require custom ABIs and libraries, and are not compatible with each other. |
36 | | - |
37 | | -So what is this project aiming to be? |
38 | | - |
39 | | -1. One centralized open-source mcp-server, written in a memory safe, high performance language that embeds a WebAssembly runtime (e.g. [Wasmtime](https://github.com/bytecodealliance/wasmtime) or [hyperlight-wasm](https://github.com/hyperlight-dev/hyperlight-wasm)), acting as a minimal trusted computing base (TCB). |
40 | | -2. `wassette` will implement allow/deny lists for file paths, network endpoints, and system calls using capability-based policy like [policy-mcp-rs](https://github.com/microsoft/policy-mcp-rs). |
41 | | -3. Untrusted tool code will be distributed as WebAssembly OCI artifacts in OCI registries, and be loaded into the trusted layer upon signature verification. Each tool will have a discrete set of capabilities. For example, tool A needs to read `./data`; not network; tool B needs read/write to `/assets` and outbound HTTP only to `api.company.com:443`. |
42 | | - |
43 | | -### What about the developer experience? |
44 | | - |
45 | | -Developers will write MCP tools as normal 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. |
46 | | - |
47 | | -If you are interested in learning more about what programming language supports WebAssembly, you can check out [this page](https://developer.fermyon.com/wasm-languages/webassembly-language-support). |
48 | | - |
49 | | -## Install |
50 | | - |
51 | | -### All Platforms (Shell Script) |
| 24 | +For Linux and macOS, you can install Wassette using the provided install script: |
52 | 25 |
|
53 | 26 | ```bash |
54 | 27 | curl -fsSL https://raw.githubusercontent.com/microsoft/wassette/main/install.sh | bash |
55 | 28 | ``` |
56 | 29 |
|
57 | | -This will detect your platform and install the latest `wassette` binary to your `$PATH`. |
58 | | - |
59 | | -## Integrate with MCP Clients |
| 30 | +This will detect your platform and install the latest `wassette` binary to your `$PATH`. For Windows, you can download the latest release from the [GitHub Releases page][Releases] |
60 | 31 |
|
61 | | -### [VSCode](https://code.visualstudio.com/docs/copilot/chat/mcp-servers) / [GitHub Copilot](https://docs.github.com/en/copilot/customizing-copilot/extending-copilot-chat-with-mcp) / [Cursor](https://docs.cursor.com/context/model-context-protocol) |
| 32 | +## Using Wassette |
62 | 33 |
|
63 | | -Add this to your VSCode or Cursor settings: |
| 34 | +With Wassette installed, the next step is to register it with your agent of |
| 35 | +choice. We have a complete [complete setup guide][setup guide] for all agents |
| 36 | +here, including Cursor, Claude Code, and Gemini CLI. However to get started with |
| 37 | +Visual Studio Code, just run the following command: |
64 | 38 |
|
65 | | -```json |
66 | | -"mcp": { |
67 | | - "servers": { |
68 | | - "wassette": { |
69 | | - "type": "sse", |
70 | | - "url": "http://127.0.0.1:9001/sse" |
71 | | - } |
72 | | - } |
73 | | -} |
| 39 | +```bash |
| 40 | +code --add-mcp '{"name":"Wassette","command":"wassette","args":["serve","--stdio"]}' |
74 | 41 | ``` |
75 | 42 |
|
76 | | -## Quick Start |
77 | | - |
78 | | -1. **Start the wassette server:** |
| 43 | +Now that your agent knows about Wassette, we are ready to load Wasm Components. To teach your agent to tell the time, we can ask it to load a time component: |
79 | 44 |
|
80 | | - ```bash |
81 | | - # Run the following cmd in your terminal to start the Wassette MCP server |
82 | | - wassette serve --http --policy-file policy.yaml |
83 | | - ``` |
| 45 | +```text |
| 46 | +Please load the time component from oci://ghcr.io/yoshuawuyts/time:latest |
| 47 | +``` |
84 | 48 |
|
85 | | -2. **Dynamically load tools:** |
| 49 | +Now that the time component is loaded, we can ask your agent to tell you the current time: |
86 | 50 |
|
87 | | - **From OCI Registry:** |
88 | | - <!-- update to point to wassette pkgs --> |
| 51 | +```text |
| 52 | +What is the current time? |
| 53 | +``` |
89 | 54 |
|
90 | | - ``` |
91 | | - # Enter the following prompt into your AI client |
92 | | - Load the filesystem tools from oci://ghcr.io/duffney/filesystem:latest |
93 | | - ``` |
| 55 | +The agent will respond with the current time, which is fetched from the time component running in a secure WebAssembly sandbox: |
94 | 56 |
|
95 | | - **From Local File:** |
| 57 | +```output |
| 58 | +The current time July 31, 2025 at 10:30 AM UTC |
| 59 | +``` |
96 | 60 |
|
97 | | - ``` |
98 | | - # Enter the following prompt into your AI client |
99 | | - Load component from file:///path/to/my-tools.wasm |
100 | | - ``` |
| 61 | +Congratulations! You've just run your first Wasm Component and taught your agent how to tell time! |
101 | 62 |
|
102 | | -3. **Use the newly loaded tools immediately:** |
| 63 | +## Building for Wassette |
103 | 64 |
|
104 | | - ``` |
105 | | - # Enter the following prompt into your AI client |
106 | | - Use the read-file tool to get the contents of the Justfile at the root of this repo |
107 | | - ``` |
| 65 | +Wasm Components provide fully typed interfaces defined using WebAssembly |
| 66 | +Interface Types (WIT). Wassette can take any Wasm Component and load it as an |
| 67 | +MCP tool by inspecting the types it exposes. Take for example the following WIT |
| 68 | +definition for a time server: |
108 | 69 |
|
109 | | - The tools are now available in your AI client's tool list - no restart required! Wassette automatically detects what functions each component exports and makes them available as MCP tools. |
| 70 | +```wit |
| 71 | +package local:time-server; |
110 | 72 |
|
111 | | -**Built-in Tools for Dynamic Loading:** |
| 73 | +world time-server { |
| 74 | + export get-current-time: func() -> string; |
| 75 | +} |
| 76 | +``` |
112 | 77 |
|
113 | | -- `load-component` - Load WebAssembly components from any source |
114 | | -- `unload-component` - Remove components from the runtime |
| 78 | +You'll notice that this interface doesn't mention MCP at all; it is just a |
| 79 | +regular library interface that exports a function. That means there is no such |
| 80 | +thing as a "Wassette-specific Wasm Component". Wassette is able to load any Wasm |
| 81 | +Component and expose its functions as MCP tools. Just like Components built for Wassette can be re-used by other Wasm runtimes. |
115 | 82 |
|
116 | | -## Examples |
| 83 | +See the [`examples/`](./examples/) directory for a complete list of examples. Here is a |
| 84 | +selection of examples written in different languages: |
117 | 85 |
|
118 | 86 | | Example | Description | |
119 | 87 | | ------------------------------------------ | ------------------------------------------------------ | |
120 | | -| [fetch-rs](examples/fetch-rs/) | HTTP client for making web requests | |
121 | 88 | | [filesystem-rs](examples/filesystem-rs/) | File system operations (read, write, list directories) | |
122 | 89 | | [eval-py](examples/eval-py/) | Python code execution sandbox | |
123 | 90 | | [get-weather-js](examples/get-weather-js/) | Weather API client for fetching weather data | |
124 | | -| [time-server-js](examples/time-server-js/) | Simple time server component | |
125 | 91 | | [gomodule-go](examples/gomodule-go/) | Go module information tool | |
126 | 92 |
|
127 | | -See the `examples/` directory for more components you can build and load dynamically. |
128 | | - |
129 | 93 | ## Contributing |
130 | 94 |
|
131 | | -Please see [CONTRIBUTING.md](CONTRIBUTING.md) for more information on how to contribute to this project. |
| 95 | +Please see [CONTRIBUTING.md][Contributing] for more information on how to contribute to this project. |
132 | 96 |
|
133 | 97 | ## License |
134 | 98 |
|
135 | | -<sup> |
136 | | -Licensed under the <a href="LICENSE">MIT License</a>. |
137 | | -</sup> |
| 99 | +This project is icensed under the <a href="LICENSE">MIT License</a>. |
138 | 100 |
|
139 | 101 | ## Trademarks |
140 | 102 |
|
141 | 103 | This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow [Microsoft’s Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks). Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party’s policies. |
| 104 | + |
| 105 | +[setup guide]: https://github.com/microsoft/wassette/blob/main/docs/mcp-clients.md |
| 106 | +[Contributing]: CONTRIBUTING.md |
| 107 | +[Releases]: https://github.com/microsoft/wassette/releases |
| 108 | +[Discord]: https://discord.gg/microsoft-open-source |
0 commit comments