Skip to content

Post platform meta (aspect ratio) parity across API and MCP#86

Merged
paulocastellano merged 2 commits into
mainfrom
feat/api-mcp-post-meta-parity
Jun 10, 2026
Merged

Post platform meta (aspect ratio) parity across API and MCP#86
paulocastellano merged 2 commits into
mainfrom
feat/api-mcp-post-meta-parity

Conversation

@paulocastellano

Copy link
Copy Markdown
Contributor

Follow-up to #82. That PR made meta.aspect_ratio crop Facebook (and already Instagram) feed images at publish time, but the API and MCP surfaces only half-supported it. This closes the three gaps so the feature behaves the same on every creation path.

Gaps closed

  1. Couldn't set meta on create. Api\StorePostRequest and MCP CreatePostTool accepted only social_account_id + content_type — you could only set aspect ratio via update. They now accept platforms.*.meta, and CreatePost persists it.
  2. Value wasn't validated. API/MCP accepted meta as a free-form array, so an invalid aspect_ratio (e.g. 3:2) slipped through and the publisher silently center-cropped to square. Now validated everywhere.
  3. No read-back. Api\PostPlatformResource (used by both API and MCP responses) exposed content_type but not meta, so clients never got the aspect ratio back. It now returns meta.

How

  • New App\Enums\PostPlatform\AspectRatio backed enum (1:1, 4:5, 16:9, original) — single source of truth.
  • App UpdatePostRequest, API Store/Update, and MCP Create/Update tools all validate via Rule::enum(AspectRatio::class) (replacing the inline Rule::in([...])).
  • CreatePost persists platforms.*.meta; MCP create documents meta in its schema.
  • Api\PostPlatformResource exposes meta.

No behavior change for the App editor (already worked); this brings API + MCP to the same place.

Tests

  • API: create with meta.aspect_ratio persists + is returned in the response; invalid ratio rejected on create and update.
  • MCP: create-post persists meta; invalid ratio rejected on create and update.

Full suite: 1703 passed, 2 skipped. Pint clean.

PR #82 made `meta.aspect_ratio` crop Facebook (and already Instagram) feed
images at publish time, but the API and MCP surfaces only half-supported it:
you couldn't set meta at creation, the value wasn't validated, and responses
never returned it. This closes those gaps.

- New `AspectRatio` enum is the single source of truth for the allowed ratios
  (1:1, 4:5, 16:9, original). App/API/MCP requests now validate via
  `Rule::enum(AspectRatio::class)` — an invalid ratio is rejected everywhere
  instead of silently center-cropping to square.
- API `StorePostRequest` and MCP `CreatePostTool` now accept `platforms.*.meta`;
  `CreatePost` persists it. MCP create documents `meta` in its schema.
- `Api\PostPlatformResource` now exposes `meta`, so API and MCP responses return
  the aspect_ratio (and other per-platform meta) a client set.
Review follow-ups:
- AspectRatio::toFloat() now owns the crop ratio math; CropsImageForAspectRatio
  delegates to it so the enum is the single source of truth for both validation
  and cropping (no more parallel literal map).
- API update controller now reloads postPlatforms before returning, so the
  update response reflects the persisted platform meta/content_type (was stale).
- Tests: AspectRatio enum unit test; API valid-update read-back + 'original'
  on create; MCP response read-back + valid update.
@paulocastellano paulocastellano merged commit 525cf5f into main Jun 10, 2026
2 checks passed
@paulocastellano paulocastellano deleted the feat/api-mcp-post-meta-parity branch June 10, 2026 19:06
paulocastellano added a commit that referenced this pull request Jun 10, 2026
Conflict resolutions + integration fixes:
- CreatePost: kept the branch's merge-into-existing meta persistence (equivalent
  to main's #86 replace on create, and what the automations flow was built on).
- FacebookSettings.vue: kept both new defaults (previewOnly + meta).
- RunGenerateNode + GenerateNodeConfig.vue: ContentType::InstagramCarousel was
  removed on main (#80); an IG carousel is now a multi-image instagram_feed, so
  the carousel-capable list uses InstagramFeed.
- GenerateNodeTest: fixtures use the ContentType enum and the new instagram_feed
  carousel signal.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant