mcpField
M
MCP Server Go

MCP Server Go

本地服务
github.com/shaneholloman开发工具170 周前更新

关于 MCP Server Go

MCP Server Go 是用于构建 MCP 服务的 Go 实现,面向需要连接大模型应用与数据、工具的开发者。它提供工具、资源和提示词的高级 API,协议支持仍在开发中。

主要功能

  1. 01高级 Go 服务端 API
  2. 02注册工具
  3. 03静态与动态资源
  4. 04可复用提示词定义
  5. 05协议与连接管理

适用场景

  1. 01用 Go 构建 MCP 服务
  2. 02将应用数据作为资源提供
  3. 03向大模型应用提供操作工具
  4. 04定义可复用交互提示词

MCP 相关

该库实现 MCP 服务端,向 MCP 客户端提供工具、资源和提示词。项目目标是覆盖核心规范,部分高级能力仍在开发中。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

暂未收录安装方式

我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。

代码仓库

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

MCP Server Go

Go Report Card GoDoc

提示

Model Context Protocol(MCP)的 Go 实现,可让大模型应用与外部数据源和工具无缝集成。

package main

import (
    "context"
    "fmt"

    "github.com/shaneholloman/mcp-server-go/mcp"
    "github.com/shaneholloman/mcp-server-go/server"
)

func main() {
    // Create MCP server
    s := server.NewMCPServer(
        "Demo",
        "1.0.0",
    )

    // Add tool
    tool := mcp.NewTool("hello_world",
        mcp.WithDescription("Say hello to someone"),
        mcp.WithString("name",
            mcp.Required(),
            mcp.Description("Name of the person to greet"),
        ),
    )

    // Add tool handler
    s.AddTool(tool, helloHandler)

    // Start the stdio server
    if err := server.ServeStdio(s); err != nil {
        fmt.Printf("Server error: %v\n", err)
    }
}

func helloHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
    name, ok := request.Params.Arguments["name"].(string)
    if !ok {
        return mcp.NewToolResultError("name must be a string"), nil
    }

    return mcp.NewToolResultText(fmt.Sprintf("Hello, %s!", name)), nil
}

就是这样!

MCP Go 会处理所有复杂的协议细节和服务管理,让你专注于构建出色的工具。它力求提供高层级且易于使用的体验。

主要特性

  • 快速:高层级接口意味着更少的代码和更快的开发
  • 简单:只需少量样板代码即可构建 MCP 服务
  • 完整*:MCP Go 力求完整实现 MCP 核心规范

重要

MCP Go 正在积极开发中,MCP 规范本身也在不断完善。核心功能已可使用,但一些高级功能仍在开发中。

目录

安装

go get github.com/shaneholloman/mcp-server-go

快速开始

我们来创建一个简单的 MCP 服务,提供计算器工具和一些数据:

package main

import (
    "context"
    "fmt"

    "github.com/shaneholloman/mcp-server-go/mcp"
    "github.com/shaneholloman/mcp-server-go/server"
)

func main() {
    // Create a new MCP server
    s := server.NewMCPServer(
        "Calculator Demo",
        "1.0.0",
        server.WithResourceCapabilities(true, true),
        server.WithLogging(),
    )

    // Add a calculator tool
    calculatorTool := mcp.NewTool("calculate",
        mcp.WithDescription("Perform basic arithmetic operations"),
        mcp.WithString("operation",
            mcp.Required(),
            mcp.Description("The operation to perform (add, subtract, multiply, divide)"),
            mcp.Enum("add", "subtract", "multiply", "divide"),
        ),
        mcp.WithNumber("x",
            mcp.Required(),
            mcp.Description("First number"),
        ),
        mcp.WithNumber("y",
            mcp.Required(),
            mcp.Description("Second number"),
        ),
    )

    // Add the calculator handler
    s.AddTool(calculatorTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
        op := request.Params.Arguments["operation"].(string)
        x := request.Params.Arguments["x"].(float64)
        y := request.Params.Arguments["y"].(float64)

        var result float64
        switch op {
        case "add":
            result = x + y
        case "subtract":
            result = x - y
        case "multiply":
            result = x * y
        case "divide":
            if y == 0 {
                return mcp.NewToolResultError("Cannot divide by zero"), nil
            }
            result = x / y
        }

        return mcp.NewToolResultText(fmt.Sprintf("%.2f", result)), nil
    })

    // Start the server
    if err := server.ServeStdio(s); err != nil {
        fmt.Printf("Server error: %v\n", err)
    }
}

什么是 MCP?

Model Context Protocol(MCP) 让你能够构建以安全、标准化的方式向大模型应用提供数据和功能的服务。可以把它看作专为大模型交互设计的 Web API。MCP 服务可以:

  • 通过资源提供数据(可以把它们看作类似 GET 端点的东西;用于将信息加载到大模型的上下文中)
  • 通过工具提供功能(可以把它们看作类似 POST 端点的东西;用于执行代码或产生其他副作用)
  • 通过提示词定义交互模式(用于大模型交互的可复用模板)
  • 以及更多!

核心概念

服务
显示服务示例

服务是 MCP 协议的核心接口,负责连接管理、协议合规和消息路由:

// Create a basic server
s := server.NewMCPServer(
    "My Server",  // Server name
    "1.0.0",     // Version
)

// Start the server using stdio
if err := server.ServeStdio(s); err != nil {
    log.Fatalf("Server error: %v", err)
}
资源
显示资源示例 资源是向大模型提供数据的方式。它们可以是各种内容——文件、API 响应、数据库查询结果、系统信息等。资源可以是:
  • 静态(固定 URI)
  • 动态(使用 URI 模板)

以下是一个静态资源的简单示例:

// Static resource example - exposing a README file
resource := mcp.NewResource(
    "docs://readme",
    "Project README",
    mcp.WithResourceDescription("The project's README file"),
    mcp.WithMIMEType("text/markdown"),
    mcp.WithAnnotations([]mcp.Role{mcp.RoleAssistant}, 0.8),
)

// Add resource with its handler
s.AddResource(resource, func(ctx context.Context, request mcp.ReadResourceRequest) ([]interface{}, error) {
    content, err := os.ReadFile("README.md")
    if err != nil {
        return nil, err
    }

    return []interface{}{
        mcp.TextResourceContents{
            ResourceContents: mcp.ResourceContents{
                URI:      "docs://readme",
                MIMEType: "text/markdown",
            },
            Text: string(content),
        },
    }, nil
})

以下是使用模板的动态资源示例:

// Dynamic resource example - user profiles by ID
template := mcp.NewResourceTemplate(
    "users://{id}/profile",
    "User Profile",
    mcp.WithTemplateDescription("Returns user profile information"),
    mcp.WithTemplateMIMEType("application/json"),
    mcp.WithTemplateAnnotations([]mcp.Role{mcp.RoleAssistant, mcp.RoleUser}, 0.5),
)

// Add template with its handler
s.AddResourceTemplate(template, func(ctx context.Context, request mcp.ReadResourceRequest) ([]interface{}, error) {
    userID := request.Params.URI // Extract ID from the full URI

    profile, err := getUserProfile(userID)  // Your DB/API call here
    if err != nil {
        return nil, err
    }

    return []interface{}{
        mcp.TextResourceContents{
            ResourceContents: mcp.ResourceContents{
                URI:      fmt.Sprintf("users://%s/profile", userID),
                MIMEType: "application/json",
            },
            Text: profile,
        },
    }, nil
})

这些示例虽然简单,但展示了核心概念。资源还可以复杂得多,例如提供多个内容、使用注解、与数据库或外部 API 集成等。

工具
显示工具示例

工具让大模型能够通过你的服务执行操作。与资源不同,工具需要执行计算并产生副作用。它们类似于 REST API 中的 POST 端点。

简单计算示例:

calculatorTool := mcp.NewTool("calculate",
    mcp.WithDescription("Perform basic arithmetic calculations"),
    mcp.WithString("operation",
        mcp.Required(),
        mcp.Description("The arithmetic operation to perform"),
        mcp.Enum("add", "subtract", "multiply", "divide"),
    ),
    mcp.WithNumber("x",
        mcp.Required(),
        mcp.Description("First number"),
    ),
    mcp.WithNumber("y",
        mcp.Required(),
        mcp.Description("Second number"),
    ),
)

s.AddTool(calculatorTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
    op := request.Params.Arguments["operation"].(string)
    x := request.Params.Arguments["x"].(float64)
    y := request.Params.Arguments["y"].(float64)

    var result float64
    switch op {
    case "add":
        result = x + y
    case "subtract":
        result = x - y
    case "multiply":
        result = x * y
    case "divide":
        if y == 0 {
            return mcp.NewToolResultError("Division by zero is not allowed"), nil
        }
        result = x / y
    }

    return mcp.FormatNumberResult(result), nil
})

HTTP 请求示例:

httpTool := mcp.NewTool("http_request",
    mcp.WithDescription("Make HTTP requests to external APIs"),
    mcp.WithString("method",
        mcp.Required(),
        mcp.Description("HTTP method to use"),
        mcp.Enum("GET", "POST", "PUT", "DELETE"),
    ),
    mcp.WithString("url",
        mcp.Required(),
        mcp.Description("URL to send the request to"),
        mcp.Pattern("^https?://.*"),
    ),
    mcp.WithString("body",
        mcp.Description("Request body (for POST/PUT)"),
    ),
)

