file.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. package storage
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/mark3labs/mcp-go/mcp"
  6. "github.com/mark3labs/mcp-go/server"
  7. "fwh-toolbox-server/cmd/mcp/tools/helper"
  8. "fwh-toolbox-server/utils/filestore"
  9. )
  10. // mcpFileStore MCP 专用的文件存储实例
  11. var mcpFileStore *filestore.FileStore
  12. // InitFileStore 初始化 MCP FileStore(由 main.go 调用)
  13. func InitFileStore(fs *filestore.FileStore) {
  14. mcpFileStore = fs
  15. }
  16. // GetFileStore 获取 MCP FileStore 实例
  17. func GetFileStore() *filestore.FileStore {
  18. return mcpFileStore
  19. }
  20. func registerFileTools(s *server.MCPServer) {
  21. s.AddTool(
  22. mcp.NewTool("storage_file_read",
  23. mcp.WithDescription("读取用户上传的文件内容。用户通过前端上传的文件存储在 /uploads/ 路径下。"),
  24. mcp.WithString("path", mcp.Required(), mcp.Description("文件路径,格式为 /uploads/{filename}")),
  25. ),
  26. handleFileRead,
  27. )
  28. s.AddTool(
  29. mcp.NewTool("storage_file_write",
  30. mcp.WithDescription("将文本内容写入文件存储(MinIO)。可用于保存分析结果、生成报告等。文件路径会自动添加 /uploads/ 前缀。"),
  31. mcp.WithString("path", mcp.Required(), mcp.Description("文件路径,格式为 /uploads/{filename}(如 /uploads/report.csv)")),
  32. mcp.WithString("content", mcp.Required(), mcp.Description("要写入的文本内容")),
  33. mcp.WithString("userId", mcp.Description("用户标识,用于文件路径隔离(尽量填写,不传则使用默认值 mcp-agent)")),
  34. mcp.WithString("sessionId", mcp.Description("会话标识,用于文件路径隔离(尽量填写,不传则使用默认值 mcp-session)")),
  35. ),
  36. handleFileWrite,
  37. )
  38. s.AddTool(
  39. mcp.NewTool("storage_file_list",
  40. mcp.WithDescription("列出当前会话中用户上传的所有文件,返回文件名、路径、大小等信息。"),
  41. ),
  42. handleFileList,
  43. )
  44. }
  45. func handleFileRead(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
  46. path, err := req.RequireString("path")
  47. if err != nil {
  48. return helper.ParamError("path"), nil
  49. }
  50. if mcpFileStore == nil {
  51. return helper.ServiceError("文件存储", fmt.Errorf("未初始化")), nil
  52. }
  53. if !mcpFileStore.HasFile(path) {
  54. return helper.EmptyResult(fmt.Sprintf("文件不存在: %s", path)), nil
  55. }
  56. content, err := mcpFileStore.ReadFile(path)
  57. if err != nil {
  58. return helper.ServiceError("读取文件", err), nil
  59. }
  60. return helper.TextResult(content), nil
  61. }
  62. func handleFileList(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
  63. if mcpFileStore == nil {
  64. return helper.ServiceError("文件存储", fmt.Errorf("未初始化")), nil
  65. }
  66. files := mcpFileStore.GetFiles()
  67. if len(files) == 0 {
  68. return helper.EmptyResult("当前没有上传的文件"), nil
  69. }
  70. return helper.JSONResult(files), nil
  71. }
  72. func handleFileWrite(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
  73. path, err := req.RequireString("path")
  74. if err != nil {
  75. return helper.ParamError("path"), nil
  76. }
  77. content, err := req.RequireString("content")
  78. if err != nil {
  79. return helper.ParamError("content"), nil
  80. }
  81. if mcpFileStore == nil {
  82. return helper.ServiceError("文件存储", fmt.Errorf("未初始化")), nil
  83. }
  84. userId := req.GetString("userId", "mcp-agent")
  85. sessionId := req.GetString("sessionId", "mcp-session")
  86. record, err := mcpFileStore.WriteFile(userId, sessionId, path, content)
  87. if err != nil {
  88. return helper.ServiceError("写入文件", err), nil
  89. }
  90. return helper.JSONResult(map[string]any{
  91. "message": "文件写入成功",
  92. "path": record.Path,
  93. "fileName": record.FileName,
  94. "size": record.Size,
  95. "key": record.Key,
  96. }), nil
  97. }