TECHSCORE BLOG

マーケティングSaaS を提供するシナジーマーケティングのエンジニアブログです。

Figma MCP × GitHub Copilot でデザイン→コードの自動化を試してみた

はじめに

デザインとコードのギャップは、フロントエンド開発でよく直面する課題です。 Figmaで意図どおりのデザインを作っても、実装では「パディングが微妙に違う」「フォントサイズが合わない」「色や余白のルールをどうコードに反映するかわからない」といったズレが起きがちです。 そこで注目したいのが、Figma MCP(Model Context Protocol)サーバーと GitHub Copilot の連携です。FigmaのデザインデータをAIが参照し、デザイン→コード変換を支援します。 本記事では、セットアップから簡単な React コンポーネント生成までの流れを紹介します。

この記事で扱う環境

  • Figma デスクトップアプリ(Professional / Organization / Enterprise プランの Dev または Full シート推奨)
  • VS Code(最新版)
  • GitHub Copilot (Free / Pro / Pro+ / Business / Enterprise いずれかのプラン)

プランによる制限: Starter プランでも MCP サーバーは利用できますが、月6回までのツール呼び出し制限があります。本格的に使う場合は Professional / Organization / Enterprise プランの Dev または Full シートが必要です


Figma MCP サーバーとは

MCP(Model Context Protocol)は、Anthropicが策定したオープンな標準規格で、AIエージェントが外部のデータソースと連携するための統一インターフェースです。 FigmaはこのMCPに対応したサーバーを提供しており、AIエージェントがFigmaのデザインデータを直接参照できるようになっています。具体的には以下のような情報をAIに渡せます。

  • フレームやコンポーネントのレイアウト情報
  • 色・文字サイズ・余白などのデザインルール
  • コンポーネントの階層構造
  • 画像・アイコンなどのアセット(設定により自動ダウンロードも可能)

画像として渡すのではなく「構造化されたデータ」として渡せることが最大のポイントです。AIが推測するのではなく、正確な数値とセマンティクスを元にコードを生成できます。

FigmaのMCPサーバーには2種類あります。

