
Research
/Security News
PolinRider Spreads Through Compromised GitHub Accounts and Packagist
Operators behind PolinRider used a compromised GitHub account to plant malware in four development versions of a Packagist package with 700,000+ downloads.
@three-ws/assistant-mcp
Advanced tools
Generate a paste-ready three.ws assistant widget from any AI agent. build_assistant_widget turns a config into an embeddable <script> tag, a frame URL, and a ThreeAssistant.init() snippet for a floating 3D avatar chatbot on any website; list_assistant_opt
Generate a paste-ready three.ws assistant widget, a floating 3D avatar chatbot for any website, from any AI agent.
A Model Context Protocol server that lets any AI assistant build a paste-ready embed for the three.ws assistant widget over stdio. Describe how you want the assistant to look and behave and
build_assistant_widgetreturns a ready-to-paste<script>tag, a standalone frame URL for<iframe>embedding, and an equivalentThreeAssistant.init({...})JavaScript-API snippet, a floating 3D avatar chatbot that lives in the corner of any site.list_assistant_optionsenumerates every built-in avatar, background preset, interaction mode, chat lane, anddata-*attribute you can set.
Both tools are pure and offline: building an embed is deterministic string logic over local validators. Every field is validated and clamped, so a bad or hostile value falls back to a safe default and the generated HTML is always well-formed. No API key, no signer, no payment, no network call. Point THREE_WS_BASE at a deployment (or leave the default) and go.
npm install @three-ws/assistant-mcp
Or run with npx (no install):
npx -y @three-ws/assistant-mcp
Claude Code, one line:
claude mcp add assistant -- npx -y @three-ws/assistant-mcp
Claude Desktop / Cursor (claude_desktop_config.json or mcp.json):
{
"mcpServers": {
"assistant": {
"command": "npx",
"args": ["-y", "@three-ws/assistant-mcp"]
}
}
}
Inspect the surface with the MCP Inspector:
npx -y @modelcontextprotocol/inspector npx @three-ws/assistant-mcp
| Tool | Type | What it does |
|---|---|---|
build_assistant_widget | read-only | A config → a paste-ready <script> embed (non-default settings as data-*), a frame URL, a ThreeAssistant.init() snippet, and the normalized config. |
list_assistant_options | read-only | Enumerate every built-in avatar, background preset and grammar, interaction mode, chat lane, and the full data-* attribute reference. |
build_assistant_widget is a pure function: the same config always yields the same embed, and it never touches the network. The generated <script> tag carries only the settings that differ from their defaults, so a minimal config yields a minimal tag. The frame_url carries every resolved value (including defaults) so the standalone frame renders deterministically when dropped into an <iframe>.
build_assistant_widget, all optional:
| Field | Type / values | Default |
|---|---|---|
avatar | avatar id, /avatars/*.glb path, or GLB URL | mannequin |
agent | a three.ws agent id (alternative to avatar) | (none) |
background | transparent | #hex | ember/ocean/violet/forest/dusk/slate | gradient:#a,#b[,angle] | transparent |
mode | chat | speak | both | both |
name | string (≤ 60) | (none) |
greeting | string (≤ 200) | (none) |
context | string (≤ 500), what the assistant should know about the site | (none) |
accent | #hex | #f97316 |
position | right | left | right |
voice | boolean, start with voice on/off | on |
badge | boolean, show the three.ws attribution badge | on |
Any value that fails validation (a bad hex, an unknown background, an over-long string) falls back to its default rather than being rejected, so you always get a working embed.
list_assistant_options, filter (optional: avatars | backgrounds | modes | chat_lanes | attributes). Omit to get everything.
// build_assistant_widget
> {
"avatar": "/avatars/selfie-girl.glb",
"background": "ocean",
"mode": "both",
"name": "Aria",
"greeting": "Hi! Ask me anything about the site.",
"accent": "#00c2ff",
"position": "left"
}
{
"ok": true,
"snippet": "<script src=\"https://three.ws/assistant/v1.js\" async data-avatar=\"/avatars/selfie-girl.glb\" data-bg=\"ocean\" data-name=\"Aria\" data-greeting=\"Hi! Ask me anything about the site.\" data-accent=\"#00c2ff\" data-position=\"left\"></script>",
"frame_url": "https://three.ws/assistant-frame?avatar=%2Favatars%2Fselfie-girl.glb&bg=ocean&mode=both&name=Aria&greeting=Hi%21+Ask+me+anything+about+the+site.&accent=%2300c2ff",
"js_api": "ThreeAssistant.init({\n \"bg\": \"ocean\",\n \"mode\": \"both\",\n \"accent\": \"#00c2ff\",\n \"position\": \"left\",\n \"avatar\": \"/avatars/selfie-girl.glb\",\n \"name\": \"Aria\",\n \"greeting\": \"Hi! Ask me anything about the site.\"\n});",
"builder_url": "https://three.ws/assistant",
"config": { "bg": "ocean", "mode": "both", "accent": "#00c2ff", "position": "left", "avatar": "/avatars/selfie-girl.glb", "name": "Aria", "greeting": "Hi! Ask me anything about the site." },
"notes": "Chat runs on the free three.ws LLM chain by default (no key). Visitors can paste their own Groq or OpenRouter key in the widget settings for a private lane; that key stays in their browser."
}
Paste the snippet before </body> on any page, or drop the frame_url into an <iframe>. Design it visually first at three.ws/assistant.
THREE_WS_BASE only sets the origin baked into the generated URLs.| Variable | Required | Default |
|---|---|---|
THREE_WS_BASE | no | https://three.ws |
The package entry point exports TOOLS (every tool definition: name, title,
description, inputSchema, annotations, handler) and buildServer(), which returns a
fully-registered McpServer with no transport attached. Both tools are pure and offline, so you
can call them directly as a widget-builder library with no MCP client involved.
// run from a checkout: node this-file.mjs
import { TOOLS, buildServer } from '@three-ws/assistant-mcp';
const build = TOOLS.find((t) => t.name === 'build_assistant_widget');
const { snippet } = await build.handler({ avatar: '/avatars/michelle.glb', background: 'dusk' });
console.log(snippet);
// Or hand the whole registered server to your own MCP transport.
buildServer();
<script src="https://three.ws/assistant/v1.js" async data-avatar="/avatars/michelle.glb" data-bg="dusk"></script>
Part of the three.ws SDK suite, 3D AI agents, on-chain identity, and agent payments.
Website · Changelog · GitHub
FAQs
Generate a paste-ready three.ws assistant widget from any AI agent. build_assistant_widget turns a config into an embeddable <script> tag, a frame URL, and a ThreeAssistant.init() snippet for a floating 3D avatar chatbot on any website; list_assistant_opt
The npm package @three-ws/assistant-mcp receives a total of 169 weekly downloads. As such, @three-ws/assistant-mcp popularity was classified as not popular.
We found that @three-ws/assistant-mcp demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Research
/Security News
Operators behind PolinRider used a compromised GitHub account to plant malware in four development versions of a Packagist package with 700,000+ downloads.

Security News
GitHub Actions now supports cache-mode, a least-privilege control on the Actions cache aimed at the cache poisoning technique behind recent compromises.

Company News
Allow myself to introduce... myself.