Figma の MCP Server が話題なので、実用に向けてのイメージをつかめる程度には知っときたいと思って使ってみた。

GLips/Figma-Context-MCP: MCP server to provide Figma layout information to AI coding agents like Cursor

MCP Server の設定は以下。 npx で起動するのはセキュリティ的に問題があると実感し始めたけど今回は検証なので許容する。

{
  "mcpServers": {
    "Framelink Figma MCP": {
      "command": "npx",
      "args": [
        "-y",
        "figma-developer-mcp",
        "--figma-api-key=YOUR-KEY",
        "--stdio"
      ]
    }
  }
}

アクセストークンの取得の仕方は以下に書いてある。

Manage personal access tokens – Figma Learn - Help Center

検証に使える自分の Figma デザインは持ってないので、フリーのデザインを使わせてもらった。

今回使ったのはこれ。

https://www.figma.com/community/file/1212997233512196965

MCP Client 側は Roo Code。

まずヘッダ部分だけ実装してみてもらった。このようにスコープが小さいとけっこう意図通りにやってくれる。 出力が長いけど、作業過程がわかって興味深いので全部貼っておく(途中出力に含まれるクレデンシャル・ローカルのファイルパスなどは手動で消してある)

**User:**

[attempt_completion] Result:
The user has provided feedback on the results. Consider their input to continue the task, and then attempt completion again.
<feedback>
headerコンポーネントを作って、その中に
https://www.figma.com/design/r4YswqA4C1RrHv6jpxG2Fq/Website-Wireframes-UI-Kit--Community-?node-id=1-203&t=tZvWMJAe4f7luzjW-4  このデザインを実装してください
</feedback>
<environment_details>
# VSCode Visible Files
.roo/mcp.json

# VSCode Open Tabs
.roo/mcp.json

# Current Time
2025/4/10 午前9:21:01 (Asia/Tokyo, UTC+9:00)

# Current Context Size (Tokens)
19,010 (10%)

# Current Cost
$0.20

# Current Mode
<slug>code</slug>
<name>Code</name>
</environment_details>

---

**Assistant:**

<thinking>
ユーザーがMCPサーバーを再起動したとのことです。トークンが変更され、MCPサーバーが再起動されたので、再度`get_figma_data`ツールを使用してみましょう。
</thinking>

MCPサーバーが再起動されたとのことですので、再度Figmaのデザインデータを取得してみましょう。

<use_mcp_tool>
<server_name>figma-developer-mcp</server_name>
<tool_name>get_figma_data</tool_name>
<arguments>
{
  "fileKey": "r4YswqA4C1RrHv6jpxG2Fq",
  "nodeId": "1-203"
}
</arguments>
</use_mcp_tool>

---

**User:**

[use_mcp_tool for 'figma-developer-mcp'] Result:
metadata:
  name: Website Wireframes UI Kit (Community)
  lastModified: '2025-04-09T10:23:44Z'
  thumbnailUrl: >-
nodes:
  - id: '1:203'
    name: Nav Bar Top
    type: FRAME
    fills: fill_B1WIFZ
    strokes: stroke_C76OTB
    layout: layout_8CUAIW
    children:
      - id: '1:204'
        name: Logo
        type: TEXT
        textStyle: style_DAWB0P
        fills: fill_U6MZKP
        layout: layout_8CUAIW
        text: Logo
      - id: '1:205'
        name: Group 32
        type: GROUP
        layout: layout_8CUAIW
        borderRadius: 4px
        children:
          - id: '1:206'
            name: Group 31
            type: GROUP
            layout: layout_8CUAIW
            borderRadius: 0px 0px 0px 0px
            children:
              - id: '1:207'
                name: Home
                type: TEXT
                textStyle: style_156EE0
                fills: fill_U6MZKP
                layout: layout_8CUAIW
                text: Home
              - id: '1:208'
                name: How it Work
                type: TEXT
                textStyle: style_HWVGJI
                fills: fill_TS3RHG
                layout: layout_8CUAIW
                text: How it Work
                opacity: 0.8999999761581421
              - id: '1:209'
                name: Rental Detals
                type: TEXT
                textStyle: style_PW1X72
                fills: fill_TS3RHG
                layout: layout_8CUAIW
                text: Rental Detals
                opacity: 0.8999999761581421
              - id: '1:210'
                name: Why Choose Us
                type: TEXT
                textStyle: style_HWVGJI
                fills: fill_TS3RHG
                layout: layout_8CUAIW
                text: Why Choose Us
                opacity: 0.8999999761581421
              - id: '1:211'
                name: Testimonial
                type: TEXT
                textStyle: style_PW1X72
                fills: fill_TS3RHG
                layout: layout_8CUAIW
                text: Testimonial
                opacity: 0.8999999761581421
          - id: '1:212'
            name: Register
            type: TEXT
            textStyle: style_HWVGJI
            fills: fill_TS3RHG
            layout: layout_8CUAIW
            text: Register
            opacity: 0.75
          - id: '1:213'
            name: Line 3
            type: LINE
            strokes: stroke_C76OTB
            layout: layout_8CUAIW
            opacity: 0.800000011920929
          - id: '1:214'
            name: Rectangle 23783
            type: RECTANGLE
            fills: fill_TS3RHG
            layout: layout_8CUAIW
            borderRadius: 4px
          - id: '1:215'
            name: Log In
            type: TEXT
            textStyle: style_4JM879
            fills: fill_GP1YTE
            layout: layout_8CUAIW
            text: Log In
