🗂

Figma MCPのメタデータとデザインコンテキストの中身

に公開

メタデータとデザインコンテキストの主な違い

  • メタデータ: 簡易データ
    • MCPツールのget_metadataによって取得できる
    • XML形式の「メタデータ」
    • デザインの全体構造を把握するための限定的な情報だけが含まれる
  • デザインコンテキスト: 詳細データ
    • MCPツールのget_design_contextによって取得できる
    • JSX形式の「デザインコンテキスト/コード」
      • React+Tailwind CSS
    • デザインを実装するために必要なスタイル情報がすべて含まれる
    • 情報量が多すぎる場合に「メタデータ」を返す場合がある
      • forceCode: trueにすれば「コード」を強制できる

ツール呼び出し時の追加のメッセージ

各ツールを呼び出すと、「メタデータ」や「デザインコンテキスト」の本体に続いて、注意書きのようなメッセージも返ってきます。
AIはこのメッセージに書かれた指示に従って考えて行動します。

ツール呼び出し時の引数

引数によって取得結果を変えられる場合があります。
ただし、公式ドキュメントには記載されていないものも多いです。
AIエージェントに聞けば、MCPサーバで定義されている最新の情報を教えてくれます。

取得例に使ったデザイン

シンプルなグロナビを例にします。

メタデータ get_metadata

引数

  • nodeId(string): FigmaデザインのノードID
    • 省略時は現在選択されているノード

現状、引数を変えても特に変化がないと思われるもの

  • clientLanguages(string): 使用言語
  • clientFrameworks(string): 使用フレームワーク

戻り値(XML)

<frame id="13:76" name="Navigation" x="627" y="50" width="673" height="149">
  <frame id="13:28" name="Text" x="50" y="63" width="378" height="23">
    <text id="13:55" name="トップ" x="0" y="0" width="48" height="23" />
    <text id="13:56" name="製品情報" x="78" y="0" width="64" height="23" />
    <text id="13:57" name="私たちについて" x="172" y="0" width="112" height="23" />
    <text id="13:58" name="お知らせ" x="314" y="0" width="64" height="23" />
  </frame>
  <frame id="13:60" name="Button" x="458" y="50" width="165" height="49">
    <text id="13:61" name="お問い合わせ" x="25" y="15" width="95" height="19" />
    <frame id="13:62" name="Arrow" x="130" y="19.5" width="10" height="10" />
  </frame>
</frame>

デザインの全体構造を把握するのに特化したデータになっています。

  • レイヤー名
    • テキストレイヤーは名前がなければ中身がそのまま入る
  • 親要素を起点とした配置情報
  • 各ノードのID
    • これを使って部分的にget_metadataget_design_contextを再度呼び出せる

追加のメッセージ

デザインを実装する場合はget_design_contextを使うことが示唆されています。

IMPORTANT: After you call this tool, you MUST call get_design_context if trying to implement the design, since this tool only returns metadata. If you do not call get_design_context, the agent will not be able to implement the design.

データの中身によらず、定型文だと思われます。

デザインコンテキスト get_design_context

引数

  • nodeId(string): FigmaデザインのノードID
    • 省略時は現在選択されているノード
  • forceCode(boolean): コードを強制的に返すかどうか
    • falseだと、情報量が多すぎる場合に「メタデータ」を返す場合がある

現状、引数を変えても特に変化がないと思われるもの

  • clientLanguages(string): 使用言語
  • clientFrameworks(string): 使用フレームワーク
  • artifactType(string): 出力される成果物の種類
    • WEB_PAGE_OR_APP_SCREEN
    • COMPONENT_WITHIN_A_WEB_PAGE_OR_APP_SCREEN
    • REUSABLE_COMPONENT
    • DESIGN_SYSTEM
  • taskType: 実行したいタスクの種類
    • CREATE_ARTIFACT
    • CHANGE_ARTIFACT
    • DELETE_ARTIFACT

戻り値(JSX)

import { imgArrow } from "./svg-80g63";

export default function Navigation() {
  return (
    <div className="bg-white box-border content-stretch flex gap-[30px] items-center p-[50px] relative size-full" data-name="Navigation" data-node-id="13:76">
      <div className="content-stretch flex font-['Noto_Sans_JP:Medium',sans-serif] font-medium gap-[30px] items-start leading-[23px] relative shrink-0 text-[16px] text-[color:var(--custom-black,#212529)] text-nowrap whitespace-pre" data-name="Text" data-node-id="13:28">
        <p className="relative shrink-0" data-node-id="13:55">トップ</p>
        <p className="relative shrink-0" data-node-id="13:56">製品情報</p>
        <p className="relative shrink-0" data-node-id="13:57">私たちについて</p>
        <p className="relative shrink-0" data-node-id="13:58">お知らせ</p>
      </div>
      <div className="bg-gradient-to-b box-border content-stretch flex from-[var(--primary-light,#4f9cf9)] gap-[10px] items-center justify-center px-[25px] py-[15px] relative rounded-[10px] shrink-0 to-[var(--primary,#043873)]" data-name="Button" data-node-id="13:60">
        <p className="font-['Noto_Sans_JP:Medium',sans-serif] font-medium leading-[normal] not-italic relative shrink-0 text-[16px] text-nowrap text-white tracking-[-0.32px] whitespace-pre" data-node-id="13:61">
          お問い合わせ
        </p>
        <div className="relative shrink-0 size-[10px]" data-name="Arrow" data-node-id="13:62">
          <div className="absolute inset-[-5%]">
            <img alt="" className="block max-w-none size-full" src={imgArrow} />
          </div>
        </div>
      </div>
    </div>
  );
}

