前端搭建 MCP Client(Web版)+ Server + Agent 实践

开发者福利!热门AI工具限时免费用 购周边即赠Coding Plan Lite,Claude Code、Cursor等20+工具畅享,效率翻倍! 阅读详情

image.png先上个效果图,上图是在 web 版 Client 中使用 todoist-mcp-server 帮我新建了一条 todolist

本文主要介绍整体的思路和实现以及踩坑记录。

前言

‌MCP(Model Context Protocol)是一种开放协议,旨在通过标准化接口实现大语言模型(LLMs)与外部数据源及工具的无缝集成。MCP由 Anthropic 公司在2024年底推出,其设计理念类似于USB接口,为AI模型提供了一个“即插即用”的扩展能力,使其能够轻松连接至不同的工具和数据源‌。想深入了解可查看 官方文档,这里只做实战经验分享。

概念介绍

  • MCP Hosts(MCP 应用):如Claude Desktop、IDE、AI应用等,希望通过MCP访问数据或工具。

  • MCP Clients(MCP 客户端):与一对一与服务端进行连接,相当于我们应用中实现数据库交互需要实现的一个客户端。

  • MCP Servers(MCP 服务端):基于MCP协议实现特定功能的程序。

  • Local Data Sources:本地数据源,公MCP服务器进行本地访问。

  • Remote Services:远端服务,供MCP服务器访问远端访问,例如api的方式。

本文主要搭建 Web 版本的 MCP Client 和 MCP Server

技术栈

系统要求:Node.js >= 18(本地用了v20)

核心依赖库:CopilotKitLangChain及其生态。

  • CopilotKit:React UI + 适用于 AI Copilot、AI 聊天机器人和应用内 AI 代理的优雅基础架构。

  • LangChain.js 和 LangGraph:LangChain相关主要用于开发agent。

  • langchainjs-mcp-adapters :提供了一个轻量级的包装器,使得 MCP 与 LangChain.js 兼容。

  • modelcontextprotocol/typescript-sdk:MCP TypeScript SDK

  • open-mcp-client:CopilotKit 开源的 MCP Client。

  • mcp-server-supos:一个可用的 MCP Server。

Client

页面大概这样,包括:左侧管理MCP Server、右侧聊天机器人

image.png

技术方案
mcp架构.png

声明:此 Client 是基于CopilotKit 开源的 MCP Client open-mcp-client 二次改造

image.png

该代码库主要分为两个部分:

  1. /agent – 连接到 MCP Server并调用其工具的LangGraph代理(Python)。

  2. /app – 使用 CopilotKit 进行UI和状态同步的前端应用程序(Next.js)。

由于 Python 的 agent 在 Windows 环境下运行时报错:

image.png

本人Python编码能力有限,基于此改造成了基于 JS 的 agent/agent-js部分),后续均以agent-js为例;想用 Python 的也可按后续的改动点对 /agent 进行修改。

一、agent部分

文件结构
image.png

核心代码

「agent.js」 - 基于 langgraph 创建 workflow,其中主要节点为 chat_node,该节点功能点:

  • 定义LLM

import { ChatOpenAI } from"@langchain/openai";
// import { HttpsProxyAgent } from "https-proxy-agent";

// const agentProxy = new HttpsProxyAgent("http://127.0.0.1:xxxx");
...
// 1 Define the model
const model = new ChatOpenAI(
    {
      temperature: 0,
      model: "gpt-4o",
    },
    // todo: test, 走本地代理便于翻墙
    // {
    //   httpAgent: agentProxy,
    // }
  );
...

「注意:本地联调需访问 openai 时,如果是使用的代理工具,还是需要在代码里指定代理地址(HttpsProxyAgent)」

  • 从 state 获取 MCP Server Configs,创建 MCP Client 连接到 MCP Server,连通后获取 Server 的 tools。(@langchain/mcp-adapters)

const mcpConfig: any = state.mcp_config || {};

// 重要:设置环境变量时,最好把当前进程的环境变量也传递过去,确保执行Server的子进程需要的环境变量都存在
let newMcpConfig: any = {};
Object.keys(mcpConfig).forEach((key) => {
    newMcpConfig[key] = { ...mcpConfig[key] };
    if (newMcpConfig[key].env) {
      newMcpConfig[key].env = { ...process.env, ...newMcpConfig[key].env };
    }
  });

console.log("****mcpConfig****", mcpConfig);

