├── examples ├── context7-rs │ ├── .gitignore │ ├── wit │ │ ├── deps │ │ │ ├── cli │ │ │ │ ├── run.wit │ │ │ │ ├── command.wit │ │ │ │ ├── stdio.wit │ │ │ │ ├── exit.wit │ │ │ │ ├── environment.wit │ │ │ │ ├── imports.wit │ │ │ │ └── terminal.wit │ │ │ ├── io │ │ │ │ ├── world.wit │ │ │ │ ├── error.wit │ │ │ │ └── poll.wit │ │ │ ├── filesystem │ │ │ │ ├── world.wit │ │ │ │ └── preopens.wit │ │ │ ├── random │ │ │ │ ├── world.wit │ │ │ │ ├── insecure.wit │ │ │ │ ├── insecure-seed.wit │ │ │ │ └── random.wit │ │ │ ├── clocks │ │ │ │ ├── world.wit │ │ │ │ ├── monotonic-clock.wit │ │ │ │ ├── wall-clock.wit │ │ │ │ └── timezone.wit │ │ │ ├── sockets │ │ │ │ ├── instance-network.wit │ │ │ │ ├── world.wit │ │ │ │ ├── udp-create-socket.wit │ │ │ │ └── tcp-create-socket.wit │ │ │ └── http │ │ │ │ ├── proxy.wit │ │ │ │ └── handler.wit │ │ └── world.wit │ ├── Justfile │ ├── policy.yaml │ ├── Cargo-component.lock │ ├── Cargo.toml │ └── README.md ├── brave-search-rs │ ├── .gitignore │ ├── .cargo │ │ └── config.toml │ ├── policy.yaml │ ├── wit │ │ └── world.wit │ ├── Justfile │ └── Cargo.toml ├── fetch-rs │ ├── .gitignore │ ├── fetch_rs.cwasm │ ├── fetch_rs.wasm │ ├── Cargo-component.lock │ ├── wit │ │ └── world.wit │ ├── policy.yaml │ ├── Justfile │ ├── Cargo.toml │ ├── fetch_rs.metadata.json │ └── README.md ├── filesystem-rs │ ├── .gitignore │ ├── get_file_into.png │ ├── Justfile │ ├── Cargo.toml │ ├── policy.yaml │ └── Cargo.lock ├── time-server-js │ ├── .gitignore │ ├── Justfile │ ├── policy.yaml │ ├── time.js │ ├── package.json │ ├── wit │ │ └── world.wit │ └── README.md ├── arxiv-rs │ ├── .gitignore │ ├── policy.yaml │ ├── Justfile │ ├── Cargo.toml │ └── wit │ │ └── world.wit ├── github-js │ ├── .gitignore │ ├── Justfile │ ├── policy.yaml │ ├── package.json │ └── wit │ │ └── deps │ │ └── wasi-config-0.2.0-draft │ │ └── package.wit ├── memory-js │ ├── Justfile │ ├── .gitignore │ ├── policy.yaml │ ├── package.json │ └── test_component.sh ├── get-weather-js │ ├── .gitignore │ ├── Justfile │ ├── get-weather.png │ ├── wit │ │ ├── mcp.wit │ │ └── deps │ │ │ └── wasi-config-0.2.0-draft │ │ │ └── package.wit │ ├── policy.yaml │ ├── package.json │ └── weather.js ├── get-open-meteo-weather-js │ ├── .gitignore │ ├── Justfile │ ├── get-weather.png │ ├── wit │ │ └── mcp.wit │ ├── policy.yaml │ ├── package.json │ ├── weather.js │ └── README.md ├── gomodule-go │ ├── gomodule-info.png │ ├── go.mod │ ├── gen │ │ ├── local │ │ │ └── gomodule-server │ │ │ │ ├── gomodule │ │ │ │ ├── gomodule.wit.go │ │ │ │ ├── empty.s │ │ │ │ ├── gomodule.exports.go │ │ │ │ └── gomodule.wasm.go │ │ │ │ └── gomodule-server │ │ │ │ └── gomodule-server.wit.go │ │ └── wasi │ │ │ ├── cli │ │ │ ├── exit │ │ │ │ ├── empty.s │ │ │ │ ├── exit.wasm.go │ │ │ │ └── exit.wit.go │ │ │ ├── stdin │ │ │ │ ├── empty.s │ │ │ │ ├── stdin.wasm.go │ │ │ │ └── stdin.wit.go │ │ │ ├── stderr │ │ │ │ ├── empty.s │ │ │ │ ├── stderr.wasm.go │ │ │ │ └── stderr.wit.go │ │ │ ├── stdout │ │ │ │ ├── empty.s │ │ │ │ ├── stdout.wasm.go │ │ │ │ └── stdout.wit.go │ │ │ ├── environment │ │ │ │ ├── empty.s │ │ │ │ ├── environment.wasm.go │ │ │ │ └── environment.wit.go │ │ │ ├── terminal-input │ │ │ │ ├── empty.s │ │ │ │ ├── terminal-input.wasm.go │ │ │ │ └── terminal-input.wit.go │ │ │ ├── terminal-output │ │ │ │ ├── empty.s │ │ │ │ ├── terminal-output.wasm.go │ │ │ │ └── terminal-output.wit.go │ │ │ ├── terminal-stderr │ │ │ │ ├── empty.s │ │ │ │ ├── terminal-stderr.wasm.go │ │ │ │ └── terminal-stderr.wit.go │ │ │ ├── terminal-stdin │ │ │ │ ├── empty.s │ │ │ │ ├── terminal-stdin.wasm.go │ │ │ │ └── terminal-stdin.wit.go │ │ │ └── terminal-stdout │ │ │ │ ├── empty.s │ │ │ │ ├── terminal-stdout.wasm.go │ │ │ │ └── terminal-stdout.wit.go │ │ │ ├── io │ │ │ ├── error │ │ │ │ ├── empty.s │ │ │ │ ├── error.wasm.go │ │ │ │ └── error.wit.go │ │ │ ├── poll │ │ │ │ ├── empty.s │ │ │ │ ├── poll.wasm.go │ │ │ │ └── poll.wit.go │ │ │ └── streams │ │ │ │ └── empty.s │ │ │ ├── http │ │ │ ├── types │ │ │ │ └── empty.s │ │ │ └── outgoing-handler │ │ │ │ ├── empty.s │ │ │ │ ├── outgoing-handler.wasm.go │ │ │ │ ├── abi.go │ │ │ │ └── outgoing-handler.wit.go │ │ │ ├── random │ │ │ ├── random │ │ │ │ ├── empty.s │ │ │ │ ├── random.wasm.go │ │ │ │ └── random.wit.go │ │ │ ├── insecure │ │ │ │ ├── empty.s │ │ │ │ ├── insecure.wasm.go │ │ │ │ └── insecure.wit.go │ │ │ └── insecure-seed │ │ │ │ ├── empty.s │ │ │ │ ├── insecure-seed.wasm.go │ │ │ │ └── insecure-seed.wit.go │ │ │ ├── sockets │ │ │ ├── tcp │ │ │ │ └── empty.s │ │ │ ├── udp │ │ │ │ └── empty.s │ │ │ ├── network │ │ │ │ ├── empty.s │ │ │ │ ├── network.wasm.go │ │ │ │ └── abi.go │ │ │ ├── instance-network │ │ │ │ ├── empty.s │ │ │ │ ├── instance-network.wasm.go │ │ │ │ └── instance-network.wit.go │ │ │ ├── ip-name-lookup │ │ │ │ ├── empty.s │ │ │ │ ├── abi.go │ │ │ │ └── ip-name-lookup.wasm.go │ │ │ ├── tcp-create-socket │ │ │ │ ├── empty.s │ │ │ │ ├── tcp-create-socket.wasm.go │ │ │ │ └── tcp-create-socket.wit.go │ │ │ └── udp-create-socket │ │ │ │ ├── empty.s │ │ │ │ ├── udp-create-socket.wasm.go │ │ │ │ └── udp-create-socket.wit.go │ │ │ ├── clocks │ │ │ ├── wall-clock │ │ │ │ ├── empty.s │ │ │ │ └── wall-clock.wasm.go │ │ │ └── monotonic-clock │ │ │ │ ├── empty.s │ │ │ │ └── monotonic-clock.wasm.go │ │ │ └── filesystem │ │ │ ├── preopens │ │ │ ├── empty.s │ │ │ ├── preopens.wasm.go │ │ │ └── preopens.wit.go │ │ │ └── types │ │ │ ├── empty.s │ │ │ └── abi.go │ ├── Justfile │ ├── go.sum │ ├── wit │ │ ├── world.wit │ │ └── deps │ │ │ └── wasi-io-0.2.0 │ │ │ └── package.wit │ ├── .gitignore │ ├── wkg.lock │ └── README.md ├── eval-py │ ├── pyproject.toml │ ├── Justfile │ ├── wit_world │ │ ├── types.py │ │ └── __init__.py │ ├── main.py │ ├── wit │ │ └── world.wit │ ├── README.md │ └── uv.lock └── manifests │ ├── simple.yaml │ ├── with-secrets.yaml │ ├── production.yaml │ └── multi-component.yaml ├── Claude.md ├── .gitattributes ├── changelog.d ├── 572.misc.md ├── 516.feature.md ├── inspect-component-id.feature.md ├── 481.feature.md └── README.md ├── assets └── architecture.png ├── src └── lib.rs ├── crates ├── component2json │ ├── testdata │ │ ├── fetch-rs.wasm │ │ ├── context7-rs.wasm │ │ ├── filesystem.wasm │ │ └── brave-search-rs.wasm │ └── Cargo.toml ├── policy │ ├── testdata │ │ ├── minimal.yaml │ │ ├── environment-only.yaml │ │ ├── network-only.yaml │ │ ├── docker-privileged.yaml │ │ ├── storage-only.yaml │ │ ├── resource-limits.yaml │ │ ├── restricted.yaml │ │ ├── docker.yaml │ │ ├── web-service.yaml │ │ ├── development.yaml │ │ └── comprehensive.yaml │ └── Cargo.toml ├── mcp-server │ ├── src │ │ ├── lib.rs │ │ └── resources.rs │ └── Cargo.toml └── wassette │ ├── Cargo.toml │ └── src │ └── runtime_context.rs ├── rust-toolchain.toml ├── docs ├── versions.json ├── book.toml ├── quick-start.md ├── theme │ └── version-picker.css ├── mermaid-init.js ├── SUMMARY.md ├── design │ └── architecture.md ├── cookbook │ └── publishing-to-oci-registries.md └── TODO.md ├── .gitignore ├── audit.toml ├── rules └── agent.md ├── _typos.toml ├── policy.yaml ├── rustfmt.toml ├── CODE_OF_CONDUCT.md ├── SECURITY.md ├── scripts ├── install-protobuf.sh └── README.md ├── lychee.toml ├── .github ├── workflows │ ├── nix.yml │ ├── dependabot-automerge.yml │ └── validate-registry.yml ├── actions │ └── rust-cache │ │ └── action.yml └── dependabot.yml ├── CONTRIBUTING.md ├── .dockerignore ├── LICENSE ├── NOTICE ├── Formula └── wassette.rb ├── Dockerfile.prebuilt ├── deny.toml ├── component-registry.json ├── winget └── Microsoft.Wassette.yaml └── Dockerfile /examples/context7-rs/.gitignore: -------------------------------------------------------------------------------- 1 | /target -------------------------------------------------------------------------------- /Claude.md: -------------------------------------------------------------------------------- 1 | See [AGENTS.md](./AGENTS.md) 2 | -------------------------------------------------------------------------------- /examples/brave-search-rs/.gitignore: -------------------------------------------------------------------------------- 1 | target/ -------------------------------------------------------------------------------- /examples/fetch-rs/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /examples/filesystem-rs/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /examples/time-server-js/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | time.wasm -------------------------------------------------------------------------------- /examples/arxiv-rs/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | Cargo.lock 3 | *.wasm 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | .github/workflows/*.lock.yml linguist-generated=true merge=ours -------------------------------------------------------------------------------- /examples/github-js/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | *.wasm 3 | package-lock.json 4 | -------------------------------------------------------------------------------- /examples/github-js/Justfile: -------------------------------------------------------------------------------- 1 | build: 2 | npm install 3 | npm run build 4 | -------------------------------------------------------------------------------- /examples/memory-js/Justfile: -------------------------------------------------------------------------------- 1 | build: 2 | npm install 3 | npm run build 4 | -------------------------------------------------------------------------------- /examples/time-server-js/Justfile: -------------------------------------------------------------------------------- 1 | build: 2 | npm install 3 | npm run build -------------------------------------------------------------------------------- /changelog.d/572.misc.md: -------------------------------------------------------------------------------- 1 | Removed activation job from changelog-fragment workflow. 2 | -------------------------------------------------------------------------------- /examples/get-weather-js/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | *.wasm 4 | pnpm-lock.yaml 5 | out-dir -------------------------------------------------------------------------------- /examples/get-weather-js/Justfile: -------------------------------------------------------------------------------- 1 | build: 2 | npm install 3 | npm run build:component 4 | -------------------------------------------------------------------------------- /assets/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/wassette/HEAD/assets/architecture.png -------------------------------------------------------------------------------- /examples/get-open-meteo-weather-js/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | *.wasm 4 | pnpm-lock.yaml 5 | out-dir -------------------------------------------------------------------------------- /examples/get-open-meteo-weather-js/Justfile: -------------------------------------------------------------------------------- 1 | build: 2 | npm install 3 | npm run build:component 4 | -------------------------------------------------------------------------------- /examples/fetch-rs/fetch_rs.cwasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/wassette/HEAD/examples/fetch-rs/fetch_rs.cwasm -------------------------------------------------------------------------------- /examples/fetch-rs/fetch_rs.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/wassette/HEAD/examples/fetch-rs/fetch_rs.wasm -------------------------------------------------------------------------------- /examples/memory-js/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | package-lock.json 3 | *.wasm 4 | *.cwasm 5 | *.metadata.json 6 | downloads/ 7 | -------------------------------------------------------------------------------- /changelog.d/516.feature.md: -------------------------------------------------------------------------------- 1 | Enhanced permission error handling for network requests with improved user feedback and clearer guidance. -------------------------------------------------------------------------------- /examples/get-weather-js/get-weather.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/wassette/HEAD/examples/get-weather-js/get-weather.png -------------------------------------------------------------------------------- /examples/gomodule-go/gomodule-info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/wassette/HEAD/examples/gomodule-go/gomodule-info.png -------------------------------------------------------------------------------- /examples/filesystem-rs/get_file_into.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/wassette/HEAD/examples/filesystem-rs/get_file_into.png -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | pub use {mcp_server, wassette}; 5 | -------------------------------------------------------------------------------- /crates/component2json/testdata/fetch-rs.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/wassette/HEAD/crates/component2json/testdata/fetch-rs.wasm -------------------------------------------------------------------------------- /examples/brave-search-rs/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "wasm32-wasip2" 3 | 4 | [target.wasm32-wasip2] 5 | runner = "wasmtime" 6 | -------------------------------------------------------------------------------- /crates/component2json/testdata/context7-rs.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/wassette/HEAD/crates/component2json/testdata/context7-rs.wasm -------------------------------------------------------------------------------- /crates/component2json/testdata/filesystem.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/wassette/HEAD/crates/component2json/testdata/filesystem.wasm -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "1.90" 3 | components = ["rustfmt", "clippy"] 4 | targets = ["wasm32-wasip2", "wasm32-wasip1"] 5 | -------------------------------------------------------------------------------- /crates/component2json/testdata/brave-search-rs.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/wassette/HEAD/crates/component2json/testdata/brave-search-rs.wasm -------------------------------------------------------------------------------- /examples/get-open-meteo-weather-js/get-weather.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/wassette/HEAD/examples/get-open-meteo-weather-js/get-weather.png -------------------------------------------------------------------------------- /examples/fetch-rs/Cargo-component.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by cargo-component. 2 | # It is not intended for manual editing. 3 | version = 1 4 | -------------------------------------------------------------------------------- /docs/versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "versions": [ 3 | "latest", 4 | "v0.3.0", 5 | "v0.2.0", 6 | "v0.1.0" 7 | ], 8 | "latest": "latest" 9 | } 10 | -------------------------------------------------------------------------------- /examples/context7-rs/wit/deps/cli/run.wit: -------------------------------------------------------------------------------- 1 | @since(version = 0.2.0) 2 | interface run { 3 | /// Run the program. 4 | @since(version = 0.2.0) 5 | run: func() -> result; 6 | } 7 | -------------------------------------------------------------------------------- /examples/gomodule-go/go.mod: -------------------------------------------------------------------------------- 1 | module gomodule-server-go 2 | 3 | go 1.23.2 4 | 5 | require ( 6 | github.com/ydnar/wasi-http-go v0.0.0-20250620060720-9877ebcf27b5 7 | go.bytecodealliance.org/cm v0.2.2 8 | ) 9 | -------------------------------------------------------------------------------- /crates/policy/testdata/minimal.yaml: -------------------------------------------------------------------------------- 1 | $schema: https://raw.githubusercontent.com/microsoft/policy-mcp/main/schema/policy-v1.0.schema.json 2 | version: "1.0" 3 | description: "Minimal valid policy" 4 | permissions: {} -------------------------------------------------------------------------------- /examples/memory-js/policy.yaml: -------------------------------------------------------------------------------- 1 | $schema: https://raw.githubusercontent.com/microsoft/policy-mcp/main/schema/policy-v1.0.schema.json 2 | version: "1.0" 3 | description: "Permission policy for memory server" 4 | permissions: {} 5 | -------------------------------------------------------------------------------- /examples/time-server-js/policy.yaml: -------------------------------------------------------------------------------- 1 | $schema: https://raw.githubusercontent.com/microsoft/policy-mcp/main/schema/policy-v1.0.schema.json 2 | version: "1.0" 3 | description: "Permission policy for time-server" 4 | permissions: {} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /bin 3 | .DS_Store 4 | /result 5 | # Env and .envrc files 6 | .env* 7 | 8 | # mdbook output 9 | /docs/book 10 | mdbook 11 | mdbook-mermaid 12 | 13 | # typos binary 14 | typos 15 | __pycache__/ 16 | -------------------------------------------------------------------------------- /examples/brave-search-rs/policy.yaml: -------------------------------------------------------------------------------- 1 | version: "1.0" 2 | description: "Permission policy for brave-search-rs example in wassette" 3 | permissions: 4 | network: 5 | allow: 6 | - host: "https://api.search.brave.com/" 7 | -------------------------------------------------------------------------------- /examples/context7-rs/Justfile: -------------------------------------------------------------------------------- 1 | install-wasi-target: 2 | rustup target add wasm32-wasip2 3 | 4 | build mode="debug": install-wasi-target 5 | cargo build --target wasm32-wasip2 {{ if mode == "release" { "--release" } else { "" } }} 6 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/local/gomodule-server/gomodule/gomodule.wit.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | // Package gomodule represents the exported interface "local:gomodule-server/gomodule". 4 | package gomodule 5 | -------------------------------------------------------------------------------- /examples/arxiv-rs/policy.yaml: -------------------------------------------------------------------------------- 1 | version: "1.0" 2 | description: "Permission policy for arxiv-rs example in wassette" 3 | permissions: 4 | network: 5 | allow: 6 | - host: "http://export.arxiv.org/" 7 | - host: "http://arxiv.org/" 8 | -------------------------------------------------------------------------------- /examples/context7-rs/wit/deps/cli/command.wit: -------------------------------------------------------------------------------- 1 | package wasi:cli@0.2.1; 2 | 3 | @since(version = 0.2.0) 4 | world command { 5 | @since(version = 0.2.0) 6 | include imports; 7 | 8 | @since(version = 0.2.0) 9 | export run; 10 | } 11 | -------------------------------------------------------------------------------- /examples/context7-rs/wit/deps/io/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:io@0.2.1; 2 | 3 | @since(version = 0.2.0) 4 | world imports { 5 | @since(version = 0.2.0) 6 | import streams; 7 | 8 | @since(version = 0.2.0) 9 | import poll; 10 | } 11 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/exit/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/stdin/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/io/error/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/io/poll/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/stderr/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/stdout/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/http/types/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/io/streams/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/random/random/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/sockets/tcp/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/sockets/udp/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/gomodule-go/Justfile: -------------------------------------------------------------------------------- 1 | bindings: 2 | go run go.bytecodealliance.org/cmd/wit-bindgen-go@v0.6.2 generate -o gen ./wit 3 | 4 | build: bindings 5 | tinygo build -o gomodule.wasm -target wasip2 --wit-package ./wit --wit-world gomodule-server main.go -------------------------------------------------------------------------------- /examples/gomodule-go/gen/local/gomodule-server/gomodule-server/gomodule-server.wit.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | // Package gomoduleserver represents the world "local:gomodule-server/gomodule-server". 4 | package gomoduleserver 5 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/environment/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/terminal-input/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/terminal-output/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/terminal-stderr/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/terminal-stdin/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/terminal-stdout/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/clocks/wall-clock/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/filesystem/preopens/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/filesystem/types/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/random/insecure/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/sockets/network/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/context7-rs/wit/deps/filesystem/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:filesystem@0.2.1; 2 | 3 | @since(version = 0.2.0) 4 | world imports { 5 | @since(version = 0.2.0) 6 | import types; 7 | @since(version = 0.2.0) 8 | import preopens; 9 | } 10 | -------------------------------------------------------------------------------- /examples/eval-py/pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "eval-py" 3 | version = "0.1.0" 4 | description = "Python evaluation MCP server" 5 | readme = "README.md" 6 | requires-python = ">=3.10" 7 | dependencies = [ 8 | "componentize-py>=0.17.1", 9 | ] 10 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/clocks/monotonic-clock/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/http/outgoing-handler/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/random/insecure-seed/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/sockets/instance-network/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/sockets/ip-name-lookup/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/context7-rs/policy.yaml: -------------------------------------------------------------------------------- 1 | version: "1.0" 2 | description: "Permission policy for context7 component" 3 | permissions: 4 | network: 5 | allow: 6 | - host: "context7.com" 7 | environment: 8 | allow: 9 | - key: "CONTEXT7_API_KEY" 10 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/local/gomodule-server/gomodule/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/sockets/tcp-create-socket/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/sockets/udp-create-socket/empty.s: -------------------------------------------------------------------------------- 1 | // This file exists for testing this package without WebAssembly, 2 | // allowing empty function bodies with a //go:wasmimport directive. 3 | // See https://pkg.go.dev/cmd/compile for more information. 4 | -------------------------------------------------------------------------------- /examples/time-server-js/time.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | async function getCurrentTime() { 5 | return new Date().toISOString(); 6 | } 7 | 8 | export const time = { 9 | getCurrentTime 10 | }; -------------------------------------------------------------------------------- /examples/fetch-rs/wit/world.wit: -------------------------------------------------------------------------------- 1 | package component:fetch-rs; 2 | 3 | /// An example world for the component to target. 4 | world fetch { 5 | /// Fetch data from a URL and return the response body as a String 6 | export fetch: func(url: string) -> result; 7 | } 8 | -------------------------------------------------------------------------------- /examples/get-open-meteo-weather-js/wit/mcp.wit: -------------------------------------------------------------------------------- 1 | package mossaka:mcp@0.1.0; 2 | 3 | /// Weather information services 4 | world weather-mcp { 5 | /// Get current weather information for a specified city 6 | export get-weather: func(city: string) -> result; 7 | } -------------------------------------------------------------------------------- /examples/fetch-rs/policy.yaml: -------------------------------------------------------------------------------- 1 | $schema: https://raw.githubusercontent.com/microsoft/policy-mcp/main/schema/policy-v1.0.schema.json 2 | version: "1.0" 3 | description: "Permission policy for wassette weather demo" 4 | permissions: 5 | network: 6 | allow: 7 | - host: "https://rss.nytimes.com/" 8 | -------------------------------------------------------------------------------- /changelog.d/inspect-component-id.feature.md: -------------------------------------------------------------------------------- 1 | Modified `wassette inspect` command to accept component ID instead of file path or URI. Components must now be loaded first using `component load` before inspection, which better aligns with the command's intended purpose of inspecting already-loaded components. 2 | -------------------------------------------------------------------------------- /audit.toml: -------------------------------------------------------------------------------- 1 | # Cargo Audit Configuration 2 | [advisories] 3 | # Allow the paste crate warning as it's classified as unmaintained but still functional 4 | # We acknowledge the risk and plan to migrate to pastey in the future when possible 5 | ignore = [ 6 | "RUSTSEC-2024-0436" # paste - no longer maintained 7 | ] -------------------------------------------------------------------------------- /examples/get-weather-js/wit/mcp.wit: -------------------------------------------------------------------------------- 1 | package mossaka:mcp@0.1.0; 2 | 3 | /// Weather information services 4 | world weather-mcp { 5 | import wasi:config/store@0.2.0-draft; 6 | 7 | /// Get current weather information for a specified city 8 | export get-weather: func(city: string) -> result; 9 | } -------------------------------------------------------------------------------- /rules/agent.md: -------------------------------------------------------------------------------- 1 | # Wassette AI Agent Instructions 2 | 3 | **ALWAYS use the built-in `grant-storage-permission`, `grant-network-permission`, and `grant-environment-variable-permission` tools to manage permissions for Wassette components. NEVER manually edit or modify policy files directly (such as `policy.yaml` files).** 4 | -------------------------------------------------------------------------------- /examples/context7-rs/wit/deps/random/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:random@0.2.1; 2 | 3 | @since(version = 0.2.0) 4 | world imports { 5 | @since(version = 0.2.0) 6 | import random; 7 | 8 | @since(version = 0.2.0) 9 | import insecure; 10 | 11 | @since(version = 0.2.0) 12 | import insecure-seed; 13 | } 14 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/exit/exit.wasm.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package exit 4 | 5 | // This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0". 6 | 7 | //go:wasmimport wasi:cli/exit@0.2.0 exit 8 | //go:noescape 9 | func wasmimport_Exit(status0 uint32) 10 | -------------------------------------------------------------------------------- /examples/context7-rs/wit/deps/clocks/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:clocks@0.2.1; 2 | 3 | @since(version = 0.2.0) 4 | world imports { 5 | @since(version = 0.2.0) 6 | import monotonic-clock; 7 | @since(version = 0.2.0) 8 | import wall-clock; 9 | @unstable(feature = clocks-timezone) 10 | import timezone; 11 | } 12 | -------------------------------------------------------------------------------- /examples/manifests/simple.yaml: -------------------------------------------------------------------------------- 1 | version: 1 2 | components: 3 | - uri: oci://ghcr.io/microsoft/get-weather-js:latest 4 | name: weather-service 5 | permissions: 6 | network: 7 | allow: 8 | - host: api.openweathermap.com 9 | environment: 10 | allow: 11 | - key: OPENWEATHER_API_KEY 12 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/stdin/stdin.wasm.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package stdin 4 | 5 | // This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0". 6 | 7 | //go:wasmimport wasi:cli/stdin@0.2.0 get-stdin 8 | //go:noescape 9 | func wasmimport_GetStdin() (result0 uint32) 10 | -------------------------------------------------------------------------------- /_typos.toml: -------------------------------------------------------------------------------- 1 | [files] 2 | extend-exclude = [ 3 | "**/*.wit", 4 | "**/*.wit.go", 5 | "**/mermaid.min.js", 6 | "**/mermaid-init.js", 7 | "**/bindings.rs", 8 | ] 9 | 10 | [default.extend-words] 11 | # Part of "Wassette" pronunciation guide 12 | Wass = "Wass" 13 | # CSS variable name in docs/theme/toc.css 14 | existant = "existant" 15 | -------------------------------------------------------------------------------- /changelog.d/481.feature.md: -------------------------------------------------------------------------------- 1 | Added `wassette registry` CLI subcommands for searching and fetching components from the centralized component registry. New commands include `wassette registry search [query]` to search for components by name, description, or URI, and `wassette registry get ` to fetch and load components directly from the registry. 2 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/stderr/stderr.wasm.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package stderr 4 | 5 | // This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0". 6 | 7 | //go:wasmimport wasi:cli/stderr@0.2.0 get-stderr 8 | //go:noescape 9 | func wasmimport_GetStderr() (result0 uint32) 10 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/stdout/stdout.wasm.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package stdout 4 | 5 | // This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0". 6 | 7 | //go:wasmimport wasi:cli/stdout@0.2.0 get-stdout 8 | //go:noescape 9 | func wasmimport_GetStdout() (result0 uint32) 10 | -------------------------------------------------------------------------------- /examples/get-open-meteo-weather-js/policy.yaml: -------------------------------------------------------------------------------- 1 | $schema: https://raw.githubusercontent.com/microsoft/policy-mcp/main/schema/policy-v1.0.schema.json 2 | version: "1.0" 3 | description: "Permission policy for wassette weather demo" 4 | permissions: 5 | network: 6 | allow: 7 | - host: "geocoding-api.open-meteo.com" 8 | - host: "api.open-meteo.com" 9 | -------------------------------------------------------------------------------- /policy.yaml: -------------------------------------------------------------------------------- 1 | $schema: https://raw.githubusercontent.com/microsoft/policy-mcp/main/schema/policy-v1.0.schema.json 2 | version: "1.0" 3 | description: "Permission policy for wassette weather demo" 4 | permissions: 5 | network: 6 | allow: 7 | - host: "api.openweathermap.org" 8 | environment: 9 | allow: 10 | - key: "OPENWEATHER_API_KEY" 11 | -------------------------------------------------------------------------------- /examples/github-js/policy.yaml: -------------------------------------------------------------------------------- 1 | $schema: https://raw.githubusercontent.com/microsoft/policy-mcp/main/schema/policy-v1.0.schema.json 2 | version: "1.0" 3 | description: "Permission policy for GitHub API integration" 4 | permissions: 5 | network: 6 | allow: 7 | - host: "api.github.com" 8 | environment: 9 | allow: 10 | - key: "GITHUB_TOKEN" 11 | -------------------------------------------------------------------------------- /examples/brave-search-rs/wit/world.wit: -------------------------------------------------------------------------------- 1 | package component:brave-search-rs; 2 | 3 | /// An example world for the component to target. 4 | world brave-search { 5 | /// Search using Brave Search API and return the results as a formatted string 6 | /// Reads BRAVE_SEARCH_API_KEY from environment variables 7 | export search: func(query: string) -> result; 8 | } 9 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/sockets/network/network.wasm.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package network 4 | 5 | // This file contains wasmimport and wasmexport declarations for "wasi:sockets@0.2.0". 6 | 7 | //go:wasmimport wasi:sockets/network@0.2.0 [resource-drop]network 8 | //go:noescape 9 | func wasmimport_NetworkResourceDrop(self0 uint32) 10 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | newline_style = "Native" 2 | unstable_features = true # Cargo fmt now needs to be called with `cargo +nightly fmt` 3 | group_imports = "StdExternalCrate" # create three groups for std, external and local crates 4 | # Merge imports from the same module 5 | # See: https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#imports_granularity 6 | imports_granularity = "Module" -------------------------------------------------------------------------------- /examples/get-weather-js/policy.yaml: -------------------------------------------------------------------------------- 1 | $schema: https://raw.githubusercontent.com/microsoft/policy-mcp/main/schema/policy-v1.0.schema.json 2 | version: "1.0" 3 | description: "Permission policy for wassette weather demo" 4 | permissions: 5 | network: 6 | allow: 7 | - host: "api.openweathermap.org" 8 | environment: 9 | allow: 10 | - key: "OPENWEATHER_API_KEY" 11 | -------------------------------------------------------------------------------- /examples/context7-rs/wit/deps/filesystem/preopens.wit: -------------------------------------------------------------------------------- 1 | package wasi:filesystem@0.2.1; 2 | 3 | @since(version = 0.2.0) 4 | interface preopens { 5 | @since(version = 0.2.0) 6 | use types.{descriptor}; 7 | 8 | /// Return the set of preopened directories, and their path. 9 | @since(version = 0.2.0) 10 | get-directories: func() -> list>; 11 | } 12 | -------------------------------------------------------------------------------- /examples/fetch-rs/Justfile: -------------------------------------------------------------------------------- 1 | install-wasi-target: 2 | rustup target add wasm32-wasip2 3 | 4 | build mode="debug": install-wasi-target 5 | cargo build --target wasm32-wasip2 {{ if mode == "release" { "--release" } else { "" } }} 6 | 7 | build-auditable mode="debug": install-wasi-target 8 | cargo auditable build --target wasm32-wasip2 {{ if mode == "release" { "--release" } else { "" } }} -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/random/insecure-seed/insecure-seed.wasm.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package insecureseed 4 | 5 | // This file contains wasmimport and wasmexport declarations for "wasi:random@0.2.0". 6 | 7 | //go:wasmimport wasi:random/insecure-seed@0.2.0 insecure-seed 8 | //go:noescape 9 | func wasmimport_InsecureSeed(result *[2]uint64) 10 | -------------------------------------------------------------------------------- /examples/arxiv-rs/Justfile: -------------------------------------------------------------------------------- 1 | install-wasi-target: 2 | rustup target add wasm32-wasip2 3 | 4 | build mode="debug": install-wasi-target 5 | cargo build --target wasm32-wasip2 {{ if mode == "release" { "--release" } else { "" } }} 6 | 7 | build-auditable mode="debug": install-wasi-target 8 | cargo auditable build --target wasm32-wasip2 {{ if mode == "release" { "--release" } else { "" } }} 9 | -------------------------------------------------------------------------------- /examples/filesystem-rs/Justfile: -------------------------------------------------------------------------------- 1 | install-wasi-target: 2 | rustup target add wasm32-wasip2 3 | 4 | build mode="debug": install-wasi-target 5 | cargo build --target wasm32-wasip2 {{ if mode == "release" { "--release" } else { "" } }} 6 | 7 | build-auditable mode="debug": install-wasi-target 8 | cargo auditable build --target wasm32-wasip2 {{ if mode == "release" { "--release" } else { "" } }} -------------------------------------------------------------------------------- /examples/brave-search-rs/Justfile: -------------------------------------------------------------------------------- 1 | install-wasi-target: 2 | rustup target add wasm32-wasip2 3 | 4 | build mode="debug": install-wasi-target 5 | cargo build --target wasm32-wasip2 {{ if mode == "release" { "--release" } else { "" } }} 6 | 7 | build-auditable mode="debug": install-wasi-target 8 | cargo auditable build --target wasm32-wasip2 {{ if mode == "release" { "--release" } else { "" } }} 9 | -------------------------------------------------------------------------------- /examples/context7-rs/wit/deps/sockets/instance-network.wit: -------------------------------------------------------------------------------- 1 | 2 | /// This interface provides a value-export of the default network handle.. 3 | @since(version = 0.2.0) 4 | interface instance-network { 5 | @since(version = 0.2.0) 6 | use network.{network}; 7 | 8 | /// Get a handle to the default network. 9 | @since(version = 0.2.0) 10 | instance-network: func() -> network; 11 | } 12 | -------------------------------------------------------------------------------- /examples/eval-py/Justfile: -------------------------------------------------------------------------------- 1 | install-uv: 2 | if ! command -v uv &> /dev/null; then curl -LsSf https://astral.sh/uv/install.sh | sh; fi 3 | 4 | install: install-uv 5 | uv pip install componentize-py 6 | 7 | bindings: 8 | uv run componentize-py -d wit -w sandbox bindings . 9 | 10 | build: 11 | uv run componentize-py -d wit -w sandbox componentize -s main -o eval.wasm 12 | 13 | all: bindings build -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/terminal-input/terminal-input.wasm.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package terminalinput 4 | 5 | // This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0". 6 | 7 | //go:wasmimport wasi:cli/terminal-input@0.2.0 [resource-drop]terminal-input 8 | //go:noescape 9 | func wasmimport_TerminalInputResourceDrop(self0 uint32) 10 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/sockets/instance-network/instance-network.wasm.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package instancenetwork 4 | 5 | // This file contains wasmimport and wasmexport declarations for "wasi:sockets@0.2.0". 6 | 7 | //go:wasmimport wasi:sockets/instance-network@0.2.0 instance-network 8 | //go:noescape 9 | func wasmimport_InstanceNetwork() (result0 uint32) 10 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/terminal-output/terminal-output.wasm.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package terminaloutput 4 | 5 | // This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0". 6 | 7 | //go:wasmimport wasi:cli/terminal-output@0.2.0 [resource-drop]terminal-output 8 | //go:noescape 9 | func wasmimport_TerminalOutputResourceDrop(self0 uint32) 10 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/sockets/network/abi.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package network 4 | 5 | import ( 6 | "go.bytecodealliance.org/cm" 7 | "unsafe" 8 | ) 9 | 10 | // IPv6SocketAddressShape is used for storage in variant or result types. 11 | type IPv6SocketAddressShape struct { 12 | _ cm.HostLayout 13 | shape [unsafe.Sizeof(IPv6SocketAddress{})]byte 14 | } 15 | -------------------------------------------------------------------------------- /crates/mcp-server/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | pub use wassette::LifecycleManager; 5 | 6 | pub mod components; 7 | pub mod prompts; 8 | pub mod resources; 9 | pub mod tools; 10 | 11 | pub use prompts::{handle_prompts_get, handle_prompts_list}; 12 | pub use resources::handle_resources_list; 13 | pub use tools::{handle_tools_call, handle_tools_list}; 14 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/sockets/ip-name-lookup/abi.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package ipnamelookup 4 | 5 | import ( 6 | "go.bytecodealliance.org/cm" 7 | "unsafe" 8 | ) 9 | 10 | // OptionIPAddressShape is used for storage in variant or result types. 11 | type OptionIPAddressShape struct { 12 | _ cm.HostLayout 13 | shape [unsafe.Sizeof(cm.Option[IPAddress]{})]byte 14 | } 15 | -------------------------------------------------------------------------------- /examples/time-server-js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "time-server", 3 | "version": "1.0.0", 4 | "main": "time.js", 5 | "scripts": { 6 | "build": "jco componentize ./time.js --wit ./wit -d http -d random -d stdio -o ./time.wasm" 7 | }, 8 | "license": "Apache-2.0", 9 | "dependencies": { 10 | "@bytecodealliance/componentize-js": "0.18.1", 11 | "@bytecodealliance/jco": "^1.11.1" 12 | } 13 | } -------------------------------------------------------------------------------- /examples/gomodule-go/go.sum: -------------------------------------------------------------------------------- 1 | github.com/ydnar/wasi-http-go v0.0.0-20250620060720-9877ebcf27b5 h1:WFlSpsBgZ0SZcbNJkpuV6bLFPm0rpjiII1Sot14Oucs= 2 | github.com/ydnar/wasi-http-go v0.0.0-20250620060720-9877ebcf27b5/go.mod h1:d8SobHm5UmjaDQZQhxSnzTer69vfXAMnNOn8ios/Jb4= 3 | go.bytecodealliance.org/cm v0.2.2 h1:M9iHS6qs884mbQbIjtLX1OifgyPG9DuMs2iwz8G4WQA= 4 | go.bytecodealliance.org/cm v0.2.2/go.mod h1:JD5vtVNZv7sBoQQkvBvAAVKJPhR/bqBH7yYXTItMfZI= 5 | -------------------------------------------------------------------------------- /examples/time-server-js/wit/world.wit: -------------------------------------------------------------------------------- 1 | package local:time-server; 2 | 3 | interface time { 4 | /// Get the current date and time as a formatted string 5 | /// Returns the current timestamp in ISO 8601 format 6 | get-current-time: func() -> string; 7 | } 8 | 9 | /// A world that exports time server functionality 10 | /// This component provides access to current system time information 11 | world time-server { 12 | export time; 13 | } -------------------------------------------------------------------------------- /crates/policy/testdata/environment-only.yaml: -------------------------------------------------------------------------------- 1 | $schema: https://raw.githubusercontent.com/microsoft/policy-mcp/main/schema/policy-v1.0.schema.json 2 | version: "1.0" 3 | description: "Environment-only policy for basic shell access" 4 | permissions: 5 | environment: 6 | allow: 7 | - key: "PATH" 8 | - key: "HOME" 9 | - key: "USER" 10 | - key: "SHELL" 11 | - key: "TERM" 12 | - key: "LANG" 13 | - key: "NODE_ENV" 14 | - key: "PYTHON_PATH" -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/terminal-stdin/terminal-stdin.wasm.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package terminalstdin 4 | 5 | import ( 6 | "go.bytecodealliance.org/cm" 7 | ) 8 | 9 | // This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0". 10 | 11 | //go:wasmimport wasi:cli/terminal-stdin@0.2.0 get-terminal-stdin 12 | //go:noescape 13 | func wasmimport_GetTerminalStdin(result *cm.Option[TerminalInput]) 14 | -------------------------------------------------------------------------------- /examples/manifests/with-secrets.yaml: -------------------------------------------------------------------------------- 1 | version: 1 2 | components: 3 | - uri: oci://ghcr.io/microsoft/get-weather-js:latest 4 | name: weather-service 5 | permissions: 6 | network: 7 | allow: 8 | - host: api.openweathermap.com 9 | environment: 10 | allow: 11 | - key: OPENWEATHER_API_KEY 12 | value_from: OPENWEATHER_API_KEY 13 | - key: API_TIMEOUT 14 | value_from: API_TIMEOUT 15 | -------------------------------------------------------------------------------- /examples/get-weather-js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module", 3 | "dependencies": { 4 | "@bytecodealliance/componentize-js": "0.18.1", 5 | "@bytecodealliance/jco": "^1.11.1" 6 | }, 7 | "scripts": { 8 | "build:component": "jco componentize -w ./wit weather.js -o weather.wasm", 9 | "transpile": "jco transpile weather.wasm -o out-dir", 10 | "debug": "node use-weather.js" 11 | }, 12 | "license": "Apache-2.0" 13 | } 14 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/terminal-stderr/terminal-stderr.wasm.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package terminalstderr 4 | 5 | import ( 6 | "go.bytecodealliance.org/cm" 7 | ) 8 | 9 | // This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0". 10 | 11 | //go:wasmimport wasi:cli/terminal-stderr@0.2.0 get-terminal-stderr 12 | //go:noescape 13 | func wasmimport_GetTerminalStderr(result *cm.Option[TerminalOutput]) 14 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/terminal-stdout/terminal-stdout.wasm.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package terminalstdout 4 | 5 | import ( 6 | "go.bytecodealliance.org/cm" 7 | ) 8 | 9 | // This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0". 10 | 11 | //go:wasmimport wasi:cli/terminal-stdout@0.2.0 get-terminal-stdout 12 | //go:noescape 13 | func wasmimport_GetTerminalStdout(result *cm.Option[TerminalOutput]) 14 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/filesystem/preopens/preopens.wasm.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package preopens 4 | 5 | import ( 6 | "go.bytecodealliance.org/cm" 7 | ) 8 | 9 | // This file contains wasmimport and wasmexport declarations for "wasi:filesystem@0.2.0". 10 | 11 | //go:wasmimport wasi:filesystem/preopens@0.2.0 get-directories 12 | //go:noescape 13 | func wasmimport_GetDirectories(result *cm.List[cm.Tuple[Descriptor, string]]) 14 | -------------------------------------------------------------------------------- /examples/github-js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "github-mcp", 3 | "version": "1.0.0", 4 | "description": "GitHub REST API integration as a WebAssembly component", 5 | "type": "module", 6 | "main": "github.js", 7 | "scripts": { 8 | "build": "jco componentize -w ./wit github.js -o github.wasm" 9 | }, 10 | "license": "MIT", 11 | "dependencies": { 12 | "@bytecodealliance/componentize-js": "0.18.1", 13 | "@bytecodealliance/jco": "^1.11.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/get-open-meteo-weather-js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module", 3 | "dependencies": { 4 | "@bytecodealliance/componentize-js": "0.18.1", 5 | "@bytecodealliance/jco": "^1.11.1" 6 | }, 7 | "scripts": { 8 | "build:component": "jco componentize -w ./wit weather.js -o weather.wasm", 9 | "transpile": "jco transpile weather.wasm -o out-dir", 10 | "debug": "node use-weather.js" 11 | }, 12 | "license": "Apache-2.0" 13 | } 14 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/clocks/wall-clock/wall-clock.wasm.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package wallclock 4 | 5 | // This file contains wasmimport and wasmexport declarations for "wasi:clocks@0.2.0". 6 | 7 | //go:wasmimport wasi:clocks/wall-clock@0.2.0 now 8 | //go:noescape 9 | func wasmimport_Now(result *DateTime) 10 | 11 | //go:wasmimport wasi:clocks/wall-clock@0.2.0 resolution 12 | //go:noescape 13 | func wasmimport_Resolution(result *DateTime) 14 | -------------------------------------------------------------------------------- /crates/component2json/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "component2json" 3 | version = "0.1.0" 4 | edition = "2021" 5 | description = "A library for converting WebAssembly Interface Types (WIT) to JSON Schema and back" 6 | license.workspace = true 7 | 8 | [dependencies] 9 | serde = { workspace = true, features = ["derive"] } 10 | serde_json = { workspace = true } 11 | wasmtime = { workspace = true } 12 | wasmparser = "0.240" 13 | thiserror = { workspace = true } 14 | 15 | [dev-dependencies] 16 | wat = "1.243" -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/io/error/error.wasm.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package ioerror 4 | 5 | // This file contains wasmimport and wasmexport declarations for "wasi:io@0.2.0". 6 | 7 | //go:wasmimport wasi:io/error@0.2.0 [resource-drop]error 8 | //go:noescape 9 | func wasmimport_ErrorResourceDrop(self0 uint32) 10 | 11 | //go:wasmimport wasi:io/error@0.2.0 [method]error.to-debug-string 12 | //go:noescape 13 | func wasmimport_ErrorToDebugString(self0 uint32, result *string) 14 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/sockets/tcp-create-socket/tcp-create-socket.wasm.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package tcpcreatesocket 4 | 5 | import ( 6 | "go.bytecodealliance.org/cm" 7 | ) 8 | 9 | // This file contains wasmimport and wasmexport declarations for "wasi:sockets@0.2.0". 10 | 11 | //go:wasmimport wasi:sockets/tcp-create-socket@0.2.0 create-tcp-socket 12 | //go:noescape 13 | func wasmimport_CreateTCPSocket(addressFamily0 uint32, result *cm.Result[TCPSocket, TCPSocket, ErrorCode]) 14 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/sockets/udp-create-socket/udp-create-socket.wasm.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package udpcreatesocket 4 | 5 | import ( 6 | "go.bytecodealliance.org/cm" 7 | ) 8 | 9 | // This file contains wasmimport and wasmexport declarations for "wasi:sockets@0.2.0". 10 | 11 | //go:wasmimport wasi:sockets/udp-create-socket@0.2.0 create-udp-socket 12 | //go:noescape 13 | func wasmimport_CreateUDPSocket(addressFamily0 uint32, result *cm.Result[UDPSocket, UDPSocket, ErrorCode]) 14 | -------------------------------------------------------------------------------- /crates/policy/testdata/network-only.yaml: -------------------------------------------------------------------------------- 1 | $schema: https://raw.githubusercontent.com/microsoft/policy-mcp/main/schema/policy-v1.0.schema.json 2 | version: "1.0" 3 | description: "Network-only policy for API access" 4 | permissions: 5 | network: 6 | allow: 7 | - host: "api.github.com" 8 | - host: "*.googleapis.com" 9 | - host: "registry.npmjs.org" 10 | - cidr: "192.168.1.0/24" 11 | - cidr: "10.0.0.0/8" 12 | deny: 13 | - host: "*.facebook.com" 14 | - host: "*.doubleclick.net" 15 | - cidr: "169.254.0.0/16" -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/http/outgoing-handler/outgoing-handler.wasm.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package outgoinghandler 4 | 5 | import ( 6 | "go.bytecodealliance.org/cm" 7 | ) 8 | 9 | // This file contains wasmimport and wasmexport declarations for "wasi:http@0.2.0". 10 | 11 | //go:wasmimport wasi:http/outgoing-handler@0.2.0 handle 12 | //go:noescape 13 | func wasmimport_Handle(request0 uint32, options0 uint32, options1 uint32, result *cm.Result[ErrorCodeShape, FutureIncomingResponse, ErrorCode]) 14 | -------------------------------------------------------------------------------- /crates/mcp-server/src/resources.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | use anyhow::Result; 5 | use rmcp::model::{ListResourcesRequest, ListResourcesResult}; 6 | 7 | pub async fn handle_resources_list(req: serde_json::Value) -> Result { 8 | let _parsed_req: ListResourcesRequest = serde_json::from_value(req)?; 9 | let response = ListResourcesResult { 10 | resources: vec![], 11 | next_cursor: None, 12 | }; 13 | Ok(serde_json::to_value(response)?) 14 | } 15 | -------------------------------------------------------------------------------- /examples/context7-rs/wit/deps/sockets/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:sockets@0.2.1; 2 | 3 | @since(version = 0.2.0) 4 | world imports { 5 | @since(version = 0.2.0) 6 | import instance-network; 7 | @since(version = 0.2.0) 8 | import network; 9 | @since(version = 0.2.0) 10 | import udp; 11 | @since(version = 0.2.0) 12 | import udp-create-socket; 13 | @since(version = 0.2.0) 14 | import tcp; 15 | @since(version = 0.2.0) 16 | import tcp-create-socket; 17 | @since(version = 0.2.0) 18 | import ip-name-lookup; 19 | } 20 | -------------------------------------------------------------------------------- /examples/filesystem-rs/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "filesystem" 3 | version = "0.1.0" 4 | edition = "2021" 5 | license = "MIT" 6 | 7 | [dependencies] 8 | anyhow = "1.0.95" 9 | wit-bindgen-rt = { version = "0.37.0", features = ["bitflags"] } 10 | 11 | [lib] 12 | crate-type = ["cdylib"] 13 | 14 | [profile.release] 15 | codegen-units = 1 16 | opt-level = "s" 17 | debug = false 18 | strip = true 19 | lto = true 20 | 21 | [package.metadata.component] 22 | package = "component:filesystem" 23 | 24 | [package.metadata.component.dependencies] 25 | 26 | [workspace] 27 | -------------------------------------------------------------------------------- /crates/mcp-server/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mcp-server" 3 | version = "0.1.0" 4 | edition = "2021" 5 | license.workspace = true 6 | 7 | [dependencies] 8 | serde_json = { workspace = true } 9 | anyhow = { workspace = true } 10 | rmcp = { workspace = true } 11 | wassette = { workspace = true } 12 | tracing = { workspace = true, features = ["attributes"] } 13 | futures = { workspace = true } 14 | 15 | [dev-dependencies] 16 | tokio-test = { workspace = true } 17 | tempfile = { workspace = true } 18 | tokio = { workspace = true, features = ["test-util", "macros"] } 19 | -------------------------------------------------------------------------------- /examples/context7-rs/Cargo-component.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by cargo-component. 2 | # It is not intended for manual editing. 3 | version = 1 4 | 5 | [[package]] 6 | name = "wasi:cli" 7 | 8 | [[package.version]] 9 | requirement = "^0.2.0" 10 | version = "0.2.1" 11 | digest = "sha256:3ecc55e42b2fef72492c380159006c675952647e45e07e1a7b23ffe343d863b8" 12 | 13 | [[package]] 14 | name = "wasi:http" 15 | 16 | [[package.version]] 17 | requirement = "^0.2.0" 18 | version = "0.2.1" 19 | digest = "sha256:a2e003de97f144467a05a545d376207267e82abb18741505a6b87aa40f4b33db" 20 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/random/random/random.wasm.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package random 4 | 5 | import ( 6 | "go.bytecodealliance.org/cm" 7 | ) 8 | 9 | // This file contains wasmimport and wasmexport declarations for "wasi:random@0.2.0". 10 | 11 | //go:wasmimport wasi:random/random@0.2.0 get-random-bytes 12 | //go:noescape 13 | func wasmimport_GetRandomBytes(len0 uint64, result *cm.List[uint8]) 14 | 15 | //go:wasmimport wasi:random/random@0.2.0 get-random-u64 16 | //go:noescape 17 | func wasmimport_GetRandomU64() (result0 uint64) 18 | -------------------------------------------------------------------------------- /examples/fetch-rs/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fetch-rs" 3 | version = "0.1.0" 4 | edition = "2021" 5 | license = "MIT" 6 | 7 | [dependencies] 8 | serde_json = "1.0.137" 9 | spin-executor = "3.0.1" 10 | spin-sdk = "3.0.1" 11 | wit-bindgen-rt = { version = "0.26.0", features = ["bitflags"] } 12 | scraper = "0.18.1" 13 | 14 | [lib] 15 | crate-type = ["cdylib"] 16 | 17 | [profile.release] 18 | codegen-units = 1 19 | opt-level = "s" 20 | debug = false 21 | strip = true 22 | lto = true 23 | 24 | [package.metadata.component] 25 | package = "component:fetch-rs" 26 | 27 | [workspace] 28 | -------------------------------------------------------------------------------- /examples/arxiv-rs/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "arxiv-rs" 3 | version = "0.1.0" 4 | edition = "2021" 5 | license = "MIT" 6 | 7 | [dependencies] 8 | serde = { version = "1.0", features = ["derive"] } 9 | spin-executor = "3.0.1" 10 | spin-sdk = "3.0.1" 11 | wit-bindgen-rt = { version = "0.26.0", features = ["bitflags"] } 12 | 13 | [lib] 14 | crate-type = ["cdylib"] 15 | 16 | [profile.release] 17 | codegen-units = 1 18 | opt-level = "s" 19 | debug = false 20 | strip = true 21 | lto = true 22 | 23 | [package.metadata.component] 24 | package = "component:arxiv-rs" 25 | 26 | [workspace] 27 | -------------------------------------------------------------------------------- /crates/policy/testdata/docker-privileged.yaml: -------------------------------------------------------------------------------- 1 | $schema: https://raw.githubusercontent.com/microsoft/policy-mcp/main/schema/policy-v1.0.schema.json 2 | version: "1.0" 3 | description: "Policy with privileged Docker runtime for system administration" 4 | permissions: 5 | storage: 6 | allow: 7 | - uri: "fs://admin/**" 8 | access: ["read", "write"] 9 | 10 | runtime: 11 | docker: 12 | security: 13 | privileged: true 14 | no_new_privileges: false 15 | capabilities: 16 | drop: [] 17 | add: ["SYS_ADMIN", "NET_BIND_SERVICE", "SYS_TIME"] -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/exit/exit.wit.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | // Package exit represents the imported interface "wasi:cli/exit@0.2.0". 4 | package exit 5 | 6 | import ( 7 | "go.bytecodealliance.org/cm" 8 | ) 9 | 10 | // Exit represents the imported function "exit". 11 | // 12 | // Exit the current instance and any linked instances. 13 | // 14 | // exit: func(status: result) 15 | // 16 | //go:nosplit 17 | func Exit(status cm.BoolResult) { 18 | status0 := (uint32)(cm.BoolToU32(status)) 19 | wasmimport_Exit((uint32)(status0)) 20 | return 21 | } 22 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | - Employees can reach out at [aka.ms/opensource/moderation-support](https://aka.ms/opensource/moderation-support) -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which 6 | includes all source code repositories in our GitHub organizations. 7 | 8 | **Please do not report security vulnerabilities through public GitHub issues.** 9 | 10 | For security reporting information, locations, contact information, and policies, 11 | please review the latest guidance for Microsoft repositories at 12 | [https://aka.ms/SECURITY.md](https://aka.ms/SECURITY.md). 13 | 14 | -------------------------------------------------------------------------------- /examples/memory-js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "memory", 3 | "version": "1.0.0", 4 | "description": "Knowledge graph memory server as a WebAssembly component", 5 | "main": "memory.js", 6 | "type": "module", 7 | "scripts": { 8 | "build": "jco componentize ./memory.js --wit ./wit -o ./memory.wasm" 9 | }, 10 | "keywords": [ 11 | "mcp", 12 | "memory", 13 | "knowledge-graph", 14 | "wasm", 15 | "component" 16 | ], 17 | "license": "MIT", 18 | "dependencies": { 19 | "@bytecodealliance/componentize-js": "0.18.1", 20 | "@bytecodealliance/jco": "^1.11.1" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /crates/policy/testdata/storage-only.yaml: -------------------------------------------------------------------------------- 1 | $schema: https://raw.githubusercontent.com/microsoft/policy-mcp/main/schema/policy-v1.0.schema.json 2 | version: "1.1" 3 | description: "Storage-only policy for file system access" 4 | permissions: 5 | storage: 6 | allow: 7 | - uri: "fs://tmp/**" 8 | access: ["read", "write"] 9 | - uri: "fs://var/log/*.log" 10 | access: ["read"] 11 | - uri: "fs://home/user/documents/*" 12 | access: ["read", "write"] 13 | deny: 14 | - uri: "fs://etc/**" 15 | access: ["read", "write"] 16 | - uri: "fs://root/**" 17 | access: ["read", "write"] -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/random/insecure/insecure.wasm.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package insecure 4 | 5 | import ( 6 | "go.bytecodealliance.org/cm" 7 | ) 8 | 9 | // This file contains wasmimport and wasmexport declarations for "wasi:random@0.2.0". 10 | 11 | //go:wasmimport wasi:random/insecure@0.2.0 get-insecure-random-bytes 12 | //go:noescape 13 | func wasmimport_GetInsecureRandomBytes(len0 uint64, result *cm.List[uint8]) 14 | 15 | //go:wasmimport wasi:random/insecure@0.2.0 get-insecure-random-u64 16 | //go:noescape 17 | func wasmimport_GetInsecureRandomU64() (result0 uint64) 18 | -------------------------------------------------------------------------------- /examples/brave-search-rs/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "brave-search-rs" 3 | version = "0.1.0" 4 | edition = "2021" 5 | license = "MIT" 6 | 7 | [dependencies] 8 | serde = { version = "1.0", features = ["derive"] } 9 | serde_json = "1.0.137" 10 | spin-executor = "3.0.1" 11 | spin-sdk = "3.0.1" 12 | wit-bindgen-rt = { version = "0.26.0", features = ["bitflags"] } 13 | 14 | [lib] 15 | crate-type = ["cdylib"] 16 | 17 | [profile.release] 18 | codegen-units = 1 19 | opt-level = "s" 20 | debug = false 21 | strip = true 22 | lto = true 23 | 24 | [package.metadata.component] 25 | package = "component:brave-search-rs" 26 | 27 | [workspace] 28 | -------------------------------------------------------------------------------- /crates/policy/testdata/resource-limits.yaml: -------------------------------------------------------------------------------- 1 | $schema: https://raw.githubusercontent.com/microsoft/policy-mcp/main/schema/policy-v1.0.schema.json 2 | version: "1.0" 3 | description: "Policy with k8s-style resource limits" 4 | permissions: 5 | storage: 6 | allow: 7 | - uri: "fs://workspace/**" 8 | access: ["read", "write"] 9 | - uri: "fs://config/app.yaml" 10 | access: ["read"] 11 | 12 | network: 13 | allow: 14 | - host: "api.openai.com" 15 | 16 | resources: 17 | limits: 18 | cpu: "500m" # millicores (k8s-style) 19 | memory: "512Mi" # human-readable (Ki, Mi, Gi) -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/http/outgoing-handler/abi.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package outgoinghandler 4 | 5 | import ( 6 | "go.bytecodealliance.org/cm" 7 | "unsafe" 8 | ) 9 | 10 | // ErrorCodeShape is used for storage in variant or result types. 11 | type ErrorCodeShape struct { 12 | _ cm.HostLayout 13 | shape [unsafe.Sizeof(ErrorCode{})]byte 14 | } 15 | 16 | func lower_OptionRequestOptions(v cm.Option[RequestOptions]) (f0 uint32, f1 uint32) { 17 | some := v.Some() 18 | if some != nil { 19 | f0 = 1 20 | v1 := cm.Reinterpret[uint32](*some) 21 | f1 = (uint32)(v1) 22 | } 23 | return 24 | } 25 | -------------------------------------------------------------------------------- /scripts/install-protobuf.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Helper script for Github Actions to install protobuf on different runners. 4 | echo "OS: $RUNNER_OS" 5 | 6 | if [ "$RUNNER_OS" == 'Linux' ]; then 7 | # Install on Linux 8 | sudo apt-get update 9 | sudo apt-get install -y protobuf-compiler 10 | elif [ "$RUNNER_OS" == 'macOS' ]; then 11 | # Install on macOS 12 | brew install protobuf 13 | elif [ "$RUNNER_OS" == 'Windows' ]; then 14 | # Install on Windows 15 | choco install -y protoc 16 | else 17 | echo "Unsupported OS: $RUNNER_OS" 18 | exit 1 19 | fi 20 | 21 | # Check the installed Protobuf version 22 | protoc --version -------------------------------------------------------------------------------- /examples/gomodule-go/wit/world.wit: -------------------------------------------------------------------------------- 1 | package local:gomodule-server; 2 | 3 | interface gomodule { 4 | /// Get the latest version of multiple Go modules 5 | /// Returns JSON string with module -> version mapping 6 | get-latest-versions: func(module-names: string) -> result; 7 | 8 | /// Get detailed information about multiple Go modules 9 | /// Returns JSON string with module information array 10 | get-module-info: func(module-names: string) -> result; 11 | } 12 | 13 | world gomodule-server { 14 | include wasi:cli/imports@0.2.0; 15 | import wasi:http/outgoing-handler@0.2.0; 16 | 17 | export gomodule; 18 | } -------------------------------------------------------------------------------- /examples/context7-rs/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "context7" 3 | version = "0.1.0" 4 | edition = "2021" 5 | license = "MIT" 6 | 7 | [dependencies] 8 | serde_json = "1" 9 | wit-bindgen-rt = { version = "0.44.0", features = ["bitflags"] } 10 | urlencoding = "2" 11 | 12 | [lib] 13 | crate-type = ["cdylib"] 14 | 15 | [profile.release] 16 | codegen-units = 1 17 | opt-level = "s" 18 | debug = false 19 | strip = true 20 | lto = true 21 | 22 | [package.metadata.component] 23 | package = "local:context7" 24 | 25 | [package.metadata.component.dependencies] 26 | 27 | [package.metadata.component.target.dependencies] 28 | "wasi:http" = "0.2.0" 29 | "wasi:cli" = "0.2.0" 30 | 31 | [workspace] 32 | -------------------------------------------------------------------------------- /examples/context7-rs/wit/deps/cli/stdio.wit: -------------------------------------------------------------------------------- 1 | @since(version = 0.2.0) 2 | interface stdin { 3 | @since(version = 0.2.0) 4 | use wasi:io/streams@0.2.1.{input-stream}; 5 | 6 | @since(version = 0.2.0) 7 | get-stdin: func() -> input-stream; 8 | } 9 | 10 | @since(version = 0.2.0) 11 | interface stdout { 12 | @since(version = 0.2.0) 13 | use wasi:io/streams@0.2.1.{output-stream}; 14 | 15 | @since(version = 0.2.0) 16 | get-stdout: func() -> output-stream; 17 | } 18 | 19 | @since(version = 0.2.0) 20 | interface stderr { 21 | @since(version = 0.2.0) 22 | use wasi:io/streams@0.2.1.{output-stream}; 23 | 24 | @since(version = 0.2.0) 25 | get-stderr: func() -> output-stream; 26 | } 27 | -------------------------------------------------------------------------------- /lychee.toml: -------------------------------------------------------------------------------- 1 | # Lychee link checker configuration 2 | # See: https://lychee.cli.rs/#/usage/config 3 | 4 | # Accept status codes 5 | # By default, lychee only accepts 200 OK 6 | # We need to accept 302 Found for VS Code protocol handler redirects 7 | accept = [200, 302] 8 | 9 | # Maximum number of concurrent network requests 10 | max_concurrency = 10 11 | 12 | # Don't check these URLs 13 | exclude = [ 14 | # VS Code protocol handler links return 302 redirects - these are intentional 15 | 'https://vscode.dev/redirect?url=vscode:mcp/install*', 16 | 'https://vscode.dev/redirect?url=vscode-insiders:mcp/install*', 17 | ] 18 | 19 | # Exclude link patterns 20 | exclude_link_local = true 21 | -------------------------------------------------------------------------------- /.github/workflows/nix.yml: -------------------------------------------------------------------------------- 1 | name: Nix 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | jobs: 10 | nix-flake: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 14 | - uses: cachix/install-nix-action@fd24c48048070c1be9acd18c9d369a83f0fe94d7 # v31 15 | with: 16 | nix_path: nixpkgs=channel:nixos-unstable 17 | - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 18 | with: 19 | name: wassette 20 | authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' 21 | - run: nix flake check 22 | - run: nix build 23 | -------------------------------------------------------------------------------- /examples/eval-py/wit_world/types.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Microsoft Corporation. 2 | # Licensed under the MIT license. 3 | 4 | from typing import TypeVar, Generic, Union, Optional, Protocol, Tuple, List, Any, Self 5 | from types import TracebackType 6 | from enum import Flag, Enum, auto 7 | from dataclasses import dataclass 8 | from abc import abstractmethod 9 | import weakref 10 | 11 | 12 | S = TypeVar('S') 13 | @dataclass 14 | class Some(Generic[S]): 15 | value: S 16 | 17 | T = TypeVar('T') 18 | @dataclass 19 | class Ok(Generic[T]): 20 | value: T 21 | 22 | E = TypeVar('E') 23 | @dataclass(frozen=True) 24 | class Err(Generic[E], Exception): 25 | value: E 26 | 27 | Result = Union[Ok[T], Err[E]] 28 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/environment/environment.wasm.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package environment 4 | 5 | import ( 6 | "go.bytecodealliance.org/cm" 7 | ) 8 | 9 | // This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0". 10 | 11 | //go:wasmimport wasi:cli/environment@0.2.0 get-environment 12 | //go:noescape 13 | func wasmimport_GetEnvironment(result *cm.List[[2]string]) 14 | 15 | //go:wasmimport wasi:cli/environment@0.2.0 get-arguments 16 | //go:noescape 17 | func wasmimport_GetArguments(result *cm.List[string]) 18 | 19 | //go:wasmimport wasi:cli/environment@0.2.0 initial-cwd 20 | //go:noescape 21 | func wasmimport_InitialCWD(result *cm.Option[string]) 22 | -------------------------------------------------------------------------------- /examples/gomodule-go/.gitignore: -------------------------------------------------------------------------------- 1 | # If you prefer the allow list template instead of the deny list, see community template: 2 | # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore 3 | # 4 | # Binaries for programs and plugins 5 | *.exe 6 | *.exe~ 7 | *.dll 8 | *.so 9 | *.dylib 10 | *.wasm 11 | 12 | # Test binary, built with `go test -c` 13 | *.test 14 | 15 | # Code coverage profiles and other test artifacts 16 | *.out 17 | coverage.* 18 | *.coverprofile 19 | profile.cov 20 | 21 | # Dependency directories (remove the comment below to include it) 22 | # vendor/ 23 | 24 | # Go workspace file 25 | go.work 26 | go.work.sum 27 | 28 | # env file 29 | .env 30 | 31 | # Editor/IDE 32 | # .idea/ 33 | # .vscode/ -------------------------------------------------------------------------------- /crates/policy/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "policy" 3 | version = "0.1.0" 4 | edition = "2021" 5 | license.workspace = true 6 | description = "A Rust library for parsing and validating capability-based security policies for MCP servers" 7 | repository = "https://github.com/microsoft/wassette" 8 | homepage = "https://github.com/microsoft/wassette" 9 | readme = "README.md" 10 | keywords = ["mcp", "security", "policy", "webassembly", "permissions"] 11 | categories = ["parser-implementations", "web-programming", "config"] 12 | authors = ["Microsoft Corporation"] 13 | 14 | 15 | [dependencies] 16 | serde = { version = "1.0", features = ["derive"] } 17 | anyhow = "1.0" 18 | serde_yaml = "0.9.33" 19 | 20 | [dev-dependencies] 21 | tempfile = "3.23" 22 | -------------------------------------------------------------------------------- /examples/manifests/production.yaml: -------------------------------------------------------------------------------- 1 | version: 1 2 | components: 3 | - uri: oci://ghcr.io/microsoft/get-weather-js:1.2.3 4 | name: weather-service 5 | digest: sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef 6 | permissions: 7 | network: 8 | allow: 9 | - host: api.openweathermap.com 10 | environment: 11 | allow: 12 | - key: OPENWEATHER_API_KEY 13 | value_from: OPENWEATHER_API_KEY 14 | 15 | - uri: oci://ghcr.io/microsoft/time-server:2.0.1 16 | name: time-service 17 | digest: sha256:fedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321 18 | permissions: 19 | network: 20 | allow: 21 | - host: worldtimeapi.org 22 | -------------------------------------------------------------------------------- /examples/time-server-js/README.md: -------------------------------------------------------------------------------- 1 | # Time Server Example (JavaScript) 2 | 3 | This example demonstrates how to get the current time using a Wassette component written in JavaScript. 4 | 5 | For more information on installing Wassette, please see the [installation instructions](https://github.com/microsoft/wassette?tab=readme-ov-file#installation). 6 | 7 | ## Usage 8 | 9 | To use this component, load it from the OCI registry and ask for the current time. 10 | 11 | **Load the component:** 12 | ``` 13 | Please load the component from oci://ghcr.io/microsoft/time-server-js:latest 14 | ``` 15 | 16 | **Get the current time:** 17 | ``` 18 | What is the current time? 19 | ``` 20 | 21 | The source code for this example can be found in [`time.js`](time.js). 22 | -------------------------------------------------------------------------------- /examples/context7-rs/wit/deps/cli/exit.wit: -------------------------------------------------------------------------------- 1 | @since(version = 0.2.0) 2 | interface exit { 3 | /// Exit the current instance and any linked instances. 4 | @since(version = 0.2.0) 5 | exit: func(status: result); 6 | 7 | /// Exit the current instance and any linked instances, reporting the 8 | /// specified status code to the host. 9 | /// 10 | /// The meaning of the code depends on the context, with 0 usually meaning 11 | /// "success", and other values indicating various types of failure. 12 | /// 13 | /// This function does not return; the effect is analogous to a trap, but 14 | /// without the connotation that something bad has happened. 15 | @unstable(feature = cli-exit-with-code) 16 | exit-with-code: func(status-code: u8); 17 | } 18 | -------------------------------------------------------------------------------- /examples/manifests/multi-component.yaml: -------------------------------------------------------------------------------- 1 | version: 1 2 | components: 3 | - uri: oci://ghcr.io/microsoft/get-weather-js:latest 4 | name: weather-service 5 | permissions: 6 | network: 7 | allow: 8 | - host: api.openweathermap.com 9 | environment: 10 | allow: 11 | - key: OPENWEATHER_API_KEY 12 | 13 | - uri: oci://ghcr.io/microsoft/time-server:latest 14 | name: time-service 15 | permissions: 16 | network: 17 | allow: 18 | - host: worldtimeapi.org 19 | 20 | - uri: oci://ghcr.io/microsoft/filesystem-rs:latest 21 | name: filesystem-service 22 | permissions: 23 | storage: 24 | allow: 25 | - uri: fs:///tmp/workspace 26 | access: [read, write] 27 | -------------------------------------------------------------------------------- /.github/actions/rust-cache/action.yml: -------------------------------------------------------------------------------- 1 | name: Setup rust cache 2 | 3 | runs: 4 | using: composite 5 | steps: 6 | - name: Get rust version 7 | run: echo "RUST_VERSION=$(rustc --version | awk '{print $2}')" >> $GITHUB_ENV 8 | shell: bash 9 | - name: Get Cargo.lock SHA 10 | shell: bash 11 | run: | 12 | if command -v sha256sum >/dev/null 2>&1; then 13 | echo "CARGO_LOCK_SHA=$(sha256sum Cargo.lock | awk '{print $1}')" >> $GITHUB_ENV 14 | else 15 | echo "CARGO_LOCK_SHA=$(shasum -a 256 Cargo.lock | awk '{print $1}')" >> $GITHUB_ENV 16 | fi 17 | - uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0 18 | with: 19 | shared-key: "wassette-${{ env.RUST_VERSION }}-${{ env.CARGO_LOCK_SHA }}" 20 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/stdin/stdin.wit.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | // Package stdin represents the imported interface "wasi:cli/stdin@0.2.0". 4 | package stdin 5 | 6 | import ( 7 | "go.bytecodealliance.org/cm" 8 | "gomodule-server-go/gen/wasi/io/streams" 9 | ) 10 | 11 | // InputStream represents the imported type alias "wasi:cli/stdin@0.2.0#input-stream". 12 | // 13 | // See [streams.InputStream] for more information. 14 | type InputStream = streams.InputStream 15 | 16 | // GetStdin represents the imported function "get-stdin". 17 | // 18 | // get-stdin: func() -> input-stream 19 | // 20 | //go:nosplit 21 | func GetStdin() (result InputStream) { 22 | result0 := wasmimport_GetStdin() 23 | result = cm.Reinterpret[InputStream]((uint32)(result0)) 24 | return 25 | } 26 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/stderr/stderr.wit.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | // Package stderr represents the imported interface "wasi:cli/stderr@0.2.0". 4 | package stderr 5 | 6 | import ( 7 | "go.bytecodealliance.org/cm" 8 | "gomodule-server-go/gen/wasi/io/streams" 9 | ) 10 | 11 | // OutputStream represents the imported type alias "wasi:cli/stderr@0.2.0#output-stream". 12 | // 13 | // See [streams.OutputStream] for more information. 14 | type OutputStream = streams.OutputStream 15 | 16 | // GetStderr represents the imported function "get-stderr". 17 | // 18 | // get-stderr: func() -> output-stream 19 | // 20 | //go:nosplit 21 | func GetStderr() (result OutputStream) { 22 | result0 := wasmimport_GetStderr() 23 | result = cm.Reinterpret[OutputStream]((uint32)(result0)) 24 | return 25 | } 26 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/stdout/stdout.wit.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | // Package stdout represents the imported interface "wasi:cli/stdout@0.2.0". 4 | package stdout 5 | 6 | import ( 7 | "go.bytecodealliance.org/cm" 8 | "gomodule-server-go/gen/wasi/io/streams" 9 | ) 10 | 11 | // OutputStream represents the imported type alias "wasi:cli/stdout@0.2.0#output-stream". 12 | // 13 | // See [streams.OutputStream] for more information. 14 | type OutputStream = streams.OutputStream 15 | 16 | // GetStdout represents the imported function "get-stdout". 17 | // 18 | // get-stdout: func() -> output-stream 19 | // 20 | //go:nosplit 21 | func GetStdout() (result OutputStream) { 22 | result0 := wasmimport_GetStdout() 23 | result = cm.Reinterpret[OutputStream]((uint32)(result0)) 24 | return 25 | } 26 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/clocks/monotonic-clock/monotonic-clock.wasm.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package monotonicclock 4 | 5 | // This file contains wasmimport and wasmexport declarations for "wasi:clocks@0.2.0". 6 | 7 | //go:wasmimport wasi:clocks/monotonic-clock@0.2.0 now 8 | //go:noescape 9 | func wasmimport_Now() (result0 uint64) 10 | 11 | //go:wasmimport wasi:clocks/monotonic-clock@0.2.0 resolution 12 | //go:noescape 13 | func wasmimport_Resolution() (result0 uint64) 14 | 15 | //go:wasmimport wasi:clocks/monotonic-clock@0.2.0 subscribe-instant 16 | //go:noescape 17 | func wasmimport_SubscribeInstant(when0 uint64) (result0 uint32) 18 | 19 | //go:wasmimport wasi:clocks/monotonic-clock@0.2.0 subscribe-duration 20 | //go:noescape 21 | func wasmimport_SubscribeDuration(when0 uint64) (result0 uint32) 22 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/io/poll/poll.wasm.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package poll 4 | 5 | import ( 6 | "go.bytecodealliance.org/cm" 7 | ) 8 | 9 | // This file contains wasmimport and wasmexport declarations for "wasi:io@0.2.0". 10 | 11 | //go:wasmimport wasi:io/poll@0.2.0 [resource-drop]pollable 12 | //go:noescape 13 | func wasmimport_PollableResourceDrop(self0 uint32) 14 | 15 | //go:wasmimport wasi:io/poll@0.2.0 [method]pollable.block 16 | //go:noescape 17 | func wasmimport_PollableBlock(self0 uint32) 18 | 19 | //go:wasmimport wasi:io/poll@0.2.0 [method]pollable.ready 20 | //go:noescape 21 | func wasmimport_PollableReady(self0 uint32) (result0 uint32) 22 | 23 | //go:wasmimport wasi:io/poll@0.2.0 poll 24 | //go:noescape 25 | func wasmimport_Poll(in0 *Pollable, in1 uint32, result *cm.List[uint32]) 26 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/filesystem/preopens/preopens.wit.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | // Package preopens represents the imported interface "wasi:filesystem/preopens@0.2.0". 4 | package preopens 5 | 6 | import ( 7 | "go.bytecodealliance.org/cm" 8 | "gomodule-server-go/gen/wasi/filesystem/types" 9 | ) 10 | 11 | // Descriptor represents the imported type alias "wasi:filesystem/preopens@0.2.0#descriptor". 12 | // 13 | // See [types.Descriptor] for more information. 14 | type Descriptor = types.Descriptor 15 | 16 | // GetDirectories represents the imported function "get-directories". 17 | // 18 | // get-directories: func() -> list> 19 | // 20 | //go:nosplit 21 | func GetDirectories() (result cm.List[cm.Tuple[Descriptor, string]]) { 22 | wasmimport_GetDirectories(&result) 23 | return 24 | } 25 | -------------------------------------------------------------------------------- /examples/filesystem-rs/policy.yaml: -------------------------------------------------------------------------------- 1 | $schema: https://raw.githubusercontent.com/microsoft/policy-mcp/main/schema/policy-v1.0.schema.json 2 | # file system access policy for wassette project 3 | # https://github.com/microsoft/policy-mcp-rs 4 | version: "1.0" 5 | description: "Permission policy for filesystem access in wassette" 6 | permissions: 7 | storage: 8 | allow: 9 | # Allow read access to the wassette project directory 10 | - uri: "fs:///home/runner/work/wassette/wassette" 11 | access: ["read"] 12 | # Allow read and write access to tmp for testing 13 | - uri: "fs:///tmp" 14 | access: ["read", "write"] 15 | # Example: Allow read and write access to a specific directory 16 | # Uncomment and modify the path below to enable write operations 17 | # - uri: "fs:///Users/USERNAME/tmp" 18 | # access: ["read", "write"] 19 | 20 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/sockets/instance-network/instance-network.wit.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | // Package instancenetwork represents the imported interface "wasi:sockets/instance-network@0.2.0". 4 | package instancenetwork 5 | 6 | import ( 7 | "go.bytecodealliance.org/cm" 8 | "gomodule-server-go/gen/wasi/sockets/network" 9 | ) 10 | 11 | // Network represents the imported type alias "wasi:sockets/instance-network@0.2.0#network". 12 | // 13 | // See [network.Network] for more information. 14 | type Network = network.Network 15 | 16 | // InstanceNetwork represents the imported function "instance-network". 17 | // 18 | // instance-network: func() -> network 19 | // 20 | //go:nosplit 21 | func InstanceNetwork() (result Network) { 22 | result0 := wasmimport_InstanceNetwork() 23 | result = cm.Reinterpret[Network]((uint32)(result0)) 24 | return 25 | } 26 | -------------------------------------------------------------------------------- /examples/eval-py/wit_world/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Microsoft Corporation. 2 | # Licensed under the MIT license. 3 | 4 | from typing import TypeVar, Generic, Union, Optional, Protocol, Tuple, List, Any, Self 5 | from types import TracebackType 6 | from enum import Flag, Enum, auto 7 | from dataclasses import dataclass 8 | from abc import abstractmethod 9 | import weakref 10 | 11 | from .types import Result, Ok, Err, Some 12 | 13 | 14 | 15 | class WitWorld(Protocol): 16 | 17 | @abstractmethod 18 | def eval(self, expression: str) -> str: 19 | """ 20 | Raises: `wit_world.types.Err(wit_world.imports.str)` 21 | """ 22 | raise NotImplementedError 23 | 24 | @abstractmethod 25 | def exec(self, statements: str) -> str: 26 | """ 27 | Raises: `wit_world.types.Err(wit_world.imports.str)` 28 | """ 29 | raise NotImplementedError 30 | 31 | -------------------------------------------------------------------------------- /examples/context7-rs/wit/deps/cli/environment.wit: -------------------------------------------------------------------------------- 1 | @since(version = 0.2.0) 2 | interface environment { 3 | /// Get the POSIX-style environment variables. 4 | /// 5 | /// Each environment variable is provided as a pair of string variable names 6 | /// and string value. 7 | /// 8 | /// Morally, these are a value import, but until value imports are available 9 | /// in the component model, this import function should return the same 10 | /// values each time it is called. 11 | @since(version = 0.2.0) 12 | get-environment: func() -> list>; 13 | 14 | /// Get the POSIX-style arguments to the program. 15 | @since(version = 0.2.0) 16 | get-arguments: func() -> list; 17 | 18 | /// Return a path that programs should use as their initial current working 19 | /// directory, interpreting `.` as shorthand for this. 20 | @since(version = 0.2.0) 21 | initial-cwd: func() -> option; 22 | } 23 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | This project welcomes contributions and suggestions. Most contributions require you to 4 | agree to a Contributor License Agreement (CLA) declaring that you have the right to, 5 | and actually do, grant us the rights to use your contribution. For details, visit 6 | https://cla.microsoft.com. 7 | 8 | When you submit a pull request, a CLA-bot will automatically determine whether you need 9 | to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the 10 | instructions provided by the bot. You will only need to do this once across all repositories using our CLA. 11 | 12 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 13 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 14 | or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. -------------------------------------------------------------------------------- /examples/filesystem-rs/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "anyhow" 7 | version = "1.0.95" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" 10 | 11 | [[package]] 12 | name = "bitflags" 13 | version = "2.8.0" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" 16 | 17 | [[package]] 18 | name = "filesystem" 19 | version = "0.1.0" 20 | dependencies = [ 21 | "anyhow", 22 | "wit-bindgen-rt", 23 | ] 24 | 25 | [[package]] 26 | name = "wit-bindgen-rt" 27 | version = "0.37.0" 28 | source = "registry+https://github.com/rust-lang/crates.io-index" 29 | checksum = "fc801b991c56492f87ab3086e786468f75c285a4d73017ab0ebc2fa1aed5d82c" 30 | dependencies = [ 31 | "bitflags", 32 | ] 33 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # Git files 2 | .git 3 | .gitignore 4 | .gitattributes 5 | 6 | # GitHub workflows and documentation 7 | .github 8 | docs/book 9 | docs/TODO.md 10 | 11 | # Target and build artifacts 12 | target/** 13 | !target/release/wassette 14 | bin 15 | *.wasm 16 | 17 | # Examples and tests 18 | examples/*/target 19 | tests 20 | 21 | # Documentation 22 | *.md 23 | !README.md 24 | LICENSE 25 | NOTICE 26 | SECURITY.md 27 | CODE_OF_CONDUCT.md 28 | CONTRIBUTING.md 29 | 30 | # Development files 31 | .vscode 32 | .idea 33 | *.swp 34 | *.swo 35 | *~ 36 | 37 | # Rust artifacts 38 | **/*.rs.bk 39 | Cargo.lock.bak 40 | 41 | # OS files 42 | .DS_Store 43 | Thumbs.db 44 | 45 | # CI/Docker files 46 | Dockerfile.ci 47 | docker-compose.yml 48 | 49 | # Scripts 50 | scripts 51 | 52 | # Package manager files 53 | Formula 54 | flake.nix 55 | flake.lock 56 | winget 57 | 58 | # Other 59 | assets 60 | audit.toml 61 | deny.toml 62 | _typos.toml 63 | rustfmt.toml 64 | component-registry.json 65 | policy.yaml 66 | install.sh 67 | -------------------------------------------------------------------------------- /docs/book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | authors = ["Microsoft"] 3 | description = "Documentation for Wassette - A security-oriented runtime that runs WebAssembly Components via MCP" 4 | language = "en" 5 | src = "." 6 | title = "Wassette Documentation" 7 | 8 | [build] 9 | build-dir = "book" 10 | 11 | [preprocessor.tabs] 12 | 13 | [output.html] 14 | additional-js = ["mermaid.min.js", "mermaid-init.js", "theme/version-picker.js", "theme/toc.js"] 15 | additional-css = ["theme/version-picker.css", "theme/toc.css"] 16 | smart-punctuation = true 17 | git-repository-url = "https://github.com/microsoft/wassette" 18 | edit-url-template = "https://github.com/microsoft/wassette/edit/main/docs/{path}" 19 | 20 | [output.html.search] 21 | enable = true 22 | limit-results = 30 23 | teaser-word-count = 30 24 | use-boolean-and = true 25 | boost-title = 2 26 | boost-hierarchy = 1 27 | boost-paragraph = 1 28 | expand = true 29 | heading-split-level = 3 30 | 31 | [preprocessor] 32 | 33 | [preprocessor.mermaid] 34 | command = "mdbook-mermaid" 35 | -------------------------------------------------------------------------------- /crates/policy/testdata/restricted.yaml: -------------------------------------------------------------------------------- 1 | $schema: https://raw.githubusercontent.com/microsoft/policy-mcp/main/schema/policy-v1.0.schema.json 2 | version: "1.0" 3 | description: "Highly restricted policy for untrusted code" 4 | permissions: 5 | storage: 6 | allow: 7 | - uri: "fs://sandbox/readonly/**" 8 | access: ["read"] 9 | - uri: "fs://sandbox/temp/**" 10 | access: ["write"] 11 | deny: 12 | - uri: "fs://sandbox/temp/system/**" 13 | access: ["read", "write"] 14 | 15 | network: 16 | allow: 17 | - host: "api.safe-service.com" 18 | deny: 19 | - host: "*" 20 | - cidr: "0.0.0.0/0" 21 | 22 | environment: 23 | allow: 24 | - key: "PATH" 25 | - key: "HOME" 26 | 27 | runtime: 28 | docker: 29 | security: 30 | privileged: false 31 | no_new_privileges: true 32 | capabilities: 33 | drop: ["ALL"] 34 | add: [] 35 | 36 | resources: 37 | cpu: 10.0 38 | memory: 128 39 | io: 100 -------------------------------------------------------------------------------- /docs/quick-start.md: -------------------------------------------------------------------------------- 1 | # Quick Start 2 | 3 | After installing Wassette, get started in 3 simple steps: 4 | 5 | **1. Connect to an AI agent** 6 | 7 | For VS Code with GitHub Copilot, click to install: 8 | 9 | [![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_Server-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect?url=vscode:mcp/install?%7B%22name%22%3A%22wassette%22%2C%22gallery%22%3Afalse%2C%22command%22%3A%22wassette%22%2C%22args%22%3A%5B%22run%22%5D%7D) 10 | 11 | Or use the command line: 12 | ```bash 13 | code --add-mcp '{"name":"Wassette","command":"wassette","args":["run"]}' 14 | ``` 15 | 16 | **2. Load a component** 17 | 18 | Ask your AI agent: 19 | ``` 20 | Please load the time component from ghcr.io/microsoft/time-server-js:latest 21 | ``` 22 | 23 | **3. Use the component** 24 | 25 | Ask your AI agent: 26 | ``` 27 | What is the current time? 28 | ``` 29 | 30 | For other AI agents (Cursor, Claude Code, Gemini CLI), see the [MCP clients guide](./mcp-clients.md). 31 | -------------------------------------------------------------------------------- /docs/theme/version-picker.css: -------------------------------------------------------------------------------- 1 | /* Version picker styling */ 2 | .version-picker-container { 3 | display: flex; 4 | align-items: center; 5 | margin-right: 10px; 6 | } 7 | 8 | .version-picker { 9 | padding: 4px 8px; 10 | border: 1px solid var(--theme-popup-border, #ccc); 11 | background: var(--theme-popup-bg, #fff); 12 | color: var(--theme-popup-fg, #000); 13 | border-radius: 4px; 14 | font-size: 0.9em; 15 | cursor: pointer; 16 | outline: none; 17 | transition: border-color 0.2s ease; 18 | } 19 | 20 | .version-picker:hover { 21 | border-color: var(--links, #4183c4); 22 | } 23 | 24 | .version-picker:focus { 25 | border-color: var(--links, #4183c4); 26 | box-shadow: 0 0 0 2px rgba(65, 131, 196, 0.2); 27 | } 28 | 29 | /* Dark mode support */ 30 | .coal .version-picker, 31 | .navy .version-picker, 32 | .ayu .version-picker { 33 | border-color: var(--theme-popup-border, #555); 34 | background: var(--theme-popup-bg, #3b3b3b); 35 | color: var(--theme-popup-fg, #fff); 36 | } 37 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/io/error/error.wit.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | // Package ioerror represents the imported interface "wasi:io/error@0.2.0". 4 | package ioerror 5 | 6 | import ( 7 | "go.bytecodealliance.org/cm" 8 | ) 9 | 10 | // Error represents the imported resource "wasi:io/error@0.2.0#error". 11 | // 12 | // resource error 13 | type Error cm.Resource 14 | 15 | // ResourceDrop represents the imported resource-drop for resource "error". 16 | // 17 | // Drops a resource handle. 18 | // 19 | //go:nosplit 20 | func (self Error) ResourceDrop() { 21 | self0 := cm.Reinterpret[uint32](self) 22 | wasmimport_ErrorResourceDrop((uint32)(self0)) 23 | return 24 | } 25 | 26 | // ToDebugString represents the imported method "to-debug-string". 27 | // 28 | // to-debug-string: func() -> string 29 | // 30 | //go:nosplit 31 | func (self Error) ToDebugString() (result string) { 32 | self0 := cm.Reinterpret[uint32](self) 33 | wasmimport_ErrorToDebugString((uint32)(self0), &result) 34 | return 35 | } 36 | -------------------------------------------------------------------------------- /examples/context7-rs/wit/deps/cli/imports.wit: -------------------------------------------------------------------------------- 1 | package wasi:cli@0.2.1; 2 | 3 | @since(version = 0.2.0) 4 | world imports { 5 | @since(version = 0.2.0) 6 | include wasi:clocks/imports@0.2.1; 7 | @since(version = 0.2.0) 8 | include wasi:filesystem/imports@0.2.1; 9 | @since(version = 0.2.0) 10 | include wasi:sockets/imports@0.2.1; 11 | @since(version = 0.2.0) 12 | include wasi:random/imports@0.2.1; 13 | @since(version = 0.2.0) 14 | include wasi:io/imports@0.2.1; 15 | 16 | @since(version = 0.2.0) 17 | import environment; 18 | @since(version = 0.2.0) 19 | import exit; 20 | @since(version = 0.2.0) 21 | import stdin; 22 | @since(version = 0.2.0) 23 | import stdout; 24 | @since(version = 0.2.0) 25 | import stderr; 26 | @since(version = 0.2.0) 27 | import terminal-input; 28 | @since(version = 0.2.0) 29 | import terminal-output; 30 | @since(version = 0.2.0) 31 | import terminal-stdin; 32 | @since(version = 0.2.0) 33 | import terminal-stdout; 34 | @since(version = 0.2.0) 35 | import terminal-stderr; 36 | } 37 | -------------------------------------------------------------------------------- /crates/policy/testdata/docker.yaml: -------------------------------------------------------------------------------- 1 | $schema: https://raw.githubusercontent.com/microsoft/policy-mcp/main/schema/policy-v1.0.schema.json 2 | version: "1.0" 3 | description: "Permission policy for docker container" 4 | permissions: 5 | storage: 6 | allow: 7 | - uri: "fs://work/agent/**" 8 | access: ["read", "write"] 9 | - uri: "fs://work/agent/config.yaml" 10 | access: ["read"] 11 | 12 | network: 13 | allow: 14 | - host: "api.openai.com" 15 | - host: "*.internal.myorg.com" 16 | - cidr: "10.0.0.0/8" 17 | 18 | environment: 19 | allow: 20 | - key: "PATH" 21 | - key: "HOME" 22 | 23 | runtime: 24 | docker: 25 | security: 26 | privileged: false 27 | no_new_privileges: true 28 | capabilities: 29 | drop: ["ALL"] 30 | add: ["NET_BIND_SERVICE"] 31 | hyperlight: 32 | # future 33 | 34 | 35 | # resources: 36 | # cpu (percentage), memory (mb), io (iops) 37 | 38 | # ipc: 39 | # allow: 40 | # - uri: "pipe://myservice" 41 | -------------------------------------------------------------------------------- /examples/context7-rs/wit/deps/random/insecure.wit: -------------------------------------------------------------------------------- 1 | package wasi:random@0.2.1; 2 | /// The insecure interface for insecure pseudo-random numbers. 3 | /// 4 | /// It is intended to be portable at least between Unix-family platforms and 5 | /// Windows. 6 | @since(version = 0.2.0) 7 | interface insecure { 8 | /// Return `len` insecure pseudo-random bytes. 9 | /// 10 | /// This function is not cryptographically secure. Do not use it for 11 | /// anything related to security. 12 | /// 13 | /// There are no requirements on the values of the returned bytes, however 14 | /// implementations are encouraged to return evenly distributed values with 15 | /// a long period. 16 | @since(version = 0.2.0) 17 | get-insecure-random-bytes: func(len: u64) -> list; 18 | 19 | /// Return an insecure pseudo-random `u64` value. 20 | /// 21 | /// This function returns the same type of pseudo-random data as 22 | /// `get-insecure-random-bytes`, represented as a `u64`. 23 | @since(version = 0.2.0) 24 | get-insecure-random-u64: func() -> u64; 25 | } 26 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/terminal-output/terminal-output.wit.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | // Package terminaloutput represents the imported interface "wasi:cli/terminal-output@0.2.0". 4 | // 5 | // Terminal output. 6 | // 7 | // In the future, this may include functions for querying the terminal 8 | // size, being notified of terminal size changes, querying supported 9 | // features, and so on. 10 | package terminaloutput 11 | 12 | import ( 13 | "go.bytecodealliance.org/cm" 14 | ) 15 | 16 | // TerminalOutput represents the imported resource "wasi:cli/terminal-output@0.2.0#terminal-output". 17 | // 18 | // The output side of a terminal. 19 | // 20 | // resource terminal-output 21 | type TerminalOutput cm.Resource 22 | 23 | // ResourceDrop represents the imported resource-drop for resource "terminal-output". 24 | // 25 | // Drops a resource handle. 26 | // 27 | //go:nosplit 28 | func (self TerminalOutput) ResourceDrop() { 29 | self0 := cm.Reinterpret[uint32](self) 30 | wasmimport_TerminalOutputResourceDrop((uint32)(self0)) 31 | return 32 | } 33 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/terminal-input/terminal-input.wit.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | // Package terminalinput represents the imported interface "wasi:cli/terminal-input@0.2.0". 4 | // 5 | // Terminal input. 6 | // 7 | // In the future, this may include functions for disabling echoing, 8 | // disabling input buffering so that keyboard events are sent through 9 | // immediately, querying supported features, and so on. 10 | package terminalinput 11 | 12 | import ( 13 | "go.bytecodealliance.org/cm" 14 | ) 15 | 16 | // TerminalInput represents the imported resource "wasi:cli/terminal-input@0.2.0#terminal-input". 17 | // 18 | // The input side of a terminal. 19 | // 20 | // resource terminal-input 21 | type TerminalInput cm.Resource 22 | 23 | // ResourceDrop represents the imported resource-drop for resource "terminal-input". 24 | // 25 | // Drops a resource handle. 26 | // 27 | //go:nosplit 28 | func (self TerminalInput) ResourceDrop() { 29 | self0 := cm.Reinterpret[uint32](self) 30 | wasmimport_TerminalInputResourceDrop((uint32)(self0)) 31 | return 32 | } 33 | -------------------------------------------------------------------------------- /examples/gomodule-go/wkg.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically generated. 2 | # It is not intended for manual editing. 3 | version = 1 4 | 5 | [[packages]] 6 | name = "wasi:cli" 7 | registry = "wasi.dev" 8 | 9 | [[packages.versions]] 10 | requirement = "=0.2.0" 11 | version = "0.2.0" 12 | digest = "sha256:e7e85458e11caf76554b724ebf4f113259decf0f3b1ee2e2930de096f72114a7" 13 | 14 | [[packages]] 15 | name = "wasi:clocks" 16 | registry = "wasi.dev" 17 | 18 | [[packages.versions]] 19 | requirement = "=0.2.0" 20 | version = "0.2.0" 21 | digest = "sha256:51911098e929732f65d1d84f8dc393299f18a9e8de632d854714f37142efe97b" 22 | 23 | [[packages]] 24 | name = "wasi:http" 25 | registry = "wasi.dev" 26 | 27 | [[packages.versions]] 28 | requirement = "=0.2.0" 29 | version = "0.2.0" 30 | digest = "sha256:5a568e6e2d60c1ce51220e1833cdd5b88db9f615720edc762a9b4a6f36b383bd" 31 | 32 | [[packages]] 33 | name = "wasi:random" 34 | registry = "wasi.dev" 35 | 36 | [[packages.versions]] 37 | requirement = "=0.2.0" 38 | version = "0.2.0" 39 | digest = "sha256:5d535edc544d06719cf337861b7917c3d565360295e5dc424046dceddb0a0e42" 40 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "cargo" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | groups: 8 | wasmtime: 9 | patterns: 10 | - "wasmtime*" 11 | # GitHub Actions updates are temporarily disabled because agentic workflow 12 | # lock files (*.lock.yml) are auto-generated from *.md source files. 13 | # Dependabot cannot distinguish between regular workflows and generated 14 | # lock files, so we must disable all GitHub Actions updates until a 15 | # mechanism is implemented to keep .md and .lock.yml files in sync. 16 | # 17 | # To update GitHub Actions versions in regular workflows: manual updates. 18 | # To update GitHub Actions versions in agentic workflows: update .md 19 | # source files and recompile with 'gh aw compile'. 20 | # 21 | # - package-ecosystem: "github-actions" 22 | # directory: "/" 23 | # schedule: 24 | # interval: "weekly" 25 | # groups: 26 | # upload-download-artifact: 27 | # patterns: 28 | # - "upload-artifact" 29 | # - "download-artifact" 30 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/local/gomodule-server/gomodule/gomodule.exports.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package gomodule 4 | 5 | import ( 6 | "go.bytecodealliance.org/cm" 7 | ) 8 | 9 | // Exports represents the caller-defined exports from "local:gomodule-server/gomodule". 10 | var Exports struct { 11 | // GetLatestVersions represents the caller-defined, exported function "get-latest-versions". 12 | // 13 | // Get the latest version of multiple Go modules 14 | // Returns JSON string with module -> version mapping 15 | // 16 | // get-latest-versions: func(module-names: string) -> result 17 | GetLatestVersions func(moduleNames string) (result cm.Result[string, string, string]) 18 | 19 | // GetModuleInfo represents the caller-defined, exported function "get-module-info". 20 | // 21 | // Get detailed information about multiple Go modules 22 | // Returns JSON string with module information array 23 | // 24 | // get-module-info: func(module-names: string) -> result 25 | GetModuleInfo func(moduleNames string) (result cm.Result[string, string, string]) 26 | } 27 | -------------------------------------------------------------------------------- /examples/eval-py/main.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Microsoft Corporation. 2 | # Licensed under the MIT license. 3 | 4 | # code is from https://github.com/bytecodealliance/componentize-py/blob/main/examples/sandbox/guest.py 5 | import contextlib 6 | import io 7 | import json 8 | 9 | import wit_world 10 | from wit_world.types import Err 11 | 12 | 13 | def handle(e: Exception) -> Err[str]: 14 | message = str(e) 15 | if message == "": 16 | return Err(f"{type(e).__name__}") 17 | else: 18 | return Err(f"{type(e).__name__}: {message}") 19 | 20 | 21 | class WitWorld(wit_world.WitWorld): 22 | def eval(self, expression: str) -> str: 23 | try: 24 | return json.dumps(eval(expression)) 25 | except Exception as e: 26 | raise handle(e) 27 | 28 | def exec(self, statements: str) -> str: 29 | buffer = io.StringIO() 30 | try: 31 | with contextlib.redirect_stdout(buffer), contextlib.redirect_stderr(buffer): 32 | exec(statements) 33 | return buffer.getvalue() 34 | except Exception as e: 35 | raise handle(e) 36 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/terminal-stdin/terminal-stdin.wit.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | // Package terminalstdin represents the imported interface "wasi:cli/terminal-stdin@0.2.0". 4 | // 5 | // An interface providing an optional `terminal-input` for stdin as a 6 | // link-time authority. 7 | package terminalstdin 8 | 9 | import ( 10 | "go.bytecodealliance.org/cm" 11 | terminalinput "gomodule-server-go/gen/wasi/cli/terminal-input" 12 | ) 13 | 14 | // TerminalInput represents the imported type alias "wasi:cli/terminal-stdin@0.2.0#terminal-input". 15 | // 16 | // See [terminalinput.TerminalInput] for more information. 17 | type TerminalInput = terminalinput.TerminalInput 18 | 19 | // GetTerminalStdin represents the imported function "get-terminal-stdin". 20 | // 21 | // If stdin is connected to a terminal, return a `terminal-input` handle 22 | // allowing further interaction with it. 23 | // 24 | // get-terminal-stdin: func() -> option 25 | // 26 | //go:nosplit 27 | func GetTerminalStdin() (result cm.Option[TerminalInput]) { 28 | wasmimport_GetTerminalStdin(&result) 29 | return 30 | } 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) Microsoft Corporation. 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | NOTICES 2 | 3 | This repository incorporates material as listed below or described in the code. 4 | 5 | This project includes code from the componentize-py project (https://github.com/bytecodealliance/componentize-py), licensed under the Apache License, Version 2.0. 6 | 7 | Copyright 2024-2025 Bytecode Alliance. 8 | 9 | You may obtain a copy of the license at: 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | This project includes inspirations of plugin examples from the [tuananh/hyper-mcp](https://github.com/tuananh/hyper-mcp) project, under hyper-mcp/examples/plugins. No code was directly copied. 13 | 14 | hyper-mcp is licensed under the Apache License, Version 2.0. 15 | 16 | You may obtain a copy of the license at: 17 | http://www.apache.org/licenses/LICENSE-2.0 18 | 19 | This project includes inspirations of server examples in the [modelcontextprotocol/servers](https://github.com/modelcontextprotocol/servers) project. No code was directly copied. 20 | 21 | modelcontextprotocol/servers is licensed under the MIT License. 22 | 23 | You may obtain a copy of the license at: 24 | https://github.com/modelcontextprotocol/servers/blob/main/LICENSE -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/terminal-stderr/terminal-stderr.wit.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | // Package terminalstderr represents the imported interface "wasi:cli/terminal-stderr@0.2.0". 4 | // 5 | // An interface providing an optional `terminal-output` for stderr as a 6 | // link-time authority. 7 | package terminalstderr 8 | 9 | import ( 10 | "go.bytecodealliance.org/cm" 11 | terminaloutput "gomodule-server-go/gen/wasi/cli/terminal-output" 12 | ) 13 | 14 | // TerminalOutput represents the imported type alias "wasi:cli/terminal-stderr@0.2.0#terminal-output". 15 | // 16 | // See [terminaloutput.TerminalOutput] for more information. 17 | type TerminalOutput = terminaloutput.TerminalOutput 18 | 19 | // GetTerminalStderr represents the imported function "get-terminal-stderr". 20 | // 21 | // If stderr is connected to a terminal, return a `terminal-output` handle 22 | // allowing further interaction with it. 23 | // 24 | // get-terminal-stderr: func() -> option 25 | // 26 | //go:nosplit 27 | func GetTerminalStderr() (result cm.Option[TerminalOutput]) { 28 | wasmimport_GetTerminalStderr(&result) 29 | return 30 | } 31 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/terminal-stdout/terminal-stdout.wit.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | // Package terminalstdout represents the imported interface "wasi:cli/terminal-stdout@0.2.0". 4 | // 5 | // An interface providing an optional `terminal-output` for stdout as a 6 | // link-time authority. 7 | package terminalstdout 8 | 9 | import ( 10 | "go.bytecodealliance.org/cm" 11 | terminaloutput "gomodule-server-go/gen/wasi/cli/terminal-output" 12 | ) 13 | 14 | // TerminalOutput represents the imported type alias "wasi:cli/terminal-stdout@0.2.0#terminal-output". 15 | // 16 | // See [terminaloutput.TerminalOutput] for more information. 17 | type TerminalOutput = terminaloutput.TerminalOutput 18 | 19 | // GetTerminalStdout represents the imported function "get-terminal-stdout". 20 | // 21 | // If stdout is connected to a terminal, return a `terminal-output` handle 22 | // allowing further interaction with it. 23 | // 24 | // get-terminal-stdout: func() -> option 25 | // 26 | //go:nosplit 27 | func GetTerminalStdout() (result cm.Option[TerminalOutput]) { 28 | wasmimport_GetTerminalStdout(&result) 29 | return 30 | } 31 | -------------------------------------------------------------------------------- /examples/eval-py/wit/world.wit: -------------------------------------------------------------------------------- 1 | package local:eval-py; 2 | 3 | /// A sandboxed Python execution environment 4 | world sandbox { 5 | /// Evaluate a Python expression and return its result 6 | /// 7 | /// # Parameters 8 | /// * `expression` - A Python expression to evaluate (e.g., "2 + 2", "len('hello')") 9 | /// 10 | /// # Returns 11 | /// A result containing either: 12 | /// * Success: String representation of the expression's result 13 | /// * Error: String describing the evaluation error (syntax error, runtime error, etc.) 14 | export eval: func(expression: string) -> result; 15 | 16 | /// Execute Python statements and return any output 17 | /// 18 | /// # Parameters 19 | /// * `statements` - Python statements to execute (e.g., "print('hello')", "x = 5; print(x)") 20 | /// 21 | /// # Returns 22 | /// A result containing either: 23 | /// * Success: String containing any printed output or execution results 24 | /// * Error: String describing the execution error (syntax error, runtime error, etc.) 25 | export exec: func(statements: string) -> result; 26 | } -------------------------------------------------------------------------------- /examples/gomodule-go/gen/local/gomodule-server/gomodule/gomodule.wasm.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package gomodule 4 | 5 | import ( 6 | "go.bytecodealliance.org/cm" 7 | ) 8 | 9 | // This file contains wasmimport and wasmexport declarations for "local:gomodule-server". 10 | 11 | //go:wasmexport local:gomodule-server/gomodule#get-latest-versions 12 | //export local:gomodule-server/gomodule#get-latest-versions 13 | func wasmexport_GetLatestVersions(moduleNames0 *uint8, moduleNames1 uint32) (result *cm.Result[string, string, string]) { 14 | moduleNames := cm.LiftString[string]((*uint8)(moduleNames0), (uint32)(moduleNames1)) 15 | result_ := Exports.GetLatestVersions(moduleNames) 16 | result = &result_ 17 | return 18 | } 19 | 20 | //go:wasmexport local:gomodule-server/gomodule#get-module-info 21 | //export local:gomodule-server/gomodule#get-module-info 22 | func wasmexport_GetModuleInfo(moduleNames0 *uint8, moduleNames1 uint32) (result *cm.Result[string, string, string]) { 23 | moduleNames := cm.LiftString[string]((*uint8)(moduleNames0), (uint32)(moduleNames1)) 24 | result_ := Exports.GetModuleInfo(moduleNames) 25 | result = &result_ 26 | return 27 | } 28 | -------------------------------------------------------------------------------- /examples/context7-rs/wit/world.wit: -------------------------------------------------------------------------------- 1 | package local:context7@0.1.0; 2 | 3 | interface context7 { 4 | record library-result { 5 | id: string, 6 | name: string, 7 | description: string, 8 | code-snippets: u32, 9 | trust-score: u32, 10 | versions: list, 11 | } 12 | 13 | record search-response { 14 | success: bool, 15 | results: list, 16 | error: option, 17 | } 18 | 19 | record docs-response { 20 | success: bool, 21 | content: option, 22 | error: option, 23 | } 24 | 25 | /// Resolves a library name to Context7-compatible library IDs 26 | resolve-library-id: func(library-name: string) -> search-response; 27 | 28 | /// Fetches documentation for a library using Context7-compatible library ID 29 | get-library-docs: func( 30 | context7-compatible-library-id: string, 31 | topic: option, 32 | tokens: option 33 | ) -> docs-response; 34 | } 35 | 36 | world context7-component { 37 | import wasi:http/outgoing-handler@0.2.1; 38 | import wasi:cli/environment@0.2.1; 39 | export context7; 40 | } 41 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/sockets/ip-name-lookup/ip-name-lookup.wasm.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package ipnamelookup 4 | 5 | import ( 6 | "go.bytecodealliance.org/cm" 7 | ) 8 | 9 | // This file contains wasmimport and wasmexport declarations for "wasi:sockets@0.2.0". 10 | 11 | //go:wasmimport wasi:sockets/ip-name-lookup@0.2.0 [resource-drop]resolve-address-stream 12 | //go:noescape 13 | func wasmimport_ResolveAddressStreamResourceDrop(self0 uint32) 14 | 15 | //go:wasmimport wasi:sockets/ip-name-lookup@0.2.0 [method]resolve-address-stream.resolve-next-address 16 | //go:noescape 17 | func wasmimport_ResolveAddressStreamResolveNextAddress(self0 uint32, result *cm.Result[OptionIPAddressShape, cm.Option[IPAddress], ErrorCode]) 18 | 19 | //go:wasmimport wasi:sockets/ip-name-lookup@0.2.0 [method]resolve-address-stream.subscribe 20 | //go:noescape 21 | func wasmimport_ResolveAddressStreamSubscribe(self0 uint32) (result0 uint32) 22 | 23 | //go:wasmimport wasi:sockets/ip-name-lookup@0.2.0 resolve-addresses 24 | //go:noescape 25 | func wasmimport_ResolveAddresses(network0 uint32, name0 *uint8, name1 uint32, result *cm.Result[ResolveAddressStream, ResolveAddressStream, ErrorCode]) 26 | -------------------------------------------------------------------------------- /docs/mermaid-init.js: -------------------------------------------------------------------------------- 1 | (() => { 2 | const darkThemes = ['ayu', 'navy', 'coal']; 3 | const lightThemes = ['light', 'rust']; 4 | 5 | const classList = document.getElementsByTagName('html')[0].classList; 6 | 7 | let lastThemeWasLight = true; 8 | for (const cssClass of classList) { 9 | if (darkThemes.includes(cssClass)) { 10 | lastThemeWasLight = false; 11 | break; 12 | } 13 | } 14 | 15 | const theme = lastThemeWasLight ? 'default' : 'dark'; 16 | mermaid.initialize({ startOnLoad: true, theme }); 17 | 18 | // Simplest way to make mermaid re-render the diagrams in the new theme is via refreshing the page 19 | 20 | for (const darkTheme of darkThemes) { 21 | document.getElementById(darkTheme).addEventListener('click', () => { 22 | if (lastThemeWasLight) { 23 | window.location.reload(); 24 | } 25 | }); 26 | } 27 | 28 | for (const lightTheme of lightThemes) { 29 | document.getElementById(lightTheme).addEventListener('click', () => { 30 | if (!lastThemeWasLight) { 31 | window.location.reload(); 32 | } 33 | }); 34 | } 35 | })(); 36 | -------------------------------------------------------------------------------- /examples/get-weather-js/weather.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | import { get } from "wasi:config/store@0.2.0-draft"; 5 | 6 | export async function getWeather(city) { 7 | const apiKey = await get("OPENWEATHER_API_KEY"); 8 | if (apiKey === undefined) { 9 | throw "Error: OPENWEATHER_API_KEY is not set"; 10 | } 11 | 12 | try { 13 | const geoResponse = await fetch( 14 | `https://api.openweathermap.org/geo/1.0/direct?q=${city}&limit=1&appid=${apiKey}` 15 | ); 16 | if (!geoResponse.ok) { 17 | throw "Error: Failed to fetch geo data"; 18 | } 19 | const geoData = await geoResponse.json(); 20 | const lat = geoData[0].lat; 21 | const lon = geoData[0].lon; 22 | const response = await fetch( 23 | `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${apiKey}&units=metric` 24 | ); 25 | if (!response.ok) { 26 | throw "Error: Failed to fetch weather data"; 27 | } 28 | const data = await response.json(); 29 | const weather = data.main.temp.toString(); 30 | return weather; 31 | } catch (error) { 32 | throw error.message || "Error fetching weather data"; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /examples/github-js/wit/deps/wasi-config-0.2.0-draft/package.wit: -------------------------------------------------------------------------------- 1 | package wasi:config@0.2.0-draft; 2 | 3 | interface store { 4 | /// An error type that encapsulates the different errors that can occur fetching config 5 | variant config-error { 6 | /// This indicates an error from an "upstream" config source. 7 | /// As this could be almost _anything_ (such as Vault, Kubernetes ConfigMaps, KeyValue buckets, etc), 8 | /// the error message is a string. 9 | upstream(string), 10 | /// This indicates an error from an I/O operation. 11 | /// As this could be almost _anything_ (such as a file read, network connection, etc), 12 | /// the error message is a string. 13 | /// Depending on how this ends up being consumed, 14 | /// we may consider moving this to use the `wasi:io/error` type instead. 15 | /// For simplicity right now in supporting multiple implementations, it is being left as a string. 16 | io(string), 17 | } 18 | 19 | /// Gets a single opaque config value set at the given key if it exists 20 | get: func(key: string) -> result, config-error>; 21 | 22 | /// Gets a list of all set config data 23 | get-all: func() -> result>, config-error>; 24 | } 25 | 26 | world imports { 27 | import store; 28 | } 29 | -------------------------------------------------------------------------------- /examples/get-weather-js/wit/deps/wasi-config-0.2.0-draft/package.wit: -------------------------------------------------------------------------------- 1 | package wasi:config@0.2.0-draft; 2 | 3 | interface store { 4 | /// An error type that encapsulates the different errors that can occur fetching config 5 | variant config-error { 6 | /// This indicates an error from an "upstream" config source. 7 | /// As this could be almost _anything_ (such as Vault, Kubernetes ConfigMaps, KeyValue buckets, etc), 8 | /// the error message is a string. 9 | upstream(string), 10 | /// This indicates an error from an I/O operation. 11 | /// As this could be almost _anything_ (such as a file read, network connection, etc), 12 | /// the error message is a string. 13 | /// Depending on how this ends up being consumed, 14 | /// we may consider moving this to use the `wasi:io/error` type instead. 15 | /// For simplicity right now in supporting multiple implementations, it is being left as a string. 16 | io(string), 17 | } 18 | 19 | /// Gets a single opaque config value set at the given key if it exists 20 | get: func(key: string) -> result, config-error>; 21 | 22 | /// Gets a list of all set config data 23 | get-all: func() -> result>, config-error>; 24 | } 25 | 26 | world imports { 27 | import store; 28 | } 29 | -------------------------------------------------------------------------------- /examples/context7-rs/wit/deps/random/insecure-seed.wit: -------------------------------------------------------------------------------- 1 | package wasi:random@0.2.1; 2 | /// The insecure-seed interface for seeding hash-map DoS resistance. 3 | /// 4 | /// It is intended to be portable at least between Unix-family platforms and 5 | /// Windows. 6 | @since(version = 0.2.0) 7 | interface insecure-seed { 8 | /// Return a 128-bit value that may contain a pseudo-random value. 9 | /// 10 | /// The returned value is not required to be computed from a CSPRNG, and may 11 | /// even be entirely deterministic. Host implementations are encouraged to 12 | /// provide pseudo-random values to any program exposed to 13 | /// attacker-controlled content, to enable DoS protection built into many 14 | /// languages' hash-map implementations. 15 | /// 16 | /// This function is intended to only be called once, by a source language 17 | /// to initialize Denial Of Service (DoS) protection in its hash-map 18 | /// implementation. 19 | /// 20 | /// # Expected future evolution 21 | /// 22 | /// This will likely be changed to a value import, to prevent it from being 23 | /// called multiple times and potentially used for purposes other than DoS 24 | /// protection. 25 | @since(version = 0.2.0) 26 | insecure-seed: func() -> tuple; 27 | } 28 | -------------------------------------------------------------------------------- /crates/policy/testdata/web-service.yaml: -------------------------------------------------------------------------------- 1 | $schema: https://raw.githubusercontent.com/microsoft/policy-mcp/main/schema/policy-v1.0.schema.json 2 | version: "1.0" 3 | description: "Web service policy for HTTP server deployment" 4 | permissions: 5 | storage: 6 | allow: 7 | - uri: "fs://app/**" 8 | access: ["read"] 9 | - uri: "fs://logs/**" 10 | access: ["write"] 11 | - uri: "fs://uploads/**" 12 | access: ["read", "write"] 13 | deny: 14 | - uri: "fs://app/config/secrets.yaml" 15 | access: ["read"] 16 | 17 | network: 18 | allow: 19 | - host: "api.stripe.com" 20 | - host: "api.sendgrid.com" 21 | - host: "*.amazonaws.com" 22 | - cidr: "10.0.0.0/8" 23 | deny: 24 | - host: "*.internal.admin.com" 25 | 26 | environment: 27 | allow: 28 | - key: "PATH" 29 | - key: "PORT" 30 | - key: "NODE_ENV" 31 | - key: "DATABASE_URL" 32 | - key: "REDIS_URL" 33 | - key: "JWT_SECRET" 34 | - key: "STRIPE_API_KEY" 35 | 36 | runtime: 37 | docker: 38 | security: 39 | privileged: false 40 | no_new_privileges: true 41 | capabilities: 42 | drop: ["ALL"] 43 | add: ["NET_BIND_SERVICE"] 44 | 45 | resources: 46 | cpu: 75.0 47 | memory: 512 48 | io: 500 -------------------------------------------------------------------------------- /examples/get-open-meteo-weather-js/weather.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | export async function getWeather(city) { 5 | try { 6 | // Geocode the location using Open-Meteo 7 | const geoResponse = await fetch( 8 | `https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(city)}&count=1&language=en&format=json` 9 | ); 10 | if (!geoResponse.ok) { 11 | throw "Error: Failed to fetch geo data"; 12 | } 13 | const geoData = await geoResponse.json(); 14 | if (!geoData.results || geoData.results.length === 0) { 15 | throw `Error: Location '${city}' not found`; 16 | } 17 | 18 | const lat = geoData.results[0].latitude; 19 | const lon = geoData.results[0].longitude; 20 | 21 | // Get weather data from Open-Meteo 22 | const response = await fetch( 23 | `https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}¤t=temperature_2m` 24 | ); 25 | if (!response.ok) { 26 | throw "Error: Failed to fetch weather data"; 27 | } 28 | const data = await response.json(); 29 | const weather = data.current.temperature_2m.toString(); 30 | return weather; 31 | } catch (error) { 32 | throw error.message || "Error fetching weather data"; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /examples/arxiv-rs/wit/world.wit: -------------------------------------------------------------------------------- 1 | package component:arxiv-rs; 2 | 3 | /// An example world for arXiv research component 4 | world arxiv { 5 | /// Search for papers on arXiv 6 | /// 7 | /// Parameters: 8 | /// - query: search query (e.g., "machine learning", "cat:cs.AI", "ti:neural networks") 9 | /// - max-results: maximum number of results to return 10 | /// - date-from: optional date filter in YYYYMMDD format (empty string to skip) 11 | /// - categories: optional comma-separated category filter (empty string to skip) 12 | /// 13 | /// Returns formatted markdown with paper results 14 | export search-papers: func(query: string, max-results: u32, date-from: string, categories: string) -> result; 15 | 16 | /// Download a paper PDF from arXiv 17 | /// 18 | /// Parameters: 19 | /// - id: arXiv paper ID (e.g., "2301.00001") 20 | /// 21 | /// Returns the PDF content as bytes 22 | export download-paper: func(id: string) -> result, string>; 23 | 24 | /// Read paper metadata and abstract from arXiv 25 | /// 26 | /// Parameters: 27 | /// - id: arXiv paper ID (e.g., "2301.00001") 28 | /// 29 | /// Returns formatted markdown with paper details 30 | export read-paper: func(id: string) -> result; 31 | } 32 | -------------------------------------------------------------------------------- /crates/wassette/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wassette" 3 | version = "0.1.0" 4 | edition = "2021" 5 | license.workspace = true 6 | 7 | [dependencies] 8 | anyhow = { workspace = true } 9 | component2json = { path = "../component2json" } 10 | etcetera = { workspace = true } 11 | futures = { workspace = true } 12 | hex = "0.4" 13 | http = "1.4" 14 | num_cpus = "1.0" 15 | hyper = { version = "1.7", features = ["client"] } 16 | oci-client = { workspace = true } 17 | oci-wasm = { workspace = true } 18 | policy = { workspace = true } 19 | reqwest = { workspace = true } 20 | serde = { workspace = true } 21 | serde_json = { workspace = true } 22 | sha2 = "0.10" 23 | serde_yaml = { workspace = true } 24 | tempfile = { workspace = true } 25 | tokio = { workspace = true, features = ["full", "test-util"] } 26 | tokio-util = { workspace = true, features = ["io"] } 27 | tracing = { workspace = true, features = ["attributes"] } 28 | url = "2.5" 29 | wasmtime = { workspace = true } 30 | wasmtime-wasi = { workspace = true } 31 | wasmtime-wasi-http = { workspace = true } 32 | wasmtime-wasi-config = { workspace = true } 33 | 34 | [dev-dependencies] 35 | proptest = "1.8" 36 | temp-env = "0.3" 37 | test-log = { workspace = true, features = ["trace"] } 38 | tokio-test = { workspace = true } 39 | tracing-subscriber = { workspace = true, features = ["env-filter"] } 40 | tracing-test = { workspace = true } 41 | -------------------------------------------------------------------------------- /examples/context7-rs/wit/deps/random/random.wit: -------------------------------------------------------------------------------- 1 | package wasi:random@0.2.1; 2 | /// WASI Random is a random data API. 3 | /// 4 | /// It is intended to be portable at least between Unix-family platforms and 5 | /// Windows. 6 | @since(version = 0.2.0) 7 | interface random { 8 | /// Return `len` cryptographically-secure random or pseudo-random bytes. 9 | /// 10 | /// This function must produce data at least as cryptographically secure and 11 | /// fast as an adequately seeded cryptographically-secure pseudo-random 12 | /// number generator (CSPRNG). It must not block, from the perspective of 13 | /// the calling program, under any circumstances, including on the first 14 | /// request and on requests for numbers of bytes. The returned data must 15 | /// always be unpredictable. 16 | /// 17 | /// This function must always return fresh data. Deterministic environments 18 | /// must omit this function, rather than implementing it with deterministic 19 | /// data. 20 | @since(version = 0.2.0) 21 | get-random-bytes: func(len: u64) -> list; 22 | 23 | /// Return a cryptographically-secure random or pseudo-random `u64` value. 24 | /// 25 | /// This function returns the same type of data as `get-random-bytes`, 26 | /// represented as a `u64`. 27 | @since(version = 0.2.0) 28 | get-random-u64: func() -> u64; 29 | } 30 | -------------------------------------------------------------------------------- /crates/policy/testdata/development.yaml: -------------------------------------------------------------------------------- 1 | $schema: https://raw.githubusercontent.com/microsoft/policy-mcp/main/schema/policy-v1.0.schema.json 2 | version: "1.0" 3 | description: "Development environment policy with broad permissions" 4 | permissions: 5 | storage: 6 | allow: 7 | - uri: "fs://workspace/**" 8 | access: ["read", "write"] 9 | - uri: "fs://home/dev/**" 10 | access: ["read", "write"] 11 | - uri: "fs://tmp/**" 12 | access: ["read", "write"] 13 | deny: 14 | - uri: "fs://etc/passwd" 15 | access: ["write"] 16 | - uri: "fs://etc/shadow" 17 | access: ["read", "write"] 18 | 19 | network: 20 | allow: 21 | - host: "*.npmjs.org" 22 | - host: "*.github.com" 23 | - host: "*.docker.io" 24 | - host: "*.pypi.org" 25 | - host: "localhost" 26 | - cidr: "127.0.0.0/8" 27 | - cidr: "192.168.0.0/16" 28 | - cidr: "10.0.0.0/8" 29 | 30 | environment: 31 | allow: 32 | - key: "PATH" 33 | - key: "HOME" 34 | - key: "USER" 35 | - key: "SHELL" 36 | - key: "TERM" 37 | - key: "EDITOR" 38 | - key: "NODE_ENV" 39 | - key: "PYTHON_PATH" 40 | - key: "GOPATH" 41 | - key: "CARGO_HOME" 42 | - key: "RUSTUP_HOME" 43 | 44 | runtime: 45 | docker: 46 | security: 47 | privileged: false 48 | no_new_privileges: true 49 | capabilities: 50 | drop: ["ALL"] 51 | add: ["NET_BIND_SERVICE"] -------------------------------------------------------------------------------- /examples/eval-py/README.md: -------------------------------------------------------------------------------- 1 | # Python Evaluation Example 2 | 3 | This example demonstrates how to evaluate a Python expression using a Wassette component. 4 | 5 | For more information on installing Wassette, please see the [installation instructions](https://github.com/microsoft/wassette?tab=readme-ov-file#installation). 6 | 7 | ## Building 8 | 9 | This example uses `componentize-py` to build the component with an additional documentation injection step: 10 | 11 | ```bash 12 | # Generate bindings and build the component 13 | just build 14 | 15 | # From repository root: inject WIT documentation into the component 16 | just inject-docs examples/eval-py/eval.wasm examples/eval-py/wit 17 | ``` 18 | 19 | The documentation injection embeds the WIT interface documentation into the WASM binary, making it available to AI agents when they discover this tool. See [`wit/world.wit`](wit/world.wit) for the documented interface. 20 | 21 | For more information about documenting components, see the [Documenting WIT Interfaces](../../docs/cookbook/documenting-wit.md) guide. 22 | 23 | ## Usage 24 | 25 | To use this component, load it from the OCI registry and provide a Python expression to evaluate. 26 | 27 | **Load the component:** 28 | ``` 29 | Please load the component from oci://ghcr.io/microsoft/eval-py:latest 30 | ``` 31 | 32 | **Evaluate an expression:** 33 | ``` 34 | Please evaluate the python expression '2 + 2' 35 | ``` 36 | 37 | The source code for this example can be found in [`main.py`](main.py). 38 | -------------------------------------------------------------------------------- /examples/gomodule-go/README.md: -------------------------------------------------------------------------------- 1 | # Go Module Example (Go) 2 | 3 | This example demonstrates how to get information about Go modules using a Wassette component written in Go. 4 | 5 | For more information on installing Wassette, please see the [installation instructions](https://github.com/microsoft/wassette?tab=readme-ov-file#installation). 6 | 7 | ## Building 8 | 9 | This example uses TinyGo to build the component with an additional documentation injection step: 10 | 11 | ```bash 12 | # Generate bindings and build the component 13 | just build 14 | 15 | # From repository root: inject WIT documentation into the component 16 | just inject-docs examples/gomodule-go/gomodule.wasm examples/gomodule-go/wit 17 | ``` 18 | 19 | The documentation injection embeds the WIT interface documentation into the WASM binary, making it available to AI agents when they discover this tool. See [`wit/world.wit`](wit/world.wit) for the documented interface. 20 | 21 | For more information about documenting components, see the [Documenting WIT Interfaces](../../docs/cookbook/documenting-wit.md) guide. 22 | 23 | ## Usage 24 | 25 | To use this component, load it from the OCI registry and provide a Go module path. 26 | 27 | **Load the component:** 28 | ``` 29 | Please load the component from oci://ghcr.io/microsoft/gomodule-go:latest 30 | ``` 31 | 32 | **Get module information:** 33 | ``` 34 | get the latest versions for the go module urfave/cli 35 | ``` 36 | 37 | The source code for this example can be found in [`main.go`](main.go). 38 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/random/insecure-seed/insecure-seed.wit.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | // Package insecureseed represents the imported interface "wasi:random/insecure-seed@0.2.0". 4 | // 5 | // The insecure-seed interface for seeding hash-map DoS resistance. 6 | // 7 | // It is intended to be portable at least between Unix-family platforms and 8 | // Windows. 9 | package insecureseed 10 | 11 | // InsecureSeed represents the imported function "insecure-seed". 12 | // 13 | // Return a 128-bit value that may contain a pseudo-random value. 14 | // 15 | // The returned value is not required to be computed from a CSPRNG, and may 16 | // even be entirely deterministic. Host implementations are encouraged to 17 | // provide pseudo-random values to any program exposed to 18 | // attacker-controlled content, to enable DoS protection built into many 19 | // languages' hash-map implementations. 20 | // 21 | // This function is intended to only be called once, by a source language 22 | // to initialize Denial Of Service (DoS) protection in its hash-map 23 | // implementation. 24 | // 25 | // # Expected future evolution 26 | // 27 | // This will likely be changed to a value import, to prevent it from being 28 | // called multiple times and potentially used for purposes other than DoS 29 | // protection. 30 | // 31 | // insecure-seed: func() -> tuple 32 | // 33 | //go:nosplit 34 | func InsecureSeed() (result [2]uint64) { 35 | wasmimport_InsecureSeed(&result) 36 | return 37 | } 38 | -------------------------------------------------------------------------------- /crates/policy/testdata/comprehensive.yaml: -------------------------------------------------------------------------------- 1 | $schema: https://raw.githubusercontent.com/microsoft/policy-mcp/main/schema/policy-v1.0.schema.json 2 | version: "1.0" 3 | description: "Comprehensive policy with all permission types" 4 | permissions: 5 | storage: 6 | allow: 7 | - uri: "fs://workspace/**" 8 | access: ["read", "write"] 9 | - uri: "fs://config/app.yaml" 10 | access: ["read"] 11 | deny: 12 | - uri: "fs://system/**" 13 | access: ["read", "write"] 14 | 15 | network: 16 | allow: 17 | - host: "api.openai.com" 18 | - host: "*.internal.company.com" 19 | - cidr: "10.0.0.0/8" 20 | - cidr: "172.16.0.0/12" 21 | deny: 22 | - host: "*.malicious.com" 23 | - cidr: "0.0.0.0/0" 24 | 25 | environment: 26 | allow: 27 | - key: "PATH" 28 | - key: "HOME" 29 | - key: "USER" 30 | - key: "API_KEY" 31 | - key: "DATABASE_URL" 32 | 33 | runtime: 34 | docker: 35 | security: 36 | privileged: false 37 | no_new_privileges: true 38 | capabilities: 39 | drop: ["ALL"] 40 | add: ["NET_BIND_SERVICE", "SYS_TIME"] 41 | hyperlight: 42 | 43 | resources: 44 | limits: 45 | cpu: "50" # 50 cores 46 | memory: "1Gi" # 1 GiB 47 | # Legacy field maintained for backward compatibility 48 | io: 1000 49 | 50 | ipc: 51 | allow: 52 | - uri: "pipe://app-service" 53 | - uri: "socket://unix:/tmp/app.sock" 54 | deny: 55 | - uri: "pipe://system-service" -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/filesystem/types/abi.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | package types 4 | 5 | import ( 6 | "go.bytecodealliance.org/cm" 7 | wallclock "gomodule-server-go/gen/wasi/clocks/wall-clock" 8 | "unsafe" 9 | ) 10 | 11 | // MetadataHashValueShape is used for storage in variant or result types. 12 | type MetadataHashValueShape struct { 13 | _ cm.HostLayout 14 | shape [unsafe.Sizeof(MetadataHashValue{})]byte 15 | } 16 | 17 | // TupleListU8BoolShape is used for storage in variant or result types. 18 | type TupleListU8BoolShape struct { 19 | _ cm.HostLayout 20 | shape [unsafe.Sizeof(cm.Tuple[cm.List[uint8], bool]{})]byte 21 | } 22 | 23 | func lower_DateTime(v wallclock.DateTime) (f0 uint64, f1 uint32) { 24 | f0 = (uint64)(v.Seconds) 25 | f1 = (uint32)(v.Nanoseconds) 26 | return 27 | } 28 | 29 | func lower_NewTimestamp(v NewTimestamp) (f0 uint32, f1 uint64, f2 uint32) { 30 | f0 = (uint32)(v.Tag()) 31 | switch f0 { 32 | case 2: // timestamp 33 | v1, v2 := lower_DateTime(*cm.Case[DateTime](&v, 2)) 34 | f1 = (uint64)(v1) 35 | f2 = (uint32)(v2) 36 | } 37 | return 38 | } 39 | 40 | // DescriptorStatShape is used for storage in variant or result types. 41 | type DescriptorStatShape struct { 42 | _ cm.HostLayout 43 | shape [unsafe.Sizeof(DescriptorStat{})]byte 44 | } 45 | 46 | // OptionDirectoryEntryShape is used for storage in variant or result types. 47 | type OptionDirectoryEntryShape struct { 48 | _ cm.HostLayout 49 | shape [unsafe.Sizeof(cm.Option[DirectoryEntry]{})]byte 50 | } 51 | -------------------------------------------------------------------------------- /examples/get-open-meteo-weather-js/README.md: -------------------------------------------------------------------------------- 1 | # Get Weather Example (JavaScript) 2 | 3 | This example demonstrates how to get the weather for a given location using a Wassette component written in JavaScript. 4 | 5 | For more information on installing Wassette, please see the [installation instructions](https://github.com/microsoft/wassette?tab=readme-ov-file#installation). 6 | 7 | ## Usage 8 | 9 | This component uses the [Open-Meteo API](https://open-meteo.com/), which provides free weather data without requiring authentication. 10 | 11 | Load the component from the OCI registry and provide a city name. 12 | 13 | **Load the component:** 14 | 15 | ``` 16 | Please load the component from oci://ghcr.io/microsoft/get-weather-js:latest 17 | ``` 18 | 19 | **Get the weather:** 20 | 21 | ``` 22 | get the weather for Toronto 23 | ``` 24 | 25 | ## Policy 26 | 27 | By default, WebAssembly (Wasm) components do not have any access to the host machine or network. The `policy.yaml` file is used to explicitly define what network resources and environment variables are made available to the component. This ensures that the component can only access the resources that are explicitly allowed. 28 | 29 | Example: 30 | 31 | ```yaml 32 | version: "1.0" 33 | description: "Permission policy for wassette weather demo" 34 | permissions: 35 | network: 36 | allow: 37 | - host: "geocoding-api.open-meteo.com" # For geocoding city names to coordinates 38 | - host: "api.open-meteo.com" # For fetching weather data 39 | ``` 40 | 41 | The source code for this example can be found in [`weather.js`](weather.js). 42 | -------------------------------------------------------------------------------- /docs/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | - [Overview](./overview.md) 4 | - [Installation](./installation.md) 5 | - [Quick Start](./quick-start.md) 6 | - [Concepts](./concepts.md) 7 | - [MCP Clients](./mcp-clients.md) 8 | - [FAQ](./faq.md) 9 | 10 | # Deployment 11 | 12 | - [Docker](./deployment/docker.md) 13 | - [Operations](./deployment/operations.md) 14 | 15 | # Developer Guide 16 | 17 | - [Getting Started](./development/getting-started.md) 18 | 19 | # Cookbook 20 | 21 | - [Building Wasm Components](./cookbook/README.md) 22 | - [Documenting WIT Interfaces](./cookbook/documenting-wit.md) 23 | - [Migrating from JavaScript MCP Servers](./cookbook/migrating-from-mcp-server.md) 24 | - [JavaScript/TypeScript](./cookbook/javascript.md) 25 | - [Python](./cookbook/python.md) 26 | - [Rust](./cookbook/rust.md) 27 | - [Go](./cookbook/go.md) 28 | - [Publishing to OCI Registries](./cookbook/publishing-to-oci-registries.md) 29 | 30 | # Reference 31 | 32 | - [CLI](./reference/cli.md) 33 | - [Built-in Tools](./reference/built-in-tools.md) 34 | - [Permissions](./reference/permissions.md) 35 | - [Environment Variables](./reference/environment-variables.md) 36 | - [config.toml](./reference/configuration-files.md) 37 | - [Community Components](./reference/community-components.md) 38 | 39 | # Design & Architecture 40 | 41 | - [Architecture](./design/architecture.md) 42 | - [Permission System](./design/permission-system.md) 43 | - [MCP Threat Model](./design/mcp-threat-model.md) 44 | - [Component Schemas & Structured Output](./design/component2json-structured-output.md) 45 | - [Agentic Workflows](./design/agentic-workflows.md) 46 | -------------------------------------------------------------------------------- /Formula/wassette.rb: -------------------------------------------------------------------------------- 1 | class Wassette < Formula 2 | desc "Wassette: A security-oriented runtime that runs WebAssembly Components via MCP" 3 | homepage "https://github.com/microsoft/wassette" 4 | # Change this to install a different version of wassette. 5 | # The release tag in GitHub must exist with a 'v' prefix (e.g., v0.1.0). 6 | version "0.3.0" 7 | 8 | on_macos do 9 | if Hardware::CPU.intel? 10 | url "https://github.com/microsoft/wassette/releases/download/v#{version}/wassette_#{version}_darwin_amd64.tar.gz" 11 | sha256 "2800d0ea1f722fb6814caed07f7b93ab1fa637f75b3a096d8b482158c8c2eb98" 12 | else 13 | url "https://github.com/microsoft/wassette/releases/download/v#{version}/wassette_#{version}_darwin_arm64.tar.gz" 14 | sha256 "394ede6bd2ad8420e59d4cd88e6a6c0299e6b7997b044599282f0d6941c5d575" 15 | end 16 | end 17 | 18 | on_linux do 19 | if Hardware::CPU.intel? 20 | url "https://github.com/microsoft/wassette/releases/download/v#{version}/wassette_#{version}_linux_amd64.tar.gz" 21 | sha256 "7510424ce5ef7db02ae8e02d8dbf49ce1a723cec61451201d3107a405f56d6c9" 22 | else 23 | url "https://github.com/microsoft/wassette/releases/download/v#{version}/wassette_#{version}_linux_arm64.tar.gz" 24 | sha256 "fa92161cf0bf1644f368ab4f87bdcd4483079d679ed7baeebfbbeb5a0e43df9a" 25 | end 26 | end 27 | 28 | def install 29 | bin.install "wassette" 30 | end 31 | 32 | test do 33 | # Check if the installed binary's version matches the formula's version 34 | assert_match "wassette-mcp-server #{version}", shell_output("#{bin}/wassette --version") 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /Dockerfile.prebuilt: -------------------------------------------------------------------------------- 1 | # Wassette Docker Image (Pre-built Binary) 2 | # This Dockerfile uses a pre-built Wassette binary for faster builds 3 | # Useful when you already have the binary compiled on your host system 4 | 5 | FROM debian:bookworm-slim 6 | 7 | # Install runtime dependencies 8 | RUN apt-get update && \ 9 | apt-get install -y --no-install-recommends \ 10 | ca-certificates \ 11 | libssl3 && \ 12 | rm -rf /var/lib/apt/lists/* 13 | 14 | # Create a non-root user for running Wassette 15 | RUN useradd -m -u 1000 -s /bin/bash wassette 16 | 17 | # Create necessary directories with proper permissions 18 | RUN mkdir -p /home/wassette/.local/share/wassette/components && \ 19 | mkdir -p /home/wassette/.config/wassette/secrets && \ 20 | chown -R wassette:wassette /home/wassette 21 | 22 | # Copy the pre-built binary from the host (build context) 23 | # Build the binary first with: cargo build --release --bin wassette 24 | # Then copy it: COPY target/release/wassette /usr/local/bin/wassette 25 | COPY target/release/wassette /usr/local/bin/wassette 26 | RUN chmod +x /usr/local/bin/wassette 27 | 28 | # Set up environment 29 | ENV HOME=/home/wassette 30 | ENV XDG_DATA_HOME=/home/wassette/.local/share 31 | ENV XDG_CONFIG_HOME=/home/wassette/.config 32 | 33 | # Switch to the non-root user 34 | USER wassette 35 | WORKDIR /home/wassette 36 | 37 | # Expose the default HTTP port (when using --http or --sse) 38 | EXPOSE 9001 39 | 40 | # Default command: start Wassette with streamable-http transport 41 | # Override this in docker run or docker-compose for different transports 42 | CMD ["wassette", "serve", "--streamable-http"] 43 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/io/poll/poll.wit.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | // Package poll represents the imported interface "wasi:io/poll@0.2.0". 4 | package poll 5 | 6 | import ( 7 | "go.bytecodealliance.org/cm" 8 | ) 9 | 10 | // Pollable represents the imported resource "wasi:io/poll@0.2.0#pollable". 11 | // 12 | // resource pollable 13 | type Pollable cm.Resource 14 | 15 | // ResourceDrop represents the imported resource-drop for resource "pollable". 16 | // 17 | // Drops a resource handle. 18 | // 19 | //go:nosplit 20 | func (self Pollable) ResourceDrop() { 21 | self0 := cm.Reinterpret[uint32](self) 22 | wasmimport_PollableResourceDrop((uint32)(self0)) 23 | return 24 | } 25 | 26 | // Block represents the imported method "block". 27 | // 28 | // block: func() 29 | // 30 | //go:nosplit 31 | func (self Pollable) Block() { 32 | self0 := cm.Reinterpret[uint32](self) 33 | wasmimport_PollableBlock((uint32)(self0)) 34 | return 35 | } 36 | 37 | // Ready represents the imported method "ready". 38 | // 39 | // ready: func() -> bool 40 | // 41 | //go:nosplit 42 | func (self Pollable) Ready() (result bool) { 43 | self0 := cm.Reinterpret[uint32](self) 44 | result0 := wasmimport_PollableReady((uint32)(self0)) 45 | result = (bool)(cm.U32ToBool((uint32)(result0))) 46 | return 47 | } 48 | 49 | // Poll represents the imported function "poll". 50 | // 51 | // poll: func(in: list>) -> list 52 | // 53 | //go:nosplit 54 | func Poll(in cm.List[Pollable]) (result cm.List[uint32]) { 55 | in0, in1 := cm.LowerList(in) 56 | wasmimport_Poll((*Pollable)(in0), (uint32)(in1), &result) 57 | return 58 | } 59 | -------------------------------------------------------------------------------- /examples/gomodule-go/wit/deps/wasi-io-0.2.0/package.wit: -------------------------------------------------------------------------------- 1 | package wasi:io@0.2.0; 2 | 3 | interface poll { 4 | resource pollable { 5 | ready: func() -> bool; 6 | block: func(); 7 | } 8 | 9 | poll: func(in: list>) -> list; 10 | } 11 | 12 | interface error { 13 | resource error { 14 | to-debug-string: func() -> string; 15 | } 16 | } 17 | 18 | interface streams { 19 | use error.{error}; 20 | use poll.{pollable}; 21 | 22 | variant stream-error { 23 | last-operation-failed(error), 24 | closed, 25 | } 26 | 27 | resource input-stream { 28 | read: func(len: u64) -> result, stream-error>; 29 | blocking-read: func(len: u64) -> result, stream-error>; 30 | skip: func(len: u64) -> result; 31 | blocking-skip: func(len: u64) -> result; 32 | subscribe: func() -> pollable; 33 | } 34 | 35 | resource output-stream { 36 | check-write: func() -> result; 37 | write: func(contents: list) -> result<_, stream-error>; 38 | blocking-write-and-flush: func(contents: list) -> result<_, stream-error>; 39 | flush: func() -> result<_, stream-error>; 40 | blocking-flush: func() -> result<_, stream-error>; 41 | subscribe: func() -> pollable; 42 | write-zeroes: func(len: u64) -> result<_, stream-error>; 43 | blocking-write-zeroes-and-flush: func(len: u64) -> result<_, stream-error>; 44 | splice: func(src: borrow, len: u64) -> result; 45 | blocking-splice: func(src: borrow, len: u64) -> result; 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/cli/environment/environment.wit.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | // Package environment represents the imported interface "wasi:cli/environment@0.2.0". 4 | package environment 5 | 6 | import ( 7 | "go.bytecodealliance.org/cm" 8 | ) 9 | 10 | // GetEnvironment represents the imported function "get-environment". 11 | // 12 | // Get the POSIX-style environment variables. 13 | // 14 | // Each environment variable is provided as a pair of string variable names 15 | // and string value. 16 | // 17 | // Morally, these are a value import, but until value imports are available 18 | // in the component model, this import function should return the same 19 | // values each time it is called. 20 | // 21 | // get-environment: func() -> list> 22 | // 23 | //go:nosplit 24 | func GetEnvironment() (result cm.List[[2]string]) { 25 | wasmimport_GetEnvironment(&result) 26 | return 27 | } 28 | 29 | // GetArguments represents the imported function "get-arguments". 30 | // 31 | // Get the POSIX-style arguments to the program. 32 | // 33 | // get-arguments: func() -> list 34 | // 35 | //go:nosplit 36 | func GetArguments() (result cm.List[string]) { 37 | wasmimport_GetArguments(&result) 38 | return 39 | } 40 | 41 | // InitialCWD represents the imported function "initial-cwd". 42 | // 43 | // Return a path that programs should use as their initial current working 44 | // directory, interpreting `.` as shorthand for this. 45 | // 46 | // initial-cwd: func() -> option 47 | // 48 | //go:nosplit 49 | func InitialCWD() (result cm.Option[string]) { 50 | wasmimport_InitialCWD(&result) 51 | return 52 | } 53 | -------------------------------------------------------------------------------- /examples/context7-rs/wit/deps/io/error.wit: -------------------------------------------------------------------------------- 1 | package wasi:io@0.2.1; 2 | 3 | @since(version = 0.2.0) 4 | interface error { 5 | /// A resource which represents some error information. 6 | /// 7 | /// The only method provided by this resource is `to-debug-string`, 8 | /// which provides some human-readable information about the error. 9 | /// 10 | /// In the `wasi:io` package, this resource is returned through the 11 | /// `wasi:io/streams/stream-error` type. 12 | /// 13 | /// To provide more specific error information, other interfaces may 14 | /// offer functions to "downcast" this error into more specific types. For example, 15 | /// errors returned from streams derived from filesystem types can be described using 16 | /// the filesystem's own error-code type. This is done using the function 17 | /// `wasi:filesystem/types/filesystem-error-code`, which takes a `borrow` 18 | /// parameter and returns an `option`. 19 | /// 20 | /// The set of functions which can "downcast" an `error` into a more 21 | /// concrete type is open. 22 | @since(version = 0.2.0) 23 | resource error { 24 | /// Returns a string that is suitable to assist humans in debugging 25 | /// this error. 26 | /// 27 | /// WARNING: The returned string should not be consumed mechanically! 28 | /// It may change across platforms, hosts, or other implementation 29 | /// details. Parsing this string is a major platform-compatibility 30 | /// hazard. 31 | @since(version = 0.2.0) 32 | to-debug-string: func() -> string; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/sockets/tcp-create-socket/tcp-create-socket.wit.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | // Package tcpcreatesocket represents the imported interface "wasi:sockets/tcp-create-socket@0.2.0". 4 | package tcpcreatesocket 5 | 6 | import ( 7 | "go.bytecodealliance.org/cm" 8 | "gomodule-server-go/gen/wasi/sockets/network" 9 | "gomodule-server-go/gen/wasi/sockets/tcp" 10 | ) 11 | 12 | // Network represents the imported type alias "wasi:sockets/tcp-create-socket@0.2.0#network". 13 | // 14 | // See [network.Network] for more information. 15 | type Network = network.Network 16 | 17 | // ErrorCode represents the type alias "wasi:sockets/tcp-create-socket@0.2.0#error-code". 18 | // 19 | // See [network.ErrorCode] for more information. 20 | type ErrorCode = network.ErrorCode 21 | 22 | // IPAddressFamily represents the type alias "wasi:sockets/tcp-create-socket@0.2.0#ip-address-family". 23 | // 24 | // See [network.IPAddressFamily] for more information. 25 | type IPAddressFamily = network.IPAddressFamily 26 | 27 | // TCPSocket represents the imported type alias "wasi:sockets/tcp-create-socket@0.2.0#tcp-socket". 28 | // 29 | // See [tcp.TCPSocket] for more information. 30 | type TCPSocket = tcp.TCPSocket 31 | 32 | // CreateTCPSocket represents the imported function "create-tcp-socket". 33 | // 34 | // create-tcp-socket: func(address-family: ip-address-family) -> result 36 | // 37 | //go:nosplit 38 | func CreateTCPSocket(addressFamily IPAddressFamily) (result cm.Result[TCPSocket, TCPSocket, ErrorCode]) { 39 | addressFamily0 := (uint32)(addressFamily) 40 | wasmimport_CreateTCPSocket((uint32)(addressFamily0), &result) 41 | return 42 | } 43 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/sockets/udp-create-socket/udp-create-socket.wit.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | // Package udpcreatesocket represents the imported interface "wasi:sockets/udp-create-socket@0.2.0". 4 | package udpcreatesocket 5 | 6 | import ( 7 | "go.bytecodealliance.org/cm" 8 | "gomodule-server-go/gen/wasi/sockets/network" 9 | "gomodule-server-go/gen/wasi/sockets/udp" 10 | ) 11 | 12 | // Network represents the imported type alias "wasi:sockets/udp-create-socket@0.2.0#network". 13 | // 14 | // See [network.Network] for more information. 15 | type Network = network.Network 16 | 17 | // ErrorCode represents the type alias "wasi:sockets/udp-create-socket@0.2.0#error-code". 18 | // 19 | // See [network.ErrorCode] for more information. 20 | type ErrorCode = network.ErrorCode 21 | 22 | // IPAddressFamily represents the type alias "wasi:sockets/udp-create-socket@0.2.0#ip-address-family". 23 | // 24 | // See [network.IPAddressFamily] for more information. 25 | type IPAddressFamily = network.IPAddressFamily 26 | 27 | // UDPSocket represents the imported type alias "wasi:sockets/udp-create-socket@0.2.0#udp-socket". 28 | // 29 | // See [udp.UDPSocket] for more information. 30 | type UDPSocket = udp.UDPSocket 31 | 32 | // CreateUDPSocket represents the imported function "create-udp-socket". 33 | // 34 | // create-udp-socket: func(address-family: ip-address-family) -> result 36 | // 37 | //go:nosplit 38 | func CreateUDPSocket(addressFamily IPAddressFamily) (result cm.Result[UDPSocket, UDPSocket, ErrorCode]) { 39 | addressFamily0 := (uint32)(addressFamily) 40 | wasmimport_CreateUDPSocket((uint32)(addressFamily0), &result) 41 | return 42 | } 43 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/random/insecure/insecure.wit.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | // Package insecure represents the imported interface "wasi:random/insecure@0.2.0". 4 | // 5 | // The insecure interface for insecure pseudo-random numbers. 6 | // 7 | // It is intended to be portable at least between Unix-family platforms and 8 | // Windows. 9 | package insecure 10 | 11 | import ( 12 | "go.bytecodealliance.org/cm" 13 | ) 14 | 15 | // GetInsecureRandomBytes represents the imported function "get-insecure-random-bytes". 16 | // 17 | // Return `len` insecure pseudo-random bytes. 18 | // 19 | // This function is not cryptographically secure. Do not use it for 20 | // anything related to security. 21 | // 22 | // There are no requirements on the values of the returned bytes, however 23 | // implementations are encouraged to return evenly distributed values with 24 | // a long period. 25 | // 26 | // get-insecure-random-bytes: func(len: u64) -> list 27 | // 28 | //go:nosplit 29 | func GetInsecureRandomBytes(len_ uint64) (result cm.List[uint8]) { 30 | len0 := (uint64)(len_) 31 | wasmimport_GetInsecureRandomBytes((uint64)(len0), &result) 32 | return 33 | } 34 | 35 | // GetInsecureRandomU64 represents the imported function "get-insecure-random-u64". 36 | // 37 | // Return an insecure pseudo-random `u64` value. 38 | // 39 | // This function returns the same type of pseudo-random data as 40 | // `get-insecure-random-bytes`, represented as a `u64`. 41 | // 42 | // get-insecure-random-u64: func() -> u64 43 | // 44 | //go:nosplit 45 | func GetInsecureRandomU64() (result uint64) { 46 | result0 := wasmimport_GetInsecureRandomU64() 47 | result = (uint64)((uint64)(result0)) 48 | return 49 | } 50 | -------------------------------------------------------------------------------- /examples/context7-rs/wit/deps/sockets/udp-create-socket.wit: -------------------------------------------------------------------------------- 1 | @since(version = 0.2.0) 2 | interface udp-create-socket { 3 | @since(version = 0.2.0) 4 | use network.{network, error-code, ip-address-family}; 5 | @since(version = 0.2.0) 6 | use udp.{udp-socket}; 7 | 8 | /// Create a new UDP socket. 9 | /// 10 | /// Similar to `socket(AF_INET or AF_INET6, SOCK_DGRAM, IPPROTO_UDP)` in POSIX. 11 | /// On IPv6 sockets, IPV6_V6ONLY is enabled by default and can't be configured otherwise. 12 | /// 13 | /// This function does not require a network capability handle. This is considered to be safe because 14 | /// at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind` is called, 15 | /// the socket is effectively an in-memory configuration object, unable to communicate with the outside world. 16 | /// 17 | /// All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous operations. 18 | /// 19 | /// # Typical errors 20 | /// - `not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT) 21 | /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) 22 | /// 23 | /// # References: 24 | /// - 25 | /// - 26 | /// - 27 | /// - 28 | @since(version = 0.2.0) 29 | create-udp-socket: func(address-family: ip-address-family) -> result; 30 | } 31 | -------------------------------------------------------------------------------- /deny.toml: -------------------------------------------------------------------------------- 1 | # Cargo-deny configuration for wassette 2 | # Documentation: https://embarkstudios.github.io/cargo-deny/ 3 | 4 | # Advisory database configuration 5 | [advisories] 6 | # Ignore list for known issues that are acceptable 7 | ignore = [ 8 | # paste crate is unmaintained but still widely used and safe 9 | { id = "RUSTSEC-2024-0436", reason = "paste crate is unmaintained but still widely used and safe" }, 10 | # fxhash crate is unmaintained but pulled in transitively by wasmtime via fxprof-processed-profile 11 | # The crate is still safe and functional, and we cannot control this transitive dependency 12 | # TODO: This can be removed after upgrading to wasmtime > 36.0.2 (fixed in https://github.com/bytecodealliance/wasmtime/issues/11633) 13 | { id = "RUSTSEC-2025-0057", reason = "fxhash is transitively required by wasmtime and still safe despite being unmaintained" }, 14 | ] 15 | 16 | # License checking configuration 17 | [licenses] 18 | # Explicitly allowed licenses - OSI approved and commonly used licenses 19 | allow = [ 20 | "MIT", 21 | "Apache-2.0", 22 | "Apache-2.0 WITH LLVM-exception", 23 | "BSD-2-Clause", 24 | "BSD-3-Clause", 25 | "ISC", 26 | "Zlib", 27 | "Unicode-3.0", 28 | "CDLA-Permissive-2.0", 29 | ] 30 | confidence-threshold = 0.8 31 | 32 | # Dependency bans configuration 33 | [bans] 34 | # Allow multiple versions with warnings (common in large dependency graphs) 35 | multiple-versions = "warn" 36 | # Allow wildcard version requirements 37 | wildcards = "allow" 38 | 39 | # Source checking configuration 40 | [sources] 41 | # Only allow crates from crates.io 42 | allow-registry = ["https://github.com/rust-lang/crates.io-index"] 43 | unknown-registry = "deny" 44 | unknown-git = "deny" -------------------------------------------------------------------------------- /examples/context7-rs/wit/deps/sockets/tcp-create-socket.wit: -------------------------------------------------------------------------------- 1 | @since(version = 0.2.0) 2 | interface tcp-create-socket { 3 | @since(version = 0.2.0) 4 | use network.{network, error-code, ip-address-family}; 5 | @since(version = 0.2.0) 6 | use tcp.{tcp-socket}; 7 | 8 | /// Create a new TCP socket. 9 | /// 10 | /// Similar to `socket(AF_INET or AF_INET6, SOCK_STREAM, IPPROTO_TCP)` in POSIX. 11 | /// On IPv6 sockets, IPV6_V6ONLY is enabled by default and can't be configured otherwise. 12 | /// 13 | /// This function does not require a network capability handle. This is considered to be safe because 14 | /// at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind`/`connect` 15 | /// is called, the socket is effectively an in-memory configuration object, unable to communicate with the outside world. 16 | /// 17 | /// All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous operations. 18 | /// 19 | /// # Typical errors 20 | /// - `not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT) 21 | /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) 22 | /// 23 | /// # References 24 | /// - 25 | /// - 26 | /// - 27 | /// - 28 | @since(version = 0.2.0) 29 | create-tcp-socket: func(address-family: ip-address-family) -> result; 30 | } 31 | -------------------------------------------------------------------------------- /docs/design/architecture.md: -------------------------------------------------------------------------------- 1 | ```mermaid 2 | sequenceDiagram 3 | participant Client as MCP Client 4 | participant Server as Wassette MCP Server 5 | participant LM as LifecycleManager 6 | participant Engine as Wasmtime Engine 7 | participant Registry as Component Registry 8 | participant Policy as Policy Engine 9 | 10 | Client->>Server: load-component(path) 11 | Server->>LM: load_component(uri) 12 | 13 | alt OCI Registry 14 | LM->>LM: Download from OCI 15 | else Local File 16 | LM->>LM: Load from filesystem 17 | else HTTP URL 18 | LM->>LM: Download from URL 19 | end 20 | 21 | LM->>Engine: Create Component 22 | Engine->>Engine: Compile WebAssembly 23 | Engine->>Engine: Extract WIT Interface 24 | 25 | LM->>Registry: Register Component 26 | Registry->>Registry: Generate JSON Schema 27 | Registry->>Registry: Map Tools to Component 28 | 29 | LM->>Policy: Apply Default Policy 30 | Policy->>Policy: Create WASI State Template 31 | 32 | LM-->>Server: Component ID + LoadResult 33 | Server-->>Client: Success with ID 34 | 35 | Note over Client,Policy: Component is now loaded and ready 36 | 37 | Client->>Server: call_tool(tool_name, args) 38 | Server->>LM: execute_component_call(id, func, params) 39 | 40 | LM->>Policy: Get WASI State for Component 41 | Policy->>Policy: Apply Security Policy 42 | Policy->>Engine: Create Store with WASI Context 43 | 44 | LM->>Engine: Instantiate Component 45 | Engine->>Engine: Call Function with Args 46 | Engine->>Engine: Execute in Sandbox 47 | 48 | Engine-->>LM: Results 49 | LM-->>Server: JSON Response 50 | Server-->>Client: Tool Result 51 | ``` -------------------------------------------------------------------------------- /examples/fetch-rs/fetch_rs.metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "component_id": "fetch_rs", 3 | "tool_schemas": [ 4 | { 5 | "description": "Auto-generated schema for function 'fetch'", 6 | "inputSchema": { 7 | "properties": { 8 | "url": { 9 | "type": "string" 10 | } 11 | }, 12 | "required": [ 13 | "url" 14 | ], 15 | "type": "object" 16 | }, 17 | "name": "fetch", 18 | "outputSchema": { 19 | "properties": { 20 | "result": { 21 | "oneOf": [ 22 | { 23 | "properties": { 24 | "ok": { 25 | "type": "string" 26 | } 27 | }, 28 | "required": [ 29 | "ok" 30 | ], 31 | "type": "object" 32 | }, 33 | { 34 | "properties": { 35 | "err": { 36 | "type": "string" 37 | } 38 | }, 39 | "required": [ 40 | "err" 41 | ], 42 | "type": "object" 43 | } 44 | ] 45 | } 46 | }, 47 | "required": [ 48 | "result" 49 | ], 50 | "type": "object" 51 | } 52 | } 53 | ], 54 | "function_identifiers": [ 55 | { 56 | "package_name": null, 57 | "interface_name": null, 58 | "function_name": "fetch" 59 | } 60 | ], 61 | "tool_names": [ 62 | "fetch" 63 | ], 64 | "validation_stamp": { 65 | "file_size": 18123689, 66 | "mtime": 1762878688, 67 | "content_hash": null 68 | }, 69 | "created_at": 1762879837 70 | } -------------------------------------------------------------------------------- /component-registry.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Weather Server", 4 | "description": "A weather component written in JavaScript", 5 | "uri": "oci://ghcr.io/microsoft/get-weather-js:latest" 6 | }, 7 | { 8 | "name": "Open-Meteo Weather", 9 | "description": "A weather component using Open-Meteo API written in JavaScript", 10 | "uri": "oci://ghcr.io/microsoft/get-open-meteo-weather-js:latest" 11 | }, 12 | { 13 | "name": "Time Server", 14 | "description": "A time server component written in JavaScript", 15 | "uri": "oci://ghcr.io/microsoft/time-server-js:latest" 16 | }, 17 | { 18 | "name": "Python Eval", 19 | "description": "A Python expression evaluation component", 20 | "uri": "oci://ghcr.io/microsoft/eval-py:latest" 21 | }, 22 | { 23 | "name": "Fetch", 24 | "description": "A fetch component written in Rust", 25 | "uri": "oci://ghcr.io/microsoft/fetch-rs:latest" 26 | }, 27 | { 28 | "name": "Filesystem", 29 | "description": "A filesystem component written in Rust", 30 | "uri": "oci://ghcr.io/microsoft/filesystem-rs:latest" 31 | }, 32 | { 33 | "name": "Brave Search", 34 | "description": "A web search component using Brave Search API written in Rust", 35 | "uri": "oci://ghcr.io/microsoft/brave-search-rs:latest" 36 | }, 37 | { 38 | "name": "Context7", 39 | "description": "A library documentation search component using Context7 API written in Rust", 40 | "uri": "oci://ghcr.io/microsoft/context7-rs:latest" 41 | }, 42 | { 43 | "name": "Go Module Information", 44 | "description": "A Go module component", 45 | "uri": "oci://ghcr.io/microsoft/gomodule-go:latest" 46 | } 47 | ] 48 | -------------------------------------------------------------------------------- /examples/memory-js/test_component.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Test script to verify all exported functions of memory-js component 3 | 4 | set -e 5 | 6 | echo "=== Memory-JS Component Function Verification ===" 7 | echo "" 8 | 9 | # Build the component 10 | echo "Building component..." 11 | cd "$(dirname "$0")" 12 | npm install > /dev/null 2>&1 13 | npm run build > /dev/null 2>&1 14 | echo "✓ Component built successfully" 15 | echo "" 16 | 17 | # Verify component structure using component2json 18 | echo "Analyzing component with component2json..." 19 | cd ../.. 20 | cargo build -p component2json > /dev/null 2>&1 21 | 22 | echo "" 23 | echo "=== Exported Functions ===" 24 | cargo run -p component2json --quiet -- examples/memory-js/memory.wasm 2>&1 | \ 25 | grep "local_memory_knowledge-graph-ops" | \ 26 | sed 's/, Some.*//' | \ 27 | sed 's/local_memory_knowledge-graph-ops_//' | \ 28 | nl -w2 -s'. ' 29 | 30 | echo "" 31 | echo "=== Verification Complete ===" 32 | echo "✓ All 9 functions are properly exported:" 33 | echo " 1. create-entities - Creates new entities in the graph" 34 | echo " 2. create-relations - Creates relations between entities" 35 | echo " 3. add-observations - Adds observations to entities" 36 | echo " 4. delete-entities - Deletes entities from the graph" 37 | echo " 5. delete-observations - Deletes specific observations" 38 | echo " 6. delete-relations - Deletes relations from the graph" 39 | echo " 7. read-graph - Reads the entire knowledge graph" 40 | echo " 8. search-nodes - Searches nodes by text query" 41 | echo " 9. open-nodes - Opens specific nodes by name" 42 | echo "" 43 | echo "✓ All functions have valid input/output schemas" 44 | echo "✓ All functions use proper result error handling" 45 | echo "✓ Component is ready for use with Wassette" 46 | -------------------------------------------------------------------------------- /examples/context7-rs/wit/deps/clocks/monotonic-clock.wit: -------------------------------------------------------------------------------- 1 | package wasi:clocks@0.2.1; 2 | /// WASI Monotonic Clock is a clock API intended to let users measure elapsed 3 | /// time. 4 | /// 5 | /// It is intended to be portable at least between Unix-family platforms and 6 | /// Windows. 7 | /// 8 | /// A monotonic clock is a clock which has an unspecified initial value, and 9 | /// successive reads of the clock will produce non-decreasing values. 10 | @since(version = 0.2.0) 11 | interface monotonic-clock { 12 | @since(version = 0.2.0) 13 | use wasi:io/poll@0.2.1.{pollable}; 14 | 15 | /// An instant in time, in nanoseconds. An instant is relative to an 16 | /// unspecified initial value, and can only be compared to instances from 17 | /// the same monotonic-clock. 18 | @since(version = 0.2.0) 19 | type instant = u64; 20 | 21 | /// A duration of time, in nanoseconds. 22 | @since(version = 0.2.0) 23 | type duration = u64; 24 | 25 | /// Read the current value of the clock. 26 | /// 27 | /// The clock is monotonic, therefore calling this function repeatedly will 28 | /// produce a sequence of non-decreasing values. 29 | @since(version = 0.2.0) 30 | now: func() -> instant; 31 | 32 | /// Query the resolution of the clock. Returns the duration of time 33 | /// corresponding to a clock tick. 34 | @since(version = 0.2.0) 35 | resolution: func() -> duration; 36 | 37 | /// Create a `pollable` which will resolve once the specified instant 38 | /// has occurred. 39 | @since(version = 0.2.0) 40 | subscribe-instant: func( 41 | when: instant, 42 | ) -> pollable; 43 | 44 | /// Create a `pollable` that will resolve after the specified duration has 45 | /// elapsed from the time this function is invoked. 46 | @since(version = 0.2.0) 47 | subscribe-duration: func( 48 | when: duration, 49 | ) -> pollable; 50 | } 51 | -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/random/random/random.wit.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | // Package random represents the imported interface "wasi:random/random@0.2.0". 4 | // 5 | // WASI Random is a random data API. 6 | // 7 | // It is intended to be portable at least between Unix-family platforms and 8 | // Windows. 9 | package random 10 | 11 | import ( 12 | "go.bytecodealliance.org/cm" 13 | ) 14 | 15 | // GetRandomBytes represents the imported function "get-random-bytes". 16 | // 17 | // Return `len` cryptographically-secure random or pseudo-random bytes. 18 | // 19 | // This function must produce data at least as cryptographically secure and 20 | // fast as an adequately seeded cryptographically-secure pseudo-random 21 | // number generator (CSPRNG). It must not block, from the perspective of 22 | // the calling program, under any circumstances, including on the first 23 | // request and on requests for numbers of bytes. The returned data must 24 | // always be unpredictable. 25 | // 26 | // This function must always return fresh data. Deterministic environments 27 | // must omit this function, rather than implementing it with deterministic 28 | // data. 29 | // 30 | // get-random-bytes: func(len: u64) -> list 31 | // 32 | //go:nosplit 33 | func GetRandomBytes(len_ uint64) (result cm.List[uint8]) { 34 | len0 := (uint64)(len_) 35 | wasmimport_GetRandomBytes((uint64)(len0), &result) 36 | return 37 | } 38 | 39 | // GetRandomU64 represents the imported function "get-random-u64". 40 | // 41 | // Return a cryptographically-secure random or pseudo-random `u64` value. 42 | // 43 | // This function returns the same type of data as `get-random-bytes`, 44 | // represented as a `u64`. 45 | // 46 | // get-random-u64: func() -> u64 47 | // 48 | //go:nosplit 49 | func GetRandomU64() (result uint64) { 50 | result0 := wasmimport_GetRandomU64() 51 | result = (uint64)((uint64)(result0)) 52 | return 53 | } 54 | -------------------------------------------------------------------------------- /.github/workflows/dependabot-automerge.yml: -------------------------------------------------------------------------------- 1 | name: Dependabot Automerge 2 | 3 | on: 4 | pull_request: 5 | types: [opened, synchronize] 6 | 7 | permissions: 8 | contents: write 9 | pull-requests: write 10 | 11 | jobs: 12 | dependabot: 13 | runs-on: ubuntu-latest 14 | # Only run for dependabot PRs 15 | if: github.actor == 'dependabot[bot]' 16 | steps: 17 | - name: Dependabot metadata 18 | id: metadata 19 | uses: dependabot/fetch-metadata@08eff52bf64351f401fb50d4972fa95b9f2c2d1b # v2.2.0 20 | with: 21 | github-token: "${{ secrets.GITHUB_TOKEN }}" 22 | 23 | - name: Enable auto-merge for patch and minor updates 24 | # Auto-merge patch and minor updates, but require manual review for major updates 25 | if: ${{ steps.metadata.outputs.update-type != 'version-update:semver-major' }} 26 | continue-on-error: true 27 | run: | 28 | echo "Enabling auto-merge for ${{ steps.metadata.outputs.update-type }} update" 29 | gh pr merge --auto --squash "$PR_URL" 30 | env: 31 | PR_URL: ${{ github.event.pull_request.html_url }} 32 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 33 | 34 | - name: Comment on major updates 35 | if: ${{ steps.metadata.outputs.update-type == 'version-update:semver-major' }} 36 | uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v7.1.0 37 | with: 38 | script: | 39 | github.rest.issues.createComment({ 40 | issue_number: context.issue.number, 41 | owner: context.repo.owner, 42 | repo: context.repo.repo, 43 | body: '🚨 **Major version update detected!** This PR requires manual review before merging due to potential breaking changes.\n\n**Dependency:** `${{ steps.metadata.outputs.dependency-name }}`\n**Update Type:** `${{ steps.metadata.outputs.update-type }}`' 44 | }) -------------------------------------------------------------------------------- /.github/workflows/validate-registry.yml: -------------------------------------------------------------------------------- 1 | name: Validate Component Registry 2 | 3 | on: 4 | pull_request: 5 | branches: [ "main" ] 6 | paths: 7 | - 'component-registry.json' 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | validate: 14 | runs-on: ubuntu-latest 15 | permissions: 16 | contents: read 17 | 18 | steps: 19 | - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 20 | with: 21 | fetch-depth: 0 # Fetch all history to compare with main branch 22 | 23 | - name: Setup Node.js 24 | uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 25 | with: 26 | node-version: '20' 27 | 28 | - name: Install build dependencies 29 | run: ./scripts/install-protobuf.sh 30 | shell: bash 31 | 32 | - name: Setup Rust toolchain 33 | uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1.15.2 34 | 35 | - uses: ./.github/actions/rust-cache 36 | 37 | - name: Setup Just 38 | uses: extractions/setup-just@e33e0265a09d6d736e2ee1e0eb685ef1de4669ff # v3.0.0 39 | 40 | - name: Build wassette 41 | run: just build release 42 | 43 | - name: Validate component registry 44 | run: ./scripts/validate-component-registry.sh 45 | 46 | - name: Summary 47 | if: always() 48 | run: | 49 | if [ $? -eq 0 ]; then 50 | echo "## ✓ Component Registry Validation Passed" >> $GITHUB_STEP_SUMMARY 51 | echo "" >> $GITHUB_STEP_SUMMARY 52 | echo "All new and modified component URIs were successfully validated." >> $GITHUB_STEP_SUMMARY 53 | else 54 | echo "## ✗ Component Registry Validation Failed" >> $GITHUB_STEP_SUMMARY 55 | echo "" >> $GITHUB_STEP_SUMMARY 56 | echo "One or more component URIs failed validation. Please check the logs above for details." >> $GITHUB_STEP_SUMMARY 57 | fi 58 | -------------------------------------------------------------------------------- /examples/context7-rs/wit/deps/io/poll.wit: -------------------------------------------------------------------------------- 1 | package wasi:io@0.2.1; 2 | 3 | /// A poll API intended to let users wait for I/O events on multiple handles 4 | /// at once. 5 | @since(version = 0.2.0) 6 | interface poll { 7 | /// `pollable` represents a single I/O event which may be ready, or not. 8 | @since(version = 0.2.0) 9 | resource pollable { 10 | 11 | /// Return the readiness of a pollable. This function never blocks. 12 | /// 13 | /// Returns `true` when the pollable is ready, and `false` otherwise. 14 | @since(version = 0.2.0) 15 | ready: func() -> bool; 16 | 17 | /// `block` returns immediately if the pollable is ready, and otherwise 18 | /// blocks until ready. 19 | /// 20 | /// This function is equivalent to calling `poll.poll` on a list 21 | /// containing only this pollable. 22 | @since(version = 0.2.0) 23 | block: func(); 24 | } 25 | 26 | /// Poll for completion on a set of pollables. 27 | /// 28 | /// This function takes a list of pollables, which identify I/O sources of 29 | /// interest, and waits until one or more of the events is ready for I/O. 30 | /// 31 | /// The result `list` contains one or more indices of handles in the 32 | /// argument list that is ready for I/O. 33 | /// 34 | /// This function traps if either: 35 | /// - the list is empty, or: 36 | /// - the list contains more elements than can be indexed with a `u32` value. 37 | /// 38 | /// A timeout can be implemented by adding a pollable from the 39 | /// wasi-clocks API to the list. 40 | /// 41 | /// This function does not return a `result`; polling in itself does not 42 | /// do any I/O so it doesn't fail. If any of the I/O sources identified by 43 | /// the pollables has an error, it is indicated by marking the source as 44 | /// being ready for I/O. 45 | @since(version = 0.2.0) 46 | poll: func(in: list>) -> list; 47 | } 48 | -------------------------------------------------------------------------------- /examples/context7-rs/wit/deps/clocks/wall-clock.wit: -------------------------------------------------------------------------------- 1 | package wasi:clocks@0.2.1; 2 | /// WASI Wall Clock is a clock API intended to let users query the current 3 | /// time. The name "wall" makes an analogy to a "clock on the wall", which 4 | /// is not necessarily monotonic as it may be reset. 5 | /// 6 | /// It is intended to be portable at least between Unix-family platforms and 7 | /// Windows. 8 | /// 9 | /// A wall clock is a clock which measures the date and time according to 10 | /// some external reference. 11 | /// 12 | /// External references may be reset, so this clock is not necessarily 13 | /// monotonic, making it unsuitable for measuring elapsed time. 14 | /// 15 | /// It is intended for reporting the current date and time for humans. 16 | @since(version = 0.2.0) 17 | interface wall-clock { 18 | /// A time and date in seconds plus nanoseconds. 19 | @since(version = 0.2.0) 20 | record datetime { 21 | seconds: u64, 22 | nanoseconds: u32, 23 | } 24 | 25 | /// Read the current value of the clock. 26 | /// 27 | /// This clock is not monotonic, therefore calling this function repeatedly 28 | /// will not necessarily produce a sequence of non-decreasing values. 29 | /// 30 | /// The returned timestamps represent the number of seconds since 31 | /// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch], 32 | /// also known as [Unix Time]. 33 | /// 34 | /// The nanoseconds field of the output is always less than 1000000000. 35 | /// 36 | /// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16 37 | /// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time 38 | @since(version = 0.2.0) 39 | now: func() -> datetime; 40 | 41 | /// Query the resolution of the clock. 42 | /// 43 | /// The nanoseconds field of the output is always less than 1000000000. 44 | @since(version = 0.2.0) 45 | resolution: func() -> datetime; 46 | } 47 | -------------------------------------------------------------------------------- /changelog.d/README.md: -------------------------------------------------------------------------------- 1 | # Changelog Fragments 2 | 3 | This directory contains changelog fragments for pending changes that will be included in the next release. We use the [towncrier](https://towncrier.readthedocs.io/) format for managing changelog fragments. 4 | 5 | ## Format 6 | 7 | Each fragment file follows the towncrier naming convention: `.` 8 | 9 | The file can have any extension (`.md`, `.rst`, `.txt`) or no extension. We use `.md` for consistency. 10 | 11 | Where `` is one of: 12 | - `feature` - New features 13 | - `bugfix` - Bug fixes 14 | - `doc` - Documentation improvements 15 | - `removal` - Deprecations or removal of public API 16 | - `misc` - Miscellaneous changes not of interest to users 17 | 18 | ## Example 19 | 20 | For PR #1234 that adds a new feature: 21 | 22 | **File**: `1234.feature.md` 23 | 24 | **Content**: 25 | ```markdown 26 | Added support for new component loading feature. 27 | ``` 28 | 29 | ## Automated Generation 30 | 31 | Changelog fragments are automatically created by the agentic workflow when PRs are opened or reopened. The workflow analyzes the PR title and description to determine the appropriate change type and creates the fragment file. 32 | 33 | ## Manual Creation 34 | 35 | You can also manually create fragment files if needed. Just follow the naming convention and write a concise description of the change. 36 | 37 | ## Processing 38 | 39 | During release preparation, use towncrier to build the changelog: 40 | 41 | ```bash 42 | towncrier build --version X.Y.Z 43 | ``` 44 | 45 | This will consolidate all fragment files into the CHANGELOG.md file and remove the fragments from this directory. 46 | 47 | ## Example Files 48 | 49 | This directory contains example fragment files (starting with `.example`) that demonstrate the format: 50 | - `.example.feature.md` - Example of a feature addition 51 | - `.example.bugfix.md` - Example of a bug fix 52 | 53 | These example files should be ignored by towncrier (they start with `.` so they won't be picked up). 54 | -------------------------------------------------------------------------------- /examples/fetch-rs/README.md: -------------------------------------------------------------------------------- 1 | # Fetch Example (Rust) 2 | 3 | This example demonstrates how to fetch content from a URL using a Wassette component written in Rust. 4 | 5 | For more information on installing Wassette, please see the [installation instructions](https://github.com/microsoft/wassette?tab=readme-ov-file#installation). 6 | 7 | ## Building 8 | 9 | This example uses the standard Rust build process with an additional documentation injection step: 10 | 11 | ```bash 12 | # Build the component 13 | cargo build --target wasm32-wasip2 --release 14 | 15 | # From repository root: inject WIT documentation into the component 16 | just inject-docs examples/fetch-rs/target/wasm32-wasip2/release/fetch_rs.wasm examples/fetch-rs/wit 17 | ``` 18 | 19 | The documentation injection embeds the WIT interface documentation into the WASM binary, making it available to AI agents when they discover this tool. See [`wit/world.wit`](wit/world.wit) for the documented interface. 20 | 21 | For more information about documenting components, see the [Documenting WIT Interfaces](../../docs/cookbook/documenting-wit.md) guide. 22 | 23 | ## Usage 24 | 25 | To use this component, load it from the OCI registry and provide a URL to fetch. 26 | 27 | **Load the component:** 28 | 29 | ``` 30 | Please load the component from oci://ghcr.io/microsoft/fetch-rs:latest 31 | ``` 32 | 33 | **Fetch content:** 34 | 35 | ``` 36 | Please fetch the content of https://example.com 37 | ``` 38 | 39 | ## Policy 40 | 41 | By default, WebAssembly (Wasm) components do not have any access to the host machine or network. The `policy.yaml` file is used to explicitly define what network resources are made available to the component. This ensures that the component can only access the resources that are explicitly allowed. 42 | 43 | Example: 44 | 45 | ```yaml 46 | version: "1.0" 47 | description: "Permission policy for fetch-rs example in wassette" 48 | permissions: 49 | network: 50 | allow: 51 | - host: "https://rss.nytimes.com/" 52 | ``` 53 | 54 | The source code for this example can be found in [`src/lib.rs`](src/lib.rs). 55 | -------------------------------------------------------------------------------- /examples/eval-py/uv.lock: -------------------------------------------------------------------------------- 1 | version = 1 2 | requires-python = ">=3.10" 3 | 4 | [[package]] 5 | name = "componentize-py" 6 | version = "0.17.1" 7 | source = { registry = "https://pypi.org/simple" } 8 | sdist = { url = "https://files.pythonhosted.org/packages/24/6d/c00b2b09ff22d0cc5587f0a8d146a3682c0ee9adb8f8bbbcc7479965a571/componentize_py-0.17.1.tar.gz", hash = "sha256:a3dec642771405cbfd652a182811bfb5dbfd0b0a383d3fa03347800e25b99d22", size = 161925 } 9 | wheels = [ 10 | { url = "https://files.pythonhosted.org/packages/24/07/291f03cb1185d148985213b50194160ffb0c2cae80def62bd4807557647e/componentize_py-0.17.1-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:31611ce4fff2500d30fda011fbd2919fbf9adbb8db5041ed70f7138f21cf0479", size = 19404639 }, 11 | { url = "https://files.pythonhosted.org/packages/56/af/fad0ef80ab3992ab733931a5b22f007a71447d031c876e0c7b3d106020c5/componentize_py-0.17.1-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:f70807f0b6a270d7f6489ae5f6c92ae57251aaee4046c8b07b354fbfc826e02c", size = 18947122 }, 12 | { url = "https://files.pythonhosted.org/packages/07/2b/612f7e57231f1269da434f222379782b9ea47de47c86ffa72021353c178f/componentize_py-0.17.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:d453218e6931e2d7ccac4031342a8e0ec2fd49787c3be222a4d492675659a378", size = 19713907 }, 13 | { url = "https://files.pythonhosted.org/packages/36/2d/b6b8ce3ab84517bb9eafec7e6cd08fb167b68aec4551ece2686c9b0d559c/componentize_py-0.17.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:c3321c21682040806274957caf992033fd33049e9c6de0ef3e4ac27b6d10d828", size = 20288778 }, 14 | { url = "https://files.pythonhosted.org/packages/62/d2/07e670e8a228834e0f2701a90f4e94942af2284cff84fc3b736887b3a227/componentize_py-0.17.1-cp39-abi3-win_amd64.whl", hash = "sha256:ab9ae2d8ab246604609ba031dd0f97666e1a4af932bc5e1f3349223bf8270a1a", size = 18263892 }, 15 | ] 16 | 17 | [[package]] 18 | name = "eval-py" 19 | version = "0.1.0" 20 | source = { virtual = "." } 21 | dependencies = [ 22 | { name = "componentize-py" }, 23 | ] 24 | 25 | [package.metadata] 26 | requires-dist = [{ name = "componentize-py", specifier = ">=0.17.1" }] 27 | -------------------------------------------------------------------------------- /examples/context7-rs/wit/deps/http/proxy.wit: -------------------------------------------------------------------------------- 1 | package wasi:http@0.2.1; 2 | 3 | /// The `wasi:http/imports` world imports all the APIs for HTTP proxies. 4 | /// It is intended to be `include`d in other worlds. 5 | @since(version = 0.2.0) 6 | world imports { 7 | /// HTTP proxies have access to time and randomness. 8 | @since(version = 0.2.0) 9 | import wasi:clocks/monotonic-clock@0.2.1; 10 | @since(version = 0.2.0) 11 | import wasi:clocks/wall-clock@0.2.1; 12 | @since(version = 0.2.0) 13 | import wasi:random/random@0.2.1; 14 | 15 | /// Proxies have standard output and error streams which are expected to 16 | /// terminate in a developer-facing console provided by the host. 17 | @since(version = 0.2.0) 18 | import wasi:cli/stdout@0.2.1; 19 | @since(version = 0.2.0) 20 | import wasi:cli/stderr@0.2.1; 21 | 22 | /// TODO: this is a temporary workaround until component tooling is able to 23 | /// gracefully handle the absence of stdin. Hosts must return an eof stream 24 | /// for this import, which is what wasi-libc + tooling will do automatically 25 | /// when this import is properly removed. 26 | @since(version = 0.2.0) 27 | import wasi:cli/stdin@0.2.1; 28 | 29 | /// This is the default handler to use when user code simply wants to make an 30 | /// HTTP request (e.g., via `fetch()`). 31 | @since(version = 0.2.0) 32 | import outgoing-handler; 33 | } 34 | 35 | /// The `wasi:http/proxy` world captures a widely-implementable intersection of 36 | /// hosts that includes HTTP forward and reverse proxies. Components targeting 37 | /// this world may concurrently stream in and out any number of incoming and 38 | /// outgoing HTTP requests. 39 | @since(version = 0.2.0) 40 | world proxy { 41 | @since(version = 0.2.0) 42 | include imports; 43 | 44 | /// The host delivers incoming HTTP requests to a component by calling the 45 | /// `handle` function of this exported interface. A host may arbitrarily reuse 46 | /// or not reuse component instance when delivering incoming HTTP requests and 47 | /// thus a component must be able to handle 0..N calls to `handle`. 48 | @since(version = 0.2.0) 49 | export incoming-handler; 50 | } 51 | -------------------------------------------------------------------------------- /examples/context7-rs/wit/deps/http/handler.wit: -------------------------------------------------------------------------------- 1 | /// This interface defines a handler of incoming HTTP Requests. It should 2 | /// be exported by components which can respond to HTTP Requests. 3 | @since(version = 0.2.0) 4 | interface incoming-handler { 5 | @since(version = 0.2.0) 6 | use types.{incoming-request, response-outparam}; 7 | 8 | /// This function is invoked with an incoming HTTP Request, and a resource 9 | /// `response-outparam` which provides the capability to reply with an HTTP 10 | /// Response. The response is sent by calling the `response-outparam.set` 11 | /// method, which allows execution to continue after the response has been 12 | /// sent. This enables both streaming to the response body, and performing other 13 | /// work. 14 | /// 15 | /// The implementor of this function must write a response to the 16 | /// `response-outparam` before returning, or else the caller will respond 17 | /// with an error on its behalf. 18 | @since(version = 0.2.0) 19 | handle: func( 20 | request: incoming-request, 21 | response-out: response-outparam 22 | ); 23 | } 24 | 25 | /// This interface defines a handler of outgoing HTTP Requests. It should be 26 | /// imported by components which wish to make HTTP Requests. 27 | @since(version = 0.2.0) 28 | interface outgoing-handler { 29 | @since(version = 0.2.0) 30 | use types.{ 31 | outgoing-request, request-options, future-incoming-response, error-code 32 | }; 33 | 34 | /// This function is invoked with an outgoing HTTP Request, and it returns 35 | /// a resource `future-incoming-response` which represents an HTTP Response 36 | /// which may arrive in the future. 37 | /// 38 | /// The `options` argument accepts optional parameters for the HTTP 39 | /// protocol's transport layer. 40 | /// 41 | /// This function may return an error if the `outgoing-request` is invalid 42 | /// or not allowed to be made. Otherwise, protocol errors are reported 43 | /// through the `future-incoming-response`. 44 | @since(version = 0.2.0) 45 | handle: func( 46 | request: outgoing-request, 47 | options: option 48 | ) -> result; 49 | } 50 | -------------------------------------------------------------------------------- /winget/Microsoft.Wassette.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.singleton.1.6.0.schema.json 2 | 3 | PackageIdentifier: Microsoft.Wassette 4 | PackageVersion: 0.3.0 5 | PackageLocale: en-US 6 | Publisher: Microsoft Corporation 7 | PublisherUrl: https://github.com/microsoft/wassette 8 | PublisherSupportUrl: https://github.com/microsoft/wassette/issues 9 | Author: Microsoft Corporation 10 | PackageName: Wassette 11 | PackageUrl: https://github.com/microsoft/wassette 12 | License: MIT 13 | LicenseUrl: https://github.com/microsoft/wassette/blob/main/LICENSE 14 | Copyright: Copyright (c) Microsoft Corporation 15 | CopyrightUrl: https://github.com/microsoft/wassette/blob/main/LICENSE 16 | ShortDescription: A security-oriented runtime that runs WebAssembly Components via MCP 17 | Description: |- 18 | Wassette is a security-oriented runtime that runs WebAssembly Components via MCP (Model Context Protocol). 19 | It makes it easy to extend AI agents with new tools, all without ever having to leave the chat window. 20 | Wasm Components built for Wassette are generic and reusable, and Wassette is built on the Wasmtime security 21 | sandbox, providing browser-grade isolation of tools. 22 | Moniker: wassette 23 | Tags: 24 | - mcp 25 | - webassembly 26 | - wasm 27 | - ai-tools 28 | - security 29 | - sandbox 30 | - runtime 31 | - component 32 | ReleaseDate: 2025-10-03 33 | Installers: 34 | - Architecture: x64 35 | InstallerType: zip 36 | InstallerUrl: https://github.com/microsoft/wassette/releases/download/v0.3.0/wassette_0.3.0_windows_amd64.zip 37 | InstallerSha256: fa92161cf0bf1644f368ab4f87bdcd4483079d679ed7baeebfbbeb5a0e43df9a 38 | NestedInstallerType: portable 39 | NestedInstallerFiles: 40 | - RelativeFilePath: wassette.exe 41 | PortableCommandAlias: wassette 42 | - Architecture: arm64 43 | InstallerType: zip 44 | InstallerUrl: https://github.com/microsoft/wassette/releases/download/v0.3.0/wassette_0.3.0_windows_arm64.zip 45 | InstallerSha256: 8e8be37fa39abf2a90b80debda24013dff2e443a2b90b8db26f530e369468b6d 46 | NestedInstallerType: portable 47 | NestedInstallerFiles: 48 | - RelativeFilePath: wassette.exe 49 | PortableCommandAlias: wassette 50 | ManifestType: singleton 51 | ManifestVersion: 1.6.0 52 | -------------------------------------------------------------------------------- /docs/cookbook/publishing-to-oci-registries.md: -------------------------------------------------------------------------------- 1 | # Publishing Wasm Components to OCI Registries 2 | 3 | Publish your WebAssembly components to OCI registries like GitHub Container Registry (GHCR) for easy distribution. Once published, load components with: `wassette component load oci://ghcr.io/user/component:latest` 4 | 5 | ## Prerequisites 6 | 7 | - A built `.wasm` component (see [JavaScript](./javascript.md), [Python](./python.md), [Rust](./rust.md), or [Go](./go.md) guides) 8 | - Access to an OCI registry (GHCR, Docker Hub, Azure Container Registry, etc.) 9 | - Authentication credentials for your registry 10 | 11 | ## Method 1: Local Publishing with wkg CLI 12 | 13 | Install the `wkg` tool: 14 | 15 | ```bash 16 | cargo install wkg 17 | # or faster: cargo binstall wkg -y 18 | ``` 19 | 20 | Authenticate to GHCR: 21 | 22 | ```bash 23 | # Create a GitHub PAT with 'write:packages' scope at https://github.com/settings/tokens/new 24 | echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin 25 | ``` 26 | 27 | Publish your component: 28 | 29 | ```bash 30 | # Basic publish 31 | wkg oci push ghcr.io/your-username/component-name:v1.0.0 component.wasm 32 | 33 | # With metadata annotations 34 | wkg oci push ghcr.io/your-username/component-name:v1.0.0 component.wasm \ 35 | --annotation "org.opencontainers.image.description"="Component description" \ 36 | --annotation "org.opencontainers.image.source"="https://github.com/your-username/repo" \ 37 | --annotation "org.opencontainers.image.version"="1.0.0" \ 38 | --annotation "org.opencontainers.image.licenses"="MIT" 39 | ``` 40 | 41 | ## Versioning Strategy 42 | 43 | ```bash 44 | wkg oci push ghcr.io/user/component:latest component.wasm # Latest stable 45 | wkg oci push ghcr.io/user/component:v1.0.0 component.wasm # Semantic version 46 | wkg oci push ghcr.io/user/component:abc1234 component.wasm # Commit SHA 47 | wkg oci push ghcr.io/user/component:v1.0.0-beta.1 component.wasm # Pre-release 48 | ``` 49 | 50 | ## Best Practices 51 | 52 | - Always tag with specific versions, not just `latest` 53 | - Sign components with Cosign for security 54 | - Use CI/CD for consistent builds 55 | - Add OCI annotations for discoverability 56 | - Follow semantic versioning (MAJOR.MINOR.PATCH) 57 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Wassette Docker Image 2 | # This Dockerfile provides a containerized runtime for Wassette with additional security isolation 3 | 4 | # Stage 1: Build the Wassette binary 5 | FROM rust:1.90-bookworm AS builder 6 | 7 | # Install ca-certificates for HTTPS support during build 8 | RUN apt-get update && \ 9 | apt-get install -y --no-install-recommends ca-certificates && \ 10 | rm -rf /var/lib/apt/lists/* 11 | 12 | WORKDIR /build 13 | 14 | # Copy the project files 15 | COPY Cargo.toml Cargo.lock ./ 16 | COPY src ./src 17 | COPY crates ./crates 18 | COPY build.rs ./ 19 | 20 | # Build the release binary 21 | RUN cargo build --release --bin wassette 22 | 23 | # Stage 2: Create the runtime image 24 | FROM debian:bookworm-slim 25 | 26 | # Install runtime dependencies 27 | RUN apt-get update && \ 28 | apt-get install -y --no-install-recommends \ 29 | ca-certificates \ 30 | libssl3 && \ 31 | rm -rf /var/lib/apt/lists/* 32 | 33 | # Create a non-root user for running Wassette 34 | RUN useradd -m -u 1000 -s /bin/bash wassette 35 | 36 | # Create necessary directories with proper permissions 37 | RUN mkdir -p /home/wassette/.local/share/wassette/components && \ 38 | mkdir -p /home/wassette/.config/wassette/secrets && \ 39 | chown -R wassette:wassette /home/wassette 40 | 41 | # Copy the binary from the builder stage 42 | COPY --from=builder /build/target/release/wassette /usr/local/bin/wassette 43 | 44 | # Set up environment 45 | ENV HOME=/home/wassette 46 | ENV XDG_DATA_HOME=/home/wassette/.local/share 47 | ENV XDG_CONFIG_HOME=/home/wassette/.config 48 | 49 | # Twelve-factor app compliance: support PORT and BIND_HOST environment variables 50 | # Default PORT is 9001; default BIND_HOST in containers is 0.0.0.0 51 | # (required for external connections; differs from non-containerized default of 127.0.0.1) 52 | ENV PORT=9001 53 | ENV BIND_HOST=0.0.0.0 54 | 55 | # Switch to the non-root user 56 | USER wassette 57 | WORKDIR /home/wassette 58 | 59 | # Expose the default HTTP port (configurable via PORT env var) 60 | EXPOSE 9001 61 | 62 | # Default command: start Wassette with streamable-http transport 63 | # Override this in docker run or docker-compose for different transports 64 | CMD ["wassette", "serve", "--streamable-http"] 65 | -------------------------------------------------------------------------------- /examples/context7-rs/wit/deps/cli/terminal.wit: -------------------------------------------------------------------------------- 1 | /// Terminal input. 2 | /// 3 | /// In the future, this may include functions for disabling echoing, 4 | /// disabling input buffering so that keyboard events are sent through 5 | /// immediately, querying supported features, and so on. 6 | @since(version = 0.2.0) 7 | interface terminal-input { 8 | /// The input side of a terminal. 9 | @since(version = 0.2.0) 10 | resource terminal-input; 11 | } 12 | 13 | /// Terminal output. 14 | /// 15 | /// In the future, this may include functions for querying the terminal 16 | /// size, being notified of terminal size changes, querying supported 17 | /// features, and so on. 18 | @since(version = 0.2.0) 19 | interface terminal-output { 20 | /// The output side of a terminal. 21 | @since(version = 0.2.0) 22 | resource terminal-output; 23 | } 24 | 25 | /// An interface providing an optional `terminal-input` for stdin as a 26 | /// link-time authority. 27 | @since(version = 0.2.0) 28 | interface terminal-stdin { 29 | @since(version = 0.2.0) 30 | use terminal-input.{terminal-input}; 31 | 32 | /// If stdin is connected to a terminal, return a `terminal-input` handle 33 | /// allowing further interaction with it. 34 | @since(version = 0.2.0) 35 | get-terminal-stdin: func() -> option; 36 | } 37 | 38 | /// An interface providing an optional `terminal-output` for stdout as a 39 | /// link-time authority. 40 | @since(version = 0.2.0) 41 | interface terminal-stdout { 42 | @since(version = 0.2.0) 43 | use terminal-output.{terminal-output}; 44 | 45 | /// If stdout is connected to a terminal, return a `terminal-output` handle 46 | /// allowing further interaction with it. 47 | @since(version = 0.2.0) 48 | get-terminal-stdout: func() -> option; 49 | } 50 | 51 | /// An interface providing an optional `terminal-output` for stderr as a 52 | /// link-time authority. 53 | @since(version = 0.2.0) 54 | interface terminal-stderr { 55 | @since(version = 0.2.0) 56 | use terminal-output.{terminal-output}; 57 | 58 | /// If stderr is connected to a terminal, return a `terminal-output` handle 59 | /// allowing further interaction with it. 60 | @since(version = 0.2.0) 61 | get-terminal-stderr: func() -> option; 62 | } 63 | -------------------------------------------------------------------------------- /scripts/README.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG Automation Scripts 2 | 3 | Scripts for automating CHANGELOG management during releases. 4 | 5 | ## Scripts 6 | 7 | ### changelog_utils.py 8 | 9 | Python utility for extracting and updating CHANGELOG.md content. 10 | 11 | **Extract changelog content:** 12 | ```bash 13 | python3 scripts/changelog_utils.py extract [changelog_path] 14 | ``` 15 | 16 | **Update changelog post-release:** 17 | ```bash 18 | python3 scripts/changelog_utils.py update [changelog_path] 19 | ``` 20 | 21 | **Examples:** 22 | ```bash 23 | # Extract v0.4.0 content 24 | python3 scripts/changelog_utils.py extract v0.4.0 25 | 26 | # Update CHANGELOG after v0.4.0 release 27 | python3 scripts/changelog_utils.py update v0.4.0 v0.3.0 28 | 29 | # Use custom changelog path 30 | python3 scripts/changelog_utils.py extract v0.4.0 docs/CHANGELOG.md 31 | ``` 32 | 33 | ### test_changelog_utils.py 34 | 35 | Unit tests for changelog_utils module. 36 | 37 | **Run tests:** 38 | ```bash 39 | cd scripts 40 | python3 test_changelog_utils.py 41 | ``` 42 | 43 | ## Release Workflow Integration 44 | 45 | The `.github/workflows/release.yml` workflow uses these scripts to: 46 | 47 | 1. **During Release:** Extract CHANGELOG content for GitHub release notes 48 | 2. **Post-Release:** Update CHANGELOG.md on the release branch (converts `[Unreleased]` to versioned section, adds new `[Unreleased]`, updates comparison links) 49 | 3. **Create PR:** Automatically create a PR to merge the release branch with updated CHANGELOG back to main 50 | 51 | ### Release Branch Strategy 52 | 53 | The release workflow now uses a release branch strategy to prevent blocking development: 54 | 55 | - CHANGELOG updates are made on the `release/vX.Y.Z` branch 56 | - A PR is automatically created to merge the release branch back to main 57 | - Development can continue on main without interruption during the release process 58 | 59 | See `RELEASE.md` for complete documentation of the release process. 60 | 61 | ## Manual Testing 62 | 63 | ```bash 64 | # Test extraction 65 | python3 scripts/changelog_utils.py extract v0.3.0 66 | 67 | # Test update (backup first!) 68 | cp CHANGELOG.md CHANGELOG.md.backup 69 | python3 scripts/changelog_utils.py update v0.4.0 v0.3.0 70 | git diff CHANGELOG.md 71 | mv CHANGELOG.md.backup CHANGELOG.md # Restore if needed 72 | ``` 73 | -------------------------------------------------------------------------------- /examples/context7-rs/wit/deps/clocks/timezone.wit: -------------------------------------------------------------------------------- 1 | package wasi:clocks@0.2.1; 2 | 3 | @unstable(feature = clocks-timezone) 4 | interface timezone { 5 | @unstable(feature = clocks-timezone) 6 | use wall-clock.{datetime}; 7 | 8 | /// Return information needed to display the given `datetime`. This includes 9 | /// the UTC offset, the time zone name, and a flag indicating whether 10 | /// daylight saving time is active. 11 | /// 12 | /// If the timezone cannot be determined for the given `datetime`, return a 13 | /// `timezone-display` for `UTC` with a `utc-offset` of 0 and no daylight 14 | /// saving time. 15 | @unstable(feature = clocks-timezone) 16 | display: func(when: datetime) -> timezone-display; 17 | 18 | /// The same as `display`, but only return the UTC offset. 19 | @unstable(feature = clocks-timezone) 20 | utc-offset: func(when: datetime) -> s32; 21 | 22 | /// Information useful for displaying the timezone of a specific `datetime`. 23 | /// 24 | /// This information may vary within a single `timezone` to reflect daylight 25 | /// saving time adjustments. 26 | @unstable(feature = clocks-timezone) 27 | record timezone-display { 28 | /// The number of seconds difference between UTC time and the local 29 | /// time of the timezone. 30 | /// 31 | /// The returned value will always be less than 86400 which is the 32 | /// number of seconds in a day (24*60*60). 33 | /// 34 | /// In implementations that do not expose an actual time zone, this 35 | /// should return 0. 36 | utc-offset: s32, 37 | 38 | /// The abbreviated name of the timezone to display to a user. The name 39 | /// `UTC` indicates Coordinated Universal Time. Otherwise, this should 40 | /// reference local standards for the name of the time zone. 41 | /// 42 | /// In implementations that do not expose an actual time zone, this 43 | /// should be the string `UTC`. 44 | /// 45 | /// In time zones that do not have an applicable name, a formatted 46 | /// representation of the UTC offset may be returned, such as `-04:00`. 47 | name: string, 48 | 49 | /// Whether daylight saving time is active. 50 | /// 51 | /// In implementations that do not expose an actual time zone, this 52 | /// should return false. 53 | in-daylight-saving-time: bool, 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /crates/wassette/src/runtime_context.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT license. 3 | 4 | //! Support utilities for sharing Wasmtime engine and linker state across lifecycle 5 | //! manager instances. 6 | 7 | use std::sync::Arc; 8 | 9 | use anyhow::Result; 10 | use wasmtime::component::{Component, InstancePre, Linker}; 11 | use wasmtime::Engine; 12 | use wasmtime_wasi_config::WasiConfig; 13 | 14 | use crate::{WasiState, WassetteWasiState}; 15 | 16 | /// Encapsulates Wasmtime engine and linker setup for reuse across the lifecycle manager. 17 | #[derive(Clone)] 18 | pub struct RuntimeContext { 19 | engine: Arc, 20 | linker: Arc>>, 21 | } 22 | 23 | impl RuntimeContext { 24 | /// Build a runtime context with the standard configuration used by Wassette. 25 | pub fn initialize() -> Result { 26 | let mut config = wasmtime::Config::new(); 27 | config.wasm_component_model(true); 28 | config.async_support(true); 29 | 30 | let engine = Arc::new(Engine::new(&config)?); 31 | 32 | let mut linker = Linker::new(engine.as_ref()); 33 | wasmtime_wasi::p2::add_to_linker_async(&mut linker)?; 34 | wasmtime_wasi_http::add_only_http_to_linker_async(&mut linker)?; 35 | wasmtime_wasi_config::add_to_linker( 36 | &mut linker, 37 | |h: &mut WassetteWasiState| WasiConfig::from(&h.inner.wasi_config_vars), 38 | )?; 39 | 40 | Ok(Self { 41 | engine, 42 | linker: Arc::new(linker), 43 | }) 44 | } 45 | 46 | /// Produce a cached `InstancePre` handle for the provided component using 47 | /// the shared linker configuration. 48 | pub fn instantiate_pre( 49 | &self, 50 | component: &Component, 51 | ) -> wasmtime::Result>> { 52 | self.linker.instantiate_pre(component) 53 | } 54 | } 55 | 56 | impl AsRef for RuntimeContext { 57 | fn as_ref(&self) -> &Engine { 58 | self.engine.as_ref() 59 | } 60 | } 61 | 62 | impl AsRef>> for RuntimeContext { 63 | fn as_ref(&self) -> &Linker> { 64 | self.linker.as_ref() 65 | } 66 | } 67 | 68 | impl std::ops::Deref for RuntimeContext { 69 | type Target = Engine; 70 | 71 | fn deref(&self) -> &Self::Target { 72 | self.engine.as_ref() 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /docs/TODO.md: -------------------------------------------------------------------------------- 1 | # Documentation TODO 2 | 3 | This file contains suggestions for improving the Wassette documentation structure and content. 4 | 5 | ## Suggested Content Additions 6 | 7 | ### 1. Introduction Page (`introduction.md`) 8 | Add a welcoming introduction page that explains: 9 | - What Wassette is (MCP server running Tools as WebAssembly components) 10 | - Who it's for (developers, system administrators, security-conscious users) 11 | - Key benefits (security, isolation, cross-platform compatibility) 12 | - How to navigate the documentation 13 | 14 | ### 2. Comprehensive Installation Guide (`installation.md`) 15 | Create a unified installation guide that: 16 | - Provides overview of all installation methods 17 | - Guides users to choose the best method for their platform 18 | - Links to specific installation methods (Homebrew, Nix, Winget, source builds) 19 | - Includes verification steps and troubleshooting 20 | 21 | ### 3. Development Setup Guide (`development.md`) 22 | Add a guide for contributors covering: 23 | - Setting up development environment 24 | - Building from source 25 | - Running tests 26 | - Code style and contribution guidelines 27 | - Debugging with MCP inspector 28 | - Using Justfile commands 29 | 30 | ### 4. Examples and Usage (`examples.md`) 31 | Create an examples showcase with: 32 | - Language support matrix showing which languages are supported for WASM tools 33 | - Step-by-step examples of creating and using WASM tools 34 | - Common use cases and patterns 35 | - Integration examples with different MCP clients 36 | 37 | ## Suggested Content Improvements 38 | 39 | ### Documentation Structure 40 | - Add clear navigation hierarchy with logical grouping 41 | - Include search functionality (already provided by mdbook) 42 | - Add edit links for community contributions (already configured) 43 | - Ensure mobile-friendly responsive design (provided by mdbook) 44 | 45 | ### Content Enhancements 46 | - Add code examples with syntax highlighting 47 | - Include diagrams for architecture documentation 48 | - Provide troubleshooting sections 49 | - Add FAQ section for common questions 50 | - Include performance and security best practices 51 | 52 | ## Implementation Notes 53 | 54 | These improvements would enhance the user experience by: 55 | - Providing clear entry points for different user types 56 | - Offering comprehensive guidance for both users and contributors 57 | - Showcasing the capabilities and use cases of Wassette 58 | - Making the documentation more discoverable and navigable -------------------------------------------------------------------------------- /examples/gomodule-go/gen/wasi/http/outgoing-handler/outgoing-handler.wit.go: -------------------------------------------------------------------------------- 1 | // Code generated by wit-bindgen-go. DO NOT EDIT. 2 | 3 | // Package outgoinghandler represents the imported interface "wasi:http/outgoing-handler@0.2.0". 4 | // 5 | // This interface defines a handler of outgoing HTTP Requests. It should be 6 | // imported by components which wish to make HTTP Requests. 7 | package outgoinghandler 8 | 9 | import ( 10 | "go.bytecodealliance.org/cm" 11 | "gomodule-server-go/gen/wasi/http/types" 12 | ) 13 | 14 | // OutgoingRequest represents the imported type alias "wasi:http/outgoing-handler@0.2.0#outgoing-request". 15 | // 16 | // See [types.OutgoingRequest] for more information. 17 | type OutgoingRequest = types.OutgoingRequest 18 | 19 | // RequestOptions represents the imported type alias "wasi:http/outgoing-handler@0.2.0#request-options". 20 | // 21 | // See [types.RequestOptions] for more information. 22 | type RequestOptions = types.RequestOptions 23 | 24 | // FutureIncomingResponse represents the imported type alias "wasi:http/outgoing-handler@0.2.0#future-incoming-response". 25 | // 26 | // See [types.FutureIncomingResponse] for more information. 27 | type FutureIncomingResponse = types.FutureIncomingResponse 28 | 29 | // ErrorCode represents the type alias "wasi:http/outgoing-handler@0.2.0#error-code". 30 | // 31 | // See [types.ErrorCode] for more information. 32 | type ErrorCode = types.ErrorCode 33 | 34 | // Handle represents the imported function "handle". 35 | // 36 | // This function is invoked with an outgoing HTTP Request, and it returns 37 | // a resource `future-incoming-response` which represents an HTTP Response 38 | // which may arrive in the future. 39 | // 40 | // The `options` argument accepts optional parameters for the HTTP 41 | // protocol's transport layer. 42 | // 43 | // This function may return an error if the `outgoing-request` is invalid 44 | // or not allowed to be made. Otherwise, protocol errors are reported 45 | // through the `future-incoming-response`. 46 | // 47 | // handle: func(request: outgoing-request, options: option) -> result 49 | // 50 | //go:nosplit 51 | func Handle(request OutgoingRequest, options cm.Option[RequestOptions]) (result cm.Result[ErrorCodeShape, FutureIncomingResponse, ErrorCode]) { 52 | request0 := cm.Reinterpret[uint32](request) 53 | options0, options1 := lower_OptionRequestOptions(options) 54 | wasmimport_Handle((uint32)(request0), (uint32)(options0), (uint32)(options1), &result) 55 | return 56 | } 57 | -------------------------------------------------------------------------------- /examples/context7-rs/README.md: -------------------------------------------------------------------------------- 1 | # Context7 Example (Rust) 2 | 3 | This example demonstrates how to use the Context7 API to search for libraries and fetch documentation using a Wassette component written in Rust. 4 | 5 | For more information on installing Wassette, please see the [installation instructions](https://github.com/microsoft/wassette?tab=readme-ov-file#installation). 6 | 7 | ## Usage 8 | 9 | To use this component, you will need an API key from [Context7](https://context7.com). Set the API key as an environment variable: 10 | 11 | ```bash 12 | export CONTEXT7_API_KEY="your_api_key_here" 13 | ``` 14 | 15 | See the [Environment Variables reference](../../docs/reference/environment-variables.md) for alternative methods including config files and Docker. 16 | 17 | Then, load the component from the local file system. 18 | 19 | **Load the component:** 20 | 21 | ``` 22 | Please load the component from file:///path/to/mcp-wasmtime/examples/context7-rs/target/wasm32-wasip2/debug/context7.wasm 23 | ``` 24 | 25 | **Search for libraries:** 26 | 27 | ``` 28 | resolve library id for "react" 29 | ``` 30 | 31 | **Get library documentation:** 32 | 33 | ``` 34 | get library docs for "library-id" with topic "hooks" and 15000 tokens 35 | ``` 36 | 37 | ## Policy 38 | 39 | By default, WebAssembly (Wasm) components do not have any access to the host machine or network. The `policy.yaml` file is used to explicitly define what network resources and environment variables are made available to the component. This ensures that the component can only access the resources that are explicitly allowed. 40 | 41 | Example: 42 | 43 | ```yaml 44 | version: "1.0" 45 | description: "Permission policy for context7 component" 46 | permissions: 47 | network: 48 | allow: 49 | - host: "context7.com" 50 | environment: 51 | allow: 52 | - key: "CONTEXT7_API_KEY" 53 | ``` 54 | 55 | ## Available Functions 56 | 57 | The component exports two main functions: 58 | 59 | 1. **resolve-library-id**: Searches for libraries by name and returns Context7-compatible library IDs 60 | - Input: library name (string) 61 | - Output: search response with results, success flag, and optional error 62 | 63 | 2. **get-library-docs**: Fetches documentation for a specific library using its Context7-compatible ID 64 | - Input: library ID (string), optional topic (string), optional token count (u32) 65 | - Output: docs response with content, success flag, and optional error 66 | 67 | The source code for this example can be found in [`src/lib.rs`](src/lib.rs). 68 | --------------------------------------------------------------------------------