Skip to main content
juneui
New Member
March 26, 2026
Question

[MCP] loadFontAsync fails for locally installed fonts

  • March 26, 2026
  • 28 replies
  • 2547 views

 I ran into a font issue while working with MCP use_figma and wanted to share it here.

 

I have a font installed on my system (Pretendard) that works perfectly fine in the Figma UI — it shows up as "Installed by you" in the font picker. However, it's completely invisible to the Plugin API when running through MCP use_figma.

 

listAvailableFontsAsync() returns around 7,600 fonts, but none of them are locally installed ones. It seems to only return Google Fonts.

loadFontAsync() also fails, and trying to appendChild a component instance that contains text using the font throws a font load error — even into a non-auto-layout frame.

 

Steps to Reproduce

 1. Install a local font on your system (I tried both ~/Library/Fonts/ and /Library/Fonts/ on macOS)
 2. Confirm the font shows up normally in the Figma UI
 3. Run the following via MCP use_figma:

 const fonts = await figma.listAvailableFontsAsync();
 const result = fonts.filter(f => f.fontName.family === "Pretendard");
 return result.length; // 0

 await figma.loadFontAsync({ family: "Pretendard", style: "Bold" });
 // Error: The font "Pretendard Bold" could not be loaded.

 

This makes it impossible to work with design system libraries that use local fonts — which is very common in CJK environments (Korean, Japanese, etc.). You can create component instances on the page, but you can't put them inside frames or apply text styles, so you effectively can't build any screens through MCP.

 

Is there a known workaround for this, or is local font access not yet supported in the MCP beta?

Thanks.

28 replies

S1lverstein
New Member
April 27, 2026

Hey ​@megaroeny

 

Thank you for detailing what you discovered trying to use your Font Awesome font with the MCP; while expected when it comes to using a local font with the MCP, noting what you tested will be helpful for others who are not aware and try any of the tests you documented. Are the other fonts you listed local-only fonts, or were those uploaded to your organization?

 

Uploading fonts to your organization as mentioned by ​@Junko3  is another solution you can use in the meantime.

 

Thanks Adam, appreciate the acknowledgement — but I want to push back on the "limitation vs bug" framing from @Junko3 

If a file renders correctly in Figma desktop, the MCP has to render it correctly too. That's the floor. Right now the MCP can't read or mutate text on instances of components that use local fonts, which makes it structurally unusable for any design system that isn't built on Inter — i.e. essentially every branded product team out there.

The "upload to your organization" workaround is gated behind Org and Enterprise plans. For agencies and freelancers on Pro seats — a large share of the people generating MCP demand — that's not a workaround, it's "buy a different plan." And even on Org/Enterprise it isn't a quick fix: uploading a brand font is an admin/IT ticket that takes days to land, then has to be repeated for every new client engagement and every new pitch. We don't have that time. By the time the fonts are uploaded, the pitch is over.

Multiply that across every agency adopting MCP and the support load on your end won't be small either: every team will hit this, and every one of them will need to be told in person.

There's a conceptually clean fix: the MCP server is already connected to an authenticated desktop session that has the local fonts loaded and is rendering the file. Read them through that session instead of relying only on the server-side font list. Until that lands, please track this as a bug, not a feedback signal — labeling it a "limitation" tells your team this works as intended, and it very visibly doesn't. 
 

I just burned 1.5 hours and a non-trivial pile of Opus 4.7 tokens debugging why my agent couldn't update components in a file that renders perfectly in my Figma desktop. The agent did everything right — followed the official figma-use skill, applied text styles via importStyleByKeyAsync, bound variables, the lot. Every path failed at the same wall: Cannot use unloaded font "PP Neue Montreal Medium". The font is installed on my machine. Figma desktop renders it. The MCP can't see it. From a user's seat that is not a "limitation by design" — it's the tool silently failing on the most common possible input.

Victoria Roux
New Member
April 28, 2026

I agree with S1lverstein. Having to update my entire team to the org level for such a trivial feature is wild. This is a huge bug in the Figma MCP. 

Silverjerk
New Member
April 29, 2026

Just chiming in here as well to parrot S1lverstein and Victoria’s feedback. 

Without proper font support across every subscription level, the Figma MCP feature is dead in the water for our team. That blocker doesn’t encourage me to upgrade. What it does instead is puts myself and my team in a position to find an alternative tool that can provide similar results; one that doesn’t force us into an arbitrary upgrade path. 

Giving the Figma team the benefit of the doubt, I’m assuming this was an unintended consequence of existing subscription features that were in place before the Figma MCP released, leading to this frustrating (but otherwise inadvertent) bug. 

Please take this feedback to heart. At least where our team is concerned, an Org upgrade is not just about a financial constraint, it introduces a set of features that a team of our size simply won’t utilize. 

Darth_UX
New Participant
May 4, 2026

Just chiming in to say same problem here. I am doing some experiments with Claude making Data Grids in Figma and I can’t use Arial Regular. That’s not really acceptable, you know? Please find a way to fix this asap. We need to be able to use the common fonts we design in every day when we do prompt based design work.

Jacob Price
New Member
May 14, 2026

Really need an update here… 

Aaron_Xu
Active Member
May 15, 2026

My current solution is, ask AI to fallback font family to inter, then use a script to restore text style batchly.
here is my script

