diff --git a/buba-dashboard/public/index.html b/buba-dashboard/public/index.html new file mode 100644 index 0000000..217a8be --- /dev/null +++ b/buba-dashboard/public/index.html @@ -0,0 +1,1335 @@ + + + + + +Buba — Pastel Dream Dashboard ✦ + + + + +
+
✦ waking up ✦
+
+

✦ Buba Dream Dashboard ✦

+
Initializing...
+
+
+
+
00:00:00
+
— sessions today
+
+
+
Sessions
+
Sub-Agents
+
Active
+
Today
+
+
+
✦ Activity Feed
+
+
+
+ + + + diff --git a/buba-dashboard/server.js b/buba-dashboard/server.js new file mode 100644 index 0000000..75ca3c4 --- /dev/null +++ b/buba-dashboard/server.js @@ -0,0 +1,237 @@ +const express = require('express'); +const fs = require('fs'); +const path = require('path'); +const readline = require('readline'); + +const app = express(); +const PORT = 8890; + +const SESSIONS_DIR = '/Users/jakeshore/.clawdbot/agents/main/sessions'; +const WORKSPACE = '/Users/jakeshore/.clawdbot/workspace'; +const MEMORY_DIR = path.join(WORKSPACE, 'memory'); + +// Serve static files +app.use(express.static(path.join(__dirname, 'public'))); + +// Parse JSONL file (last N lines for efficiency) +async function parseSessionFile(filePath, maxLines = 50) { + const messages = []; + try { + const content = fs.readFileSync(filePath, 'utf8'); + const lines = content.trim().split('\n').slice(-maxLines); + for (const line of lines) { + try { + const parsed = JSON.parse(line); + messages.push(parsed); + } catch (e) { /* skip malformed */ } + } + } catch (e) { /* file not readable */ } + return messages; +} + +// Get all sessions with metadata +function getSessionFiles() { + try { + const files = fs.readdirSync(SESSIONS_DIR) + .filter(f => f.endsWith('.jsonl')) + .map(f => { + const fullPath = path.join(SESSIONS_DIR, f); + const stat = fs.statSync(fullPath); + return { + id: f.replace('.jsonl', ''), + file: f, + path: fullPath, + size: stat.size, + modified: stat.mtime, + created: stat.ctime, + }; + }) + .sort((a, b) => b.modified - a.modified); + return files; + } catch (e) { + return []; + } +} + +// Extract activity from messages +function extractActivity(messages, sessionId) { + const activities = []; + for (const msg of messages) { + const ts = msg.timestamp || msg.ts || null; + + if (msg.role === 'user') { + const content = typeof msg.content === 'string' ? msg.content : + Array.isArray(msg.content) ? msg.content.map(c => c.text || '').join(' ') : ''; + if (content && !content.startsWith('HEARTBEAT')) { + activities.push({ + type: 'user_message', + session: sessionId, + content: content.substring(0, 200), + timestamp: ts, + }); + } + } + + if (msg.role === 'assistant') { + const content = typeof msg.content === 'string' ? msg.content : + Array.isArray(msg.content) ? msg.content.map(c => c.text || '').join(' ') : ''; + + // Check for tool use + if (Array.isArray(msg.content)) { + for (const block of msg.content) { + if (block.type === 'tool_use') { + activities.push({ + type: 'tool_call', + session: sessionId, + tool: block.name, + content: block.name + (block.input?.command ? ': ' + block.input.command.substring(0, 80) : + block.input?.action ? ': ' + block.input.action : + block.input?.query ? ': ' + block.input.query.substring(0, 80) : ''), + timestamp: ts, + }); + } + } + } + + if (content && content !== 'NO_REPLY' && content !== 'HEARTBEAT_OK') { + activities.push({ + type: 'buba_reply', + session: sessionId, + content: content.substring(0, 200), + timestamp: ts, + }); + } + } + } + return activities; +} + +// API: Dashboard state +app.get('/api/state', async (req, res) => { + try { + const sessions = getSessionFiles(); + const now = Date.now(); + const oneHourAgo = now - (60 * 60 * 1000); + const oneDayAgo = now - (24 * 60 * 60 * 1000); + + // Categorize sessions + const activeSessions = sessions.filter(s => s.modified.getTime() > oneHourAgo); + const recentSessions = sessions.filter(s => s.modified.getTime() > oneDayAgo); + const subagentSessions = sessions.filter(s => s.id.includes('subagent')); + const activeSubagents = subagentSessions.filter(s => s.modified.getTime() > oneHourAgo); + + // Parse main session for recent activity + const mainSession = sessions.find(s => !s.id.includes('subagent')); + let recentActivity = []; + + // Get activity from recent sessions + const sessionsToScan = sessions.slice(0, 10); + for (const session of sessionsToScan) { + const messages = await parseSessionFile(session.path, 20); + const activity = extractActivity(messages, session.id); + recentActivity.push(...activity); + } + + // Sort by recency and limit + recentActivity.sort((a, b) => { + const ta = a.timestamp ? new Date(a.timestamp).getTime() : 0; + const tb = b.timestamp ? new Date(b.timestamp).getTime() : 0; + return tb - ta; + }); + recentActivity = recentActivity.slice(0, 50); + + // Read working state + let workingState = ''; + try { + workingState = fs.readFileSync(path.join(MEMORY_DIR, 'working-state.md'), 'utf8'); + } catch (e) { } + + // Read today's log + let todayLog = ''; + const today = new Date().toISOString().split('T')[0]; + try { + todayLog = fs.readFileSync(path.join(MEMORY_DIR, `${today}.md`), 'utf8'); + } catch (e) { } + + // Sub-agent details + const subagentDetails = []; + for (const sa of subagentSessions.slice(0, 20)) { + const messages = await parseSessionFile(sa.path, 5); + const firstMsg = messages.find(m => m.role === 'user'); + const lastMsg = [...messages].reverse().find(m => m.role === 'assistant'); + const isActive = sa.modified.getTime() > oneHourAgo; + + let task = ''; + if (firstMsg) { + const content = typeof firstMsg.content === 'string' ? firstMsg.content : + Array.isArray(firstMsg.content) ? firstMsg.content.map(c => c.text || '').join(' ') : ''; + task = content.substring(0, 150); + } + + subagentDetails.push({ + id: sa.id.split(':').pop().substring(0, 8), + fullId: sa.id, + task: task, + active: isActive, + lastModified: sa.modified, + size: sa.size, + }); + } + + // Stats + const totalSessions = sessions.length; + const totalSubagents = subagentSessions.length; + const todaysSessions = sessions.filter(s => { + const d = s.created.toISOString().split('T')[0]; + return d === today; + }).length; + + // Tools used today + const toolCounts = {}; + for (const act of recentActivity) { + if (act.type === 'tool_call') { + const tool = act.tool || 'unknown'; + toolCounts[tool] = (toolCounts[tool] || 0) + 1; + } + } + + res.json({ + timestamp: new Date().toISOString(), + buba: { + status: activeSessions.length > 0 ? 'active' : 'idle', + currentTask: workingState.split('\n').slice(0, 5).join('\n'), + uptime: '24/7', + }, + stats: { + totalSessions, + totalSubagents, + activeSessions: activeSessions.length, + activeSubagents: activeSubagents.length, + todaysSessions, + toolsUsedRecently: toolCounts, + }, + subagents: subagentDetails, + activity: recentActivity, + workingState: workingState.substring(0, 2000), + todayLog: todayLog.substring(0, 2000), + }); + } catch (e) { + res.status(500).json({ error: e.message }); + } +}); + +// API: Session detail +app.get('/api/session/:id', async (req, res) => { + try { + const sessionFile = path.join(SESSIONS_DIR, req.params.id + '.jsonl'); + const messages = await parseSessionFile(sessionFile, 100); + res.json({ messages }); + } catch (e) { + res.status(500).json({ error: e.message }); + } +}); + +app.listen(PORT, '0.0.0.0', () => { + console.log(`Buba Dashboard running at http://localhost:${PORT}`); + console.log(`Network: http://192.168.0.25:8890`); +}); diff --git a/good-society-2025-artist-stats.md b/good-society-2025-artist-stats.md new file mode 100644 index 0000000..405c86e --- /dev/null +++ b/good-society-2025-artist-stats.md @@ -0,0 +1,183 @@ +# Good Society 2025 Artist Statistics + +Research completed: January 2026 +Total Artists Researched: 67 + +## Artist Statistics Table + +| # | Artist | Platform | Monthly Listeners/Followers | Notes | +|---|--------|----------|----------------------------|-------| +| 1 | A Hundred Drums | Spotify | 58,200 | | +| 2 | Aaya | Spotify | 206 | Very small presence, may be emerging artist | +| 3 | Abelation | Spotify | 32,100 | | +| 4 | AIRGLO | Spotify | 45,400 | | +| 5 | Aych | Spotify | 3,200 | | +| 6 | Babsy. | Spotify | 455,400 | One of the largest artists | +| 7 | Baby Kush | SoundCloud | N/A | Active on SoundCloud, minimal Spotify presence | +| 8 | Badlike | Spotify | 5,900 | | +| 9 | BEMM | Spotify | 95 | Very emerging artist | +| 10 | Blue Blood | Spotify | 24,800 | | +| 11 | Buku | Spotify | 140,700 | | +| 12 | Bunny G | Spotify | 25 | Very small, emerging artist | +| 13 | capshun | Spotify | 25,500 | | +| 14 | Combine | SoundCloud | N/A | Couldn't locate Spotify profile | +| 15 | Dabow | Spotify | 29,000 | | +| 16 | Dehm | Bandcamp/SoundCloud | N/A | Active on Bandcamp via DOMEOFDOOM label | +| 17 | Depths | Spotify | 611 | Very small presence | +| 18 | Dêtre | SoundCloud/Apple Music | N/A | Active on SoundCloud, minimal Spotify | +| 19 | D!llema | N/A | N/A | Could not locate profile | +| 20 | Dimond Saints | Spotify | 60,100 | | +| 21 | DVNK | N/A | N/A | Could not locate profile | +| 22 | EAZYBAKED | Spotify | 136,000 | | +| 23 | Effin | Spotify | 333,200 | One of the largest artists | +| 24 | Farley. | Spotify | 36,400 | | +| 25 | Fly | Spotify | 63 | Very small artist, emerging | +| 26 | Gunpoint | Spotify | 36,600 | Dallas-based bass producer | +| 27 | Hamdi | Spotify | 1,400,000 | **LARGEST ARTIST** - UK dubstep | +| 28 | Handz | N/A | N/A | Could not locate profile | +| 29 | Hershe | N/A | N/A | Could not locate profile | +| 30 | JiLLi | Spotify | 36,200 | | +| 31 | jordnmoody | Spotify | 33,800 | | +| 32 | Juush | Spotify | 44,900 | | +| 33 | Know Good | Spotify | 389,900 | One of the larger artists | +| 34 | Litha | Spotify | 59 | Very small, may not be correct profile | +| 35 | Lumasi | Spotify | 80,700 | | +| 36 | MadBliss | Spotify | 13,300 | | +| 37 | Milano | SoundCloud | N/A | Lost Dogz member, unclear Spotify profile | +| 38 | Mindset | Spotify | 9,400 | Bass producer | +| 39 | Moceans | Spotify | 10,500 | | +| 40 | Nikita, The Wicked | Spotify | 248,500 | Large presence, San Francisco-based | +| 41 | Odd Language | Spotify | 30,200 | | +| 42 | Ooga | Spotify | 24,600 | Bay Area producer | +| 43 | PAV4N (P4van) | Spotify | 77,300 | UK grime/dubstep | +| 44 | Pastry. | SoundCloud | N/A | Bass Waffle curator, minimal Spotify | +| 45 | Phayla | Beatport/SoundCloud | N/A | Drum & bass producer | +| 46 | Phrva | Spotify | 61,400 | Rising dubstep artist | +| 47 | Ricky Marano | Spotify | 172,300 | | +| 48 | Roto | Spotify | 26,200 | | +| 49 | rSUN (Rsun) | Spotify | 154,300 | Virginia trap/bass producer | +| 50 | Sayara | Spotify | 93 | Very new artist (producing since Oct 2023) | +| 51 | Simula | Spotify | 202,900 | Large following | +| 52 | Solotrip | SoundCloud | N/A | Active on SoundCloud | +| 53 | Spunky | Spotify | 5,300 | | +| 54 | Sully | Spotify | 40,700 | UK dubstep/garage producer | +| 55 | Sumthin Sumthin | Spotify | 95,400 | | +| 56 | Terminal 6 | SoundCloud | N/A | Collaborates with Know Good | +| 57 | The Widdler | Spotify | 127,000 | Classic dubstep artist | +| 58 | Tone | N/A | N/A | Could not locate profile | +| 59 | Torcha | Spotify | 6,600 | Toronto-based 140 dubstep | +| 60 | Untitld | Spotify | 2,500 | | +| 61 | Violet | Spotify | 5,000 | Riverside, CA bass producer | +| 62 | Vyhara | Spotify | 4,800 | | +| 63 | Zen Selekta | Spotify | 34,100 | Atlanta-based ceremonial bass | + +## COLLABORATORS + +| # | Artist/Entity | Platform | Monthly Listeners/Followers | Notes | +|---|---------------|----------|----------------------------|-------| +| 64 | B Side | Spotify | 1,400 | Multiple profiles exist | +| 65 | Pirate Panda | N/A | N/A | Could not locate | +| 66 | Same Same But Different | Festival | N/A | This is a music festival, not an artist | +| 67 | Yappy Studios | N/A | N/A | Could not locate - may be production/visual studio | + +--- + +## Summary Statistics + +### By Size Category: + +**Major Artists (100K+ monthly listeners):** +- Hamdi: 1,400,000 +- Babsy.: 455,400 +- Know Good: 389,900 +- Effin: 333,200 +- Nikita, The Wicked: 248,500 +- Simula: 202,900 +- Ricky Marano: 172,300 +- rSUN: 154,300 +- Buku: 140,700 +- EAZYBAKED: 136,000 +- The Widdler: 127,000 + +**Mid-Tier Artists (20K-100K monthly listeners):** +- Sumthin Sumthin: 95,400 +- Lumasi: 80,700 +- PAV4N: 77,300 +- Phrva: 61,400 +- Dimond Saints: 60,100 +- A Hundred Drums: 58,200 +- AIRGLO: 45,400 +- Juush: 44,900 +- Sully: 40,700 +- Farley.: 36,400 +- Gunpoint: 36,600 +- JiLLi: 36,200 +- Zen Selekta: 34,100 +- jordnmoody: 33,800 +- Abelation: 32,100 +- Odd Language: 30,200 +- Dabow: 29,000 +- Roto: 26,200 +- capshun: 25,500 +- Blue Blood: 24,800 +- Ooga: 24,600 + +**Emerging Artists (5K-20K monthly listeners):** +- MadBliss: 13,300 +- Moceans: 10,500 +- Mindset: 9,400 +- Torcha: 6,600 +- Badlike: 5,900 +- Spunky: 5,300 +- Violet: 5,000 +- Vyhara: 4,800 +- Aych: 3,200 + +**Very Small/New Artists (Under 5K):** +- Untitld: 2,500 +- B Side: 1,400 +- Depths: 611 +- Aaya: 206 +- BEMM: 95 +- Sayara: 93 +- Fly: 63 +- Litha: 59 +- Bunny G: 25 + +**Artists Not Found on Spotify:** +- Baby Kush (SoundCloud only) +- Combine +- Dehm (Bandcamp/DOMEOFDOOM) +- Dêtre (SoundCloud/Apple Music) +- D!llema +- DVNK +- Handz +- Hershe +- Milano (Lost Dogz - unclear profile) +- Pastry. (SoundCloud primarily) +- Phayla (Beatport/SoundCloud) +- Solotrip (SoundCloud) +- Terminal 6 (Collaborator) +- Tone +- Pirate Panda +- Yappy Studios + +--- + +## Notes + +- **Hamdi** stands out as the festival's biggest booking by far with 1.4M monthly listeners +- Strong representation of mid-tier experimental bass artists (20K-100K range) +- Several very emerging artists with under 1,000 monthly listeners, indicating Good Society's commitment to new talent +- Many artists are primarily active on SoundCloud, Bandcamp, or other platforms rather than Spotify +- "Same Same But Different" is actually a music festival, not an artist +- "Yappy Studios" appears to be a production/visual studio rather than a music artist +- The lineup represents a strong mix of established bass music names and underground/emerging talent +- Geographic diversity: Artists from UK (Hamdi, Sully, PAV4N), California (Bay Area, LA, Riverside), Toronto, Atlanta, Dallas, Virginia, and more +- Genre span: Dubstep, drum & bass, experimental bass, trap, UK garage, 140, grime, and more + +--- + +**Research Method:** Web searches for Spotify monthly listeners were conducted for each artist. When Spotify data was unavailable, alternative platforms (SoundCloud, Apple Music, Bandcamp, Instagram, TikTok) were checked. Some artists could not be located on any major platform, which may indicate they are local DJs, visual artists, or have minimal online presence. + +**Data Current As Of:** January 2026 diff --git a/mcp-command-center/state.json b/mcp-command-center/state.json index 0f17c66..51bc7b2 100644 --- a/mcp-command-center/state.json +++ b/mcp-command-center/state.json @@ -1,7 +1,7 @@ { "version": 1, - "lastUpdated": "2026-02-12T22:02:00-05:00", - "updatedBy": "Buba (heartbeat: no advances — dec-004 still awaiting reaction 29h+, all else gated on API credentials)", + "lastUpdated": "2026-02-13T02:00:00-05:00", + "updatedBy": "Buba (heartbeat 2AM: no advances possible — dec-004 at 31h+ no reaction, 23 MCPs gated on Stage 7 design approval, 2 on API credentials)", "phases": [ { "id": 1, diff --git a/mcp-factory-v3/FACTORY-SPEC.md b/mcp-factory-v3/FACTORY-SPEC.md new file mode 100644 index 0000000..79016be --- /dev/null +++ b/mcp-factory-v3/FACTORY-SPEC.md @@ -0,0 +1,90 @@ +# MCP Factory V3 — Quality-First Build System + +## Quality Standards (Feb 2026) + +Every MCP server MUST include these features: + +### Server Architecture +- **Lazy-loaded tool modules** — tools loaded on-demand, not all at startup +- **Dual transport** — HTTP (SSE) + stdio support +- **Graceful shutdown** — SIGINT/SIGTERM handlers, connection cleanup +- **Health endpoint** — `/health` for monitoring +- **Structured logging** — JSON logs with levels, request IDs +- **Environment validation** — fail fast on missing required env vars + +### API Client +- **Retry with exponential backoff** — 3 retries, 1s/2s/4s delays +- **Rate limit awareness** — respect 429 headers, auto-throttle +- **Automatic pagination** — cursor/offset pagination abstracted away +- **Request/response interceptors** — logging, error normalization +- **Timeout handling** — 30s default, configurable per-request +- **Auth refresh** — auto-refresh OAuth tokens before expiry + +### Tool Quality +- **Strict inputSchema** — Zod validation on all inputs +- **Typed outputs** — consistent response shapes +- **Error categorization** — user errors vs system errors vs auth errors +- **Pagination support** — limit/offset/cursor params where applicable +- **Bulk operations** — batch create/update/delete where API supports it +- **Search/filter** — rich query params, not just list-all + +### React MCP Apps (UI Resources) +- **React 18+ with Suspense** — lazy loading components +- **Code splitting** — dynamic imports for heavy components +- **Error boundaries** — graceful error UI, not white screens +- **Loading skeletons** — shimmer/skeleton UI during data fetch +- **Dark theme** — CSS custom properties, #0f172a/#1e293b base +- **Responsive** — mobile-first, works on all screen sizes +- **Accessible** — ARIA labels, keyboard navigation, focus management +- **Optimistic UI** — instant feedback on user actions +- **Virtual scrolling** — for large lists (100+ items) +- **Toast notifications** — success/error feedback +- **Empty states** — helpful messaging when no data +- **Client-side search/filter** — instant filtering without API calls +- **Debounced inputs** — search inputs don't fire on every keystroke + +### TypeScript +- **Strict mode** — `"strict": true` in tsconfig +- **No `any` types** — everything typed, use `unknown` if needed +- **Discriminated unions** — for API response variants +- **Branded types** — for IDs (CustomerId, OrderId, etc.) + +### Documentation +- **README.md** — setup, env vars, examples, API reference +- **Tool catalog** — table of all tools with descriptions +- **App catalog** — table of all apps with screenshots descriptions + +## Factory Pipeline + +### Phase 1: Manifest Creation (Opus, 1 agent) +- Research API docs for each platform +- Create manifest.json with categories, endpoints, auth pattern +- Human review before proceeding + +### Phase 2: Foundation Build (Sonnet, 1 agent per server) +- API client + types + server shell +- Scope: ~15 min per server +- Verify: TSC compiles, server starts + +### Phase 3: Tool Build (Sonnet, 1 agent per server) +- All tool files based on manifest categories +- Scope: ~15 min per server +- Verify: TSC compiles, tool count matches manifest + +### Phase 4: App Build (Sonnet, 1 agent per server) +- All React apps +- Scope: ~15 min per server +- Verify: file count, each app has required files + +### Phase 5: Quality Pass (Sonnet, 1 agent per batch) +- TSC strict mode check +- Verify lazy loading patterns +- Check error boundaries exist +- Verify loading skeletons +- Fix any issues + +### Phase 6: Git + Deploy +- Commit each server individually +- Push to monorepo +- Sync to individual repos +- All done via bash script (zero tokens) diff --git a/mcp-factory-v3/manifests/batch-1.json b/mcp-factory-v3/manifests/batch-1.json new file mode 100644 index 0000000..79e4641 --- /dev/null +++ b/mcp-factory-v3/manifests/batch-1.json @@ -0,0 +1,47 @@ +[ + { + "name": "shopify", + "displayName": "Shopify", + "repo": "shopify-mcp-2026-complete", + "apiBase": "https://{store}.myshopify.com/admin/api/2024-01", + "auth": "oauth2", + "toolCategories": ["products", "orders", "customers", "inventory", "collections", "discounts", "shipping", "fulfillments", "themes", "pages", "blogs", "analytics", "webhooks"], + "appCount": 18 + }, + { + "name": "stripe", + "displayName": "Stripe", + "repo": "stripe-mcp-2026-complete", + "apiBase": "https://api.stripe.com/v1", + "auth": "bearer", + "toolCategories": ["charges", "customers", "subscriptions", "invoices", "products", "prices", "payment-intents", "payment-methods", "refunds", "disputes", "payouts", "balance", "events", "webhooks"], + "appCount": 18 + }, + { + "name": "quickbooks", + "displayName": "QuickBooks Online", + "repo": "quickbooks-mcp-2026-complete", + "apiBase": "https://quickbooks.api.intuit.com/v3/company/{realmId}", + "auth": "oauth2", + "toolCategories": ["invoices", "customers", "payments", "estimates", "bills", "vendors", "items", "accounts", "reports", "employees", "time-activities", "taxes", "purchases", "journal-entries"], + "appCount": 18 + }, + { + "name": "hubspot", + "displayName": "HubSpot", + "repo": "hubspot-mcp-2026-complete", + "apiBase": "https://api.hubapi.com", + "auth": "bearer", + "toolCategories": ["contacts", "companies", "deals", "tickets", "emails", "engagements", "pipelines", "lists", "forms", "campaigns", "blog", "analytics", "workflows", "webhooks"], + "appCount": 20 + }, + { + "name": "salesforce", + "displayName": "Salesforce", + "repo": "salesforce-mcp-2026-complete", + "apiBase": "https://{instance}.salesforce.com/services/data/v59.0", + "auth": "oauth2", + "toolCategories": ["accounts", "contacts", "leads", "opportunities", "cases", "tasks", "events", "campaigns", "reports", "dashboards", "users", "custom-objects", "soql", "bulk-api"], + "appCount": 20 + } +] diff --git a/mcp-factory-v3/manifests/batch-2.json b/mcp-factory-v3/manifests/batch-2.json new file mode 100644 index 0000000..8a43c1b --- /dev/null +++ b/mcp-factory-v3/manifests/batch-2.json @@ -0,0 +1,47 @@ +[ + { + "name": "notion", + "displayName": "Notion", + "repo": "notion-mcp-2026-complete", + "apiBase": "https://api.notion.com/v1", + "auth": "bearer", + "toolCategories": ["pages", "databases", "blocks", "users", "comments", "search"], + "appCount": 15 + }, + { + "name": "airtable", + "displayName": "Airtable", + "repo": "airtable-mcp-2026-complete", + "apiBase": "https://api.airtable.com/v0", + "auth": "bearer", + "toolCategories": ["bases", "tables", "records", "fields", "views", "webhooks", "automations"], + "appCount": 15 + }, + { + "name": "intercom", + "displayName": "Intercom", + "repo": "intercom-mcp-2026-complete", + "apiBase": "https://api.intercom.io", + "auth": "bearer", + "toolCategories": ["contacts", "conversations", "companies", "articles", "help-center", "tickets", "tags", "segments", "events", "messages", "teams", "admins"], + "appCount": 16 + }, + { + "name": "monday", + "displayName": "Monday.com", + "repo": "monday-mcp-2026-complete", + "apiBase": "https://api.monday.com/v2", + "auth": "bearer", + "toolCategories": ["boards", "items", "columns", "groups", "updates", "users", "teams", "workspaces", "folders", "webhooks", "automations"], + "appCount": 16 + }, + { + "name": "xero", + "displayName": "Xero", + "repo": "xero-mcp-2026-complete", + "apiBase": "https://api.xero.com/api.xro/2.0", + "auth": "oauth2", + "toolCategories": ["invoices", "contacts", "accounts", "bank-transactions", "payments", "bills", "credit-notes", "purchase-orders", "quotes", "reports", "employees", "payroll", "tax-rates"], + "appCount": 18 + } +] diff --git a/mcp-factory-v3/manifests/batch-3.json b/mcp-factory-v3/manifests/batch-3.json new file mode 100644 index 0000000..3fc67bf --- /dev/null +++ b/mcp-factory-v3/manifests/batch-3.json @@ -0,0 +1,47 @@ +[ + { + "name": "jira", + "displayName": "Jira/Atlassian", + "repo": "jira-mcp-2026-complete", + "apiBase": "https://{domain}.atlassian.net/rest/api/3", + "auth": "basic_or_oauth2", + "toolCategories": ["issues", "projects", "boards", "sprints", "users", "comments", "attachments", "transitions", "fields", "filters", "dashboards", "webhooks"], + "appCount": 18 + }, + { + "name": "linear", + "displayName": "Linear", + "repo": "linear-mcp-2026-complete", + "apiBase": "https://api.linear.app/graphql", + "auth": "bearer", + "toolCategories": ["issues", "projects", "teams", "cycles", "labels", "milestones", "users", "comments", "workflows", "webhooks"], + "appCount": 15 + }, + { + "name": "asana", + "displayName": "Asana", + "repo": "asana-mcp-2026-complete", + "apiBase": "https://app.asana.com/api/1.0", + "auth": "bearer", + "toolCategories": ["tasks", "projects", "workspaces", "teams", "users", "sections", "tags", "goals", "portfolios", "custom-fields", "status-updates", "webhooks"], + "appCount": 16 + }, + { + "name": "docusign", + "displayName": "DocuSign", + "repo": "docusign-mcp-2026-complete", + "apiBase": "https://{account}.docusign.net/restapi/v2.1", + "auth": "oauth2", + "toolCategories": ["envelopes", "templates", "recipients", "documents", "signing", "folders", "users", "accounts", "reports", "bulk-send"], + "appCount": 14 + }, + { + "name": "square", + "displayName": "Square", + "repo": "square-mcp-2026-complete", + "apiBase": "https://connect.squareup.com/v2", + "auth": "bearer", + "toolCategories": ["payments", "orders", "customers", "catalog", "inventory", "locations", "team", "invoices", "subscriptions", "loyalty", "bookings", "disputes", "refunds"], + "appCount": 18 + } +] diff --git a/mcp-factory-v3/manifests/batch-4.json b/mcp-factory-v3/manifests/batch-4.json new file mode 100644 index 0000000..011a857 --- /dev/null +++ b/mcp-factory-v3/manifests/batch-4.json @@ -0,0 +1,47 @@ +[ + { + "name": "klaviyo", + "displayName": "Klaviyo", + "repo": "klaviyo-mcp-2026-complete", + "apiBase": "https://a.klaviyo.com/api", + "auth": "bearer", + "toolCategories": ["profiles", "lists", "segments", "campaigns", "flows", "templates", "metrics", "events", "catalogs", "forms", "tags", "reporting"], + "appCount": 16 + }, + { + "name": "activecampaign", + "displayName": "ActiveCampaign", + "repo": "activecampaign-mcp-2026-complete", + "apiBase": "https://{account}.api-us1.com/api/3", + "auth": "api_key", + "toolCategories": ["contacts", "deals", "lists", "campaigns", "automations", "forms", "tags", "tasks", "notes", "pipelines", "accounts", "webhooks"], + "appCount": 16 + }, + { + "name": "salesloft", + "displayName": "Salesloft", + "repo": "salesloft-mcp-2026-complete", + "apiBase": "https://api.salesloft.com/v2", + "auth": "oauth2", + "toolCategories": ["people", "cadences", "emails", "calls", "accounts", "steps", "users", "teams", "imports", "activities", "notes"], + "appCount": 14 + }, + { + "name": "zoho-crm", + "displayName": "Zoho CRM", + "repo": "zoho-crm-mcp-2026-complete", + "apiBase": "https://www.zohoapis.com/crm/v6", + "auth": "oauth2", + "toolCategories": ["leads", "contacts", "accounts", "deals", "tasks", "events", "calls", "notes", "products", "quotes", "invoices", "campaigns", "blueprints", "workflows"], + "appCount": 18 + }, + { + "name": "sendgrid", + "displayName": "SendGrid", + "repo": "sendgrid-mcp-2026-complete", + "apiBase": "https://api.sendgrid.com/v3", + "auth": "bearer", + "toolCategories": ["mail", "contacts", "lists", "segments", "templates", "campaigns", "senders", "stats", "suppressions", "webhooks", "api-keys"], + "appCount": 14 + } +] diff --git a/mcp-factory-v3/manifests/batch-5.json b/mcp-factory-v3/manifests/batch-5.json new file mode 100644 index 0000000..4975efa --- /dev/null +++ b/mcp-factory-v3/manifests/batch-5.json @@ -0,0 +1,47 @@ +[ + { + "name": "greenhouse", + "displayName": "Greenhouse", + "repo": "greenhouse-mcp-2026-complete", + "apiBase": "https://harvest.greenhouse.io/v1", + "auth": "basic", + "toolCategories": ["candidates", "applications", "jobs", "offers", "scorecards", "interviews", "users", "departments", "offices", "custom-fields", "activity-feed"], + "appCount": 15 + }, + { + "name": "datadog", + "displayName": "Datadog", + "repo": "datadog-mcp-2026-complete", + "apiBase": "https://api.datadoghq.com/api/v2", + "auth": "api_key_app_key", + "toolCategories": ["monitors", "dashboards", "events", "metrics", "logs", "incidents", "service-checks", "hosts", "downtimes", "synthetics", "apm"], + "appCount": 16 + }, + { + "name": "supabase", + "displayName": "Supabase", + "repo": "supabase-mcp-2026-complete", + "apiBase": "https://{project}.supabase.co", + "auth": "bearer", + "toolCategories": ["database", "auth", "storage", "edge-functions", "realtime", "rpc", "migrations", "policies"], + "appCount": 14 + }, + { + "name": "typeform", + "displayName": "Typeform", + "repo": "typeform-mcp-2026-complete", + "apiBase": "https://api.typeform.com", + "auth": "bearer", + "toolCategories": ["forms", "responses", "workspaces", "themes", "images", "insights", "webhooks"], + "appCount": 12 + }, + { + "name": "chargebee", + "displayName": "Chargebee", + "repo": "chargebee-mcp-2026-complete", + "apiBase": "https://{site}.chargebee.com/api/v2", + "auth": "basic", + "toolCategories": ["subscriptions", "customers", "invoices", "plans", "addons", "coupons", "payments", "credit-notes", "events", "quotes", "exports"], + "appCount": 15 + } +] diff --git a/mcp-factory-v3/manifests/batch-6.json b/mcp-factory-v3/manifests/batch-6.json new file mode 100644 index 0000000..cbbc5f2 --- /dev/null +++ b/mcp-factory-v3/manifests/batch-6.json @@ -0,0 +1,47 @@ +[ + { + "name": "pandadoc", + "displayName": "PandaDoc", + "repo": "pandadoc-mcp-2026-complete", + "apiBase": "https://api.pandadoc.com/public/v1", + "auth": "bearer", + "toolCategories": ["documents", "templates", "contacts", "content-library", "forms", "webhooks", "workspaces", "members"], + "appCount": 12 + }, + { + "name": "loom", + "displayName": "Loom", + "repo": "loom-mcp-2026-complete", + "apiBase": "https://www.loom.com/v1", + "auth": "bearer", + "toolCategories": ["videos", "folders", "workspaces", "members", "comments", "transcripts", "analytics", "embeds"], + "appCount": 12 + }, + { + "name": "webflow", + "displayName": "Webflow", + "repo": "webflow-mcp-2026-complete", + "apiBase": "https://api.webflow.com/v2", + "auth": "bearer", + "toolCategories": ["sites", "pages", "collections", "items", "orders", "products", "inventory", "users", "forms", "webhooks", "assets"], + "appCount": 15 + }, + { + "name": "apollo", + "displayName": "Apollo.io", + "repo": "apollo-mcp-2026-complete", + "apiBase": "https://api.apollo.io/v1", + "auth": "api_key", + "toolCategories": ["people", "organizations", "contacts", "accounts", "sequences", "tasks", "emails", "opportunities", "labels", "lists", "enrichment"], + "appCount": 15 + }, + { + "name": "lever", + "displayName": "Lever", + "repo": "lever-mcp-2026-complete", + "apiBase": "https://api.lever.co/v1", + "auth": "basic_or_oauth2", + "toolCategories": ["opportunities", "candidates", "postings", "interviews", "offers", "stages", "users", "archive-reasons", "sources", "tags", "feedback-forms"], + "appCount": 14 + } +] diff --git a/mcp-factory-v3/scripts/build-manifest.sh b/mcp-factory-v3/scripts/build-manifest.sh new file mode 100755 index 0000000..a42cbcb --- /dev/null +++ b/mcp-factory-v3/scripts/build-manifest.sh @@ -0,0 +1,309 @@ +#!/bin/bash +# MCP Factory V3 — Manifest Builder +# Creates the manifest file for all 30 servers + +MANIFEST_DIR="$(dirname "$0")/../manifests" +mkdir -p "$MANIFEST_DIR" + +cat > "$MANIFEST_DIR/batch-1.json" << 'EOF' +[ + { + "name": "shopify", + "displayName": "Shopify", + "repo": "shopify-mcp-2026-complete", + "apiBase": "https://{store}.myshopify.com/admin/api/2024-01", + "auth": "oauth2", + "toolCategories": ["products", "orders", "customers", "inventory", "collections", "discounts", "shipping", "fulfillments", "themes", "pages", "blogs", "analytics", "webhooks"], + "appCount": 18 + }, + { + "name": "stripe", + "displayName": "Stripe", + "repo": "stripe-mcp-2026-complete", + "apiBase": "https://api.stripe.com/v1", + "auth": "bearer", + "toolCategories": ["charges", "customers", "subscriptions", "invoices", "products", "prices", "payment-intents", "payment-methods", "refunds", "disputes", "payouts", "balance", "events", "webhooks"], + "appCount": 18 + }, + { + "name": "quickbooks", + "displayName": "QuickBooks Online", + "repo": "quickbooks-mcp-2026-complete", + "apiBase": "https://quickbooks.api.intuit.com/v3/company/{realmId}", + "auth": "oauth2", + "toolCategories": ["invoices", "customers", "payments", "estimates", "bills", "vendors", "items", "accounts", "reports", "employees", "time-activities", "taxes", "purchases", "journal-entries"], + "appCount": 18 + }, + { + "name": "hubspot", + "displayName": "HubSpot", + "repo": "hubspot-mcp-2026-complete", + "apiBase": "https://api.hubapi.com", + "auth": "bearer", + "toolCategories": ["contacts", "companies", "deals", "tickets", "emails", "engagements", "pipelines", "lists", "forms", "campaigns", "blog", "analytics", "workflows", "webhooks"], + "appCount": 20 + }, + { + "name": "salesforce", + "displayName": "Salesforce", + "repo": "salesforce-mcp-2026-complete", + "apiBase": "https://{instance}.salesforce.com/services/data/v59.0", + "auth": "oauth2", + "toolCategories": ["accounts", "contacts", "leads", "opportunities", "cases", "tasks", "events", "campaigns", "reports", "dashboards", "users", "custom-objects", "soql", "bulk-api"], + "appCount": 20 + } +] +EOF + +cat > "$MANIFEST_DIR/batch-2.json" << 'EOF' +[ + { + "name": "notion", + "displayName": "Notion", + "repo": "notion-mcp-2026-complete", + "apiBase": "https://api.notion.com/v1", + "auth": "bearer", + "toolCategories": ["pages", "databases", "blocks", "users", "comments", "search"], + "appCount": 15 + }, + { + "name": "airtable", + "displayName": "Airtable", + "repo": "airtable-mcp-2026-complete", + "apiBase": "https://api.airtable.com/v0", + "auth": "bearer", + "toolCategories": ["bases", "tables", "records", "fields", "views", "webhooks", "automations"], + "appCount": 15 + }, + { + "name": "intercom", + "displayName": "Intercom", + "repo": "intercom-mcp-2026-complete", + "apiBase": "https://api.intercom.io", + "auth": "bearer", + "toolCategories": ["contacts", "conversations", "companies", "articles", "help-center", "tickets", "tags", "segments", "events", "messages", "teams", "admins"], + "appCount": 16 + }, + { + "name": "monday", + "displayName": "Monday.com", + "repo": "monday-mcp-2026-complete", + "apiBase": "https://api.monday.com/v2", + "auth": "bearer", + "toolCategories": ["boards", "items", "columns", "groups", "updates", "users", "teams", "workspaces", "folders", "webhooks", "automations"], + "appCount": 16 + }, + { + "name": "xero", + "displayName": "Xero", + "repo": "xero-mcp-2026-complete", + "apiBase": "https://api.xero.com/api.xro/2.0", + "auth": "oauth2", + "toolCategories": ["invoices", "contacts", "accounts", "bank-transactions", "payments", "bills", "credit-notes", "purchase-orders", "quotes", "reports", "employees", "payroll", "tax-rates"], + "appCount": 18 + } +] +EOF + +cat > "$MANIFEST_DIR/batch-3.json" << 'EOF' +[ + { + "name": "jira", + "displayName": "Jira/Atlassian", + "repo": "jira-mcp-2026-complete", + "apiBase": "https://{domain}.atlassian.net/rest/api/3", + "auth": "basic_or_oauth2", + "toolCategories": ["issues", "projects", "boards", "sprints", "users", "comments", "attachments", "transitions", "fields", "filters", "dashboards", "webhooks"], + "appCount": 18 + }, + { + "name": "linear", + "displayName": "Linear", + "repo": "linear-mcp-2026-complete", + "apiBase": "https://api.linear.app/graphql", + "auth": "bearer", + "toolCategories": ["issues", "projects", "teams", "cycles", "labels", "milestones", "users", "comments", "workflows", "webhooks"], + "appCount": 15 + }, + { + "name": "asana", + "displayName": "Asana", + "repo": "asana-mcp-2026-complete", + "apiBase": "https://app.asana.com/api/1.0", + "auth": "bearer", + "toolCategories": ["tasks", "projects", "workspaces", "teams", "users", "sections", "tags", "goals", "portfolios", "custom-fields", "status-updates", "webhooks"], + "appCount": 16 + }, + { + "name": "docusign", + "displayName": "DocuSign", + "repo": "docusign-mcp-2026-complete", + "apiBase": "https://{account}.docusign.net/restapi/v2.1", + "auth": "oauth2", + "toolCategories": ["envelopes", "templates", "recipients", "documents", "signing", "folders", "users", "accounts", "reports", "bulk-send"], + "appCount": 14 + }, + { + "name": "square", + "displayName": "Square", + "repo": "square-mcp-2026-complete", + "apiBase": "https://connect.squareup.com/v2", + "auth": "bearer", + "toolCategories": ["payments", "orders", "customers", "catalog", "inventory", "locations", "team", "invoices", "subscriptions", "loyalty", "bookings", "disputes", "refunds"], + "appCount": 18 + } +] +EOF + +cat > "$MANIFEST_DIR/batch-4.json" << 'EOF' +[ + { + "name": "klaviyo", + "displayName": "Klaviyo", + "repo": "klaviyo-mcp-2026-complete", + "apiBase": "https://a.klaviyo.com/api", + "auth": "bearer", + "toolCategories": ["profiles", "lists", "segments", "campaigns", "flows", "templates", "metrics", "events", "catalogs", "forms", "tags", "reporting"], + "appCount": 16 + }, + { + "name": "activecampaign", + "displayName": "ActiveCampaign", + "repo": "activecampaign-mcp-2026-complete", + "apiBase": "https://{account}.api-us1.com/api/3", + "auth": "api_key", + "toolCategories": ["contacts", "deals", "lists", "campaigns", "automations", "forms", "tags", "tasks", "notes", "pipelines", "accounts", "webhooks"], + "appCount": 16 + }, + { + "name": "salesloft", + "displayName": "Salesloft", + "repo": "salesloft-mcp-2026-complete", + "apiBase": "https://api.salesloft.com/v2", + "auth": "oauth2", + "toolCategories": ["people", "cadences", "emails", "calls", "accounts", "steps", "users", "teams", "imports", "activities", "notes"], + "appCount": 14 + }, + { + "name": "zoho-crm", + "displayName": "Zoho CRM", + "repo": "zoho-crm-mcp-2026-complete", + "apiBase": "https://www.zohoapis.com/crm/v6", + "auth": "oauth2", + "toolCategories": ["leads", "contacts", "accounts", "deals", "tasks", "events", "calls", "notes", "products", "quotes", "invoices", "campaigns", "blueprints", "workflows"], + "appCount": 18 + }, + { + "name": "sendgrid", + "displayName": "SendGrid", + "repo": "sendgrid-mcp-2026-complete", + "apiBase": "https://api.sendgrid.com/v3", + "auth": "bearer", + "toolCategories": ["mail", "contacts", "lists", "segments", "templates", "campaigns", "senders", "stats", "suppressions", "webhooks", "api-keys"], + "appCount": 14 + } +] +EOF + +cat > "$MANIFEST_DIR/batch-5.json" << 'EOF' +[ + { + "name": "greenhouse", + "displayName": "Greenhouse", + "repo": "greenhouse-mcp-2026-complete", + "apiBase": "https://harvest.greenhouse.io/v1", + "auth": "basic", + "toolCategories": ["candidates", "applications", "jobs", "offers", "scorecards", "interviews", "users", "departments", "offices", "custom-fields", "activity-feed"], + "appCount": 15 + }, + { + "name": "datadog", + "displayName": "Datadog", + "repo": "datadog-mcp-2026-complete", + "apiBase": "https://api.datadoghq.com/api/v2", + "auth": "api_key_app_key", + "toolCategories": ["monitors", "dashboards", "events", "metrics", "logs", "incidents", "service-checks", "hosts", "downtimes", "synthetics", "apm"], + "appCount": 16 + }, + { + "name": "supabase", + "displayName": "Supabase", + "repo": "supabase-mcp-2026-complete", + "apiBase": "https://{project}.supabase.co", + "auth": "bearer", + "toolCategories": ["database", "auth", "storage", "edge-functions", "realtime", "rpc", "migrations", "policies"], + "appCount": 14 + }, + { + "name": "typeform", + "displayName": "Typeform", + "repo": "typeform-mcp-2026-complete", + "apiBase": "https://api.typeform.com", + "auth": "bearer", + "toolCategories": ["forms", "responses", "workspaces", "themes", "images", "insights", "webhooks"], + "appCount": 12 + }, + { + "name": "chargebee", + "displayName": "Chargebee", + "repo": "chargebee-mcp-2026-complete", + "apiBase": "https://{site}.chargebee.com/api/v2", + "auth": "basic", + "toolCategories": ["subscriptions", "customers", "invoices", "plans", "addons", "coupons", "payments", "credit-notes", "events", "quotes", "exports"], + "appCount": 15 + } +] +EOF + +cat > "$MANIFEST_DIR/batch-6.json" << 'EOF' +[ + { + "name": "pandadoc", + "displayName": "PandaDoc", + "repo": "pandadoc-mcp-2026-complete", + "apiBase": "https://api.pandadoc.com/public/v1", + "auth": "bearer", + "toolCategories": ["documents", "templates", "contacts", "content-library", "forms", "webhooks", "workspaces", "members"], + "appCount": 12 + }, + { + "name": "loom", + "displayName": "Loom", + "repo": "loom-mcp-2026-complete", + "apiBase": "https://www.loom.com/v1", + "auth": "bearer", + "toolCategories": ["videos", "folders", "workspaces", "members", "comments", "transcripts", "analytics", "embeds"], + "appCount": 12 + }, + { + "name": "webflow", + "displayName": "Webflow", + "repo": "webflow-mcp-2026-complete", + "apiBase": "https://api.webflow.com/v2", + "auth": "bearer", + "toolCategories": ["sites", "pages", "collections", "items", "orders", "products", "inventory", "users", "forms", "webhooks", "assets"], + "appCount": 15 + }, + { + "name": "apollo", + "displayName": "Apollo.io", + "repo": "apollo-mcp-2026-complete", + "apiBase": "https://api.apollo.io/v1", + "auth": "api_key", + "toolCategories": ["people", "organizations", "contacts", "accounts", "sequences", "tasks", "emails", "opportunities", "labels", "lists", "enrichment"], + "appCount": 15 + }, + { + "name": "lever", + "displayName": "Lever", + "repo": "lever-mcp-2026-complete", + "apiBase": "https://api.lever.co/v1", + "auth": "basic_or_oauth2", + "toolCategories": ["opportunities", "candidates", "postings", "interviews", "offers", "stages", "users", "archive-reasons", "sources", "tags", "feedback-forms"], + "appCount": 14 + } +] +EOF + +echo "All 6 batch manifests created (30 servers total)" +ls -la "$MANIFEST_DIR" diff --git a/mcp-factory-v3/templates/AGENT-PROMPT-APPS.md b/mcp-factory-v3/templates/AGENT-PROMPT-APPS.md new file mode 100644 index 0000000..cfcd80e --- /dev/null +++ b/mcp-factory-v3/templates/AGENT-PROMPT-APPS.md @@ -0,0 +1,272 @@ +# App Build Agent Prompt + +Build ALL React MCP Apps for the {{NAME}} MCP server at {{DIR}}. + +## Foundation + Tools Already Exist +DO NOT modify any existing files. Only ADD app files under `src/ui/react-app/`. + +## Apps to Build + +{{APP_LIST}} + +## Quality Requirements — 2026 Standards + +### Each App Directory Structure +``` +src/ui/react-app/{app-name}/ +├── App.tsx # Main component +├── index.html # Entry point +├── main.tsx # React mount with ErrorBoundary +├── styles.css # Dark theme styles +└── vite.config.ts # Build config +``` + +### main.tsx — With Error Boundary + Suspense +```tsx +import React, { Suspense } from 'react'; +import ReactDOM from 'react-dom/client'; +import './styles.css'; + +// Lazy load the main app component +const App = React.lazy(() => import('./App')); + +// Error Boundary +class ErrorBoundary extends React.Component< + { children: React.ReactNode }, + { hasError: boolean; error?: Error } +> { + constructor(props: { children: React.ReactNode }) { + super(props); + this.state = { hasError: false }; + } + static getDerivedStateFromError(error: Error) { + return { hasError: true, error }; + } + render() { + if (this.state.hasError) { + return ( +
+