// 2 Create client
const client = new MultiServerMCPClient(newMcpConfig);
// examples
// const client = new MultiServerMCPClient({
//   math: {
//     transport: "stdio",
//     command: "npx",
//     args: ["-y", "mcp-server-supos"],
//     env: {"SUPOS_API_KEY": "xxxxx"}
//   },
// });

// 3 Initialize connection to the server
await client.initializeConnections();
const tools = client.getTools();
  • 基于 model 和 tools 创建代理,并调用模型发送状态中的消息

// 4 Create the React agent width model and tools
  const agent = createReactAgent({
    llm: model,
    tools,
  });

  // 5 Invoke the model with the system message and the messages in the state
  const response = await agent.invoke({ messages: state.messages });

「完整代码」

agent.js

/**
 * This is the main entry point for the agent.
 * It defines the workflow graph, state, tools, nodes and edges.
 */

import { RunnableConfig } from"@langchain/core/runnables";
import {
  MemorySaver,
  START,
  StateGraph,
  Command,
  END,
} from"@langchain/langgraph";
import { createReactAgent } from"@langchain/langgraph/prebuilt";
import { Connection, MultiServerMCPClient } from"@langchain/mcp-adapters";
import { AgentState, AgentStateAnnotation } from"./state";
import { getModel } from"./model";

// 判断操作系统
const isWindows = process.platform === "win32";

const DEFAULT_MCP_CONFIG: Record<string, Connection> = {
supos: {
    command: isWindows ? "npx.cmd" : "npx",
    args: [
      "-y",
      "mcp-server-supos",
    ],
    env: {
      SUPOS_API_URL: process.env.SUPOS_API_URL || "",
      SUPOS_API_KEY: process.env.SUPOS_API_KEY || "",
      SUPOS_MQTT_URL: process.env.SUPOS_MQTT_URL || "",
    },
    transport: "stdio",
  },
};

asyncfunction chat_node(state: AgentState, config: RunnableConfig) {
// 1 Define the model
const model = getModel(state);

const mcpConfig: any = { ...DEFAULT_MCP_CONFIG, ...(state.mcp_config || {}) };

// 重要:设置环境变量时,最好把当前进程的环境变量也传递过去,确保执行Server的子进程需要的环境变量都存在
let newMcpConfig: any = {};
Object.keys(mcpConfig).forEach((key) => {
    newMcpConfig[key] = { ...mcpConfig[key] };
    if (newMcpConfig[key].env) {
      newMcpConfig[key].env = { ...process.env, ...newMcpConfig[key].env };
    }
  });

console.log("****mcpConfig****", mcpConfig);

// 2 Create client
const client = new MultiServerMCPClient(newMcpConfig);
// const client = new MultiServerMCPClient({
//   math: {
//     transport: "stdio",
//     command: "npx",
//     args: ["-y", "mcp-server-supos"],
//     env: {"SUPOS_API_KEY": "xxxxx"}
//   },
// });

// 3 Initialize connection to the server
await client.initializeConnections();
const tools = client.getTools();

// 4 Create the React agent width model and tools
const agent = createReactAgent({
    llm: model,
    tools,
  });

// 5 Invoke the model with the system message and the messages in the state
const response = await agent.invoke({ messages: state.messages });

// 6 Return the response, which will be added to the state
return [
    new Command({
      goto: END,
      update: { messages: response.messages },
    }),
  ];
}

// Define the workflow graph
const workflow = new StateGraph(AgentStateAnnotation)
  .addNode("chat_node", chat_node)
  .addEdge(START, "chat_node");

const memory = new MemorySaver();

exportconst graph = workflow.compile({
checkpointer: memory,
});

model.js

/**
 * This module provides a function to get a model based on the configuration.
 */
import { BaseChatModel } from"@langchain/core/language_models/chat_models";
import { AgentState } from"./state";
import { ChatOpenAI } from"@langchain/openai";
import { ChatAnthropic } from"@langchain/anthropic";
import { ChatMistralAI } from"@langchain/mistralai";
// import { HttpsProxyAgent } from "https-proxy-agent";

// todo test agentProxy
// const agentProxy = new HttpsProxyAgent("http://127.0.0.1:7897");

function getModel(state: AgentState): BaseChatModel {
/**
   * Get a model based on the environment variable.
   */
const stateModel = state.model;
const stateModelSdk = state.modelSdk;
// 解密
const stateApiKey = atob(state.apiKey || "");
const model = process.env.MODEL || stateModel;

console.log(
    `Using stateModelSdk: ${stateModelSdk}, stateApiKey: ${stateApiKey}, stateModel: ${stateModel}`
  );

if (stateModelSdk === "openai") {
    returnnew ChatOpenAI({
      temperature: 0,
      model: model || "gpt-4o",
      apiKey: stateApiKey || undefined,
    }
      // {
      //   httpAgent: agentProxy,
      // }
    );
  }
if (stateModelSdk === "anthropic") {
    returnnew ChatAnthropic({
      temperature: 0,
      modelName: model || "claude-3-7-sonnet-latest",
      apiKey: stateApiKey || undefined,
    });
  }
if (stateModelSdk === "mistralai") {
    returnnew ChatMistralAI({
      temperature: 0,
      modelName: model || "codestral-latest",
      apiKey: stateApiKey || undefined,
    });
  }

thrownewError("Invalid model specified");
}

export { getModel };

state.js

import { Annotation } from"@langchain/langgraph";
import { CopilotKitStateAnnotation } from"@copilotkit/sdk-js/langgraph";
import { Connection } from"@langchain/mcp-adapters";

// Define the AgentState annotation, extending MessagesState
exportconst AgentStateAnnotation = Annotation.Root({
model: Annotation<string>,
modelSdk: Annotation<string>,
apiKey: Annotation<string>,
mcp_config: Annotation<Connection>,
  ...CopilotKitStateAnnotation.spec,
});

export type AgentState = typeof AgentStateAnnotation.State;
构建和运行
  1. 定义 langgraph.json 配置文件,定义 agent 相关配置,比如agent名称:sample_agent

{
  "node_version": "20",
"dockerfile_lines": [],
"dependencies": ["."],
"graphs": {
    "sample_agent": "./src/agent.ts:graph"// 定义agent名称等,用于前端指定使用
  },
"env": ".env"// 指定环境变量从.env文件中获取,生产环境可以删除该配置,从系统变量中获取
}

在本地运行时,在根路径 /agent-js 添加 .env 文件

LANGSMITH_API_KEY=lsv2_...OPENAI_API_KEY=sk-...
2.借助命令行工具@langchain/langgraph-cli进行构建和运行,在 package.json 中定义脚本:
"scripts": {
    "start": "npx @langchain/langgraph-cli dev --host localhost --port 8123",
    "dev": "npx @langchain/langgraph-cli dev --host localhost --port 8123 --no-browser"
  },

加上--no-browser不会自动打开本地调试的studio页面

运行后可以在Studio预览联调等

(Studio:https://smith.langchain.com/studio/thread?baseUrl=http%3A%2F%2Flocalhost%3A8123)

image.png
注意点(踩坑记录)
1. 引入modelcontextprotocol/
typescript-sdk报错:

@modelcontextprotocol/sdk fails in CommonJS projects due to incompatible ESM-only dependency (pkce-challenge)

image.png

主要是modelcontextprotocol/

typescript-sdk的cjs包里面引用的pkce-challenge不支持cjs

image.png

官方的issues也有提出些解决方案,但目前为止官方还未发布解决了该问题的版本

image.png

「解决:package.json 添加"type": "module" 字段,声明项目使用 「ES Modules (ESM)」  规范」

2. 配置 MCP Server 环境变量 env 问题

例如:Node.js 的 child_process.spawn() 方法无法找到例如 npx 等可执行文件。
「环境变量 PATH 缺失」,系统未正确识别 npx 的安装路径。

可能的原因:

1)MCP Server配置了 env 参数后,导致传入的 env 覆盖了默认从父进程获取的环境变量
image.png

「解决:对配置了 env 的 Server,将当前的环境变量合并传入」

const mcpConfig: any = state.mcp_config || {};

  // 重要:设置环境变量时,最好把当前进程的环境变量也传递过去,确保执行Server的子进程需要的环境变量都存在
  let newMcpConfig: any = {};
  Object.keys(mcpConfig).forEach((key) => {
    newMcpConfig[key] = { ...mcpConfig[key] };
    if (newMcpConfig[key].env) {
      newMcpConfig[key].env = { ...process.env, ...newMcpConfig[key].env };
    }
  });
2) 「跨平台路径问题」:比如在 Windows 中直接调用 npx 需使用 npx.cmd
// 判断操作系统
const isWindows = process.platform === "win32";

const DEFAULT_MCP_CONFIG: Record<string, Connection> = {
supos: {
    command: isWindows ? "npx.cmd" : "npx",
    args: [
      "-y",
      "mcp-server-supos",
    ],
    env: {
      SUPOS_API_URL: process.env.SUPOS_API_URL || "",
      SUPOS_API_KEY: process.env.SUPOS_API_KEY || "",
      SUPOS_MQTT_URL: process.env.SUPOS_MQTT_URL || "",
    },
    transport: "stdio",
  },
};

