component.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. package mcp
  2. import (
  3. "context"
  4. "dbview/service/internal/common/logger"
  5. "github.com/mark3labs/mcp-go/mcp"
  6. "github.com/mark3labs/mcp-go/server"
  7. "go.uber.org/zap"
  8. )
  9. // Config MCP 组件配置(可按需扩展,例如新增 SSE/WS 等传输层参数)。
  10. // 目前仅提供名称/版本控制与开关。
  11. // 若未来需要从全局配置加载,可在 bootstrap 层读取后传入。
  12. type Config struct {
  13. Enable bool // 是否启用 MCP 服务
  14. ServerName string // MCP Server 名称(展示给客户端)
  15. ServerVersion string // MCP Server 版本
  16. }
  17. // DefaultConfig 提供一个安全的默认值(关闭状态)。
  18. func DefaultConfig() Config {
  19. return Config{
  20. Enable: false,
  21. ServerName: "dbview-mcp",
  22. ServerVersion: "0.1.0",
  23. }
  24. }
  25. // Component 封装 mcp-go Server,便于在项目内统一注册工具、启动 Stdio 服务。
  26. type Component struct {
  27. cfg Config
  28. server *server.MCPServer
  29. logger logger.Logger
  30. }
  31. // NewComponent 创建 MCP 组件;仅注册 Server 与 Logger,不启动。
  32. func NewComponent(cfg Config, logger logger.Logger) *Component {
  33. if cfg.ServerName == "" {
  34. cfg.ServerName = "dbview-mcp"
  35. }
  36. if cfg.ServerVersion == "" {
  37. cfg.ServerVersion = "0.1.0"
  38. }
  39. return &Component{
  40. cfg: cfg,
  41. server: server.NewMCPServer(cfg.ServerName, cfg.ServerVersion),
  42. logger: logger,
  43. }
  44. }
  45. // RegisterHealthTool 注册一个内置健康检查工具,便于客户端验证 MCP 连接。
  46. func (c *Component) RegisterHealthTool() {
  47. healthTool := mcp.NewTool("health",
  48. mcp.WithDescription("返回 MCP 服务健康状态"),
  49. )
  50. c.server.AddTool(healthTool, func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
  51. return &mcp.CallToolResult{
  52. Content: []mcp.Content{mcp.TextContent{Text: "ok"}},
  53. }, nil
  54. })
  55. }
  56. // RegisterEchoTool 注册一个示例工具,可用于调试与演示。
  57. // 参数:message(string,可选),返回与输入一致的文本。
  58. func (c *Component) RegisterEchoTool() {
  59. echoTool := mcp.NewTool("echo",
  60. mcp.WithDescription("回显传入的 message 文本"),
  61. mcp.WithString("message", mcp.Description("要回显的文本")),
  62. )
  63. c.server.AddTool(echoTool, func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
  64. args, _ := req.Params.Arguments.(map[string]any)
  65. msg, _ := args["message"].(string)
  66. if msg == "" {
  67. msg = "(empty)"
  68. }
  69. return &mcp.CallToolResult{
  70. Content: []mcp.Content{mcp.TextContent{Text: msg}},
  71. }, nil
  72. })
  73. }
  74. // Server 返回底层 MCPServer,便于外部注册自定义工具。
  75. func (c *Component) Server() *server.MCPServer {
  76. return c.server
  77. }
  78. // ServeStdio 启动基于 stdio 的 MCP 服务(常用于被 IDE/CLI 以子进程方式拉起)。
  79. func (c *Component) ServeStdio(ctx context.Context) error {
  80. if !c.cfg.Enable {
  81. c.logger.Warn("MCP 组件未启用,跳过 ServeStdio")
  82. return nil
  83. }
  84. c.logger.Info("启动 MCP Stdio 服务", zap.String("server", c.cfg.ServerName), zap.String("version", c.cfg.ServerVersion))
  85. // mcp-go 当前 Stdio Server 不接受外部 Context;如需退出,可由调用方中断进程。
  86. return server.ServeStdio(c.server)
  87. }