Skip to main content

beeper-mcp

Unified messaging via Beeper Desktop MCP. Search chats, send messages, manage conversations across all networks (iMessage, WhatsApp, Signal, Telegram, Discord, Slack, etc.)

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

المستودع
plurigrid/asi
آخر نشاط في المصدر
١٠ يونيو ٢٠٢٦ في ١١:٥٥
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٦٧
التفرعات
١٢

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

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

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

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

مستكشف الملفات
4 ملفات

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
beeper-mcp
description
Unified messaging via Beeper Desktop MCP. Search chats, send messages, manage conversations across all networks (iMessage, WhatsApp, Signal, Telegram, Discord, Slack, etc.)
version
1.1.0
trit
0
role
ERGODIC
color
#6B5CE7
hue
249
tags
["messaging","beeper","mcp","communication","chat"]
deployed
2026-01-06T00:00:00.000Z
pre_hook
pre-hook.sh
## CRITICAL: TOKENS PAY RENT **Every output token must produce actionable value.** Violations: 1. **NO PASSIVE SUMMARIES** - Regurgitating conversation content without action items, code, or artifacts is FORBIDDEN 2. **NO AGREEMENT WITHOUT IMPLEMENTATION** - "I agree with X" must be followed by code/file/commit implementing X 3. **NO RHETORICAL QUESTIONS** - Ask only when you cannot proceed without the answer 4. **NO PRAISE/VALIDATION** - Skip "great question" / "you're right" - proceed to work **When reviewing message history:** - Extract ACTION ITEMS → create files, send messages, write code - Extract DECISIONS → update configs, create artifacts documenting the decision - Extract BLOCKERS → file issues, send follow-up messages - NEVER just summarize what was discussed **Enforcement:** If output contains summary without artifact, STOP and create the artifact first. # Beeper MCP Skill Access all messaging networks through Beeper's unified interface. ## Quick Start ``` # Search for a chat mcp__beeper__search "contact name" # Send a message mcp__beeper__send_message chatID="..." text="Hello!" # List recent chats mcp__beeper__search_chats limit=10 ``` ## Core Tools | Tool | Purpose | |------|---------| | `search` | Find chats, groups, or people by name | | `search_chats` | List/filter chats by type, inbox, activity | | `search_messages` | Find messages by content (literal match) | | `get_chat` | Get chat details and participants | | `list_messages` | Get messages from a specific chat | | `send_message` | Send text message to a chat | | `archive_chat` | Archive/unarchive a chat | | `set_chat_reminder` | Set reminder for a chat | | `focus_app` | Open Beeper Desktop to specific chat | ## Search Guidelines **CRITICAL**: Queries are LITERAL WORD MATCHING, not semantic search. - RIGHT: `query="dinner"` or `query="flight"` - WRONG: `query="dinner plans tonight"` or `query="travel arrangements"` Multiple words = ALL must match. Use single keywords. ## User Identity Clarification **IMPORTANT**: Beeper/Matrix has TWO identifiers per user: 1. **Matrix userID**: `@username:beeper.com` (permanent, searchable) 2. **Display name**: User-chosen name (can differ from userID) Example: User `@jsmith:beeper.com` may have display name "John Smith" When search finds a match: - The search matched the **userID** OR **display name** - Chat participant lists show **display names**, not userIDs - To see userIDs, use `list_messages` and check `senderID` field When reporting search results: - Cross-reference `list_messages` to map `senderID` ↔ `senderName` - Report as "username (displays as 'Display Name')" for clarity ## Resource-Aware Message Processing **CRITICAL**: Always work backwards from most recent messages to avoid: - Re-processing already-handled tasks - Repeating fixed issues - Heap exhaustion from loading too much history ### Default Workflow (Backwards-First) ```javascript // 1. Start with most recent (no cursor = newest first) const recent = await list_messages(chatID, { limit: 20 }); // 2. Check if already processed (use DuckDB tracking) const unprocessed = recent.items.filter(msg => !isProcessed(msg.id)); // 3. Process only new messages for (const msg of unprocessed) { await processMessage(msg); markProcessed(msg.id); } // 4. If need more history, paginate backwards if (needsMoreContext) { const older = await list_messages(chatID, { cursor: recent.cursor, direction: 'before', limit: 20 }); } ``` ### DuckDB Tracking Schema ```sql CREATE TABLE IF NOT EXISTS beeper_processed_messages ( message_id VARCHAR PRIMARY KEY, chat_id VARCHAR, processed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, task_extracted BOOLEAN, issue_status VARCHAR -- 'open', 'fixed', 'duplicate' ); CREATE INDEX idx_msg_chat ON beeper_processed_messages(chat_id, processed_at DESC); ``` ### Check Before Processing ```javascript function isAlreadyFixed(messageText) { // Query DuckDB for similar fixed issues const similar = db.query(` SELECT issue_id, description FROM fixed_issues WHERE description % ? -- Full-text similarity LIMIT 1 `, [messageText]); if (similar.length > 0) { console.warn(`⚠️ Similar issue already fixed: ${similar[0].description}`); return true; } return false; } ``` ## Workflow Patterns ### Find and Message Someone 1. `search "person name"` - Get chatID 2. **Verify identity**: `list_messages chatID="..." limit=5` - Check recent messages ONLY 3. `send_message chatID="..." text="..."` ### Identify Users in a Chat 1. `list_messages chatID="..." limit=10` - Get RECENT messages only (not entire history) 2. Map userID ↔ displayName from the subset ### Search Message History (Resource-Aware) 1. `search_chats` to get chatIDs of relevant chats 2. `search_messages chatIDs=[...] query="keyword" limit=20 dateAfter="2026-01-08T00:00:00Z"` 3. **Never omit dateAfter** - prevents loading entire chat history ### Monitor Unread ``` search_chats unreadOnly=true inbox="primary" limit=10 ``` ### Filter by Network Use `accountIDs` parameter after getting accounts via `get_accounts`. ## Message Formatting Messages support Markdown. Use sparingly for clarity. ## Chat Types - `single` - Direct messages (1:1) - `group` - Group chats - `any` - All types ## Inbox Filters - `primary` - Non-archived, non-low-priority - `low-priority` - Low priority inbox - `archive` - Archived chats ## Resource-Aware Random Walk Pattern **NEVER pull full message history into context.** Instead: ### 1. Query in DuckDB First ```sql -- Store messages incrementally, query locally CREATE TABLE IF NOT EXISTS beeper_messages ( id VARCHAR PRIMARY KEY, chat_id VARCHAR, sender_id VARCHAR, sender_name VARCHAR, text TEXT, timestamp TIMESTAMPTZ, processed BOOLEAN DEFAULT FALSE ); -- Sample recent messages via random walk SELECT * FROM beeper_messages WHERE chat_id = ? ORDER BY RANDOM() -- Ergodic sampling LIMIT 5; ``` ### 2. TreeSitter for Structure Extraction ```bash # Extract code blocks from messages without loading full text tree-sitter parse --scope source.markdown message.md \ | grep -E "(fenced_code_block|code_span)" ``` ### 3. Triadic Walker Pattern ``` MINUS (-1): Validate message exists in DuckDB before fetching ERGODIC (0): Random walk sample from local cache PLUS (+1): Fetch ONLY if not in cache, with strict limit ``` ### 4. Context Budget Enforcement ```python CONTEXT_BUDGET = 10000 # chars current_context = 0 def safe_fetch(chat_id, limit=5): # Check DuckDB cache first cached = db.query("SELECT * FROM beeper_messages WHERE chat_id = ? LIMIT ?", chat_id, limit) if len(cached) >= limit: return cached # Zero network cost # Fetch only missing, with limit remaining = limit - len(cached) fresh = mcp__beeper__list_messages(chatID=chat_id, limit=remaining) # Enforce budget for msg in fresh.items: msg_size = len(msg.get('text', '')) if current_context + msg_size > CONTEXT_BUDGET: break current_context += msg_size db.insert("beeper_messages", msg) return db.query("SELECT * FROM beeper_messages WHERE chat_id = ? LIMIT ?", chat_id, limit) ``` ### 5. SICP Lazy Evaluation ```scheme ;; Don't fetch until actually needed (define (beeper-messages chat-id) (delay (mcp__beeper__list_messages chatID: chat-id limit: 5))) ;; Only force when required (define (get-latest-sender chat-id) (let ((msgs (force (beeper-messages chat-id)))) (cdar msgs))) ; Just sender from first message ``` ## GF(3) Integration This skill operates as ERGODIC (0) in triadic compositions: - Coordinates message flow between networks - Synthesizes cross-platform conversations - Neutral hub for communication triads ### Triadic Fetch Strategy | Trit | Role | Beeper Action | |------|------|---------------| | MINUS (-1) | Validator | Check DuckDB cache, reject if stale | | ERGODIC (0) | Coordinator | Random walk sample, enforce budget | | PLUS (+1) | Generator | Fetch fresh data, strict `limit` param | ## Conversation Branch Awareness (Higher-Order Wiring) Track conversation threads as **wiring diagrams** - morphisms between topic states. ### Branch Detection Schema ```sql CREATE TABLE IF NOT EXISTS beeper_conversation_branches ( branch_id VARCHAR PRIMARY KEY, chat_id VARCHAR NOT NULL, parent_branch_id VARCHAR, -- NULL for root topic VARCHAR NOT NULL, first_message_id VARCHAR, last_message_id VARCHAR, status VARCHAR DEFAULT 'open', -- 'open', 'resolved', 'merged', 'stale' created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, resolved_at TIMESTAMP, FOREIGN KEY (parent_branch_id) REFERENCES beeper_conversation_branches(branch_id) ); CREATE TABLE IF NOT EXISTS beeper_branch_transitions ( from_branch VARCHAR, to_branch VARCHAR, transition_type VARCHAR, -- 'fork', 'merge', 'abandon', 'resolve' message_id VARCHAR, -- message that triggered transition timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (from_branch, to_branch, message_id) ); ``` ### Wiring Diagram Structure ``` Conversation as Category: - Objects: Topic states (branches) - Morphisms: Message sequences that transform one topic to another - Composition: Thread continuation ┌─────────────────┐ │ patents (open) │◄──── current focus └────────┬────────┘ │ fork @ msg:838941332 ┌───────────────┼───────────────┐ ▼ ▼ ▼ ┌────────┐ ┌───────────┐ ┌──────────┐ │ GF(3) │ │bisimulation│ │ toad OOM │ │resolved│ │ resolved │ │ open │ └────────┘ └───────────┘ └──────────┘ ``` ### Branch Detection Heuristics ```python def detect_branch(messages: list) -> list[Branch]: branches = [] current_topic = None for msg in messages: # Topic markers if msg.text.startswith('**Re:') or msg.text.startswith('Re:'): # Explicit reply = potential branch topic = extract_topic(msg.text) if topic != current_topic: branches.append(Branch( topic=topic, fork_message=msg.id, parent=current_topic )) # Numbered lists often indicate parallel threads if re.match(r'^\d+\.', msg.text): items = extract_numbered_items(msg.text) for item in items: branches.append(Branch(topic=item, parent=current_topic)) # Questions create potential branches if msg.text.strip().endswith('?'): branches.append(Branch( topic=f"Q: {msg.text[:50]}", status='awaiting_response' )) return branches ``` ### Zigger Chat Branch State Track active branches in zigger conversation: ```sql -- Query current branch state for a chat SELECT b.branch_id, b.topic, b.status, COUNT(t.to_branch) as child_count FROM beeper_conversation_branches b LEFT JOIN beeper_branch_transitions t ON b.branch_id = t.from_branch WHERE b.chat_id = '!NhltGRLZWLUeHEBiFT:beeper.com' -- zigger GROUP BY b.branch_id ORDER BY b.created_at DESC; ``` ### Before Responding: Check Branch Context ```python def get_branch_context(chat_id: str) -> dict: """Always call before responding to understand conversation topology.""" # Get open branches open_branches = db.query(""" SELECT topic, status, first_message_id FROM beeper_conversation_branches WHERE chat_id = ? AND status = 'open' """, chat_id) # Get unresolved questions questions = db.query(""" SELECT topic FROM beeper_conversation_branches WHERE chat_id = ? AND topic LIKE 'Q:%' AND status = 'awaiting_response' """, chat_id) return { 'open_branches': open_branches, 'unanswered_questions': questions, 'should_address': questions[0] if questions else open_branches[0] } ``` ### Wiring Composition Rules 1. **Fork**: One message spawns multiple topics → create child branches 2. **Merge**: Response addresses multiple branches → mark as merged 3. **Resolve**: Explicit closure ("done", "fixed", "shipped") → mark resolved 4. **Abandon**: No activity for 7 days → mark stale ### Integration with Tokens Pay Rent When reviewing messages, branch tracking prevents: - Re-answering resolved questions - Missing open threads - Losing context on forked discussions **Update branch state as side effect of every beeper interaction.** ## MCP Server Config ```json { "beeper": { "command": "/bin/sh", "args": [ "-c", "BEEPER_ACCESS_TOKEN=$(/Users/alice/.cargo/bin/fnox get BEEPER_ACCESS_TOKEN --age-key-file /Users/alice/.age/key.txt) exec npx -y @beeper/desktop-mcp" ] } } ``` Requires: - `fnox` at `/Users/alice/.cargo/bin/fnox` - Age key at `/Users/alice/.age/key.txt` - `npx` in PATH - Beeper Desktop running
عرض على GitHub