欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go語(yǔ)言開發(fā)實(shí)現(xiàn)查詢IP信息的MCP服務(wù)器

 更新時(shí)間:2025年04月25日 15:23:50   作者:陳明勇  
隨著?MCP?的快速普及和廣泛應(yīng)用,MCP?服務(wù)器也層出不窮,本文將詳細(xì)介紹如何在?Go?語(yǔ)言中使用?go-mcp?庫(kù)來(lái)開發(fā)一個(gè)查詢?IP?信息的?MCP?服務(wù)器,有需要的小伙伴可以參考下

前言

隨著 MCP 的快速普及和廣泛應(yīng)用,MCP 服務(wù)器也層出不窮。大多數(shù)開發(fā)者使用的 MCP 服務(wù)器開發(fā)庫(kù)是官方提供的 typescript-sdk,而作為 Go 開發(fā)者,我們也可以借助優(yōu)秀的第三方庫(kù)去開發(fā) MCP 服務(wù)器,例如 ThinkInAIXYZ/go-mcp

本文將詳細(xì)介紹如何在 Go 語(yǔ)言中使用 go-mcp 庫(kù)來(lái)開發(fā)一個(gè)查詢 IP 信息的 MCP 服務(wù)器。

mcp-ip-geo 服務(wù)器

mcp-ip-geo 是一個(gè)用于查詢 IP 信息的 MCP 服務(wù)器,項(xiàng)目已開源,倉(cāng)庫(kù)地址:mcp-ip-geo

目錄結(jié)構(gòu)說(shuō)明

├─cmd
│  └─mcp-ip-geo
└─internal
    ├─domain
    ├─server
    ├─service
    └─tools

  • cmd/mcp-ip-geo:應(yīng)用的啟動(dòng)入口目錄,包含如 main.go 啟動(dòng)文件。
  • internal/domain:定義項(xiàng)目中的核心數(shù)據(jù)結(jié)構(gòu),例如 IP API 的響應(yīng)體等。
  • internal/serverMCP 服務(wù)器的核心邏輯實(shí)現(xiàn)。
  • internal/service:對(duì)接第三方服務(wù)的實(shí)現(xiàn),如調(diào)用 IP 解析 API
  • internal/toolsMCP 工具的具體實(shí)現(xiàn),支持靈活擴(kuò)展和注冊(cè)。

查詢 IP 信息功能實(shí)現(xiàn)

代碼位于 service 包中,通過(guò) ip-api.com 提供的接口獲取 IP 地理位置信息,具體實(shí)現(xiàn)如下:

package service

import (
    "context"
    "fmt"
    "github.com/chenmingyong0423/mcp-ip-geo/internal/domain"
    "net/http"
    "time"

    httpchain "github.com/chenmingyong0423/go-http-chain"
)

func NewIpApiService() *IpApiService {
    return &IpApiService{
       host: "http://ip-api.com",
       client: httpchain.NewWithClient(&http.Client{
          Timeout: time.Second * 10,
       }),
    }
}

type IIpApiService interface {
    GetLocation(ctx context.Context, ip string) (*domain.IpApiResponse, error)
}

var _ IIpApiService = (*IpApiService)(nil)

type IpApiService struct {
    host   string
    client *httpchain.Client
}

func (s *IpApiService) GetLocation(ctx context.Context, ip string) (*domain.IpApiResponse, error) {
    var resp domain.IpApiResponse
    err := s.client.Get(fmt.Sprintf("%s/json/%s", s.host, ip)).DoAndParse(ctx, &resp)
    if err != nil {
       return nil, err
    }
    return &resp, nil
}

