download_lesson_attachment deckte bisher nur die Leserichtung ab, der Nutzer legt Arbeitsblätter aber tatsächlich über die Anhang-Funktion an Einzelstunden ab. Neues Write-Tool nimmt Dateiname + Base64-Inhalt entgegen, validiert vor der Bestätigungsnachfrage (leer/ungültig/zu groß) und lädt erst nach Bestätigung hoch. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -180,6 +180,8 @@ public sealed class McpServerHostedService : IAsyncDisposable
|
||||
"Ändert eine Verlaufsplan-Phase einer Einzelstunde (Bestätigung durch den Nutzer nötig).");
|
||||
AddWriteTool(lessonPlanTools.RemoveLessonPhase, "remove_lesson_phase",
|
||||
"Entfernt eine Verlaufsplan-Phase aus einer Einzelstunde (Bestätigung durch den Nutzer nötig).");
|
||||
AddWriteTool(lessonPlanTools.AddLessonAttachment, "add_lesson_attachment",
|
||||
"Fügt einer Einzelstunde ein neues Material als Base64-kodierten Anhang hinzu (Bestätigung durch den Nutzer nötig).");
|
||||
|
||||
System.Diagnostics.Debug.Assert(
|
||||
toolCollection.Select(t => t.ProtocolTool.Name).OrderBy(n => n)
|
||||
|
||||
@@ -40,5 +40,6 @@ public static class McpToolScope
|
||||
"add_lesson_phase",
|
||||
"update_lesson_phase",
|
||||
"remove_lesson_phase",
|
||||
"add_lesson_attachment",
|
||||
];
|
||||
}
|
||||
|
||||
@@ -63,6 +63,42 @@ public class LessonPlanTools(
|
||||
return new AttachmentContentDto(attachment.FileName, attachment.SizeBytes, Convert.ToBase64String(buffer.ToArray()));
|
||||
}
|
||||
|
||||
[Description("Fügt einer Einzelstunde ein neues Material (z.B. ein von der KI erzeugtes Arbeitsblatt) als Anhang hinzu, Base64-kodiert. Muss der Nutzer erst bestätigen.")]
|
||||
public async Task<WriteResultDto> AddLessonAttachment(
|
||||
[Description("ID der Einzelstunde.")] Guid lessonId,
|
||||
[Description("Dateiname inkl. Endung, z.B. \"arbeitsblatt.pdf\".")] string fileName,
|
||||
[Description("Dateiinhalt, Base64-kodiert.")] string base64Content,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
var lesson = lessons.GetById(lessonId);
|
||||
if (lesson is null) return new WriteResultDto(false, null, "Unbekannte Stunden-ID.");
|
||||
|
||||
byte[] bytes;
|
||||
try { bytes = Convert.FromBase64String(base64Content); }
|
||||
catch (FormatException) { return new WriteResultDto(false, null, "Ungültiger Base64-Inhalt."); }
|
||||
|
||||
if (bytes.Length == 0) return new WriteResultDto(false, null, "Leerer Dateiinhalt.");
|
||||
if (bytes.Length > IAttachmentStorage.MaxSizeBytes)
|
||||
return new WriteResultDto(false, null,
|
||||
$"Datei ist mit {bytes.Length / 1024 / 1024} MB zu groß (Limit {IAttachmentStorage.MaxSizeBytes / 1024 / 1024} MB).");
|
||||
|
||||
var sizeDisplay = bytes.Length >= 1024 * 1024
|
||||
? $"{bytes.Length / 1024 / 1024} MB" : $"{Math.Max(1, bytes.Length / 1024)} KB";
|
||||
var message = $"„{fileName}“ ({sizeDisplay}) zu „{lesson.Topic}“ am {lesson.Date:dd.MM.yyyy} hinzufügen?";
|
||||
if (!await confirmation.ConfirmAsync("Material anhängen?", message, ct))
|
||||
return new WriteResultDto(false, null, "Vom Nutzer abgelehnt oder nicht bestätigt.");
|
||||
|
||||
string storageId;
|
||||
using (var stream = new MemoryStream(bytes)) storageId = attachments.Upload(fileName, stream);
|
||||
|
||||
lesson.Attachments.Add(new DocumentAttachment { StorageId = storageId, FileName = fileName, SizeBytes = bytes.Length });
|
||||
lessons.Save(lesson);
|
||||
// DocumentAttachment hat keine eigene Guid-Id (nur StorageId, ein string) - deshalb Id hier
|
||||
// null, storageId steht stattdessen in der Nachricht (für einen unmittelbaren Folgeaufruf,
|
||||
// z.B. download_lesson_attachment zur Bestätigung, ohne erst get_lesson_plans erneut aufzurufen).
|
||||
return new WriteResultDto(true, null, $"Anhang gespeichert (storageId={storageId}).");
|
||||
}
|
||||
|
||||
// ── Unterrichtseinheiten (Unit) ──────────────────────────────────────────────────────────
|
||||
|
||||
[Description("Legt eine neue Unterrichtseinheit an. Muss der Nutzer erst in einem Dialog in LehrerApp bestätigen.")]
|
||||
|
||||
Reference in New Issue
Block a user