pwa-sticker-mcp
PWA Sticker MCP · 共有スタンプ
人とAIが同じPWAスタンプライブラリを共用できるようにする:人はドロワーでクリックして送信し、モデルはMCP経由で同じ画像を送信する。
人間向けのPWAドロワーとAI向けのMCPサーバーは、1つのスタンプライブラリと1つの添付契約を共有します。
この公開版は、実際の家庭用PWAの現役機能から独立して抽出され、最も有用な部分を保持しています:
PWA スタンプドロワー:アップロード、遅延読み込み、最近使った順の並べ替え、長押しまたはキーボードで管理に入る、削除
iOS に優しい正方形グリッド:スクロールする grid で崩れやすい
aspect-ratioに依存しない静的 WebP ドロワープレビュー:
ffmpegがある場合、192px の先頭フレームを自動生成し、実際の送信は引き続き元画像または元 GIFMCP の3つのツール:
list_stickers、send_sticker、add_sticker画像のみのメッセージ:
{ text: "", attachments: [...] }を送信し、ダミーのプレースホルダーテキストを作る必要はありませんすぐに実行できるローカル Relay/demo を備え、完全なループを先に確認してから自分のチャットバックエンドに接続できます
リポジトリには、私たちの家族のスタンプ画像、チャット履歴、ドメイン、アカウント、認証情報は含まれていません。
まず実行する
Node.js 20+ が必要です;ffmpeg は任意です。
npm install
npm run demohttp://127.0.0.1:8787 を開き、画像を1枚追加してクリックすると、ページに送信したばかりの画像のみのメッセージが表示されます。
データはデフォルトでプロジェクト内の .data/ に書き込まれ、.gitignore で除外されています。
この実行は同時に MCP へ利用可能な Relay を提供します。別のターミナルを開いてください:
STICKER_RELAY_URL=http://127.0.0.1:8787 npm run mcpRelated MCP server: Firmament Open Brain
MCP クライアントに接続する
Claude Desktop、Claude Code、その他 stdio MCP をサポートするクライアントは次を使用できます:
{
"mcpServers": {
"stickers": {
"command": "node",
"args": ["/absolute/path/to/pwa-sticker-mcp/src/mcp-server.js"],
"env": {
"STICKER_RELAY_URL": "https://chat.example.com",
"STICKER_TOKEN": "your-relay-token",
"STICKER_STICKERS_PATH": "/api/stickers",
"STICKER_UPLOAD_PATH": "/api/upload",
"STICKER_SEND_PATH": "/api/send"
}
}
}
}ツールの意味:
list_stickers(query?):共有ライブラリを一覧表示し、名前でフィルタリングできますsend_sticker(query):id、完全名、または一意のキーワードで一致するものを送信しますadd_sticker(path, name?):モデルが動作するマシン上のローカル画像を共有ライブラリに登録しますが、送信はしません
キーワードが複数のスタンプに一致した場合、ツールはモデルに絞り込むよう求め、勝手に1つを選ぶことはありません。
ドロワーを既存の PWA に組み込む
モジュールとスタイルを導入:
<link rel="stylesheet" href="/sticker-drawer.css">
<div id="stickerDrawer"></div>
<button
id="stickerButton"
type="button"
aria-controls="stickerDrawer"
aria-expanded="false"
aria-pressed="false"
>
表情包
</button>
<script type="module">
import { StickerDrawer } from '/sticker-drawer.js'
new StickerDrawer({
root: document.querySelector('#stickerDrawer'),
trigger: document.querySelector('#stickerButton'),
apiBase: 'https://chat.example.com',
headers: () => ({ Authorization: `Bearer ${getRelayToken()}` }),
async onSend(attachment) {
await sendMessage({ text: '', attachments: [attachment] })
},
onNotice(message, kind) {
showToast(message, kind)
}
})
</script>onSend を省略すると、コンポーネントは同じ payload を send エンドポイントに POST します。エンドポイントは名前を変更できます:
new StickerDrawer({
root,
trigger,
endpoints: {
stickers: '/app/stickers',
upload: '/app/upload',
send: '/app/send'
}
})コンポーネントは中立的な CSS 変数を使用しており、組み込む側に demo の色を採用することを要求しません:
:root {
--psm-surface: #171717;
--psm-surface-muted: #242424;
--psm-ink: #fafafa;
--psm-muted: #b8b8b8;
--psm-accent: #f1b657;
--psm-danger: #e26363;
--psm-line: #343434;
}Relay API 契約
既存のバックエンドは demo server を使う必要はなく、次の5つのリクエストを実装するだけで済みます:
GET /api/stickers
POST /api/upload?name=<filename> raw image body
POST /api/stickers register uploaded metadata
POST /api/stickers/<id>/use update recent-use order
DELETE /api/stickers/<id>
POST /api/send send an image attachmentGET /api/stickers は次を返します:
{
"stickers": [
{
"id": "abc123",
"name": "wave hello",
"url": "/uploads/wave.gif",
"thumb_url": "/uploads/sticker-thumb-wave.webp",
"mime": "image/gif",
"width": 320,
"height": 240,
"last_used": 1787800000
}
]
}POST /api/send の中心的な payload:
{
"text": "",
"attachments": [
{
"url": "/uploads/wave.gif",
"name": "wave hello",
"mime": "image/gif",
"kind": "image",
"width": 320,
"height": 240
}
]
}チャット API のフィールドが異なる場合は、PWA の onSend で一度変換し、MCP の
STICKER_SEND_PATH を上記の payload を受け入れる軽量なアダプターエンドポイントに向ければよい。
ローカル Relay 設定
HOST=127.0.0.1 \
PORT=8787 \
STICKER_DATA_DIR=/path/to/data \
STICKER_TOKEN=choose-a-token \
npm run demoデフォルトでは
127.0.0.1のみをリッスンしますSTICKER_TOKENを設定すると、すべての/api/*リクエストで同じ token が要求されます:MCP は Bearer を使用します;demo のホームページを開くと、ローカルサーバーは同じ値の HttpOnly/SameSite cookie を書き込むため、ブラウザの demo は引き続き直接使用できますSTICKER_FFMPEG=offでサムネイル生成を無効にできます;ffmpegがインストールされていない場合も、自動的に元画像プレビューにフォールバックしますライブラリのエントリを削除しても、アップロード済みの元画像は削除されません。古いメッセージがまだそれを参照している可能性があるためです
テスト
npm test
npm run check焦点を絞ったテストは、共有ライブラリの並べ替え/削除/重複登録、「ローカル画像 → アップロード → ライブラリ登録 → MCP と同じ構造の送信 payload」の完全なパスをカバーしています。
成り立ちとクレジット
それは家庭向け AI コンパニオンプロジェクトから生まれました。人はスマートフォンの PWA でスタンプを集められ、AI も、トーンが合ったときに同じスタンプセットを自然に送れます。
公開版は 词词 が発起しライセンスを供与しました;Sunnymilk(Sunny、家庭内の Codex) が本番実装から抽出・汎用化し、MCP シェルと独立した demo を補完しました。
オープンソース版は Cici が発起し、Sunnymilk(Sunny、家庭内の Codex) が抽出・汎用化しました。
ライセンス
MIT
This server cannot be deployed
Maintenance
Related MCP Connectors
Persistent personal memory for AI assistants — save, search, and recall across every MCP client.
Cross-tool persistent memory and context for AI assistants over MCP.
- JustOnceOAuthai.justonce
Persistent memory for AI assistants — one shared, OAuth-secured vault for every MCP client.
Your memory, everywhere AI goes. Build knowledge once, access it via MCP anywhere.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI to send expressive stickers based on conversation context, with a built-in UI for managing stickers.58MIT
- FlicenseNot gradedqualityCmaintenanceEnables each user to have a private, per-user memory store that persists across AI tools, allowing them to store, recall, search, list, and delete memories via MCP.-
- AlicenseNot gradedqualityBmaintenanceLocal-first custom sticker library for MCP agents, enabling image import, auto-tagging, search, and context-aware retrieval via standard MCP tools.27MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI chat clients to search, manage, and send custom meme/sticker images through MCP, with images stored in SQLite and served via public URLs; supports MCP Apps displaying images inline in chat.2MIT