Skip to content

MCP Protocol: Bridging Frontend Toolchains

MCP (Model Context Protocol) is becoming the standard protocol between AI and tools. Let's talk about how frontend engineers can leverage MCP to boost development efficiency.

What is MCP

MCP = Model Context Protocol

Essence: enables AI models to safely call external tools and data sources
Analogy: like how APIs serve web apps, MCP serves AI models

Supporters: Anthropic (Claude), major IDEs, dev tools

MCP Architecture

┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│  AI Model   │────▶│  MCP Client │────▶│  MCP Server │
│  (Claude)   │◀────│  (IDE/CLI)  │◀────│  (Tool)     │
└─────────────┘     └─────────────┘     └─────────────┘

MCP Server provides:
  - Resources: data sources (files, databases, APIs)
  - Tools: executable operations
  - Prompts: preset prompt templates

Hands-On: Building a Figma MCP Server

ts
// figma-mcp-server.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

const server = new Server(
  { name: "figma-mcp", version: "1.0.0" },
  { capabilities: { tools: {} } },
);

// 注册工具:获取 Figma 设计稿信息
server.setRequestHandler("tools/list", async () => ({
  tools: [
    {
      name: "get_figma_file",
      description: "获取 Figma 文件的结构和组件信息",
      inputSchema: {
        type: "object",
        properties: {
          fileKey: { type: "string", description: "Figma 文件 key" },
          nodeId: { type: "string", description: "节点 ID(可选)" },
        },
        required: ["fileKey"],
      },
    },
    {
      name: "export_figma_assets",
      description: "导出 Figma 中的图标和图片资源",
      inputSchema: {
        type: "object",
        properties: {
          fileKey: { type: "string" },
          format: { type: "string", enum: ["svg", "png", "jpg"] },
          scale: { type: "number", default: 1 },
        },
        required: ["fileKey", "format"],
      },
    },
  ],
}));

// 处理工具调用
server.setRequestHandler("tools/call", async (request) => {
  const { name, arguments: args } = request.params;

  if (name === "get_figma_file") {
    const response = await fetch(
      `https://api.figma.com/v1/files/${args.fileKey}`,
      {
        headers: { "X-Figma-Token": process.env.FIGMA_TOKEN! },
      },
    );
    const data = await response.json();
    return {
      content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
    };
  }

  throw new Error(`Unknown tool: ${name}`);
});

// 启动服务
const transport = new StdioServerTransport();
await server.connect(transport);

Hands-On: Frontend Project Analysis MCP Server

ts
// project-analyzer-mcp.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { glob } from "glob";
import fs from "fs/promises";

const server = new Server(
  { name: "project-analyzer", version: "1.0.0" },
  { capabilities: { tools: {} } },
);

server.setRequestHandler("tools/list", async () => ({
  tools: [
    {
      name: "analyze_dependencies",
      description: "分析项目依赖关系和未使用的包",
      inputSchema: {
        type: "object",
        properties: {
          projectRoot: { type: "string" },
        },
        required: ["projectRoot"],
      },
    },
    {
      name: "find_unused_exports",
      description: "查找未被引用的导出",
      inputSchema: {
        type: "object",
        properties: {
          projectRoot: { type: "string" },
          pattern: { type: "string", default: "src/**/*.{ts,tsx}" },
        },
        required: ["projectRoot"],
      },
    },
    {
      name: "component_usage_report",
      description: "生成组件使用频率报告",
      inputSchema: {
        type: "object",
        properties: {
          projectRoot: { type: "string" },
        },
        required: ["projectRoot"],
      },
    },
  ],
}));

server.setRequestHandler("tools/call", async (request) => {
  const { name, arguments: args } = request.params;

  if (name === "analyze_dependencies") {
    const pkgJson = JSON.parse(
      await fs.readFile(`${args.projectRoot}/package.json`, "utf-8"),
    );
    const allFiles = await glob(`${args.projectRoot}/src/**/*.{ts,tsx}`);
    const imports = new Set<string>();

    for (const file of allFiles) {
      const content = await fs.readFile(file, "utf-8");
      const matches = content.matchAll(/from ['"]([^'"]+)['"]/g);
      for (const match of matches) {
        if (!match[1].startsWith(".") && !match[1].startsWith("@/")) {
          imports.add(
            match[1]
              .split("/")
              .slice(0, match[1].startsWith("@") ? 2 : 1)
              .join("/"),
          );
        }
      }
    }

    const deps = Object.keys(pkgJson.dependencies || {});
    const unused = deps.filter((d) => !imports.has(d));

    return {
      content: [
        {
          type: "text",
          text: JSON.stringify({ used: [...imports], unused }, null, 2),
        },
      ],
    };
  }

  throw new Error(`Unknown tool: ${name}`);
});

const transport = new StdioServerTransport();
await server.connect(transport);

Configuring MCP in Claude Code

json
// .claude/mcp.json
{
  "mcpServers": {
    "figma": {
      "command": "node",
      "args": ["./mcp-servers/figma-mcp-server.js"],
      "env": {
        "FIGMA_TOKEN": "${FIGMA_TOKEN}"
      }
    },
    "project-analyzer": {
      "command": "node",
      "args": ["./mcp-servers/project-analyzer.js"]
    }
  }
}

Once configured, you can tell Claude Code directly: "Help me analyze this project's dependency usage," and the AI will automatically call the MCP tools.

Summary

  • MCP is the standardized protocol for AI tool calls, solving the "how does AI access external tools" problem
  • Frontend toolchains (Figma, ESLint, test frameworks) can all be wrapped as MCP Servers
  • Claude Code natively supports MCP with a simple configuration
  • The barrier to building your own MCP Server is low; the SDK handles most of the heavy lifting
  • In 2025, the MCP ecosystem is expanding rapidly—worth keeping an eye on

MIT Licensed