feat: 新增MCP Server功能,支持文档全局检索工具 (#1010)
Some checks failed
Go / Ubuntu Latest GCC (push) Has been cancelled
Go / Windows Latest MSVC (push) Has been cancelled

* feat: i18n国际化语言支持完全可配置,并新增俄语支持

* feat: 新增MCP Server功能,支持文档全局检索工具
This commit is contained in:
nl8590687
2025-09-22 17:57:05 +08:00
committed by GitHub
parent b9f13815e8
commit df09353563
9 changed files with 177 additions and 6 deletions

68
mcp/handler.go Normal file
View File

@@ -0,0 +1,68 @@
package mcp
import (
"context"
"encoding/json"
"github.com/mark3labs/mcp-go/mcp"
"github.com/mindoc-org/mindoc/conf"
"github.com/mindoc-org/mindoc/models"
"github.com/mindoc-org/mindoc/utils/sqltil"
)
// GetGlobalSearchMcpTool 获取全局搜索的mcp工具
func GetGlobalSearchMcpTool() mcp.Tool {
return mcp.NewTool("MinDocGlobalSearch",
mcp.WithDescription("MinDoc全局文档内容搜索"),
mcp.WithString("keyword",
mcp.Required(),
mcp.Description("要执行全局搜索的关键词,多个搜索关键词请用空格分割,请使用最少的关键词来检索,结果中只会出现包含全部关键词的结果,过多的无关词会导致更少的检索结果"),
),
mcp.WithNumber("pageIndex",
mcp.Required(),
mcp.Description("全局搜索时指定分页的顺序下标每页最多有10条结果建议只查看1-10页文档内容的搜索结果"),
mcp.Enum("1", "2", "3", "4", "5", "6", "7", "8", "9", "10"),
),
)
}
// GlobalSearchMcpHandler 全局搜索的mcp处理函数
func GlobalSearchMcpHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
paramMap := request.Params.Arguments.(map[string]any)
pageIndex := 1
if v, ok := paramMap["pageIndex"].(float64); ok {
pageIndex = int(v)
}
totalCount, result := globalSearchFunction(paramMap["keyword"].(string), pageIndex)
jsonContent, err := json.Marshal(result)
if err != nil {
return mcp.NewToolResultStructuredOnly(map[string]any{
"totalCount": 0,
"result": make([]map[string]any, 0),
}), err
}
structContent := make([]map[string]any, 0)
err = json.Unmarshal(jsonContent, &structContent)
if err != nil {
return mcp.NewToolResultStructuredOnly(map[string]any{
"totalCount": 0,
"result": make([]map[string]any, 0),
}), err
}
return mcp.NewToolResultStructuredOnly(map[string]any{
"totalCount": totalCount,
"result": structContent,
}), nil
}
func globalSearchFunction(keyword string, pageIndex int) (int, []*models.DocumentSearchResult) {
memberId := 0
searchResult, totalCount, err := models.NewDocumentSearchResult().FindToPager(sqltil.EscapeLike(keyword),
pageIndex, conf.PageSize, memberId)
if err != nil {
return 0, make([]*models.DocumentSearchResult, 0)
}
return totalCount, searchResult
}

30
mcp/mcp.go Normal file
View File

@@ -0,0 +1,30 @@
package mcp
import (
"github.com/mark3labs/mcp-go/server"
)
// MCPServer MinDoc MCP Server
type MCPServer struct {
server *server.MCPServer
}
// NewMCPServer creates a new MinDoc MCP Server
func NewMCPServer() *MCPServer {
mcpServer := server.NewMCPServer(
"MinDoc MCP Server",
"1.0.0",
server.WithRecovery(),
)
mcpServer.AddTool(GetGlobalSearchMcpTool(), GlobalSearchMcpHandler)
return &MCPServer{
server: mcpServer,
}
}
// ServeHTTP Run starts the server
func (s *MCPServer) ServeHTTP() *server.StreamableHTTPServer {
return server.NewStreamableHTTPServer(s.server)
}

22
mcp/middleware.go Normal file
View File

@@ -0,0 +1,22 @@
package mcp
import (
"context"
"net/http"
"github.com/beego/beego/v2/server/web"
beegoContext "github.com/beego/beego/v2/server/web/context"
)
// AuthMiddleware 返回一个中间件函数用于验证MCP请求中的认证令牌
func AuthMiddleware(ctx *beegoContext.Context) {
presetMcpApiKey := web.AppConfig.DefaultString("mcp_api_key", "")
mcpApiKeyParamValue := ctx.Request.URL.Query().Get("api_key")
if presetMcpApiKey != mcpApiKeyParamValue {
http.Error(ctx.ResponseWriter, "Missing or invalid mcp authorization key", http.StatusUnauthorized)
return
}
// Add mcp_api_key to request context
ctx.Request.WithContext(context.WithValue(ctx.Request.Context(), "mcp_api_key", mcpApiKeyParamValue))
}