阅读视图

发现新文章,点击刷新页面。

上班摸鱼看掘金,老板突然出现在身后...

那是一个平静的下午。

我正在掘金上摸鱼写文章,代码编辑器在另一个屏幕上装模作样地躺着。

突然,一个熟悉的声音从身后传来:

"小明,在干嘛呢?"

心跳瞬间飙到 180,肾上腺素狂飙。我的手指以肌肉记忆般的速度按下了 Alt+Q

0.1 秒后——

屏幕上的掘金文章瞬间蒸发,取而代之的是一个朴实无华的百度首页。

我淡定转身,面不改色: "老板,正准备查个技术问题!"

老板满意地点点头,拍了拍我的肩膀:"不错,要多钻研。" 然后转身离开。

我长舒一口气,心率逐渐平复。再次按下 Alt+Q——掘金文章完美归位。

这不是科幻片,也不是魔术。

这是我上周刚撸出来的 浏览器伪装插件 —— 一个真正的"职场求生神器"。

今天,我就把这个插件制作过程,毫无保留地分享给你。

先看效果:按下 Alt+Q显示百度界面, 再次按下 Alt+Q回到原来页面

摸鱼插件效果.gif

需求分析

核心功能

  • 一键切换:按快捷键(Alt+Q)0.1秒瞬间切换
  • 完美伪装:标题、图标、页面内容三位一体
  • 无缝恢复:再按一次,一切如初
  • 兼容性强:支持99%的网站(包括掘金、知乎、B站...)

立即使用

5分钟搞定安装:复制代码 → 创建文件 → 加载扩展 → 开始使用!

📦 获取完整代码 👉 GitHub: https://github.com/Teernage/disguise-extension/tree/main 如果对你有帮助,欢迎 Star ⭐ 支持!

实现过程

第一步:创建插件结构

disguise-extension/
├── manifest.json      # 插件配置文件
├── background.js      # 后台脚本
├── disguise.js        # 核心逻辑
└── rules.json         # 网络请求规则

第二步:配置 manifest.json

{
  "manifest_version": 3,
  "name": "网站伪装器",
  "version": "1.0",
  "permissions": ["activeTab", "scripting", "declarativeNetRequest"],
  "host_permissions": ["<all_urls>"],
  "background": {
    "service_worker": "background.js"
  },
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["disguise.js"]
    }
  ],
  "declarative_net_request": {
    "rule_resources": [
      {
        "id": "remove_frame_headers",
        "enabled": true,
        "path": "rules.json"
      }
    ]
  },
  "commands": {
    "toggle": {
      "suggested_key": { "default": "Alt+Q" },
      "description": "切换伪装"
    }
  }
}

关键配置说明:

  • permissions:申请必要权限
  • content_scripts:在所有网页注入脚本
  • declarativeNetRequest:修改 HTTP 响应头
  • commands:注册快捷键

第三步:处理快捷键(background.js)

// 监听快捷键
chrome.commands.onCommand.addListener(async (command) => {
  if (command === 'toggle') {
    const [tab] = await chrome.tabs.query({
      active: true,
      currentWindow: true,
    });
    chrome.tabs.sendMessage(tab.id, { action: 'toggle' });
  }
});

工作流程:

用户按 Alt+Q
    ↓
background.js 监听到快捷键
    ↓
发送消息到当前标签页
    ↓
disguise.js 接收消息并执行切换

第四步:核心伪装逻辑(disguise.js)

const config = {
  url: 'https://www.baidu.com/',
  title: '百度一下',
};

let isDisguised = false;
let originalTitle = document.title;
let originalIcon = null;

// 接收快捷键消息
chrome.runtime.onMessage.addListener((msg) => {
  if (msg.action === 'toggle') {
    toggle();
  }
});

function toggle() {
  isDisguised = !isDisguised;
  let iframe = document.getElementById('work-iframe');

  if (isDisguised) {
    // 保存原始图标
    const iconLink = document.querySelector('link[rel*="icon"]');
    if (iconLink) originalIcon = iconLink.href;

    // 修改标题和图标
    document.title = config.title;
    changeFavicon(`${config.url}/favicon.ico`);

    // 创建或显示 iframe
    if (!iframe) {
      iframe = document.createElement('iframe');
      iframe.id = 'work-iframe';
      iframe.src = config.url;

      // 设置iframe样式
      Object.assign(iframe.style, {
        position: 'fixed',
        top: '0',
        left: '0',
        width: '100vw',
        height: '100vh',
        zIndex: '2147483647',
        border: 'none',
        background: 'white',
      });

      // 添加加载错误处理
      iframe.onerror = () => {
        console.warn('iframe 加载失败,可能被跨域阻止');
        showFallbackMessage(iframe);
      };

      document.body.appendChild(iframe);
    }
    iframe.style.display = 'block';
  } else if (iframe) {
    // 恢复原始标题和图标
    document.title = originalTitle;
    if (originalIcon) {
      changeFavicon(originalIcon);
    } else {
      // 如果没有原始图标,移除当前图标
      const currentIcon = document.querySelector('link[rel*="icon"]');
      if (currentIcon) currentIcon.remove();
    }

    iframe.style.display = 'none';
  }
}

function changeFavicon(iconUrl) {
  // 移除所有现有的图标链接
  const existingIcons = document.querySelectorAll('link[rel*="icon"]');
  existingIcons.forEach((icon) => icon.remove());

  // 创建新的图标链接
  const link = document.createElement('link');
  link.rel = 'icon';
  link.type = 'image/x-icon';
  link.href = iconUrl;
  document.head.appendChild(link);
}

// 当 iframe 被阻止时显示 404 页面
function showFallbackMessage(iframe) {
  const fallback = document.createElement('div');
  fallback.id = 'fallback-message';
  fallback.innerHTML = `
    <div style="
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      height: 100vh;
      background: #f5f5f5;
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;
      margin: 0;
      color: #333;
    ">
      <div style="text-align: center; max-width: 600px; padding: 40px;">
        <h1 style="
          font-size: 120px;
          margin: 0;
          color: #ddd;
          font-weight: 700;
        ">404</h1>
        
        <h2 style="
          font-size: 24px;
          margin: 20px 0;
          color: #666;
          font-weight: 400;
        ">页面未找到</h2>
        
        <p style="
          font-size: 16px;
          color: #999;
          line-height: 1.6;
          margin: 20px 0;
        ">
          抱歉,您访问的页面不存在或已被删除。
        </p>
        
        <div style="margin-top: 30px;">
          <a href="${config.url}" style="
            display: inline-block;
            padding: 12px 30px;
            background: #1a73e8;
            color: white;
            text-decoration: none;
            border-radius: 4px;
            font-size: 14px;
            transition: background 0.3s;
          " onmouseover="this.style.background='#1557b0'" 
             onmouseout="this.style.background='#1a73e8'">
            返回首页
          </a>
        </div>
      </div>
    </div>
  `;

  iframe.style.display = 'none';
  document.body.appendChild(fallback);
}

第五步rules.json

很多网站(如百度)设置了 X-Frame-Options 响应头,禁止被 iframe 嵌入。

我们需要通过 declarativeNetRequest 移除这些限制:

[
  {
    "id": 1,
    "priority": 1,
    "action": {
      "type": "modifyHeaders",
      "responseHeaders": [
        {
          "header": "X-Frame-Options",
          "operation": "remove"
        },
        {
          "header": "Content-Security-Policy",
          "operation": "remove"
        }
      ]
    },
    "condition": {
      "urlFilter": "*",
      "resourceTypes": ["sub_frame"]
    }
  }
]

作用:

  • 移除 X-Frame-Options 响应头
  • 移除 Content-Security-Policy 响应头
  • 允许任何网站被 iframe 嵌入

技术细节

1. 为什么用 iframe?

方案对比:

方案 优点 缺点
修改 DOM 简单 无法完美还原复杂网站
截图替换 真实 无法交互
iframe 嵌入 完美伪装 + 可交互 可能被跨域阻止

最终选择: iframe + 跨域绕过

2. 如何处理跨域限制?

问题:

很多网站设置了 X-Frame-Options: DENY,禁止被 iframe 嵌入。

解决方案:

使用 Chrome Extension 的 declarativeNetRequest API,在响应到达浏览器前移除这些响应头。

{

"action": {

        "type": "modifyHeaders",

        "responseHeaders": [ { "header": "X-Frame-Options", "operation": "remove" }]

        }

}

原理:

服务器返回响应
    ↓
X-Frame-Options: DENY
    ↓
插件拦截并移除响应头
    ↓
浏览器接收到无限制的响应
    ↓
iframe 成功加载 ✅

安装使用

安装:开发者模式加载

  1. 打开 Chrome 浏览器
  2. 访问 chrome://extensions/
  3. 开启「开发者模式」
  4. 点击「加载已解压的扩展程序」
  5. 选择disguise-extension文件夹

