Principle:Mlc ai Web llm Chrome Extension Manifest
Overview
Configuration pattern for declaring Chrome Extension capabilities required for in-browser LLM inference with WebGPU and WASM. The Manifest V3 file is the entry point for any Chrome extension that uses @mlc-ai/web-llm and must correctly declare permissions, Content Security Policy directives, service worker registration, and content script injection before any web-llm code can execute in the extension context.
Description
Chrome Manifest V3 configuration for web-llm extensions requires specific permissions and Content Security Policy settings that differ from standard web applications. Three configuration areas are critical:
Content Security Policy (CSP): The manifest must enable wasm-unsafe-eval in the script-src directive to allow WebAssembly execution. Web-llm compiles model inference kernels to WASM via the TVM runtime, and Chrome Extensions block WASM execution by default. Additionally, connect-src must whitelist the Hugging Face CDN domains (including huggingface.co, cdn-lfs.huggingface.co, cdn-lfs-us-1.huggingface.co, cdn-lfs-us-1.hf.co, and cas-bridge.xethub.hf.co) so the extension can download model weights at runtime.
Service Worker Registration: The background field must declare a service_worker entry with "type": "module". This enables ES module imports in the background script, which is required because @mlc-ai/web-llm is distributed as an ES module. The service worker hosts the actual MLCEngine instance and persists it across popup open/close cycles.
Permissions and Content Scripts: The extension needs the storage permission for model caching metadata. If the extension accesses page content for context-aware inference, it also needs tabs, webNavigation, and a content script declared with appropriate URL match patterns.
Usage
Use this as the first step when building a Chrome extension that runs LLM inference. The manifest must be correctly configured before any web-llm code can execute in the extension context. Errors in the CSP configuration will result in silent WASM compilation failures or blocked network requests to model weight servers.
When to apply:
- Starting a new Chrome extension project that uses
@mlc-ai/web-llm - Migrating an existing extension from Manifest V2 to Manifest V3
- Debugging "CompileError: WebAssembly.instantiate()" failures in extension context
- Debugging blocked fetch requests to Hugging Face model repositories
When not to apply:
- Standard web applications (they do not require manifest.json)
- Extensions that use a remote LLM API rather than local inference
Theoretical Basis
Chrome Extensions operate under a stricter security model than regular web pages. Manifest V3 introduced declarative permissions and a restricted CSP that disallows unsafe-eval by default. Since WebAssembly compilation is treated as a form of code evaluation, Chrome provides the wasm-unsafe-eval directive as a more targeted permission that allows WASM without enabling JavaScript eval().
The service worker model in Manifest V3 replaces the persistent background pages of Manifest V2. Service workers are event-driven and can be terminated by Chrome after a period of inactivity (typically 30 seconds). This lifecycle behavior directly influences the design of the web-llm extension architecture, requiring keep-alive heartbeats and model caching logic.
The module-type service worker ("type": "module") is required because @mlc-ai/web-llm uses ES module syntax (import/export). Without this declaration, the browser would treat the background script as a classic script, causing syntax errors on any import statement.
I/O Contract
Input: A valid manifest.json file placed at the root of the extension source directory.
Output: Chrome recognizes the extension and grants the declared permissions, CSP directives, and service worker registration.
Key fields and their constraints:
| Field | Required Value | Purpose |
|---|---|---|
manifest_version |
3 |
Manifest V3 is required for service worker background scripts |
background.service_worker |
Path to background script | Registers the service worker that hosts MLCEngine |
background.type |
"module" |
Enables ES module imports in the service worker |
content_security_policy.extension_pages |
Must include wasm-unsafe-eval in script-src |
Allows WASM compilation for TVM runtime |
permissions |
At minimum ["storage"] |
Enables model cache metadata storage |
content_scripts |
Optional; required for page content access | Injects DOM access script into web pages |
Usage Examples
Minimal manifest for web-llm extension with service worker:
{
"manifest_version": 3,
"name": "MyLLMExtension",
"version": "1.0.0",
"description": "In-browser LLM inference via web-llm",
"content_security_policy": {
"extension_pages": "script-src 'self' 'wasm-unsafe-eval'; default-src 'self' data:; connect-src 'self' data: https://huggingface.co https://cdn-lfs.huggingface.co https://cdn-lfs-us-1.huggingface.co https://raw.githubusercontent.com https://cdn-lfs-us-1.hf.co https://cas-bridge.xethub.hf.co"
},
"action": {
"default_title": "MyLLMExtension",
"default_popup": "popup.html"
},
"background": {
"service_worker": "background.ts",
"type": "module"
},
"permissions": ["storage"]
}
Full manifest with content scripts and page access (from the repository example):
{
"manifest_version": 3,
"name": "MLCBot",
"version": "0.1.0",
"description": "Chat with your browser",
"icons": {
"16": "icons/icon-16.png",
"32": "icons/icon-32.png",
"64": "icons/icon-64.png",
"128": "icons/icon-128.png"
},
"content_security_policy": {
"extension_pages": "style-src-elem 'self' https://cdnjs.cloudflare.com; font-src 'self' https://cdnjs.cloudflare.com; script-src 'self' 'wasm-unsafe-eval'; default-src 'self' data:; connect-src 'self' data: http://localhost:8000 https://huggingface.co https://cdn-lfs.huggingface.co https://cdn-lfs-us-1.huggingface.co https://raw.githubusercontent.com https://cdn-lfs-us-1.hf.co https://cas-bridge.xethub.hf.co"
},
"action": {
"default_title": "MLCBot",
"default_popup": "popup.html"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
],
"background": {
"service_worker": "background.ts",
"type": "module"
},
"permissions": ["storage", "tabs", "webNavigation"]
}
Related Pages
- Implementation:Mlc_ai_Web_llm_Manifest_V3_Configuration
- Mlc_ai_Web_llm_Extension_Service_Worker - The service worker pattern that depends on this manifest configuration
- Mlc_ai_Web_llm_Extension_Client_Engine - The popup-side engine proxy that connects to the service worker declared here
- Mlc_ai_Web_llm_Page_Content_Access - Content script injection configured in this manifest