{"name":"Spaceback MCP Server","version":"1.0.0","transport":"StreamableHTTP","auth":"oauth","endpoints":{"mcp":"/mcp","health":"/health","skills":"/skills/"},"profile":"full","profileHint":"Append ?profile=streamlined to the /mcp URL for the streamlined toolset (default: full).","docsUrl":"https://spaceback.rembrand.com/tools/mcp-setup","skillsUrl":"https://spaceback-mcp.rembrand.com/skills/","skillsCatalogUrl":"https://spaceback-mcp.rembrand.com/skills/skills.json","skillsInstallCommand":"curl -fsSL https://spaceback-mcp.rembrand.com/skills/install.sh | SPACEBACK_SKILLS_BASE_URL=https://spaceback-mcp.rembrand.com/skills bash","skillsPackPath":"skills-pack","setup":{"claudeDesktop":{"file":"claude_desktop_config.json","config":{"mcpServers":{"spaceback":{"command":"npx","args":["-y","mcp-remote","https://spaceback-mcp.rembrand.com/mcp"]}}}},"nativeHttp":{"file":".mcp.json","config":{"mcpServers":{"spaceback":{"type":"http","url":"https://spaceback-mcp.rembrand.com/mcp"}}}}},"instructions":"Spaceback MCP helps agents work with Spaceback brands, social posts, and video creatives.\nEvery workspace action happens inside one organization. When the user names a workspace, call list-organizations with q set to that name and pass the matching id as organizationId (the list is capped and disclosed as truncated for accounts with many orgs — filter, do not scan). When they do not, the server uses their workspace preference: a pinned default org when set, the sole accessible org when they have exactly one, or needsOrganization when multiple orgs are ambiguous — never brand-history or list-order guessing. If a tool returns needsOrganization, ask the user to choose or point them to the MCP Setup page to pin a default.\nStart by calling list-brands, then choose existing media-ready source content with list-brand-recommended-posts. Unless the user names a post, URL, platform, or theme, you MUST use briefing.lead from list-brand-recommended-posts and present its rationale. If leadSource is composite_fallback, disclose that the briefing is not ready and you are using the top composite-scored fallback.\nUse list-brand-posts only as a chronological/browse inventory, not as a ranking or \"best post\" selector.\nNew brand from a domain: create-brand with brandUrl (SPA create path — Brandfetch/scrape identity + handles + eager hydrate). Poll show-brand until scrape_pending is false; if jobIds were returned poll show-import-job, else when social_handles appear call hydrate-brand-posts. Empty library on an existing brand: show-brand → hydrate-brand-posts when handles exist, else resolve-social-profile → browse-social-profile → import-social-post. Do not invent a source post.\nIf a client reports \"No approval received\" for browse/list tools, the human missed or declined the tool-approval prompt; ask them to approve and retry instead of treating it as an outage or routing around it.\nHydrates and imports are async. Poll show-import-job every 15–30s until done/failed, then list posts. For a chosen post, poll show-social-post until summary.mediaReady is true (can take several minutes).\nIf show-social-post reports mediaStatus.likelyStalled, stop polling that post and choose existing media-ready content instead.\nFor create-creative, omit brand-fit overrides and mediaKind unless you have explicit user input; the server inherits brand identity and derives mediaKind from source-post media.\nCustom / AI backdrops: list-ad-backgrounds, upload-ad-background (public image URL), or generate-ad-background (pass heroSourcePostId — server ffmpeg samples the durable hero; prefer this over the Ad Builder AI tab for TikTok heroes that time out in the browser). Poll get-ad-background until ready=true. Optional animate-ad-background (POST :id/video) for an MP4 — poll until videoReady. Pass adBackgroundId for the main plate and/or endCardAdBackgroundId for an end-card-only plate (generate/upload with slot:end_card). Omitting either id on update clears that plate. Pass endCardDurationSec for the end-card tail (default ~4.1s); it must leave the template at least 2s, so its cap is durationSec−2 — 13 on a default 15s ad.\ncreate-creative makes VIDEO creatives in two formats: \"vertical\" (9:16 social, layouts V01–V07) and \"horizontal\" (16:9 YouTube-style, layouts H01–H08). Default is vertical; pass format:\"horizontal\" for landscape. The variant must match the format. For DISPLAY (HTML5 banner) creatives use create-display-creative instead.\nAd LENGTH is durationSec on create-creative / update-creative — total seconds, default 15, same range as the app's own picker (6 / 15 / 30 or any custom length up to 120). socialDuration is only the engagement loop inside the ad and never changes how long the ad is. An ad under 3s cannot carry an end card at all — pass endCard:\"NONE\" for those.\ndurationSec sets how long the AD is; it does NOT shorten the hero. When the source post is longer than the ad, the hero is simply cut off mid-sentence — use Smart Clip: plan-clip (sourcePostId + targetDurationSec, returns trim strategies and a recommendedStrategyId; can take up to ~2 minutes), render-clip, poll get-clip until ready, then pass clipJobId to create-creative alongside the same durationSec. Keep sourcePostId set too — it still supplies caption/handle/counts. plan-clip tells you when the source already fits and no clip is needed. Prefer 15s or 30s ads: they carry the most CTV/OLV inventory, and Smart Clip is what makes a standard length work with an odd-length source.\nSaved team templates (the user's own layouts): list-team-templates, then pass the templateId to create-creative / update-creative as its applyWith argument. The layout is copied onto the ad; templates are edited in the app, not here.\nCreate video drafts with create-creative. Drafts are immediately reviewable through editInBuilder and are not rendered automatically.\nRevise a video creative with update-creative — it rebuilds the content in place (same id). On a never-rendered draft nothing renders, so iterate for free until the user approves; on an already-rendered creative the same call also queues the re-render (poll get-creative), because a saved edit with a stale output is never allowed. Pass the full desired content each call, not just the changed field — except for copy-only tweaks, where keepDesign: true changes just the copy args passed and keeps Ad Builder edits. Creatives that have delivered impressions (receiving traffic, or no longer receiving) are refused — their ad tag has served; duplicate into a new creative instead.\nOnly call render-creative after the user confirms the draft is ready to render.\nAfter render-creative, poll get-creative about every 30 seconds until status is done.\nNEVER hand out a rendered-file URL, and none of the tools return one: a presigned asset link needs no login, lasts 7 days and cannot be revoked. To let a human see a finished creative, share shareUrl (the revocable /p/share/c/ page — mint it with create-share-link) or point them at viewInUI / editInBuilder, where the download sits behind their own session. Display ZIPs are downloaded from viewInUI only.\ncreate-display-creative makes DISPLAY (HTML5 banner) creatives in every IAB preset size (300x250 default via size; or sizes for several). Pass platform (default instagram) and optional layout (framed / edge-to-edge / story / banner-only; omit to derive — Instagram feed defaults to edge-to-edge, so layout:\"framed\" for the framed card). UNLIKE video there is NO draft step — confirm copy/brand fit first, then poll get-display-creative until \"done\" and send the user to viewInUI for the ZIP; editInBuilder is the live preview. Browse with list-creatives (kind \"display\"). Edit in place with update-display-creative (pass only fields to change, including size / platform / layout); omitted fields keep; no content fields = plain rebuild. Content edits refused after delivery — duplicate instead. Brand fit (colors, fonts) still goes through editInBuilder.\nShare a finished creative with create-share-link: it returns a public /p/share/c/ preview URL that needs no login (the same link the Creatives UI copies). The page plays the watermarked render, so render first — on an unrendered draft the link resolves to an empty preview. The link is stable — calling it again returns the same URL; revoking or rotating a shared link is done in the app, not through MCP. Use resolve-share-link to check what an existing link points at, or to get the creative id back from a link. To send a SET of creatives as one review page, group them with create-label + apply-label and share the gridUrl from create-label-share-link (needs org-admin; otherwise pass creativeIds to create-share-link for one link each).\nManage existing creatives with rename-creative (sets the display title) and delete-creative (removes it from the library — archives it). Both work for video and display creatives. Only call delete-creative after the user explicitly confirms; verify the id with list-creatives first.\nUse ids returned by this server. Resources from other workspaces are rejected or hidden.\nTeams organize creatives within an org: discover them with list-teams, pass teamId on create-creative when the org has multiple teams (or pin a default team on the MCP Setup page). A sole team resolves without asking; never invent a team from list order when multiple exist — if a tool returns needsTeam, ask the user. editInBuilder opens the creative in its team context.\nManual import (last resort, operator-driven): when import-social-post fails because a post needs a signed-in browser (private, login-walled, age-gated, region-blocked, a LinkedIn ad-review URL, or a Facebook Dynamic Creative URL — any facebook.com host carrying a dco_ad_token param, not just business.facebook.com) — capture it yourself and use the 3-step ladder: start-manual-social-upload, PUT the parts straight to S3 yourself, finish-manual-social-upload, then create-manual-social-post. Do NOT reach for it for ordinary imports. Media is required: a post with no importable media is terminal, so report it to the user instead of retrying. Unlike URL imports, create-manual-social-post BLOCKS until media is ready; a timeout returns a postId to poll and is not a failure.\nPerformance reporting is read-only and starts with get-report-summary; the same scope arguments (organizationId, brandId/brandIds, labelIds, creativeIds, startDate/endDate) work on get-report-timeseries (daily, with provisional days flagged in partialDates), list-report-creatives (per creative — also the leaderboard, via sortBy, and the source of ids for get-creative-report), get-report-breakdown (share by label/brand/kind/size/ad_server) and list-report-tags (per ad tag, so DCO variants and both ad servers are separate rows — never sum them into a per-creative total). Dates default to the last 30 days ending today and cannot span more than 365 days. impressions are BILLABLE impressions (invoiced, invalid traffic excluded), ctr = clicks/impressions, cvr = conversions/CLICKS, and every date is a calendar day in the account reportTimeZone. When conversions, cvr or videoCompletionRate come back null, say \"not tracked\" — never \"zero\" — and repeat the caveats. These tools cover current CM360/Innovid delivery; migrated Spaceback v1 (legacy:) creatives, invoices and QR inventory are not exposed here. Send humans to viewInUI rather than transcribing whole tables.\nTrafficking (getting a finished creative into a DSP or ad server): get-creative-tracking reads landingPage / clickTracker / impressionTracker / usesClickTrackerAsLandingPage and DCO variables per creative version; update-creative-tracking writes them in bulk — send only the fields to change, omitted fields are never cleared, unchanged rows are no-ops, so re-sending a whole media plan is safe — then poll show-tracking-job until done and report errors[] per row. done = SAVED, not served: call list-creative-tags with checkDelivery:true and export only when readyForExport is true (stale[] names what is not yet serving its latest build on the ad server) — never treat matching tracker values as delivery. Tracker fields are display-only; video tracking lives on the ad tag. list-creative-tags returns the adTag strings (VAST URL or display script) for delivered tags with their deliveredAt, names creatives with none in missing[] and mid re-push in refreshing[]; email-creative-tags generates missing tags and emails the xlsx tag sheet to the signed-in user (fire-and-forget, nothing to poll). Where a tag is minted is an ORG-level setting, never a property of the creative: list-ad-destinations shows the CM360 / Innovid accounts and which is default; create-ad-tag mints one tag for one creative there — display (HTML) or video (VAST/overlay), the family read from the creative. email-creative-tags only fills creatives with NO tag yet and silently skips any that already has one, so it can never add a second tag — use create-ad-tag with that destinationId and its own label. Tracker values are per TAG, not copied from a sibling: read them with list-creative-ad-tags and pass the same ones, landingPage bare (the ad server wraps it behind the tracker); impressionTracker is display markup on a display tag and a VAST Impression URL on a video one. check-ad-tags proves what a tag actually serves. A whole tag sheet (xlsx/csv from an agency): list-creative-tags with includeTrackers for the current values and tagIds, show the user what would change, then after they confirm send the changes in one update-ad-tag-trackers call with tags[]. No tag at all usually means the org has no enabled destination, which only the Spaceback settings UI can add. Pass dspPartner (e.g. \"adform\") to bake that DSP's click macro into display tags. DV360 upload files: get-dv360-bulk-csv.\nFeeds (one size, many creatives in rotation, one ad-server tag per placement or audience — use them when a buyer needs tags before the creative exists, one tag per audience, or creatives swapped on dates): create-feed, attach-feed-creatives, create-feed-tags (label = the buyer's tag name; the ad-server placement name is generated and never changes), get-feed-tag-codes to hand tags out. Every tag serves every live creative, so a creative is swapped by attaching the new one, then remove-feed-creative on the old one — never the reverse. The backend refuses the removal until the replacement is live on the ad server; if refused, wait and retry, never work around it. Trackers are per TAG (update-feed-tag) and need a creative on the feed first (a placeholder is fine). schedule-feed-creative switches a creative on/off on a date. get-feed-tag-sheet reads the sheet (read-only); bulk edits loop update-feed-tag / pause-feed-creative. create-feed-share-link: one public page of the whole rotation. email-feed-tags emails the feed tag xlsx.\nHuman setup docs are available at https://spaceback.rembrand.com/tools/mcp-setup.\nOptional agent skills (spaceback-router, onboard-brand, draft-creative, duplicate-creative, draft-display) cover brand cold-start, video ads (vertical and horizontal), duplicating an existing creative with a new hero, and display banner creatives. Install from MCP Setup.","tools":["create-creative","update-creative","replace-creative-video","render-creative","get-creative","list-creatives","rename-creative","delete-creative","create-share-link","resolve-share-link","list-labels","create-label","apply-label","create-label-share-link","list-team-templates","create-display-creative","get-display-creative","update-display-creative","duplicate-display-creative","list-ad-backgrounds","get-ad-background","generate-ad-background","upload-ad-background","animate-ad-background","plan-clip","render-clip","get-clip","list-organizations","list-teams","list-brands","show-brand","show-brand-assets","create-brand","import-social-post","start-manual-social-upload","finish-manual-social-upload","create-manual-social-post","show-social-post","list-brand-posts","list-brand-recommended-posts","hydrate-brand-posts","show-import-job","link-social-post-brand","redetect-social-post-brand","resolve-social-profile","browse-social-profile","get-report-summary","get-report-timeseries","list-report-creatives","get-report-breakdown","list-report-tags","get-creative-report","get-creative-tracking","update-creative-tracking","show-tracking-job","list-ad-destinations","create-ad-tag","list-creative-ad-tags","update-ad-tag-trackers","check-ad-tags","list-creative-tags","email-creative-tags","get-dv360-bulk-csv","list-feeds","get-feed","create-feed","create-feed-tags","update-feed-tag","get-feed-tag-codes","attach-feed-creatives","pause-feed-creative","remove-feed-creative","schedule-feed-creative","get-feed-tag-sheet","create-feed-share-link","email-feed-tags"]}