The night before I started a new settings screen, I sat staring at my MCP list. Both the Figma server and the Stitch server were already registered. Both turn screens into code, and either one gives you plausible SwiftUI. Yet on the days I picked one, I barely had to redo anything; on the days I picked the other, I rewrote everything by evening.
The difference wasn't the quality of the tools. It was who already held the correct screen.
The short answer
Figma MCP reads a screen that already exists. Stitch MCP helps you produce a screen that doesn't exist yet.
If a designer (or past me) finished the screen in Figma, connect Figma MCP. The code's job is fidelity to fixed dimensions, colors, and component structure. If all you have is a vague picture in your head, Stitch MCP is the better start: it proposes screens from a prompt, and you pick one as the starting point for code.
As an indie developer, I hit both situations in the same week. Putting the rule into words cut down the late-night dithering considerably.
What each server hands back
Most of the confusion comes from the surface similarity: both return screen information. The character of that information differs.
| Aspect | Figma MCP | Stitch MCP |
|---|---|---|
| Premise | A finished frame exists in Figma | No screen yet; you start from text or a reference image |
| What comes back | Layout, color, and typography data plus a screenshot | Generated screen proposals and the information to hand them to code |
| What code must do | Stay faithful to dimensions and tokens | Choose among proposals |
| How it fails | Code drifts a few pixels from the design | Each run differs, so there is no baseline |
| Best for | Implementing a settled design, reworking an existing app | First drafts, exploring direction |
The "how it fails" row mattered most to me. Drift against Figma can be counted as a diff, because a correct answer exists. Variation in Stitch can't be counted, because there is no correct answer yet. Whether you are enjoying the variation or trying to stop it decides the tool.
Three questions
I run through these in order.
First: does the correct screen exist in Figma? If so, use Figma MCP and stop there. Second: if not, do I want a proposal or an implementation right now? For a proposal, generate screens with Stitch and keep the one I like. If I want an implementation but have no screen, picking one proposal first is the shorter road. Third: will this screen keep changing? If yes, I place the chosen Stitch proposal into Figma as the new source of truth, and from then on Figma MCP carries the work alone.
For the days I'm too tired to think, here is that routine as a small script.
# choose_design_source.py
# Decide which MCP to enable before turning a screen into code.
# Usage: python3 choose_design_source.py --has-figma-frame yes --need proposal --keeps-changing yes
import argparse
def choose(has_frame: bool, need: str, keeps_changing: bool) -> tuple[str, str]:
"""Return (MCP to use, reason)."""
if has_frame:
return "figma", "The correct screen is in Figma. Read its dimensions and tokens."
if need == "implementation":
# Rushing to implement without a screen turns proposal variance into code variance
return "stitch", "No screen yet. Narrow to one proposal in Stitch before implementing."
if keeps_changing:
return "stitch→figma", "Draft in Stitch, then move the chosen one into Figma as the source of truth."
return "stitch", "Exploration phase. Accept variation and keep only the one you like."
def main() -> None:
p = argparse.ArgumentParser()
p.add_argument("--has-figma-frame", choices=["yes", "no"], required=True)
p.add_argument("--need", choices=["proposal", "implementation"], required=True)
p.add_argument("--keeps-changing", choices=["yes", "no"], default="no")
a = p.parse_args()
tool, why = choose(a.has_figma_frame == "yes", a.need, a.keeps_changing == "yes")
print(f"MCP to use: {tool}\nReason: {why}")
if __name__ == "__main__":
main()The logic is simple. Still, being asked "are you trying to implement without a screen?" every time stopped me at least twice.
What happened when I kept both connected
There was a period when I thought, "If I can't decide, I'll connect both." It didn't go well.
Every connected MCP server adds its tool descriptions to the agent's context. With two screen-generating systems loaded, the agent switched between them based on how I phrased the request. I'd ask it to "turn this screen into code," and it would go looking for a Figma frame, or start generating a brand-new screen in Stitch that I never asked for. More tools didn't make it more accurate; it just let the agent make the choice for me.
Now I enable only the side I need and keep the other's definition disabled. The CLI's mcp subcommand switches them without opening a config file.
# Register once (replace URLs and tokens with your own)
agy mcp add figma --type http https://mcp.figma.com/mcp
agy mcp add stitch --type http --header "Authorization: Bearer ${STITCH_TOKEN}" YOUR_STITCH_MCP_URL
# A day when Figma holds the correct screen
agy mcp disable stitch
agy mcp enable figma
agy mcp list # confirm by eye that exactly one is enabled
# A day when I'm exploring
agy mcp disable figma
agy mcp enable stitchFor Stitch, use the endpoint and auth method from the official setup instructions; I left YOUR_STITCH_MCP_URL blank on purpose. Figma's first connection (approval in the browser, for example) can also vary by environment, so I'd follow the official guide for that initial step.
Running agy mcp list after every switch is a dull habit that paid off. One morning a server I thought I had disabled was still on.
Moving the "correct answer" from Stitch to Figma
A note on the third question. Stitch is good at producing proposals, but maintaining a chosen proposal for months requires the correct screen to live somewhere outside the code, especially if someone else needs to review the design. I redraw the chosen Stitch screen as a Figma frame and make later changes there.
It looks like extra work. But Figma MCP then reads dimensions and tokens during implementation, and I recovered the cost by the second screen. Explore in Stitch, keep the answer in Figma, and let the code look only at the answer. That one sentence is my promise to myself.
The smallest test when you're still unsure
If the three questions don't settle it, try one existing screen before switching servers. Have Figma MCP read the frame of a screen you've already shipped and ask for a diff against the current code. If it produces a believable diff, you have a sign that it can be trusted as a reader of the correct answer.
For Stitch, send the same prompt twice and see how much the proposals vary. If the spread is tolerable, it suits exploration; if not, that screen is probably ready to have its answer fixed in Figma.
What to do next
Run agy mcp list and check that only one screen-related server is enabled. If two are, ask whether today's screen already has a correct answer, then agy mcp disable the side that doesn't match. I try never to skip that small step, even on rushed days.