Something went wrong

+
{this.state.error?.message}
+ +
+ ); + } + return this.props.children; + } +} + +// Loading skeleton +function LoadingSkeleton() { + return ( +
+
+
+
+
+ ); +} + +ReactDOM.createRoot(document.getElementById('root')!).render( + + + }> + + + + +); +``` + +### App.tsx — Modern React Patterns +```tsx +import React, { useState, useMemo, useCallback, useTransition } from 'react'; + +// Debounce hook for search +function useDebounce(value: T, delay: number): T { + const [debounced, setDebounced] = React.useState(value); + React.useEffect(() => { + const t = setTimeout(() => setDebounced(value), delay); + return () => clearTimeout(t); + }, [value, delay]); + return debounced; +} + +// Toast notification system +function useToast() { + const [toasts, setToasts] = useState>([]); + const show = useCallback((message: string, type: 'success' | 'error' = 'success') => { + const id = Date.now(); + setToasts(prev => [...prev, { id, message, type }]); + setTimeout(() => setToasts(prev => prev.filter(t => t.id !== id)), 3000); + }, []); + return { toasts, show }; +} + +export default function App() { + const [search, setSearch] = useState(''); + const [isPending, startTransition] = useTransition(); + const debouncedSearch = useDebounce(search, 300); + const { toasts, show: showToast } = useToast(); + + // Mock data — replace with MCP tool calls + const [data] = useState(MOCK_DATA); + + // Client-side filtering with useMemo + const filtered = useMemo(() => + data.filter(item => + item.name.toLowerCase().includes(debouncedSearch.toLowerCase()) + ), [data, debouncedSearch]); + + return ( +
+ {/* Header with search */} +
+