globalVars:
  styles:
    fill_B1WIFZ:
      - rgba(255, 255, 255, 0)
    stroke_C76OTB:
      colors:
        - '#486284'
      strokeWeight: 1px
    layout_8CUAIW:
      mode: none
      sizing: {}
    style_DAWB0P:
      fontFamily: Plus Jakarta Sans
      fontWeight: 600
      fontSize: 32
      lineHeight: 1.5em
      letterSpacing: '-3%'
      textAlignHorizontal: LEFT
      textAlignVertical: CENTER
    fill_U6MZKP:
      - '#1A202C'
    style_156EE0:
      fontFamily: Plus Jakarta Sans
      fontWeight: 600
      fontSize: 16
      lineHeight: 1.5em
      letterSpacing: '-3%'
      textAlignHorizontal: LEFT
      textAlignVertical: CENTER
    style_HWVGJI:
      fontFamily: Plus Jakarta Sans
      fontWeight: 500
      fontSize: 16
      lineHeight: 1.5em
      letterSpacing: '-3%'
      textAlignHorizontal: LEFT
      textAlignVertical: CENTER
    fill_TS3RHG:
      - '#486284'
    style_PW1X72:
      fontFamily: Plus Jakarta Sans
      fontWeight: 500
      fontSize: 16
      lineHeight: 1.5em
      letterSpacing: '-3%'
      textAlignHorizontal: CENTER
      textAlignVertical: CENTER
    style_4JM879:
      fontFamily: Plus Jakarta Sans
      fontWeight: 500
      fontSize: 14
      lineHeight: 1.5em
      letterSpacing: '-3%'
      textAlignHorizontal: LEFT
      textAlignVertical: CENTER
    fill_GP1YTE:
      - '#FFFFFF'

<environment_details>
# VSCode Visible Files
.roo/mcp.json

# VSCode Open Tabs
.roo/mcp.json

# Current Time
2025/4/10 午前9:30:22 (Asia/Tokyo, UTC+9:00)

# Current Context Size (Tokens)
21,592 (11%)

# Current Cost
$0.34

# Current Mode
<slug>code</slug>
<name>Code</name>
</environment_details>

---

**Assistant:**

<thinking>
Figmaのデザインデータを正常に取得できました。このデータを基に、Headerコンポーネントを作成します。

デザインの概要:
- 「Nav Bar Top」というフレーム
- 左側に「Logo」テキスト
- 中央に「Home」「How it Work」「Rental Detals」「Why Choose Us」「Testimonial」というナビゲーションリンク
- 右側に「Register」リンクと「Log In」ボタン
- フォントファミリーは「Plus Jakarta Sans」

まず、Headerコンポーネントを作成するためのディレクトリとファイルを作成します。Next.jsのプロジェクト構造に合わせて、`components`ディレクトリを作成し、その中に`Header.tsx`ファイルを作成します。

また、Plus Jakarta Sansフォントを使用するために、Next.jsのフォント設定も行う必要があります。
</thinking>

Figmaのデザインデータを取得できました。これを基にHeaderコンポーネントを実装していきます。

まず、コンポーネント用のディレクトリを作成します。

<execute_command>
<command>mkdir -p components</command>
</execute_command>

---

**User:**

[execute_command for 'mkdir -p components'] Result:
Command executed in terminal 1 within working directory '/Users/xxxxxxxxx/Code/misc/figma-mcp-next-app'. Exit code: 0
Output:
%