安装摸鱼插件.gif

用法

  1. 访问任意网站(如掘金)
  2. 按 Alt+Q
  3. 页面瞬间变成百度首页
  4. 再按 Alt+Q 恢复

自定义伪装网站

修改 disguise.js 中的配置:

const config = {
  url: 'https://www.baidu.com/',     // 伪装的网站
  title: '百度一下',                  // 标签页标题
};

重要提醒: 此插件仅供学习交流,请勿在工作时间摸鱼!🤣

如果觉得对您有帮助,欢迎点赞 👍 收藏 ⭐ 关注 🔔 支持一下!

女朋友被链接折磨疯了,我写了个工具一键解救

有一天女朋友跟我抱怨:工作里被各种链接折腾得头大,飞书和浏览器之间来回切窗口,一会忘了看哪个,心情都被搅乱了。我回头一想——我也一样,办公室每个人都被链接淹没。

同事丢来的需求文档、群里转的会议记录、GitLab 的 MR 链接、还有那些永远刷不完的通知——每点一个链接就得在聊天工具和浏览器之间跳转,回来后一秒钟就忘了"本来要点哪个、看哪个"。更别提那些收集了一堆好文章想集中看,或者别人发来一串链接让你"挑哪个好"的时候,光是打开就要折腾半天。

"

这不是注意力不集中,是工具没有帮你省掉这些无意义的切换。

"

于是我做了一个极简 Chrome 插件: Open‑All 。它只做一件事——把你所有网址一次性在新窗口打开。你复制粘贴一次,它把链接都整齐地摆在新标签页里,你只要从左到右按顺序看就行。简单、直接,让你把注意力放在真正重要的事情上

先看效果:一键打开多个链接

批量打开所有url.gif

这些痛点你肯定也遇到过

每天都在经历的折磨

  • 浏览器和飞书、企微、钉钉来回切应用 :复制链接、粘贴、点开、切回来,这套动作做一遍就够烦的了
  • 容易忘事 :打开到第几个链接了?这个看过没?脑子根本记不住
  • 启动成本高 :一想到链接要一个个点开,就懒得开始了
  • 没法对比 :想要横向比较几个方案,但打开方案链接都费劲

具体什么时候最痛苦

  1. 收集的文章想一口气看完 :平时存了一堆好文章,周末想集中看,结果光打开就累了
  2. 别人让你帮忙选 :同事发来几个方案链接问你觉得哪个好,你得全部打开才能比较
  3. 代码 Review :GitLab 上好几个 MR 要看,还有相关的 Issue 和 CI 结果
  4. 开会前准备 :会议文档、背景资料、相关链接,都得提前打开看看

我的解决方案

设计思路很简单

  • 就解决一个问题 :批量打开链接,不搞那些花里胡哨的功能
  • 零学习成本 :会复制粘贴就会用
  • 让你专注 :少折腾,多干活

能干什么

  • 把一堆链接一次性在新窗口打开
  • 自动保存你输入的内容,不怕误关
  • 界面超简单,点两下就搞定

技术实现

项目结构

shiba-cursor
├── manifest.json      # 扩展的"身份证"
├── popup.html         # 弹窗样式
└── popup.js          # 弹窗交互

文件说明:

  • manifest.json:扩展身份信息
  • popup.html:弹窗样式
  • popup.js:弹窗交互

🚀 浏览项目的完整代码可以点击这里 github.com/Teernage/op…,如果对你有帮助欢迎Star。

动手实现

第一步:创建项目文件

  1. 创建文件夹 open-all

  2. 创建manifest.json文件

