欢迎光临
我们一直在努力

前端直连模型 vs 完整 MCP:大模型驱动地图的原理与实践(技术栈Vue + Cesium + Node.js + WebSocket + MCP)

在这里插入图片描述

适合读者:完全新手、前端开发者、对大模型工具调用感兴趣的工程师 技术栈示例:Vue + Cesium + Node.js + WebSocket + MCP 教程目标:看懂并搭建一套“用户通过聊天输入指令,大模型决定调用工具,再驱动地图执行动作”的完整链路


目录

  • 1. 这篇教程要解决什么问题
  • 2. 先别写代码:先搞懂两个很像但本质不同的方案
    • 2.1 方案一:前端直连模型
    • 2.2 方案二:真正完整的 MCP
    • 2.3 它们最核心的区别
  • 3. 为什么很多人一开始会把两套方案混在一起
  • 4. 先建立整体认知:完整 MCP 里有哪些角色
  • 5. 完整 MCP 的时序图:一句“飞到上海”是怎么穿过整个系统的
  • 6. 为什么这个架构更适合地图场景
  • 7. 本教程的 demo 架构
  • 8. 实战之前,先看一遍项目职责拆分
  • 9. 实战搭建:从零把链路跑通
    • 9.1 第一步:浏览器只负责执行地图动作
    • 9.2 第二步:Node 负责 MCP Server + WebSocket 桥接
    • 9.3 第三步:Host 负责“模型 ↔ 工具”循环
    • 9.4 第四步:把“终端输入”升级成“页面输入”
  • 10. 两种页面聊天方案对比:哪种是“真 MCP”
  • 11. 一次完整调用的分层理解
    • 11.4 把读者最容易追问的几个问题串起来理解
  • 12. 新手最容易踩的坑
  • 13. 你可以如何扩展这套地图能力
  • 14. 学完这篇教程后,你应该真正记住什么

1. 这篇教程要解决什么问题

很多人第一次做“大模型驱动地图”的时候,都会有一个非常自然的想法:

我在网页上放一个聊天框,用户输入“飞到上海”,然后把这句话发给模型;模型决定调用工具;前端收到工具调用后,直接控制地图飞过去。

这个想法并不算错,而且它确实能跑。

但问题在于:这不一定是完整的 MCP 架构。

如果你后面想把地图能力做成:

  • 可以被不同宿主统一调用
  • 可以被大模型按工具方式自动发现
  • 可以在前端、桌面、服务端之间分层复用
  • 可以持续扩展成“通用地图执行器”

那你很快就会发现:

“前端直接请求模型并本地执行工具”,和 “真正完整的 MCP 链路”,其实是两套不同的设计思路。

这篇教程,就是要把这两件事讲清楚。

我们会先讲原理,再讲架构,最后用一个 Vue + Cesium + Node + MCP 的最小 demo 把整个链路跑起来。


2. 先别写代码:先搞懂两个很像但本质不同的方案

2.1 方案一:前端直连模型

这是最容易想到、也最容易快速跑通的一种方式。

