Installation¶
Everything runs locally: a .NET tool started by your MCP client, plus a plugin inside Figma Desktop.
Nothing is uploaded anywhere, and the only outbound traffic is to api.figma.com when a tool actually
needs REST.
What you need¶
| .NET 10 SDK | dotnet.microsoft.com/download. The SDK ships the ASP.NET Core runtime the bridge needs; installing the runtime alone is not enough to run dotnet tool install |
| An MCP client | Claude Code, Claude Desktop, Cursor, VS Code, Codex, Windsurf — anything that starts an MCP server over stdio |
| Figma Desktop | Required for every write tool and for quota-free reads. Any plan, including free. Browser Figma cannot run a development plugin |
| A Figma token | Optional — only the REST channel uses it |
macOS, Windows and Linux are all supported. Check the SDK with:
dotnet --version # 10.x
Step 1 — install the server¶
As a global tool (recommended)¶
dotnet tool install -g Snail.MCP.Figma
This gives you an s3l-mcp-figma command, which is what MCP clients will start. Verify:
dotnet tool list -g | grep snail # snail.mcp.figma <version> s3l-mcp-figma
If the shell answers command not found, the tools folder is not on PATH:
| OS | Folder | Fix |
|---|---|---|
| macOS, Linux | ~/.dotnet/tools |
add export PATH="$PATH:$HOME/.dotnet/tools" to ~/.zshrc or ~/.bashrc |
| Windows | %USERPROFILE%\.dotnet\tools |
usually added by the installer; otherwise add it in Environment Variables |
Clients do not always inherit your shell PATH — GUI apps in particular. If a client cannot start the
server, put the absolute path in command: ~/.dotnet/tools/s3l-mcp-figma (macOS, Linux) or
C:\Users\<you>\.dotnet\tools\s3l-mcp-figma.exe (Windows).
Without installing¶
.NET 10 can run the package on demand:
dnx Snail.MCP.Figma --yes
In a client configuration that becomes "command": "dnx", "args": ["Snail.MCP.Figma", "--yes"].
The first start downloads the package; later starts are as fast as the installed tool. Pin a version with
Snail.MCP.Figma@0.1.0 if you do not want it to move.
From source¶
git clone https://github.com/orldev/Snail.MCP.Figma.git
cd Snail.MCP.Figma
dotnet build -c Release
The command is then dotnet with "args": ["<repo>/src/bin/Release/net10.0/Snail.MCP.Figma.dll"].
The repository also carries .mcp.json, which registers a Debug build for Claude Code out of the box.
Do not start the server by hand
It speaks JSON-RPC over stdio and has no interactive interface — launched from a terminal it just waits. The client starts it, and the idle watchdog stops it an hour after the last tool call.
Step 2 — create a Figma token (optional)¶
Skip this if you only intend to work in files open in Figma Desktop: the plugin channel needs no token.
In Figma: avatar → Settings → Security → Personal access tokens → Generate new token. Copy it right
away — it is shown once. Personal tokens start with figd_, OAuth tokens (figu_) are accepted as well.
The scopes worth granting, and what each one buys:
| Scope | Endpoints the server calls | Tools |
|---|---|---|
| File content — read | /v1/files/…, /v1/images/… |
REST reads and renders: figma_get_file_data, figma_get_component, figma_get_styles, figma_get_component_image |
| File versions — read | /v1/files/{key}/versions |
figma_get_file_versions, figma_get_file_at_version, figma_diff_versions, figma_blame_node, figma_generate_changelog |
| Comments — read and write | /v1/files/{key}/comments |
figma_get_comments, figma_post_comment, figma_delete_comment |
| Library assets — read | /v1/components/{key}, /v1/styles/{key}, /v1/teams/{id}/… |
figma_get_library_component_by_key, figma_get_library_style_by_key, figma_search_team_components |
| Variables — read and write | /v1/files/{key}/variables/… |
REST variables. Figma restricts this API to Enterprise plans; on any other plan read variables through the plugin (figma_get_token_values) |
Keep the token in the env block of the client configuration or in your shell environment. The server will
read it from a settings file too, but do not put it there — a file is easy to commit by accident.
Step 3 — register the server with your client¶
Every example below sets one variable, the token; it can be dropped entirely if you work through the plugin only. Everything else has a default — see Configuration.
Claude Code¶
claude mcp add s3l-mcp-figma --scope user \
--env SNAIL_MCP_FIGMA_ACCESS_TOKEN=figd_... \
-- s3l-mcp-figma
--scope user makes it available in every project; use --scope project to write it into the repository's
.mcp.json instead. claude mcp list shows the result, and /mcp inside a session shows the live
connection.
Claude Desktop¶
Edit claude_desktop_config.json and restart the app.
| OS | Path |
|---|---|
| macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Windows | %APPDATA%\Claude\claude_desktop_config.json |
{
"mcpServers": {
"s3l-mcp-figma": {
"command": "s3l-mcp-figma",
"env": {
"SNAIL_MCP_FIGMA_ACCESS_TOKEN": "figd_..."
}
}
}
}
Cursor¶
The same block, in ~/.cursor/mcp.json for every project or .cursor/mcp.json for one.
VS Code¶
.vscode/mcp.json (per project) or the user-level mcp.json — the key is servers and the transport is
explicit:
{
"servers": {
"s3l-mcp-figma": {
"type": "stdio",
"command": "s3l-mcp-figma",
"env": { "SNAIL_MCP_FIGMA_ACCESS_TOKEN": "figd_..." }
}
}
}
Codex CLI¶
~/.codex/config.toml:
[mcp_servers.s3l-mcp-figma]
command = "s3l-mcp-figma"
args = []
env = { SNAIL_MCP_FIGMA_ACCESS_TOKEN = "figd_..." }
Windsurf and other clients¶
Windsurf reads ~/.codeium/windsurf/mcp_config.json, and most other clients use the same mcpServers
shape as Claude Desktop: a command, optional args, and an env map.
If you did not install the global tool¶
Replace the command with the form matching your choice:
| Install | command |
args |
|---|---|---|
| Global tool | s3l-mcp-figma |
— |
dnx |
dnx |
["Snail.MCP.Figma", "--yes"] |
| From source | dotnet |
["<repo>/src/bin/Release/net10.0/Snail.MCP.Figma.dll"] |
Step 4 — install the Figma plugin¶
Writes and plugin-first reads need the bundled plugin running in Figma Desktop. On its first start the
server unpacks it into ~/.s3l-mcp-figma/plugin — so let the client start the server once before this
step, and read the exact path from csharp_diagnose under plugin.bundledPath.
- Plugins → Development → Import plugin from manifest…
- Pick
manifest.jsonfrom that folder. This is done once. - Open a file and run Plugins → Development → Snail Bridge; keep the plugin window open.
The plugin discovers the server itself on ports 9223–9232, so the start order does not matter and several agent sessions attach to the same plugin. The full picture, including multi-file sessions: Plugin setup.
Step 5 — verify¶
Ask your assistant to run these two:
| Tool | Answers |
|---|---|
csharp_diagnose |
the effective configuration, whether the bridge listens, live plugin sessions, the snapshot cache, quota buckets, whether the token is valid |
figma_get_status |
the same connection seen from Figma: which files have a session and which one is active |
Then paste a file link and ask for something cheap, such as the list of pages
(figma_get_file_data with depth: 1).
One server for every agent¶
By default every client session starts a server of its own: four agents in Figma Desktop are four processes, and four panels' worth of connections in every file. With several agents working at once, run one server for all of them instead. stdio stays the default; the shared server is opt-in.
Measured with four sessions on an Apple Silicon Mac:
Framework-dependent (dotnet …dll) |
Native | |
|---|---|---|
| Four stdio processes | 359 MB, 135 ms from start to initialize |
160 MB, 82 ms |
| One shared server | 100 MB | 40 MB, a new session answered in about a millisecond |
-
Publish and install the job. From a clone of the repository:
dotnet publish src -c Release -r osx-arm64 -p:SnailMcpInstall=trueThis publishes the native server into
~/.s3l-mcp/Snail.MCP.Figma/and writes the launchd jobs3l.mcp.figma.plistbeside it, fromdeploy/s3l.mcp.figma.plist. The first time, it prints the two commands that load the job:cp ~/.s3l-mcp/Snail.MCP.Figma/s3l.mcp.figma.plist ~/Library/LaunchAgents/ launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/s3l.mcp.figma.plistLater installs restart a loaded job by themselves — as long as the loaded job is the one they write. Edit the copy in
~/Library/LaunchAgents/and they stop restarting it, printing the commands that would load the new job over your edits instead. -
Give the server your settings in its settings file, not in the job. The job runs with
SNAIL_MCP_FIGMA_TRANSPORT=Httpand nothing else. Put the token into~/.config/s3l-mcp-figma/config.json, readable by you alone:mkdir -p ~/.config/s3l-mcp-figma printf '{ "AccessToken": "figd_..." }\n' > ~/.config/s3l-mcp-figma/config.json chmod 600 ~/.config/s3l-mcp-figma/config.json launchctl kickstart -k gui/$(id -u)/s3l.mcp.figmaThe server reads the file itself, so the same file serves stdio sessions too, and on Linux or Windows the service needs nothing of its own. Any other setting goes there as well —
"DataDirectory"when the plugin was imported into Figma from a folder other than~/.s3l-mcp-figma; see Configuration. -
Register it as an HTTP server in every client, in place of the stdio entry:
{ "mcpServers": { "s3l-mcp-figma": { "type": "http", "url": "http://127.0.0.1:9233/mcp" } } } -
Restart the plugin in each open file once (Plugins → Development → Snail Bridge). The panel learns the new protocol from the server; nothing has to be imported again.
The server listens on loopback only and refuses any request that carries an Origin header, so no web page can
reach it. Each client session is an agent of its own, named in the panel after the folder it works in, and a
session nobody has used for 15 minutes ends. Logs go to ~/Library/Logs/Snail.MCP.Figma.log; once it passes 64 MB the
server moves it to Snail.MCP.Figma.1.log and starts it over, so the two together stay under 128 MB. To go back to
stdio, launchctl bootout gui/$(id -u)/s3l.mcp.figma and restore the stdio entry.
Updating¶
A native publication holds the program itself, ~/.s3l-mcp/Snail.MCP.Figma/current/Snail.MCP.Figma, and no
Snail.MCP.Figma.dll: a stdio registration that ran dotnet …/Snail.MCP.Figma.dll from there names the program as its
command instead, with no arguments.
dotnet tool update -g Snail.MCP.Figma
Restart the MCP server in your client afterwards — a running process keeps the assembly it started with. If the update also changed the plugin bundle, its panel shows a re-import plugin banner: repeat step 4.
Uninstalling¶
dotnet tool uninstall -g Snail.MCP.Figma
Remove the registration from your client's configuration, delete ~/.s3l-mcp-figma (snapshot cache,
unpacked plugin, screenshots — nothing is stored anywhere else) with ~/.snail-mcp-figma when it is there, the link the
server left at the old name when it moved the folder, and remove Snail Bridge from
Figma's Plugins → Development list.
When installation goes wrong¶
| Symptom | Cause and fix |
|---|---|
command not found: s3l-mcp-figma |
PATH — see step 1, or use the absolute path in command |
| The client shows the server but no tools | The process failed to start. Check the client's MCP log; a wrong command or a missing .NET 10 is the usual reason |
You must install .NET to run this application |
The tool was installed with an older SDK, or only a runtime is present. Install the .NET 10 SDK |
| The plugin sees no server | The server exits after an hour of idling and starts again with the next tool call — ask the assistant for anything, then check the plugin. Ports 9223–9232 must be free |
| A tool answers that the plugin is not connected | Snail Bridge is not running in that file; see Troubleshooting |