Skip to content

Figma MCP: get_design_context output truncated at 50KB → generated frontend code silently drops design data (wrong colors, missing nodes, broken layout) #35661

Closed as not planned

Description

@Zby9999

Summary

When using the Figma MCP server (mcp.figma.com/mcp) with OpenCode, get_design_context returns a large React+Tailwind code blob that routinely exceeds OpenCode's 50 KB / 2,000 line tool-output truncation limit. The full output is silently offloaded to a tool-output file and the model is left with a truncated preview. The model rarely reads the spill file, so frontend code generated from Figma silently diverges from the source design — missing nodes, wrong colors, dropped table rows, broken layout. This is the single biggest cause of "Figma-to-code fidelity is poor" reports and it is not a Figma MCP bug — it is OpenCode's generic tool-output truncation policy misfiring on MCP tool results.

Reproduction (concrete, just ran on v1.17.14)

  1. opencode v1.17.14 on macOS, Figma MCP configured as remote (https://mcp.figma.com/mcp), authenticated via OAuth.
  2. Created a Figma design file with a realistic dashboard: header + 4 KPI tiles (each with a 12-bar sparkline) + a 45-row data table + footer. ~390 nodes total. Not unusually complex — a single medium screen.
  3. Called get_design_context(fileKey, nodeId=rootId, clientFrameworks=react, clientLanguages=typescript).

Result

  • Full MCP tool output: 54,606 bytes / 1,060 lines (measured at <REDACTED: local tool-output spill file>).
  • Truncation threshold (default): MAX_BYTES = 50 * 1024 = 51,200 bytes; MAX_LINES = 2_000. Byte cap fires first.
  • What the model actually received: the React/JSX code cut off mid-node at Row/John Collison → <p>$0 — i.e. the 41st of 45 table rows. The trailing ~3,414 bytes were dropped, which include:
    • the last 4 table rows (John Collison, Evan Spiegel, Bobby Murphy…),
    • the footer,
    • all the closing </div> tags,
    • the Figma MCP metadata footer (SUPER CRITICAL: ... convert to match target stack, asset URL declarations, node-id legend).

The truncation marker returned to the model:

...3414 bytes truncated...
The tool call succeeded but the output was truncated. Full output saved to: <REDACTED: user-local tool-output spill file path>
Use the Task tool to have explore agent process this file with Grep and Read (with offset/limit). Do NOT read the full file yourself - delegate to save context.

Observed downstream damage (why generated frontend "deviates from Figma")

When the model builds from the truncated preview, without reading the spill file:

  • Missing nodes: the last ~10% of the subtree (rows, footer, trailing structure) simply do not exist in the model's view → they are missing in the generated React component.
  • Broken JSX: the preview ends mid-<p> with no closing tags. The model either hallucinates the rest or emits unbalanced markup.
  • Lost design-intent metadata: the Figma MCP footer that carries conversion hints and asset URLs is in the truncated tail, so image sources and "convert to your stack" guidance are gone.
  • Color/spacing drift on larger files: at ~55 KB this repro is borderline. Real production Figma frames (full landing pages, dashboards with charts, multi-section marketing pages) easily hit 150–400 KB. There the head-preview still fits, but the model never sees the bulk of token bindings, variant props, or nested component structure — so it guesses, and the result is the "many data points deviate from the Figma reference" symptom the user reported.
  • The hint doesn't help enough: the truncation message tells the model to Task-delegate reading the spill file. In practice the model frequently skips that (it looks like a one-shot code gen task) and writes code from the head preview directly.

Root cause (source-confirmed)

In packages/opencode/src/session/tools.ts, every MCP tool result flows through:

const truncated = yield* truncate.output(textParts.join("\n\n"), {}, input.agent)
const metadata = {
  ...result.metadata,
  truncated: truncated.truncated,
  ...(truncated.truncated && { outputPath: truncated.outputPath }),
}

Truncate.output (packages/opencode/src/tool/truncate.ts) uses fixed defaults from packages/core/src/tool-output-store.ts:

export const MAX_LINES = 2_000
export const MAX_BYTES = 50 * 1024   // 50 KB

When either threshold is exceeded, the full text is written to a tool-output/tool_<id> file and the model receives only a head/tail preview + a hint. For MCP tools that return structured, essential-to-fidelity payloads (Figma get_design_context, Playwright DOM snapshots, large DB query results, get_figjam, etc.), the 50 KB cap is far too low and the head-only preview is the wrong shape:

Why this is worse for Figma than for e.g. Bash/Read

  • Bash/Read output is usually linear text where the head or tail carries most of the signal — a head+tail preview is a reasonable summary.
  • Figma get_design_context output is structured code + a metadata footer. Neither end is a summary; both ends carry distinct, non-redundant information (head = opening structure, tail = closing structure + conversion hints + asset map). A head-only preview loses ~50% of the signal even at 2× the threshold.
  • Figma MCP is also the canonical "design-to-code" path that the OpenCode skills (figma-implement-design, figma-use) explicitly route through get_design_context. So the truncation policy actively undermines a first-class documented workflow.

Expected behavior

  1. Raise the truncation threshold for MCP tool results, or make it per-tool/per-server configurable. 50 KB is a 2010-era limit; modern MCP tools (Figma, Playwright, Notion, Linear) routinely return 100–500 KB of structured JSON that is cheap to keep in context relative to its value. A saner default would be ~500 KB–1 MB, with a configurable cap.
  2. For MCP tools that return code/JSON, don't head-truncate — stream to file and pass a path, or send the whole thing when under the (higher) cap. The current "head preview + hope the model re-reads" pattern is the worst of both worlds: it costs a round-trip and still loses data.
  3. Make the recovery path actually work: if OpenCode is going to keep spill files, Read must respect offset/limit reliably (see Tool output truncation loses the most important content (background_output synthesis drop, read offset ignored, grep head_limit bypassed) #33650 symptom 2) and the truncation hint should be framed as a hard requirement, not a suggestion the model can skip.
  4. Surface truncation to the user in the TUI — currently the only signal is a line buried in the tool result that the model often ignores. A visible "⚠ tool output truncated, X bytes saved to Y, model may be missing data" indicator would let users catch silent fidelity loss.
  5. (Nice-to-have) Per-MCP-server overrides in opencode.json so power users can bump Figma's limit without raising it for everything.

Environment

  • OpenCode: 1.17.14 (npm opencode-ai, darwin-arm64)
  • OS: macOS (darwin, Apple Silicon)
  • Figma MCP: remote, https://mcp.figma.com/mcp, OAuth-authenticated
  • Reproduction file: created via create_new_file + use_figma (dashboard, 45-row table, ~390 nodes). Reproduces on any Figma frame whose get_design_context JSON exceeds ~50 KB — i.e. most real screens.

Workaround for affected users

Bump the limits in opencode.json under a tool_output document entry (undocumented but present in Config):

```jsonc
{
"tool_output": {
"max_bytes": 1048576, // 1 MB
"max_lines": 20000
}
}
```

This eliminates the truncation for the vast majority of Figma frames. But it's a global sledgehammer (also raises it for Bash/grep/etc.) and is not discoverable — most users hit the silent truncation first and conclude "Figma-to-code in OpenCode is just bad."

Related issues

Severity

High. This silently corrupts the most-hyped OpenCode workflow (Figma design-to-code) on any non-trivial screen, with no user-visible warning, and the documented recovery path (re-read the spill file) is itself broken. Users experience it as "the AI generates code that doesn't match my Figma" and blame either the model or Figma MCP — neither of which is at fault.

Activity

  1. github-actions commented on Jul 7, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    It may be worth checking whether one of those existing issues is the right place to track this, or if the Figma-specific angle (structured code + metadata footer, design-to-code workflow impact) warrants keeping it separate.

  2. github-actions commented on Sep 6, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions