mirror of
https://github.com/mindoc-org/mindoc.git
synced 2025-10-07 16:13:51 +08:00
feat: 新增MCP Server功能,支持文档全局检索工具 (#1010)
* feat: i18n国际化语言支持完全可配置,并新增俄语支持 * feat: 新增MCP Server功能,支持文档全局检索工具
This commit is contained in:
68
mcp/handler.go
Normal file
68
mcp/handler.go
Normal 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
30
mcp/mcp.go
Normal 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
22
mcp/middleware.go
Normal 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))
|
||||
}
|
Reference in New Issue
Block a user