Hi there 👋

Welcome to BruceDing’s blog

使用Mcp Inspector调试MCP Server

工具的介绍参考这里,使用方式也比较简单。 使用类似的命令,启动服务。 npx @modelcontextprotocol/inspector <command> 我们使用前文提到的 pairec-mcp-demo 作为参考。 启动命令 npx -y @modelcontextprotocol/inspector "/Users/bruceding 1/Projects/go/src/go-echo-mcp/pairec-mcp-demo/pairec-mcp-demo" --log_dir ./log /Users/bruceding 1/Projects/go/src/go-echo-mcp/pairec-mcp-demo/pairec-mcp-demo 是sever 的二进制路径。 --log_dir ./log 中两个是命令行的启动参数。 启动成功后,会出现如下的提示,浏览器打开相应的地址。 在打开的页面中,选择 transport type ,确认 command 和 arguments 没有问题后,点击 connect ,会返回连接成功的信息。 连接成功后,如果测试 Tools 功能,选择 Tools tab, 调用 List Tools 方法,会列出 tools 工具,进行测试即可。

March 30, 2025 · 1 min · 45 words

Mcp协议解析

从上文 中,介绍了MCP 协议的基本内容,如何使用以及如何基于 stdio transport 开发mcp server 。 本文主要介绍下mcp协议的实现细节。通过从0开始开发一个mcp server, 并且通过日志的方式记录mcp client 和 mcp server 之间的数据是如何交互的。 开发思路是通过 stdio 进行数据读取,然后写入到日志中。注册到 cline 中这样就能接受到 mcp client 的请求了。 通过mcp 协议规范,处理请求,然后返回respone 数据。 处理完一种请求后,不断的更新服务,不断的和mcp client 进行交互,进入下一轮请求,循环往复,直至一个完整的链路完成。 MCP 协议使用 JSON-RPC格式,具体的request,response schema 可以参考这里。 全部的源码参考这里。 还是使用 Tools 走通整个链路。 下图中可以看出 Server 启动时,client 就是发起初始化请求,Server 要把相应的能力高速 Client (Resource, Promot, Tool)。 假设如果只支持 Tool 能力,client 会发起 tools/list 请求,把所有的工具信息获取到。包括 名称、参数列表、描述等等。 如果用户发起了请求, Client 会把用户的提示 + tools 列表信息给到 LLM LLM 会选择格式的工具,并组装请求高速 Client Client 发起tools/call 调用, mcp server 执行相应的工具功能 返回请求后,client 把结果告诉LLM, LLM 进行总结后,输出到客户。 我们看下核心的代码功能。 实际就是监听标准的输入,解析出 method 方法,然后进行相应的处理。...

March 27, 2025 · 3 min · 611 words

MCP协议介绍

MCP(Model Context Protocol,模型上下文协议) 是一个开源的协议,提供了一种通用、标准的方式把LLM AI 大模型和不同数据源以及工具连接起来。类似USB HUB 方式。 与传统调用 API 的方式不同,每个工具都有不同的调用方式,不同的AI 应用或者 LLM 调用时,都需要集成一遍。MCP 的出现,本质上来说出现一个中间层,把工具的提供方和工具的调用方进行了解耦,这样AI应用可以灵活的使用现有已经实现的工具,而不需要单独的集成,提供了开发效率。 协议架构 MCP HOSTS 面向终端用户的AI 应用,类似 Claude Desktop, IDEs 等通过MCP 协议来访问数据 MCP Client 协议的客户端,可以和mcp server 1:1 进行连接。他们之间通过 mcp 协议交互。Client 通常被集成到 host 中。 MCP Server 实现了mcp 协议的服务提供方,它会把数据源以及工具的使用通过服务暴露出去。 目前包括两种 transport layer: Stdio transport 通过标准的输入输出进行通讯(stdin, stdout) mcp server 运行在本机的进程中,比如 IDE 中的 AI 助手操作本地的终端,或者管理目录和文件等等 HTTP with SSE transport 使用 SSE 协议进行远程服务通讯 使用http post 请求方式 MCP 的协议是通过 JSON-RPC 2.0的方式来通讯的,具体协议可以参考这里。需要理解消息类型 request/response, 一个请求,正确的相应后返回 response , 具体response 业务数据封装在 result 字段中。 当请求出错的情况下,返回的错误信息封装到 error 字段中。 还有一种特殊的请求叫 Notifications , 这个请求不会带RequestId, 也不需要返回响应数据。 在MCP server 的实现中,需要定义好需要提供哪几类数据到client 使用。...

March 20, 2025 · 3 min · 440 words

Wasm component model介绍