s.AddTool(httpTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
    method := request.Params.Arguments["method"].(string)
    url := request.Params.Arguments["url"].(string)
    body := ""
    if b, ok := request.Params.Arguments["body"].(string); ok {
        body = b
    }

    // Create and send request
    var req *http.Request
    var err error
    if body != "" {
        req, err = http.NewRequest(method, url, strings.NewReader(body))
    } else {
        req, err = http.NewRequest(method, url, nil)
    }
    if err != nil {
        return mcp.NewToolResultError(fmt.Sprintf("Failed to create request: %v", err)), nil
    }

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return mcp.NewToolResultError(fmt.Sprintf("Request failed: %v", err)), nil
    }
    defer resp.Body.Close()

    // Return response
    respBody, err := io.ReadAll(resp.Body)
    if err != nil {
        return mcp.NewToolResultError(fmt.Sprintf("Failed to read response: %v", err)), nil
    }

    return mcp.NewToolResultText(fmt.Sprintf("Status: %d\nBody: %s", resp.StatusCode, string(respBody))), nil
})

工具可以用于执行任何类型的计算或产生副作用:

  • 数据库查询
  • 文件操作
  • 外部 API 调用
  • 计算
  • 系统操作

每个工具都应:

  • 有清晰的描述
  • 验证输入
  • 妥善处理错误
  • 返回结构化响应
  • 使用合适的结果类型
### 提示词
显示提示词示例

提示词是可重复使用的模板,可帮助大模型与服务器有效交互。它们就像编码在服务器中的“最佳实践”。以下是一些示例:

// Simple greeting prompt
s.AddPrompt(mcp.NewPrompt("greeting",
    mcp.WithPromptDescription("A friendly greeting prompt"),
    mcp.WithArgument("name",
        mcp.ArgumentDescription("Name of the person to greet"),
    ),
), func(ctx context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
    name := request.Params.Arguments["name"].(string)
    if name == "" {
        name = "friend"
    }

    return mcp.NewGetPromptResult(
        "A friendly greeting",
        []mcp.PromptMessage{
            mcp.NewPromptMessage(
                mcp.RoleAssistant,
                mcp.NewTextContent(fmt.Sprintf("Hello, %s! How can I help you today?", name)),
            ),
        },
    ), nil
})

// Code review prompt with embedded resource
s.AddPrompt(mcp.NewPrompt("code_review",
    mcp.WithPromptDescription("Code review assistance"),
    mcp.WithArgument("pr_number",
        mcp.ArgumentDescription("Pull request number to review"),
        mcp.RequiredArgument(),
    ),
), func(ctx context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
    prNumber := request.Params.Arguments["pr_number"].(string)
    if prNumber == "" {
        return nil, fmt.Errorf("pr_number is required")
    }

    return mcp.NewGetPromptResult(
        "Code review assistance",
        []mcp.PromptMessage{
            mcp.NewPromptMessage(
                mcp.RoleSystem,
                mcp.NewTextContent("You are a helpful code reviewer. Review the changes and provide constructive feedback."),
            ),
            mcp.NewPromptMessage(
                mcp.RoleAssistant,
                mcp.NewEmbeddedResource(mcp.ResourceContents{
                    URI: fmt.Sprintf("git://pulls/%s/diff", prNumber),
                    MIMEType: "text/x-diff",
                }),
            ),
        },
    ), nil
})

// Database query builder prompt
s.AddPrompt(mcp.NewPrompt("query_builder",
    mcp.WithPromptDescription("SQL query builder assistance"),
    mcp.WithArgument("table",
        mcp.ArgumentDescription("Name of the table to query"),
        mcp.RequiredArgument(),
    ),
), func(ctx context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
    tableName := request.Params.Arguments["table"].(string)
    if tableName == "" {
        return nil, fmt.Errorf("table name is required")
    }

    return mcp.NewGetPromptResult(
        "SQL query builder assistance",
        []mcp.PromptMessage{
            mcp.NewPromptMessage(
                mcp.RoleSystem,
                mcp.NewTextContent("You are a SQL expert. Help construct efficient and safe queries."),
            ),
            mcp.NewPromptMessage(
                mcp.RoleAssistant,
                mcp.NewEmbeddedResource(mcp.ResourceContents{
                    URI: fmt.Sprintf("db://schema/%s", tableName),
                    MIMEType: "application/json",
                }),
            ),
        },
    ), nil
})

提示词可以包含:

  • 系统指令
  • 必需参数
  • 嵌入的资源
  • 多条消息
  • 不同的内容类型(文本、图像等)
  • 自定义 URI 方案

示例

示例请参见 examples/ 目录。

参与贡献

打开开发者指南
先决条件

Go 版本 >= 1.23

开发环境安装

创建此仓库的分叉,然后克隆它:

git clone https://github.com/shaneholloman/mcp-server-go.git
cd mcp-server-go
测试

请务必测试任何新功能。测试应当简单且独立,并预见变化,而不是固化复杂模式。

从根目录运行测试:

go test -v './...'
创建拉取请求

分叉此仓库并创建一个新分支:

git checkout -b my-branch

进行更改并提交:

git add . && git commit -m "My changes"

将更改推送到你的分叉:

git push origin my-branch

如有任何疑问,欢迎在 GitHub issue 或讨论区中联系!

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。