<environment_details>
# VSCode Visible Files
.roo/mcp.json

# VSCode Open Tabs
.roo/mcp.json

# Current Time
2025/4/10 午前9:30:31 (Asia/Tokyo, UTC+9:00)

# Current Context Size (Tokens)
23,651 (12%)

# Current Cost
$0.36

# Current Mode
<slug>code</slug>
<name>Code</name>
</environment_details>

---

**Assistant:**

<thinking>
`components`ディレクトリが正常に作成されました。次に、`Header.tsx`ファイルを作成します。

Figmaのデザインに基づいて、以下の要素を実装します:
1. ロゴ(左側)
2. ナビゲーションリンク(中央)
3. 登録とログインボタン(右側)

また、Plus Jakarta Sansフォントを使用するために、Next.jsのフォント設定も行います。Next.js 13以降では、App Routerを使用している場合、`app/layout.tsx`ファイルでフォントを設定します。

まず、`Header.tsx`コンポーネントを作成しましょう。
</thinking>

次に、Headerコンポーネントを作成します。Figmaのデザインに基づいて実装します。

<write_to_file>
<path>components/Header.tsx</path>
<content>
import Link from 'next/link';

const Header = () => {
  return (
    <header className="w-full py-4 border-b border-[#486284]/80">
      <div className="container mx-auto px-4 flex items-center justify-between">
        {/* Logo */}
        <div className="text-[32px] font-semibold text-[#1A202C] tracking-tight">
          Logo
        </div>

        {/* Navigation Links */}
        <nav className="hidden md:flex items-center space-x-6">
          <Link href="/" className="font-semibold text-[16px] text-[#1A202C]">
            Home
          </Link>
          <Link href="/how-it-works" className="font-medium text-[16px] text-[#486284] opacity-90">
            How it Work
          </Link>
          <Link href="/rental-details" className="font-medium text-[16px] text-[#486284] opacity-90">
            Rental Detals
          </Link>
          <Link href="/why-choose-us" className="font-medium text-[16px] text-[#486284] opacity-90">
            Why Choose Us
          </Link>
          <Link href="/testimonial" className="font-medium text-[16px] text-[#486284] opacity-90">
            Testimonial
          </Link>
        </nav>

        {/* Auth Buttons */}
        <div className="flex items-center space-x-4">
          <Link href="/register" className="font-medium text-[16px] text-[#486284] opacity-75">
            Register
          </Link>
          <div className="h-6 w-px bg-[#486284] opacity-80"></div>
          <Link
            href="/login"
            className="font-medium text-[14px] text-white bg-[#486284] px-4 py-2 rounded"
          >
            Log In
          </Link>
        </div>
      </div>
    </header>
  );
};

export default Header;
</content>
<line_count>48</line_count>
</write_to_file>

---

**User:**

[write_to_file for 'components/Header.tsx'] Result:
The user made the following updates to your content:

@@ -33,10 +33,10 @@
           <Link href="/register" className="font-medium text-[16px] text-[#486284] opacity-75">
             Register
           </Link>
           <div className="h-6 w-px bg-[#486284] opacity-80"></div>
-          <Link
-            href="/login"
+          <Link
+            href="/login"
             className="font-medium text-[14px] text-white bg-[#486284] px-4 py-2 rounded"
           >
             Log In
           </Link>


The updated content, which includes both your original modifications and the user's edits, has been successfully saved to components/Header.tsx. Here is the full, updated content of the file, including line numbers:

