CPN 한국어 자습서 · 외부 문서 한국어 미러
MCP 문서 · Extensions
Build an MCP App · 원문: modelcontextprotocol.io/extensions/apps/build
아래는 원문을 한국어로 옮긴 미러입니다. 코드·명령은 원문 그대로이며, 가장 최신 정보는 하단 원문 링크에서 확인하세요.
MCP 앱으로 인터랙티브 UI 애플리케이션을 구축하기 위한 시작 가이드
Node.js 18 이상이 필요합니다. MCP 도구와 리소스에 대한 친숙함이 권장되며, MCP TypeScript SDK에 대한 경험이 있으면 도움이 됩니다.
MCP 앱을 만드는 가장 빠른 방법은 MCP 앱 스킬이 있는 AI 코딩 에이전트를 사용하는 것입니다. 프로젝트를 수동으로 설정하려면 수동 설정으로 건너뛰세요.
Claude Code를 사용 중이라면 스킬을 직접 설치할 수 있습니다:
/plugin marketplace add modelcontextprotocol/ext-apps /plugin install mcp-apps@modelcontextprotocol-ext-apps
Vercel Skills CLI를 사용하면 여러 AI 코딩 에이전트에 스킬을 설치할 수 있습니다:
npx skills add modelcontextprotocol/ext-apps
또는 ext-apps 저장소를 클론하여 스킬을 수동으로 설치할 수 있습니다:
git clone https://github.com/modelcontextprotocol/ext-apps.git
스킬 디렉터리 위치:
| 에이전트 | 스킬 디렉터리 (macOS/Linux) | 스킬 디렉터리 (Windows) |
|---|---|---|
| Claude Code | ~/.claude/skills/ |
%USERPROFILE%\.claude\skills\ |
| VS Code | ~/.copilot/skills/ |
%USERPROFILE%\.copilot\skills\ |
| Gemini CLI | ~/.gemini/skills/ |
%USERPROFILE%\.gemini\skills\ |
| Cline | ~/.cline/skills/ |
%USERPROFILE%\.cline\skills\ |
| Goose | ~/.config/goose/skills/ |
%USERPROFILE%\.config\goose\skills\ |
참고: 이 목록은 포괄적이지 않습니다. 다른 에이전트는 다른 위치에서 스킬을 지원할 수 있으므로, 에이전트의 문서를 확인하세요.
Claude Code에 전역 설치하는 방법:
# macOS/Linux cp -r ext-apps/plugins/mcp-apps/skills/create-mcp-app ~/.claude/skills/create-mcp-app # Windows Copy-Item -Recurse ext-apps\plugins\mcp-apps\skills\create-mcp-app $env:USERPROFILE\.claude\skills\create-mcp-app
그런 다음 AI 코딩 에이전트에 요청합니다:
Create an MCP App that displays a color picker
my-mcp-app/
package.json
tsconfig.json
vite.config.ts
server.ts # 도구 + 리소스가 있는 MCP 서버
mcp-app.html # UI 진입점
src/
mcp-app.ts # UI 로직
npm install @modelcontextprotocol/ext-apps @modelcontextprotocol/sdk npm install -D typescript vite vite-plugin-singlefile express cors @types/express @types/cors tsx
ext-apps 패키지는 서버 측(도구와 리소스 등록)과 클라이언트 측(App 클래스) 모두에 헬퍼를 제공합니다. vite-plugin-singlefile을 사용하면 UI와 에셋을 단일 HTML 파일로 번들링하지만, 이는 선택 사항입니다.
package.json:
{
"type": "module",
"scripts": {
"build": "INPUT=mcp-app.html vite build",
"serve": "npx tsx server.ts"
}
}
tsconfig.json:
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"outDir": "dist"
},
"include": ["*.ts", "src/**/*.ts"]
}
vite.config.ts:
import { defineConfig } from "vite";
import { viteSingleFile } from "vite-plugin-singlefile";
export default defineConfig({
plugins: [viteSingleFile()],
build: {
outDir: "dist",
rollupOptions: {
input: process.env.INPUT,
},
},
});
서버 시간을 표시하는 간단한 앱 예제입니다.
// server.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import {
registerAppTool,
registerAppResource,
RESOURCE_MIME_TYPE,
} from "@modelcontextprotocol/ext-apps/server";
import cors from "cors";
import express from "express";
import fs from "node:fs/promises";
import path from "node:path";
const server = new McpServer({
name: "My MCP App Server",
version: "1.0.0",
});
// ui:// 스킴은 호스트에게 이것이 MCP 앱 리소스임을 알립니다.
const resourceUri = "ui://get-time/mcp-app.html";
// 현재 시간을 반환하는 도구 등록
registerAppTool(
server,
"get-time",
{
title: "Get Time",
description: "Returns the current server time.",
inputSchema: {},
_meta: { ui: { resourceUri } },
},
async () => {
const time = new Date().toISOString();
return {
content: [{ type: "text", text: time }],
};
},
);
// 번들된 HTML을 제공하는 리소스 등록
registerAppResource(
server,
resourceUri,
resourceUri,
{ mimeType: RESOURCE_MIME_TYPE },
async () => {
const html = await fs.readFile(
path.join(import.meta.dirname, "dist", "mcp-app.html"),
"utf-8",
);
return {
contents: [
{ uri: resourceUri, mimeType: RESOURCE_MIME_TYPE, text: html },
],
};
},
);
// HTTP를 통해 MCP 서버 노출
const expressApp = express();
expressApp.use(cors());
expressApp.use(express.json());
expressApp.post("/mcp", async (req, res) => {
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: undefined,
enableJsonResponse: true,
});
res.on("close", () => transport.close());
await server.connect(transport);
await transport.handleRequest(req, res, req.body);
});
expressApp.listen(3001, (err) => {
if (err) {
console.error("Error starting server:", err);
process.exit(1);
}
console.log("Server listening on http://localhost:3001/mcp");
});
핵심 구성 요소:
resourceUri: ui:// 스킴은 호스트에게 이것이 MCP 앱 리소스임을 알립니다.registerAppTool: _meta.ui.resourceUri 필드가 있는 도구를 등록합니다. 호스트가 이 도구를 호출하면 UI가 가져와져 렌더링되고, 도구 결과가 도착하면 앱으로 전달됩니다.registerAppResource: 호스트가 UI 리소스를 요청할 때 번들된 HTML을 제공합니다.<!-- mcp-app.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Get Time App</title>
</head>
<body>
<p>
<strong>Server Time:</strong>
<code id="server-time">Loading...</code>
</p>
<button id="get-time-btn">Get Server Time</button>
<script type="module" src="/src/mcp-app.ts"></script>
</body>
</html>
// src/mcp-app.ts
import { App } from "@modelcontextprotocol/ext-apps";
const serverTimeEl = document.getElementById("server-time")!;
const getTimeBtn = document.getElementById("get-time-btn")!;
const app = new App({ name: "Get Time App", version: "1.0.0" });
// 호스트와의 통신 연결
app.connect();
// 호스트가 푸시하는 초기 도구 결과 처리
app.ontoolresult = (result) => {
const time = result.content?.find((c) => c.type === "text")?.text;
serverTimeEl.textContent = time ?? "[ERROR]";
};
// 사용자가 UI와 상호작용할 때 도구를 직접 호출
getTimeBtn.addEventListener("click", async () => {
const result = await app.callServerTool({
name: "get-time",
arguments: {},
});
const time = result.content?.find((c) => c.type === "text")?.text;
serverTimeEl.textContent = time ?? "[ERROR]";
});
핵심 구성 요소:
app.connect(): 호스트와의 통신을 연결합니다. 앱 초기화 시 한 번 호출하세요.app.ontoolresult: 호스트가 앱으로 도구 결과를 푸시할 때 발생하는 콜백입니다.app.callServerTool(): 앱에서 서버의 도구를 직접 호출할 수 있습니다.UI를 빌드하고 로컬 서버를 시작합니다:
# macOS/Linux npm run build && npm run serve # Windows npm run build; npm run serve
기본 설정에서 서버는 http://localhost:3001/mcp에서 사용 가능합니다.
별도의 터미널에서 터널을 실행합니다:
npx cloudflared tunnel --url http://localhost:3001
생성된 URL을 복사하여 Claude에 커스텀 커넥터로 추가합니다.
참고: 커스텀 커넥터는 유료 Claude 플랜(Pro, Max, Team)에서 사용할 수 있습니다.
# macOS/Linux git clone https://github.com/modelcontextprotocol/ext-apps.git cd ext-apps/examples/basic-host npm install SERVERS='["http://localhost:3001/mcp"]' npm start # Windows git clone https://github.com/modelcontextprotocol/ext-apps.git cd ext-apps\examples\basic-host npm install $env:SERVERS='["http://localhost:3001/mcp"]'; npm start
http://localhost:8080으로 이동합니다. 도구를 선택하고 호출하면 UI 리소스를 가져와 샌드박스 iframe에서 렌더링합니다.
원문(영어): https://modelcontextprotocol.io/extensions/apps/build · 본 문서는 학습용 한국어 번역이며 원본의 권리는 원저작자(Model Context Protocol)에게 있습니다.
원문(영어): https://modelcontextprotocol.io/extensions/apps/build