使用go搭建本地mcp实现AI选股小记
使用Go语言基于MCP协议打造AI选股工具
【TypeScript】三分钟让 Trae、Cursor 用上你自己的 MCP
一文弄懂用Go实现自己的MCP服务
什么是MCP
Model Context Protocol 即MCP,是一种协议,它允许大型语言模型LLMs访问自定义的工具和服务。
比如可以使用trae中的智能体作为MCP客户端可以选择想 MCP Server 发起请求,以使用它们提供的工具。你可以自行添加 MCP Server,并添加到自定义的智能体中来使用
在 trae 中,MCP Server 支持三种传输类型:stdio 传输,SSE 传输,Streamable HTTP 传输
技术实现
编辑工具:vscode
插件:cline
go代码参考:使用Go语言基于MCP协议打造AI选股工具
//mcptest.gopackage mainimport ("bytes""context""encoding/json""fmt""io""net/http""strings""time""github.com/mark3labs/mcp-go/mcp""github.com/mark3labs/mcp-go/server""github.com/spf13/cast""github.com/tidwall/gjson"
)type StockSearchRequest struct {KeyWord string `json:"KeyWord"`PageSize int `json:"pageSize"`PageNo int `json:"pageNo"`Fingerprint string `json:"fingerprint"`MatchWord string `json:"matchWord"`ShareToGuba bool `json:"shareToGuba"`Timestamp string `json:"timestamp"`RequestID string `json:"requestId"`RemovedConditionIDList []interface{} `json:"removedConditionIdList"`OwnSelectAll bool `json:"ownSelectAll"`NeedCorrect bool `json:"needCorrect"`Client string `json:"client"`DxInfo []interface{} `json:"dxInfo"`Biz string `json:"biz"`Gids []interface{} `json:"gids"`
}func main() {mcpServer := server.NewMCPServer("mcp-server-ai-stock", "1.0.0", server.WithToolCapabilities(false))queryStocks := mcp.NewTool("query_stocks",mcp.WithDescription("智能选股:描述你期望的股票(自然语言选股),返回股票的最新交易数据。"),mcp.WithString("keyword",mcp.Description("选股条件,例:\n"+"1. 股票或板块名称:宁德时代、比亚迪、新能源、AI、白酒\n"+"2. 技术指标:MACD、5日均线、RSI、KDJ\n"+"3. 财务条件:ROE>15%、净利润增长率>30%\n"+"4. 复合条件:MACD金叉且成交量放大;股价在5日均线上方;不要ST股及不要退市股;不要科创板;不要北交所"),),)mcpServer.AddTool(queryStocks, queryStocksHandler)if err := server.ServeStdio(mcpServer); err != nil {panic(err)}
}func queryStocksHandler(ctx context.Context, request mcp.CallToolRequest) (res *mcp.CallToolResult, err error) {keyword := cast.ToString(cast.ToStringMap(request.Params.Arguments)["keyword"])requestBody, err := json.Marshal(&StockSearchRequest{PageNo: 1,PageSize: 50,KeyWord: keyword,Fingerprint: "6d09ac0e7326d9299bb77ac2090dadd9",Gids: []interface{}{},Timestamp: cast.ToString(time.Now().UnixMilli()),RequestID: "jVZgmtMhiPYtiDb7g2yferYT9aCrY1TA1758537136613",NeedCorrect: true,RemovedConditionIDList: []interface{}{},DxInfo: []interface{}{},Biz: "web_ai_select_stocks",Client: "web",})if err != nil {return &mcp.CallToolResult{Content: []mcp.Content{mcp.NewTextContent(fmt.Sprintf("序列化请求失败: %v", err))}}, nil}client := &http.Client{Timeout: 30 * time.Second}req, err := http.NewRequestWithContext(ctx, "POST", "https://np-tjxg-g.eastmoney.com/api/smart-tag/stock/v3/pw/search-code", bytes.NewBuffer(requestBody))if err != nil {return &mcp.CallToolResult{Content: []mcp.Content{mcp.NewTextContent(fmt.Sprintf("创建请求失败: %v", err))}}, nil}req.Header.Set("Content-Type", "application/json")req.Header.Set("Origin", "https://xuangu.eastmoney.com")req.Header.Set("Referer", "https://xuangu.eastmoney.com/")req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0")resp, err := client.Do(req)if err != nil {return &mcp.CallToolResult{Content: []mcp.Content{mcp.NewTextContent(fmt.Sprintf("请求失败: %v", err))}}, nil}defer func() { _ = resp.Body.Close() }()body, err := io.ReadAll(resp.Body)if err != nil {return &mcp.CallToolResult{Content: []mcp.Content{mcp.NewTextContent(fmt.Sprintf("读取响应失败: %v", err))}}, nil}g := gjson.ParseBytes(body)if g.Get("code").Int() != 100 {return &mcp.CallToolResult{Content: []mcp.Content{mcp.NewTextContent(fmt.Sprintf("响应非100: %s", string(body)))}}, nil}if g.Get("data.result.total").Int() <= 0 {return &mcp.CallToolResult{Content: []mcp.Content{mcp.NewTextContent("未找到符合条件的股票")}}, nil}content := parseSearchCodeResponse(g)return &mcp.CallToolResult{Content: []mcp.Content{mcp.NewTextContent(content)}}, nil
}func parseSearchCodeResponse(g gjson.Result) string {var (columns []stringb strings.Builder)_, _ = b.WriteString("## 筛选的股票数据\n")g.Get("data.result.columns").ForEach(func(_, o gjson.Result) bool {columns = append(columns, o.Get("key").String()) // 英文字段_, _ = b.WriteString(o.Get("title").String() + o.Get("unit").String() + "|") // 中文表头return true})g.Get("data.result.dataList").ForEach(func(_, o gjson.Result) bool {_, _ = b.WriteString("\n|")for _, column := range columns {_, _ = b.WriteString(strings.ReplaceAll(o.Get(column).String(), "|", ",") + "|")}return true})return b.String()
}
上述代码实际是请求 东方财富 的开发API
执行命令,生成服务器端可执行文件
go build -o mcp-server mcptest.go
安装好cline插件之后,需要配置连接mcp服务器的脚本
增加如下配置
{"mcpServers": {"mcp-calculator-server": {"command": "/Users/yourusername/Workspace/go/src/mcp-server/mcp-server"}}
}
配置成功后即可看到如下信息
结果
输入 “宁德时代”
会看到自动调用本地的mcp-server
输出
智能体美化后输出
输入 “MACD金叉且市盈率小于30”
输出
美化