<final_file_content path="components/Header.tsx">
 1 | import Link from 'next/link';
 2 |
 3 | const Header = () => {
 4 |   return (
 5 |     <header className="w-full py-4 border-b border-[#486284]/80">
 6 |       <div className="container mx-auto px-4 flex items-center justify-between">
 7 |         {/* Logo */}
 8 |         <div className="text-[32px] font-semibold text-[#1A202C] tracking-tight">
 9 |           Logo
10 |         </div>
11 |
12 |         {/* Navigation Links */}
13 |         <nav className="hidden md:flex items-center space-x-6">
14 |           <Link href="/" className="font-semibold text-[16px] text-[#1A202C]">
15 |             Home
16 |           </Link>
17 |           <Link href="/how-it-works" className="font-medium text-[16px] text-[#486284] opacity-90">
18 |             How it Work
19 |           </Link>
20 |           <Link href="/rental-details" className="font-medium text-[16px] text-[#486284] opacity-90">
21 |             Rental Detals
22 |           </Link>
23 |           <Link href="/why-choose-us" className="font-medium text-[16px] text-[#486284] opacity-90">
24 |             Why Choose Us
25 |           </Link>
26 |           <Link href="/testimonial" className="font-medium text-[16px] text-[#486284] opacity-90">
27 |             Testimonial
28 |           </Link>
29 |         </nav>
30 |
31 |         {/* Auth Buttons */}
32 |         <div className="flex items-center space-x-4">
33 |           <Link href="/register" className="font-medium text-[16px] text-[#486284] opacity-75">
34 |             Register
35 |           </Link>
36 |           <div className="h-6 w-px bg-[#486284] opacity-80"></div>
37 |           <Link
38 |             href="/login"
39 |             className="font-medium text-[14px] text-white bg-[#486284] px-4 py-2 rounded"
40 |           >
41 |             Log In
42 |           </Link>
43 |         </div>
44 |       </div>
45 |     </header>
46 |   );
47 | };
48 |
49 | export default Header;

</final_file_content>

Please note:
1. You do not need to re-write the file with these changes, as they have already been applied.
2. Proceed with the task using cline updated file content as the new baseline.
3. If the user's edits have addressed part of the task or changed the requirements, adjust your approach accordingly.
<environment_details>
# VSCode Visible Files
components/Header.tsx

# VSCode Open Tabs
.roo/mcp.json,components/Header.tsx

# Current Time
2025/4/10 午前9:30:45 (Asia/Tokyo, UTC+9:00)

# Current Context Size (Tokens)
24,661 (12%)

# Current Cost
$0.38

# Current Mode
<slug>code</slug>
<name>Code</name>


# Current Workspace Directory (/Users/xxxxxxxxx/Code/misc/figma-mcp-next-app) Files
.gitignore
eslint.config.mjs
next.config.ts
package-lock.json
package.json
postcss.config.mjs
README.md
tsconfig.json
app/
app/favicon.ico
app/globals.css
app/layout.tsx
app/page.tsx
components/
components/Header.tsx
public/
public/file.svg
public/globe.svg
public/next.svg
public/vercel.svg
public/window.svg
</environment_details>

---

**Assistant:**

<thinking>
タスクの状況を確認します。これまでに以下のことを行いました:

1. Next.js + TypeScript + Tailwind CSSプロジェクトを初期化しました。
2. Figmaのデザインデータを取得しました。
3. `components`ディレクトリを作成し、`Header.tsx`コンポーネントを実装しました。

次に行うべきことは:

1. Plus Jakarta Sansフォントを設定する
2. Headerコンポーネントをアプリケーションに統合する
3. 実装したHeaderコンポーネントが正しく表示されることを確認する

まず、Plus Jakarta Sansフォントを設定するために、Next.jsのフォント設定を行います。Next.js 13以降では、App Routerを使用している場合、`app/layout.tsx`ファイルでフォントを設定します。

現在の`app/layout.tsx`ファイルの内容を確認しましょう。
</thinking>

Headerコンポーネントを作成しました。次に、Plus Jakarta Sansフォントを設定し、Headerコンポーネントをアプリケーションに統合します。

まず、現在の`app/layout.tsx`ファイルの内容を確認しましょう。

<read_file>
<path>app/layout.tsx</path>
</read_file>

[Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the message.]

---

**User:**

[read_file for 'app/layout.tsx'] Result:
<file><path>app/layout.tsx</path>
<content lines="1-34">
 1 | import type { Metadata } from "next";
 2 | import { Geist, Geist_Mono } from "next/font/google";
 3 | import "./globals.css";
 4 |
 5 | const geistSans = Geist({
 6 |   variable: "--font-geist-sans",
 7 |   subsets: ["latin"],
 8 | });
 9 |
10 | const geistMono = Geist_Mono({
11 |   variable: "--font-geist-mono",
12 |   subsets: ["latin"],
13 | });
14 |
15 | export const metadata: Metadata = {
16 |   title: "Create Next App",
17 |   description: "Generated by create next app",
18 | };
19 |
20 | export default function RootLayout({
21 |   children,
22 | }: Readonly<{
23 |   children: React.ReactNode;
24 | }>) {
25 |   return (
26 |     <html lang="en">
27 |       <body
28 |         className={`${geistSans.variable} ${geistMono.variable} antialiased`}
29 |       >
30 |         {children}
31 |       </body>
32 |     </html>
33 |   );
34 | }
</content>
</file>
<environment_details>
# VSCode Visible Files
components/Header.tsx

