Repository navigation
MCP returns fallback code instead of Code Connect output for large instance subtrees #417
Description
Summary
Figma MCP (get_code_connect_map and get_design_context) stops returning a component's Code Connect template result once the selected instance has many connected descendants. It returns a fallback instead. Dev Mode shows the correct template result for the same node at the same time. MCP gives no error and no "lookup timed out" notice.
The parent template only returns a marker containing the instance name. It does not inspect or execute any children.
In a minimal reproduction made from generic components in a fresh file (no team library involved), we saw a consistent boundary:
- the template result is returned with 142 connected instances under the selected node;
- a fallback is returned from 143 connected instances.
This is an observation from our reproduction; we have not found any documentation of such a limit.
Environment
@figma/code-connect2.0.2, parserless templates (*.figma.ts)- Components and instances in the same file (no library publish needed to reproduce)
- Figma remote MCP server (
https://mcp.figma.com/mcp), called from Claude Code - Observed on 2026-10-24
Reproduction
Components
| Component | Content |
|---|---|
Cell |
TEXT property label |
HeaderCell |
TEXT property label |
Row |
a slot Cells, filled with Cell instances |
Table |
slots Head (filled with HeaderCell) and Body (filled with Row) |
Icon |
a plain icon |
IconCell |
a cell with a fixed Icon instance as a sublayer |
Every component has a Code Connect template, and slot contents are filled per instance.
Templates
Replace the URL in each template with the link to its corresponding component. Give each component its own template ID.
Table: a fixed string only.
// url=<link to the corresponding Figma component>
import figma from 'figma';
const instance = figma.selectedInstance;
export default {
id: 'Table',
imports: [],
example: figma.code`// PROBE-R v1 · ${instance.name}`,
metadata: { nestable: false },
};The child templates return simple tags and do not execute other templates. For example, Cell uses:
// url=<link to the corresponding Figma component>
import figma from 'figma';
const instance = figma.selectedInstance;
const label = instance.getString('label');
export default {
id: 'Cell',
imports: ["import { Cell } from './Cell'"],
example: figma.code`<Cell>${label}</Cell>`,
metadata: { nestable: true },
};Steps
- Publish the templates with
figma connect publish. - Place
Tableinstances whose row and header counts give different numbers of connected instances. The count includes the root and fixed sublayer instances. With six cells per row, 19 rows and eight headers give 142 instances including the table itself:1 + 19 + 19 × 6 + 8. Adding one header gives 143. - For each instance, select it in Dev Mode, and call
get_code_connect_mapandget_design_contextwith its node ID.
Results
get_code_connect_map: we judged each result only by whether the PROBE-R v1 mark is present in the root entry's snippet.
| Connected instances under the selected node | MCP root snippet | Dev Mode |
|---|---|---|
| 35, 42, 63, 84, 91, 98, 112, 119, 126, 133, 140, 141, 142 | // PROBE-R v1 · … (sizes run twice gave the same result) |
template result (checked at 35 and 142) |
| 143, 144, 145, 146, 147, 217 | <Table19Rows9Headers /> etc. (see below) |
template result (checked at 143, 143 with icons, and 217) |
What the fallback looks like:
get_code_connect_map: the root entry keepshasTemplate: true. Itssnippetis a tag named after the layer,snippetImportsis[], andsnippetNestedFunctionscontains one Tailwind design-code function. Every descendant entry still has its normal template snippet.get_design_context:- In the minimal reproduction, the
CodeConnectSnippetfor the root contains an auto-generated<Table body="…" head="…">with child tags instead of the template result. - In our production design system (a library used from another file), the response was Tailwind design code with no
CodeConnectSnippetat all.
- In the minimal reproduction, the
Other observations in the minimal reproduction:
- The same 142/143 boundary appeared when fixed icon instances were included in the count, even though those icons were absent from the map. A table of
IconCells with 82 map entries (142 instances including the fixedIconsublayers) succeeded, and one with 83 map entries (143 instances) fell back. - Adding plain layers did not trigger the fallback in our tests. A table with 63 connected instances and 1,086 nodes in total succeeded.
- A larger response still succeeded. A 140-instance table whose cell templates produce 400 characters each (an 83 KB response) returned the template result.
- The boundary did not move in any of these cases:
- adding up to 60 instances without templates;
- nesting instances up to 5 levels deep;
- adding hidden connected instances, in each of four ways: a boolean property defaulting to off,
visible = falsein the definition, a property turned off on the instance, and a layer hidden directly on the instance.
- A failed request completed in 6.9 seconds, while a successful request took 11.0 seconds. Total request duration alone therefore does not explain the fallback; a timeout within an internal stage remains possible.
Additional observation from a production library (different boundary)
We see the same fallback with our real components: a published library, with instances placed in another file. The boundary there was different.
How we counted:
- Connected means an instance of a component that has a Code Connect template, counted with the Plugin API with
figma.skipInvisibleInstanceChildren = false. - Hidden means the instance or one of its ancestors has
visible = false. Our tables have 18 such instances, hidden by component properties: header icons, footer cells and a loading spinner.
What we did: starting from an 11-row table, we added icons to a cell slot one at a time and ran each copy twice.
| Visible connected | Hidden connected | Total | Result |
|---|---|---|---|
| 121 | 18 | 139 | template result |
| 122 | 18 | 140 | template result |
| 123 | 18 | 141 | fallback |
| 124, 125, 126 | 18 | 142, 143, 144 | fallback |
So the production-library tests had a different boundary: 140 instances succeeded and 141 fell back when hidden connected instances were included in our count. Adding hidden instances did not move the boundary in the local reproduction. We have not isolated the cause of this difference.
Expected
MCP returns the same template result that Dev Mode shows. If MCP hits a limit, the response should say so, as the "Code Connect lookup timed out" notice does. Then clients can tell "not connected" apart from "lookup incomplete". Today the fallback looks like a normal snippet.
Questions
- Is there a limit on how many connected instances MCP resolves under one selected node? What exactly does it count (for example, hidden instances of library components), and is it documented?
- Can a client request only the selected node's template result, without resolving Code Connect output for its descendants?
- Could the fallback be marked explicitly, for example with a flag on the entry or a notice in the response?
Related: #407 ("Code Connect lookup timed out" on wide nodes).
Activity
nayukata commentedon Oct 27, 2026
We see the "library used from another file" case from this issue, but without the instance-count boundary. In our setup it fails even for a single instance.
Environment: remote MCP server (
https://mcp.figma.com/mcp) called from Claude Code, Enterprise plan with a Full seat,@figma/code-connect2.0.0 with template files, labelReact. Observed on 2026-10-27.Results (
get_design_contextwithclientFrameworks: "react"):get_design_contextget_code_connect_mapCodeConnectSnippetCodeConnectSnippetCodeConnectSnippetCodeConnectSnippeton 2026-09-09. Our last template change was published on 2026-09-10.disableCodeConnect: falseorclientFrameworks: "React"made no difference.So, apart from the 142/143 boundary,
get_design_contextmay also be failing to resolve Code Connect for any library instance placed in another file, whileget_code_connect_mapstill resolves it.islobodiuk-figma commentedon Oct 29, 2026
@nayukata this seems related to a regression that we fixed yesterday. Please try it again, and if the problem persist please report a bug.
uthem150 commentedon Oct 29, 2026
Following the fix mentioned above, we re-tested the case described in this issue on 2026-10-29, and the instance-count boundary still reproduces.
get_code_connect_mapon a published-libraryDataGridinstance with many connected descendants (164 entries in the map) still returnshasTemplate: truewith the rootsnippetbeing<DataGrid />and a Tailwind design-code function insnippetNestedFunctions, instead of the template result. Descendant entries still return their normal template snippets, and Dev Mode shows the correct template result for the same node (checked on the same day).Could you confirm whether the instance-count limit is expected behavior, and whether the fallback could be marked explicitly in the response?