二、前端应用部分

前端应用部分改动主要是页面上的一些功能添加等,例如支持选模型,支持配置 env 参数等,页面功能相关的内容就略过,可以直接看 open-mcp-client,这里简单介绍下整体的一个架构。

架构方案

主要是 CopilotKit + Next.js,先看下 「CopilotKit」 官方的一个架构图:

image.png

根据本文实际用到的简化下(本文采用的 CoAgents模式

copilotkit架构.png

核心代码(以Next.js为例)

核心依赖 @copilotkit/react-ui @copilotkit/react-core @copilotkit/runtime


image.png

1. 设置运行时端点

/app/api/copilotkit/route.ts:设置 agent 远程端点

import {
    CopilotRuntime,
    ExperimentalEmptyAdapter,
    copilotRuntimeNextJSAppRouterEndpoint,
    langGraphPlatformEndpoint
} from"@copilotkit/runtime";;
import { NextRequest } from"next/server";

// You can use any service adapter here for multi-agent support.
const serviceAdapter = new ExperimentalEmptyAdapter();

const runtime = new CopilotRuntime({
    remoteEndpoints: [
        langGraphPlatformEndpoint({
            // agent部署地址
            deploymentUrl: `${process.env.AGENT_DEPLOYMENT_URL || 'http://localhost:8123'}`, 
            langsmithApiKey: process.env.LANGSMITH_API_KEY,
            agents: [
                {
                    name: 'sample_agent', // agent 名称
                    description: 'A helpful LLM agent.',
                }
            ]
        }),
    ],
});

exportconst POST = async (req: NextRequest) => {
    const { handleRequest } = copilotRuntimeNextJSAppRouterEndpoint({
        runtime,
        serviceAdapter,
        endpoint: "/api/copilotkit",
    });

    return handleRequest(req);
};
2. 页面接入 CopilotKit UI

/app/layout.tsx:页面最外层用 CopilotKit 包裹,配置 runtimeUrl 和 agent

import type { Metadata } from"next";
import { Geist, Geist_Mono } from"next/font/google";
import"./globals.css";
import"@copilotkit/react-ui/styles.css";
import { CopilotKit } from"@copilotkit/react-core";

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

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

exportconst metadata: Metadata = {
title: "Open MCP Client",
description: "An open source MCP client built with CopilotKit 🪁",
};

exportdefaultfunction RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
return (
    <html lang="en">
      <body
        className={`${geistSans.variable} ${geistMono.variable} antialiased w-screen h-screen`}
      >
        <CopilotKit
          runtimeUrl="/api/copilotkit"
          agent="sample_agent"
          showDevConsole={false}
        >
          {children}
        </CopilotKit>
      </body>
    </html>
  );
}

/app/page.tsx:选择需要的聊天组件,例如 CopilotPopup

"use client";
import { CopilotPopup } from "@copilotkit/react-ui";

export function Home() {
  return (
    <>
      <YourMainContent />
      <CopilotChat
          className="h-full flex flex-col"
          instructions={
            "Youareassistingtheuserasbestasyoucan.Answerinthebestwaypossiblegiventhedatayouhave."
          }
          labels={{
            title: "MCPAssistant",
            initial: "Needanyhelp?",
          }}
        />
    </>
  );
}
构建和运行

这里就参照 Next.js 官方即可

package.json

"scripts": {
    "dev-frontend": "pnpm i && next dev --turbopack",
    "dev-agent-js": "cd agent-js && pnpm i && npx @langchain/langgraph-cli dev --host 0.0.0.0 --port 8123 --no-browser",
    "dev-agent-py": "cd agent && poetry install && poetry run langgraph dev --host 0.0.0.0 --port 8123 --no-browser",
    "dev": "pnpx concurrently \"pnpm dev-frontend\" \"pnpm dev-agent-js\" --names ui,agent --prefix-colors blue,green",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },

Server

建议直接参考 MCP Server Typescript SDK 示例开发,官网文档的用法更新没那么及时,容易走弯路。

mcp-server-supos 是一个可用的 MCP Server,也发布了对应的 npm 包。

这里截取核心代码片段,想了解更多可点击查看源码和使用文档等。

核心代码

  • 提供tool-调用API查询信息

  • 实时订阅MQTT topic数据进行缓存,用于提供 tool 查询分析最新数据

  • 示例 server.resource

index.ts

