跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
JavaScriptNode.jsAI大前端

大模型驱动地图实战:前端直连与完整 MCP 架构对比

综述由AI生成对比了大模型驱动地图的两种方案:前端直连模型与完整 MCP 架构。详细解析了 Host、MCP Server 及浏览器的角色分工,通过 Vue、Cesium、Node.js 和 WebSocket 搭建最小化 Demo,演示了从用户输入到地图动作执行的完整链路。重点阐述了为何完整 MCP 更适合扩展与复用,并提供了新手避坑指南与能力扩展建议。

性能调优发布于 2026/4/6更新于 2026/5/2428 浏览

在这里插入图片描述


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

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

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

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

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

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

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

那你很快就会发现:

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

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

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


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

2.1 方案一:前端直连模型

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

它的基本流程是:

  1. 用户在网页输入'飞到上海'
  2. 前端把用户消息和工具定义一起发给模型
  3. 模型返回:要调用 flyToShanghai
  4. 前端收到 tool_calls
  5. 前端本地执行 flyToShanghai
  6. 前端控制 Cesium 飞到上海
  7. 前端再把工具结果发回模型
  8. 模型生成最终回复

它的时序图长这样:

用户 -> 前端页面 -> 大模型 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 的工作流程是:

  1. 收到用户输入
  2. 请求模型
  3. 把工具列表发给模型
  4. 模型返回 tool_calls
  5. Host 调用 MCP Server
  6. Host 拿到工具结果
  7. Host 再把结果发给模型
  8. 模型生成最终回复

这个过程可以抽象成这样:

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);

你可以把这几步理解成:

  1. args:找到餐厅地址
  2. connect:走进餐厅
  3. listTools:向餐厅要菜单
  4. 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
  • 谁是浏览器执行器
  • 谁才是真正的工具源头

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


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

  1. 先困惑模型和 Node 的关系
  2. 再困惑工具是怎么被发现的
  3. 再进一步意识到'为什么看起来和前端直连很像'
  4. 最后才真正明白:完整 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 根据模型决策去调工具,再让浏览器执行地图动作'。

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

  1. 前端直连模型 能跑,但不等于完整 MCP
  2. Host 是'模型和工具之间的真正调度者'
  3. 浏览器 在地图场景里最适合做执行器,而不是全能中枢

最后,把两套方案再浓缩成最简版本:

前端直连模型
页面自己又当聊天端,又当工具执行端 
完整 MCP
Host 负责调度,Node 负责工具,浏览器负责执行 

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


结语

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

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

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

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

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

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

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

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

目录

  1. 1. 这篇教程要解决什么问题
  2. 2. 先别写代码:先搞懂两个很像但本质不同的方案
  3. 2.1 方案一:前端直连模型
  4. 2.2 方案二:真正完整的 MCP
  5. 2.3 它们最核心的区别
  6. 3. 为什么很多人一开始会把两套方案混在一起
  7. 4. 先建立整体认知:完整 MCP 里有哪些角色
  8. 4.1 用户
  9. 4.2 Host
  10. 4.3 MCP Server
  11. 4.4 浏览器 + Cesium
  12. 5. 完整 MCP 的时序图:一句“飞到上海”是怎么穿过整个系统的
  13. 5.1 模型并没有直接连 Node
  14. 5.2 浏览器并不参与“思考”
  15. 6. 为什么这个架构更适合地图场景
  16. 7. 本教程的 demo 架构
  17. 前端页面(Vue + Cesium)
  18. MiniBridge
  19. Node index.ts
  20. Host
  21. 8. 实战之前,先看一遍项目职责拆分
  22. 第 1 层:执行层
  23. 第 2 层:工具层
  24. 第 3 层:智能调度层
  25. 9. 实战搭建:从零把链路跑通
  26. 9.1 第一步:浏览器只负责执行地图动作
  27. 9.2 第二步:Node 负责 MCP Server + WebSocket 桥接
  28. 9.2.1 注册 MCP 工具
  29. 9.2.2 通过 WebSocket 把动作发给浏览器
  30. 9.3 第三步:Host 负责“模型 ↔ 工具”循环
  31. 9.4 第四步:把“终端输入”升级成“页面输入”
  32. 10. 两种页面聊天方案对比:哪种是“真 MCP”
  33. 10.1 方式 A:页面直接请求模型
  34. 10.2 方式 B:页面请求 Host Web API
  35. 一句话判断标准
  36. 11. 一次完整调用的分层理解
  37. 11.1 语义层
  38. 11.2 工具层
  39. 11.3 执行层
  40. 11.4 把读者最容易追问的几个问题串起来理解
  41. 问题一:“大模型和 Node 这条链路到底怎么连起来的?”
  42. 问题二:“host-web.ts 里没有把工具传给 StdioClientTransport,那工具是怎么来的?”
  43. 问题三:“后面看起来不是和前端直连一样吗?不也还是把 tools 发给模型吗?”
  44. 前端直连模型
  45. 完整 MCP
  46. 问题四:“既然终端里输入能飞到上海,为什么还要做页面输入?”
  47. 问题五:“我到底该怎么判断自己现在是不是在走完整 MCP?”
  48. 问题六:“为什么我一开始总觉得两套方案混在一起?”
  49. 12. 新手最容易踩的坑
  50. 12.1 把“tool calling”误以为就是 MCP
  51. 12.2 让浏览器既当聊天端又当执行端
  52. 12.3 误以为模型直接调用 Node
  53. 12.4 忘了浏览器必须先连上 WebSocket
  54. 12.5 同时起了两个 Server,导致端口冲突
  55. 13. 你可以如何扩展这套地图能力
  56. 13.1 通用飞行类
  57. 13.2 地图绘制类
  58. 13.3 图层控制类
  59. 13.4 场景查询类
  60. 13.5 复杂业务类
  61. 14. 学完这篇教程后,你应该真正记住什么
  62. 前端直连模型
  63. 完整 MCP
  64. 结语
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 大模型工具函数调用(Function Calling)实战指南
  • Java 参数传递机制详解:值传递与引用传递的区别
  • Neo4j Desktop 2 安装与使用指南
  • DeepSeek-OCR-WEBUI 实战:从部署到网页调用的全流程自动化文档处理
  • AI 产品架构设计:从 0 到 1 搭建信息架构与核心业务流程
  • 哈希表进阶:哈希桶封装 unordered_set 和 unordered_map 与迭代器详解
  • Nginx-1.28.0 Windows 版安装包及核心功能说明
  • 哈希表进阶:用哈希桶封装 unordered_set 和 unordered_map 及迭代器实现
  • MySQL 数据类型详解
  • FastAPI:Python 高性能 Web 框架实战指南
  • 数据库迁移 TCO 分析:MySQL 替代隐性成本与工具链实测
  • MySQL 迁移 TCO 全景账本:隐性成本与工程化工具链实测
  • C# OpenVINO Sharp 使用 Anomalib PatchCore 进行缺陷检测
  • Flutter 三方库 algolia_client_recommend 鸿蒙适配指南
  • 链表经典题目实战解析:LeetCode Hot 100 高频题解
  • 数据库迁移 TCO 全景账本:MySQL 替代隐性成本与工具链实战
  • DeepSeek-R1-Distill-Llama-8B 模型安全与对抗攻击防护
  • ChatGPT 结构化 Prompt 高级应用
  • ASP.NET Core Razor Pages 从零搭建入门指南
  • 基于 Python 的单脉冲雷达导引头回波生成技术

相关免费在线工具

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • 随机西班牙地址生成器

    随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online