trypost/tests/Feature/Mcp/RequestMediaUploadToolTest.php
Paulo Castellano 564f157e44 Fix MCP upload rate limits and Instagram Reel duration caps.
Key signed uploads by workspace so ChatGPT's shared egress IPs don't throttle tenants together, raise the MCP upload cap to 300MB, and expose accurate Reel max durations via API/MCP.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 21:21:39 -03:00

72 lines
2.3 KiB
PHP

<?php
declare(strict_types=1);
use App\Enums\UserWorkspace\Role;
use App\Mcp\Servers\TryPostServer;
use App\Mcp\Tools\Post\RequestMediaUploadTool;
use App\Models\User;
use App\Models\Workspace;
use Illuminate\Support\Facades\URL;
use Illuminate\Testing\Fluent\AssertableJson;
beforeEach(function () {
$this->user = User::factory()->create();
$this->workspace = Workspace::factory()->create(['user_id' => $this->user->id]);
$this->workspace->members()->attach($this->user->id, ['role' => Role::Member->value]);
$this->user->update(['current_workspace_id' => $this->workspace->id]);
});
test('returns a single-use signed upload URL', function () {
$response = TryPostServer::actingAs($this->user)
->tool(RequestMediaUploadTool::class, []);
$response->assertOk()
->assertStructuredContent(function (AssertableJson $json) {
$json->has('upload_token')
->has('upload_url')
->has('expires_at')
->where('max_bytes', 300 * 1024 * 1024)
->where('field_name', 'media')
->etc();
});
});
test('signed URL is valid against the api.uploads.store route', function () {
$uploadUrl = null;
TryPostServer::actingAs($this->user)
->tool(RequestMediaUploadTool::class, [])
->assertOk()
->assertStructuredContent(function (AssertableJson $json) use (&$uploadUrl) {
$json->etc();
$uploadUrl = $json->toArray()['upload_url'];
});
expect(URL::hasValidSignature(
request()->create($uploadUrl, 'POST'),
))->toBeTrue();
});
test('each call returns a distinct upload_token', function () {
$firstToken = null;
$secondToken = null;
TryPostServer::actingAs($this->user)
->tool(RequestMediaUploadTool::class, [])
->assertOk()
->assertStructuredContent(function (AssertableJson $json) use (&$firstToken) {
$json->etc();
$firstToken = $json->toArray()['upload_token'];
});
TryPostServer::actingAs($this->user)
->tool(RequestMediaUploadTool::class, [])
->assertOk()
->assertStructuredContent(function (AssertableJson $json) use (&$secondToken) {
$json->etc();
$secondToken = $json->toArray()['upload_token'];
});
expect($firstToken)->not->toBe($secondToken);
});