#!/usr/bin/env node
import { McpServer } from"@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from"@modelcontextprotocol/sdk/server/stdio.js";
import fetch from"node-fetch";
import { z } from"zod";
import fs, { readFileSync } from"fs";
import _ from"lodash";
import mqtt from"mqtt";
import { pathToFileURL } from"url";

import { createFilePath } from"./utils.js";

let SUPOS_API_URL =
  process.env.SUPOS_API_URL;
let SUPOS_API_KEY =
  process.env.SUPOS_API_KEY;
let SUPOS_MQTT_URL =
  process.env.SUPOS_MQTT_URL;

if (!SUPOS_API_URL) {
console.error("SUPOS_API_URL environment variable is not set");
  process.exit(1);
}

if (!SUPOS_API_KEY) {
console.error("SUPOS_API_KEY environment variable is not set");
  process.exit(1);
}

const filePath = createFilePath();
const fileUri = pathToFileURL(filePath).href;

asyncfunction getModelTopicDetail(topic: string): Promise<any> {
const url = `${SUPOS_API_URL}/open-api/supos/uns/model?topic=${encodeURIComponent(
    topic
  )}`;

const response = await fetch(url, {
    headers: {
      apiKey: `${SUPOS_API_KEY}`,
    },
  });

if (!response.ok) {
    thrownewError(`SupOS API error: ${response.statusText}`);
  }

returnawait response.json();
}

function getAllTopicRealtimeData() {
// 缓存实时数据,定时写入缓存文件
const cache = newMap();
let timer: any = null;

const options = {
    clean: true,
    connectTimeout: 4000,
    clientId: "emqx_topic_all",
    rejectUnauthorized: false,
    reconnectPeriod: 0, // 不进行重连
  };

const connectUrl = SUPOS_MQTT_URL;
if (!connectUrl) {
    return;
  }

const client = mqtt.connect(connectUrl, options);

  client.on("connect", function () {
    client.subscribe("#", function (err) {
      // console.log("err", err);
    });
  });

  client.on("message", function (topic, message) {
    cache.set(topic, message.toString());
  });

  client.on("error", function (error) {
    // console.log("error", error);
  });
  client.on("close", function () {
    if (timer) {
      clearInterval(timer);
    }
  });
// 每 5 秒批量写入一次
  timer = setInterval(() => {
    const cacheJson = JSON.stringify(
      Object.fromEntries(Array.from(cache)),
      null,
      2
    );
    // 将更新后的数据写入 JSON 文件
    fs.writeFile(
      filePath,
      cacheJson,
      {
        encoding: "utf-8",
      },
      (error) => {
        if (error) {
          fs.writeFile(
            filePath,
            JSON.stringify({ msg: "写入数据失败" }, null, 2),
            { encoding: "utf-8" },
            () => {}
          );
        }
      }
    );
  }, 5000);
}

function createMcpServer() {
const server = new McpServer(
    {
      name: "mcp-server-supos",
      version: "0.0.1",
    },
    {
      capabilities: {
        tools: {},
      },
    }
  );

// Static resource
  server.resource("all-topic-realtime-data", fileUri, async (uri) => ({
    contents: [
      {
        uri: uri.href,
        text: readFileSync(filePath, { encoding: "utf-8" }),
      },
    ],
  }));

  server.tool(
    "get-model-topic-detail",
    { topic: z.string() },
    async (args: any) => {
      const detail = await getModelTopicDetail(args.topic);
      return {
        content: [{ type: "text", text: `${JSON.stringify(detail)}` }],
      };
    }
  );

  server.tool("get-all-topic-realtime-data", {}, async () => {
    return {
      content: [
        {
          type: "text",
          text: readFileSync(filePath, { encoding: "utf-8" }),
        },
      ],
    };
  });

asyncfunction runServer() {
    const transport = new StdioServerTransport();
    const serverConnect = await server.connect(transport);
    console.error("SupOS MCP Server running on stdio");
    return serverConnect;
  }

  runServer().catch((error) => {
    console.error("Fatal error in main():", error);
    process.exit(1);
  });
}

asyncfunction main() {
try {
    createMcpServer();
    getAllTopicRealtimeData();
  } catch (error) {
    console.error("Error in main():", error);
    process.exit(1);
  }
}

main();

utils.ts

import fs from"fs";
import path from"path";

exportfunction createFilePath(
  filedir: string = ".cache",
  filename: string = "all_topic_realdata.json"
) {
// 获取项目根路径
const rootPath = process.cwd();

// 创建缓存目录
const filePath = path.resolve(rootPath, filedir, filename);
const dirPath = path.dirname(filePath);

// 检查目录是否存在,如果不存在则创建
if (!fs.existsSync(dirPath)) {
    fs.mkdirSync(dirPath, { recursive: true });
  }

return filePath;
}