在前面的文章中,可以看到如何生成 wasip1 的wasm 模块。wasip1 中wasm 的使用中还有很多限制: 函数的入参只支持整型和浮点类型,不支持字符串类型。 使用共享内存的方式传递数据,数据要传递的话,入参只能使用指针和数据长度。 wasip1中一个wasm 文件就可以认为是一个module. wasip2 引入了 component model的概念,它扩展了module的功能,使用更高抽象的WIT(wasm interface type) 来描述module的接口。通过WIT, 可以把各个语言的实现翻译成canonical ABI ,定义了底层的内存是如何组织的,更高级的对象如何在内存中表示等等。 目前 component model 还是发展中,对于guest 语言来说,都有成熟的demo介绍如何使用WIT并生成wasm 文件。但是对于 host 来说,目前只有rust支持运行,还没有看到其他语言的例子。 WIT 的定义可以参考 https://component-model.bytecodealliance.org/design/wit.html。从这里也能看到具体语言的应用。 wasmtime 也支持了如何运行component model,只不过目前只能运行 “command” component。也就是说需要引入了wasi:cli/command world。 C 支持 component model 在介绍之前,首先安装 wit-bindgen, wasm-tools, WASI SDK , wkg这几个工具。 如果安装过 rust, 可以通过 cargo 安装。 安装 wkg cargo install wkg 安装 wit-bindgen cargo install wit-bindgen-cli 安装 wasm-tools cargo install wasm-tools 安装 WASI SDK,可以通过这里下载已经预编译的。...

March 11, 2025 · 1 min · 202 words

Wasm导入函数示例

从wasm技术介绍 里可以看到如何导出函数,并且在宿主机里进行调用。本文介绍如何进行导入函数,从宿主机导入函数并在wasm函数里使用。 还是基于tinygo 来进行演示。 首先定义导入函数 //go:build tinygo package main import ( "fmt" "reflect" "unsafe" ) //export CallFromHost func CallFromHost() int32 //export Add func Add(a, b int32) int32 { return a + b } type User struct { Name string Age int } //export CallHost func CallHost() int32 { return CallFromHost() } //export AddUser func AddUser(nameData *byte, nameLen int32, age int32) bool { fmt.Println(nameLen, age) name := RawBytePtrToString(nameData, int(nameLen)) user := User{Name: name, Age: int(age)} fmt....

March 8, 2025 · 3 min · 488 words

Badger的GC初步探究

类似 RocksDB, badger 是 Go 基于 LSM 实现的 KV 数据库。本文介绍基于 badger 的 1.62 版本。 与传统的LSM 不同,对于 value 数据,badger 会写入 value log,来减少写放大和读放大。但是也会造成问题,就是磁盘会占用过多。 value log 的 gc 实现的比较简单。 我们先看下 badger 写入链路。 数据会优先写入 value log , 这里实际当成了 WAL 使用 value pointer 会记录 写入 value log 文件的 fid ,offset, len 然后把数据写入 memtable ,如何memtable 数据写满的话,会变成不可更改的 memtable , 然后写入到 SST Tables 中。 那么何时刷新 memtable , 目前有两种情况: 一个是 memtable 大小控制,超过 memtable 规定的大小,就会刷新。默认是 64M , 通过WithMaxTableSize 可以指定 在一个通过 LogRotatesToFlush 控制,这个参数是说 写入 value log 的文件轮转了多少次,默认是 2 次。 超过这个数值也会刷新。 当 badger 进行重启的时候,会对部分数据进行回放操作。从哪个点的数据进行回放,是通过 head pointer 实现的。 head pointer 记录了 fid 和 offset , 数据比这个 head pointer 晚的话,都会进行回放。...

March 4, 2025 · 2 min · 235 words

Raft协议学习

