diff --git a/BRAINSTORM-mcp-app-2026-02-22.md b/BRAINSTORM-mcp-app-2026-02-22.md new file mode 100644 index 00000000..e9e90a1f --- /dev/null +++ b/BRAINSTORM-mcp-app-2026-02-22.md @@ -0,0 +1,285 @@ +# BRAINSTORM: Scribe as MCP App in Claude Desktop + +**Mode:** Architecture | **Depth:** Deep (8 questions) | **Date:** 2026-02-22 + +--- + +## Context + +MCP Apps is a new extension to the Model Context Protocol that lets any MCP server deliver interactive UI (HTML/JS/CSS) within a sandboxed iframe inside Claude Desktop's chat window. Scribe already has a complete browser-mode fallback (IndexedDB via Dexie) that mirrors its Tauri backend 1:1 — making it uniquely well-positioned for this integration. + +### User Answers (8 Expert Questions) + +| # | Question | Answer | +|---|----------|--------| +| 1 | Primary use case | Write alongside Claude — draft/edit notes while chatting | +| 2 | Data sharing | Undecided — wants pros/cons | +| 3 | UI scope | Full app (ambitious) | +| 4 | AI bridge | Full tool integration — notes, search, organize as MCP tools | +| 5 | Bundling | Single HTML file (vite-plugin-singlefile) | +| 6 | Code location | In Scribe repo (monorepo) — `src/mcp-server/` | +| 7 | Discovery | Both: local custom connector (dev) + published (production) | +| 8 | Deploy v1 | Local only (`npm run serve`) | + +--- + +## Architecture Overview + +``` +┌──────────────────────────────────────────────────────────────┐ +│ Claude Desktop / claude.ai │ +│ ┌────────────────────────────────────────────────────────┐ │ +│ │ Chat Conversation │ │ +│ │ ┌──────────────────────────────────────────────────┐ │ │ +│ │ │ MCP App Iframe (sandboxed) │ │ │ +│ │ │ ┌──────────────────────────────────────────────┐│ │ │ +│ │ │ │ SCRIBE (browser mode) ││ │ │ +│ │ │ │ - Full React UI ││ │ │ +│ │ │ │ - IndexedDB persistence (Dexie) ││ │ │ +│ │ │ │ - CodeMirror editor ││ │ │ +│ │ │ │ - All features except Tauri-native ││ │ │ +│ │ │ └──────────────────────────────────────────────┘│ │ │ +│ │ │ ↕ App.connect() / postMessage │ │ │ +│ │ └──────────────────────────────────────────────────┘ │ │ +│ └────────────────────────────────────────────────────────┘ │ +│ ↕ MCP Protocol (HTTP) │ +│ ┌────────────────────────────────────────────────────────┐ │ +│ │ Scribe MCP Server (localhost:3001) │ │ +│ │ - Registers tools (create/search/edit notes) │ │ +│ │ - Serves bundled HTML as ui:// resource │ │ +│ │ - Express + StreamableHTTP transport │ │ +│ └────────────────────────────────────────────────────────┘ │ +└──────────────────────────────────────────────────────────────┘ +``` + +--- + +## Quick Wins (< 2 hours each) + +1. **Proof of concept: static editor** — Bundle `vite build` + `vite-plugin-singlefile`, serve from a minimal MCP server, verify it renders in Claude Desktop +2. **Platform detection for iframe** — Extend `platform.ts` to detect MCP App iframe context (no `__TAURI__`, inside iframe) +3. **Single "open-scribe" tool** — Register one tool that renders the full Scribe UI + +## Medium Effort (4-8 hours) + +4. **Full tool suite** — Map `browserApi` operations to MCP tools: `create-note`, `search-notes`, `list-projects`, `get-note`, `update-note` +5. **Bidirectional context** — Use `app.updateContext()` to push current note content to Claude's context window +6. **Vite build pipeline** — Add `mcp-app` build target with singlefile plugin alongside existing Tauri/Vite builds +7. **iframe-specific CSS** — Handle sandboxed iframe viewport: no title bar, constrained height, responsive layout + +## Long-term (Future sessions) + +8. **Data sharing via MCP server** — Server reads Scribe's SQLite DB for unified data +9. **Published connector** — Package and list in Claude's connector directory +10. **Theme sync** — Detect Claude Desktop's dark/light mode and match Scribe's theme +11. **Collaborative editing** — Claude writes directly into the editor via tool calls + +--- + +## Data Strategy: Pros & Cons + +### Option A: Independent (Sandboxed IndexedDB) + +| Aspect | Detail | +|--------|--------| +| **Pro** | Zero setup — browser mode "just works" in iframe | +| **Pro** | No filesystem access needed — fully sandboxed | +| **Pro** | Each Claude conversation gets its own workspace | +| **Con** | Notes created in Claude Desktop are isolated from desktop Scribe | +| **Con** | No cross-session persistence (iframe storage may be ephemeral) | +| **Complexity** | Low — existing `browserApi` works unchanged | + +### Option B: Shared via MCP Server + +| Aspect | Detail | +|--------|--------| +| **Pro** | Unified data — notes visible in both desktop Scribe and Claude Desktop | +| **Pro** | MCP server can read/write Scribe's SQLite DB directly | +| **Pro** | Claude's MCP tools operate on real data | +| **Con** | Requires server to locate and access Scribe's DB file | +| **Con** | Concurrent access (Tauri + MCP server) needs WAL mode or locking | +| **Con** | More complex — server becomes a data layer | +| **Complexity** | Medium — new DB access layer in server | + +### Option C: Export/Import Bridge + +| Aspect | Detail | +|--------|--------| +| **Pro** | Clean separation — explicit user action to sync | +| **Pro** | No concurrency issues | +| **Con** | Manual friction — not seamless | +| **Complexity** | Low | + +### Recommendation + +**Start with Option A (independent)** for v1 — it works immediately with zero changes to existing code. Plan for **Option B** in v2 when the feature proves valuable. The MCP server already has access to tools; adding SQLite read access is a natural evolution. + +--- + +## MCP Tool Design + +### Core Tools (v1) + +| Tool | Description | UI? | +|------|-------------|-----| +| `open-scribe` | Opens the full Scribe editor in-conversation | Yes (primary) | +| `create-note` | Creates a note with title/content | No (text result) | +| `search-notes` | Full-text search across notes | No (text result) | +| `get-note` | Retrieve a specific note by ID or title | No (text result) | +| `list-notes` | List recent/all notes | No (text result) | + +### Extended Tools (v2) + +| Tool | Description | UI? | +|------|-------------|-----| +| `edit-note` | Update existing note content | Yes (opens editor to note) | +| `list-projects` | Show all projects | No | +| `create-project` | Create a new project | No | +| `search-tags` | Find notes by tag | No | +| `daily-note` | Open/create today's daily note | Yes (opens editor) | +| `export-note` | Export note as markdown/PDF | No (text result) | + +### Tool Result → UI Flow + +``` +User: "Open my writing app" +Claude: Calls open-scribe tool + → Host fetches ui://scribe/app.html + → Renders full Scribe in iframe + → app.ontoolresult receives initial state + → User writes alongside Claude + +User: "Create a note about our discussion" +Claude: Calls create-note tool with title + content + → Returns note ID + confirmation + → If Scribe is open, app receives tool result and navigates to new note +``` + +--- + +## Build Pipeline + +### New Scripts (package.json) + +```json +{ + "scripts": { + "mcp:build": "INPUT=src/mcp-app/mcp-app.html vite build --config vite.mcp.config.ts", + "mcp:serve": "npx tsx src/mcp-server/server.ts", + "mcp:dev": "npm run mcp:build && npm run mcp:serve" + } +} +``` + +### Vite Config (vite.mcp.config.ts) + +Separate Vite config for MCP App build: +- Uses `vite-plugin-singlefile` to inline all JS/CSS +- Excludes Tauri-specific imports +- Targets `src/mcp-app/mcp-app.html` as entry +- Outputs to `dist-mcp/` + +### Directory Structure + +``` +scribe/ +├── src/ +│ ├── renderer/ # Existing React app +│ │ └── src/ +│ │ ├── lib/ # browserApi, platform, etc. +│ │ └── components/ +│ ├── mcp-app/ # MCP App entry point +│ │ ├── mcp-app.html # HTML entry (loads React app) +│ │ └── mcp-app.ts # App class + host communication +│ └── mcp-server/ # MCP server +│ ├── server.ts # Express + MCP SDK server +│ ├── tools.ts # Tool definitions +│ └── resources.ts # UI resource handler +├── src-tauri/ # Existing Tauri backend +├── vite.config.ts # Existing (Tauri build) +├── vite.mcp.config.ts # New (MCP App build) +├── dist/ # Existing (Tauri frontend) +└── dist-mcp/ # New (MCP bundled HTML) +``` + +--- + +## Iframe Constraints & Adaptations + +### What Works in Sandboxed Iframe +- React rendering +- IndexedDB / Dexie persistence +- CodeMirror editor +- Zustand state management +- CSS / Tailwind styling +- localStorage (preferences) +- KaTeX math rendering +- Markdown rendering (react-markdown) + +### What Needs Adaptation +| Feature | Desktop | MCP App | Solution | +|---------|---------|---------|----------| +| Title bar / drag region | Tauri overlay | N/A | Hide via CSS class | +| File dialogs | Tauri native | N/A | Disable export buttons | +| Terminal panel | xterm.js + PTY | N/A | Hide terminal tab | +| Font installation | Homebrew | N/A | Use web-safe fonts only | +| Clipboard | Tauri API | navigator.clipboard | Already has browser fallback | +| Window resize | Tauri window | Iframe resize | CSS max-height | +| Global shortcuts | Tauri shortcuts | N/A | Use in-app shortcuts only | + +### New Platform Detection + +```typescript +// src/renderer/src/lib/platform.ts (extended) +export const isMcpApp = (): boolean => { + return isBrowser() && window.self !== window.top // in iframe +} + +export const getPlatform = (): 'tauri' | 'browser' | 'mcp-app' => { + if (isTauri()) return 'tauri' + if (isMcpApp()) return 'mcp-app' + return 'browser' +} +``` + +--- + +## Security Considerations + +- **CSP**: `vite-plugin-singlefile` inlines everything, avoiding cross-origin issues +- **IndexedDB isolation**: Each origin gets separate storage — MCP iframe will have its own +- **No credential exposure**: Scribe stores no API keys in browser mode (AI features use Tauri backend) +- **Tool authorization**: Host manages tool call approvals — users see each tool invocation + +--- + +## Risk Assessment + +| Risk | Impact | Likelihood | Mitigation | +|------|--------|------------|------------| +| Bundle too large for iframe | Medium | Medium | Tree-shake unused deps, lazy-load CodeMirror | +| IndexedDB not persistent in iframe | High | Low | Use `navigator.storage.persist()`, warn user | +| Claude Desktop iframe size too small | Medium | Medium | Responsive CSS, collapsible sidebar | +| MCP Apps spec changes | Low | Medium | Pin `@modelcontextprotocol/ext-apps` version | + +--- + +## Recommended Path + +**Phase 1 (v1.17.0):** Proof of concept +- `open-scribe` tool renders full editor in Claude Desktop +- Independent IndexedDB storage +- Local server only (`npm run mcp:serve`) +- 3 additional text-only tools (`create-note`, `search-notes`, `get-note`) + +**Phase 2 (v1.18.0):** Full integration +- Bidirectional context (Claude sees your writing) +- 10+ tools covering full CRUD +- Shared SQLite data (read from Tauri DB) +- Published connector + +**Phase 3 (v1.19.0):** Polish +- Theme sync with Claude Desktop +- Responsive iframe layout optimization +- Offline persistence guarantees +- User documentation and setup guide diff --git a/docs/reference/CLAUDE.md b/docs/reference/CLAUDE.md index 266bfe56..7441ae49 100644 --- a/docs/reference/CLAUDE.md +++ b/docs/reference/CLAUDE.md @@ -199,6 +199,28 @@ npm run test # Run tests npm run typecheck # TypeScript check ``` +### Claude Code Desktop Preview + +Scribe supports **in-app preview** inside Claude Code Desktop (Feb 2026+). Claude starts the Vite dev server and renders the running app in an embedded browser — auto-verifying changes by screenshotting, inspecting DOM, and clicking elements. + +**Config:** `.claude/launch.json` (already set up) + +```json +{ + "name": "scribe-dev", + "runtimeExecutable": "npm", + "runtimeArgs": ["run", "dev:vite"], + "port": 5173 +} +``` + +**Key details:** +- Uses `dev:vite` (not `dev`) — runs Vite only, no Tauri compilation needed +- App auto-detects browser mode via `platform.ts` → uses IndexedDB/Dexie for storage +- Port 5173 matches Vite's default +- No worktree needed — launch.json is config, not feature code +- When opening in Claude Code Desktop, **uncheck worktree isolation** to work on `dev` directly + ### Terminal CLI ```bash diff --git a/docs/specs/SPEC-mcp-app-claude-desktop-2026-02-22.md b/docs/specs/SPEC-mcp-app-claude-desktop-2026-02-22.md new file mode 100644 index 00000000..20a58351 --- /dev/null +++ b/docs/specs/SPEC-mcp-app-claude-desktop-2026-02-22.md @@ -0,0 +1,540 @@ +# SPEC: Scribe as MCP App in Claude Desktop + +> **Run Scribe's full writing environment inside Claude Desktop's conversation window via MCP Apps** + +**Generated:** 2026-02-22 +**Status:** Draft +**Priority:** P1 (New Distribution Channel) +**From Brainstorm:** [BRAINSTORM-mcp-app-2026-02-22.md](../../BRAINSTORM-mcp-app-2026-02-22.md) + +--- + +## Overview + +MCP Apps is an extension to the Model Context Protocol that allows MCP servers to deliver interactive HTML/JS/CSS applications within a sandboxed iframe in Claude Desktop's chat window. Scribe already has a complete browser-mode fallback (`browserApi` + IndexedDB via Dexie) that mirrors the Tauri backend 1:1. This spec defines how to package Scribe as an MCP App so users can write alongside Claude — drafting and editing notes in-conversation with full tool integration. + +**Why this matters:** Scribe becomes the writing surface inside Claude conversations. Users stop context-switching between apps. Claude can read what you're writing, create notes, and organize your work — all within the chat. + +--- + +## Primary User Story + +> **As a** Scribe user who also uses Claude Desktop, +> **I want to** open Scribe directly inside my Claude conversation, +> **So that** I can write and organize notes alongside Claude without switching windows. + +### Acceptance Criteria + +- [ ] Running `npm run mcp:serve` starts a local MCP server on `localhost:3001` +- [ ] Adding the server as a custom connector in Claude Desktop works +- [ ] Asking Claude to "open my writing app" renders Scribe in an iframe +- [ ] The full Scribe UI loads (sidebar, editor, tabs, settings) +- [ ] Notes persist across tool calls within the same conversation +- [ ] Claude can create, search, and retrieve notes via MCP tools +- [ ] Editor is usable at Claude Desktop's iframe dimensions + +--- + +## Secondary User Stories + +### Claude as Writing Assistant + +> **As a** writer using Scribe in Claude Desktop, +> **I want** Claude to see what I'm currently writing, +> **So that** Claude can provide contextual suggestions, edits, and feedback. + +### Note Organization via Chat + +> **As a** knowledge worker, +> **I want to** tell Claude "create a note about X" and have it appear in Scribe, +> **So that** I can capture ideas from our conversation without manual copy-paste. + +### Quick Research Capture + +> **As a** researcher, +> **I want to** ask Claude to search my existing notes while I write, +> **So that** I can reference previous work without leaving the editor. + +--- + +## Architecture + +### System Diagram + +```mermaid +graph TB + subgraph "Claude Desktop" + Chat[Chat Conversation] + subgraph "Sandboxed Iframe" + ScribeUI[Scribe React App
browser mode] + IDB[(IndexedDB
Dexie)] + ScribeUI --> IDB + end + AppClass[App class
postMessage bridge] + ScribeUI <--> AppClass + Chat <--> AppClass + end + + subgraph "Local Machine" + MCPServer[Scribe MCP Server
Express + MCP SDK
localhost:3001] + HTML[dist-mcp/mcp-app.html
Single-file bundle] + MCPServer -->|serves| HTML + end + + Chat <-->|MCP Protocol
HTTP POST| MCPServer + AppClass <-->|tool calls
context updates| MCPServer +``` + +### Component Responsibilities + +| Component | Role | +|-----------|------| +| **MCP Server** (`src/mcp-server/server.ts`) | Registers tools, serves UI resource, handles tool execution | +| **Tool Definitions** (`src/mcp-server/tools.ts`) | Defines MCP tools mapping to Scribe operations | +| **Resource Handler** (`src/mcp-server/resources.ts`) | Serves bundled HTML as `ui://scribe/app.html` | +| **MCP App Entry** (`src/mcp-app/mcp-app.ts`) | Initializes `App` class, bridges host ↔ Scribe | +| **MCP App HTML** (`src/mcp-app/mcp-app.html`) | HTML entry point loading React app | +| **Platform Detection** (`src/renderer/src/lib/platform.ts`) | Extended with `isMcpApp()` for iframe context | +| **Vite MCP Config** (`vite.mcp.config.ts`) | Separate build config with `vite-plugin-singlefile` | + +--- + +## API Design + +### MCP Tools (v1 — Phase 1) + +| Tool Name | Input Schema | Returns | Has UI? | +|-----------|-------------|---------|---------| +| `open-scribe` | `{}` (no args) | Welcome message | Yes — renders full app | +| `create-note` | `{ title: string, content?: string, project?: string }` | Note ID + confirmation | No | +| `search-notes` | `{ query: string, limit?: number }` | Array of matching notes (title, snippet, id) | No | +| `get-note` | `{ id?: string, title?: string }` | Full note content | No | +| `list-notes` | `{ project?: string, limit?: number }` | Array of note summaries | No | + +### MCP Tools (v2 — Phase 2) + +| Tool Name | Input Schema | Returns | Has UI? | +|-----------|-------------|---------|---------| +| `update-note` | `{ id: string, content?: string, title?: string }` | Updated note | No | +| `delete-note` | `{ id: string }` | Confirmation | No | +| `list-projects` | `{}` | Array of projects | No | +| `create-project` | `{ name: string, type?: string }` | Project ID | No | +| `search-tags` | `{ query: string }` | Matching tags with counts | No | +| `get-daily-note` | `{ date?: string }` | Today's daily note | Yes — opens editor | +| `export-note` | `{ id: string, format: 'markdown' \| 'html' }` | Exported content | No | + +### MCP Resource + +``` +URI: ui://scribe/app.html +MIME: text/html; ext=mcp +Content: Bundled single-file HTML (Scribe React app) +``` + +### Host ↔ App Communication + +```typescript +// src/mcp-app/mcp-app.ts +import { App } from '@modelcontextprotocol/ext-apps' + +const app = new App({ name: 'Scribe', version: '1.17.0' }) +app.connect() + +// Receive tool results (e.g., after create-note) +app.ontoolresult = (result) => { + // Navigate editor to newly created note, or refresh note list +} + +// Push current editor state to Claude's context +function pushEditorContext(noteTitle: string, content: string) { + app.updateContext({ + type: 'text', + text: `Currently editing: "${noteTitle}"\n\n${content}` + }) +} + +// Call tools from within the app +async function createNoteFromApp(title: string, content: string) { + return app.callServerTool({ + name: 'create-note', + arguments: { title, content } + }) +} +``` + +--- + +## Data Models + +### v1: Independent IndexedDB (Sandboxed) + +No new data models needed. The existing `browser-db.ts` Dexie schema works unchanged: + +```typescript +// Existing — works in iframe as-is +class ScribeBrowserDB extends Dexie { + notes!: Table + tags!: Table + note_tags!: Table + note_links!: Table + projects!: Table + chat_sessions!: Table + chat_messages!: Table +} +``` + +**Limitation:** Data is isolated per iframe origin. Notes created in Claude Desktop won't appear in desktop Scribe. + +### v2: Shared SQLite via MCP Server + +The MCP server reads Scribe's SQLite database directly: + +```typescript +// src/mcp-server/db.ts (v2) +import Database from 'better-sqlite3' +import { homedir } from 'os' +import { join } from 'path' + +// Scribe stores its DB at a known Tauri path +const DB_PATH = join(homedir(), 'Library/Application Support/com.scribe.app/scribe.db') + +export function openScribeDb() { + return new Database(DB_PATH, { readonly: false }) +} +``` + +--- + +## Dependencies + +### New Dependencies + +| Package | Purpose | Version | +|---------|---------|---------| +| `@modelcontextprotocol/sdk` | MCP server SDK | `^1.x` | +| `@modelcontextprotocol/ext-apps` | MCP Apps helpers (server + client) | `^1.x` | +| `express` | HTTP server for MCP transport | `^4.x` | +| `cors` | CORS middleware | `^2.x` | +| `tsx` | TypeScript execution for server | `^4.x` | +| `vite-plugin-singlefile` | Bundle HTML + JS + CSS into one file | `^2.x` | + +### Dev Dependencies + +| Package | Purpose | +|---------|---------| +| `@types/express` | Express type definitions | +| `@types/cors` | CORS type definitions | + +### Existing Dependencies (Reused) + +- `react`, `react-dom` — UI framework +- `@uiw/react-codemirror` — Editor +- `dexie` — IndexedDB wrapper +- `zustand` — State management +- `tailwindcss` — Styling +- `lucide-react` — Icons +- `react-markdown`, `remark-gfm` — Markdown rendering +- `katex` — Math rendering + +--- + +## UI/UX Specifications + +### User Flow + +```mermaid +sequenceDiagram + actor User + participant Claude as Claude Desktop + participant MCP as MCP Server + participant Scribe as Scribe (iframe) + + User->>Claude: "Open my writing app" + Claude->>MCP: call open-scribe tool + MCP-->>Claude: tool result + ui resource URI + Claude->>MCP: fetch ui://scribe/app.html + MCP-->>Claude: bundled HTML + Claude->>Scribe: render in sandboxed iframe + Scribe->>Scribe: Initialize (browser mode, IndexedDB) + Scribe-->>User: Full Scribe editor visible in chat + + User->>Scribe: Write a note + Scribe->>Claude: app.updateContext(current note) + User->>Claude: "Summarize what I just wrote" + Claude-->>User: Summary based on editor context + + User->>Claude: "Create a note called 'Meeting Notes'" + Claude->>MCP: call create-note + MCP-->>Claude: Note created (id: abc123) + Claude->>Scribe: ontoolresult → navigate to new note + Scribe-->>User: Editor opens new note +``` + +### Iframe Layout Adaptations + +| Viewport | Behavior | +|----------|----------| +| **Width < 600px** | Sidebar collapses to icon bar, editor fills width | +| **Width 600-900px** | Sidebar in compact mode, editor primary | +| **Width > 900px** | Full layout (sidebar + editor + optional panel) | +| **Height** | `max-height: 80vh` with internal scroll on editor | + +### Features Hidden in MCP App Mode + +These features require Tauri-native APIs and are hidden when `isMcpApp()` returns `true`: + +| Feature | Reason | Replacement | +|---------|--------|-------------| +| Terminal panel | Requires PTY access | Hidden tab | +| File export dialogs | Tauri dialog API | Download via blob URL | +| Font installation | Requires Homebrew | Web-safe fonts only | +| Global shortcuts | Tauri shortcut API | In-app shortcuts only | +| Window title bar / drag region | Tauri window chrome | CSS hidden | +| Claude chat sidebar tab | Redundant (already in Claude) | Hidden tab | + +### CSS Adaptations + +```css +/* Applied when platform === 'mcp-app' */ +.mcp-app-mode .drag-region { display: none; } +.mcp-app-mode .terminal-tab { display: none; } +.mcp-app-mode .claude-tab { display: none; } +.mcp-app-mode { max-height: 80vh; overflow: hidden; } +.mcp-app-mode .editor-area { min-height: 400px; } +``` + +### Accessibility + +- [ ] Keyboard navigation works within iframe sandbox +- [ ] Focus trapping respects iframe boundary +- [ ] Screen reader announces MCP App content +- [ ] Color contrast meets WCAG 2.1 AA within Scribe themes +- [ ] `prefers-reduced-motion` respected in animations + +--- + +## Documentation Plan + +### User-Facing Documentation + +#### 1. Setup Guide (`docs/guides/mcp-app-setup.md`) + +Step-by-step guide for running Scribe inside Claude Desktop: + +- **Prerequisites:** Node.js 18+, Claude Desktop (Pro/Max/Team), npm +- **Installation:** `cd scribe && npm install && npm run mcp:build` +- **Running:** `npm run mcp:serve` +- **Connecting:** How to add custom connector in Claude Desktop settings + - Navigate to Settings → Connectors → Add Custom Connector + - Enter URL: `http://localhost:3001/mcp` + - Name: "Scribe" +- **First use:** Start a new chat, ask Claude to "open Scribe" +- **Troubleshooting:** + - Server not starting (port conflicts) + - Connector not appearing (check URL, ensure server running) + - Blank iframe (check browser console, rebuild) + - Data not persisting (IndexedDB storage limits) + +#### 2. MCP Tools Reference (`docs/reference/mcp-tools.md`) + +Complete reference for all MCP tools: + +- Tool name, description, input schema (with examples) +- Response format with sample outputs +- Which tools render UI vs. return text +- Error responses and edge cases +- Example prompts that trigger each tool + +#### 3. Architecture Guide (`docs/architecture/mcp-app.md`) + +Technical documentation for contributors: + +- System diagram (from this spec) +- Build pipeline explanation (Vite dual-config) +- Platform detection logic (`isTauri` / `isBrowser` / `isMcpApp`) +- Data flow: tool call → server → response → iframe +- Host ↔ App communication protocol +- Security model (CSP, iframe sandbox, storage isolation) + +### Developer Documentation + +#### 4. Contributing Guide Addition (`CONTRIBUTING.md` section) + +New section in contributing docs: + +- How to develop the MCP App locally +- Running MCP server in dev mode with hot-reload +- Testing with the `basic-host` test harness +- Testing with Claude Desktop (cloudflared tunnel) +- Adding new MCP tools +- Modifying the iframe UI + +#### 5. README Update + +New section in project README: + +```markdown +## Run in Claude Desktop + +Scribe can run directly inside Claude Desktop as an MCP App: + +\`\`\`bash +npm run mcp:build && npm run mcp:serve +\`\`\` + +Then add `http://localhost:3001/mcp` as a custom connector in Claude Desktop. +Ask Claude: "Open my writing app" — Scribe appears in your conversation. + +See [MCP App Setup Guide](docs/guides/mcp-app-setup.md) for details. +``` + +#### 6. Inline Code Documentation + +All new files include JSDoc headers: + +```typescript +/** + * Scribe MCP Server + * + * Exposes Scribe's writing environment as an MCP App for Claude Desktop. + * Registers tools for note CRUD + search, and serves the bundled + * Scribe UI as an interactive resource rendered in-conversation. + * + * @see https://modelcontextprotocol.io/extensions/apps/build + * @module mcp-server + */ +``` + +--- + +## Integration Plan + +### Phase 1: Local MCP App (v1.17.0) + +**Goal:** Scribe renders and works inside Claude Desktop locally. + +| Step | Task | Files | Est. | +|------|------|-------|------| +| 1.1 | Install MCP dependencies | `package.json` | 15m | +| 1.2 | Create Vite MCP config with singlefile plugin | `vite.mcp.config.ts` | 30m | +| 1.3 | Create MCP App HTML entry point | `src/mcp-app/mcp-app.html` | 15m | +| 1.4 | Create MCP App bridge (App class) | `src/mcp-app/mcp-app.ts` | 1h | +| 1.5 | Extend platform detection | `src/renderer/src/lib/platform.ts` | 15m | +| 1.6 | Add MCP-app CSS mode | `src/renderer/src/index.css` | 30m | +| 1.7 | Hide Tauri-only features in MCP mode | Various components | 1h | +| 1.8 | Create MCP server with Express | `src/mcp-server/server.ts` | 1h | +| 1.9 | Define `open-scribe` tool + UI resource | `src/mcp-server/tools.ts`, `resources.ts` | 1h | +| 1.10 | Define text-only tools (create, search, get, list) | `src/mcp-server/tools.ts` | 2h | +| 1.11 | Build and test end-to-end | - | 1h | +| 1.12 | Write setup guide | `docs/guides/mcp-app-setup.md` | 1h | +| 1.13 | Write MCP tools reference | `docs/reference/mcp-tools.md` | 1h | +| 1.14 | Update README | `README.md` | 15m | + +**Total estimate:** ~10-12 hours + +### Phase 2: Full Tool Integration (v1.18.0) + +| Step | Task | Est. | +|------|------|------| +| 2.1 | Bidirectional context (`app.updateContext()`) | 2h | +| 2.2 | Extended tool suite (update, delete, projects, tags) | 4h | +| 2.3 | Tool result → UI navigation (open note from tool call) | 2h | +| 2.4 | Shared SQLite backend (server reads Tauri DB) | 4h | +| 2.5 | Write architecture guide | 2h | +| 2.6 | Update contributing guide | 1h | + +### Phase 3: Production Distribution (v1.19.0) + +| Step | Task | Est. | +|------|------|------| +| 3.1 | Published connector (Claude directory listing) | 4h | +| 3.2 | Theme sync (detect host dark/light mode) | 2h | +| 3.3 | Responsive iframe optimization | 2h | +| 3.4 | Persistence guarantees (`navigator.storage.persist`) | 1h | +| 3.5 | Cloudflare tunnel documentation | 1h | +| 3.6 | End-to-end testing suite | 4h | + +### Integration with Existing Build System + +``` +Existing: + npm run dev → tauri dev (Vite + Tauri) + npm run build → tauri build (production binary) + npm run dev:vite → vite (browser-only dev server) + +New (added): + npm run mcp:build → vite build --config vite.mcp.config.ts + npm run mcp:serve → tsx src/mcp-server/server.ts + npm run mcp:dev → mcp:build && mcp:serve +``` + +### CI/CD Integration + +- Add `mcp:build` to CI pipeline to catch build failures +- Bundle size check (warn if single HTML > 5MB) +- MCP server smoke test (start server, call tool, verify response) + +--- + +## Open Questions + +1. **IndexedDB persistence in sandboxed iframe** — Does Claude Desktop's iframe allow persistent IndexedDB, or is storage cleared between conversations? Needs testing. +2. **Bundle size** — With CodeMirror + KaTeX + D3 + React, the single-file bundle may be large. Should we lazy-load heavy deps? +3. **MCP Apps spec stability** — The spec is under active development. How should we handle breaking changes? +4. **iframe resize events** — Does Claude Desktop resize the iframe dynamically? How do we handle viewport changes? + +--- + +## Review Checklist + +- [ ] All new files have JSDoc documentation headers +- [ ] Platform detection covers all three modes (tauri, browser, mcp-app) +- [ ] MCP server starts clean with `npm run mcp:serve` +- [ ] Single-file HTML bundle renders correctly +- [ ] All 5 v1 tools work end-to-end +- [ ] Tauri-only features are hidden in MCP App mode +- [ ] Setup guide tested on a fresh machine +- [ ] MCP tools reference has examples for every tool +- [ ] README updated with MCP App section +- [ ] No regressions in existing Tauri or browser builds +- [ ] Bundle size < 5MB (target) + +--- + +## Implementation Notes + +### Key Architectural Advantage + +Scribe's existing `platform.ts` + `browserApi` abstraction means the MCP App requires **zero changes** to core business logic. The entire React app runs unchanged — we're just adding a new entry point, a new build target, and an MCP server wrapper. + +### Bundle Size Strategy + +The single-file approach (`vite-plugin-singlefile`) inlines all JS/CSS/assets into one HTML file. Expected size breakdown: + +| Dependency | Approx. Size (gzipped) | +|-----------|----------------------| +| React + ReactDOM | ~45KB | +| CodeMirror (core + markdown) | ~120KB | +| Tailwind CSS | ~15KB | +| KaTeX | ~90KB | +| D3 (charts) | ~80KB | +| Dexie | ~20KB | +| Scribe app code | ~50KB | +| **Total** | **~420KB gzipped** | + +This is well within acceptable iframe loading times. + +### Testing Strategy + +1. **Unit tests:** MCP server tool handlers (input validation, response format) +2. **Integration tests:** Start server → call tool → verify response +3. **Manual E2E:** Build → serve → add to Claude Desktop → verify rendering +4. **basic-host harness:** Use MCP's test host for automated UI testing + +--- + +## History + +| Date | Change | +|------|--------| +| 2026-02-22 | Initial spec created from deep architecture brainstorm | diff --git a/package-lock.json b/package-lock.json index 0d8470e6..c6b5f06b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "scribe", - "version": "1.16.2", + "version": "1.17.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "scribe", - "version": "1.16.2", + "version": "1.17.0", "license": "MIT", "dependencies": { "@codemirror/lang-markdown": "^6.5.0", @@ -17,7 +17,7 @@ "@dnd-kit/sortable": "^10.0.0", "@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-visually-hidden": "^1.2.4", - "@tauri-apps/plugin-dialog": "^2.4.2", + "@tauri-apps/plugin-dialog": "^2.6.0", "@types/d3": "^7.4.3", "@types/katex": "^0.16.7", "@uiw/react-codemirror": "^4.25.4", @@ -42,8 +42,8 @@ }, "devDependencies": { "@playwright/test": "^1.57.0", - "@tauri-apps/api": "^2.9.1", - "@tauri-apps/cli": "^2.9.6", + "@tauri-apps/api": "^2.10.1", + "@tauri-apps/cli": "^2.10.0", "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^16.3.1", "@testing-library/user-event": "^14.6.1", @@ -195,7 +195,6 @@ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -2123,7 +2122,6 @@ "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.39.8.tgz", "integrity": "sha512-1rASYd9Z/mE3tkbC9wInRlCNyCkSn+nLsiQKZhEDUUJiUfs/5FHDpCUDaQpoTIaNGeDc6/bhaEAyLmeEucEFPw==", "license": "MIT", - "peer": true, "dependencies": { "@codemirror/state": "^6.5.0", "crelt": "^1.0.6", @@ -2219,7 +2217,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -2263,7 +2260,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" } @@ -2285,7 +2281,6 @@ "resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz", "integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==", "license": "MIT", - "peer": true, "dependencies": { "@dnd-kit/accessibility": "^3.1.1", "@dnd-kit/utilities": "^3.2.2", @@ -4425,9 +4420,9 @@ } }, "node_modules/@tauri-apps/api": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.9.1.tgz", - "integrity": "sha512-IGlhP6EivjXHepbBic618GOmiWe4URJiIeZFlB7x3czM0yDHHYviH1Xvoiv4FefdkQtn6v7TuwWCRfOGdnVUGw==", + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.10.1.tgz", + "integrity": "sha512-hKL/jWf293UDSUN09rR69hrToyIXBb8CjGaWC7gfinvnQrBVvnLr08FeFi38gxtugAVyVcTa5/FD/Xnkb1siBw==", "license": "Apache-2.0 OR MIT", "funding": { "type": "opencollective", @@ -4435,9 +4430,9 @@ } }, "node_modules/@tauri-apps/cli": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.9.6.tgz", - "integrity": "sha512-3xDdXL5omQ3sPfBfdC8fCtDKcnyV7OqyzQgfyT5P3+zY6lcPqIYKQBvUasNvppi21RSdfhy44ttvJmftb0PCDw==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.10.0.tgz", + "integrity": "sha512-ZwT0T+7bw4+DPCSWzmviwq5XbXlM0cNoleDKOYPFYqcZqeKY31KlpoMW/MOON/tOFBPgi31a2v3w9gliqwL2+Q==", "dev": true, "license": "Apache-2.0 OR MIT", "bin": { @@ -4451,23 +4446,23 @@ "url": "https://opencollective.com/tauri" }, "optionalDependencies": { - "@tauri-apps/cli-darwin-arm64": "2.9.6", - "@tauri-apps/cli-darwin-x64": "2.9.6", - "@tauri-apps/cli-linux-arm-gnueabihf": "2.9.6", - "@tauri-apps/cli-linux-arm64-gnu": "2.9.6", - "@tauri-apps/cli-linux-arm64-musl": "2.9.6", - "@tauri-apps/cli-linux-riscv64-gnu": "2.9.6", - "@tauri-apps/cli-linux-x64-gnu": "2.9.6", - "@tauri-apps/cli-linux-x64-musl": "2.9.6", - "@tauri-apps/cli-win32-arm64-msvc": "2.9.6", - "@tauri-apps/cli-win32-ia32-msvc": "2.9.6", - "@tauri-apps/cli-win32-x64-msvc": "2.9.6" + "@tauri-apps/cli-darwin-arm64": "2.10.0", + "@tauri-apps/cli-darwin-x64": "2.10.0", + "@tauri-apps/cli-linux-arm-gnueabihf": "2.10.0", + "@tauri-apps/cli-linux-arm64-gnu": "2.10.0", + "@tauri-apps/cli-linux-arm64-musl": "2.10.0", + "@tauri-apps/cli-linux-riscv64-gnu": "2.10.0", + "@tauri-apps/cli-linux-x64-gnu": "2.10.0", + "@tauri-apps/cli-linux-x64-musl": "2.10.0", + "@tauri-apps/cli-win32-arm64-msvc": "2.10.0", + "@tauri-apps/cli-win32-ia32-msvc": "2.10.0", + "@tauri-apps/cli-win32-x64-msvc": "2.10.0" } }, "node_modules/@tauri-apps/cli-darwin-arm64": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.9.6.tgz", - "integrity": "sha512-gf5no6N9FCk1qMrti4lfwP77JHP5haASZgVbBgpZG7BUepB3fhiLCXGUK8LvuOjP36HivXewjg72LTnPDScnQQ==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.10.0.tgz", + "integrity": "sha512-avqHD4HRjrMamE/7R/kzJPcAJnZs0IIS+1nkDP5b+TNBn3py7N2aIo9LIpy+VQq0AkN8G5dDpZtOOBkmWt/zjA==", "cpu": [ "arm64" ], @@ -4482,9 +4477,9 @@ } }, "node_modules/@tauri-apps/cli-darwin-x64": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.9.6.tgz", - "integrity": "sha512-oWh74WmqbERwwrwcueJyY6HYhgCksUc6NT7WKeXyrlY/FPmNgdyQAgcLuTSkhRFuQ6zh4Np1HZpOqCTpeZBDcw==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.10.0.tgz", + "integrity": "sha512-keDmlvJRStzVFjZTd0xYkBONLtgBC9eMTpmXnBXzsHuawV2q9PvDo2x6D5mhuoMVrJ9QWjgaPKBBCFks4dK71Q==", "cpu": [ "x64" ], @@ -4499,9 +4494,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.9.6.tgz", - "integrity": "sha512-/zde3bFroFsNXOHN204DC2qUxAcAanUjVXXSdEGmhwMUZeAQalNj5cz2Qli2elsRjKN/hVbZOJj0gQ5zaYUjSg==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.10.0.tgz", + "integrity": "sha512-e5u0VfLZsMAC9iHaOEANumgl6lfnJx0Dtjkd8IJpysZ8jp0tJ6wrIkto2OzQgzcYyRCKgX72aKE0PFgZputA8g==", "cpu": [ "arm" ], @@ -4516,9 +4511,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-gnu": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.9.6.tgz", - "integrity": "sha512-pvbljdhp9VOo4RnID5ywSxgBs7qiylTPlK56cTk7InR3kYSTJKYMqv/4Q/4rGo/mG8cVppesKIeBMH42fw6wjg==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.10.0.tgz", + "integrity": "sha512-YrYYk2dfmBs5m+OIMCrb+JH/oo+4FtlpcrTCgiFYc7vcs6m3QDd1TTyWu0u01ewsCtK2kOdluhr/zKku+KP7HA==", "cpu": [ "arm64" ], @@ -4533,9 +4528,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-musl": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.9.6.tgz", - "integrity": "sha512-02TKUndpodXBCR0oP//6dZWGYcc22Upf2eP27NvC6z0DIqvkBBFziQUcvi2n6SrwTRL0yGgQjkm9K5NIn8s6jw==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.10.0.tgz", + "integrity": "sha512-GUoPdVJmrJRIXFfW3Rkt+eGK9ygOdyISACZfC/bCSfOnGt8kNdQIQr5WRH9QUaTVFIwxMlQyV3m+yXYP+xhSVA==", "cpu": [ "arm64" ], @@ -4550,9 +4545,9 @@ } }, "node_modules/@tauri-apps/cli-linux-riscv64-gnu": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.9.6.tgz", - "integrity": "sha512-fmp1hnulbqzl1GkXl4aTX9fV+ubHw2LqlLH1PE3BxZ11EQk+l/TmiEongjnxF0ie4kV8DQfDNJ1KGiIdWe1GvQ==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.10.0.tgz", + "integrity": "sha512-JO7s3TlSxshwsoKNCDkyvsx5gw2QAs/Y2GbR5UE2d5kkU138ATKoPOtxn8G1fFT1aDW4LH0rYAAfBpGkDyJJnw==", "cpu": [ "riscv64" ], @@ -4567,9 +4562,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-gnu": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.9.6.tgz", - "integrity": "sha512-vY0le8ad2KaV1PJr+jCd8fUF9VOjwwQP/uBuTJvhvKTloEwxYA/kAjKK9OpIslGA9m/zcnSo74czI6bBrm2sYA==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.10.0.tgz", + "integrity": "sha512-Uvh4SUUp4A6DVRSMWjelww0GnZI3PlVy7VS+DRF5napKuIehVjGl9XD0uKoCoxwAQBLctvipyEK+pDXpJeoHng==", "cpu": [ "x64" ], @@ -4584,9 +4579,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-musl": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.9.6.tgz", - "integrity": "sha512-TOEuB8YCFZTWVDzsO2yW0+zGcoMiPPwcUgdnW1ODnmgfwccpnihDRoks+ABT1e3fHb1ol8QQWsHSCovb3o2ENQ==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.10.0.tgz", + "integrity": "sha512-AP0KRK6bJuTpQ8kMNWvhIpKUkQJfcPFeba7QshOQZjJ8wOS6emwTN4K5g/d3AbCMo0RRdnZWwu67MlmtJyxC1Q==", "cpu": [ "x64" ], @@ -4601,9 +4596,9 @@ } }, "node_modules/@tauri-apps/cli-win32-arm64-msvc": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.9.6.tgz", - "integrity": "sha512-ujmDGMRc4qRLAnj8nNG26Rlz9klJ0I0jmZs2BPpmNNf0gM/rcVHhqbEkAaHPTBVIrtUdf7bGvQAD2pyIiUrBHQ==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.10.0.tgz", + "integrity": "sha512-97DXVU3dJystrq7W41IX+82JEorLNY+3+ECYxvXWqkq7DBN6FsA08x/EFGE8N/b0LTOui9X2dvpGGoeZKKV08g==", "cpu": [ "arm64" ], @@ -4618,9 +4613,9 @@ } }, "node_modules/@tauri-apps/cli-win32-ia32-msvc": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.9.6.tgz", - "integrity": "sha512-S4pT0yAJgFX8QRCyKA1iKjZ9Q/oPjCZf66A/VlG5Yw54Nnr88J1uBpmenINbXxzyhduWrIXBaUbEY1K80ZbpMg==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.10.0.tgz", + "integrity": "sha512-EHyQ1iwrWy1CwMalEm9z2a6L5isQ121pe7FcA2xe4VWMJp+GHSDDGvbTv/OPdkt2Lyr7DAZBpZHM6nvlHXEc4A==", "cpu": [ "ia32" ], @@ -4635,9 +4630,9 @@ } }, "node_modules/@tauri-apps/cli-win32-x64-msvc": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.9.6.tgz", - "integrity": "sha512-ldWuWSSkWbKOPjQMJoYVj9wLHcOniv7diyI5UAJ4XsBdtaFB0pKHQsqw/ItUma0VXGC7vB4E9fZjivmxur60aw==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.10.0.tgz", + "integrity": "sha512-NTpyQxkpzGmU6ceWBTY2xRIEaS0ZLbVx1HE1zTA3TY/pV3+cPoPPOs+7YScr4IMzXMtOw7tLw5LEXo5oIG3qaQ==", "cpu": [ "x64" ], @@ -4652,9 +4647,9 @@ } }, "node_modules/@tauri-apps/plugin-dialog": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-dialog/-/plugin-dialog-2.4.2.tgz", - "integrity": "sha512-lNIn5CZuw8WZOn8zHzmFmDSzg5zfohWoa3mdULP0YFh/VogVdMVWZPcWSHlydsiJhRQYaTNSYKN7RmZKE2lCYQ==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-dialog/-/plugin-dialog-2.6.0.tgz", + "integrity": "sha512-q4Uq3eY87TdcYzXACiYSPhmpBA76shgmQswGkSVio4C82Sz2W4iehe9TnKYwbq7weHiL88Yw19XZm7v28+Micg==", "license": "MIT OR Apache-2.0", "dependencies": { "@tauri-apps/api": "^2.8.0" @@ -4755,7 +4750,8 @@ "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@types/babel__core": { "version": "7.20.5", @@ -5149,7 +5145,6 @@ "integrity": "sha512-N2clP5pJhB2YnZJ3PIHFk5RkygRX5WO/5f0WC08tp0wd+sv0rsJk3MqWn3CbNmT2J505a5336jaQj4ph1AdMug==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~6.21.0" } @@ -5165,7 +5160,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.27.tgz", "integrity": "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==", "license": "MIT", - "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.2.2" @@ -5177,7 +5171,6 @@ "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", "devOptional": true, "license": "MIT", - "peer": true, "peerDependencies": { "@types/react": "^18.0.0" } @@ -5365,7 +5358,6 @@ "integrity": "sha512-rkoPH+RqWopVxDnCBE/ysIdfQ2A7j1eDmW8tCxxrR9nnFBa9jKf86VgsSAzxBd1x+ny0GC4JgiD3SNfRHv3pOg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@vitest/utils": "4.0.16", "fflate": "^0.8.2", @@ -5436,7 +5428,6 @@ "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -5785,7 +5776,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -6490,7 +6480,6 @@ "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", "license": "ISC", - "peer": true, "engines": { "node": ">=12" } @@ -6788,7 +6777,8 @@ "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/dompurify": { "version": "3.3.1", @@ -8536,7 +8526,6 @@ "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", "dev": true, "license": "MIT", - "peer": true, "bin": { "jiti": "bin/jiti.js" } @@ -8811,6 +8800,7 @@ "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", "dev": true, "license": "MIT", + "peer": true, "bin": { "lz-string": "bin/bin.js" } @@ -10165,7 +10155,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -10328,6 +10317,7 @@ "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -10343,6 +10333,7 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10" }, @@ -10406,7 +10397,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -10419,7 +10409,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -10433,7 +10422,8 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/react-markdown": { "version": "10.1.0", @@ -11736,7 +11726,6 @@ "integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", @@ -11838,7 +11827,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -12420,7 +12408,6 @@ "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", @@ -12512,7 +12499,6 @@ "integrity": "sha512-E4t7DJ9pESL6E3I8nFjPa4xGUd3PmiWDLsDztS2qXSJWfHtbQnwAWylaBvSNY48I3vr8PTqIZlyK8TE3V3CA4Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@vitest/expect": "4.0.16", "@vitest/mocker": "4.0.16", @@ -13069,7 +13055,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -13083,7 +13068,6 @@ "integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -13520,7 +13504,6 @@ "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==", "dev": true, "license": "MIT", - "peer": true, "bin": { "rollup": "dist/bin/rollup" }, diff --git a/package.json b/package.json index b3d164c8..054c22dd 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "@dnd-kit/sortable": "^10.0.0", "@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-visually-hidden": "^1.2.4", - "@tauri-apps/plugin-dialog": "^2.4.2", + "@tauri-apps/plugin-dialog": "^2.6.0", "@types/d3": "^7.4.3", "@types/katex": "^0.16.7", "@uiw/react-codemirror": "^4.25.4", @@ -56,8 +56,8 @@ }, "devDependencies": { "@playwright/test": "^1.57.0", - "@tauri-apps/api": "^2.9.1", - "@tauri-apps/cli": "^2.9.6", + "@tauri-apps/api": "^2.10.1", + "@tauri-apps/cli": "^2.10.0", "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^16.3.1", "@testing-library/user-event": "^14.6.1", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 6bd6ed80..46776a21 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -15,19 +15,19 @@ name = "scribe_lib" crate-type = ["staticlib", "cdylib", "rlib"] [build-dependencies] -tauri-build = { version = "2.5.3", features = [] } +tauri-build = { version = "2.5.5", features = [] } [dependencies] serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } log = "0.4" -tauri = { version = "2.9.5", features = [] } +tauri = { version = "2.10.2", features = [] } tauri-plugin-log = "2" rusqlite = { version = "0.31", features = ["bundled"] } uuid = { version = "1.6", features = ["v4"] } regex = "1.10" tauri-plugin-global-shortcut = "2.3.1" -tauri-plugin-dialog = "2.4.2" +tauri-plugin-dialog = "2.6.0" chrono = "0.4.42" lazy_static = "1.4" dirs = "5.0"