exportfunction readFileSync(filePath: string, options: any) {
try {
    return fs.readFileSync(filePath, options);
  } catch (err) {
    return`读取文件时出错: ${err}`;
  }
}

如何使用

「Client」:目前支持MCP协议的客户端已有很多,比如桌面端应用 Claude for Desktop,或者IDE的一些插件等(VSCode 的 Cline 插件),想了解已支持的客户端可访问 Model Context Protocol Client

「Server」:除了官方例子Model Context Protocol Client 外,已有很多网站整合了 MCP Servers,例如 mcp.so, Glama 等。

下面列举几个介绍下:

1. 配合本文 web 版 Client 使用(以todoist-mcp-server为例子)
1)配置
image.png
2)使用
image.png
2. 配合 Claude 使用

具体可参考:mcp-server-supos README.md,服务换成自己需要的即可

3. 使用 VSCode 的 Cline 插件

由于使用 npx 找不到路径,这里以 node 执行本地文件为例

1)配置
image.png
2)使用
image.png

结语

以上便是近期使用 MCP 的一点小经验~

整理完后看了下,如果只是单纯想集成些 MCP Server,其实可以不用 agent 形式,直接使用 copilotkit 的标准模式,在本地服务调用 langchainjs-mcp-adapters 和 LLM 即可,例如:

import {
  CopilotRuntime,
  LangChainAdapter,
  copilotRuntimeNextJSAppRouterEndpoint,
} from'@copilotkit/runtime';
import { ChatOpenAI } from"@langchain/openai";
import { NextRequest } from'next/server';

// todo: 调用 @langchain/mcp-adapters 集成 MCP Server 获取 tools 给到大模型
 ...

const model = new ChatOpenAI({ model: "gpt-4o", apiKey: process.env.OPENAI_API_KEY });
const serviceAdapter = new LangChainAdapter({
    chainFn: async ({ messages, tools }) => {
    return model.bindTools(tools).stream(messages);
    // or optionally enable strict mode
    // return model.bindTools(tools, { strict: true }).stream(messages);
  }
});
const runtime = new CopilotRuntime();

exportconst POST = async (req: NextRequest) => {
const { handleRequest } = copilotRuntimeNextJSAppRouterEndpoint({
    runtime,
    serviceAdapter,
    endpoint: '/api/copilotkit',
  });

return handleRequest(req);
};

但这样可能少了些上下文状态等,具体可以下来都试试~


   -END -

如果您关注前端+AI 相关领域可以扫码进群交流

添加小编微信进群😊

关于奇舞团

奇舞团是 360 集团最大的大前端团队,非常重视人才培养,有工程师、讲师、翻译官、业务接口人、团队 Leader 等多种发展方向供员工选择,并辅以提供相应的技术力、专业力、通用力、领导力等培训课程。奇舞团以开放和求贤的心态欢迎各种优秀人才关注和加入奇舞团。

快速上手:实现你的第一个 MCP Client 本文介绍了如何使用 MCP Python SDK 编写一个 MCP 客户端,并集成 LLM 来实现灵活的工具调用和数据处理。通过简单的示例和进阶示例,展示了如何通过标准输入输出(stdio)方式与 MCP 服务器建立连接,并集成 LLM(如通义千问)来实现更复杂的应用场景。 阅读详情

相关推荐

MCP】从0到1实现一个MCP Client

MCP Client(Model Context Protocol Client)是模型上下文协议(MCP)架构中的核心组件,负责连接AI模型(如Claude、GPT等)与外部数据源或工具服务

Jeffray1991的博客 1600

必看!SpringAI轻松构建MCP Client-Server架构

MCP 是 Model Context Protocol,模型上下文协议,它是由 Anthropic(Claude 大模型母公司)提出的开放协议,用于大模型连接外部“数据源”的一种协议。是通过 Spring Boot 集成扩展了 MCP 的 Java SDK(开发工具),它同时提供了 Spring Boot 客户端和服务器的启动器,方便使用 Spring AI MCP 快速开发 AI 应用程序。

磊哥聊Java 7782

MCP客户端Client开发

打开client.py文件编写代码,可以用记事本、notepad++等,不过建议用一款编程软件,这样可以提升代码编写效率,作者采用vscode。创建项目和创建虚拟环境,已经在上篇中介绍过了,这里不做详细介绍,仅仅列出相关命令。组合上述代码,运行结果如下,这样一个简单的连接AI客户端就实现好了 ^_^将上述代码组合,一个简单的客户端就开发好了!注:MODEL可以更换为DeepSeek模型或者其他或者本地模型。至此客户端和服务端实现完成,是不是不是很难 ^_^执行上述命令创建好了项目并且激活了虚拟环境。

