| 120 | } |
| 121 | |
| 122 | func withPanicRecovery[T any]( |
| 123 | toolName string, |
| 124 | handler func(context.Context, *mcp.CallToolRequest, T) (*mcp.CallToolResult, any, error), |
| 125 | ) func(context.Context, *mcp.CallToolRequest, T) (*mcp.CallToolResult, any, error) { |
| 126 | |
| 127 | return func(ctx context.Context, req *mcp.CallToolRequest, args T) (result *mcp.CallToolResult, resp any, err error) { |
| 128 | defer func() { |
| 129 | if r := recover(); r != nil { |
| 130 | logrus.WithFields(logrus.Fields{ |
| 131 | "tool": toolName, |
| 132 | "panic": r, |
| 133 | }).Error("Tool handler panicked") |
| 134 | |
| 135 | logrus.Errorf("Stack trace:\n%s", debug.Stack()) |
| 136 | |
| 137 | result = &mcp.CallToolResult{ |
| 138 | Content: []mcp.Content{ |
| 139 | &mcp.TextContent{ |
| 140 | Text: fmt.Sprintf("工具 %s 执行时发生内部错误: %v\n\n请查看服务端日志获取详细信息。", toolName, r), |
| 141 | }, |
| 142 | }, |
| 143 | IsError: true, |
| 144 | } |
| 145 | resp = nil |
| 146 | err = nil |
| 147 | } |
| 148 | }() |
| 149 | |
| 150 | return handler(ctx, req, args) |
| 151 | } |
| 152 | } |
| 153 | |
| 154 | // registerTools 注册所有 MCP 工具 |
| 155 | func registerTools(server *mcp.Server, appServer *AppServer) { |