# VSCode Open Tabs
.roo/mcp.json,components/Header.tsx

# Current Time
2025/4/10 午前9:30:54 (Asia/Tokyo, UTC+9:00)

# Current Context Size (Tokens)
26,625 (13%)

# Current Cost
$0.39

# Current Mode
<slug>code</slug>
<name>Code</name>
</environment_details>

---

**Assistant:**

<thinking>
`app/layout.tsx`ファイルの内容を確認しました。現在、Geistフォントが設定されています。Figmaのデザインでは、Plus Jakarta Sansフォントが使用されているため、このフォントを追加する必要があります。

次に、`app/page.tsx`ファイルの内容を確認して、Headerコンポーネントをどのように統合するかを検討します。
</thinking>

次に、`app/page.tsx`ファイルの内容を確認しましょう。

<read_file>
<path>app/page.tsx</path>
</read_file>

---

**User:**

[read_file for 'app/page.tsx'] Result:
<file><path>app/page.tsx</path>
<content lines="1-103">
  1 | import Image from "next/image";
  2 |
  3 | export default function Home() {
  4 |   return (
  5 |     <div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
  6 |       <main className="flex flex-col gap-[32px] row-start-2 items-center sm:items-start">
  7 |         <Image
  8 |           className="dark:invert"
  9 |           src="/next.svg"
 10 |           alt="Next.js logo"
 11 |           width={180}
 12 |           height={38}
 13 |           priority
 14 |         />
 15 |         <ol className="list-inside list-decimal text-sm/6 text-center sm:text-left font-[family-name:var(--font-geist-mono)]">
 16 |           <li className="mb-2 tracking-[-.01em]">
 17 |             Get started by editing{" "}
 18 |             <code className="bg-black/[.05] dark:bg-white/[.06] px-1 py-0.5 rounded font-[family-name:var(--font-geist-mono)] font-semibold">
 19 |               app/page.tsx
 20 |             </code>
 21 |             .
 22 |           </li>
 23 |           <li className="tracking-[-.01em]">
 24 |             Save and see your changes instantly.
 25 |           </li>
 26 |         </ol>
 27 |
 28 |         <div className="flex gap-4 items-center flex-col sm:flex-row">
 29 |           <a
 30 |             className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-foreground text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 sm:w-auto"
 31 |             href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
 32 |             target="_blank"
 33 |             rel="noopener noreferrer"
 34 |           >
 35 |             <Image
 36 |               className="dark:invert"
 37 |               src="/vercel.svg"
 38 |               alt="Vercel logomark"
 39 |               width={20}
 40 |               height={20}
 41 |             />
 42 |             Deploy now
 43 |           </a>
 44 |           <a
 45 |             className="rounded-full border border-solid border-black/[.08] dark:border-white/[.145] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 w-full sm:w-auto md:w-[158px]"
 46 |             href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
 47 |             target="_blank"
 48 |             rel="noopener noreferrer"
 49 |           >
 50 |             Read our docs
 51 |           </a>
 52 |         </div>
 53 |       </main>
 54 |       <footer className="row-start-3 flex gap-[24px] flex-wrap items-center justify-center">
 55 |         <a
 56 |           className="flex items-center gap-2 hover:underline hover:underline-offset-4"
 57 |           href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
 58 |           target="_blank"
 59 |           rel="noopener noreferrer"
 60 |         >
 61 |           <Image
 62 |             aria-hidden
 63 |             src="/file.svg"
 64 |             alt="File icon"
 65 |             width={16}
 66 |             height={16}
 67 |           />
 68 |           Learn
 69 |         </a>
 70 |         <a
 71 |           className="flex items-center gap-2 hover:underline hover:underline-offset-4"
 72 |           href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
 73 |           target="_blank"
 74 |           rel="noopener noreferrer"
 75 |         >
 76 |           <Image
 77 |             aria-hidden
 78 |             src="/window.svg"
 79 |             alt="Window icon"
 80 |             width={16}
 81 |             height={16}
 82 |           />
 83 |           Examples
 84 |         </a>
 85 |         <a
 86 |           className="flex items-center gap-2 hover:underline hover:underline-offset-4"
 87 |           href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
 88 |           target="_blank"
 89 |           rel="noopener noreferrer"
 90 |         >
 91 |           <Image
 92 |             aria-hidden
 93 |             src="/globe.svg"
 94 |             alt="Globe icon"
 95 |             width={16}
 96 |             height={16}
 97 |           />
 98 |           Go to nextjs.org →
 99 |         </a>
100 |       </footer>
101 |     </div>
102 |   );
103 | }
</content>
</file>
<environment_details>
# VSCode Visible Files
components/Header.tsx

# VSCode Open Tabs
.roo/mcp.json,components/Header.tsx

# Current Time
2025/4/10 午前9:30:59 (Asia/Tokyo, UTC+9:00)

# Current Context Size (Tokens)
27,358 (14%)

# Current Cost
$0.41

# Current Mode
<slug>code</slug>
<name>Code</name>
</environment_details>

---

**Assistant:**

<thinking>
`app/page.tsx`ファイルの内容を確認しました。これはNext.jsのデフォルトのホームページです。

次に、以下の変更を行います:

1. `app/layout.tsx`ファイルを更新して、Plus Jakarta Sansフォントを追加します。
2. `app/layout.tsx`ファイルにHeaderコンポーネントを追加します。
3. `app/page.tsx`ファイルを更新して、新しいレイアウトに合わせます。

まず、`app/layout.tsx`ファイルを更新します。Plus Jakarta Sansフォントを追加し、Headerコンポーネントをインポートして使用します。
</thinking>

次に、Plus Jakarta Sansフォントを追加し、Headerコンポーネントをアプリケーションに統合します。

まず、`app/layout.tsx`ファイルを更新します:

<apply_diff>
<path>app/layout.tsx</path>
<diff>
<<<<<<< SEARCH
:start_line:1
:end_line:3
-------
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
=======
import type { Metadata } from "next";
import { Geist, Geist_Mono, Plus_Jakarta_Sans } from "next/font/google";
import "./globals.css";
import Header from "../components/Header";
>>>>>>> REPLACE

<<<<<<< SEARCH
:start_line:5
:end_line:13
-------
const geistSans = Geist({
  variable: "--font-geist-sans",
  subsets: ["latin"],
});

const geistMono = Geist_Mono({
  variable: "--font-geist-mono",
  subsets: ["latin"],
});
=======
const geistSans = Geist({
  variable: "--font-geist-sans",
  subsets: ["latin"],
});

const geistMono = Geist_Mono({
  variable: "--font-geist-mono",
  subsets: ["latin"],
});

const plusJakartaSans = Plus_Jakarta_Sans({
  variable: "--font-plus-jakarta-sans",
  subsets: ["latin"],
  weight: ["400", "500", "600", "700"],
});
>>>>>>> REPLACE

<<<<<<< SEARCH
:start_line:26
:end_line:31
-------
      <body
        className={`${geistSans.variable} ${geistMono.variable} antialiased`}
      >
        {children}
      </body>
=======
      <body
        className={`${geistSans.variable} ${geistMono.variable} ${plusJakartaSans.variable} antialiased`}
      >
        <Header />
        {children}
      </body>
>>>>>>> REPLACE
</diff>
</apply_diff>

---

**User:**

[apply_diff for 'app/layout.tsx'] Result:
Changes successfully applied to app/layout.tsx:



<environment_details>
# VSCode Visible Files
app/layout.tsx

# VSCode Open Tabs
.roo/mcp.json,components/Header.tsx,app/layout.tsx

# Current Time
2025/4/10 午前9:31:13 (Asia/Tokyo, UTC+9:00)

# Current Context Size (Tokens)
29,983 (15%)

# Current Cost
$0.43

# Current Mode
<slug>code</slug>
<name>Code</name>
</environment_details>

---

**Assistant:**

<thinking>
`app/layout.tsx`ファイルが正常に更新されました。次に、Headerコンポーネントで使用するフォントを適用するために、`components/Header.tsx`ファイルを更新します。Plus Jakarta Sansフォントを使用するようにスタイルを変更します。
</thinking>

次に、Headerコンポーネントを更新して、Plus Jakarta Sansフォントを使用するようにします:

<apply_diff>
<path>components/Header.tsx</path>
<diff>
<<<<<<< SEARCH
:start_line:8
:end_line:9
-------
        <div className="text-[32px] font-semibold text-[#1A202C] tracking-tight">
          Logo
=======
        <div className="text-[32px] font-semibold text-[#1A202C] tracking-tight font-[family-name:var(--font-plus-jakarta-sans)]">
          Logo
>>>>>>> REPLACE