デスクトップ MCP サーバー リモート MCP サーバー
動作場所 ローカル(http://127.0.0.1:3845/mcp Figmaホスト(https://mcp.figma.com/mcp
必要なもの Figmaデスクトップアプリ ブラウザでも可
認証 トークン不要 Figmaアカウント認証が必要
プラン Dev / Full シート(有料プラン) 全プランで利用可(制限あり)

今回はデスクトップアプリを使うので、デスクトップ MCP サーバーを利用します。 なお、Figma MCP はここ数ヶ月で対応ツールが急速に広がっており、2026年2月には OpenAI Codex との連携もリリースされました。GitHub Copilot 以外の選択肢も今後ますます増えていくことが予想されます。

セットアップ手順

Step1 : Figma デスクトップMCPサーバーを有効化する

ここが最初のハマりポイントです。「preferencesにある」という情報も散見されますが、これは古い情報で現在はDev Modeのインスペクトパネル内にあります。

手順

  1. Figma デスクトップアプリを開く。
  2. デザインファイルを開く(Drafts 内のファイルや Starter プランでは制限があるので注意)。
  3. ツールバーのトグルで Dev Mode に切り替える。
  4. 右サイドバー(インスペクトパネル)の MCP サーバーセクションで「Enable desktop MCP server」をクリックする。(新規の場合は、「Set up Figma MCP」と表示される)
  5. 画面下部に確認メッセージが表示されれば OK。


メニューバーの「Figma」→「Settings」には MCP の項目がありません。アプリウィンドウ内の Figmaロゴメニュー →「Preferences」に存在するバージョンもありますが、最新版では Dev Mode パネル内に統合されています。

サーバーが起動すると、ローカルに http://127.0.0.1:3845/mcp でサーバーが立ち上がります。


Step 2:VS Code に MCP サーバーを追加する

VS Code 側の設定はコマンドパレットから操作できます。

  1. ⌘ Shift P(Windows: Ctrl Shift P)でコマンドパレットを開く
  2. MCP: Add Server を検索・選択
  3. HTTP を選択
  4. サーバー URL に http://127.0.0.1:3845/mcp を入力して Enter
  5. Server ID に figma-desktop と入力して Enter
  6. グローバルまたはワークスペースのどちらに追加するか選択

完了すると、mcp.json に以下の設定が自動追加されます。

{
  "servers": {
    "figma-desktop": {
      "type": "http",
      "url": "http://127.0.0.1:3845/mcp"
    }
  }
}

API トークン不要でローカル完結なのは、セキュリティ観点からも企業利用に向いています。

接続確認

Copilot Chat を Agent Mode で開き、ツールアイコン(🔧)をクリックすると利用可能なツール一覧が表示されます。その中に figma-desktop 関連のツールが表示されていれば接続成功です。表示されない場合は Figma デスクトップと VS Code を再起動してみてください。


Step 3:サンプルプロジェクトを用意する

生成されたコンポーネントをすぐに確認できるよう、Vite + React + TypeScript + Tailwind CSS の環境を用意します。

プロジェクトの作成

npm create vite@latest figma-mcp-demo -- --template react-ts
cd figma-mcp-demo
npm install

Tailwind CSS の導入

npm install -D tailwindcss @tailwindcss/vite

vite.config.ts に Tailwind プラグインを追加します。

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import tailwindcss from '@tailwindcss/vite'

export default defineConfig({
  plugins: [
    react(),
    tailwindcss(),
  ],
})

src/index.css の先頭に以下を追加します。

@import "tailwindcss";

開発サーバーの起動

npm run dev

ブラウザで http://localhost:5173 が開けば準備完了です。

あとは Copilot が生成したコンポーネントを src/components/ 以下に配置し、src/App.tsx でインポートするだけで動作確認できます。

Step 4:デモ - 棒グラフコンポーネントを生成してみる

今回のデモには、Figma コミュニティで公開されている Dashboard UI Kit を使います。管理画面のUIパーツが一通り揃っているテンプレートで、誰でも無料でコピーして使えます。

デモで使うのはその中の 棒グラフコンポーネント です。外部ライブラリ不要で Tailwind CSS だけで再現できる構成のため、MCP の出力精度を確認するのに適しています。

Figma でフレームを選択する

Dashboard UI Kit を Dev Mode で開き、棒グラフのフレームを選択します。

MCPサーバーは選択ベースで動作するため、Figma上でフレームを選択した状態で Copilot に指示するのがポイントです。

Copilot Chat でコード生成を指示する

VS Code の Copilot Chat を Agent Mode で開き、以下のようなプロンプトを入力します。

現在Figmaで選択しているフレームを元に、React + Tailwind CSS のコンポーネントを作成してください。
外部ライブラリは使わず、Tailwind CSS のみで実装してください。
セマンティックなHTMLを使い、データは props で受け取る形にしてください。

生成されたコード

import * as React from "react";

export type TrafficByDeviceItem = {
  label: string;
  value: number;
  /** Tailwind class like `bg-[#7dbbff]` */
  barClassName: string;
};

export type TrafficByDeviceCardProps = {
  title: string;
  items: TrafficByDeviceItem[];
  /** 例: [30000, 20000, 10000, 0] */
  yTicks: number[];
  /** y軸の最大値(未指定ならyTicksの最大値 or itemsの最大値) */
  yMax?: number;
  /** ツールチップ等の表示フォーマット */
  formatValue?: (value: number) => string;
};

function defaultFormatValue(value: number) {
  return value.toLocaleString("en-US");
}

function formatTick(value: number) {
  if (value >= 1000) return `${Math.round(value / 1000)}K`;
  return String(value);
}

export function TrafficByDeviceCard({
  title,
  items,
  yTicks,
  yMax,
  formatValue = defaultFormatValue,
}: TrafficByDeviceCardProps) {
  const computedMax = React.useMemo(() => {
    const tickMax = yTicks.length ? Math.max(...yTicks) : 0;
    const itemMax = items.length ? Math.max(...items.map((i) => i.value)) : 0;
    return Math.max(1, yMax ?? tickMax, itemMax);
  }, [items, yMax, yTicks]);

  const headingId = React.useId();

  return (
    <section
      aria-labelledby={headingId}
      className="w-full rounded-[20px] bg-[#f9f9fa] p-6"
      data-node-id="40380:23813"
    >
      <header className="flex items-center justify-between">
        <h2
          id={headingId}
          className="text-[14px] font-semibold leading-5 text-black"
          data-node-id="40380:23814"
        >
          {title}
        </h2>
      </header>

      <div className="mt-4 flex h-40 w-full gap-4" data-node-id="69127:12223">
        {/* Y axis */}
        <div
          className="flex w-7.25 flex-col justify-between text-right text-[12px] leading-4 text-black/40"
          aria-hidden="true"
          data-node-id="63688:9955"
        >
          {yTicks.map((t) => (
            <div key={t} className="flex flex-1 items-center justify-end">
              {formatTick(t)}
            </div>
          ))}
        </div>

        {/* Chart */}
        <figure className="relative flex flex-1 flex-col" aria-label={title}>
          <div
            className="flex-1"
            aria-hidden="true"
            data-node-id="63688:9849"
          />

          {/* Bars (reserve bottom space for labels) */}
          <div className="absolute inset-0 flex items-end justify-between pb-7">
            {items.map((item) => {
              const percent = Math.max(
                0,
                Math.min(100, (item.value / computedMax) * 100),
              );
              const barStyle = { height: `${percent}%` } as React.CSSProperties;

              return (
                <div
                  key={item.label}
                  className="flex h-full flex-1 justify-center"
                >
                  <div className="group relative flex h-full w-full max-w-7 items-end">
                    <div
                      className={`w-full rounded-lg ${item.barClassName}`}
                      style={barStyle}
                      role="img"
                      aria-label={`${item.label}: ${formatValue(item.value)}`}
                    />

                    <div className="pointer-events-none absolute left-1/2 -translate-x-1/2 -translate-y-2 opacity-0 transition-opacity group-hover:opacity-100">
                      <div className="rounded-lg bg-black/80 px-2 py-1 text-[12px] leading-4 text-white">
                        {formatValue(item.value)}
                      </div>
                    </div>
                  </div>
                </div>
              );
            })}
          </div>

          {/* X labels */}
          <figcaption
            className="absolute bottom-0 left-0 right-0 flex items-center text-center text-[12px] leading-4 text-black/40"
            aria-hidden="true"
          >
            {items.map((item) => (
              <div key={item.label} className="flex flex-1 justify-center">
                {item.label}
              </div>
            ))}
          </figcaption>
        </figure>
      </div>
    </section>
  );
}

作成されたコンポーネントを実行してみると、以下のコンポーネントが表示されました。良さそうです。 しかしまだデータが設定されていないので、棒グラフが正常に表示されるかわかりません。

次はPropsに値を設定して、棒グラフを表示してみましょう。編集するのは、src/App.tsxです。

src/App.tsx での使用例。

import { TrafficByDeviceCard } from "./components/TrafficByDeviceCard";

function App() {
  return (
    <main className="min-h-screen bg-white p-8">
      <div className="mx-auto w-full max-w-170">
        <TrafficByDeviceCard
          title="Traffic by Device"
          yTicks={[30000, 20000, 10000, 0]}
          yMax={30000}
          items={[
            { label: "Linux", value: 29200, barClassName: "bg-[#a0bce8]" },
            { label: "Mac", value: 29800, barClassName: "bg-[#6be6d3]" },
            { label: "iOS", value: 28700, barClassName: "bg-black" },
            { label: "Windows", value: 30000, barClassName: "bg-[#7dbbff]" },
            { label: "Android", value: 28100, barClassName: "bg-[#b899eb]" },
            { label: "Other", value: 29500, barClassName: "bg-[#71dd8c]" },
          ]}
        />
      </div>
    </main>
  );
}

export default App;

これで棒グラフが表示されるはずです。以下のように表示すれば成功です。もしFigmaのデザインと異なるようなコンポーネントが表示されたり、表示に問題がある場合は、Copilotに指示を出して修正してもらえばすぐに直るはずです。

生成されたコンポーネント

コンポーネントがシンプルであること、Figma側のデザインがしっかり構造化されていたこともあり、今回は追加の修正なしにそのまま動くコードが出力されました。

精度を上げるためのTips

実際に使ってみて、Figma側の準備が出力品質に直結することがわかりました。

レイヤー名をセマンティックにする

Group 5 のような名前ではなく、CardContainerPriceLabel のように意味のある名前をつけておくと、生成されるコンポーネント名や変数名も自然なものになります。

Auto Layout でレスポンシブの意図を伝える

Auto Layout を設定しておくことで、AIがレイアウトの方向性や余白の意図を正確に読み取れます。

色や余白のルールを定義しておく

色や余白の設定を Figma の Variables として定義しておくと、生成コードにもそのルールが反映されやすくなります。

Code Connect の活用

Code Connect を設定することで、Figmaコンポーネントとコードベースのコンポーネントがマッピングされ、既存の ButtonCard を再利用したコードが生成されます。デザインシステムを運用しているプロジェクトでは特に効果的です。

プロンプトに技術スタックを明示する

React + TypeScript + Tailwind CSS で、既存の Button コンポーネントを再利用してください

のように技術スタックやルールを具体的に書くと出力が安定します。


現時点での制限・注意点

  • Starter プラン: ツール呼び出しは月6回まで(本格利用は Professional 以上推奨、View シートは不可)。
  • 大きなフレーム: コンポーネント単位に分割して渡す(分割すると生成精度が安定しやすい)。
  • 画像アセット: デフォルトでは取得されない(必要なら設定モーダルで「Download assets」をオン)。
  • 生成コード: ビジネスロジックやアクセシビリティは人手でレビューする。

まとめ

Figma MCP × GitHub Copilot の連携は、デザイン→コードの翻訳コスト(余白・タイポグラフィ確認など)を削減しやすい組み合わせです。特にデスクトップアプリを使えば API トークンの管理が不要で、企業での導入ハードルも下げやすい点が魅力です。

Figma MCP は対応ツールの拡充が急ピッチで進んでおり、今後もエコシステムが広がっていくことが予想されます。まずは GitHub Copilot との連携から始め、チームの開発フローに合わせて使い方を育てていくのが現実的な進め方です。

設計→実装のループが短縮されることで、フロントエンドエンジニアがより本質的な実装に集中できる環境が近づいてきています。ぜひ試してみてください。

hiraokuのプロフィール画像
hiraoku

暇があったらクライミングしているフロントエンドエンジニアです。

シナジーマーケティング株式会社では一緒に働く仲間を募集しています。