haoswich的专栏 2040

## 如何学习大模型 AI ? 由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。 但是具体到个人,只能说是: **“最先掌握AI的人,将会比较晚掌握AI的

MCP-Client是(模型上下文协议)架构中的一个重要组件,用于连接AI模型(如ClaudeGPT等大型语言模型)与外部数据源、工具和服务的桥梁。是由Anthropic公司在2024年底首次提出并开源的一种开放标准协议,旨在解决大语言模型(LLM)与外部世界的连接问题。这一协议的核心价值在于打破了AI模型的"信息孤岛"限制,使模型能够以标准化的方式访问和处理实时数据,显著扩展了大模型的应用场景。在MCPServerAPIMCPClientAIMCPAIHostLLMClaudeCursor IDE。

Python_cocola的博客 1690

基于 MCP 的 AI Agent 应用开发实践

最近大家都在聊 MCP,发现有个最重要的点被忽略了 『通过标准化协议,将工具提供方与应用研发者解耦』 ,这一点带来的将是 AI Agent 应用研发范式的转移(类似 Web 应用研发的前后端分离)。 本文以开发 Agent TARS 应用为例,尽可能详细地介绍 MCP 在『开发范式』、『工具生态扩展』上起到的作用。

bytedanceospo的博客 1306

从零实现Agent搜索MCP Server:构建、接入与生产实践

MCP(Model Context Protocol)协议为大模型与外部数据源、工具之间提供了标准化的交互通道,其核心价值在于让AI Agent的能力发现与工具调用遵循统一语义。理解MCP Host、ClientServer的边界,是开发可复用智能体搜索服务的基础。借助TypeScript官方SDK,开发者能以较小的成本构建一个支持关键词过滤、分类检索和详情查询的MCP工具,并通过stdio或HTTP传输供Claude Desktop、Cursor等任意符合MCP规范的工具消费。在工程实践中,搜索AI A

weixin_30363509的博客 403

Buy My Agent MCP Server:AI Agent搜索与发现工具部署指南

模型上下文协议(MCP)为AI应用连接外部工具提供了标准化通道,而AI Agent作为智能执行单元,其发现与调用成为工作流集成的关键环节。MCP Server将工具能力封装为可搜索的服务,使得模型能够在对话中直接检索并选择所需Agent。文章围绕一个名为Buy My AgentMCP Server项目展开,它把Agent搜索能力标准化,支持从任意MCP客户端发起自然语言查询,并返回结构化的Agent信息。文中详细介绍了从环境准备、配置注册到接口调用的完整流程,涵盖tools/list与tools/call

weixin_34163553的博客 473

那么多的MCP server,如何构建自己的MCP client

如果说 OpenAI 插件像是浏览器中的扩展程序——在特定环境中实用但受限,那么 MCP 就像是开放的 Web 本身,带来了无限的连接与组合可能。插件虽有价值,却难以摆脱平台锁定和接口限制,而 MCP 所代表的,是一种真正去中心化、跨平台、可互操作的工具使用协议。现在,每个人都痴迷于大模型的能力,从GPT-5的谣言, 到Claude 3 性能, 以及Gemini的多模态演示。但事实是,模型并不是人工智能的全部,但Agent可能是。Agent的定义可能不是它们知道什么,而是由它们能做什么来定义。

jike007gt的博客 816

从 Function Calling 到 MCPAgent 工具调用的协议演进与架构实践

文章摘要(150字) MCP(Model Context Protocol)旨在解决不同大模型(如OpenAI、Anthropic等)工具调用(Function Calling)的私有协议碎片化问题。传统方案需为每个模型适配工具代码(N×M适配),而MCP通过标准化三层架构(Host/Client/Server)实现解耦:工具开发者只需按MCP协议暴露能力,模型通过统一接口调用。MCP不仅支持工具调用(Tools),还扩展至数据(Resources)和提示词(Prompts),但目前工具场景占主导。其核心价

恋恋风尘的博客 416

AI Agent开发避坑指南:MCP ServerClient的完整对接流程

本文详细解析了AI Agent开发中,如何完整对接MCP ServerClient的流程与常见陷阱。通过一个天气查询工具实例,从环境搭建、工具定义、本地调试到Client端连接与协议处理,系统梳理了开发步骤,并重点分享了路径配置、工具描述优化、异步资源管理等实战避坑指南,帮助开发者高效完成MCP集成。

