(text string)
| 435 | } |
| 436 | |
| 437 | func (t *MCPTool) persistLargeTextArtifact(text string) *ToolResult { |
| 438 | text = strings.TrimSpace(text) |
| 439 | limit := t.maxInlineTextRunes |
| 440 | if limit <= 0 { |
| 441 | limit = maxMCPInlineTextRunes |
| 442 | } |
| 443 | size := utf8.RuneCountInString(text) |
| 444 | if text == "" || size <= limit || t.workspace == "" { |
| 445 | return nil |
| 446 | } |
| 447 | |
| 448 | dir := filepath.Join(t.workspace, ".artifacts", "mcp") |
| 449 | if err := os.MkdirAll(dir, 0o700); err != nil { |
| 450 | return t.largeTextArtifactFallback(text, err) |
| 451 | } |
| 452 | // TODO: Add lifecycle cleanup/retention for MCP artifact files. |
| 453 | |
| 454 | pattern := fmt.Sprintf( |
| 455 | "%s_%s_*.txt", |
| 456 | sanitizeIdentifierComponent(t.serverName), |
| 457 | sanitizeIdentifierComponent(t.tool.Name), |
| 458 | ) |
| 459 | tmpFile, err := os.CreateTemp(dir, pattern) |
| 460 | if err != nil { |
| 461 | return t.largeTextArtifactFallback(text, err) |
| 462 | } |
| 463 | path := tmpFile.Name() |
| 464 | if _, err = tmpFile.WriteString(text); err != nil { |
| 465 | _ = tmpFile.Close() |
| 466 | _ = os.Remove(path) |
| 467 | return t.largeTextArtifactFallback(text, err) |
| 468 | } |
| 469 | if err = tmpFile.Close(); err != nil { |
| 470 | _ = os.Remove(path) |
| 471 | return t.largeTextArtifactFallback(text, err) |
| 472 | } |
| 473 | |
| 474 | return &ToolResult{ |
| 475 | ForLLM: fmt.Sprintf( |
| 476 | "[MCP returned a large text result (%d chars); omitted from model context and saved as a local artifact.]", |
| 477 | size, |
| 478 | ), |
| 479 | ArtifactTags: []string{"[file:" + path + "]"}, |
| 480 | } |
| 481 | } |
| 482 | |
| 483 | func (t *MCPTool) largeTextArtifactFallback(text string, err error) *ToolResult { |
| 484 | size := utf8.RuneCountInString(text) |
no test coverage detected