FigmaのMCP ServerでReact Componentを作ってもらうのを雑に試した
Figma の MCP Server が話題なので、実用に向けてのイメージをつかめる程度には知っときたいと思って使ってみた。
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 のデザイン。


ヘッダはほぼ忠実に再現できているが、他のコンポーネントは結構違うことがわかる。
これが、ヘッダ部分がコンテキストを小さく指示したからという効果もちろんありそうだけど、他のコンポーネントがデザイン的に難易度高いというのもありそう。
ただしここから個別に微調整もできるので、ひとまずの実装としては十分すぎる出来栄えだと思う。
しかしここから商用システムで実際に実用するとなると、もう一段階ハードルがありそう。
社内でデザインシステムがすでにあるなら、そことの連携が必要になる。「デザインシステム」の詳細の解像度が高くないのだけど、例えば React Component ライブラリとして持っているならそのライブラリの該当するコンポーネントを使うように指示する必要がある。 例えば、以下のような記事を読んだ。
社内デザインシステムを MCP サーバー化したら UI 実装が爆速になった
ここでは、Figma MCP に加えて Ubie UI MCP という自社の MCP サーバーを併用しているみたいで、おそらく Ubie UI MCP のほうに Component のコードの情報があるのだろうと想像する。
この方法で作っていって統制とれるのかというのも気になる。vibe coding 的にデザインに近い実装をしていくことはできるが、質の担保という意味では、どのようにレギュレーションを整えるかとか、人間がレビューするかなど現状では課題があるように思う。一方、こうした課題を AI がある程度解決するのも時間の問題な気がする。やり方次第ではもう解決しているのかもしれない。
※追記 以下のスペースに参加して聞いてた。
進行中: デザインシステムをmcpサーバ化したお話をします!
実装としてはナイーブで、対応するReact Componentのコードを文字列で返しているだけらしい。 そこからさらに精度をあげていく課題はあるとのこと。 適用可能なケースはあるけど、現時点では全てに使えるわけではない。
LayerXの記事も出てた。こちらはStorybookベース。