{
  "manifest_version": 3,
  "name": "批量打开URL",
  "version": "1.0",
  "description": "输入多个URL,一键在新窗口中打开",
  "permissions": [
    "tabs",
    "storage"
  ],
  "action": {
    "default_popup": "popup.html",
    "default_title": "批量打开URL"
  }
}
  1. 创建popup.html文件

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }

      body {
        width: 320px;
        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
          sans-serif;
        color: #333;
      }

      .container {
        background: rgba(255, 255, 255, 0.95);
        padding: 20px;
        box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
        backdrop-filter: blur(10px);
        border: 1px solid rgba(255, 255, 255, 0.2);
      }

      .title {
        font-size: 18px;
        font-weight: 600;
        text-align: center;
        margin-bottom: 16px;
        color: #1d1d1f;
        letter-spacing: -0.5px;
      }

      #urlInput {
        width: 100%;
        height: 140px;
        padding: 12px;
        border: 2px solid #e5e5e7;
        border-radius: 12px;
        font-size: 14px;
        font-family: 'SF Mono', Monaco, monospace;
        resize: none;
        background: #fafafa;
        transition: all 0.2s ease;
        line-height: 1.4;
      }

      #urlInput:focus {
        outline: none;
        border-color: #007aff;
        background: #fff;
        box-shadow: 0 0 0 4px rgba(0, 122, 255, 0.1);
      }

      #urlInput::placeholder {
        color: #8e8e93;
        font-size: 13px;
      }

      .button-group {
        display: flex;
        gap: 8px;
        margin-top: 16px;
      }

      button {
        flex: 1;
        padding: 12px 16px;
        border: none;
        border-radius: 10px;
        font-size: 14px;
        font-weight: 500;
        cursor: pointer;
        transition: all 0.2s ease;
        font-family: inherit;
      }

      #openBtn {
        background: linear-gradient(135deg, #007aff 0%, #0051d5 100%);
        color: white;
        box-shadow: 0 2px 8px rgba(0, 122, 255, 0.3);
      }

      #openBtn:hover {
        transform: translateY(-1px);
        box-shadow: 0 4px 12px rgba(0, 122, 255, 0.4);
      }

      #openBtn:active {
        transform: translateY(0);
      }

      #clearBtn {
        background: #f2f2f7;
        color: #8e8e93;
        border: 1px solid #e5e5e7;
      }

      #clearBtn:hover {
        background: #e5e5ea;
        color: #636366;
      }

      #status {
        margin-top: 12px;
        padding: 8px 12px;
        border-radius: 8px;
        font-size: 12px;
        text-align: center;
        display: none;
        background: rgba(52, 199, 89, 0.1);
        color: #30d158;
        border: 1px solid rgba(52, 199, 89, 0.2);
      }

      .tip {
        font-size: 11px;
        color: #8e8e93;
        text-align: center;
        margin-top: 8px;
        line-height: 1.3;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="title">批量打开 URL</div>

      <textarea
        id="urlInput"
        placeholder="输入 URL,每行一个:

https://www.apple.com
https://www.github.com
https://www.google.com"
      ></textarea>

      <div class="button-group">
        <button id="clearBtn">清空</button>
        <button id="openBtn">打开</button>
      </div>

      <div class="tip">输入会自动保存,打开后自动清空</div>

      <div id="status"></div>
    </div>

    <script src="popup.js"></script>
  </body>
</html>

  1. 创建popup.js文件

document.addEventListener('DOMContentLoaded', function() {
  const urlInput = document.getElementById('urlInput');
  const openBtn = document.getElementById('openBtn');
  const clearBtn = document.getElementById('clearBtn');
  const status = document.getElementById('status');

  // 恢复上次保存的输入
  chrome.storage.local.get(['savedUrls'], function(result) {
    if (result.savedUrls) {
      urlInput.value = result.savedUrls;
    }
  });

  // 自动保存输入内容
  urlInput.addEventListener('input', function() {
    chrome.storage.local.set({savedUrls: urlInput.value});
  });

  // 清空按钮
  clearBtn.addEventListener('click', function() {
    urlInput.value = '';
    chrome.storage.local.remove(['savedUrls']);
    showStatus('已清空');
  });

  // 打开URL按钮
  openBtn.addEventListener('click', function() {
    const urls = getUrls(urlInput.value);
    
    if (urls.length === 0) {
      showStatus('请输入有效的URL');
      return;
    }

    // 创建新窗口并打开所有URL
    chrome.windows.create({url: urls[0]}, function(window) {
      for (let i = 1; i < urls.length; i++) {
        chrome.tabs.create({
          windowId: window.id,
          url: urls[i],
          active: false
        });
      }
      
      // 成功打开后清空输入并移除存储
      urlInput.value = '';
      chrome.storage.local.remove(['savedUrls']);
      showStatus(`已打开 ${urls.length} 个URL`);
    });
  });

  // 解析URL
  function getUrls(input) {
    return input.split('\n')
      .map(line => line.trim())
      .filter(line => line && (line.startsWith('http://') || line.startsWith('https://')));
  }

  // 显示状态
  function showStatus(message) {
    status.textContent = message;
    status.style.display = 'block';
    setTimeout(() => {
      status.style.display = 'none';
    }, 2000);
  }
});

第二步:安装扩展

安装open all使用.gif

  1. 打开Chrome浏览器
  2. 地址栏输入:chrome://extensions/
  3. 打开右上角"开发者模式"
  4. 点击"加载已解压的扩展程序"
  5. 选择刚才的文件夹,然后确定
  6. 固定扩展
  7. 点击扩展图标即可使用

最后想说的

这个插件功能很简单,但解决的是我们每天都会遇到的真实问题。它不会让你的工作效率翻倍,但能让你少一些无聊的重复操作,多一些专注的时间。

我和女朋友现在用着都挺爽的,希望也能帮到你。如果你也有类似的困扰,试试看吧,有什么想法也欢迎在评论区聊聊。

你最希望下个版本加什么功能?评论区告诉我!

如果觉得对您有帮助,欢迎点赞 👍 收藏 ⭐ 关注 🔔 支持一下! 往期实战推荐:

老板问我:AI真能一键画广州旅游路线图?我用 MCP 现场开图

老板那天凑过来:“听说AI能一键画旅游地图?真的假的?”

我笑了:“来,给您现场演示一下。”

打开电脑,三下五除二配置好环境。在对话框里输入:“生成广州旅游路线地图,要能交互的。”

3秒后,一个精美地图跃然屏上——广州塔、沙面、陈家祠等清晰标注。

老板瞪大眼睛:“这就完了?太神奇了吧!”

“这就是MCP的魔力,让AI从聊天工具变成生产力神器。”

他摸着下巴:“看来我们得抓紧用起来了。”

想知道怎么实现?本文将从零开始,教你实现这个"魔法"

效果预览:

生成可交互地图的效果图.gif

MCP简要介绍

MCP(Model Context Protocol)就是能够让 AI 大模型更好地使用各类工具的一个协议。

AI 模型只是一个大脑,而 MCP 协议就是让模型加上手脚,可以帮你干更多的事情,比如:

  • 读取、修改你的本地文件
  • 使用浏览器上网查询信息
  • 查询实时交通路况
  • 生成各种图表、地图路线

总之,MCP 能干的事情可太多了!要知道,大模型本身其实只会问答,它自己并不会使用外部工具,而 MCP 的出现就等于是让大模型拥有了使用各种外部工具的能力。

不过要想使用 MCP,你还得用到一个东西叫做 MCP Host 。

MCP Host

MCP Host 就是一个支持 MCP 协议的软件环境,能"跑"AI 模型,并且让 AI 模型能用各种外部工具。

常见 MCP Host:

  • Claude Desktop
  • Cursor
  • Trae
  • Cline (我们今天要使用的例子)

我们今天使用 Cline 为例来讲讲 MCP 的使用方法。

安装Mcp host (Client)

cline是vscode的一个插件,首先我们要下载vscode编辑器,然后在插件商店搜索cline并安装,安装好了之后侧边栏就会出现一个cline图标,点一下就进入使用cline的地方。

配置Cline用的API key

紧接着,我们需要配置ai模型,cline支持接入不同模型的api,如cluade、gpt、deepseek等模型,我们这里演示使用deepseek模型进行演示。

deepseek的官方网站就有提供api,我们可以到deepseek官方网站注册登录,并充值获取api。

创建好key之后,将key给cline,填好之后,cline会引导我们来到聊天页面,我们随便问它一个问题,给他打个招呼,看他能不能够正常回复,能正常回复就说明接入deepseek模型成功了

概念解释:MCP Server 和 Tool

MCP Server

MCP Server 即 MCP 服务器,跟我们传统意义上的 Server 并没有什么太大的关系,它就是一个程序而已,只不过这个程序的执行是符合 MCP 协议的。

大部分的 MCP 服务器都是本地通过 Node 或者是 Python 启动的,只不过在使用的过程中可能会联网,当然它也可能不联网,纯本地使用也是可以的。不管是联不联网,它都可以叫做 MCP Server,本质就是给 MCP 客户端即 AI 模型提供服务的。

Tool

所以 MCP Server 本质就是一个程序,就像手机上的应用,这些应用都内置了一些功能模块,而 Tool 就是 MCP Server 程序中的一些工具函数。

可以把 MCP Server 理解为一个计算器应用,这个计算器有计算和换算两个功能,作为用户可以根据自己需求选择计算还是换算功能,而这两个功能就是两个Tool。

比如我们要让 DeepSeek 生成一个可交互的广州旅游路线地图,DeepSeek 是没办法完成的,但是我们可以安装一个处理生成图表的 MCP Server,它内部包含一个函数 generate_path_mapTool,这个功能是传入地点、图的大小就可以返回路线地图。

所以我们要一个广州旅游路线地图的话,就得让cline安装处理生成图表的MCP Server,然后deepseek把地点、图的大小这些参数传给MCP Server的generate_path_map就可以拿到一个可交互的广州旅游路线地图了。

配置MCP Server

前面解释了MCP Server和Tool的概念,我们再回到cline这里继续实操。

首先我们打开进入cline,进入MCP Server 设置页面,点击“已安装”,再点击“配置MCP服务器”,之后cline就会跟我们打开一个cline_mcp_settings.json文件。如果我们想新增一个MCPServer的话,我们只需要在里面填入对应的启动命令就行了。

如下操作MCPServer配置.gif

使用他人制作的MCP Server

接下来我们来安装一个别人写好的MCP Server,我们打开mcpmarket.cn/ ,这是一个MCP Server的市场,就跟我们手机的应用市场有点像,这里面有很多别人写好的MCP Server,我们去找生成图表的MCP ,复制配置就可以生效了

生成图表的MCP Serve工具链接: mcpmarket.cn/server/680e…

跟着以下的操作图进行操作使用他人制作的MCP Server.gif

按照网站上的说明,将配置添加到 cline_mcp_settings.json 文件中

window用户

{
  "mcpServers": {
    "mcp-server-chart": {
      "command": "cmd",
      "args": ["/c", "npx", "-y", "@antv/mcp-server-chart"]
    }
  }
}

mac用户

{
  "mcpServers": {
    "mcp-server-chart": {
      "command": "npx",
      "args": ["-y", "@antv/mcp-server-chart"]
    }
  }
}

注意:电脑要装Node.js环境

没有的话要自行安装哦: nodejs.org/en/download…

实战演示

配置完成后,你就可以在 Cline 中输入:

"生成一个广州的旅游路线地图"

DeepSeek 会自动调用 MCP Server 的相关工具,为你生成一个精美的交互式地图!

生成可交互地图的效果图.gif

MCP交互流程详解

sequenceDiagram
    participant 用户
    participant Cline
    participant deepseek
    participant MCP as MCP Server
    
    用户->>Cline: 生成广州旅游路线地图
    Cline->>deepseek: 用户请求 + 可用工具列表
    deepseek->>Cline: 调用generate_interactive_map工具
    Cline->>MCP: generate_interactive_map(广州, 景点列表)
    MCP->>MCP: 生成交互式地图
    MCP->>Cline: 返回地图
    Cline->>deepseek: 工具执行结果
    deepseek->>Cline: 整理回复和说明
    Cline->>用户: 显示地图和旅游建议
  1. 用户 -> Cline: “帮我生成一个广州的旅游路线地图,要可交互的哦!”
  2. Cline -> deepseek模型::cline把用户的请求和可用的mcp-server-chart工具信息一起交给模型deepseek来想办法
  3. deepseek模型 -> Cline:deepseek模型看到请求和工具后,就想:这个任务可以用mcp-server-chart工具的generate_interactive_map功能,需要指定地点、景点和样式。于是它告诉Cline:“你去调用generate_interactive_map工具,参数是广州、这些景点和旅游路线样式。”
  4. Cline -> MCP Server : Cline就拿着这些参数去调用地图工具(mcp-server-chart)的generate_interactive_map函数。
  5. MCP Server -> Cline: 地图工具mcp-server-chart接到命令后,就忙活起来,生成一个可交互的广州旅游路线地图,然后把生成的结果返回给Cline。
  6. Cline -> deepseek模型: Cline拿到地图后,就把这个结果交给deepseek模型
  7. deepseek模型 -> Cline:模型再组织一下语言,比如解释一下地图怎么用,再传给cline
  8. Cline -> 用户: 然后Cline就把最终的回答和地图一起展示给用户。

总结

上述内容我们主要讲了4点,分别是:

  1. MCP 协议的核心概念 :让 AI 模型拥有使用外部工具的能力
  2. 完整的环境搭建 :从 cline安装到 MCP Server的配置
  3. 实战操作流程 :配置 MCP Server 并生成交互式地图
  4. 技术原理理解 :MCP Host、MCP Server 和 Tool 的关系

如果觉得对您有帮助,欢迎点赞 👍 收藏 ⭐ 关注 🔔 支持一下! 往期实战推荐:

❌