Managing MCP Index
Comfy-Org/workflow_templates
Builds and maintains templates/index.mcp.json for Comfy Cloud MCP tools.
Create Super Agent Party (SAP) extensions. An agent skill from heshengtao/super-agent-party.
$ npx skills add heshengtao/super-agent-party --skill sap-extension-creator -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install heshengtao/super-agent-party sap-extension-creator --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/heshengtao/super-agent-party.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/sap-extension-creator .claude/skills/sap-extension-creator && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "sap-extension-creator" agent skill from https://github.com/heshengtao/super-agent-party/tree/main/skills/sap-extension-creator into .claude/skills/sap-extension-creator/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sap-extension-creator", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/heshengtao/super-agent-party/tree/main/skills/sap-extension-creatorType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add heshengtao/super-agent-party --skill sap-extension-creator -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install heshengtao/super-agent-party sap-extension-creator --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/heshengtao/super-agent-party.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/sap-extension-creator .agents/skills/sap-extension-creator && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "sap-extension-creator" agent skill from https://github.com/heshengtao/super-agent-party/tree/main/skills/sap-extension-creator into .agents/skills/sap-extension-creator/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sap-extension-creator", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add heshengtao/super-agent-party --skill sap-extension-creator -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install heshengtao/super-agent-party sap-extension-creator --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/heshengtao/super-agent-party.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/sap-extension-creator .cursor/skills/sap-extension-creator && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "sap-extension-creator" agent skill from https://github.com/heshengtao/super-agent-party/tree/main/skills/sap-extension-creator into .cursor/skills/sap-extension-creator/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sap-extension-creator", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/heshengtao/super-agent-party.git --path skills/sap-extension-creator--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add heshengtao/super-agent-party --skill sap-extension-creator -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install heshengtao/super-agent-party sap-extension-creator --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/heshengtao/super-agent-party.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/sap-extension-creator .gemini/skills/sap-extension-creator && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "sap-extension-creator" agent skill from https://github.com/heshengtao/super-agent-party/tree/main/skills/sap-extension-creator into .gemini/skills/sap-extension-creator/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sap-extension-creator", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install heshengtao/super-agent-party sap-extension-creatorInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add heshengtao/super-agent-party --skill sap-extension-creator -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/heshengtao/super-agent-party.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/sap-extension-creator .github/skills/sap-extension-creator && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "sap-extension-creator" agent skill from https://github.com/heshengtao/super-agent-party/tree/main/skills/sap-extension-creator into .github/skills/sap-extension-creator/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sap-extension-creator", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add heshengtao/super-agent-party --skill sap-extension-creator -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install heshengtao/super-agent-party sap-extension-creator --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/heshengtao/super-agent-party.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/sap-extension-creator .opencode/skills/sap-extension-creator && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "sap-extension-creator" agent skill from https://github.com/heshengtao/super-agent-party/tree/main/skills/sap-extension-creator into .opencode/skills/sap-extension-creator/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sap-extension-creator", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
sap-extension-creatorCreate Super Agent Party (SAP) extensions. An agent skill from heshengtao/super-agent-party.
Sap Extension Creator is an agent skill from heshengtao/super-agent-party. Create Super Agent Party (SAP) extensions. This skill should be used when users want to create, build, or scaffold a new extension for Super Agent Party - including static HTML extensions (pure frontend) and Node.js backend extensions. Triggers on requests like "create a new SAP extension", "build an extension for Super Agent Party", "scaffold a plugin", "make a chat UI extension", or when working with sap extension projects.
Its SKILL.md is about 6k tokens, which your agent loads only when the skill is triggered. The skill folder holds 11 other files, including reference files and assets (for example `assets/node-template/index.js`, `assets/node-template/package.json` and `assets/static-template/package.json`).
It sits in Frontend & Design. It works with Node.js, npm, Model Context Protocol and ComfyUI. The repository describes itself as: ⭐ All-in-one AI companion! Super Agent Party = Self hosted neuro sama + openclaw! ⭐ 全能AI伴侣!超级智能体派对 = 自托管neuro sama + openclaw! The licence is AGPL-3.0.
6 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit bfd9309. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Ships script files (JavaScript), which the agent can run.
Shell commands in SKILL.md call:
npmnodeFrom the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
github.comgitee.comcdnjs.cloudflare.comFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Sap Extension Creator loads about 6k tokens when it runs, and up to ~8.6k if it reads all its reference files. Until then it costs about 113 tokens; SKILL.md has 1,583 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from heshengtao/super-agent-party at commit bfd9309, republished under its AGPL-3.0 licence (© heshengtao). 1,583 words, ~6,038 tokens.
.claude/skills/sap-extension-creator/SKILL.md (or your agent's skills folder). This skill also uses 7 other files; get the full folder from GitHub.Create Super Agent Party extensions—self-contained packages that extend the platform with custom chat UI and tools. Two modes are supported:
npm install + node index.js <port>)Both modes support MCP tool registration (the register_node_extension_mcp protocol message works for ANY extension via WebSocket, despite the "node" in its name).
User wants to create an extension?
├─ Only needs UI (chat, display, simple interactions)? → Static Extension
└─ Needs backend logic (API calls, DB, file processing)? → Node.js Extension| File | Required | Purpose |
|---|---|---|
package.json | ✅ | Metadata, dependencies, window config |
index.html | ✅ | Main UI (full HTML page, single-file app) |
index.js | Node only | Node.js entry point |
node_modules/ | Node only | Auto-installed by SAP via npm install |
Ask the user:
my-weather-widget)Use the templates in assets/ as starting points:
assets/static-template/assets/node-template/Create the extension directory under the workspace (user will later install it into SAP's extensions/ folder).
See references/package-json-spec.md for the complete field reference. Minimum:
{
"name": "my-extension",
"version": "1.0.0",
"description": "What it does",
"author": "your-name",
"repository": "https://github.com/user/repo",
"backupRepository": "https://gitee.com/user/repo",
"category": "Tools"
}For Node.js extensions, also include:
{
"main": "index.js",
"nodePort": 0,
"dependencies": { "express": "^5.1.0" }
}For transparent/frameless widgets (e.g., mini music controllers, floating panels):
{
"transparent": true,
"width": 280,
"height": 80
}When transparent: true, SAP creates a frameless, transparent, always-on-top window (see main.js open-extension-window handler). Use this for compact overlay widgets.
The HTML page is rendered inside an Electron BrowserWindow (either directly or via an iframe). Key patterns:
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">../../fontawesome/ — these may work for static extensions but break for Node.js extensions (different serving paths).ws://host/ws for messaging and MCP.window.location.pathname for /extensions/{ext_id}/.messages_update and broadcast_messages events.set_user_input then trigger_send_message.See references/node-entry-spec.md for the full protocol. The entry point:
process.argv[2]127.0.0.1/health endpoint for readiness checksExtensions can register tools that the AI agent can call — via WebSocket in the frontend (both static and Node.js). The MCP lifecycle has three mandatory stages:
STARTUP → ws.onopen → registerMcpTools()
RUNTIME → ws.onmessage → handleMcpCall() when AI calls a tool
SHUTDOWN → window.beforeunload → unregisterMcpTools()① Register on startup — always in ws.onopen, using a dedicated function:
function registerMcpTools() {
getExtId();
ws.send(JSON.stringify({
type: 'register_node_extension_mcp',
data: {
ext_id: MY_EXT_ID,
tools: [{
name: `${MY_EXT_ID}_my_tool`,
description: 'What this tool does (use the user\'s language)',
parameters: {
type: 'object',
properties: {
param1: { type: 'string', description: '...' }
},
required: ['param1']
}
}]
}
}));
}② Handle tool calls — the AI agent calls your tool:
async function handleMcpCall(data) {
const { ext_id, tool_name, tool_params, call_id } = data;
if (ext_id !== MY_EXT_ID && !tool_name.includes(MY_EXT_ID)) return;
// ... execute logic, then:
ws.send(JSON.stringify({
type: 'mcp_tool_result',
data: { call_id, result: 'output' }
}));
}③ Unregister on shutdown — MUST send unregister_node_extension_mcp before the window closes:
function unregisterMcpTools() {
if (ws && ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ type: 'unregister_node_extension_mcp', data: { ext_id: MY_EXT_ID } }));
}
}
window.addEventListener('beforeunload', () => { unregisterMcpTools(); });Key rule: Registration and unregistration MUST be in separate named functions (registerMcpTools / unregisterMcpTools), NOT inline code. This makes the lifecycle explicit and easy for AI to understand.
If an extension has no MCP tools, all three functions can be deleted.
See sap-lx-music/index.html for a complete real-world MCP implementation example (static extension with 12+ registered tools).
Every extension should support dark/light mode and Chinese/English bilingual UI. Do NOT hardcode a single theme color scheme — use CSS variables so each extension can have its own identity.
Define light theme in :root and override in body.dark:
:root {
--bg: #ffffff;
--bg-secondary: #f5f5f5;
--text: #333333;
--text-sub: #888888;
--accent: #ec4141; /* extension's own brand color */
--accent-hover: #d73a3a;
--border: rgba(0,0,0,0.08);
--transition: 0.3s cubic-bezier(0.25, 0.1, 0.25, 1);
--font: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Helvetica Neue", sans-serif;
}
body.dark {
--bg: #2b2b2b;
--bg-secondary: #222222;
--text: #e0e0e0;
--text-sub: #888888;
--border: rgba(255,255,255,0.06);
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body {
height: 100%; font-family: var(--font);
background: var(--bg); color: var(--text);
transition: background var(--transition);
}function initTheme() {
const saved = localStorage.getItem('myext_dark');
if (saved === 'dark' || (!saved && matchMedia('(prefers-color-scheme:dark)').matches)) {
document.body.classList.add('dark');
}
}
function toggleDarkMode() {
const isDark = document.body.classList.toggle('dark');
localStorage.setItem('myext_dark', isDark ? 'dark' : 'light');
}const i18n = {
zh: {
welcome: '欢迎使用我的扩展',
send: '发送',
// ... all UI strings
},
en: {
welcome: 'Welcome to My Extension',
send: 'Send',
// ...
}
};
let lang = localStorage.getItem('myext_lang') || 'zh';
function t(k) { return i18n[lang]?.[k] || i18n.zh[k] || k; }
function toggleLanguage() {
lang = lang === 'zh' ? 'en' : 'zh';
localStorage.setItem('myext_lang', lang);
updateAllTexts(); // re-render all i18n-dependent UI
}When registering MCP tools, set description and parameters in the current user's language for better AI interaction.
Every extension should work well across different window sizes. Critical patterns:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />Use breakpoints to adapt layout at small sizes:
@media (max-width: 900px) {
/* stack layouts vertically, reduce padding */
}
@media (max-width: 600px) {
/* hide secondary elements, compact controls */
}Key responsive practices:
vw units for widths as fallback (e.g., width: 65vw; max-width: 360px)flex layouts with flex-wrap that naturally adaptdisplay: none)Extensions may be rendered inside an iframe (depending on SAP's configuration). Ensure:
window.location.pathname (works in both direct and iframe contexts):function getExtId() {
try {
const match = window.location.pathname.match(/\/extensions\/([^\/]+)/);
return match ? match[1] : 'unknown';
} catch(e) { return 'unknown'; }
}location.host (not hardcoded):const proto = location.protocol === 'https:' ? 'wss:' : 'ws:';
ws = new WebSocket(`${proto}//${location.host}/ws`);window.close() works in both direct and iframe contextswindow.top / window.parent assumptions — your extension may be the top-level windowWhen transparent: true is set in package.json, SAP creates a frameless transparent window. The extension must implement compact mode to work correctly.
From main.js, when extension.transparent is true:
{
frame: false,
transparent: true,
alwaysOnTop: true,
skipTaskbar: false,
hasShadow: false,
backgroundColor: 'rgba(0, 0, 0, 0)',
}/* Transparent backgrounds */
body.compact { background: transparent !important; }
html.compact { background: transparent !important; }
/* Drag regions — make structural elements draggable for frameless windows */
body.compact header,
body.compact footer,
body.compact #inputBar {
-webkit-app-region: drag;
}
/* Interactive elements MUST opt-out of drag */
body.compact button,
body.compact input,
body.compact textarea,
body.compact select,
body.compact a,
body.compact .compact-close-btn {
-webkit-app-region: no-drag;
}
/* Compact close button (red circle, top-right) */
.compact-close-btn { display: none; }
body.compact .compact-close-btn {
display: flex;
position: absolute;
top: 5px; right: 5px;
width: 20px; height: 20px;
background: rgb(255, 57, 57);
border: none; border-radius: 50%;
color: #fff;
align-items: center; justify-content: center;
font-size: 10px; cursor: pointer;
transition: 0.2s;
z-index: 100;
-webkit-app-region: no-drag;
}
body.compact .compact-close-btn:hover { background: #ec4141; }function checkCompactMode() {
if (window.innerHeight < 200) {
document.documentElement.classList.add('compact');
document.body.classList.add('compact');
} else {
document.documentElement.classList.remove('compact');
document.body.classList.remove('compact');
}
}
function closeWindow() { window.close(); }
checkCompactMode();
window.addEventListener('resize', checkCompactMode);The close button HTML must be placed at the body level (not nested inside containers), typically right after <body>:
<body>
<button class="compact-close-btn" onclick="closeWindow()" title="关闭窗口">
<i class="fa-solid fa-xmark"></i>
</button>
<!-- rest of content -->
</body>For transparent mini-widgets, you can also place the close button inside a content container and make it visible on hover — see sap-lx-music for this pattern.
If your extension needs to invoke custom protocol URLs (e.g., lxmusic://, myapp://), use a hidden iframe technique:
function invokeScheme(url) {
let iframe = document.getElementById('scheme-invoker');
if (!iframe) {
iframe = document.createElement('iframe');
iframe.id = 'scheme-invoker';
iframe.style.display = 'none';
document.body.appendChild(iframe);
}
iframe.src = url;
}This avoids window.open() popup blockers and works reliably inside Electron.
| Message Type | Direction | Purpose |
|---|---|---|
get_messages | → SAP | Request current message history |
messages_update | ← SAP | Message list updated |
broadcast_messages | ← SAP | Broadcast message update |
set_user_input | → SAP | Update user input text |
trigger_send_message | → SAP | Send current input as user message |
trigger_clear_message | → SAP | Clear all messages |
register_node_extension_mcp | → SAP | Register MCP tools (works for static AND Node.js) |
unregister_node_extension_mcp | → SAP | Unregister on page close |
mcp_registered | ← SAP | Confirmation of registration |
call_mcp_tool | ← SAP | AI agent calls a registered tool |
mcp_tool_result | → SAP | Return tool execution result |
trigger_close_extension | → SAP | Request extension window close |
/simple_chat)SAP exposes a stateless HTTP endpoint POST /simple_chat that extensions can call for one-off AI tasks — translation, summarization, quick Q&A, code generation — without going through the WebSocket chat flow and without adding messages to the conversation history.
This is ideal when your extension needs a quick, single-turn AI call: translate text, summarize content, extract keywords, classify input, etc.
/simple_chat vs WebSocket| Feature | /simple_chat HTTP API | WebSocket (trigger_send_message) |
|---|---|---|
| Conversation history | ❌ Stateless — no history | ✅ Full chat history |
| Messages shown in UI | ❌ Not added to chat | ✅ Rendered in message list |
| Use case | One-off: translate, summarize, classify | Multi-turn chat, agent tasks |
| Response format | OpenAI-compatible JSON / NDJSON stream | messages_update / broadcast_messages events |
| Speed | Uses SAP's fast client config | Uses current active model provider |
POST /simple_chat
Content-Type: application/jsonThe endpoint is on the same origin as the extension, so use a relative URL:
const res = await fetch('/simple_chat', { ... });{
"messages": [
{ "role": "system", "content": "You are a professional translator." },
{ "role": "user", "content": "Translate 'Hello world' to Chinese." }
],
"stream": false,
"temperature": 0.7
}| Field | Type | Required | Description |
|---|---|---|---|
messages | array | ✅ | Array of {role, content} objects (system/user/assistant) |
stream | boolean | ❌ (default false) | true for streaming, false for one-shot JSON response |
temperature | number | ❌ (default from settings) | 0–2, lower = more deterministic |
stream: false)Returns a standard OpenAI-compatible ChatCompletion JSON object:
{
"id": "chatcmpl-xxx",
"object": "chat.completion",
"created": 1234567890,
"model": "gpt-4o",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "你好世界"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 20,
"completion_tokens": 5,
"total_tokens": 25
}
}Access the result: data.choices[0].message.content
stream: true)Returns NDJSON (one JSON object per line), matching OpenAI's streaming format. Each line contains a delta chunk:
{"id":"chatcmpl-xxx","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}
{"id":"chatcmpl-xxx","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"你好"},"finish_reason":null}]}
{"id":"chatcmpl-xxx","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"世界"},"finish_reason":null}]}
{"id":"chatcmpl-xxx","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}Note: The stream does NOT send a [DONE] marker. Detect completion by checking choices[0].finish_reason.
/**
* Call SAP's /simple_chat for a one-off AI task.
* @param {Array} messages - [{role, content}, ...]
* @param {number} [temperature=0.7]
* @returns {Promise<object>} OpenAI-compatible ChatCompletion
*/
async function simpleChat(messages, temperature = 0.7) {
const res = await fetch('/simple_chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ messages, stream: false, temperature })
});
if (!res.ok) {
const err = await res.json();
throw new Error(err.error?.message || `HTTP ${res.status}`);
}
return await res.json();
}
// ---------- Practical Examples ----------
// Translation
async function translate(text, targetLang = 'Chinese') {
const res = await simpleChat([
{ role: 'system', content: `You are a translator. Translate to ${targetLang}. Reply ONLY with the translation, no explanations.` },
{ role: 'user', content: text }
]);
return res.choices[0].message.content;
}
// Summarization
async function summarize(text, maxWords = 50) {
const res = await simpleChat([
{ role: 'system', content: `Summarize in ≤${maxWords} words. Reply ONLY with the summary.` },
{ role: 'user', content: text }
]);
return res.choices[0].message.content;
}
// Quick classification
async function classify(text, labels) {
const res = await simpleChat([
{ role: 'system', content: `Classify into one of: ${labels.join(', ')}. Reply ONLY with the label.` },
{ role: 'user', content: text }
]);
return res.choices[0].message.content.trim();
}/**
* Call /simple_chat with streaming. Yields delta content strings.
* @param {Array} messages
* @param {number} [temperature=0.7]
* @returns {AsyncGenerator<string>} Yields delta content chunks
*/
async function* simpleChatStream(messages, temperature = 0.7) {
const res = await fetch('/simple_chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ messages, stream: true, temperature })
});
if (!res.ok) {
const err = await res.json();
throw new Error(err.error?.message || `HTTP ${res.status}`);
}
const reader = res.body.getReader();
const decoder = new TextDecoder();
let buf = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
buf += decoder.decode(value, { stream: true });
const lines = buf.split('\n');
buf = lines.pop(); // keep incomplete line in buffer
for (const line of lines) {
if (!line.trim()) continue;
try {
const chunk = JSON.parse(line);
const content = chunk.choices?.[0]?.delta?.content;
if (content) yield content;
if (chunk.choices?.[0]?.finish_reason === 'stop') return;
} catch(e) { /* ignore parse errors for partial lines */ }
}
}
}
// Usage: render streaming response into an element
const el = document.getElementById('output');
el.textContent = '';
for await (const chunk of simpleChatStream([
{ role: 'user', content: 'Write a haiku about coding.' }
])) {
el.textContent += chunk;
}On error, the endpoint returns a JSON object with an error field:
{
"error": {
"message": "No model providers configured",
"type": "server_error",
"code": 500
}
}Always check res.ok and parse the error body.
/simple_chat/simple_chat)./simple_chat is for your extension to call the AI, not the other way around.{owner}_{repo} (e.g., heshengtao_sap-example)beforeunload handler to send unregister_node_extension_mcpregister_node_extension_mcp message type name is historical; it works over WebSocket from any extension. Always follow the three-stage lifecycle: registerMcpTools() on WS open, handleMcpCall() on tool call, unregisterMcpTools() on beforeunloadcdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css). Relative paths like ../../fontawesome/ do NOT work for Node.js extensions (they're served from Express, not from SAP's static directory):root and body.dark. Do NOT force SAP's theme colors-webkit-app-region: drag, frameless windows cannot be moved. Without -webkit-app-region: no-drag on interactive elements, buttons become unclickableStudy these real extensions for patterns:
assets/static-template/ — Complete starter template for static extensionsassets/node-template/ — Complete starter template for Node.js extensionsreferences/package-json-spec.md — Complete package.json field referencereferences/node-entry-spec.md — Node.js entry point and lifecycle specification© heshengtao, AGPL-3.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 7 other files (references, assets) in skills/sap-extension-creator of heshengtao/super-agent-party.
Open the folder on GitHubat commit bfd9309
Sap Extension Creator next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Sap Extension Creator this skillheshengtao/super-agent-party | 2.7k | — | ~6k | Automated safety check: Pass | AGPL-3.0 | |
| Managing MCP IndexComfy-Org/workflow_templates | 1.3k | — | ~1.9k | Automated safety check: Notes | MIT | |
| Create Docsvictorgarciaesgi/nuxt-typed-router | 413 | 2 repos | ~2.8k | Automated safety check: Pass | MIT | |
| Frontend Build Timing Auditopenops-cloud/openops | 1.1k | — | ~2.3k | Automated safety check: Pass | Custom licence | |
| Better Iconsdtsola/xiaoyaosearch | 1k | 2 repos | ~895 | Automated safety check: Pass | Custom licence | |
| Orchardcore Asset ManagerOrchardCMS/OrchardCore | 8.2k | — | ~1.5k | Automated safety check: Pass | BSD-3-Clause |
Comfy-Org/workflow_templates
Builds and maintains templates/index.mcp.json for Comfy Cloud MCP tools.
victorgarciaesgi/nuxt-typed-router
Create complete documentation sites for projects. An agent skill from victorgarciaesgi/nuxt-typed-router.
openops-cloud/openops
Detects and diagnoses chunk-evaluation timing bugs in the Vite/rolldown production build of react-ui (works-in-dev / broken-in-build i18n regressions, missing UI labels, module-scope t()…
dtsola/xiaoyaosearch
Searches more than 200 Iconify icon libraries and fetches icons as SVG from a command line tool or an MCP server.
OrchardCMS/OrchardCore
Builds, watches, and manages frontend assets in OrchardCore.
arvindrk/extract-design-system
Extract design primitives from a public website and generate starter token files for your project.
Categories
Create Super Agent Party (SAP) extensions. An agent skill from heshengtao/super-agent-party. Sap Extension Creator is an agent skill from heshengtao/super-agent-party. Create Super Agent Party (SAP) extensions.
Sap Extension Creator fits situations like: requests like create a new SAP extension; build an extension for Super Agent Party; scaffold a plugin; make a chat UI extension.
Run `npx skills add heshengtao/super-agent-party --skill sap-extension-creator -a claude-code`. Or copy the skill folder (skills/sap-extension-creator in heshengtao/super-agent-party) into .claude/skills/sap-extension-creator in your project. Claude Code loads it when a task matches its description.
Run `npx skills add heshengtao/super-agent-party --skill sap-extension-creator -a codex`. Or copy the skill folder (skills/sap-extension-creator in heshengtao/super-agent-party) into .agents/skills/sap-extension-creator in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add heshengtao/super-agent-party --skill sap-extension-creator -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/sap-extension-creator, .gemini/skills/sap-extension-creator, .github/skills/sap-extension-creator and .opencode/skills/sap-extension-creator in your project.
Going by SKILL.md and its folder, Sap Extension Creator needs JavaScript for the scripts in its folder and the command-line tools its instructions call (npm and node). Our summary lists: Node.js.
SKILL.md names 3 domains. In commands or code: github.com, gitee.com and cdnjs.cloudflare.com; the agent is likely to contact these when it follows the instructions. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Sap Extension Creator is published under the AGPL-3.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 6k tokens (SKILL.md is roughly 24k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 2.6k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Sap Extension Creator: Managing MCP Index (Comfy-Org/workflow_templates, 1.3k stars), Create Docs (victorgarciaesgi/nuxt-typed-router, 413 stars), Frontend Build Timing Audit (openops-cloud/openops, 1.1k stars) and Better Icons (dtsola/xiaoyaosearch, 1k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
heshengtao (a GitHub user) maintains it in heshengtao/super-agent-party, which has 2,728 GitHub stars. The repository was last updated on October 10, 2026.
Source: heshengtao/super-agent-party on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.