Add first-party Etsy MCP server for shop listings, orders and messages

Expose php artisan etsy:mcp as JSON-RPC stdio next to laravel-boost, reuse the stored HickLab3D shop connection, create listings as drafts only, and skip Etsy v3 conversation send because that API does not exist.
This commit is contained in:
2026-11-07 15:54:05 +00:00
parent ab1fdb961f
commit 9b13640571
11 changed files with 1294 additions and 19 deletions
+4 -3
View File
@@ -33,7 +33,7 @@ class IntegrationsTest extends TestCase
{
Http::preventStrayRequests();
Http::fake([
'https://api.etsy.com/v3/public/oauth/token' => Http::response(['access_token' => '123.token', 'refresh_token' => '123.refresh', 'expires_in' => 3600]),
'https://api.etsy.com/v3/public/oauth/token' => Http::response(['access_token' => '123.token', 'refresh_token' => '123.refresh', 'expires_in' => 3600, 'scope' => 'listings_r listings_w transactions_r transactions_w shops_r']),
'https://api.etsy.com/v3/application/users/123/shops' => Http::response(['shop_id' => 42, 'shop_name' => 'HickLab3D']),
'https://api.etsy.com/v3/application/shops/42/receipts*' => Http::response(['results' => [['receipt_id' => 77, 'name' => 'Buyer']]]),
'https://api.etsy.com/v3/application/shops/42/listings*' => Http::response(['results' => [['title' => '3D print', 'quantity' => 5]]]),
@@ -47,6 +47,7 @@ class IntegrationsTest extends TestCase
$connection = EtsyConnection::firstOrFail();
$this->assertSame('123.token', $connection->access_token);
$this->assertNotSame('123.token', $connection->getRawOriginal('access_token'));
$this->assertSame('listings_r listings_w transactions_r transactions_w shops_r', $connection->scopes);
$this->actingAs($admin)->get(route('etsy.index'))->assertOk()->assertSee('3D print')->assertSee('#77');
Http::assertSentCount(4);
}
@@ -242,11 +243,11 @@ class IntegrationsTest extends TestCase
'shipping_receipt_id' => 77,
'shipping_selected_service' => 'evri-collection',
'shipping_quotes' => [['Service' => ['Slug' => 'evri-collection', 'CollectionType' => 'Collection']]],
'shipping_collection_dates' => [['CollectionDate' => '2026-10-15T10:00:00Z']],
'shipping_collection_dates' => [['CollectionDate' => $collectionDate = now()->addDay()->utc()->format('Y-m-d\TH:i:s\Z')]],
'shipping_sender_location' => ['sender_street' => 'Main Street', 'sender_town' => 'London'],
];
$booking = [
'collection_date' => '2026-10-15T10:00:00Z',
'collection_date' => $collectionDate,
'sender_name' => 'Lee Hickman', 'sender_email' => 'lee@example.test', 'sender_phone' => '07123456789',
'sender_property' => '1', 'sender_street' => 'Main Street', 'sender_town' => 'London',
'recipient_name' => 'Buyer Name', 'recipient_email' => 'buyer@example.test', 'recipient_phone' => '07123456788',