Agent Font Access
Enables agents to inspect, search, create, and edit text layers in Figma Desktop using fonts installed locally on the computer, without uploading those fonts to Figma. It supports reading selected text and font details, finding exact local font family/style names, creating text layers with installed fonts, and applying batch edits while preserving unchanged formatting.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Agent Font AccessMake the selected heading 24pt but keep its current font."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Agent Font Access
Agent Font Access lets agents create and edit Figma text using fonts installed on your computer, without uploading those fonts to Figma. It pairs a local MCP server with a companion plugin in Figma Desktop.
Use Figma’s official MCP for surrounding layout and screenshots. The desktop workflow has been tested on macOS.
The Figma companion is installed through a development import. Either the agent plugin or standalone npm package can prepare its files for you.
When to use it
Use Agent Font Access when Figma Desktop can use a font that your agent’s remote Figma tools cannot load. As of October 2026, Figma’s remote MCP can access fonts uploaded to a Figma account, but cannot access fonts installed only on your computer. Account uploads are another option if your account supports them. See Figma’s MCP server FAQ.
Related MCP server: figma-ui-mcp
Installation
You need Node.js 24 or later, Figma Desktop with edit access to a file, and the required fonts installed locally.
Install the agent plugin for Claude Code or Codex to get the skill, local server, and Figma companion setup files together. The standalone setup below works with other MCP clients.
For Claude Code, install from the repository marketplace.
claude plugin marketplace add nweii/figma-local-fonts-mcp
claude plugin install agent-font-access@agent-font-access --scope userFor Codex, follow the marketplace and desktop installation steps.
Connect the standalone server
For an MCP client with a setup form, use either npx or bunx.
Command | Arguments |
|
|
|
|
Follow standalone setup to register the server and prepare the Figma companion without cloning this repository. Use source setup for development.
Connect Figma Desktop
Ask the agent to call
figma_local_fonts_statusand run itsprepareCommandif preparation is needed. The command returns the full manifest path.In Figma Desktop, select Plugins → Development → Import plugin from manifest… and choose that manifest. Import it once per installation.
Open the intended file and run Plugins → Development → Agent Font Access. If the companion is already open, click Find agent sessions.
Ask the agent to call
figma_local_fonts_status. It should list the intended file.Select a text layer and ask the agent to inspect it. Confirm that the returned text and font match your selection.
Keep the companion window open while inspecting or editing. Closing it disconnects the file. You can collapse its details into a compact status panel without disconnecting.
Let an agent set it up
Set up Agent Font Access for my local MCP client using README.md#installation. Preserve an existing working registration. Call status and follow its setup actions, including prepareCommand when present. Keep the installation credential private. Prepare the files before giving me the full manifest path and Figma import steps. After the companion opens in my intended file, verify that status lists that file and inspection returns my selected text and font. Report the checks that passed and any remaining manual step. Ask before testing a write on a disposable duplicate.Usage
Select text in Figma, or give the agent a node link, then ask for a change such as “Increase the selected heading to 24 while keeping its font.” For existing text, the agent inspects it before applying changes against its returned revision. For new text, the agent identifies the intended parent and exact local font, then creates the layer with that font already loaded.
Tool | Purpose |
| List connected desktop files |
| Read selected or specified text, including fonts, styles, dimensions, and revisions |
| Find exact font family and style names available in Figma Desktop |
| Create a text layer directly with its installed font, position, color, and wrapping dimensions |
| Apply a batch of changes using each target’s inspected revision |
Edits preserve formatting that the request does not change. The plugin checks every target and loads all required fonts before writing. A failed font load creates no layer. For edits, a preflight failure leaves the batch unapplied; a runtime failure can leave a partial batch. Check every returned state before continuing. Figma Undo can reverse the batch.
See text operations and limits for copy replacement, mixed styles, batch limits, and wrapping dimensions. The agent skill provides setup, routing, and recovery guidance. It is included in the agent plugin; standalone MCP registration does not install it.
Troubleshooting
If the agent’s server starts after the companion, click Find agent sessions. Ask the agent to check figma_local_fonts_status for setup actions.
See troubleshooting for missing connections, unavailable fonts, stale revisions, partial edits, and conflicting server builds.
Privacy and network access
The bridge connects only through this computer's loopback interface. It makes no requests to hosted services and does not upload font files. Text, styles, and file metadata returned through MCP reach the agent client and provider you use. Figma's normal document sync still applies.
See privacy and local storage for stored files, credentials, and data handling.
Uninstall
If you installed the agent plugin, remove Agent Font Access through your client's plugin manager. The CLI equivalents are below.
claude plugin uninstall agent-font-access@agent-font-access --scope user
codex plugin remove agent-font-access@agent-font-accessIf you registered the standalone MCP, remove that registration instead.
claude mcp remove --scope user figma_local_fonts
codex mcp remove figma_local_fontsClose the companion and remove its development entry in Figma. Close agent sessions still using the server so the shared broker can stop. Removing a registration leaves the installation credential and paired companion files on disk. See local storage for their locations. Move that directory to Trash if you want to remove those files too. Source checkouts and npm caches are separate from these files.
Development
Run the checks from the source repository directory.
npm run check
npm run build
npm testRun npm run check:release to install and exercise the npm archive, check the bundled agent servers, and assemble review archives under release/. This check uses npm, Bun, Claude Code CLI, zip, and unzip. It downloads npm dependencies and prepares temporary paired files; it does not publish.
The tests cover text preservation, direct creation, MCP routing, and connection recovery. For a live check, use a disposable layer, verify its text and font, then remove it.
Follow release instructions to publish through GitHub Actions and npm trusted publishing.
After source changes, build again and restart the MCP clients and shared broker so they load the rebuilt code. Reopen the Figma companion to load its generated files. See development restart instructions.
Support
For setup problems, start with troubleshooting. Report reproducible bugs in GitHub issues, with the package version, operating system, client, and steps to reproduce. Use fictional text in examples and keep credentials and paired UI files out of reports. For vulnerabilities, follow security reporting.
AI usage
The implementation and documentation were developed with AI coding agents under human direction.
License
MIT © 2026 Nathan Cheng.
Available Tools
5 toolsfigma_local_fonts_createCreate text with an installed fontA
Create one text layer directly with an exact local font, loaded before any layer appears. Supply the intended file connection, parent on the current page, name, text, font, size, and position. Returns the created node and revision for subsequent edits. If a response times out, inspect the parent before retrying to avoid a duplicate.
| Name | Required | Description | Default |
|---|---|---|---|
| x | Yes | Position relative to the parent; auto layout controls position in AUTO mode. | |
| y | Yes | ||
| name | Yes | ||
| color | No | Solid text color; defaults to black. | |
| width | No | ||
| height | No | ||
| opacity | No | ||
| fontName | Yes | Exact installed font from local font search or inspection. Loaded before creating any layer. | |
| fontSize | Yes | ||
| parentId | Yes | Visible, unlocked page, frame, group, component, or section on the current page. Instances are not supported. | |
| characters | Yes | Text to create with one font and style. | |
| lineHeight | No | ||
| connectionId | Yes | Exact connectionId from status for the intended file. | |
| letterSpacing | No | ||
| textAutoResize | No | WIDTH_AND_HEIGHT | |
| paragraphSpacing | No | ||
| layoutPositioning | No | Use ABSOLUTE inside an auto-layout frame to honor x and y. | AUTO |
| textAlignHorizontal | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes meaningfully beyond the annotations: it discloses that the font is loaded before any layer appears (partial-failure behavior), that the call returns the created node and revision, and that a timeout can produce a duplicate node. This is exactly the non-idempotent risk the idempotentHint=false annotation hints at but does not explain. It says nothing about permissions or failure modes other than timeout.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, front-loaded with the action and the atomicity guarantee, then inputs, return value, and the retry caveat. No filler; the only slightly wasteful phrasing is 'loaded before any layer appears' appearing in both the description and the fontName schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 18-parameter mutation with no output schema, the description covers the required path, states what is returned, and warns about the practical failure mode. What's missing is guidance on the optional typography and layout parameters, which leaves richer styling calls partly unspecified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 39% across 18 parameters. The description maps the eight required inputs well (connection, parent, name, text, font, size, x/y), but the ten optional styling params (letterSpacing, paragraphSpacing, textAutoResize, textAlignHorizontal, width/height, opacity, lineHeight) get no mention anywhere the agent will read, so the description does not compensate for the coverage gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Create one text layer') and adds two distinguishing qualifiers: an exact local font and atomic font loading before any layer appears. It separates itself from the siblings implicitly (creation vs. 'edit'), though it never names figma_local_fonts_edit or figma_local_fonts_search directly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It spells out the input contract ('Supply the intended file connection, parent on the current page, name, text, font, size, and position') and gives a concrete retry rule: on timeout, inspect the parent before retrying to avoid duplicates. It stops short of explicitly saying when to use this versus figma_local_fonts_edit, which is only implied by 'for subsequent edits'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_local_fonts_editEdit Figma text with local fontsADestructive
Edit 1–30 unique inspected text layers in one batch. Supply connectionId and edits with each nodeId, revision, and requested changes. All fonts and targets are checked before writing. A failed write returns applied states, the failing node state, and unattempted IDs; use those states before retrying.
| Name | Required | Description | Default |
|---|---|---|---|
| edits | Yes | ||
| connectionId | Yes | Exact connectionId returned by local inspection. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial behavior beyond the annotations: all fonts and targets are validated before any write, writes are not atomic (a failure returns applied states), and the response identifies the failing node and unattempted IDs with retry guidance. Revision-based stale-write protection is also disclosed, which is exactly the risk context a destructive batch tool needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, front-loaded with the operation and its size bound, then inputs, then validation, then failure handling. Every sentence carries distinct information with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description usefully explains the failure payload shape and retry path, and covers the required prior-inspection step. It never states explicitly that a successful partial application can also occur without an error, or how per-edit changes combine on one node, leaving a small gap for a complex nested batch schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50%; the description reinforces connectionId (from inspection) and revision (prevents stale edits) and states the 1–30 batch bound and uniqueness requirement. However, it lumps all mutable properties under 'requested changes' without enumerating them, so fields like lineHeight, letterSpacing, textAutoResize and textAlignHorizontal remain undocumented in both places.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Edit ... text layers') and adds real scope detail: batch of 1–30, layers must already be 'inspected'. An agent can distinguish this from the create sibling, though it never names the alternative explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Clear preconditions and context: layers must be 'inspected', connectionId and per-node revision come from 'local inspection', and the retry procedure is spelled out ('use those states before retrying'). No explicit exclusions or named alternatives (e.g., 'use figma_local_fonts_create for new text layers'), so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_local_fonts_inspectInspect local Figma textARead-onlyIdempotent
Inspect selected text or explicit text and container IDs. Containers return effectively visible nested text, including instances, up to 30 layers; explicit text IDs can inspect hidden text. Returns font runs, visibility, dimensions, and revisions for editing.
| Name | Required | Description | Default |
|---|---|---|---|
| nodeIds | No | Figma text or container IDs, including IDs from the official MCP. Containers return effectively visible text; an explicit text ID can inspect a hidden layer. | |
| connectionId | No | Plugin connection from figma_local_fonts_status. Omit only when exactly one file is connected. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, non-destructive behavior, and the description adds real semantics on top: the 30-layer cap, instance traversal, and the visibility rule that hidden layers are only reachable via explicit text IDs. Only the return shape details (beyond an enumerated list) are thin.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two dense sentences with no filler, and the input modes are front-loaded before the return contents. Slightly compressed to the point of reading as a spec dump, but nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description correctly tells the agent what comes back (font runs, visibility, dimensions, revisions). It omits any mention of the plugin connection prerequisite that connectionId encodes, which is the main remaining gap for a two-parameter read tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both nodeIds and connectionId are already documented in the schema, and the description's container-versus-text-ID sentence largely restates the nodeIds schema text. Baseline 3 applies since the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (inspect) and resource (text nodes/containers) plus the two input modes (selection vs explicit IDs). It reads distinctly from siblings like figma_local_fonts_search and figma_local_fonts_edit, though it never names them to force the contrast.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear routing within the tool: containers yield visible nested text, explicit text IDs can reach hidden layers. It doesn't say when to prefer search or edit instead, so the cross-tool guidance is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_local_fonts_searchFind installed Figma fontsARead-onlyIdempotent
Search fonts available to the open Figma Desktop file by family or style. Returns bounded matches with exact family and style names to use for an intentional font change.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes | Case-insensitive family or style search; returns exact installed names. | |
| connectionId | No | Plugin connection from status. Omit only when exactly one file is connected. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive and closed-world, so safety is covered. The description adds real context beyond them: results are scoped to the fonts visible to the currently open Figma Desktop file, and output is 'bounded matches' rather than an unbounded dump. It does not state what happens with no connected file, or how many matches are returned at the default limit.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero filler. The search scope and resource come first, and the downstream purpose and return-value character follow immediately.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With only three parameters, no output schema and annotations covering safety, the definition is nearly complete: it covers what is searched, the environment constraint, and the shape of the result (exact family/style names). A brief note on the empty-result or no-file-connected case would close the remaining gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 67%: 'query' and 'connectionId' are described in the schema, and 'limit' carries bounds and a default even without a description. The description adds no semantics on top of the schema — no format hints, no explanation of how limit interacts with 'bounded matches' — so the schema is doing the work.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Search fonts') plus scope ('available to the open Figma Desktop file by family or style'). The search/inspect/edit/create distinction is inferable from the tool name and the description's lookup framing, but the description never explicitly differentiates itself from the siblings figma_local_fonts_inspect or figma_local_fonts_status.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'to use for an intentional font change' hints that this runs before an edit, and 'by family or style' indicates matching modes. There is no explicit when-to-use, when-not, or named alternative (e.g. use inspect instead when you already know the exact family), so selection against the four sibling tools is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
figma_local_fonts_statusAgent Font Access connectionsARead-onlyIdempotent
List connected Figma Desktop files. Call first to identify the target file before inspecting or editing local-font text.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false and openWorldHint=false, so the safety profile is fully covered structurally. The description adds that this is a prerequisite discovery step, but says nothing about what a 'connected file' looks like or how connections appear/disappear.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, zero waste, with the purpose front-loaded and the call-ordering guidance immediately after. Nothing could be removed without losing information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description is the only place the agent could learn what the listing returns (file names? identifiers? font/connection state?). It establishes the discovery role but leaves the shape of the result — the thing the agent must feed into the inspect/edit tools — unspecified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate; the baseline of 4 applies. The description correctly implies no inputs are required to enumerate connected files.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List connected Figma Desktop files'), which usefully disambiguates the opaque tool name figma_local_fonts_status. It doesn't explicitly name the sibling tools it precedes, but the file-listing scope is clear.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Call first to identify the target file before inspecting or editing local-font text' gives a concrete sequencing rule and names the downstream activities it enables. It doesn't address the search/create siblings or say when this call can be skipped.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v0.1.0-beta.4- First observed
figma_local_fonts_create - First observed
figma_local_fonts_edit - First observed
figma_local_fonts_inspect - First observed
figma_local_fonts_search - First observed
figma_local_fonts_status
TDQS
Scored across 5 tools
Each tool has a clearly distinct role: status lists connections, search finds fonts, inspect reads text/font runs, create makes a new text layer, and edit batch-modifies inspected layers. The read/write boundaries are explicit, and create versus edit is differentiated by new-layer creation versus revision-based updates.
All tools follow the same figma_local_fonts_<verb> snake_case convention with clear action verbs. The shared prefix makes the grouping obvious while the verb suffix distinguishes operations.
Five tools are well-scoped for local-font text workflows in Figma Desktop: connection discovery, font search, inspection, creation, and batch editing. No tool appears redundant or out of place.
The surface covers the core lifecycle: identify a file, search fonts, inspect existing text, create text with a local font, and edit existing text. A delete/remove or broader text-layer discovery operation is absent, but the stated local-font access purpose is largely covered.
Maintenance
Related MCP Connectors
The Figma MCP server brings Figma design context directly into your AI workflow.
Design tool for agents: draw, edit and check designs in files your team edits and comments on.
OCR, transcription, file extraction, and image generation for AI agents via MCP.
Agent-Native design tool - create and edit visual designs with agent assistance
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to create, modify, and manage Figma designs through natural language commands via a specialized MCP server and plugin bridge. It supports a wide range of operations including element creation, property modification, component management, and accessibility checks.3 npm105MIT
- AlicenseAqualityDmaintenanceEnables MCP clients to read design structure, take screenshots, create nodes, and edit UI directly on Figma canvas via a bridge between MCP and Figma Desktop.10697 npmMIT
- AlicenseNot gradedqualityCmaintenanceEnables MCP clients like Codex to inspect, create, update, and export Figma designs through a local desktop plugin and bridge.MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to access locally installed fonts and control Figma text through a local bridge, including listing, auditing, replacing, and setting fonts on text nodes.2MIT