代碼解釋:

  • 服務(wù)初始化(NewIpApiService

    • 創(chuàng)建一個(gè)新的 IpApiService 實(shí)例。
    • 設(shè)置了 API 地址為 http://ip-api.com。
    • 使用 httpchain 封裝的 HTTP 客戶端,設(shè)置請(qǐng)求超時(shí)時(shí)間為 10 秒。
  • 接口定義(IIpApiService

    • 定義了服務(wù)對(duì)外暴露的功能:GetLocation 方法,用于獲取 IP 地理位置信息。  
    • 使用接口有助于后續(xù)做依賴注入、mock 測(cè)試等。  
    • var _ IIpApiService = (*IpApiService)(nil) 這行代碼用于編譯時(shí)檢查,確保 IpApiService 實(shí)現(xiàn)了 IIpApiService 接口。
  • 結(jié)構(gòu)體定義(IpApiService) 

    • 包含兩個(gè)字段:
    • hostAPI 的基礎(chǔ)地址。
    • client:封裝的 HTTP 客戶端,類型為 *httpchain.Client。
  • 核心方法實(shí)現(xiàn)(GetLocation

    • 根據(jù)傳入的 IP 構(gòu)造請(qǐng)求地址:http://ip-api.com/json/{ip}。  
    • 使用 httpchain 庫(kù)發(fā)起 GET 請(qǐng)求,并將結(jié)果解析到 domain.IpApiResponse 結(jié)構(gòu)體中。  

工具實(shí)現(xiàn)

工具管理

代碼位于 tools 包中,用于管理工具,具體實(shí)現(xiàn)如下:

package tools

import (
    "github.com/ThinkInAIXYZ/go-mcp/protocol"
    "github.com/ThinkInAIXYZ/go-mcp/server"
)

type ToolFunc func() (tool *protocol.Tool, toolHandler server.ToolHandlerFunc)

func GetToolFuncList() []ToolFunc {
    return []ToolFunc{
       SingleIpParser,
    }
}

代碼解釋:

  • ToolFunc 類型定義

    • 定義了一個(gè)函數(shù)類型 ToolFunc,返回兩個(gè)值:

      • *protocol.Tool:工具的元信息;
      • server.ToolHandlerFunc:該工具的處理邏輯函數(shù)。
    • 用這種方式可以將 工具的定義工具的執(zhí)行邏輯 一并管理,后續(xù)在定義工具時(shí)都可以通過(guò)實(shí)現(xiàn)該函數(shù)簽名進(jìn)行表示。

  • GetToolFuncList 函數(shù)

    • 返回一個(gè) ToolFunc 列表。
    • 當(dāng)前只注冊(cè)了一個(gè)工具:SingleIpParser,但這種結(jié)構(gòu)易于擴(kuò)展,后續(xù)只需往列表中添加新的工具函數(shù)即可。
    • 通過(guò)集中注冊(cè),應(yīng)用在初始化時(shí)可以統(tǒng)一加載所有工具。

查詢單個(gè) IP 信息工具的實(shí)現(xiàn)

代碼位于 tools 包中,用于查詢單個(gè) IP 信息,具體實(shí)現(xiàn)如下:

package tools

import (
    "context"
    "encoding/json"
    "github.com/ThinkInAIXYZ/go-mcp/protocol"
    "github.com/ThinkInAIXYZ/go-mcp/server"
    "github.com/chenmingyong0423/mcp-ip-geo/internal/service"
)

var singleIpParserTool *protocol.Tool

type ipRequest struct {
    Ip string `json:"ip"`
}

func init() {
    var err error
    singleIpParserTool, err = protocol.NewTool("ip-details", "a tool that provides IP geolocation information", ipRequest{})
    if err != nil {
       panic(err)
    }
}

func SingleIpParser() (*protocol.Tool, server.ToolHandlerFunc) {
    ipApiService := service.NewIpApiService()

    return singleIpParserTool, func(toolRequest *protocol.CallToolRequest) (*protocol.CallToolResult, error) {
       var req ipRequest
       if err := protocol.VerifyAndUnmarshal(toolRequest.RawArguments, &req); err != nil {
          return nil, err
       }
       resp, err := ipApiService.GetLocation(context.Background(), req.Ip)
       if err != nil {
          return nil, err
       }

       marshal, err := json.Marshal(resp)
       if err != nil {
          return nil, err
       }

       return &protocol.CallToolResult{
          Content: []protocol.Content{
             protocol.TextContent{
                Type: "text",
                Text: string(marshal),
             },
          },
       }, nil
    }
}

代碼解釋:

  • 全局變量聲明

    • singleIpParserTool:存儲(chǔ)工具元信息的協(xié)議工具對(duì)象
    • ipRequest:定義工具輸入?yún)?shù)結(jié)構(gòu)體,包含 ip 字符串字段
  • 初始化函數(shù)(init

    • 在包加載時(shí)通過(guò) protocol.NewTool 創(chuàng)建工具元信息
    • 指定工具標(biāo)識(shí)符 ip-details,描述信息和輸入?yún)?shù)結(jié)構(gòu)體 ipRequest{}
    • 錯(cuò)誤處理采用 panic,確保工具元信息必須正確初始化
  • 工具注冊(cè)函數(shù)(SingleIpParser

    • 創(chuàng)建 IpApiService 服務(wù)實(shí)例用于 IP 定位查詢

    • 返回兩個(gè)值:

      • 預(yù)定義的 singleIpParserTool 元信息對(duì)象
      • 工具處理函數(shù)
  • 工具處理函數(shù)

    • 參數(shù)驗(yàn)證與解析

      • 調(diào)用 protocol.VerifyAndUnmarshal 驗(yàn)證請(qǐng)求參數(shù)有效性
      • 將原始參數(shù)反序列化到 ipRequest 結(jié)構(gòu)體
    • 服務(wù)調(diào)用

      • 使用 ipApiService.GetLocation 獲取 IP 地理位置信息
    • 結(jié)果處理

      • 將服務(wù)響應(yīng)結(jié)果序列化為 JSON 字符串并包裝為 protocol.CallToolResult 結(jié)構(gòu)體返回

服務(wù)器的創(chuàng)建與啟動(dòng)

代碼位于 server 包中,用于初始化服務(wù)并啟動(dòng)服務(wù)端,具體實(shí)現(xiàn)如下:

package server

import (
    "github.com/ThinkInAIXYZ/go-mcp/server"
    "github.com/ThinkInAIXYZ/go-mcp/transport"
    "github.com/chenmingyong0423/mcp-ip-geo/internal/tools"
)

func Run(address string) error {
    var err error

    var ts transport.ServerTransport
    if address == "" {
       ts = transport.NewStdioServerTransport()
    } else {
       ts, err = transport.NewSSEServerTransport(address)
       if err != nil {
          return err
       }
    }

    s, err := server.NewServer(ts)
    if err != nil {
       return err
    }

    toolFuncList := tools.GetToolFuncList()
    for _, tool := range toolFuncList {
       s.RegisterTool(tool())
    }

    return s.Run()
}

代碼解釋:

  • 傳輸層初始化

    • 根據(jù) address 參數(shù)判斷運(yùn)行模式:

      • 空地址模式:使用 NewStdioServerTransport 創(chuàng)建標(biāo)準(zhǔn)輸入輸出傳輸,適用于命令行工具等場(chǎng)景。
      • 指定地址模式:使用 NewSSEServerTransport 創(chuàng)建 SSE (Server-Sent Events) 傳輸,適用于 HTTP 長(zhǎng)連接服務(wù)。
  • 服務(wù)實(shí)例化

    • 使用 server.NewServer 方法創(chuàng)建服務(wù)實(shí)例,注入配置好的傳輸層對(duì)象 ts。
  • 工具注冊(cè)

    • 調(diào)用 tools.GetToolFuncList 獲取所有預(yù)定義的工具函數(shù)列表。

    • 遍歷工具列表,通過(guò) s.RegisterTool(tool()) 注冊(cè)每個(gè)工具:

      • tool() 執(zhí)行后返回元信息 *protocol.Tool 和處理函數(shù) ToolHandlerFunc。
  • 服務(wù)啟動(dòng)

    • 調(diào)用 s.Run() 啟動(dòng)服務(wù),開始監(jiān)聽請(qǐng)求。

主程序入口實(shí)現(xiàn)

代碼位于 main 包中,作為程序啟動(dòng)入口,具體實(shí)現(xiàn)如下:

package main

import (
    "flag"
    "github.com/chenmingyong0423/mcp-ip-geo/internal/server"
)

func main() {
    addr := flag.String("address", "", "The host and port to run the sse server")
    flag.Parse()

    if err := server.Run(*addr); err != nil {
       panic(err)
    }
}

代碼解釋:

  • 命令行參數(shù)解析

    • 定義 address 參數(shù):

      • 參數(shù)名稱:-address
      • 默認(rèn)值:空字符串
      • 描述:指定 SSE 服務(wù)運(yùn)行的地址和端口
    • 調(diào)用 flag.Parse() 解析命令行參數(shù)

  • 服務(wù)啟動(dòng)

    • 調(diào)用 server.Run(*addr) 啟動(dòng)服務(wù)
    • 將解析后的 address 參數(shù)值傳遞給服務(wù)啟動(dòng)函數(shù)

從源碼構(gòu)建

本地構(gòu)建

使用 Go 命令

# 在類 Unix 系統(tǒng)(Linux/macOS)上
go build -o mcp-ip-geo ./cmd/mcp-ip-geo

# 在 Windows 上
go build -o mcp-ip-geo.exe .\cmd\mcp-ip-geo

使用 Docker

構(gòu)建 Docker 鏡像:

docker build -t mcp-ip-geo-server .

運(yùn)行容器:

docker run -d --name mcp-ip-geo-server -p 8000:8000 mcp-ip-geo-server

安裝預(yù)編譯版本

使用 Go 安裝最新版本的服務(wù):

go install github.com/chenmingyong0423/mcp-ip-geo/cmd/mcp-ip-geo@latest

MCP 集成

你可以通過(guò)以下兩種方式集成 mcp-ip-geo 服務(wù):

可執(zhí)行文件集成(本地運(yùn)行)

{
  "mcpServers": {
    "mcp-ip-geo": {
      "command": "/path/to/mcp-ip-geo"
    }
  }
}

HTTP 接口集成(連接到已運(yùn)行的服務(wù))

{
  "mcpServers": {
    "mcp-ip-geo": {
      "url": "http://host:port/sse"
    }
  }
}

效果演示

小結(jié)

本文將詳細(xì)介紹 mcp-ip-geo —— 一個(gè)用于查詢 IP 信息的 MCP 服務(wù)器的實(shí)現(xiàn)細(xì)節(jié)。該服務(wù)器目前支持兩種數(shù)據(jù)傳輸方式:stdioSSE(Server-Sent Events)。未來(lái)還計(jì)劃支持 Streamable HTTP 傳輸方式,并持續(xù)擴(kuò)展更多實(shí)用的工具(tools)模塊。

到此這篇關(guān)于Go語(yǔ)言開發(fā)實(shí)現(xiàn)查詢IP信息的MCP服務(wù)器的文章就介紹到這了,更多相關(guān)Go MCP服務(wù)器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • golang中的jwt使用教程流程分析

    golang中的jwt使用教程流程分析

    這篇文章主要介紹了golang中的jwt使用教程,接下來(lái)我們需要講解一下Claims該結(jié)構(gòu)體存儲(chǔ)了token字符串的超時(shí)時(shí)間等信息以及在解析時(shí)的Token校驗(yàn)工作,需要的朋友可以參考下
    2023-05-05
  • 初學(xué)Go必備的vscode插件及最常用快捷鍵和代碼自動(dòng)補(bǔ)全

    初學(xué)Go必備的vscode插件及最常用快捷鍵和代碼自動(dòng)補(bǔ)全

    這篇文章主要給大家介紹了關(guān)于初學(xué)vscode寫Go必備的vscode插件及最常用快捷鍵和代碼自動(dòng)補(bǔ)全的相關(guān)資料,由于vscode是開源免費(fèi)的,而且開發(fā)支持vscode的插件相對(duì)比較容易,更新速度也很快,需要的朋友可以參考下
    2023-07-07
  • Go語(yǔ)言基于HTTP的內(nèi)存緩存服務(wù)的實(shí)現(xiàn)

    Go語(yǔ)言基于HTTP的內(nèi)存緩存服務(wù)的實(shí)現(xiàn)

    這篇文章主要介紹了Go語(yǔ)言基于HTTP的內(nèi)存緩存服務(wù),本程序采用REST接口,支持設(shè)置(Set)、獲取(Get)和刪除(Del)這3個(gè)基本操作,同時(shí)還支持對(duì)緩存服務(wù)狀態(tài)進(jìn)行查詢,需要的朋友可以參考下
    2022-08-08
  • go實(shí)現(xiàn)整型的二進(jìn)制轉(zhuǎn)化的方法

    go實(shí)現(xiàn)整型的二進(jìn)制轉(zhuǎn)化的方法

    這篇文章主要介紹了go實(shí)現(xiàn)整型的二進(jìn)制轉(zhuǎn)化的方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下
    2019-07-07
  • golang 切片的三種使用方式及區(qū)別的說(shuō)明

    golang 切片的三種使用方式及區(qū)別的說(shuō)明

    這篇文章主要介紹了golang 切片的三種使用方式及區(qū)別的說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04
  • golang使用正則表達(dá)式解析網(wǎng)頁(yè)

    golang使用正則表達(dá)式解析網(wǎng)頁(yè)

    這篇文章主要介紹了golang使用正則表達(dá)式解析網(wǎng)頁(yè),需要的朋友可以參考下
    2015-03-03
  • Golang實(shí)現(xiàn)密碼加密的示例詳解

    Golang實(shí)現(xiàn)密碼加密的示例詳解

    數(shù)據(jù)庫(kù)在存儲(chǔ)密碼時(shí),不能明文存儲(chǔ),需要加密后存儲(chǔ),而Golang中的加密算法有很多種,下面小編就來(lái)通過(guò)簡(jiǎn)單的示例和大家簡(jiǎn)單聊聊吧
    2023-07-07
  • Gin框架使用Zap接收日志的實(shí)現(xiàn)

    Gin框架使用Zap接收日志的實(shí)現(xiàn)

    在Gin框架中使用Zap日志中間件替代默認(rèn)日志,通過(guò)封裝日志包提升性能,實(shí)現(xiàn)更高效的日志記錄與異?;謴?fù)功能,下面就來(lái)介紹一下Gin框架使用Zap接收日志的實(shí)現(xiàn),感興趣的可以了解一下
    2025-05-05
  • Go?語(yǔ)言入門之net/url?包

    Go?語(yǔ)言入門之net/url?包

    這篇文章主要介紹了Go?語(yǔ)言入門之net/url?包,文章基于GO語(yǔ)言的相關(guān)資料展開?net/url?包的詳細(xì)內(nèi)容,具有一定的的參考價(jià)值,需要的小伙伴可以參考一下
    2022-05-05
  • 一文帶你了解Go語(yǔ)言中鎖特性和實(shí)現(xiàn)

    一文帶你了解Go語(yǔ)言中鎖特性和實(shí)現(xiàn)

    Go語(yǔ)言中的sync包主要提供的對(duì)并發(fā)操作的支持,標(biāo)志性的工具有cond(條件變量)?once?(原子性)?還有?鎖,本文會(huì)主要向大家介紹Go語(yǔ)言中鎖的特性和實(shí)現(xiàn),感興趣的可以了解下
    2024-03-03

最新評(píng)論