デザインを再現するのに必要なTailwind CSSのスタイルが含まれています。

  • Tailwind CSS
    • 冗長なスタイル指定が多く含まれるが、再現性はそれなりに高い
  • 画像
  • 変数
    • 「Figmaのバリアブル」を使っていれば変数名が入る
    • 実際の値も含まれるので変数定義がなくてもスタイルが適用される
  • data-name属性にレイヤー名
    • AIがコンテンツを推定するのに重要
  • 各ノードのID

ちなみに、冗長なスタイル指定についてはこちらにまとめてあります。
https://zenn.dev/yuichiroharai/articles/33432a0e5a9522

追加のメッセージ

長いメッセージですが、特に重要なのは以下だと思います。

  • React+Tailwindのコードを返すが、プロジェクト構成を優先して必要に応じて変換すること
  • get_screenshotでスクリーンショットを取得すること
SUPER CRITICAL: The generated React+Tailwind code MUST be converted to match the target project's technology stack and styling system.
1. Analyze the target codebase to identify: technology stack, styling approach, component patterns, and design tokens
2. Convert React syntax to the target framework/library
3. Transform all Tailwind classes to the target styling system while preserving exact visual design
4. Follow the project's existing patterns and conventions
DO NOT install any Tailwind as a dependency unless the user instructs you to do so.

Node ids have been added to the code as data attributes, e.g. `data-node-id="1:2"`.
These styles are contained in the design: primary-gradation: .
Image assets are stored on a localhost server. Clients can use these images directly in code as a way to view the image assets the same way they would other remote servers. Images and SVGs will be stored as constants, e.g. const image = 'http://localhost:3845/assets/10c13ac1a228a365cb98a0064b1d5afbc84887b2.png' These constants will be used in the code as the source for the image, e.g. <img src={image} /> This is true for both images and SVGs, so you can use the same approach for both types of assets.
IMPORTANT: After you call this tool, you MUST call get_screenshot to get a screenshot of the node for context.

こちらも定型文ですが、Figmaのスタイルを使っている場合はその情報が列挙されます。

メタデータを返した場合の追加のメッセージ

  • デザインが大きすぎたのでメタデータを返したこと
  • メタデータに含まれるサブレイヤーのIDを使用し、分割してget_design_contextを呼び出すこと

などが含まれています。

IMPORTANT: The design was too large to fit into context with get_design_context. Instead you have received a sparse metadata response, you MUST call get_design_context on the IDs of the sublayers to get the full code. Split up the calls to ensure the sublayers do not also exceed the context limit.

スクリーンショット

AIがget_design_contextを実行すると、Figma MCPの指示によってget_screenshotも実行してスクリーンショットを取得します。
ですが、具体的な活用方法を指示しない限り、この画像が自発的に使われることはなさそうです。

Antigravity(Gemini 3 Pro)とCursor(Auto)の環境でそれぞれAIに聞いてみました。
共通して言えることは、JSXコードという詳細なデータが得られていて、それで十分な実装が可能と判断した場合は、スクリーンショットを参照することはないとのことでした。

ベクターデータによる容量増加の問題

(イラストのような)たくさんのベクターデータが含まれたデザインに対して、メタデータやデザインコンテキストを取得すると、データ量が一気に増えてしまう場合があります。

メタデータ

以下のように<vector>要素が大量に続きます。

<frame id="..." name="Illustration" x="0" y="0" width="200" height="200">
  <vector id="..." name="Vector" x="0" y="0" width="100" height="100" />
  <vector id="..." name="Vector" x="0" y="50" width="100" height="100" />
  ...
</frame>

状況と対策

メタデータにはベクター要素が含まれてしまう可能性が高いです。

一応、コンポーネント化すると回避できますが、後述の理由によりあまりおすすめできません。

<symbol id="..." name="Button" x="0" y="0" width="101" height="49" />
<instance id="..." name="Button" x="160" y="0" width="101" height="49" />

<symbol>が元のコンポーネントで、<instance>がそれを元に作られたインスタンスです。

デザインコンテキスト

画像URLの宣言と<img>要素が大量に続きます。

import { img1, img2, ... } from "./svg-yv2gj";
export default function Illustration() {
  return (
    <div className="..." data-name="Illustration" data-node-id="...">
      <img alt="" className="..." src={img1} />
      <img alt="" className="..." src={img2} />
      ...
    </div>
  );
}

対策

ひとつの画像としてまとめられて返ってくる場合もあって、発生条件がよく分かっていないです。

一応の対策として、

  1. 該当するレイヤーを選択し、[コピー/貼り付けオプション] > [SVGとしてコピー]
  2. 再度、貼り付け
    • テキストが含まれていたらベクターに変換される
  3. 貼り付けたSVGの中身をすべて選択し、[グループ解除]
    • グループが無くなるまで繰り返す

この手順で回避できる場合がありました。
1つのグループの中にベクターだけがフラットに並ぶので、1枚の画像として認識されやすくなっているのかもしれません。

ちなみに、コンポーネント化していた場合、再利用するためにコンポーネントの中身が重要だと思われてしまって、ひとつの画像として認識されずらくなっている気がします。

いずれにしろ、Figma側の設定で変えられるようになると良いなと思っています。

Discussion