weixin_29100927的博客 201

深入 LangGraph:mcp-client-cli 的 ReAct Agent 与工具调用确认机制

mcp-client-cli 是一款基于 LangGraph 构建的 MCP 客户端命令行工具,它把"LLM 提示词 + MCP 服务器工具"无缝封装进一个 `llm` 命令。本文带你深入它的核心:LangGraph 如何驱动 ReAct Agent 完成"思考-行动-观察"循环,以及工具调用确认机制如何为每一次工具执行加一道人工安全闸。无论你是刚接触 MCP 的新手,还是想借鉴 Agent 工程

gitblog_00961的博客 1019

MCP Server实战:在MCP客户端中直接搜索AI Agents

模型上下文协议(Model Context Protocol,MCP)为AI应用提供了一种标准化的方式,让客户端与大模型工具之间实现无缝交互。在Agent生态快速发展的当下,如何高效发现和检索可用的AI Agents成为关键需求。基于MCPServer端实现,可以将“搜索AI Agents”封装为标准工具,使Claude Desktop、Cline、Cherry Studio等MCP客户端能够直接调用,用户无需跳出对话窗口即可完成Agent查找。这类设计不仅降低了工具切换成本,也为LLM在对话中自主调用外

weixin_30367873的博客 438

本地搭建搜索Agent(SpringAI + RAG + SearXNG + MCP

课程链接:https://coding.imooc.com/class/948.html其实现在的Agent平台把这个课的东西都实现得很好用,让我自己搭个agent我也大概率不会选择用这份代码从头搭建。就当手动搭建了下,对原理多些了解吧。

美好的事情即将发生 1155

MCP协议与AI Agent开发:从工具连接到工程化实战

在人工智能领域,大语言模型(LLM)作为强大的认知引擎,其核心价值在于理解和生成自然语言。然而,模型本身缺乏与外部系统和数据源交互的“执行能力”,这限制了其在复杂任务中的应用。为解决这一关键问题,模型上下文协议(MCP)应运而生,它定义了一套标准化的通信规范,使大模型能够动态发现、理解并安全调用外部工具。这一技术范式将AI从单纯的对话接口,升级为能够自主规划、执行多步骤任务的智能体(Agent),极大地提升了自动化水平。从工程实践角度看,基于MCPAgent开发涉及工具生态集成、任务规划、错误处理与安全控

weixin_34050005的博客 386

MCP协议开发实战:从零搭建AI Agent工具链

MCP协议:AI应用与企业系统的标准化桥梁 摘要: MCP(Model Context Protocol)是一种新兴的开放协议,旨在解决大语言模型与企业级系统对接时的标准化问题。该协议通过定义统一的工具调用规范,使AI应用能够高效连接各类数据源和业务系统。文章详细介绍了MCP的三层架构(Host-Client-Server),并以Python实现为例,展示了从创建订单查询工具到构建完整MCP Agent的开发流程。MCP的核心价值在于将AI从简单的聊天功能升级为能执行实际任务的智能Agent,同时强调了企业

2301_78577992的博客 201

[MCP在LangChain中的应用-01]利用MultiServerMCPClient连接多个MCP Server

LangChain将langchain_mcp_adapters库作为MCP客户端SDK,它以MultiServerMCPClient为核心,它类似于fastmcp.client.Client。fastmcp.client.Client基本是完全按照MCP规范定义的,所以它基本上直接使用mcp库提供的输入和输出类型。MultiServerMCPClient的定位不同,它会在实现MCP规范的基础上完成与LangChain编程模式的适配,这一点从langchain_mcp_adapters库的命名就可以看出来

JaydenAI的博客 915

手搓 MCP Client——Java 应用连接任意 MCP Server

上篇博客文章把 MCP Server 写完了——Tools、Resources、Prompts 全实现了,工具也接进 Cursor 跑通了。这节换个方向,从 Server 侧切换到 Client 侧,让大家的 Spring Boot Agent 能主动连接并调用任意 MCP Server。:暴露工具的一方,被动等待调用。上篇博客文章写的 mcp-tools-server 就是 Server。:主动发起连接的一方,调用 Server 提供的工具,把结果拿回来给 Agent 用。

· 367
上一篇: 奇舞周刊第554期:响应式机制的未来:Signal 与现代前端框架
下一篇: 基于LangChain ReAct Agents构建RAG问答系统
奇舞周刊
博客等级 码龄7年 1898粉丝 568原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值