论文地址:https://raft.github.io/raft.pdf 原理演示: https://raft.github.io/raftscope/index.html 背景 在分布式系统中,数据一致性是必须考虑的点,而且是优先考虑。在不同的场景中,数据一致性包括强一致性和弱一致性(最终一致性)。Paxos及其变种提供的共识算法扮演了重要的角色。但是非常难以理解和实现,Raft旨在简化算法逻辑,提供易于理解的共识算法。常见的 etcd 就是使用的 Raft 协议。 论文中 Raft 协议主要包括以下部分: leader 选举 日志复制 安全性(实际上是各种边界条件的考虑,额外增加了规则) 集群成员的变化 复制状态机 在集群中,机器都会处在相同的状态,及时部分机器失败的情况下。为了达到这个目的,一般使用日志副本的方式。保证副本日志的一致性,就是共识算法的作用。通过共识模块,不同的机器会产生相同的日志副本,副本里的命令是相同的,顺序是相同的。那么状态执行这些log,就会产生相同的状态。 Raft 协议 通常,一个Raft集群包含5个节点,这样可以容忍2个节点的失败。 Raft使用 term (任期)的概念来代替时间的观念。term 使用正整数表示,每次leader选举,都会增加term值。 集群中三个角色: Follower : 是个被动角色,只会接受请求进行回应。 Candidate: 候选人,只有 Candidate 才能发起选举投票。选举成功,变为 Leader。 Leader: 集群中只有一个节点是这个角色。 当系统启动,或者没有收到 leader 的心跳请求, follower 会有一个随机时间,超时后term+1,并且会变成 Candidate 会发起投票。投票成功,会变成 leader , 会立即发送心跳请求。其余失败的 Candidate 会变成 follower 。 集群中主要有两种RPC, RequestVote RPC 和 AppendEntries RPC。前者用于投票,是 Candidate 发起的。后者用于同步log数据,或者心跳请求。 一个节点收到的 term 的比自己的大,会更新当前节点的 term 。 leader 选举 当选举开始时,follower 增加当前的任期term, 然后变成 Candidate。它给自己投票,然后并发的把RequestVote 请求发送给其它节点。那么后面会出现三种情况:...

March 2, 2025 · 2 min · 240 words

ollama 使用

安装 curl -fsSL https://ollama.com/install.sh | sh 运行模型示例 ollama run llama3.2 类似docker 命令,可以使用 ollama list 和 ollama ps 命令查看已安装的模型和正在运行的模型。 自定义模型 类似 dockerfile , 可以创建Modelfile 来自定义模型的行为及输出。 比如定义一个翻译助手,从英文翻译到中文。 Modelfile 可以创建如下: FROM llama3.2 # set the system message SYSTEM """ 你的任务是把用户提供的{{.Prompt}} 直接翻译成中文。 """ 然后可以创建模型 ollama create fanyi-llama3.2 -f Modelfile 之后,可以运行 ollama run fanyi-llama3.2 Modelfile 的使用说明参考 https://github.com/ollama/ollama/blob/main/docs/modelfile.md。 使用api 接口服务 启动 server 服务 ollama serve 在本地起一个 11434 端口。 然后另一个终端,运行模型 ollama run fanyi-llama3.2 接口请求 curl http://localhost:11434/api/generate -d '{ "model": "fanyi-llama3....

March 1, 2025 · 1 min · 92 words

wasm技术介绍

什么是 WebAssembly WebAssembly(缩写为 Wasm)是一种基于堆栈的虚拟机的二进制指令格式。 Wasm 被设计为编程语言的可移植编译目标,支持在网络上部署客户端和服务器应用程序。 背景 目标很宏大, compile once , run anywhere。 特性 性能: 接近本机执行性能,编译成 low level 的二进制格式 安全: 沙箱的执行环境 多语言支持 可移植性: 跨平台,跨体系结构 有多种运行时 wasmtime wasmer wasmEdge wasmZero 两种编译技术 AOT JIT wasm 文本格式 参考:https://developer.mozilla.org/en-US/docs/WebAssembly/Guides/Understanding_the_text_format 定义个function并且导出 (module (func $add (param $lhs i32) (param $rhs i32) (result i32) local.get $lhs local.get $rhs i32.add) (export "add" (func $add)) ) 调用其它function (module (func $getAnswer (result i32) i32.const 42) (func (export "getAnswerPlus1") (result i32) call $getAnswer i32....

February 28, 2025 · 7 min · 1460 words

使用hugo搭建blog

本文介绍如何使用 hugo 搭建静态网站,网站内容push 到 github 上,通过 github action 编译然后传到 linode 机器上,通过nginx 服务访问网站内容。 hugo 的使用参考这里. 首先进行 hugo 安装, 本地电脑是mac ,通过 brew 安装 brew install hugo 然后创建一个网站, 会新建这个目录。 hugo new site bruceding-blog-site 进入 bruceding-blog-site 目录中 ,进行 git 初始化。 cd bruceding-blog-site git init 添加主题 git submodule add https://github.com/nanxiaobei/hugo-paper themes/paper echo "theme = 'paper'" >> hugo.toml 在github 上创建一个仓库,名字为 bruceding-blog-site。 然后把本地的仓库和github 上的仓库关联起来。 git remote add origin git@github.com:bruceding/bruceding-blog-site.git 新建一个blog 文章 hugo new content content/posts/使用hugo搭建blog.md 会生成类似的文件头, 把 draft 改成 false 。否则不会生成html 文件。...

February 12, 2025 · 2 min · 406 words