Skip to main content

open-mcp-apps-persistent-ui

Build and manage persistent, reusable AI-generated UI components with the open-mcp-apps MCP engine

الانتقال إلى التثبيت

معلومات المصدر

المستودع
reason-machines/mcp-skills
آخر نشاط في المصدر
٣١ يوليو ٢٠٢٦ في ٢٣:٢٣
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٧
التفرعات
٢

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
open-mcp-apps-persistent-ui
description
Build and manage persistent, reusable AI-generated UI components with the open-mcp-apps MCP engine
triggers
["create a persistent UI component","build an MCP app widget","make a reusable interface for","set up open-mcp-apps","create a kanban board that persists","build a habit tracker with open-mcp-apps","write a custom MCP app","install an app into open-mcp-apps"]
# open-mcp-apps Persistent UI Skill > Skill by [ara.so](https://ara.so) — MCP Skills collection. ## Overview **open-mcp-apps** is an MCP server that enables AI assistants to create persistent, reusable UI components. When a user asks for a UI (kanban board, habit tracker, reading list), the AI writes a single-file HTML app, saves it to a registry, and binds it to persistent SQLite-backed data. The app persists across conversations and hosts. Key capabilities: - **App registry**: AI can write and save new HTML apps on demand - **Persistent data**: Apps bind to versioned SQLite collections with idempotent mutations - **Shell runtime**: Serves apps with MCP App bridge, host theming, and data API - **17 built-in apps**: Ready-made components (companion, study cards, family week planner) ## Installation ### Standard Installation (One Command) ```bash curl -fsSL https://raw.githubusercontent.com/2nd1st/open-mcp-apps/main/install.sh | sh ``` The installer: - Prompts for which hosts to register (Claude Desktop, Claude Code, Codex) - Creates a fixed per-user data store (shared across hosts) - Registers the MCP server in each host's config **Skip prompts** (auto-yes): ```bash curl -fsSL https://raw.githubusercontent.com/2nd1st/open-mcp-apps/main/install.sh | sh -s -- --yes ``` **Target specific host**: ```bash curl -fsSL https://raw.githubusercontent.com/2nd1st/open-mcp-apps/main/install.sh | sh -s -- --host codex ``` ### Manual Installation (Clone) ```bash git clone https://github.com/2nd1st/open-mcp-apps cd open-mcp-apps node install.mjs ``` ### Post-Install 1. **Fully quit and reopen** the host (Cmd-Q on macOS, not just close window) 2. **First-run permissions**: When tools appear, click "Always allow" for each 3. **Batch permissions**: Settings → Connectors → open-mcp-apps → Tool permissions ### Data Store Location - **macOS**: `~/Library/Application Support/open-mcp-apps/open-mcp-apps.db` - **Windows**: `%APPDATA%\open-mcp-apps\open-mcp-apps.db` - **Linux**: `$XDG_DATA_HOME/open-mcp-apps/open-mcp-apps.db` or `~/.local/share/open-mcp-apps/` ### Uninstall ```bash node uninstall.mjs # Unregister, keep data node uninstall.mjs --purge # Delete everything (irreversible) node uninstall.mjs --check # Preview changes ``` **Full reset**: Delete the `.db` file (and `-wal`/`-shm` siblings) while host is fully quit. ## Core MCP Tools The server exposes these tools to the AI: ### `list_apps` Lists all installed apps with metadata. ```json { "name": "list_apps" } ``` Returns: Array of apps with `name`, `title`, `description`, `version`, `author`, `trust_tier`. ### `get_app` Retrieves an app's full source code. ```json { "name": "get_app", "arguments": { "name": "kanban-board" } } ``` ### `get_app_guide` Retrieves the authoring guide the AI should read before writing a new app. ```json { "name": "get_app_guide" } ``` Returns: Complete guide with `window.oma` API, design patterns, constraints. ### `save_app` Saves a new or updated app to the registry. ```json { "name": "save_app", "arguments": { "name": "habit-tracker", "title": "Habit Tracker", "description": "Track daily habits with streaks", "html": "<html>...</html>", "version": "1.0.0", "collections": ["habits"] } } ``` ### `delete_app` Removes an app from the registry (data persists). ```json { "name": "delete_app", "arguments": { "name": "old-app" } } ``` ### `open_app` (or `open_<name>`) Opens an app with optional initial items. ```json { "name": "open_kanban", "arguments": { "initial_items": { "tasks": [ {"id": "1", "title": "Review PR", "status": "todo"}, {"id": "2", "title": "Fix bug", "status": "in-progress"} ] } } } ``` The AI uses this after creating or when reopening an app. ## Common Patterns for AI Agents ### Pattern 1: Create a New App from User Request When user says: "make me a reading tracker" ``` 1. Call get_app_guide to read the authoring contract 2. Write single-file HTML app following the guide 3. Call save_app with the HTML and collections list 4. Call open_reading_tracker with sample initial_items ``` Example HTML structure for an app: ```html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Reading Tracker</title> </head> <body> <div class="container"> <h1>My Reading List</h1> <ul id="books"></ul> <form id="add-form"> <input id="title" placeholder="Book title"> <input id="author" placeholder="Author"> <button type="submit">Add</button> </form> </div> <script> // window.oma is injected by the engine const { items, mutate, subscribe } = window.oma; // Load collection const books = items('books'); // Render function render() { const list = document.getElementById('books'); list.innerHTML = books.map(b => `<li>${b.title} by ${b.author} <button onclick="remove('${b.id}')">✕</button></li>` ).join(''); } // Add book document.getElementById('add-form').onsubmit = (e) => { e.preventDefault(); mutate('books', { command: 'add_book', item: { id: crypto.randomUUID(), title: document.getElementById('title').value, author: document.getElementById('author').value } }); e.target.reset(); }; // Remove book window.remove = (id) => { mutate('books', { command: 'remove_book', item_id: id }); }; // Subscribe to changes subscribe('books', render); render(); </script> </body> </html> ``` ### Pattern 2: Reuse Existing App When user says: "show me my reading tracker again" ``` 1. Call list_apps to check if 'reading-tracker' exists 2. If exists: call open_reading_tracker (no initial_items needed) 3. If not: follow Pattern 1 to create it ``` ### Pattern 3: Update an App When user says: "add a rating field to my reading tracker" ``` 1. Call get_app with name="reading-tracker" 2. Modify the HTML to add rating functionality 3. Call save_app with incremented version 4. Call open_reading_tracker to show updated version ``` ### Pattern 4: Install from Library The built-in library app shows 17 ready-made apps. To use them: ``` 1. User opens library (open_library tool) 2. User clicks install in the library UI 3. App is installed and immediately available ``` Or programmatically: ```bash # Install a custom app from file node install-app.mjs ./my-custom-app.html node install-app.mjs ./untrusted-app.html --sandboxed ``` ## window.oma API Reference Every app has access to `window.oma` with these methods: ### `items(collection_name)` Returns array of all items in the collection. ```javascript const tasks = window.oma.items('tasks'); // Returns: [{id: '1', title: 'Task 1', ...}, ...] ``` ### `mutate(collection_name, command)` Idempotently mutates the collection. ```javascript window.oma.mutate('tasks', { command: 'add_task', command_id: crypto.randomUUID(), // Optional, auto-generated expected_version: window.oma.version('tasks'), // OCC item: { id: crypto.randomUUID(), title: 'New task', status: 'todo' } }); ``` ### `subscribe(collection_name, callback)` Listens for changes. ```javascript window.oma.subscribe('tasks', () => { console.log('Tasks changed, re-render'); render(); }); ``` ### `version(collection_name)` Returns current version number (for optimistic concurrency control). ```javascript const v = window.oma.version('tasks'); // e.g., 42 ``` ### `theme` Object with `mode` ('light' or 'dark') and design tokens. ```javascript if (window.oma.theme.mode === 'dark') { document.body.classList.add('dark'); } ``` ### File API (for apps with `capabilities: ['files']`) ```javascript // Upload file window.oma.files.upload(file_object).then(file_id => { console.log('Uploaded:', file_id); }); // Get file metadata window.oma.files.get(file_id).then(metadata => { console.log(metadata.name, metadata.size, metadata.mime_type); }); // Download URL const url = window.oma.files.url(file_id); // Returns: /files/<file_id> // List all files window.oma.files.list().then(files => { files.forEach(f => console.log(f.name)); }); // Delete window.oma.files.delete(file_id); ``` ## Configuration ### Environment Variables Set in the `env` block of your host's MCP server entry: ```json { "mcpServers": { "open-mcp-apps": { "command": "node", "args": ["/path/to/open-mcp-apps/src/server.mjs"], "env": { "OMA_VIEWER": "0", "PORT": "9000" } } } } ``` - **`OMA_VIEWER`**: Set to `0` to disable the browser viewer entirely - **`PORT`**: Change the viewer port (default: `8787`) ### Browser Viewer The viewer runs at `http://127.0.0.1:8787` (or custom `PORT`). It serves: - `/view/<app-name>` - Individual app pages - `/mcp` - Stateless HTTP MCP endpoint **Security**: Bound to `127.0.0.1` only. No password because any local process can access the SQLite file directly. Treat tunnel URLs as secrets if you expose it. ## Advanced: Writing Apps Manually For apps beyond the AI's context window, write in your own editor: ```bash # Create my-app.html with full bundling/tooling # Keep it ≤200 KB, self-contained, no network requests # Install as trusted (full capabilities) node install-app.mjs ./my-app.html # Install as sandboxed (no capabilities) node install-app.mjs ./my-app.html --sandboxed # List provenance node install-app.mjs --list ``` **Key constraints**: - Single HTML file, ≤200 KB - No external network requests - Engine injects CSS, design tokens, and `window.oma` - Provenance (trusted vs sandboxed) cannot be changed after install
عرض على GitHub
ملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub