feat(mcp): media tools over an optional provider media facet + registry publish fix#75
Merged
Conversation
Close the media discovery loop for external agents: list assets, pick a media/... path, reference it via contentrain_content_save. - types: MediaProvider contract (list/get/ingest/update/delete) + MediaAsset/MediaListOptions/MediaListResult/MediaIngestInput/ MediaUpdateInput; RepoProvider gains optional media?: MediaProvider facet (Studio MCP Cloud implements it; Local/GitHub/GitLab do not) - mcp: 5 new tools (contentrain_media_list/get/ingest/update/delete) as deterministic passthrough in src/tools/media.ts; registered only when the facet is present via a new media requirement in TOOL_REQUIREMENTS — local stdio servers keep listing exactly the 19 core tools. Ingest is URL-based (no binary channel in MCP); the provider owns SSRF/MIME/size policy, and media_ingest is the only openWorldHint: true tool. media_delete is destructive and requires confirm: true. - rules: MCP_TOOLS 19 -> 24, essentials document the media flow - skills: Media Tools section in references/mcp-tools.md (parity-tested) - docs: tool counts updated to 24 (19 core + 5 media) across README/docs site; stale '17 tools' mention fixed in embedding guide - fix(release): shorten server.json description to 93 chars — the MCP Registry publish step failed on main with 'expected length <= 100'; new tests/registry-manifest.test.ts pins the limit plus mcpName/npm identifier parity so this class of failure is caught pre-merge Tests: 10 new media tool cases (passthrough, SSRF policy surfacing, schema-level confirm/url guards, absent-facet behavior), availability tests updated for the media facet, 3 registry-manifest checks. Full MCP suite 675 passed (1 pre-existing branch-lifecycle timeout flake under parallel load — passes in isolation); rules 16/16, skills 85/85, oxlint 0/0, tsc clean in types/mcp, CLI compiles against new types.
✅ Deploy Preview for contentrain-ai ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase 3 of the MCP Cloud roadmap — the upstream half of the media stack: a
MediaProvidercapability contract in@contentrain/typesand fivecontentrain_media_*tools in@contentrain/mcp, registered only when the provider exposes a media facet. Also fixes the release CI failure from the last train (MCP Registry rejectedserver.json's description: limit is 100 chars, ours was 139).Four-package minor (changeset included): types, mcp, rules, skills.
The contract (
@contentrain/types)MediaProvider—list/get/ingest/update/delete— plusMediaAsset,MediaListOptions,MediaListResult,MediaIngestInput,MediaUpdateInput.RepoProvidergainsmedia?: MediaProvider. Studio implements this increateStudioGitProviderby delegating to its media service layer; Local/GitHub/GitLab providers leave it absent.The tools (
@contentrain/mcp)contentrain_media_listcontentrain_media_getcontentrain_media_ingestopenWorldHint: truetool — provider owns SSRF/MIME/size policycontentrain_media_updatecontentrain_media_deletedestructiveHint: true, requiresconfirm: true; content references are NOT rewrittenmediarequirement inTOOL_REQUIREMENTSgates onRepoProvider.mediapresence — local stdio servers still list exactly the 19 core tools, so nothing changes for existing users. Community Edition never sees media tools; no ee-boundary code needed.media_list→ pickmedia/...path →content_save(normalized to delivery URLs viamediaBaseUrl).Release CI fix
The
Publish to MCP Registrystep failed on main:422 — expected length <= 100forbody.description. Shortened to 93 chars, and addedtests/registry-manifest.test.ts(description ≤ 100,mcpNameparity, npm identifier parity) so the next violation fails in CI before merge, not at publish time. npm 1.9.0 published fine; the registry listing heals on this PR's release train.Parity chain
@contentrain/rules:MCP_TOOLS→ 24, essentials guardrails document the media flow (16/16)@contentrain/skills:references/mcp-tools.mdMedia Tools section (85/85 incl. heading parity)Testing
10 new media tool tests (facet passthrough, SSRF-policy error surfacing, schema-level
url/confirmguards, absent-facet ⇒ not listed + unknown-tool error), availability tests extended for the facet, 3 manifest checks. Full MCP suite: 675 passed (one pre-existingbranch-lifecycle30s-timeout flake under full parallel load — passes in isolation, file untouched by this diff). oxlint 0/0; tsc clean in types/mcp; CLI compiles against the new types.Studio follow-ups (their repo)
mediafacet on the loopback provider (service layer, not HTTP round-trips through own REST)contentrain_media_*from the brain-invalidation/automerge write set (media writes don't touch the content branch)media:read/write🤖 Generated with Claude Code