{{App Title}}

+
+ startTransition(() => setSearch(e.target.value))} + className="search-input" + /> + {isPending && } +
+
+ + {/* Stats cards */} +
+ {/* Stat cards with numbers */} +
+ + {/* Data grid or dashboard content */} +
+ {filtered.length === 0 ? ( +
+

No results found

+ Try adjusting your search +
+ ) : ( +
+ {filtered.map(item => ( +
+ {/* Card content */} +
+ ))} +
+ )} +
+ + {/* Toast notifications */} +
+ {toasts.map(t => ( +
{t.message}
+ ))} +
+
+ ); +} +``` + +### styles.css — Dark Theme with CSS Variables + Skeleton Animation +```css +:root { + --bg-primary: #0f172a; + --bg-secondary: #1e293b; + --bg-tertiary: #334155; + --text-primary: #f1f5f9; + --text-secondary: #94a3b8; + --text-muted: #64748b; + --accent: #3b82f6; + --accent-hover: #2563eb; + --success: #22c55e; + --warning: #f59e0b; + --error: #ef4444; + --border: #334155; + --radius: 8px; + --shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3); +} + +* { margin: 0; padding: 0; box-sizing: border-box; } + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; + background: var(--bg-primary); + color: var(--text-primary); + min-height: 100vh; +} + +/* Skeleton loading animation */ +.skeleton { + background: linear-gradient(90deg, var(--bg-secondary) 25%, var(--bg-tertiary) 50%, var(--bg-secondary) 75%); + background-size: 200% 100%; + animation: shimmer 1.5s infinite; + border-radius: var(--radius); +} +@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } } + +/* Search input */ +.search-input { + background: var(--bg-secondary); + border: 1px solid var(--border); + color: var(--text-primary); + padding: 10px 16px; + border-radius: var(--radius); + width: 280px; + transition: border-color 0.2s; +} +.search-input:focus { outline: none; border-color: var(--accent); } +.search-input::placeholder { color: var(--text-muted); } + +/* Stats grid */ +.stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; margin-bottom: 24px; } + +/* Cards */ +.card { + background: var(--bg-secondary); + border: 1px solid var(--border); + border-radius: var(--radius); + padding: 20px; + transition: transform 0.15s, box-shadow 0.15s; +} +.card:hover { transform: translateY(-2px); box-shadow: var(--shadow); } + +/* Empty state */ +.empty-state { text-align: center; padding: 60px 20px; color: var(--text-secondary); } +.empty-hint { font-size: 14px; color: var(--text-muted); } + +/* Toast notifications */ +.toast-container { position: fixed; bottom: 20px; right: 20px; display: flex; flex-direction: column; gap: 8px; z-index: 1000; } +.toast { + padding: 12px 20px; + border-radius: var(--radius); + color: white; + font-weight: 500; + animation: slideIn 0.3s ease; + box-shadow: var(--shadow); +} +.toast-success { background: var(--success); } +.toast-error { background: var(--error); } +@keyframes slideIn { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } + +/* Responsive */ +@media (max-width: 768px) { + .stats-grid { grid-template-columns: repeat(2, 1fr); } + .search-input { width: 100%; } +} +@media (max-width: 480px) { + .stats-grid { grid-template-columns: 1fr; } +} +``` + +## Rules +- Each app MUST have: ErrorBoundary, Suspense, loading skeleton, empty state, toast system +- Debounced search on all grids/lists +- CSS custom properties (not hardcoded colors) +- Mobile responsive +- DO NOT modify existing files +- Commit when done: `git add src/ui/ && git commit -m "{{name}}: Add {{count}} React MCP apps"` diff --git a/mcp-factory-v3/templates/AGENT-PROMPT-FOUNDATION.md b/mcp-factory-v3/templates/AGENT-PROMPT-FOUNDATION.md new file mode 100644 index 0000000..4b7dec6 --- /dev/null +++ b/mcp-factory-v3/templates/AGENT-PROMPT-FOUNDATION.md @@ -0,0 +1,156 @@ +# Foundation Build Agent Prompt + +Build the foundation for the {{NAME}} MCP server at {{DIR}}. + +## What to Build + +### 1. `package.json` +```json +{ + "name": "@mcpengine/{{NAME}}", + "version": "1.0.0", + "type": "module", + "main": "dist/main.js", + "scripts": { + "build": "tsc", + "start": "node dist/main.js", + "dev": "tsx watch src/main.ts" + }, + "dependencies": { + "@modelcontextprotocol/sdk": "^1.12.1", + "axios": "^1.7.0", + "zod": "^3.23.0" + }, + "devDependencies": { + "typescript": "^5.6.0", + "tsx": "^4.19.0", + "@types/node": "^22.0.0" + } +} +``` + +### 2. `tsconfig.json` +```json +{ + "compilerOptions": { + "target": "ES2022", + "module": "Node16", + "moduleResolution": "Node16", + "outDir": "dist", + "rootDir": "src", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "declaration": true, + "resolveJsonModule": true, + "forceConsistentCasingInFileNames": true, + "noUncheckedIndexedAccess": true, + "jsx": "react-jsx" + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} +``` + +### 3. `src/types/index.ts` +- Define TypeScript interfaces for ALL API entities +- Use branded types for IDs: `type CustomerId = string & { __brand: 'CustomerId' }` +- Use discriminated unions for status fields +- Export everything + +### 4. `src/clients/{{NAME}}.ts` +API client with: +- Auth: {{AUTH_TYPE}} (Bearer token / API key / OAuth2) +- Base URL: {{API_BASE}} +- Retry with exponential backoff (3 retries, 1s/2s/4s) +- Rate limit awareness (respect 429 + Retry-After header) +- Automatic pagination (abstract cursor/offset) +- Request interceptors for logging +- Response interceptors for error normalization +- Timeout: 30s default +- OAuth token auto-refresh if applicable + +```typescript +import axios, { AxiosInstance, AxiosError } from 'axios'; + +export class {{PascalName}}Client { + private client: AxiosInstance; + private rateLimitRemaining = Infinity; + private rateLimitReset = 0; + + constructor(config: { apiKey?: string; accessToken?: string; baseUrl?: string }) { + this.client = axios.create({ + baseURL: config.baseUrl || '{{API_BASE}}', + timeout: 30000, + headers: { /* auth headers */ } + }); + + // Response interceptor for rate limiting + this.client.interceptors.response.use( + (res) => { + this.rateLimitRemaining = parseInt(res.headers['x-ratelimit-remaining'] || 'Infinity'); + this.rateLimitReset = parseInt(res.headers['x-ratelimit-reset'] || '0'); + return res; + }, + async (error: AxiosError) => { + if (error.response?.status === 429) { + const retryAfter = parseInt(error.response.headers['retry-after'] || '5'); + await this.sleep(retryAfter * 1000); + return this.client.request(error.config!); + } + throw this.normalizeError(error); + } + ); + } + + // Paginated fetch helper + async paginate(endpoint: string, params?: Record): Promise { ... } + + // Retry with exponential backoff + private async withRetry(fn: () => Promise, retries = 3): Promise { ... } +} +``` + +### 5. `src/server.ts` +MCP server with: +- Lazy-loaded tool modules (dynamic import) +- Resource handlers for UI apps +- Structured error responses +- Request logging + +```typescript +import { Server } from '@modelcontextprotocol/sdk/server/index.js'; + +// Lazy load tool modules +const toolModules = { + 'customers': () => import('./tools/customers-tools.js'), + 'orders': () => import('./tools/orders-tools.js'), + // ... etc +}; + +// Tools loaded on first call +const loadedTools = new Map(); + +async function getToolHandler(category: string) { + if (!loadedTools.has(category)) { + const mod = await toolModules[category](); + loadedTools.set(category, mod); + } + return loadedTools.get(category); +} +``` + +### 6. `src/main.ts` +Entry point with: +- Environment validation (fail fast) +- Dual transport (stdio + HTTP/SSE) +- Graceful shutdown handlers +- Health check endpoint + +### 7. `.env.example` + `.gitignore` + `README.md` + +## Rules +- DO NOT create tool files or app files — only foundation +- TSC must compile clean with `strict: true` +- Run `npm install` and `npx tsc --noEmit` to verify +- Commit when done diff --git a/mcp-factory-v3/templates/AGENT-PROMPT-TOOLS.md b/mcp-factory-v3/templates/AGENT-PROMPT-TOOLS.md new file mode 100644 index 0000000..3d2ec09 --- /dev/null +++ b/mcp-factory-v3/templates/AGENT-PROMPT-TOOLS.md @@ -0,0 +1,77 @@ +# Tool Build Agent Prompt + +Build ALL tool files for the {{NAME}} MCP server at {{DIR}}. + +## Foundation Already Exists +- `src/types/index.ts` — TypeScript interfaces +- `src/clients/{{NAME}}.ts` — API client with retry, pagination, rate limiting +- `src/server.ts` — Server shell with lazy loading +- `src/main.ts` — Entry point + +DO NOT modify these files. Only ADD tool files. + +## Tool Categories to Build + +{{TOOL_CATEGORIES}} + +## Quality Requirements for Each Tool File + +### Structure +```typescript +import { z } from 'zod'; +import { {{PascalName}}Client } from '../clients/{{NAME}}.js'; +import type { ToolDefinition } from '../server.js'; + +// Input schemas with Zod +const ListCustomersInput = z.object({ + limit: z.number().min(1).max(100).default(25).describe('Results per page'), + offset: z.number().min(0).default(0).describe('Pagination offset'), + search: z.string().optional().describe('Search by name or email'), + sort_by: z.enum(['name', 'created_at', 'updated_at']).default('created_at'), + sort_order: z.enum(['asc', 'desc']).default('desc'), +}); + +// Tool definitions +export function getTools(client: {{PascalName}}Client): ToolDefinition[] { + return [ + { + name: '{{name}}_list_customers', + description: 'List customers with pagination, search, and sorting', + inputSchema: ListCustomersInput, + handler: async (input) => { + const validated = ListCustomersInput.parse(input); + const results = await client.paginate('/customers', validated); + return { content: [{ type: 'text', text: JSON.stringify(results, null, 2) }] }; + } + }, + // ... more tools + ]; +} +``` + +### Each Tool MUST Have +- **Zod input schema** — with `.describe()` on every field +- **Pagination params** — limit/offset or cursor for list operations +- **Search/filter** — where the API supports it +- **Error handling** — catch and return meaningful error messages +- **Consistent naming** — `{{name}}_verb_noun` format (e.g., `shopify_list_orders`) + +### Tool Count Targets +- Each category: 4-8 tools (CRUD + search + bulk where applicable) +- Total per server: 40-60+ tools +- Every tool must be useful — no filler + +### Common Patterns Per Category +- `list_*` — paginated list with filters +- `get_*` — single item by ID +- `create_*` — create with validated input +- `update_*` — partial update by ID +- `delete_*` — delete by ID +- `search_*` — full-text or field search +- `bulk_*` — batch operations where API supports + +## Rules +- DO NOT modify existing files +- DO NOT create app files +- Run `npx tsc --noEmit` to verify everything compiles +- Commit when done diff --git a/mcpengine-repo b/mcpengine-repo index 2c41d0f..7afa320 160000 --- a/mcpengine-repo +++ b/mcpengine-repo @@ -1 +1 @@ -Subproject commit 2c41d0fb3b0c4a00c4b114551dc5efe835dc8bb7 +Subproject commit 7afa3208ac3d8e870855a6da2729a0b7d89a3e37 diff --git a/memory/2026-02-13.md b/memory/2026-02-13.md new file mode 100644 index 0000000..5f9c1fd --- /dev/null +++ b/memory/2026-02-13.md @@ -0,0 +1,58 @@ +# Daily Log — Feb 13, 2026 + +## Session Summary + +### SOLVR Contract (COMPLETE) +- Created full SOW (QU-026-20) — $20K, 6-week timeline, 50/25/25 payment split +- v2: Added § 5 Scope Flexibility (3 free software swaps, $300/hr capped at $900 for extra work) +- v2: Added § 4.5 Early Completion clause (full $10K due if finished before Week 3) +- v3: Added § 4.6 Gross Negligence definition (14-day missed deadline + 7-day no communication) +- Updated to Team Shore Services LLC dba MCPEngage +- Created Invoice INV-026-01 for $10K deposit (Wise payment) +- Files: `proposals/solvr-contract-sow.{html,md,pdf}`, `proposals/solvr-invoice-001.{html,pdf}` + +### Good Society 2025 Artist Research (COMPLETE) +- Researched all 67 artists from the lineup image +- Top artists: Hamdi (1.4M), Babsy (455K), Know Good (390K), Effin (333K) +- 53 found on Spotify, 14 SoundCloud/Bandcamp only +- Results saved: `good-society-2025-artist-stats.md` + +### Buba 3D Neural Dashboard (3 ITERATIONS) +- v1: Dark cyberpunk Three.js 3D city — Jake said too scary/liminal/angular +- v2: Added chibi character + bloom post-processing — still too dark +- v3: Complete pastel makeover — floating island, rounded buildings, Animal Crossing aesthetic +- Buildings: MCP Factory, SOLVR, CannaBri, TheNicheQuiz, CREdispo, OpenClaw, OSKV Coaching +- Trees, flowers, clouds, pond, sparkles, pastel gradient sky +- Server: `buba-dashboard/server.js` on port 8890 +- Frontend: `buba-dashboard/public/index.html` (54.5KB Three.js) +- **NOTE:** Server needs manual restart after reboot — `cd buba-dashboard && nohup node server.js &` + +### Atlanta Airport Chibi Image (COMPLETE) +- Generated kawaii chibi family running through ATL airport +- Learned Jake's preferred style = chibi/kawaii (NOT comic book) + +### Mac Mini Mouse Fix (REBOOT NEEDED) +- Mouse freezing issue — even wired mouse doesn't work +- Killed LM Studio Helper (99.8% CPU for 17 days!) +- Killed old puppeteer Chrome zombies +- Tried: Bluetooth reset, HID driver restart, input stack restart +- Resolution: Hard reboot needed (can't sudo reboot remotely) + +### MCP Factory V3 — Batch 1+2 Progress +- All 5 foundations complete: Xero, Monday, Intercom, Airtable, Notion +- All 5 tools phases complete: Xero (84), Monday (60), Intercom (71), Airtable (34), Notion (43) +- HubSpot apps complete (20 apps) +- 5 apps sub-agents queued but not started: Xero, Monday, Intercom, Airtable, Notion +- **Re-spawn these after reboot** + +## Key Decisions +- Jake's image style = chibi kawaii anime (ALWAYS default to this) +- Company name: Team Shore Services LLC dba MCPEngage +- SOLVR gross negligence = 14-day deadline miss + 7-day no communication +- Dashboard aesthetic: PASTEL, not cyberpunk (rounded, whimsical, bright) + +## Pending After Reboot +1. Re-spawn 5 MCP apps sub-agents (xero, monday, intercom, airtable, notion) +2. Restart buba-dashboard server on port 8890 +3. Verify mouse works after reboot +4. Jake may want to continue iterating on 3D dashboard visuals diff --git a/memory/lessons-learned.md b/memory/lessons-learned.md index 3cf5874..fc5abef 100644 --- a/memory/lessons-learned.md +++ b/memory/lessons-learned.md @@ -195,8 +195,79 @@ - **What happened:** Some use subdirectories, some use .tsx files, some use .ts files, some use .html files, some use src/apps/ instead of src/ui/react-app/ - **Rule:** Check ALL patterns: subdirs in react-app/, .tsx files, .ts files, .html files, AND src/apps/*.ts. Take the max. Use a consistent counting script. -*Last updated: 2026-02-12 22:20 EST* -*Total lessons: 25* +## MCP Factory Quality Standards (2026-02-13) + +### 26. ALWAYS start from the actual API spec — never hand-pick tools from vibes +- **Date:** 2026-02-13 +- **Mistake:** For the 30 SMB MCP servers, I read API docs casually and hand-picked 7-8 "obvious" tools per server +- **What happened:** Ended up with surface-level CRUD (list/get/create/update) covering maybe 10-15% of each API, missing the tools people actually need +- **Rule:** ALWAYS pull the official OpenAPI/Swagger spec (or systematically crawl every endpoint). Build a complete endpoint inventory BEFORE deciding what becomes a tool. If Mailchimp has 127 endpoints, I need to know all 127 before picking which 50 become tools. + +### 27. Prioritize tools by real user workflows, not alphabetical CRUD +- **Date:** 2026-02-13 +- **Mistake:** Mechanically created `list_X / get_X / create_X / update_X` for each resource — zero workflow awareness +- **What happened:** A CRM MCP that can `list_leads` but can't `log_a_call` or `add_note_to_lead` — the things salespeople do 50x/day +- **Rule:** Research the platform's top use cases. Map workflow chains (create contact → add to list → send campaign → check results). Tier the tools: + - **Tier 1 (daily):** 10-15 things every user does daily + - **Tier 2 (power user):** 15-30 things power users need + - **Tier 3 (complete):** Everything else for full API coverage + - Ship Tier 1+2 minimum. Tier 3 = "best on market" differentiator. + +### 28. Rich tool descriptions are NOT optional — they drive agent behavior +- **Date:** 2026-02-13 +- **Mistake:** Wrote basic descriptions like "Lists contacts" with minimal parameter docs +- **What happened:** AI agents make tool selection decisions based on descriptions. Vague = wrong tool chosen = bad UX +- **Rule:** Every tool description must tell an AI agent WHEN to use it: + - BAD: "Lists contacts" + - GOOD: "Lists contacts with optional filtering by email, name, tag, or date range. Use when the user wants to find, search, or browse their contact database. Returns paginated results up to 100 per page." + - Every param needs: description, type+format constraints, defaults, required/optional, example values + - `_meta` labels from day one: category, access (read/write/destructive), complexity, rateLimit + +### 29. Maintain a coverage manifest for every MCP server +- **Date:** 2026-02-13 +- **Mistake:** No tracking of which endpoints were covered vs skipped. No way to measure quality. +- **Rule:** Every server gets a coverage manifest in its README: + ``` + Total API endpoints: 127 + Tools implemented: 45 + Intentionally skipped: 12 (deprecated/admin-only) + Not yet covered: 70 (backlog) + Coverage: 35% → target 80%+ + ``` + Every skipped endpoint needs a REASON (deprecated, admin-only, OAuth-only, redundant). Set 80%+ as "production quality" threshold. + +### 30. 7-8 tools per server is a demo, not a product +- **Date:** 2026-02-13 +- **Mistake:** Treated 7-8 tools as "enough" for the initial 30 servers +- **What it actually is:** A toy. Nobody can do their real job with 7 tools for a platform that has 100+ API endpoints. +- **Rule:** Minimum viable tool count depends on API size: + - Small API (<30 endpoints): 15-20 tools + - Medium API (30-100 endpoints): 30-50 tools + - Large API (100+ endpoints): 50-80+ tools + - If customers install it and can't do their #1 use case, it's not a product. + +### 31. Consistent naming conventions across ALL servers — no exceptions +- **Date:** 2026-02-13 +- **Rule:** Factory-wide naming standard: + - `list_*` for paginated collections + - `get_*` for single resource by ID + - `create_*`, `update_*`, `delete_*` for mutations + - `search_*` for query-based lookups + - Domain verbs: `send_email`, `cancel_event`, `archive_card`, `assign_task` + - NEVER mix `fetch_*` / `get_*` / `retrieve_*` — pick ONE + - All snake_case, all lowercase + +### 32. Handle pagination and rate limits properly in every server +- **Date:** 2026-02-13 +- **Rule:** Every `list_*` tool must: + - Support cursor/page tokens + - Use reasonable default page sizes (25-100, never "all") + - Return `has_more` / `next_page` indicators + - Handle API rate limits (429) with retry + exponential backoff + - Document known rate limits in tool `_meta` + +*Last updated: 2026-02-13 02:46 EST* +*Total lessons: 32* ### 17. Jake's Preferred Image Style - **Mistake:** Used comic book/vibrant cartoon style when Jake asked for "the style I like" diff --git a/memory/working-state.md b/memory/working-state.md index b0fbf09..1054925 100644 --- a/memory/working-state.md +++ b/memory/working-state.md @@ -1,26 +1,28 @@ -# Working State — Last Updated Feb 12, 11:00 PM ET +# Working State — Last Updated Feb 13, 3:35 AM ET ## Right Now -End-of-day memory checkpoint. All major work done for today. Sub-agents for batch 5+6 may have completed or failed (rate limits hit tonight). +About to reboot Mac mini to fix mouse/input freeze. All work saved. + +## Pending After Reboot +1. Re-spawn 5 MCP V3 apps sub-agents (xero, monday, intercom, airtable, notion) +2. Restart buba-dashboard server: `cd buba-dashboard && nohup node server.js > /tmp/buba-dashboard.log 2>&1 &` +3. Verify mouse works +4. Continue MCP Factory V3 pipeline ## Today's Done List -- TheNicheQuiz.com: fully deployed (domain + Worker + Flask + Postgres) -- CannaBri site: built + deployed to GitHub Pages -- Veo 3.1 video generation: first successful test -- MCP Factory V2 batches 1-4: 20 servers complete, committed, pushed -- Batch 5+6: 6 fixer sub-agents spawned for remaining 10 servers -- dec-003 resolved (approved 2, killed HR People Ops) -- dec-004 reminder posted (still pending after 29h) -- Burton Method competitor scan #6 posted -- OpenClaw contract SOW updated with LLC name -- All repos pushed (mcpengine, GHL, workspace) -- .gitignore fixed to exclude .next/ dirs -- Discord TLDR summaries generated +- [x] SOLVR contract v1/v2/v3 + invoice INV-026-01 +- [x] Good Society 2025 artist research (67 artists) +- [x] Buba 3D Dashboard v1/v2/v3 (pastel floating island) +- [x] Atlanta airport chibi image +- [x] MCP V3 Batch 1 foundations (5 servers) +- [x] MCP V3 Batch 1 tools (5 servers: 292 tools total) +- [x] MCP V3 HubSpot apps (20 apps) +- [x] Killed LM Studio (99.8% CPU for 17 days) +- [x] Fixed Xbox Controller Manager issue +- [x] Mouse troubleshooting (reboot needed) -## Pending -- dec-004: Registry listing approval (29h+ pending) -- Jake's coaching decision for Oliver/Kevin (paused at Day 7) -- CREdispo domain purchase -- Verify batch 5+6 sub-agent results -- Complete all 30 servers → research 5 new high-money MCPs -- fatgordo's CannaBri original imagery request (needs Jake approval) +## MCP Factory V3 Status +- **Foundations done:** Xero, Monday, Intercom, Airtable, Notion +- **Tools done:** Xero (84), Monday (60), Intercom (71), Airtable (34), Notion (43) +- **Apps done:** HubSpot (20) +- **Apps queued (re-spawn after reboot):** Xero, Monday, Intercom, Airtable, Notion