<<<<<<< SEARCH
:start_line:13
:end_line:28
-------
        <nav className="hidden md:flex items-center space-x-6">
          <Link href="/" className="font-semibold text-[16px] text-[#1A202C]">
            Home
          </Link>
          <Link href="/how-it-works" className="font-medium text-[16px] text-[#486284] opacity-90">
            How it Work
          </Link>
          <Link href="/rental-details" className="font-medium text-[16px] text-[#486284] opacity-90">
            Rental Detals
          </Link>
          <Link href="/why-choose-us" className="font-medium text-[16px] text-[#486284] opacity-90">
            Why Choose Us
          </Link>
          <Link href="/testimonial" className="font-medium text-[16px] text-[#486284] opacity-90">
            Testimonial
          </Link>
        </nav>
=======
        <nav className="hidden md:flex items-center space-x-6 font-[family-name:var(--font-plus-jakarta-sans)]">
          <Link href="/" className="font-semibold text-[16px] text-[#1A202C]">
            Home
          </Link>
          <Link href="/how-it-works" className="font-medium text-[16px] text-[#486284] opacity-90">
            How it Work
          </Link>
          <Link href="/rental-details" className="font-medium text-[16px] text-[#486284] opacity-90">
            Rental Detals
          </Link>
          <Link href="/why-choose-us" className="font-medium text-[16px] text-[#486284] opacity-90">
            Why Choose Us
          </Link>
          <Link href="/testimonial" className="font-medium text-[16px] text-[#486284] opacity-90">
            Testimonial
          </Link>
        </nav>
>>>>>>> REPLACE

<<<<<<< SEARCH
:start_line:31
:end_line:43
-------
        {/* Auth Buttons */}
        <div className="flex items-center space-x-4">
          <Link href="/register" className="font-medium text-[16px] text-[#486284] opacity-75">
            Register
          </Link>
          <div className="h-6 w-px bg-[#486284] opacity-80"></div>
          <Link
            href="/login"
            className="font-medium text-[14px] text-white bg-[#486284] px-4 py-2 rounded"
          >
            Log In
          </Link>
        </div>
=======
        {/* Auth Buttons */}
        <div className="flex items-center space-x-4 font-[family-name:var(--font-plus-jakarta-sans)]">
          <Link href="/register" className="font-medium text-[16px] text-[#486284] opacity-75">
            Register
          </Link>
          <div className="h-6 w-px bg-[#486284] opacity-80"></div>
          <Link
            href="/login"
            className="font-medium text-[14px] text-white bg-[#486284] px-4 py-2 rounded"
          >
            Log In
          </Link>
        </div>
>>>>>>> REPLACE
</diff>
</apply_diff>

---

**User:**

[apply_diff for 'components/Header.tsx'] Result:
Changes successfully applied to components/Header.tsx:



<environment_details>
# VSCode Visible Files
components/Header.tsx

# VSCode Open Tabs
.roo/mcp.json,app/layout.tsx,components/Header.tsx,app/page.tsx

# Current Time
2025/4/10 午前9:31:29 (Asia/Tokyo, UTC+9:00)

# Current Context Size (Tokens)
31,283 (16%)

# Current Cost
$0.46

# Current Mode
<slug>code</slug>
<name>Code</name>
</environment_details>

---

**Assistant:**

<thinking>
`components/Header.tsx`ファイルが正常に更新されました。次に、`app/page.tsx`ファイルを更新して、新しいレイアウトに合わせます。Headerコンポーネントが追加されたため、ページのレイアウトを調整する必要があります。

現在の`app/page.tsx`ファイルはNext.jsのデフォルトのホームページですが、Headerコンポーネントが追加されたことで、レイアウトを調整する必要があります。特に、上部のマージンやパディングを調整して、Headerコンポーネントとの間隔を適切にします。
</thinking>

次に、`app/page.tsx`ファイルを更新して、Headerコンポーネントが追加されたレイアウトに合わせます:

<apply_diff>
<path>app/page.tsx</path>
<diff>
<<<<<<< SEARCH
:start_line:4
:end_line:5
-------
  return (
    <div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
=======
  return (
    <div className="grid grid-rows-[1fr_20px] items-center justify-items-center min-h-[calc(100vh-72px)] p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
>>>>>>> REPLACE

<<<<<<< SEARCH
:start_line:6
:end_line:6
-------
      <main className="flex flex-col gap-[32px] row-start-2 items-center sm:items-start">
=======
      <main className="flex flex-col gap-[32px] row-start-1 items-center sm:items-start">
>>>>>>> REPLACE

<<<<<<< SEARCH
:start_line:54
:end_line:54
-------
      <footer className="row-start-3 flex gap-[24px] flex-wrap items-center justify-center">
=======
      <footer className="row-start-2 flex gap-[24px] flex-wrap items-center justify-center">
>>>>>>> REPLACE
</diff>
</apply_diff>

---

**User:**

[apply_diff for 'app/page.tsx'] Result:
Changes successfully applied to app/page.tsx:



<environment_details>
# VSCode Visible Files
app/page.tsx

# VSCode Open Tabs
.roo/mcp.json,app/layout.tsx,components/Header.tsx,app/page.tsx

# Current Time
2025/4/10 午前9:31:41 (Asia/Tokyo, UTC+9:00)

# Current Context Size (Tokens)
32,071 (16%)

# Current Cost
$0.49

# Current Mode
<slug>code</slug>
<name>Code</name>
</environment_details>

---

**Assistant:**

<thinking>
すべての必要な変更が完了しました:

1. `components/Header.tsx`ファイルを作成し、Figmaデザインに基づいたヘッダーコンポーネントを実装しました。
2. `app/layout.tsx`ファイルを更新して、Plus Jakarta Sansフォントを追加し、Headerコンポーネントを統合しました。
3. `app/page.tsx`ファイルを更新して、新しいヘッダーに合わせてレイアウトを調整しました。

次に、開発サーバーを起動して、変更が正しく適用されているか確認しましょう。
</thinking>

すべての必要な変更が完了しました。次に、開発サーバーを起動して、実装したHeaderコンポーネントが正しく表示されるか確認しましょう。

<execute_command>
<command>npm run dev</command>
</execute_command>

---

かなり出力が長くて何回かイテレーションがあったが、いい感じに実装できた。

作ったコンポーネントをレイアウトの中で適切に配置するように試行していることもわかる。

次はまるっと全体を作ってもらってみた。これだとけっこう精度が落ちることが確認できた。

次に、https://www.figma.com/design/r4YswqA4C1RrHv6jpxG2Fq/Website-Wireframes-UI-Kit–Community-?node-id=1-32&t=vvrzOT4fDjGZMxAZ-4 これを丸ごと実装してみてください。ヘッダ部分はすでに実装済みなので使いまわしてください。適宜、コンポーネント分割してください。

これで作ってもらったのが以下。

https://figma-mcp-next-app.vercel.app/

ソースコードは以下。

chokkoyamada/figma-mcp-next-app

左の画像が実装したコードとウェブサイト、右の画像が Figma のデザイン。

code implementation
figma design

ヘッダはほぼ忠実に再現できているが、他のコンポーネントは結構違うことがわかる。

これが、ヘッダ部分がコンテキストを小さく指示したからという効果もちろんありそうだけど、他のコンポーネントがデザイン的に難易度高いというのもありそう。

ただしここから個別に微調整もできるので、ひとまずの実装としては十分すぎる出来栄えだと思う。

しかしここから商用システムで実際に実用するとなると、もう一段階ハードルがありそう。

社内でデザインシステムがすでにあるなら、そことの連携が必要になる。「デザインシステム」の詳細の解像度が高くないのだけど、例えば React Component ライブラリとして持っているならそのライブラリの該当するコンポーネントを使うように指示する必要がある。 例えば、以下のような記事を読んだ。

社内デザインシステムを MCP サーバー化したら UI 実装が爆速になった

ここでは、Figma MCP に加えて Ubie UI MCP という自社の MCP サーバーを併用しているみたいで、おそらく Ubie UI MCP のほうに Component のコードの情報があるのだろうと想像する。

この方法で作っていって統制とれるのかというのも気になる。vibe coding 的にデザインに近い実装をしていくことはできるが、質の担保という意味では、どのようにレギュレーションを整えるかとか、人間がレビューするかなど現状では課題があるように思う。一方、こうした課題を AI がある程度解決するのも時間の問題な気がする。やり方次第ではもう解決しているのかもしれない。

※追記 以下のスペースに参加して聞いてた。

進行中: デザインシステムをmcpサーバ化したお話をします!

実装としてはナイーブで、対応するReact Componentのコードを文字列で返しているだけらしい。 そこからさらに精度をあげていく課題はあるとのこと。 適用可能なケースはあるけど、現時点では全てに使えるわけではない。

LayerXの記事も出てた。こちらはStorybookベース。

Storybook の情報を抜き出して MCP サーバにしてみる