Skip to main content
ClaudeWave
Skill2.4k estrellas del repoactualizado today

sap-extension-creator

The sap-extension-creator skill scaffolds new extensions for Super Agent Party, a platform for building custom chat interfaces and tools. Use this when users need to build either static HTML/CSS/JS frontends or full-stack Node.js extensions with backend logic, including setting up package.json configuration, UI templates, and optional MCP tool registration for AI integration.

Instalar en Claude Code
Copiar
git clone --depth 1 https://github.com/heshengtao/super-agent-party /tmp/sap-extension-creator && cp -r /tmp/sap-extension-creator/skills/sap-extension-creator ~/.claude/skills/sap-extension-creator
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

SKILL.md

# SAP Extension Creator

## Overview

Create Super Agent Party extensions—self-contained packages that extend the platform with custom chat UI and tools. Two modes are supported:

- **Static extension**: Pure HTML/CSS/JS frontend, served directly by SAP from the extension folder
- **Node.js extension**: Full-stack with Express backend, auto-managed by SAP (`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).

## Quick Decision Tree

```
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
```

## Core Files Every Extension Needs

| 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` |

## Workflow

### Step 1: Gather Requirements

Ask the user:

1. **Extension name?** (hyphen-case, e.g., `my-weather-widget`)
2. **Description?** (one sentence)
3. **Static or Node.js?** (Node.js only if backend logic/server-side code is needed)
4. **For Node.js: what npm dependencies?**
5. **Should it register custom tools for the AI?** (works in both static and Node.js modes via WebSocket MCP)
6. **GitHub repository URL?** (optional, for updates)
7. **Transparent window?** (frameless, always-on-top — for mini widgets like music controllers)
8. **Default window size?** (width/height in pixels)

### Step 2: Scaffold the Extension

Use the templates in `assets/` as starting points:

- **Static**: Copy `assets/static-template/`
- **Node.js**: Copy `assets/node-template/`

Create the extension directory under the workspace (user will later install it into SAP's `extensions/` folder).

### Step 3: Write package.json

See `references/package-json-spec.md` for the complete field reference. Minimum:

```json
{
  "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:
```json
{
  "main": "index.js",
  "nodePort": 0,
  "dependencies": { "express": "^5.1.0" }
}
```

For transparent/frameless widgets (e.g., mini music controllers, floating panels):
```json
{
  "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.

### Step 4: Write index.html

The HTML page is rendered inside an Electron BrowserWindow (either directly or via an iframe). Key patterns:

- **Self-contained**: The extension is a single HTML file with all CSS/JS inlined or loaded from CDN. For Node.js extensions, static assets are served from the extension directory.
- **Font Awesome**: Use CDN to ensure reliable loading in both static and Node.js modes:
  ```html
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
  ```
  Avoid relative paths like `../../fontawesome/` — these may work for static extensions but break for Node.js extensions (different serving paths).
- **Dark/Light mode**: Always support both (see "Theme & i18n" section below).
- **i18n (Chinese/English)**: Always support bilingual UI (see "Theme & i18n" section below).
- **WebSocket connection**: Connect to `ws://host/ws` for messaging and MCP.
- **Extension ID**: Parse `window.location.pathname` for `/extensions/{ext_id}/`.
- **Message rendering**: Listen for `messages_update` and `broadcast_messages` events.
- **Send user input**: Send `set_user_input` then `trigger_send_message`.

### Step 5: Write index.js (Node.js only)

See `references/node-entry-spec.md` for the full protocol. The entry point:

1. Receives a port number via `process.argv[2]`
2. Starts an Express server on that port at `127.0.0.1`
3. Serves static files from its own directory
4. Exposes a `/health` endpoint for readiness checks
5. SAP reverse-proxies requests to the extension

### Step 6: Implement Tool Registration (optional, works in both modes)

Extensions 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:

```js
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:

```js
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:

```js
function unregisterMcpTools() {
  if (ws && ws.readyState === WebSocket.OPEN) {
    ws.send(JSON.stringify({ type: 'unregister_node_ext