feat: complete create + publish post flow via MCP and REST API
Lets ChatGPT (MCP) and external clients (REST API) drive the full lifecycle of
a post — create with platform selection, attach media from URLs, schedule or
publish immediately, and fetch engagement metrics — without touching the web UI.
MCP tools added: UpdatePostTool, PublishPostTool, AttachMediaFromUrlTool,
ListContentTypesTool, GetPostMetricsTool, PreviewPostTool. CreatePostTool now
accepts platforms[] + scheduled_at + label_ids; ListPostsTool gains
status/search/limit filters.
REST endpoints added: POST /api/posts/{post}/media, GET /api/posts/{post}/metrics,
GET /api/posts/{post}/preview, GET /api/content-types.
Also fixes a silent CreatePost::execute bug — the action validated platforms[]
but ignored it, so REST callers never saw their selection persisted. Adds cross
validation rules (ContentTypeMatchesPlatform / ContentTypeMatchesPostPlatform)
so a LinkedIn account can't be saddled with x_post, and rejects inactive social
accounts during validation instead of failing silently downstream.
Shared services (PostMetricsFetcher, PostPreviewer, MediaAttacher) back both
MCP tools and REST controllers so behaviour stays aligned. New Resources
(PlatformContentTypesResource, PostMetricsResource, PostPreviewResource,
PostMediaAttachResource) keep controllers free of inline model mapping.
Suite: 1.332 passing, 0 failing — covers web (PostControllerTest), REST
(PostApiTest, PlatformApiTest, PostMediaApiTest), MCP (66 tool tests), and
the publish job (PublishToSocialPlatformTest).
Removes /docs from git tracking and TIKTOK_REVIEW_VIDEO_SCRIPT.md.
2026-05-04 11:12:28 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
|
|
beforeEach(function () {
|
|
|
|
|
$result = createApiTestToken();
|
|
|
|
|
$this->user = $result['user'];
|
|
|
|
|
$this->workspace = $result['workspace'];
|
|
|
|
|
$this->plainToken = $result['plain_token'];
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('lists content types per platform', function () {
|
2026-07-25 00:21:39 +00:00
|
|
|
$response = $this->withHeaders(['Authorization' => 'Bearer '.$this->plainToken])
|
feat: complete create + publish post flow via MCP and REST API
Lets ChatGPT (MCP) and external clients (REST API) drive the full lifecycle of
a post — create with platform selection, attach media from URLs, schedule or
publish immediately, and fetch engagement metrics — without touching the web UI.
MCP tools added: UpdatePostTool, PublishPostTool, AttachMediaFromUrlTool,
ListContentTypesTool, GetPostMetricsTool, PreviewPostTool. CreatePostTool now
accepts platforms[] + scheduled_at + label_ids; ListPostsTool gains
status/search/limit filters.
REST endpoints added: POST /api/posts/{post}/media, GET /api/posts/{post}/metrics,
GET /api/posts/{post}/preview, GET /api/content-types.
Also fixes a silent CreatePost::execute bug — the action validated platforms[]
but ignored it, so REST callers never saw their selection persisted. Adds cross
validation rules (ContentTypeMatchesPlatform / ContentTypeMatchesPostPlatform)
so a LinkedIn account can't be saddled with x_post, and rejects inactive social
accounts during validation instead of failing silently downstream.
Shared services (PostMetricsFetcher, PostPreviewer, MediaAttacher) back both
MCP tools and REST controllers so behaviour stays aligned. New Resources
(PlatformContentTypesResource, PostMetricsResource, PostPreviewResource,
PostMediaAttachResource) keep controllers free of inline model mapping.
Suite: 1.332 passing, 0 failing — covers web (PostControllerTest), REST
(PostApiTest, PlatformApiTest, PostMediaApiTest), MCP (66 tool tests), and
the publish job (PublishToSocialPlatformTest).
Removes /docs from git tracking and TIKTOK_REVIEW_VIDEO_SCRIPT.md.
2026-05-04 11:12:28 +00:00
|
|
|
->getJson(route('api.content-types'))
|
|
|
|
|
->assertOk()
|
|
|
|
|
->assertJsonStructure([
|
|
|
|
|
'platforms' => [
|
|
|
|
|
'*' => [
|
|
|
|
|
'platform',
|
|
|
|
|
'label',
|
|
|
|
|
'max_content_length',
|
|
|
|
|
'recommended_content_length',
|
|
|
|
|
'allowed_media_types',
|
|
|
|
|
'default_content_type',
|
|
|
|
|
'content_types' => [
|
2026-07-25 00:21:39 +00:00
|
|
|
'*' => [
|
|
|
|
|
'value',
|
|
|
|
|
'label',
|
|
|
|
|
'description',
|
|
|
|
|
'max_media_count',
|
2026-07-25 02:51:10 +00:00
|
|
|
'min_media_count',
|
2026-07-25 00:21:39 +00:00
|
|
|
'requires_media',
|
2026-07-25 02:51:10 +00:00
|
|
|
'accept_images',
|
|
|
|
|
'accept_videos',
|
|
|
|
|
'accept_documents',
|
|
|
|
|
'accepts_gif',
|
|
|
|
|
'forbids_mixed_media',
|
2026-07-25 00:21:39 +00:00
|
|
|
'max_video_duration_sec',
|
2026-07-25 01:01:48 +00:00
|
|
|
'max_image_bytes',
|
|
|
|
|
'max_video_bytes',
|
|
|
|
|
'max_document_bytes',
|
2026-07-25 00:21:39 +00:00
|
|
|
],
|
feat: complete create + publish post flow via MCP and REST API
Lets ChatGPT (MCP) and external clients (REST API) drive the full lifecycle of
a post — create with platform selection, attach media from URLs, schedule or
publish immediately, and fetch engagement metrics — without touching the web UI.
MCP tools added: UpdatePostTool, PublishPostTool, AttachMediaFromUrlTool,
ListContentTypesTool, GetPostMetricsTool, PreviewPostTool. CreatePostTool now
accepts platforms[] + scheduled_at + label_ids; ListPostsTool gains
status/search/limit filters.
REST endpoints added: POST /api/posts/{post}/media, GET /api/posts/{post}/metrics,
GET /api/posts/{post}/preview, GET /api/content-types.
Also fixes a silent CreatePost::execute bug — the action validated platforms[]
but ignored it, so REST callers never saw their selection persisted. Adds cross
validation rules (ContentTypeMatchesPlatform / ContentTypeMatchesPostPlatform)
so a LinkedIn account can't be saddled with x_post, and rejects inactive social
accounts during validation instead of failing silently downstream.
Shared services (PostMetricsFetcher, PostPreviewer, MediaAttacher) back both
MCP tools and REST controllers so behaviour stays aligned. New Resources
(PlatformContentTypesResource, PostMetricsResource, PostPreviewResource,
PostMediaAttachResource) keep controllers free of inline model mapping.
Suite: 1.332 passing, 0 failing — covers web (PostControllerTest), REST
(PostApiTest, PlatformApiTest, PostMediaApiTest), MCP (66 tool tests), and
the publish job (PublishToSocialPlatformTest).
Removes /docs from git tracking and TIKTOK_REVIEW_VIDEO_SCRIPT.md.
2026-05-04 11:12:28 +00:00
|
|
|
],
|
|
|
|
|
],
|
|
|
|
|
],
|
|
|
|
|
]);
|
2026-07-25 00:21:39 +00:00
|
|
|
|
|
|
|
|
$platforms = collect($response->json('platforms'));
|
|
|
|
|
$instagramTypes = collect($platforms->firstWhere('platform', 'instagram')['content_types']);
|
|
|
|
|
$facebookTypes = collect($platforms->firstWhere('platform', 'facebook')['content_types']);
|
2026-07-25 02:51:10 +00:00
|
|
|
$pinterestTypes = collect($platforms->firstWhere('platform', 'pinterest')['content_types']);
|
2026-07-25 00:21:39 +00:00
|
|
|
|
|
|
|
|
expect($instagramTypes->firstWhere('value', 'instagram_reel')['max_video_duration_sec'])->toBe(900);
|
2026-07-25 01:01:48 +00:00
|
|
|
expect($instagramTypes->firstWhere('value', 'instagram_reel')['max_video_bytes'])->toBe(1 * 1024 * 1024 * 1024);
|
2026-07-25 02:51:10 +00:00
|
|
|
expect($instagramTypes->firstWhere('value', 'instagram_reel')['accept_images'])->toBeFalse();
|
2026-07-25 00:21:39 +00:00
|
|
|
expect($facebookTypes->firstWhere('value', 'facebook_reel')['max_video_duration_sec'])->toBe(90);
|
2026-07-25 02:51:10 +00:00
|
|
|
expect($pinterestTypes->firstWhere('value', 'pinterest_carousel')['min_media_count'])->toBe(2);
|
|
|
|
|
expect($pinterestTypes->firstWhere('value', 'pinterest_pin')['min_media_count'])->toBe(0);
|
feat: complete create + publish post flow via MCP and REST API
Lets ChatGPT (MCP) and external clients (REST API) drive the full lifecycle of
a post — create with platform selection, attach media from URLs, schedule or
publish immediately, and fetch engagement metrics — without touching the web UI.
MCP tools added: UpdatePostTool, PublishPostTool, AttachMediaFromUrlTool,
ListContentTypesTool, GetPostMetricsTool, PreviewPostTool. CreatePostTool now
accepts platforms[] + scheduled_at + label_ids; ListPostsTool gains
status/search/limit filters.
REST endpoints added: POST /api/posts/{post}/media, GET /api/posts/{post}/metrics,
GET /api/posts/{post}/preview, GET /api/content-types.
Also fixes a silent CreatePost::execute bug — the action validated platforms[]
but ignored it, so REST callers never saw their selection persisted. Adds cross
validation rules (ContentTypeMatchesPlatform / ContentTypeMatchesPostPlatform)
so a LinkedIn account can't be saddled with x_post, and rejects inactive social
accounts during validation instead of failing silently downstream.
Shared services (PostMetricsFetcher, PostPreviewer, MediaAttacher) back both
MCP tools and REST controllers so behaviour stays aligned. New Resources
(PlatformContentTypesResource, PostMetricsResource, PostPreviewResource,
PostMediaAttachResource) keep controllers free of inline model mapping.
Suite: 1.332 passing, 0 failing — covers web (PostControllerTest), REST
(PostApiTest, PlatformApiTest, PostMediaApiTest), MCP (66 tool tests), and
the publish job (PublishToSocialPlatformTest).
Removes /docs from git tracking and TIKTOK_REVIEW_VIDEO_SCRIPT.md.
2026-05-04 11:12:28 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('rejects content-types without auth', function () {
|
|
|
|
|
$this->getJson(route('api.content-types'))->assertUnauthorized();
|
|
|
|
|
});
|