trypost/app/Mcp/Tools/Post/CreatePostTool.php

66 lines
2.9 KiB
PHP
Raw Normal View History

<?php
declare(strict_types=1);
namespace App\Mcp\Tools\Post;
use App\Actions\Post\CreatePost;
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
use App\Enums\PostPlatform\ContentType;
use App\Http\Resources\Api\PostResource;
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
use App\Rules\ContentTypeMatchesPlatform;
use Illuminate\Contracts\JsonSchema\JsonSchema;
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
use Illuminate\Validation\Rule;
use Laravel\Mcp\Request;
use Laravel\Mcp\Response;
use Laravel\Mcp\ResponseFactory;
use Laravel\Mcp\Server\Attributes\Description;
use Laravel\Mcp\Server\Tool;
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
#[Description('Create a draft post in the current workspace. Accepts content, scheduled_at, label_ids, and a list of platforms (social accounts to publish on, with their content_type). Use list-content-types-tool to discover valid content_types per platform.')]
class CreatePostTool extends Tool
{
public function handle(Request $request): ResponseFactory
{
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
$workspace = $request->user()->currentWorkspace;
$validated = $request->validate([
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
'content' => ['nullable', 'string', 'max:63206'],
'scheduled_at' => ['nullable', 'date', 'after:now'],
'label_ids' => ['sometimes', 'array'],
'label_ids.*' => ['uuid', Rule::exists('workspace_labels', 'id')->where('workspace_id', $workspace->id)],
'platforms' => ['sometimes', 'array'],
'platforms.*.social_account_id' => [
'required',
'uuid',
Rule::exists('social_accounts', 'id')
->where('workspace_id', $workspace->id)
->where('is_active', true),
],
'platforms.*.content_type' => ['required', 'string', Rule::in(array_column(ContentType::cases(), 'value')), new ContentTypeMatchesPlatform],
]);
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
$post = CreatePost::execute($workspace, $request->user(), $validated);
$post->load(['postPlatforms.socialAccount', 'labels']);
return Response::structured((new PostResource($post))->resolve());
}
public function schema(JsonSchema $schema): array
{
return [
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
'content' => $schema->string()->description('The post caption/text body. Optional — can be edited later.'),
'scheduled_at' => $schema->string()->description('ISO 8601 datetime in the future (e.g. 2026-05-10T15:30:00Z). Defaults to today at 09:00 UTC.'),
'label_ids' => $schema->array()
->items($schema->string())
->description('Workspace label IDs to attach to the post.'),
'platforms' => $schema->array()
->items($schema->object(fn ($p) => [
'social_account_id' => $p->string()->required()->description('UUID of the connected social account.'),
'content_type' => $p->string()->required()->description('Format for this platform (e.g. linkedin_post, x_post, instagram_feed).'),
]))
->description('Platforms to publish on. Accounts not listed remain available but disabled.'),
];
}
}