```javascript
/**
* 代码作用描述:
* 该脚本用于自动化管理 Figma 中的文本样式,共分为两个阶段:
* 1. 重置实例样式:遍历选中的组件实例,将其内部的文本样式重置为对应主组件(Main Component)的默认样式,消除冗余覆盖。
* 2. 自动匹配绑定:扫描所选范围内的独立文本层(以及重置后的文本),根据字号、字重(Weight)和行高,
* 自动从本地或已使用的非 Inter 字体样式中寻找最匹配的项并进行重新绑定。
*/
const selections = figma.currentPage.selection;
if (selections.length === 0) {
figma.notify("请选择至少一个图层。");
return;
}

// 1. 获取所有可用的目标样式(本地 + 已使用的导入样式),过滤掉 Inter 样式
const availableStyles = new Map<string, TextStyle>();
const localStyles = await figma.getLocalTextStylesAsync();
localStyles.forEach(s => availableStyles.set(s.id, s));

try {
const pageTextNodes = figma.currentPage.findAllWithCriteria({ types: ['TEXT'] });
for (const node of pageTextNodes) {
const styleId = node.textStyleId;
if (typeof styleId === 'string' && styleId !== '') {
if (!availableStyles.has(styleId)) {
const style = await figma.getStyleByIdAsync(styleId) as TextStyle | null;
if (style && style.type === 'TEXT') {
availableStyles.set(style.id, style);
}
}
}
}
} catch (e) {
console.warn("扫描已使用样式失败:", e);
}

const targetStyles = Array.from(availableStyles.values()).filter(s => s.fontName.family !== 'Inter');

// 2. 收集需要处理的节点(实例和独立文本)
const instances: InstanceNode[] = [];
const standaloneTexts: TextNode[] = [];

const traverse = (nodes: readonly SceneNode[]) => {
for (const node of nodes) {
if (node.type === 'INSTANCE') {
instances.push(node);
// 实例内部的文本由 Phase 1 统一处理,不再递归
} else if (node.type === 'TEXT') {
// 独立文本(非实例内部,ID 中不含分号)
if (!node.id.includes(';')) {
standaloneTexts.push(node);
}
}
// 递归处理容器(排除实例,因为 Phase 1 会内部处理)
if ('children' in node && node.type !== 'INSTANCE') {
traverse(node.children);
}
}
};
traverse(selections);

let resetCount = 0;
let matchedCount = 0;

// Phase 1: 重置实例中的文本样式(还原为组件默认)
for (const instance of instances) {
const mainComp = await instance.getMainComponentAsync();
if (!mainComp) continue;

const templateStyles = new Map<string, string | typeof figma.mixed>();
const templateTextNodes = mainComp.findAllWithCriteria({ types: ['TEXT'] });
for (const t of templateTextNodes) {
templateStyles.set(t.id, t.textStyleId);
}

const instanceTextNodes = instance.findAllWithCriteria({ types: ['TEXT'] });
for (const t of instanceTextNodes) {
const parts = t.id.split(';');
const templateId = parts[parts.length - 1];

if (templateStyles.has(templateId)) {
const styleId = templateStyles.get(templateId);
if (styleId !== figma.mixed && t.textStyleId !== styleId) {
await t.setTextStyleIdAsync(styleId as string);
resetCount++;
}
}
}
}

// Phase 2: 匹配并应用样式(针对独立文本或组件内的文本)
for (const textNode of standaloneTexts) {
if (textNode.hasMissingFont) continue;

const fontSize = textNode.fontSize;
const fontName = textNode.fontName;
const lineHeight = textNode.lineHeight;

if (fontSize === figma.mixed || fontName === figma.mixed || lineHeight === figma.mixed) {
continue;
}

const nodeFontStyle = (fontName as FontName).style.replace(/[\s-_]/g, '').toLowerCase();

// 寻找最佳匹配逻辑:
// 1. 首先找出所有字号和字重匹配的样式
const candidates = targetStyles.filter(style => {
if (style.fontSize !== fontSize) return false;
const styleFontStyle = style.fontName.style.replace(/[\s-_]/g, '').toLowerCase();
return styleFontStyle === nodeFontStyle;
});

if (candidates.length === 0) continue;

// 2. 在备选样式中,优先寻找行高也匹配的
let bestMatch = candidates.find(style => {
const styleLh = style.lineHeight;
const nodeLh = lineHeight as LineHeight;
if (styleLh.unit !== nodeLh.unit) return false;
if (styleLh.unit !== 'AUTO' && nodeLh.unit !== 'AUTO' && styleLh.value != null && nodeLh.value != null) {
if (Math.abs(styleLh.value - nodeLh.value) > 0.1) return false;
}
return true;
});

// 3. 如果没有行高完全匹配的,则退而求其次使用第一个字号字重匹配的样式
if (!bestMatch) {
bestMatch = candidates[0];
}

if (bestMatch && textNode.textStyleId !== bestMatch.id) {
await figma.loadFontAsync(textNode.fontName as FontName);
await textNode.setTextStyleIdAsync(bestMatch.id);
matchedCount++;
}
}

figma.notify(`完成:重置了 ${resetCount} 个实例文本,重新绑定了 ${matchedCount} 个独立文本。`);
```

tomoki
New Member
May 19, 2026

The workaround for now is using figma-console and its Figma Desktop Bridge plugin:


https://github.com/southleft/figma-console-mcp/tree/main

The setup is a bit convoluted, but it does work!

ramoses_
New Member
June 17, 2026

That can't be that hard to fix it. Figma acting like Adobe at this point taking too much time for something that is simple, avoiding the issue to make users pay more and not taking accountability with its decisions.