Setup and context: The Challenge and Promise of Connecting Multiple MCPs
Adding a single MCP connector to Cowork gives Claude access to that service's tools. Figma for Figma, GitHub for GitHub, Stripe for Stripe — each one is incredibly useful on its own. But what indie developers truly want is a system where design updates automatically propagate to code, and new feature releases automatically update pricing pages — automation that crosses multiple services seamlessly.
The gap between "I have three MCPs installed" and "my three MCPs actually work together" is wider than most people expect. Each MCP operates in its own silo, with its own authentication, its own data formats, and its own failure modes. Bridging those silos requires deliberate orchestration design — not just connecting tools, but defining the logic that coordinates them.
In this article, we'll walk through designing and implementing an orchestration system that spans three MCPs — Figma, GitHub, and Stripe — using Cowork's skills, scheduled tasks, and custom prompts. We're publishing the complete blueprint, from architecture philosophy to working code examples, in a form that indie developers can put into practice immediately.
Why Orchestration Matters for Indie Developers
Solo developers and small teams face a unique challenge: they have to wear every hat simultaneously. Designer, engineer, marketer, and product manager — often all in the same afternoon. The cognitive overhead of context switching is enormous, and manual sync tasks (exporting Figma assets to GitHub, updating Stripe descriptions after releases, compiling weekly dashboards) eat into the focused time that actually moves the product forward.
Multi-MCP orchestration addresses this directly. Rather than manually bridging services, you define the information flow once — as a Cowork skill — and let Claude handle the bridgework every time. The first time you set up a design-to-code sync that runs automatically every morning, it feels like hiring a very capable assistant who never forgets, never gets bored, and never skips a step.
The key insight is that the value isn't in automating individual tasks; it's in automating the handoffs between tasks. The most time-consuming part of any workflow isn't the work itself — it's the coordination overhead between steps. Orchestration eliminates exactly that overhead.
What is MCP Orchestration?
Single MCP vs. Multiple MCP
With a single MCP, Claude acts as an agent that "performs operations on one service." With only the Figma MCP, for example, Claude can retrieve and describe a design file — but it can't automatically commit that design to GitHub.
Multi-MCP orchestration means giving Claude access to multiple services and defining the workflow (skill) that connects them. Claude acts as the orchestrator, calling each MCP in the appropriate sequence to complete a task. The skill file acts as the "runbook" — a precise specification of what steps to take, in what order, and what to do when things go wrong.
Think of it this way: a single MCP is like having a single specialist on call. Multi-MCP orchestration is like having a project manager who knows when to call which specialist, in what order, and how to handle it if one of them is unavailable.
Three Core Orchestration Design Patterns
Here are three patterns that are most useful in an indie developer context:
Pattern 1: Sequential (Step-by-Step Execution)
The simplest and most reliable form. Get data from MCP A, process it in MCP B, and save the result in MCP C — a linear flow. When an error occurs, stop immediately and log it. This pattern is predictable, easy to debug, and appropriate for the vast majority of automation tasks.
Example: Fetch design tokens from Figma → transform the data format → commit to GitHub → log the sync timestamp
The strength of the sequential pattern is that causality is clear. Each step depends on the previous one completing successfully, which means failures are easy to trace: if something breaks, you know exactly which step failed and why.
Pattern 2: Conditional (Branching Logic)
Branch the next action based on the previous step's result. For instance: "If the latest GitHub commit modified the src/design folder, re-sync Figma tokens; otherwise skip." This conditional execution avoids unnecessary API calls and speeds up your workflow considerably when most runs don't require all steps.
Conditional patterns are particularly powerful when you want to run a broad "check everything" skill on a schedule, but only take action when there's actually something to do. This keeps your API usage efficient and your logs clean.
Pattern 3: Fan-Out / Fan-In (Parallel Information Gathering)
Send requests to multiple MCPs in parallel and aggregate all results once they're available. While Cowork skills are inherently single-threaded, writing prompts like "please check the following in order, then compile a unified report" effectively simulates parallel information gathering within a skill. Claude will work through the sources sequentially, but the end result — a unified view across all services — is what matters.
This pattern shines in dashboard-type skills where you want a snapshot of the current state across your entire stack. Rather than checking Figma, then GitHub, then Stripe manually one by one, a single skill invocation gives you all three in one place.
Overall System Architecture
The system we'll build consists of three purpose-built components, each following the single-responsibility principle:
Component 1: Design Sync Skill (Figma → GitHub)
A skill that detects when Figma components or design tokens have been updated and automatically updates the corresponding files in the GitHub repository. This is the "design-to-code" bridge — the link between what something looks like and how it's implemented.
This skill is scheduled to run every morning. If Figma hasn't changed since the last sync, it logs "no changes" and exits. If there are changes, it exports the tokens, transforms them into the appropriate JSON format, and commits them to the repository with a descriptive commit message.
Component 2: Release Notification Skill (GitHub → Stripe)
A skill triggered when a GitHub release tag is created. It reads the release notes, transforms them into user-friendly language, and updates the Stripe product description — keeping your billing page accurate and up to date without any manual copy-paste work.
This skill is intentionally run on demand rather than on a fixed schedule, since releases are event-driven. You trigger it after creating a GitHub release, and it handles everything downstream.
Component 3: Integrated Dashboard Skill (Cross-MCP)
A morning skill that aggregates Figma design diffs, GitHub's latest commits, and Stripe's revenue summary into a single actionable report saved to your workspace. This is the "pulse check" — a daily snapshot that tells you where you are and what needs your attention.
The dashboard skill also serves as an orchestration entry point: if it detects unsynced Figma changes, it can invoke the design sync skill automatically.
Implementation Step 1: Configuring MCP Connectors
First, add each MCP connector in Cowork. Navigate to the Connectors section and configure them in the following order.
Figma MCP Setup
You'll need a Figma Personal Access Token. Log in to Figma and go to Settings → Account → Personal access tokens to generate a new token. The file_read scope is sufficient for reading designs and variables.
For the Cowork MCP server configuration:
{
"figma": {
"command": "npx",
"args": ["-y", "@figma/mcp-server"],
"env": {
"FIGMA_API_KEY": "YOUR_FIGMA_API_KEY"
}
}
}A few things worth noting about Figma tokens: they don't expire by default, but Figma can invalidate them if there are suspicious access patterns. It's a good idea to name your token descriptively (e.g., "cowork-automation") so you can identify and rotate it easily if needed.
GitHub MCP Setup
You'll need a GitHub Personal Access Token (classic). The required scopes are repo for private repositories or public_repo for public repositories only. If you're working in an organization, you may also need to enable SSO authorization for the token.
{
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "YOUR_GITHUB_TOKEN"
}
}
}GitHub tokens have configurable expiry (30, 60, or 90 days, or no expiry). For automation purposes, setting no expiry is convenient, but rotate the token regularly as a security best practice. Store it only in Cowork's connector settings, never in skill files or log files.
Stripe MCP Setup
Retrieve your secret key from the Stripe Dashboard under Developers → API Keys. We strongly recommend using a test mode key (sk_test_) before going to production. Test mode keys have the same capabilities as live mode keys but don't trigger actual charges, making them safe for development and validation.
{
"stripe": {
"command": "npx",
"args": ["-y", "@stripe/agent-toolkit", "mcp"],
"env": {
"STRIPE_SECRET_KEY": "YOUR_STRIPE_SECRET_KEY"
}
}
}One important note: Stripe MCP operations that modify data (updating products, creating coupons) are irreversible in the sense that they affect your live billing system immediately. Always test with sk_test_ first and validate each skill thoroughly before switching to sk_live_.
Implementation Step 2: Building the Design Sync Skill
Create a skill definition file (SKILL.md) using the following structure. This file lives in your Cowork workspace at _skills/figma-github-sync/SKILL.md.
---
name: figma-github-sync
description: Fetch design tokens from Figma and update tokens.json in the GitHub repository
---
# Figma → GitHub Design Sync Skill
## Pre-check
Before starting, check `_logs/figma-sync.txt` for the last sync timestamp.
If the last sync was within the past 4 hours, exit with "No sync needed" and log the skip.
## Steps
### Step 1: Retrieve Design Tokens from Figma
Get the design variables from Figma file {FIGMA_FILE_ID}.
Target: All variables on the "Tokens" page (Colors, Spacing, Typography).
### Step 2: Transform Data Format
Convert the retrieved variables into the following JSON structure:
```json
{
"colors": {
"primary": "#000000",
"secondary": "#ffffff",
"accent": "#0070f3"
},
"spacing": {
"xs": "4px",
"sm": "8px",
"md": "16px",
"lg": "24px",
"xl": "48px"
},
"typography": {
"fontFamily": "Inter, sans-serif",
"fontSizeBase": "16px"
}
}If the data doesn't map cleanly to this structure, save the raw export to
_pending/figma-tokens-YYYYMMDD-raw.json and flag for manual review.
Step 3: Commit to GitHub
Update src/tokens/design-tokens.json in {GITHUB_OWNER}/{GITHUB_REPO}:
- Branch: main
- Commit message: "chore: sync design tokens from Figma [auto-update YYYY-MM-DD]"
- Only commit if the content has actually changed from the current version
Step 4: Log the Sync
Append to _logs/figma-sync.txt:
[YYYY-MM-DD HH:MM] Synced N tokens — {COMMIT_SHA}
Error Handling
- Figma API unavailable: log to
_logs/figma-sync-errors.txt, exit - GitHub write fails: log the error with HTTP status code, exit
- Unexpected token schema: save raw data to
_pending/, log "manual review required", exit - Any 401/403 error: write to
_notifications/urgent.txt(see auth error pattern below)
The pre-check step — comparing against the last sync timestamp — prevents redundant API calls when the skill is triggered multiple times in quick succession. This is a small optimization with a meaningful impact when you're running skills on a tight schedule.
---
## Implementation Step 3: Scheduling the Skill
Daily design syncs are best run on a fixed schedule. Use Cowork's Scheduled Tasks to trigger the skill automatically.
Example scheduled task configuration:
Task name: figma-github-daily-sync Schedule: Daily at 09:00 JST Description: Fetch Figma design tokens and sync to GitHub repository
Instructions: Execute all steps in _skills/figma-github-sync/SKILL.md without skipping any steps. If any step fails, log to _logs/ and exit — do not attempt to continue with partial data. After completion, report the final status (SUCCESS / SKIPPED / FAILED) and the timestamp of the last successful sync.
Specifying "execute all steps in SKILL.md without skipping any steps" in the scheduled task prompt is critical. This instruction anchors Claude's behavior to the skill's defined workflow rather than allowing it to improvise or shortcut steps when something looks "probably fine."
### Scheduling Strategy
For a typical indie dev project, we recommend the following schedule:
- Design sync: 09:00 JST daily (catches overnight Figma changes before you start working)
- Dashboard report: 08:00 JST daily (gives you the daily overview before the design sync)
- Release sync: On demand (triggered manually after each GitHub release)
This ordering ensures your dashboard always reflects a "pre-sync" state, making unsynced changes visible in the morning report — which then serves as a reminder to run the design sync.
---
## Implementation Step 4: Building the Release Notification Skill
This skill updates Stripe product information when a GitHub release tag is created. Unlike the design sync, this skill is best run **on demand** rather than on a fixed schedule.
```markdown
---
name: github-stripe-release-sync
description: Fetch latest GitHub release info and update Stripe product description
---
# GitHub → Stripe Release Sync Skill
## Pre-execution Check
- Accept repository name as argument (default: {DEFAULT_REPO})
- Target Stripe product ID: {STRIPE_PRODUCT_ID}
- Confirm that a new release exists on GitHub since the last Stripe update
(check `_logs/stripe-sync.txt` for the last-updated version)
## Steps
### Step 1: Fetch Latest Release from GitHub
Get the latest release from {GITHUB_OWNER}/{repository-name}.
Retrieve:
- Version tag (e.g., v2.1.0)
- Full release notes body
- Published date and time
### Step 2: Transform Release Notes for Stripe
Apply these rules to produce a customer-facing description:
- Remove all Markdown headers (##, ###)
- Remove technical changes that end users don't care about
(internal refactoring, CI config changes, dependency bumps)
- Rewrite remaining items as complete sentences describing user benefits
- Add an introductory line: "What's new in {VERSION}:"
- Keep the total length under 200 characters for clean display in Stripe UI
Transformation example:
- Input notes:
Bug Fixes
- Fixed crash on iOS 17.4 when opening notifications
- Fixed memory leak in background sync
Internal
- Updated to React Native 0.73
- Output description:
`What's new in v2.1.0: Fixed a crash affecting iOS 17.4 users and improved background sync reliability.`
### Step 3: Preview and Confirm
Before updating Stripe, display the following for review:
Product ID: {STRIPE_PRODUCT_ID} New description: "{GENERATED_DESCRIPTION}" Last updated: {PREVIOUS_DATE}
Proceed with update? (yes to continue)
Do NOT proceed without explicit confirmation.
### Step 4: Update Stripe Product
Update the `description` field of Stripe Product {STRIPE_PRODUCT_ID}.
Set the value to: Step 2 output + ` (Updated: YYYY-MM-DD)`
### Step 5: Log the Update
Append to `_logs/stripe-sync.txt`:
`[YYYY-MM-DD HH:MM] v{VERSION} → Stripe product {PRODUCT_ID} updated`
`Description: {UPDATED_DESCRIPTION}`
## Important Notes
- This skill modifies a live Stripe product visible to paying customers.
- The confirmation step in Step 3 is mandatory and must not be skipped.
- If the generated description looks incorrect or truncated, abort and log "ABORTED — manual review required".
The confirmation step in Step 3 deserves special attention. In the context of full automation, it might seem counterproductive to include a manual confirmation gate. But for operations that directly affect customer-facing billing pages, that gate provides a crucial safety net against malformed data. The goal is not to eliminate human judgment entirely, but to eliminate the manual work while preserving the oversight.
Implementation Step 5: Building the Integrated Dashboard Skill
A morning skill that aggregates information from all MCPs — the centerpiece of the orchestration system.
---
name: daily-dev-dashboard
description: Generate a morning report aggregating Figma, GitHub, and Stripe data
---
# Indie Dev Daily Dashboard
## Purpose
Provide a unified snapshot of the current project state across design, development, and revenue.
Run every morning before starting work.
## Data Collection
### Section A: Design (Figma)
1. Retrieve file {FIGMA_FILE_ID}
2. Check the "last modified" timestamp
3. Compare with the last sync date from `_logs/figma-sync.txt`
4. Determine: unsynced changes exist (YES / NO)
### Section B: Development (GitHub)
1. Fetch all commits to {GITHUB_OWNER}/{GITHUB_REPO} in the past 24 hours
2. Get the count of open issues (label breakdown if available: bug / feature / question)
3. Check the latest release tag and its date
### Section C: Revenue (Stripe)
1. Count new subscriptions created in the past 24 hours
2. Sum total revenue (USD) from successful charges in the past 24 hours
3. Count subscription cancellations in the past 24 hours
## Report Assembly
Save the following to `_reports/dashboard-YYYY-MM-DD.md` in the workspace:
```markdown
# Indie Dev Daily Dashboard — YYYY-MM-DD
## Design (Figma)
- Last modified: YYYY-MM-DD HH:MM UTC
- Last synced: YYYY-MM-DD HH:MM UTC
- Status: ✅ Synced / ⚠️ Unsynced changes detected
## Development (GitHub)
- Commits (past 24h): N
- Open issues: N (bugs: N / features: N / other: N)
- Latest release: vX.Y.Z (YYYY-MM-DD)
## Revenue (Stripe)
- New subscriptions: N
- Revenue (past 24h): $X,XXX.XX
- Cancellations: N
## Action Items
[Generated based on conditions below]Condition-Based Action Items
Generate action items based on the following rules:
- If Figma has unsynced changes →
🎨 Run figma-github-sync skill - If open issues ≥ 10 →
🐛 Issue backlog critical — triage required - If open issues ≥ 5 →
📋 Review open issues - If a new release exists since last Stripe sync →
💳 Update Stripe product description - If cancellations > new subscriptions →
🚨 Net subscriber loss — review churn signals - If no commits in 48+ hours (check yesterday and today) →
💡 Low activity detected
Final Output
After saving the report file, output a 4-line summary: Line 1: Today's date and overall status (✅ All good / ⚠️ N action items) Line 2: Key design status Line 3: Key development status Line 4: Key revenue status
If there are action items, prepend the summary with "⚠️ Action Required:".
The condition-based action items are where this dashboard skill becomes genuinely useful rather than just a report generator. By encoding common decision logic directly into the skill, the morning report becomes an actionable to-do list, not just an information dump.
---
## Advanced Technique: Cross-Skill Invocation
Once you have multiple individual skills working reliably, you can build a meta-skill that invokes other skills based on the dashboard findings. This is the highest level of orchestration.
```markdown
---
name: morning-automation-runner
description: Run the dashboard, then automatically execute any required follow-up skills
---
# Morning Automation Runner
## Step 1: Generate Dashboard
Execute all steps in `_skills/daily-dev-dashboard/SKILL.md`.
Save the output to `_reports/dashboard-YYYY-MM-DD.md`.
## Step 2: Process Action Items
Read the generated dashboard report.
For each action item in the report:
**If "Run figma-github-sync skill" appears:**
Execute all steps in `_skills/figma-github-sync/SKILL.md`.
Log the result to `_logs/morning-runner-YYYY-MM-DD.txt`.
**If "Update Stripe product description" appears:**
Do NOT auto-run the Stripe sync (it requires manual confirmation).
Instead, log: "PENDING — github-stripe-release-sync requires manual trigger."
**If "Issue backlog critical" appears:**
Fetch the top 5 oldest open issues from GitHub and append them to the report:
`## Top Issues Requiring Attention`
`1. #{NUMBER}: {TITLE} (opened {DATE})`
## Step 3: Final Summary
Output a single status message:
`[HH:MM] Morning automation complete. Actions taken: {N}. Pending manual review: {M}.`
Notice that the Stripe sync is deliberately excluded from automatic invocation. This reflects a key design principle: automate confidently where errors are recoverable, but preserve human oversight where mistakes have customer-facing consequences.
Error Handling Design for Production
Handling MCP Timeouts
External MCP servers occasionally time out — especially when the external service is experiencing latency or is under maintenance. Adding explicit retry logic to your skills protects against transient failures without requiring manual intervention.
## Universal Error Handling Rules
For every MCP operation:
1. If the operation returns an error, record the error message.
2. Wait 30 seconds.
3. Retry the operation once.
4. If the retry also fails, log to `_logs/errors/YYYY-MM-DD-errors.txt`:
Format: `[HH:MM] {MCP_NAME} FAILED: {ERROR_MESSAGE} (HTTP {STATUS})`
5. Skip the failed section and continue with available data.
6. Mark the skipped section clearly in the report: "⚠️ {MCP_NAME} data unavailable — could not connect."The "continue with available data" approach is important for dashboard skills. A dashboard that fails entirely because Stripe had a 30-second blip is less useful than a dashboard that shows "Stripe data unavailable" while still giving you the Figma and GitHub snapshots.
Detecting Authentication Errors
Expired or revoked API tokens are the most common production issue. Add this to every skill that connects to external services:
## Authentication Error Detection
If any operation fails with HTTP 401 (Unauthorized) or 403 (Forbidden):
1. Log to `_logs/auth-errors.txt`:
`[YYYY-MM-DD HH:MM] {MCP_NAME}: AUTH FAILED — token may be expired or revoked`
2. Write an urgent notification to `_notifications/urgent.txt`:
`[URGENT] {MCP_NAME} API token is invalid.
Action required: Go to Workspace → Connectors → Update the {MCP_NAME} token.
Skill execution has been halted to prevent partial updates.`
3. Terminate skill execution immediately.
Do NOT attempt to continue or generate partial output.The reason for immediate termination on auth failure — rather than continuing with partial data — is subtle but important. If authentication to GitHub fails mid-way through a design sync, continuing might leave the repository in an inconsistent state (Figma tokens fetched but not committed). It's always safer to halt on auth errors and require a clean retry.
Common Design Mistakes and How to Avoid Them
Mistake 1: A "Do Everything" Skill Design
For foundational knowledge on setting up scheduled tasks, see Claude Cowork Scheduled Tasks Complete Guide. Advanced patterns for combining skills with schedules are covered in Cowork Skills × Schedules: Business Automation Design Patterns.
Trying to handle all MCPs in a single monolithic skill is tempting — it means fewer files to manage. But in practice, large skills are harder to debug, harder to reuse, and more likely to confuse Claude about sequencing.
Fix: Apply the single-responsibility principle. Each skill does exactly one thing: figma-github-sync syncs tokens, github-stripe-release-sync updates product descriptions, daily-dashboard generates reports. The dashboard skill can reference the others, but each is independently testable and runnable.
Mistake 2: Undefined Failure Behavior
A skill that only documents "what to do when it succeeds" is half a specification. Claude is an LLM — without explicit failure handling, it will improvise, which may mean continuing past errors, retrying indefinitely, or making unexpected API calls.
Fix: For every major step, add: "If this step fails, do X and proceed to Y." For write operations (especially to Stripe), add: "If any preceding step failed, do not execute this step under any circumstances."
Mistake 3: No Confirmation Step for Destructive Operations
Automating everything including production writes feels efficient until something goes wrong. A malformed description pushed to Stripe's product page, visible to all your customers, is not a recoverable situation in the same way a failed commit is.
Fix: For any operation with customer-visible or billing consequences, add an explicit confirmation gate in the skill. The goal is full automation of the work, with human oversight of the outcomes.
Mistake 4: Not Versioning Your Skills
Skill files are configuration, not just documentation. When a skill breaks or produces unexpected results, you want to know what changed. Keeping skill files in the same Git repository as your project code gives you a complete history of both the code and the automation that maintains it.
Fix: Store your _skills/ folder in version control. Commit skill changes with descriptive messages like fix: add retry logic to figma-github-sync error handling.
Summary
In this article, we walked through designing and building a three-MCP orchestration system in Cowork, covering:
If you'd like to explore the broader ecosystem design of connecting MCP servers, Claude Cowork × MCP Server Complete Integration Guide provides a comprehensive reference.
- Why orchestration matters: the real cost is coordination overhead, not execution time
- Three design patterns: sequential, conditional, and fan-out/fan-in
- Complete connector setup: Figma, GitHub, and Stripe
- Three skill implementations: design sync, release notification, and integrated dashboard
- Advanced cross-skill invocation: meta-skills that orchestrate other skills
- Production error handling: timeouts, auth errors, and partial failure recovery
- Common pitfalls: monolithic skills, undefined failures, missing confirmation gates, unversioned skill files
The deepest principle here is that orchestration is about encoding your decision-making, not just your actions. When you write a skill that says "if Figma has unsynced changes, run the sync; if there's a new release, remind me to update Stripe; if issues are piling up, surface the oldest ones" — you're not just automating tasks. You're delegating the cognitive work of knowing what to do next.
That cognitive offloading is where the real productivity gain comes from. Once your morning routine is handled by a 9:00 AM dashboard run, your first deliberate act of the day becomes whatever the dashboard tells you actually needs your judgment — not status checking.