它的基本流程是:

  • 用户在网页输入“飞到上海”
  • 前端把用户消息和工具定义一起发给模型
  • 模型返回:要调用 flyToShanghai
  • 前端收到 tool_calls
  • 前端本地执行 flyToShanghai
  • 前端控制 Cesium 飞到上海
  • 前端再把工具结果发回模型
  • 模型生成最终回复
  • 它的时序图长这样:

    用户
    -> 前端页面
    -> 大模型 API
    -> 前端页面(收到 tool_calls)
    -> 前端本地工具执行
    -> Cesium 地图
    -> 前端页面
    -> 大模型 API
    -> 前端页面
    -> 用户

    这个方案的优点非常明显:

    • 容易理解
    • 容易开发
    • 页面交互很直接
    • 没有额外的 Host 层

    但它也有一个根本特点:

    前端同时承担了“聊天客户端”和“工具执行器”两种角色。

    这就是后面很多结构混乱的起点。


    2.2 方案二:真正完整的 MCP

    完整 MCP 不是前端自己决定怎么调用工具,而是由一个 Host 来负责:

    • 和用户对话
    • 和模型交互
    • 把工具提供给模型
    • 在模型决定调用工具后,真正去调用 MCP Server
    • 再把结果回灌给模型

    在这个架构里,浏览器不再负责“模型调度”,而只负责“地图动作执行”。

    完整链路如下:

    用户
    -> Host
    -> 模型
    -> Host
    -> Node MCP Server
    -> 浏览器
    -> Cesium
    -> 浏览器
    -> Node MCP Server
    -> Host
    -> 模型
    -> Host
    -> 用户

    这条链路里最关键的一句是:

    模型不直接调用 Node。Host 才是真正替模型调用工具的人。

    这是理解 MCP 的核心。


    2.3 它们最核心的区别

    很多人会觉得:

    “前端直连模型”和“完整 MCP”不都是模型调用工具吗?

    表面上看都像“工具调用”,但真正的区别在于:

    维度前端直连模型完整 MCP
    谁和模型对话 前端页面 Host
    谁拿到 tool_calls 前端页面 Host
    谁真正调工具 前端页面 Host
    Node 在哪里 可以没有 是 MCP Server
    浏览器扮演什么 聊天端 + 执行端 纯执行端
    是否符合完整 MCP 分层 不一定

    最通俗的说法是:

    • 前端直连模型:页面自己又当指挥,又当工人
    • 完整 MCP:Host 当指挥,浏览器只负责干活

    3. 为什么很多人一开始会把两套方案混在一起

    因为它们在表面上太像了。

    无论是哪种方案,你都会看到类似这些词:

    • tools
    • tool_calls
    • function calling
    • flyToShanghai
    • 地图飞行

    于是就很容易误以为:

    “我已经把 tools 发给模型了,模型也返回要调用的工具了,那我就是在做 MCP。”

    实际上不一定。

    真正的问题不是“有没有工具”,而是:

    谁在承担工具调度这件事。

    如果是前端自己在做调度,那你更接近“前端直连模型 + 本地执行工具”。

    如果是 Host 在调度,Node 暴露 MCP 工具,浏览器只执行动作,那才是完整 MCP。


    4. 先建立整体认知:完整 MCP 里有哪些角色

    在地图场景里,我们可以把系统拆成四个角色。

    4.1 用户

    负责说自然语言,比如:

    • 飞到上海
    • 把镜头拉近一点
    • 在当前位置加一个标记

    用户只关心结果,不关心内部链路。

    4.2 Host

    Host 是这套系统的大脑调度层。

    它负责:

    • 接收用户输入
    • 请求大模型
    • 把工具列表告诉模型
    • 当模型决定调用工具时,真正去调用 MCP Server
    • 把工具结果再喂回模型
    • 把最终自然语言回复返回给用户

    你可以把 Host 理解成:

    “懂模型、懂工具、懂对话流程”的中控台。

    4.3 MCP Server

    MCP Server 负责把系统能力暴露成标准工具。

    比如:

    • flyToShanghai
    • flyToLocation
    • pingBrowser
    • addPoint
    • drawPolyline

    它不直接负责和用户聊天,也不负责渲染地图。

    它只负责:

    “我这里有这些工具,你要调哪个,我帮你转成真实动作。”

    4.4 浏览器 + Cesium

    浏览器里的地图页面不再和模型直接对话,而是只做一件事:

    接收动作命令,并在地图里执行。

    比如收到:

    {
    "method": "flyTo",
    "params": {
    "longitude": 121.4737,
    "latitude": 31.2304,
    "height": 8000
    }
    }

    浏览器就调用 Cesium 相机飞行。

    所以浏览器的角色是:

    地图动作执行器。


    5. 完整 MCP 的时序图:一句“飞到上海”是怎么穿过整个系统的

    下面这张图,是整篇教程最重要的一张图。

    ┌──────┐ ┌───────────────┐ ┌──────────┐ ┌──────────────┐ ┌──────────┐ ┌────────────┐ ┌─────────┐
    │ 用户 │ │ MCP Host │ │ 模型 │ │ Node MCP │ │ WebSocket │ │ 浏览器前端 │ │ Cesium │
    │ │ │ │ │ (LLM) │ │ Server │ │ 通道 │ │ + Bridge │ │ Scene │
    └─┬────┘ └──────┬────────┘ └────┬─────┘ └──────┬───────┘ └────┬─────┘ └─────┬──────┘ └────┬────┘
    │ “飞到上海” │ │ │ │ │ │
    │──────────────────>│ │ │ │ │ │
    │ │ 把用户消息发给模型 │ │ │ │ │
    │ │──────────────────>│ │ │ │ │
    │ │ │ 判断需要用工具 │ │ │ │
    │ │<──────────────────│ tool_call: │ │ │ │
    │ │ │ flyToShanghai │ │ │ │
    │ │ 调 Node MCP 工具 │ │ │ │ │
    │ │────────────────────────────────────>│ │ │ │
    │ │ │ │ sendToBrowser() │ │ │
    │ │ │ │─────────────────>│ │ │
    │ │ │ │ │ JSON-RPC 消息 │ │
    │ │ │ │ │───────────────>│ │
    │ │ │ │ │ │ bridge.execute│
    │ │ │ │ │ │──────────────>│
    │ │ │ │ │ │ 相机飞到上海 │
    │ │ │ │<─────────────────│ 执行结果 │ │
    │ │<────────────────────────────────────│ tool result │ │ │
    │ │ 再把结果发给模型 │ │ │ │ │
    │ │──────────────────>│ │ │ │ │
    │ │<──────────────────│ 返回自然语言回复 │ │ │ │
    │<──────────────────│ │ │ │ │ │

    这张图里最值得你盯住的两个点是:

    5.1 模型并没有直接连 Node

    模型只是返回:

    我建议调用 flyToShanghai

    真正去执行 callTool() 的,是 Host。

    5.2 浏览器并不参与“思考”

    浏览器只负责:

    • 收消息
    • 执行动作
    • 回结果

    它不负责选择工具,也不负责和模型多轮推理。


    6. 为什么这个架构更适合地图场景

    地图类应用和普通文本工具类应用有一个很大的区别:

    地图动作通常必须在浏览器或图形环境里执行。

    比如:

    • 相机飞行
    • 地物绘制
    • 图层显示隐藏
    • 交互式选点
    • 实时动画

    这些事情并不适合让 Node 自己去做。

    Node 很适合做:

    • 协议层
    • 工具注册
    • 连接管理
    • 请求转发
    • 结果聚合

    浏览器很适合做:

    • 渲染
    • 动画
    • 场景执行
    • 与 Cesium 交互

    所以最自然的分工就是:

    • Host:负责智能调度
    • Node MCP Server:负责能力暴露与转发
    • 浏览器:负责地图执行

    这比“前端自己包办一切”要更清晰,也更容易扩展。


    7. 本教程的 demo 架构

    我们用一套很小的 demo 来实现完整链路。

    技术角色如下:

    前端页面(Vue + Cesium)

    负责:

    • 初始化 Cesium
    • 连接 Node 发来的 WebSocket 消息
    • 收到动作后调用 MiniBridge.execute()
    • 真正控制地图飞行

    MiniBridge

    负责把通用动作转成 Cesium API。

    比如:

    • flyTo -> viewer.camera.flyTo(…)

    Node index.ts

    负责:

    • 启动 WebSocket Server
    • 启动 MCP Server
    • 注册 flyToShanghai / pingBrowser
    • 收到工具调用后把动作转发给浏览器

    Host

    最初可以是终端版 host.ts,后面再升级成页面版 host-web.ts。

    它负责:

    • 和模型对话
    • 获取 MCP 工具列表
    • 调用 MCP 工具
    • 把工具结果回灌给模型

    8. 实战之前,先看一遍项目职责拆分

    在真正开始编码之前,我们先把职责拆成三层。

    第 1 层:执行层

    执行层在浏览器里。

    它只负责:

    • 连接 WebSocket
    • 执行收到的地图命令
    • 返回结果

    第 2 层:工具层

    工具层在 Node 里。

    它只负责:

    • 注册工具
    • 维护会话
    • 把工具调用转发给浏览器

    第 3 层:智能调度层

    智能调度层在 Host 里。

    它只负责:

    • 和模型交互
    • 决定是否调用工具
    • 触发 MCP 调用
    • 收尾生成自然语言回答

    把职责拆干净以后,你会发现整个系统其实并不复杂。

    复杂感大多来自于:

    一开始把前端、模型、工具、地图执行全写在一个文件里。


    9. 实战搭建:从零把链路跑通

    下面开始进入真正的搭建过程。


    9.1 第一步:浏览器只负责执行地图动作

    这一层你可以理解成一个“地图机器人”。

    它不思考,只执行。

    一个非常典型的桥接器长这样:

    class MiniBridge {
    constructor(viewer) {
    this.viewer = viewer
    }

    async execute(cmd) {
    const action = cmd?.action
    const params = cmd?.params || {}

    switch (action) {
    case 'flyTo':
    await this.flyTo(params)
    return { success: true }
    default:
    return { success: false, error: `Unsupported action: ${action}` }
    }
    }

    flyTo(params) {
    const { longitude, latitude, height = 8000 } = params

    return new Promise((resolve) => {
    this.viewer.camera.flyTo({
    destination: Cesium.Cartesian3.fromDegrees(longitude, latitude, height),
    complete: resolve,
    })
    })
    }
    }

    这个桥的意义在于:

    • 上层不用直接知道 Cesium API
    • 上层只需要说“执行 flyTo”
    • 浏览器负责把它翻译成具体地图动作

    这一步很关键,因为它让地图执行能力变成了一个可复用的动作接口。


    9.2 第二步:Node 负责 MCP Server + WebSocket 桥接

    这一步是整个架构的中间层。

    Node 做两件事:

    9.2.1 注册 MCP 工具

    例如:

    server.tool(
    'flyToShanghai',
    'Fly camera to Shanghai in connected browser Cesium scene.',
    {
    height: z.number().default(8000),
    duration: z.number().default(2),
    },
    async ({ height = 8000, duration = 2 }) => {
    const result = await sendToBrowser('flyTo', {
    longitude: 121.4737,
    latitude: 31.2304,
    height,
    duration,
    heading: 0,
    pitch: 45,
    })

    return {
    content: [{ type: 'text', text: JSON.stringify(result ?? { success: true }) }],
    }
    },
    )

    这里看起来像是在“飞到上海”,但其实 Node 没有自己控制地图。

    它做的只是:

    • 把工具名称暴露给外界
    • 收到工具调用时,转发一个 flyTo 命令给浏览器
    9.2.2 通过 WebSocket 把动作发给浏览器

    核心逻辑是这样的:

    function sendToBrowser(method, params, timeoutMs = 15000) {
    return new Promise((resolve, reject) => {
    const ws = getBrowser(DEFAULT_SESSION)
    if (!ws || ws.readyState !== WebSocket.OPEN) {
    reject(new Error('No browser connected.'))
    return
    }

    const id = `${Date.now()}_${Math.random().toString(36).slice(2, 8)}`

    pendingRequests.set(id, { resolve, reject, timer })

    ws.send(JSON.stringify({
    jsonrpc: '2.0',
    id,
    method,
    params,
    }))
    })
    }

    它的本质是:

    把 MCP 工具调用转成浏览器可执行的动作消息。


    9.3 第三步:Host 负责“模型 ↔ 工具”循环

    这是完整 MCP 里最容易被忽略,但又最关键的一层。

    Host 的工作流程是:

  • 收到用户输入
  • 请求模型
  • 把工具列表发给模型
  • 模型返回 tool_calls
  • Host 调用 MCP Server
  • Host 拿到工具结果
  • Host 再把结果发给模型
  • 模型生成最终回复
  • 这个过程可以抽象成这样:

    const tools = await client.listTools()

    const first = await callChatCompletions(messages, openAITools)
    const toolCalls = first?.choices?.[0]?.message?.tool_calls || []

    for (const tc of toolCalls) {
    const result = await client.callTool({
    name: tc.function.name,
    arguments: JSON.parse(tc.function.arguments || '{}'),
    })

    secondMessages.push({
    role: 'tool',
    tool_call_id: tc.id,
    content: toolResultToText(result),
    })
    }

    const second = await callChatCompletions(secondMessages, openAITools)

    很多新手在这里第一次真正理解到:

    Host 是连接“模型世界”和“工具世界”的那个人。


    9.4 第四步:把“终端输入”升级成“页面输入”

    一开始,为了最小验证链路,你可以用终端版 Host:

    • 在终端输入“飞到上海”
    • Host 去请求模型
    • Host 再调用 MCP Server

    这是最容易验证完整链路的方式。

    但最终用户肯定希望在网页输入,而不是在终端输入。

    这时,正确思路不是把“前端直连模型”改回来,而是:

    给 Host 再包一层 HTTP 接口,让页面把聊天请求发给 Host。

    于是链路就变成:

    页面输入
    -> Host Web API
    -> 模型
    -> Host Web API
    -> Node MCP Server
    -> 浏览器执行地图动作
    -> Node MCP Server
    -> Host Web API
    -> 模型
    -> 页面

    这一步很重要,因为它保证了:

    • 页面输入回来了
    • 但完整 MCP 链路没有被破坏

    也就是说,页面输入 和 完整 MCP 是可以同时成立的。


    10. 两种页面聊天方案对比:哪种是“真 MCP”

    到了这里,很多人会问:

    “那页面聊天到底有几种实现方式?”

    答案是两种。

    10.1 方式 A:页面直接请求模型

    页面
    -> 模型
    -> 页面收到 tool_calls
    -> 页面本地执行工具
    -> 页面再请求模型

    这种方式好处是简单,但页面承担了太多职责。

    10.2 方式 B:页面请求 Host Web API

    页面
    -> Host Web API
    -> 模型
    -> Host Web API
    -> MCP Server
    -> 浏览器地图执行
    -> Host Web API
    -> 模型
    -> 页面

    这种方式更符合完整 MCP,因为页面没有直接参与工具调度。

    一句话判断标准

    如果页面自己在处理 tool_calls,那通常不是完整 MCP。 如果页面只是把用户输入交给 Host,然后等待回复,那更接近完整 MCP。


    11. 一次完整调用的分层理解

    当用户在页面输入“飞到上海”时,可以从三个层面来看这件事。

    11.1 语义层

    模型在理解:

    • 用户想去哪里
    • 是否需要调用工具
    • 应该调用哪个工具

    11.2 工具层

    Host 和 MCP Server 在处理:

    • 工具发现
    • 工具参数
    • 工具调用
    • 结果返回

    11.3 执行层

    浏览器和 Cesium 在处理:

    • 相机控制
    • 地图飞行
    • 动画执行
    • 场景渲染

    你把这三层分开看,就会觉得整个系统非常清晰。

    11.4 把读者最容易追问的几个问题串起来理解

    在真实学习过程中,很多人不会一下子就被“架构图”讲明白,反而会在写 demo、跑代码、看日志的时候不断冒出一些非常具体的问题。 这些问题看起来零散,但其实正好能帮助你把完整 MCP 理解得更扎实。

    下面把几个最典型的问题串起来讲。

    问题一:“大模型和 Node 这条链路到底怎么连起来的?”

    这是最常见的困惑。

    很多人第一次看到 index.ts 里的 McpServer,会本能地以为:

    模型是不是直接连到了这个 Node 服务?

    其实不是。

    更准确的链路是:

    用户 -> Host -> 模型 -> Host -> Node MCP Server -> 浏览器 -> Cesium

    也就是说:

    • 模型只负责“决定要不要调用工具”
    • Host 才是“真正去调用 MCP 工具的人”
    • Node MCP Server 只是“被调用的工具服务”
    • 浏览器只是“执行地图动作的地方”

    所以真正连模型和 Node 的,不是模型自己,而是 Host。

    问题二:“host-web.ts 里没有把工具传给 StdioClientTransport,那工具是怎么来的?”

    这也是一个特别典型的误解。

    很多新手看到这段代码时,会以为:

    const transport = new StdioClientTransport({
    command: getNpxCommand(),
    args: ['tsx', 'index.ts'],
    })

    是不是已经把工具传进去了?

    其实没有。

    这里的意思只是:

    • 用 tsx index.ts 启动一个 MCP Server 进程
    • 再让 Host 通过 stdio 和这个进程通信

    args 不是工具内容本身,它只是告诉 transport:去启动哪一个 Server。

    真正的工具读取发生在后面:

    await client.connect(transport)
    const toolsRes = await client.listTools()
    toolsCache = toolsRes.tools || []
    openAITools = toolsCache.map(mcpToolToOpenAITool)

    你可以把这几步理解成:

  • args:找到餐厅地址
  • connect:走进餐厅
  • listTools:向餐厅要菜单
  • openAITools:把菜单整理成模型能看懂的格式
  • 所以工具并不是被“静态读取源码”拿到的,而是 index.ts 运行起来以后,通过 server.tool(…) 向外暴露,再由 Host 用 listTools() 动态读取出来的。

    问题三:“后面看起来不是和前端直连一样吗?不也还是把 tools 发给模型吗?”

    这个问题问得非常好,因为它正好点出了“哪里像、哪里不一样”。

    答案是:

    在模型接口这一层,确实很像;在系统架构这一层,本质上不一样。

    两种方案后面都会做这件事:

    messages + tools -> model -> tool_calls

    所以从模型的视角看,它们很像。

    但系统架构上差别很大:

    前端直连模型
    • 工具定义在前端
    • 工具由前端发给模型
    • 模型返回 tool_calls
    • 前端本地执行工具
    完整 MCP
    • 工具定义在 MCP Server
    • Host 用 listTools() 动态发现工具
    • Host 把工具发给模型
    • 模型返回 tool_calls
    • Host 再用 callTool() 调 MCP Server
    • 浏览器只负责执行动作

    所以更准确地说:

    完整 MCP 不是“不把工具发给模型”,而是把“工具定义权”和“工具执行调度权”从前端抽离了出来。

    问题四:“既然终端里输入能飞到上海,为什么还要做页面输入?”

    这是从“验证链路”过渡到“真正产品形态”的关键一步。

    一开始用终端输入,是为了验证最小闭环:

    终端输入 -> Host -> 模型 -> Host -> MCP Server -> 浏览器 -> Cesium

    当这条线通了以后,你已经证明:

    • Host 没问题
    • MCP Server 没问题
    • 浏览器执行链没问题

    这时候再把“终端输入”换成“页面输入”,本质上不是重新发明一套逻辑,而是把 Host 的入口从命令行换成 HTTP API:

    页面输入 -> host-web.ts -> 模型 -> host-web.ts -> MCP Server -> 浏览器 -> Cesium

    所以页面输入版的核心不是“让前端重新直连模型”,而是:

    页面把用户输入交给 Host,由 Host 继续完成完整 MCP 链路。

    问题五:“我到底该怎么判断自己现在是不是在走完整 MCP?”

    这个问题非常重要,因为很多 demo 表面上看都叫“工具调用”,但架构上完全不是一回事。

    最实用的判断标准只有一句:

    看工具定义写在哪里,工具调度由谁负责。

    如果是这样:

    • 前端自己写 getTools()
    • 前端自己发给模型
    • 前端自己执行 runLocalTool()

    那本质上还是前端直连。

    如果是这样:

    • index.ts 里 server.tool(…) 定义工具
    • Host 通过 listTools() 发现工具
    • Host 通过 callTool() 调用工具
    • 浏览器只负责执行动作

    那才是完整 MCP。

    你可以把这个判断标准记成一句话:

    前端直连看的是“页面会不会调工具”,完整 MCP 看的是“工具是不是独立存在于 MCP Server 里”。

    问题六:“为什么我一开始总觉得两套方案混在一起?”

    因为在学习初期,大家最先看到的都是这些显眼的词:

    • tools
    • tool_calls
    • flyToShanghai
    • bridge.execute
    • WebSocket

    这些词在两套架构里都出现,所以很容易产生一种错觉:

    “我都在用 tools 了,那我就是在做 MCP。”

    真正需要区分的,其实不是关键词,而是角色分工:

    • 谁是 Host
    • 谁是 MCP Server
    • 谁是浏览器执行器
    • 谁才是真正的工具源头

    一旦你把角色看清楚,之前那些零散的疑问就会突然全部串起来。


    你会发现,上面这些问题并不是无关的“零碎提问”,而是学习过程中非常自然的一条理解升级路径:

  • 先困惑模型和 Node 的关系
  • 再困惑工具是怎么被发现的
  • 再进一步意识到“为什么看起来和前端直连很像”
  • 最后才真正明白:完整 MCP 的价值,不在“有没有 tools”,而在工具定义、工具调度和动作执行被拆成了独立角色

  • 12. 新手最容易踩的坑

    12.1 把“tool calling”误以为就是 MCP

    不是的。

    tool calling 是模型返回工具调用决策。 MCP 是一整套 client-server 协议和角色分层。

    12.2 让浏览器既当聊天端又当执行端

    短期能跑,长期一定会乱。

    因为你会发现:

    • 页面越来越重
    • 工具扩展越来越难
    • 复用性越来越差

    12.3 误以为模型直接调用 Node

    模型不会自己去连 Node。

    真正调用 Node MCP 工具的是 Host。

    12.4 忘了浏览器必须先连上 WebSocket

    如果浏览器没有连上,Node 收到工具调用也没法执行地图动作。

    12.5 同时起了两个 Server,导致端口冲突

    比如 9100 已经被占用,再起一个同样监听 9100 的进程,就会报端口占用错误。


    13. 你可以如何扩展这套地图能力

    当“飞到上海”跑通以后,这套架构就已经具有扩展性了。

    你可以继续加这些工具:

    13.1 通用飞行类

    • flyToLocation({ longitude, latitude, height })
    • setCameraView(…)
    • lookAt(…)

    13.2 地图绘制类

    • addPoint(…)
    • addPolyline(…)
    • addPolygon(…)

    13.3 图层控制类

    • showLayer(…)
    • hideLayer(…)
    • toggleLayer(…)

    13.4 场景查询类

    • getCurrentCamera()
    • getSelectedEntity()
    • pingBrowser()

    13.5 复杂业务类

    • 无人机巡航
    • 路线规划
    • 智慧城市场景切换
    • 事件定位与高亮

    这时候你会真正体会到完整 MCP 架构的价值:

    你扩展的是“工具能力”,而不是把业务越写越塞进页面里。


    14. 学完这篇教程后,你应该真正记住什么

    如果你只记住一句话,请记这句:

    完整 MCP 不是“模型自己调地图”,而是“Host 根据模型决策去调工具,再让浏览器执行地图动作”。

    如果你再多记三句,那就是:

  • 前端直连模型 能跑,但不等于完整 MCP
  • Host 是“模型和工具之间的真正调度者”
  • 浏览器 在地图场景里最适合做执行器,而不是全能中枢
  • 最后,把两套方案再浓缩成最简版本:

    前端直连模型

    页面自己又当聊天端,又当工具执行端

    完整 MCP

    Host 负责调度,Node 负责工具,浏览器负责执行

    这就是这篇教程想真正教会你的东西。


    结语

    从“让地图飞到上海”这件小事出发,你其实已经接触到了一个很有代表性的工程问题:

    当大模型开始接管工具调用时,系统应该怎么分层,才不会越做越乱?

    地图场景给了我们一个很典型的答案:

    • 把思考留给模型
    • 把调度交给 Host
    • 把能力暴露给 MCP Server
    • 把渲染执行留给浏览器

    这样搭起来的系统,才真正适合继续长大。

    如果你已经把“飞到上海”跑通了,那么下一步,不是继续把代码堆在页面里,而是:

    把更多地图能力,整理成一套干净的 MCP 工具体系。

    这时,你就真正迈进了“通过大模型聊天驱动地图系统”的工程化阶段。

    赞(0)
    未经允许不得转载:171主机测评 » 前端直连模型 vs 完整 MCP:大模型驱动地图的原理与实践(技术栈Vue + Cesium + Node.js + WebSocket + MCP)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址