feat: media upload by URL and base64 with whitelist and size limit

MediaImporter streams URL imports via wp_safe_remote_get with limit_response_size,
checks Content-Length, intersects the MIME whitelist with get_allowed_mime_types and
validates real content; base64 is size-checked before decoding. Server-side failures
are write_failed; a failed alt text deletes the new attachment again (or partial_write).
MediaUploads is the shared permission/result helper of both upload abilities.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
This commit is contained in:
2026-09-26 02:37:43 +02:00
co-authored by Claude Opus 5.5
parent f027da1785
commit 2e29a6cd4d
9 changed files with 1086 additions and 4 deletions
+6 -2
View File
@@ -10,8 +10,8 @@ use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
use LIT\MCP\Limits;
/**
* Media library tools (spec §6.3). Always available. $log and $limits are used by the
* write tools that follow (upload, update, delete).
* Media library tools (spec §6.3). Always available. $log and $limits serve the write
* tools (upload now, update and delete to follow).
*/
final class MediaIntegration implements Integration
{
@@ -33,11 +33,15 @@ final class MediaIntegration implements Integration
{
$presenter = new MediaPresenter();
$finder = new MediaUsageFinder(fn (): array => $this->schema->mediaFieldKeys());
$importer = new MediaImporter($this->limits);
$uploads = new MediaUploads($presenter, $this->log, $this->schema);
return [
new MediaSearchAbility($presenter, $finder),
new MediaGetAbility($presenter, $finder),
new MediaPreviewAbility(),
new MediaUploadFromUrlAbility($importer, $uploads),
new MediaUploadAbility($importer, $uploads, $this->limits),
new MediaDownloadAbility($this->limits),
];
}