Skip to content

feat: list media via public API and MCP mediaListTool - #1926

Open
giladresisi wants to merge 2 commits into
stagingfrom
feat/media-list
Open

giladresisi wants to merge 2 commits into
stagingfrom
feat/media-list

Conversation

@giladresisi

@giladresisi giladresisi commented Aug 19, 2026 •

Copy link
Copy Markdown
Collaborator

What kind of change does this PR introduce?

Feature

Why was this change needed?

An agency customer driving Postiz from the MCP had no way to discover media already uploaded to the library: the public API only exposed upload routes and the MCP only uploadFromUrlTool, so they copied URLs from the UI by hand.

Other information:

  • GET /public/v1/media?page=&search= (api-key guarded, Sentry public_api-request metric like the other routes) returns { pages, results } from the existing MediaService.getMedia (org-scoped, non-deleted, 18/page, newest first, case-insensitive originalName search).
  • New MCP/agent tool mediaListTool with the same input/output, registered in toolList, plus one system-prompt line telling the agent to reuse listed paths before asking for a URL or re-uploading.
  • getMedia select additionally returns type, fileSize, createdAt (additive; the UI media grid uses the same method).
  • No schema change, no migration, no env vars.

Tested: unauthenticated request returns 401; with an API key, pagination (pages count, page 2), filename search and the new fields verified; mediaListTool appears in the MCP tools list and returns the same rows via tools/call; a draft created through the MCP with a listed path stores that path as the post image.

Companion PRs (merge only after this one is deployed): gitroomhq/postiz-docs#239 and gitroomhq/postiz-agent#19.

Checklist:

  • I have read the CONTRIBUTING guide.
  • I have signed the Contributor License Agreement (CLA) (ICLA for individuals, CCLA for entities).
  • I confirm I have not used AI to submit this PR or generate code for it.
  • I checked that there were no similar issues or PRs already open for this.
  • This PR fixes just ONE issue

Adds GET /public/v1/media?page=&search= and a read-only mediaListTool so
agents can reuse already-uploaded media paths as attachments instead of
re-uploading. getMedia select now also returns type, fileSize, createdAt.

Tested: unauthenticated request returns 401; with an API key pagination
(pages count, page 2), filename search and the new fields verified;
mediaListTool appears in the MCP tools list, returns the same rows, and a
draft scheduled through the MCP with a listed path stores that path as the
post image.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@postiz-contribution
postiz-contribution Bot changed the base branch from main to staging August 19, 2026 11:34
@strix-security

strix-security Bot commented Aug 19, 2026 •

Copy link
Copy Markdown

Strix Security Review

No security issues found.

Updated for 063ee50.


Reviewed by Strix
Re-run review · Configure security review settings

@postiz-agent

postiz-agent Bot commented Aug 19, 2026 •

Copy link
Copy Markdown

✅ Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
✅ Open Source Security 0 0 0 0 0 issues
✅ Licenses 0 0 0 0 0 issues
✅ Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@Get('/media')
getMedia(
@GetOrgFromRequest() org: Organization,
@Query('page') page: number,

This comment was marked as outdated.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partly confirmed: a non-numeric value or 0 fell back to page 1, but a negative value did produce a negative skip and a 500. Fixed in 063ee50 with a GetMediaDto (page: IsNumber, Min(1), parseInt transform, default 1; search: IsString), same pattern as GetNotificationsDto. Verified: page=abc, 0 and -3 now return 400, page=1.5 parses to 1, normal requests unchanged.

A negative page produced a negative Prisma skip and a 500. GetMediaDto
(same shape as GetNotificationsDto) now rejects non-numeric or < 1 values
with 400 and defaults to 1.

Tested: page=abc / 0 / -3 return 400 with validation messages, page=1.5
parses to 1, no page / page=2 / search unchanged, unauthenticated still 401.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contribution:approved Approved contributor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant