Every change Wellknown observed on this MCP server, newest first, with what it was before and what it became. Tool-surface changes carry the definition diff. Nothing here is edited after the fact.
Changed the definition of "add_custom_domain"
⟨52 unchanged words⟩ provider first.","type":"boolean"},"dnsProvider":{"additionalProperties":false,"description":"The provider that hosts the domain's DNS, recognised from its nameservers. Absent when unknown.","properties":{"helpUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The provider's own help article on DNS records, when known."},"id":{"type":"string"},"name":{"description":"The company that hosts the domain's DNS, e.g. Combell, OVHcloud, Cloudflare.","type":"string"},"panelUrl":{"description":"Where the user logs in to edit the DNS records.","type":"string"},"steps":{"description":"Steps specific to this provider, in order. Relay them with the records.","items":{"type":"string"},"type":"array"}},"required":["id","name","panelUrl","helpUrl","steps"],"type":"object"},"dnsRecords":{"description":"Every record to add ⟨237 unchanged words⟩
Authorization not required, issuer https://mcp.vibedeploy.be/
Changed the definition of "add_custom_domain", "build_and_deploy", "check_domain_availability" and 6 more
Start attaching a user-owned domain to an existing site: returns theTXTDNSrecordrecords the user adds at their DNSprovider.provider (a routing record that sends visitors here, plus a TXT that proves ownership). Idempotent: the same siteName and domain return the existing record. Once theTXTrecordsisare published (usually minutes, up to 24h), call verify_custom_domain with the returnedrecordId.recordId; VibeDeploy also re-checks automatically for a few days and emails the user when the domain is live. The site must already exist; call deploy_site first if it does not.
Authorization not required, issuer https://mcp.vibedeploy.be/
Added "promote_dist_to_source"; changed the definition of "abort_deploy", "add_custom_domain", "add_file_chunk" and 38 more (42 tools before, 43 now)
Discard astagingbegin_deploy session and itsscratchstageddir.files;Livethe live site is untouched.Returns immediately; cleanupCleanup isbest-effort andbesttheeffortsweeperandwill
Authorization not required, issuer https://mcp.vibedeploy.be/
Authorization not required, issuer https://mcp.vibedeploy.be/
Changed the definition of "commit_deploy"
⟨37 unchanged words⟩ with existing files, requires confirm:"I-want-to-replace-all-files". If the call times out or the connection drops, call commit_deploy again with the same deployId: it returns the outcome of the commit that is still running or just finished instead of starting a second one.
Authorization not required, issuer https://mcp.vibedeploy.be/
Changed the definition of "deploy_app" and "get_app_status"
⟨223 unchanged words⟩ "postgres://app:$(DB_PASSWORD)@db:5432/app".SiteSecrets from outside (API keys, OAuth client secrets,settokens) never go in the config, the source or the chat: the user adds them in the VibeDeploy dashboardare(theinjectedsite's Settings tab, section Secrets; get_app_status returns the direct link as secrets.manageUrl). Every service gets them as env varstoo.and restarts automatically; an explicit env entry with the same name wins. get_app_status lists the secret names that are set, never their values.
Authorization not required, issuer https://mcp.vibedeploy.be/
Added "deploy_app", "get_app_status" and "remove_app" (39 tools before, 42 now)
Run container services (server, database, workers) for a site — Deploy or update the site's container services: the user's own backend server, a database (Postgres, MySQL, MongoDB, ...), Redis, background workers, from any public image. Applies the whole config: services missing from it are stopped (their volumes and data are kept). Waits until every service is ready, then returns per-service status; on failure call get_app_status with logs to debug. Each call restarts the services, which also picks up new source files. App config: { "services": { "<name>": { "image": "postgres:16-alpine", "port": 5432, "public": false, "command": [...], "args": [...], "w…
Show container service status and logs — Per-service status of the site's container services (ready, restarts, waiting/crash reasons, volumes), the stored config, and optionally the recent logs of one service.
Stop all container services of a site — Stops every container service and serves the site's static files again. Volumes (database data) are kept unless deleteData is true, which is irreversible.
Authorization not required, issuer https://mcp.vibedeploy.be/
Authorization not required, issuer https://mcp.vibedeploy.be/
Authorization not required, issuer https://mcp.vibedeploy.be/
Changed the definition of "deploy_from_url"
⟨83 unchanged words⟩ call. Hostname allowlist enforced; see the archiveUrl description. Replace mode on a site that already has files needs confirm:"I-want-to-replace-all-files". A failed call never leaves a staging session open.
⟨80 unchanged words⟩ ":"uri","type":"string"},"confirm":{"const":"I-want-to-replace-all-files","description":"Required only for mode \"replace\" on a site that already has files. Pass exactly \"I-want-to-replace-all-files\" to acknowledge that the live files will be deleted and replaced with the archive's files.","type":"string"},"mode":{"description":"How the archive's files ⟨30 unchanged words⟩
Changed the definition of "list_history"
⟨34 unchanged words⟩ count, and the number of secrets detected. Each entry's snapshot holds the content from BEFORE that entry (restoring it undoes the entry). Any team member can read history.
⟨54 unchanged words⟩ :"null"}],"description":"Longhorn snapshotnametakenforimmediately BEFORE this entry's change (pre-deploy, pre-promote, pre-restore), so restoring it brings back the content that was live before this entry,ornotnull
Authorization not required, issuer https://mcp.vibedeploy.be/
Authorization not required, issuer https://mcp.vibedeploy.be/
Authorization not required, issuer https://mcp.vibedeploy.be/
Authorization not required, issuer https://mcp.vibedeploy.be/
Certificate recorded, valid to 2026-11-22
Authorization not required, issuer https://mcp.vibedeploy.be/
First tool surface recorded: 39 tools (server version 1.0.1)
Showing the latest 24 events. The API returns up to 500 and filters by kind: ?kind=tool_surface_changed
⟨52 unchanged words⟩ provider first.","type":"boolean"},"dnsRecords":{"description":"Every record to add at the DNS provider: routing (sends visitors to VibeDeploy), ownership (TXT) and the optional www/apex twin. Only present when status is pending_verification.","items":{"additionalProperties":false,"properties":{"alternative":{"additionalProperties":false,"properties":{"type":{"type":"string"},"value":{"type":"string"}},"required":["type","value"],"type":"object"},"fqdn":{"type":"string"},"host":{"description":"Value for the provider's Host/Name field ('@' is the domain itself).","type":"string"},"purpose":{"enum":["routing","ownership","www"],"type":"string"},"type":{"type":"string"},"value":{"type":"string"}},"required":["purpose","type","host","fqdn","value"],"type":"object"},"type":"array"},"domain":{"type":"string"},"instructions":{"description":"Plain-English instructions for the ⟨80 unchanged words⟩ when status is pending_verification.","properties":{"namehost":{"description":"What to type in the DNSrecordprovider's Host/Name field (e.g. '_vibedeploy.shop'); most providers append the domain themselves.","type":"string"},"name":{"description":"FulltoDNSaddrecord name (e.g. '_vibedeploy.shop.example.com').","type":"string" ⟨27 unchanged words⟩
⟨19 unchanged words⟩ MCP responses.","type":"string"},"customDomains":{"anyOf":[{"additionalProperties":false,"properties":{"allowance":{"description":"Custom domains the team's current plan includes.","type":"number"},"connected":{"description":"Custom domains on this site from both sources, one entry per hostname.","items":{"additionalProperties":false,"properties":{"domain":{"description":"Hostname, e.g. shop.example.com.","type":"string"},"source":{"description":"dashboard: linked on the dashboard Web Addresses page. mcp: added with add_custom_domain or the site API.","enum":["dashboard","mcp"],"type":"string"},"status":{"description":"live: verified and serving this site. pending: linked, not verified yet.","enum":["live","pending"],"type":"string"}},"required":["domain","status","source"],"type":"object"},"type":"array"},"nextTool":{"const":"add_custom_domain","description":"Present when this site has no custom domain yet and the team has room for one.","type":"string"},"used":{"description":"Distinct custom domains in use across the team, both sources (same count as get_account).","type":"number"}},"required":["connected","allowance","used"],"type":"object"},{"type":"null"}],"description":"Custom domains of this site and the team's custom-domain allowance; null when they could not be read."},"filesDeployed":{"type":"number"},"manageUrl" ⟨60 unchanged words⟩ ","outputDir","totalBytes","manifest","buildLog","customDomains"],"type":"object"}
⟨41 unchanged words⟩ dev and app. Not tied to a site. The result states whether the user's plan includes buying domains in the dashboard (purchase.dashboardUrl); a domain the user already owns is connected with add_custom_domain.
⟨63 unchanged words⟩ ), or null if the lookup failed."},"unavailableReason":{"description":"Set when the registrar lists the name as free but VibeDeploy cannot register it. MULTI_YEAR_ONLY: this extension is only sold for two years or more, and VibeDeploy registers and renews one year at a time.","type":"string"}},"required":["domain","available","priceCents ⟨6 unchanged words⟩ description":"Whether the domain can be registered through VibeDeploy right now.","type":"boolean"},"currency ⟨25 unchanged words⟩ was bought.","type":"string"},"ownDomain":{"description":"How a domain the user already owns is connected instead.","type":"string"},"priceCents":{"anyOf":[{"type":"number ⟨12 unchanged words⟩ or null when no price is published."},"purchase":{"additionalProperties":false,"description":"Whether and where the user can buy a domain through VibeDeploy.","properties":{"allowedOnPlan":{"description":"Whether the user's current plan includes buying domains through VibeDeploy.","type":"boolean"},"dashboardUrl":{"description":"Dashboard page where the user buys domains. Buying always happens there, never through this tool.","type":"string"},"reason":{"description":"Neutral statement of why buying is not possible. Present only when allowedOnPlan is false.","type":"string"}},"required":["allowedOnPlan","dashboardUrl"],"type":"object"},"unavailableReason":{"description":"Set when the registrar lists the name as free but VibeDeploy cannot register it. MULTI_YEAR_ONLY: this extension is only sold for two years or more, and VibeDeploy registers and renews one year at a time.","type":"string"}},"required":["available","domain","priceCents","currency","note","purchase","ownDomain"],"type":"object"}
{"$schema":"http://json-schema.org/draft-07/schema#","additionalProperties":false,"properties":{"customDomains":{"anyOf":[{"additionalProperties":false,"properties":{"allowance":{"description":"Custom domains the team's current plan includes.","type":"number"},"connected":{"description":"Custom domains on this site from both sources, one entry per hostname.","items":{"additionalProperties":false,"properties":{"domain":{"description":"Hostname, e.g. shop.example.com.","type":"string"},"source":{"description":"dashboard: linked on the dashboard Web Addresses page. mcp: added with add_custom_domain or the site API.","enum":["dashboard","mcp"],"type":"string"},"status":{"description":"live: verified and serving this site. pending: linked, not verified yet.","enum":["live","pending"],"type":"string"}},"required":["domain","status","source"],"type":"object"},"type":"array"},"nextTool":{"const":"add_custom_domain","description":"Present when this site has no custom domain yet and the team has room for one.","type":"string"},"used":{"description":"Distinct custom domains in use across the team, both sources (same count as get_account).","type":"number"}},"required":["connected","allowance","used"],"type":"object"},{"type":"null"}],"description":"Custom domains of this site and the team's custom-domain allowance; null when they could not be read. Omitted on dry runs."},"customHeaders":{"anyOf":[{"additionalProperties":false, ⟨130 unchanged words⟩
⟨13 unchanged words⟩ the site.","type":"boolean"},"customDomains":{"anyOf":[{"additionalProperties":false,"properties":{"allowance":{"description":"Custom domains the team's current plan includes.","type":"number"},"connected":{"description":"Custom domains on this site from both sources, one entry per hostname.","items":{"additionalProperties":false,"properties":{"domain":{"description":"Hostname, e.g. shop.example.com.","type":"string"},"source":{"description":"dashboard: linked on the dashboard Web Addresses page. mcp: added with add_custom_domain or the site API.","enum":["dashboard","mcp"],"type":"string"},"status":{"description":"live: verified and serving this site. pending: linked, not verified yet.","enum":["live","pending"],"type":"string"}},"required":["domain","status","source"],"type":"object"},"type":"array"},"nextTool":{"const":"add_custom_domain","description":"Present when this site has no custom domain yet and the team has room for one.","type":"string"},"used":{"description":"Distinct custom domains in use across the team, both sources (same count as get_account).","type":"number"}},"required":["connected","allowance","used"],"type":"object"},{"type":"null"}],"description":"Custom domains of this site and the team's custom-domain allowance; null when they could not be read. Omitted on dry runs."},"customHeaders":{"anyOf":[{"additionalProperties":false, ⟨160 unchanged words⟩
⟨350 unchanged words⟩ :"object"},"customDomains":{"description":"Currently attachedDistinct custom domains in use across theteam.team: added with add_custom_domain or linked and bought in the dashboard.","type":"number"},"deploysLastHour":{ ⟨42 unchanged words⟩
⟨14 unchanged words⟩ is stored (and its build settings), custom domains, bandwidth and the last 10 deploys. Use get_site ⟨18 unchanged words⟩
⟨47 unchanged words⟩ ,"windowDays"],"type":"object"},"customDomains":{"anyOf":[{"additionalProperties":false,"properties":{"allowance":{"description":"Custom domains the team's current plan includes.","type":"number"},"connected":{"description":"Custom domains on this site from both sources, one entry per hostname.","items":{"additionalProperties":false,"properties":{"domain":{"description":"Hostname, e.g. shop.example.com.","type":"string"},"source":{"description":"dashboard: linked on the dashboard Web Addresses page. mcp: added with add_custom_domain or the site API.","enum":["dashboard","mcp"],"type":"string"},"status":{"description":"live: verified and serving this site. pending: linked, not verified yet.","enum":["live","pending"],"type":"string"}},"required":["domain","status","source"],"type":"object"},"type":"array"},"nextTool":{"const":"add_custom_domain","description":"Present when this site has no custom domain yet and the team has room for one.","type":"string"},"used":{"description":"Distinct custom domains in use across the team, both sources (same count as get_account).","type":"number"}},"required":["connected","allowance","used"],"type":"object"},{"type":"null"}],"description":"Custom domains of this site and the team's custom-domain allowance; null when they could not be read."},"filePaths":{"description":"Site-relative paths of every ⟨225 unchanged words⟩ ","sourceManifest","lastDeployAt","bandwidth","history","customDomains"],"type":"object"}
Return all custom domains attached to asite.site,Eachbothentrythosehasadded with add_custom_domain (source 'mcp', with a recordIdyouforcanverify_custom_domainpassortoremove_custom_domain)verify_custom_domainand those linked in the VibeDeploy dashboard (source 'dashboard', verified orremove_custom_domain.removed on the dashboard Web Addresses page at manageUrl). Call it before add_custom_domain to avoid adding a domain twice.
⟨11 unchanged words⟩ {"domain":{"type":"string"},"manageUrl":{"description":"Source 'dashboard' only: the dashboard Web Addresses page where this domain is verified or removed.","type":"string"},"note":{"description":"Source 'dashboard' only: how this entry is managed.","type":"string"},"recordId":{"description":"Pass to verify_custom_domain or remove_custom_domain. Present on every source 'mcp' entry, absent on source 'dashboard' entries.","type":"string"},"source":{"description":"mcp: added with add_custom_domain or the site API. dashboard: linked on the dashboard Web Addresses page.","enum":["mcp","dashboard"],"type":"string"},"status":{"enum":["pending_verification","verified" ⟨3 unchanged words⟩ {"additionalProperties":false,"description":"Only presentwhenon source 'mcp' entries whose status is pending_verification.","properties":{"name": ⟨14 unchanged words⟩ "type":"object"}},"required":["recordIddomain","domainstatus","statussource"],"type":"object"},"type": ⟨9 unchanged words⟩
Check theTXT recordrecords from add_custom_domain (the ownership TXT and the routing record) and, whenitbothisarefoundright, start serving the site on thatdomaindomain;(the HTTPSiscertificateissuedfollows automatically, usually withinabouta30minutes).or two. If it fails,DNSthehasresultusuallynamesnoteachpropagatedrecordyet:towaitadd, change or remove; DNS changes can take a few minutesandtocallpropagate. Calling itagain.again on a verified domain is a harmless re-check.
⟨4 unchanged words⟩ :{"deployId":{"description":"Session idtoreturnedabort.by begin_deploy.","type":"string"}},"required": ⟨3 unchanged words⟩
Start attaching a user-owned domain to an existingsite.site:Returnsreturnsathe TXT record the usermust addadds at their DNS provider. Idempotent:calling twice withthe same(siteName,and domain)returnsreturn the existingrecord instead of creating a duplicate.record.AfterOnce the TXT is published (typically withinusuallyminutes;minutes, up to 24h), call verify_custom_domain with the returned recordId. The siteitselfmust alreadyexist on a platform subdomain (e.g. {name}.vibedeploy.be or {name}.vibedeploy.eu).exist;Callcall deploy_site first if itdoesn't.does not.
⟨5 unchanged words⟩ :{"description":"The user-owned hostname to attach,(e.g.'tester.subsite.site').'shop.example.com'. Must be a valid FQDN.","type": ⟨22 unchanged words⟩
⟨27 unchanged words⟩ True when the verification TXT was written automaticallybecause the(domainis managedregistered throughVibeDeploy's Gandi account. The caller canVibeDeploy): call verify_custom_domainimmediately without waiting for the user to add a TXT manually. Absent /rightfalseaway.meansOtherwise the userhas to addadds the record at theirownDNS providerbefore verify will succeed.first.","type":"boolean"},"domain":{ ⟨95 unchanged words⟩ ":"DNS record name to add (e.g.'_vibedeploy.tester.subsite.site''_vibedeploy.shop.example.com').","type":"string"},"type" ⟨26 unchanged words⟩
Stream aSendsingleone fileacrossinmultipleseveral calls whenits contentitexceedsisthetooper-MCP-callbigoutputforbudget.aLASTsingleRESORTtool—call.tryLasttheseresort: first:(1)try add_files with encoding:'gzip+base64'fits(about~250250 KB of textsourceinONEone call(gzip locally, base64, send — no chunking, no ordering hazards); (2), begin_deploy's uploadUrltakes a(one 100 MBtarball in one HTTPtar POSTif your sandbox can reach mcp.vibedeploy.be; (3)deploy_from_url if the files are fetchable fromoradeploy_from_url (publicURL. Only chunk when none of thosearchivework.URL). Whenyou DO chunkchunking, gzip+base64 each chunk too,—markitthequadruplesfirstthewithsourceisFirstbytesandperthechunk.lastMarkwiththeisLast,firstandchunksendwithchunksisFirst=trueof(truncatesone+filemkdir)oneandaftertheanother:lastparallelwithchunksisLast=truecorrupt(returnsit.assembledAftersize).aSendtransportchunkserror,fordo not resend thesamechunkpathblindly:seriallyrestart—theconcurrentfilechunksfrominterleaveitsandfirstcorruptchunkthe(isFirstfile.truncates it).
⟨4 unchanged words⟩ :{"content":{"description":"This chunk'sbytes. Eitherbytes,rawas UTF-8(default)text orbase64-encoded — setencodedencodingperaccordingly.encoding.PRACTICALChunkCHUNKsizeSIZE:isboundedlimited by yourLLMclient's tool-outputtokenbudget,NOTnot byVibeDeploy'stheserver.server:
AppendAdd files to an openstaging session. Call as many times as needed; commit_deploy applies them all at once. Validates path/extension/encoding onbegin_deployeverysession; callso a bad file fails fast. Same 500itMBascapoften assingle-call deploysneeded,but cumulativethenacrosscommit_deploythepublishessession.themLARGEtogether.TEXTPaths,FILES:extensionsaandfileencodingsthatarelookscheckedtooonbigeverytocall.inlineA(100-250 KBoftextHTML/CSS/JS)file usuallystillfits inONEone call— gzip it locally, base64 the result, sendwith encoding:'gzip+base64' (text compressesgzip3-5×locally,so ~250 KB of source ≈ ~70 KB on thethenwirebase64).;Preferprefer that overadd_file_chunk: one call, no ordering hazards. Only chunk when a single file exceeds ~250 KB of source even after gzip, or when you have no way to gzip locally.add_file_chunk. If yourenvironment can runshellbut can'tcan reachthis hostmcp.vibedeploy.be,gzip+base64 via add_files is the fastest path; if it CANonereachtar(.gz)thisPOSThost,to begin_deploy's uploadUrl(tarball POST, 100 MB)isbeatsfastereverything.still.
⟨12 unchanged words⟩ string"},"files":{"anyOf":[{"description":"Array form; needed for binary files.","items":{"properties":{"content":{"description":"File content: text, or base64 as set by encoding.","type":"string"},"encoding":{"description":"utf8 (default)for plain text., base64for(binary files(images, fonts),PDFs).or gzip+base64ships ~3–5× more raw text per tool call:(gzipthe byteslocallyfirst, thenbase64. Server gunzips before writing. Per-filebase64;decodedfitssize3-5xcappedmoreattext500
Apply literal find/replace editsacrosstoMANYseveral files in onetoolcall,call.inBatchthesiblingservedoffilesupdate_file_content.(targetPer-file'dist',editlivesemanticsatidenticalonce)(count:or1thedefault,editable-1source=(targetall'source',positive int assertsshippedexactbycountbuild_and_deploy).WholeSamecalleditisrulesatomicasacrossupdate_file_content.filesAll or nothing:validationifrunsanyfirst,edit'swritesmatchonlycountproceeddiffersiffromeveryitsedit'sexpected count,checknopasses.file is written.
⟨47 unchanged words⟩ "items":{"properties":{"count":{"description":"Expected matches: default 1, -1 = replace all, or an exact number.","maximum":9007199254740991,"minimum":-9007199254740991,"type":"integer"},"find":{"description":"Literal text to find (not a regex). Max 64 KB.","maxLength":65536,"minLength":1,"type":"string"},"replace":{"description":"Literal replacement; empty string deletes the match. Max 64 KB.","maxLength":65536,"type":"string"}}," ⟨8 unchanged words⟩ :"array"},"path":{"description":"File-relative pathPath inside the chosentarget.tree, e.g. index.html.","type":"string"}},"required": ⟨7 unchanged words⟩ 1,"type":"array"},"name":{"description":"Site name as shown by list_sites, e.g. my-portfolio.","type":"string"},"target":{"description ⟨26 unchanged words⟩
OpensOpen a staging session for amulti-call deploy. Use when thedeploysitethat is too largeto fit in aforsingleonedeploy_site/update_sitecall:call.stagePairfiles with add_files (one or more timesrepeatable),ORadd_file_chunk,aorsingleonetarballtar(.gz)uploadPOST to the returned uploadUrl, then publish with commit_deploy.ActiveUsesessionbegin_deploylimitonly when the files do not fit in one deploy_site or update_site call. Up to 5 open sessions pertoken:token;5.aDefaultsessionTTL:expires after 1 hour.
⟨51 unchanged words⟩ :"string"},"name":{"description":"Site name to deployNameto.ofMustanalreadyexistingexist;sitemulti-call(seesessionslist_sites).don'tSessionsauto-createdositesnot—createusesites; deploy_sitefor that, or call this against an existing site.does.","type":"string"}},"required": ⟨4 unchanged words⟩
⟨56 unchanged words⟩ :"string"},"uploadToken":{"description":"Same single-purposeThe tokenalreadyembedded in uploadUrl,exposed separately if you'd rather pass itforviaan Authorization: Bearer headerthan as a query parameter.instead. Valid only for POST /upload/<thisdeployId>. Cannot bedeployId>,usednot for/mcptool calls oranyotherdeploy session.sessions.","type":"string"},"uploadUrl":{"description":"POST a tar(.gz) archiveto this URLhere to stage many files in one HTTP call—,bypassesoutside theper-tool-calltool-call
Run aBuildbuildtheinsidesite'sastoredhardenededitableone-shotsourcepodinagainstantheisolatedsite'sone-shoteditablebuildsourcepodtreeand(writeatomicallysourcepublishfirsttheviaoutputwrite_source_filesas/thelist_source_filesliveautoPromote)site,then atomically swapreplacing thebuildservedoutputfilesinto(atherestorelivepointdist.isReusesnormallythetakensamefirst).buildUsepodbuild_and_deploytheafterGitProjectchanginggit-deploystoredflowsourceuses(write_source_files,soapply_editsthewithsametargetisolation'source');guaranteesuseapply:update_sitenoinsteadSAtotoken,uploadnofilesDB/Vaultthatreach,areNetworkPolicy-restrictedalreadyegress.built. The firstrunbuildwritessavesthebuildCommand,chosenoutputDirbuildCommand/outputDirandintorootPathSite.sourceManifest;onsubsequentthe site, so later calls can omitthosethem.fields.A failed build returns its log in the error details.
⟨3 unchanged words⟩ ,"properties":{"buildCommand":{"description":"Override for the build script's `npm runBuildbuild`commandstepoverride,(e.g. 'npm run build:prod' or 'pnpm vitebuild'). If omitted,build'.usesDefault: themanifest stored on thesavedsitemanifest, thenfalls back to'npm run build'.","type":"string"},"name":{"description":"Site name as shown by list_sites, e.g. my-portfolio. Provide name or siteId.","type":"string"},"outputDir":{"description":"Override for which directoryDirectory toshippublish.asDefault: thenew dist. If omitted, uses thesaved
⟨23 unchanged words⟩ ,"filesDeployed":{"type":"number"},"manageUrl":{"description":"Dashboard page where the user manages this site (domains, versions, settings).","type":"string"},"manifest":{"additionalProperties":false,"properties":{" ⟨23 unchanged words⟩ "},"totalBytes":{"type":"number"},"url":{"description":"Live URL of the site.","type":"string"}},"required":["siteId","name","url","manageUrl","filesDeployed","outputDir","totalBytes","manifest ⟨3 unchanged words⟩
{"destructiveHint":falsetrue,"idempotentHint":false,"openWorldHint":true,"readOnlyHint":false}
Check whether a domain can be registered and get anINDICATIVE retail price.indicativeIMPORTANT:pricethis(VATisincludedawhereread-onlyitlookupapplies).—Read-only: itdoes NOT buy,neverregisterbuys,reserve,registers orpay for any domain, and it changes nothing. The returned price is GROSS (includes 21% VAT) and indicativereservesonly.aSetdomain. alternatives:truetoalsocheckchecks the same nameacross other common TLDson(be, com, net, eu, nl, io, dev,app). Requires a valid team token butandisapp.notNot tied to aspecificsite.
⟨51 unchanged words⟩ {"type":"null"}],"description":"GrossIndicative(incl.price21%in cents (VAT)indicativeincludedpricewhereinitcentsapplies), or null ifpricing/availabilitythe lookup failed."}},"required":["domain" ⟨35 unchanged words⟩ },"note":{"description":"Reminder thatthistheispriceanis indicativegross priceandnot
Atomically applyPublish astagingbegin_deploy session's staged files to the livesite.siteRunsinpreflightone+atomicsecret/malwarestep, after a secret and malware scanagainstof the completestaged set;set (on failure the session stays openand can betore-attemptedretry oraborted.abort).ForReplacereplace-modemodeagainston a sitewiththatexistinghas files,requiresneeds confirm:"I-want-to-replace-all-files".If the callAftertimesaouttimeout orthedropped connectiondrops, callcommit_deployit again with the same deployId: it returns theoutcomerunningoforthefinished committhatinsteadisofstillstartingrunningaorsecondjustone.finishedUseinsteadcommit_deployofonlystartingto finish asecondbegin_deployone.session; deploy_site and update_site publish in one call.
⟨40 unchanged words⟩ :"string"},"delete":{"description":"Patch-modePatch mode only: site-relative paths to remove from the live siteas part ofin thiscommit. Useful for renamescommit (write newe.g.paththeviaoldadd_files,pathdeleteofoldapathrenamedherefile).","items":{"type":"string" ⟨10 unchanged words⟩ :"string"},"dryRun":{"description":"If true, preview what commit would do without touching the live site or scratch dir. ReturnsPreview the
⟨30 unchanged words⟩ :"null"}],"description":"Result ofthesyncingNetlify-stylethe _headerssync: overrides appliedfiletoin thesite's responsesiteheaders,rootplus(site-wideany/*validationresponsewarnings.headers)."},"deletedFiles":{"items":{"type" ⟨18 unchanged words⟩ "boolean"},"filesDeployed":{"type":"number"},"manageUrl":{"description":"Dashboard page where the user manages this site (domains, versions, settings). Omitted on dry runs.","type":"string"},"mode":{"enum":["replace" ⟨45 unchanged words⟩
Create a manual snapshot (backuprestore point) for a site
Take a point-in-timeLonghornsnapshot of a site's servedfiles.files,Itadoesrestorenotpointchangetheserveduser can restore in the VibeDeploy dashboard within the plan's restore window. Served content does not change, but retention cleanup may remove olderbackups.snapshots. Container data is not included. Requires an owner or admin team role.ReturnsNO_VOLUMEifmeans the sitehas no volume yet (it haswas neverbeen deployed).deployed.
⟨5 unchanged words⟩ {"description":"Optional human-readable label for thisbackup.snapshot.","maxLength":200,"type":"string"},"name":{"description":"Site name as shown by list_sites, e.g. my-portfolio. Provide name or siteId.","type":"string"},"siteId":{"description":"Site id from list_sites or get_site. Use instead of name.","type":"string"}},"type":"object"}
Delete a site (soft,restorable7-dayuntilrecoverypurged)
Soft-delete asite. confirm=true is required. Thesitemoves to status 'deleted' immediately(its hostname is freedconfirm:trueandrequired).itIt stops serving),at once and isfullypurged after theteam'splan'srecoveryrestore windowby a sweeper. Use this(purgesAtforin thenormal 'remove this from my dashboard'result);flow.untilThethenresponsethefielduser'accepted'canisrestoretrueitwhenin thesoft-deleteVibeDeployisdashboard.recorded;Usethedelete_siteresponsetoalsoremoveincludesthe'purgesAt'wholesosite;youusecanremove_apptellinsteadthetouserstopwhenonlyrecoveryitsbecomescontainerimpossible.services.
⟨17 unchanged words⟩ ,"type":"boolean"},"name":{"description":"Site name as shown by list_sites, e.g. my-portfolio. Provide name or siteId.","type":"string"},"siteId":{"description":"Site id from list_sites or get_site. Use instead of name.","type":"string"}},"required":[" ⟨3 unchanged words⟩
⟨11 unchanged words⟩ string"},"purgesAt":{"description":"ISOtimestamptimewhenthe site is purged for good: thesoft-deleteendbecomesofathehardplan'spurgerestore(~7window.daysUntilfromthennow).it can be restored in the VibeDeploy dashboard.","type":"string"},"siteId":{ ⟨15 unchanged words⟩
Remove one file from the site's editable source tree. The serveddistfilesisdounchanged.not change until build_and_deploy runs.
{"$schema":"http://json-schema.org/draft-07/schema#","properties":{"name":{"description":"Site name as shown by list_sites, e.g. my-portfolio. Provide name or siteId.","type":"string"},"path":{"description":"Source-relativePathpathinside the source tree todelete.delete, e.g. 'src/old.css'.","type":"string"},"siteId":{"description":"Site id from list_sites or get_site. Use instead of name.","type":"string"}},"required":[" ⟨3 unchanged words⟩
DeployRunorcontainerupdateservicesthenextsite'stocontaineraservicessite, from any public image: the user's ownbackendserver (running code from the site's source tree), a database(Postgres,suchMySQL,asMongoDB,Postgres...)or MySQL, Redis,backgroundor workers,fromeachanyinpublicaimage.gVisorAppliessandbox. The call applies the whole config: services missing from it are stopped (their volumesand dataare kept).Waits until every service is ready, then returns per-service status; on failure call get_app_status with logs to debug. Each call restartsand theservices, whichothersalsorestart,pickspicking up new source files.App config: { "services": { "<name>": { "image": "postgres:16-alpine", "port": 5432, "public": false, "command": [...], "args": [...], "workingDir": "/app", "env":It{waits"KEY":until"value"every},service"volumes":is{ready"/var/lib/postgresql/data":and"1Gi"returns},per-service"source":status;false,if"sourcePath":one"/app",is"memory":not"256Mi"ready,"cpu": "500m" } } }. Any public image works. Services reach each other by service name (e.g. host "db",callportget_app_status5432).withExactlylogs.oneOne service may be"public":true;itreceives all HTTP traffic forserves the site'sdomains on its "port" (plainHTTP,TLS is terminated for you). "source": true copies the site's source tree (write_source_files) into sourcePath (default /app, writable)traffic onevery start, so e.g. {"image":"node:22-alpine","source":true,"command":["sh","-c","npm ci &&itsnodeport.server.js"],"port":3000,"public":true}.Use "${generated:NAME}"as an env value is a random secret generated once and shared by every service that references it (use itfor databasepasswords); "$(OTHER)" embeds an earlier variable of the same service, e.g. "DATABASE_URL": "postgres://app:$(DB_PASSWORD)@db:5432/app". Secrets from outsidepasswords.(API keys,OAuthandclientothersecrets,outsidetokens)secrets never go in the config, the source or the chat: the user adds them in the VibeDeploy dashboard (the site'ssite Settingstab,section Secrets; get_app_status returns the direct link as secrets.manageUrlSecrets).Everyand every servicegetsreceives them asenv vars and restarts automatically; an explicit env entry with the same name wins. get_app_status lists the secret names that are set, never their values. Volumes persist across deploys; everything else is recreated.environmentForvariables.PostgresPersetsite:PGDATAup toa subdirectory of the volume. Outbound internet works (not SMTP port 25); private networks are blocked. Limits per site:6 services, 2048Mi memory and 2000m CPU in total(default 256Mi / 500m per service), 4 volumes, 3Gi storage. Container volumes are not included in snapshots yet.
⟨5 unchanged words⟩ "additionalProperties":{},"description":"The appconfig object.config;Omitomit it to use vibedeploy.json from the site's source tree.App configShape: {\"services\":{\"<name>\":{\"image\":\"postgres:16-alpine\",\"port\":5432,\"public\":false,\"command\": [...], \"args\env\":[...],{\"workingDir\KEY\":\"/app\value\
{"destructiveHint":falsetrue,"idempotentHint":false,"openWorldHint":true,"readOnlyHint":false}
Publish a website to a live URL fromFetch a publicarchive link. Point this at atar(.gz) archiveonovergithubHTTPS/andgistdeploy/itsS3filesandtotheanserverexistingfetchessiteandindeploysoneit,callno(begin_deploy, uploadfromandyourcommit_deployside.combined).Server-sideUsefetchdeploy_from_urlofwhenathetar(.gz)filesarchivearefromalready published at a publicHTTPSURL,thensuchdeployasitsacontents.repositorySidestepsarchive that holds only thecasebuiltwheresiteyour(nocode-executiondotfiles),sandboxorcanwhenreachyourgithubsandbox/reachesgistthe/allowedS3hostsetc.(listed under archiveUrl) but notmcp.vibedeploy.be's uploadmcp.vibedeploy.be;endpoint.otherwiseEquivalentusetodeploy_sitebegin_deployor→update_site.POSTInuploadUrlreplace→modecommit_deployoneintop-levelonefoldercall.thatHostnamewrapsallowlisteveryenforced;filesee(astheinarchiveUrlrepositorydescription.archives)Replaceismoderemoved,onand a site that already has files needs confirm ⟨11 unchanged words⟩
⟨5 unchanged words⟩ "description":"Public HTTPS URL of a tar(.gz)archive. The serverorfetchestar.gzitarchive (max 100 MB,60s60timeouts). Allowed hosts,parsesalsothefortarballevery redirect: github.com, codeload.github.com, *.githubusercontent.com, gist.github.com, gitlab.com, bitbucket.org, codeberg.org, *.amazonaws.com, *.r2.cloudflarestorage.com, *.backblazeb2.com, *.workers.dev, *.pages.dev, transfer.sh, 0x0.st, mcp.vibedeploy.be. GitHub, GitLab anddeploysCodebergitsarchivefiles.links
⟨12 unchanged words⟩ ,"filesDeployed":{"type":"number"},"manageUrl":{"description":"Dashboard page where the user manages this site (domains, versions, settings).","type":"string"},"mode":{"enum":["replace","patch" ⟨5 unchanged words⟩ ,"siteId":{"type":"string"},"strippedPrefix":{"description":"Top-level folder removed from every archive path (replace mode, when one folder wraps all files).","type":"string"},"url":{"type":"string"}},"required":["siteId","name","url","manageUrl","mode","filesDeployed","bytesFetched","archiveUrl ⟨2 unchanged words⟩
Publish awebsite to a live URL. Deploy astatic site or single-page appyou builtto(withaAIliveorHTTPSbyURLhand)ontotheyouraccount's platform subdomain (e.g. {name}.vibedeploy.beor {name}.vibedeploy.eu)with automatic SSL, and optionally a custom domain. The fastest way to get a localhost project.orAannewAI-generatednamesitecreatesonline.theDESTRUCTIVEsite.onAn existingsites: replaces every file on the named site withnametheREPLACESsuppliedEVERYset.FILEFiles(files not in this call aredeleted. For a new site, createsdeleted) andprovisions it. For an existing site, requiresneeds`confirmconfirm:"I-want-to-replace-all-files"` to proceed; without confirm the call is rejected before;anythingpreviewiswithtouched.dryRun:true. Use update_site(default mode:'patch') if you wantinstead toadd orchangeindividualsome fileswithout removing the rest. Use dryRun:true to preview the diff. LARGE FILES: don't split a big text file across a placeholder deploy +ofchunkedanfollow-upsexisting—site.aA 100-250 KBHTML/CSS/JStext file fits inTHISthis callwhen sentwith encoding:'gzip+base64' (gzip locally, then base64); use begin_deploy only when theresult;filestextdocompressesnot3-5×).fitTheinsiteoneiscall.publishedShipatayourtop-levelplatform404.htmlsubdomainfor multi-page sites (e.g.otherwise{name}.vibedeploy.beunknownorpaths{name}.vibedeploy.euserve index.html).Afteranddeploy,usecallplainadd_custom_domainASCIItofilealsonames. Afterwards add_custom_domain can serveattheasiteuser-ownedonhostname.the user's own domain.
⟨6 unchanged words⟩ :"I-want-to-replace-all-files","description":"Required when thenamedsite alreadyexists. Passexists: exactly \"I-want-to-replace-all-files\"to,acknowledgeconfirming that every existing filewill beis deleted andreplaced with this new fileset.replaced. Omiton first deploy offor a new site.If you want to add or change files without removing the others, use update_site instead — it defaults to patch mode.","type":"string"},"dryRun":{"description":"If true, validate input + introspect what would change but don't write or delete. Returns the same shapeValidatewithand`dryRun:previewtrue`withoutandwriting;
⟨6 unchanged words⟩ :{"created":{"description":"True ifthe sitethiswascall createdby thisthecall.site.","type":"boolean"},"customHeaders":{ ⟨23 unchanged words⟩ :"null"}],"description":"Result ofthe Netlify-style _headers sync: includesyncingathe _headers file in the site rootto override(site-widedefault/* response headers(e.g. Permissions-Policy).Site-wide (/*) rules only."},"deletedFiles":{"description":"Files that existed before this call and were removed by it. Empty forbrand-newasites.new site.","items":{"type":"string"},"type":"array"},"dryRun":{"description":"Trueif this wason
Return the team's plan, its limits,andcurrentusage. Use this BEFORE deploy_site or add_custom_domain to knowusage,whethertheatrialdeployendwoulddatetripandatheplanper-tokenlimit,MCPinsteadrateoflimit.provokingCallPLAN_LIMIT_EXCEEDED.itAlsobeforereturnsdeploy_sitetheorper-tokenadd_custom_domainMCPtorate-limitcheckceilinga(liveplanremaininglimitisinsteadinofX-RateLimit-Remainingrunningresponseintoheader).PLAN_LIMIT_EXCEEDED.
⟨65 unchanged words⟩ :"number"},"mcpCallsPerHour":{"description":"Per-tokenMCPcaptooloncallstotalallowedMCPpertoolhourcalls.perLivetoken; the remainingheadroomcount isalso returnedin the X-RateLimit-RemainingHTTP response header on every call.header.","type":"number"},"sites":{ ⟨31 unchanged words⟩ :"object"},"plan":{"description":"EffectivePlanplanname.
Per-service status ofShow the site's container services: per-service status (ready, restarts,waiting/crashwaiting or crash reasons, volumes), the stored config, the ⟨19 unchanged words⟩ and optionally the recent logs of one service. Use get_app_status instead of get_site for anything about containers.
⟨22 unchanged words⟩ ,"type":"string"},"name":{"description":"Site name as shown by list_sites, e.g. my-portfolio. Provide name or siteId.","type":"string"},"siteId":{"description":"Site id from list_sites or get_site. Use instead of name.","type":"string"},"tail":{"description ⟨14 unchanged words⟩
⟨24 unchanged words⟩ DNS records to publish and their verification status.Submissions:ThePOSTsubmissionJSONformattofor thereturned `endpoint` with Content-Type: application/json (UTF-8). Flat object ofsite's formfields (strings/numbers/booleans; checkbox groups may be arrays of strings, joined with ', '). Max 30 fields, 5000 chars/field, 20000 total. Response: {success:true,data:{ok:true}} or {success:false,error:{code,message}}. Rate limit: 10 submits per IP per 10 minutes. Include a hidden honeypot input (default "_gotcha") andisleavedescribeditunderempty.set_forms_config.
Returnnameone site's details: live URL,urlstatus, plan, served file paths, whether editable source is stored (and its build settings), bandwidth and the lastdeploy10timedeploys. Use get_site to inspect a site before editing it; use list_sites to find site names, andrecentget_app_statusdeployforhistory.container services.
{"$schema":"http://json-schema.org/draft-07/schema#","properties":{"name":{"description":"Site name as shown by list_sites, e.g. my-portfolio. Provide name or siteId.","type":"string"},"siteId":{"description":"Site id from list_sites or get_site. Use instead of name.","type":"string"}},"type":"object"}
⟨15 unchanged words⟩ by this site over the window (usageonly —only; the bandwidth cap is team-scoped, see get_account) ⟨21 unchanged words⟩ ":{"description":"Site-relative paths of everyfile currently on the pod (same scope as `files`). Lets a caller see what's thereservedbeforefile,decidingtowhichpick paths topatch or deleteread,without having to downloadpatchtheorsite.delete. Omitted when thelivepodintrospectioncannotstepbefailsinspected
⟨3 unchanged words⟩ properties":{"name":{"description":"Sitename.name as shown by list_sites, e.g. my-portfolio. Providethisname or siteId.","type":"string"}," ⟨18 unchanged words⟩ integer"},"siteId":{"description":"Siteid.idProvidefromthislist_sites or get_site. Use instead of name.","type":"string"}},"type":"object"}
ReturnList the team's begin_deploy staging sessions,forby default theteamactivethisonestoken(openbelongsandto.committing),Defaultsup tocurrently-active50.onesUseful(openafter+acommitting).crashUpor restart to50commitrows.or abort leftovers.
Read the DNS records VibeDeploy tracks for a site (the records it created/manages on your behalf), oldest first. Returns each record'shost, type,and value. Any team membervalue),includingoldestviewersfirst,canincludingreadcustom-domainDNSverification records.This tool is read-only andRead-only:doesitNOTnevercreatecreates,change,changes ordeletedeletesanya DNS record.
⟨4 unchanged words⟩ :{"name":{"description":"Site nametoaslookshownupbyDNSlist_sites,recordse.g.for.my-portfolio. Provide name or siteId.","type":"string"},"siteId":{"description":"Site idto look upfromDNSlist_sitesrecordsorfor.get_site.ProvideUsenameinsteadorofsiteId.name.
⟨12 unchanged words⟩ records VibeDeploy tracks for this site, oldest first.Read-only — DNS changes are not made through this tool.","items":{"additionalProperties":false,"properties" ⟨70 unchanged words⟩
Return SHA-256+and sizeforof everyfile currently served. Use BEFORE re-deploying to skip filesservedwhosefile.contentBeforehasn'tachanged:redeploy, hash your local files,diff against this listcompare, andonlyuploadshiponly thedifferenceschangedviaones with update_site mode:'patch' or begin_deploy→plus add_files.For SPAs with content-hashed bundle names this typically reduces a full-site redeploy to a handful of files.
⟨4 unchanged words⟩ :{"name":{"description":"Site nameorascustomshowndomain.bySamelist_sites,lookupe.g.rulesmy-portfolio.asProvideget_site.name or siteId.","type":"string"},"siteId":{"description":"Site id from list_sites or get_site. Use instead of name.","type":"string"}},"type":"object"}
Return themostsite'srecentlast 50 deploy and snapshothistoryentriesfor a site, newestfirst. Includes the sourcefirst:(howiteach was triggered),an optionallabel,the associated Longhornsnapshot name(if any),thefile count,andthe number ofsecrets detected. Each entry's snapshot holds the content from BEFORE thatentryentry.(restoringRestoringitisundoesdone by theentry).userAnyinteamthememberVibeDeploycandashboardreadwithinhistory.the plan's restore window; there is no restore tool.
{"$schema":"http://json-schema.org/draft-07/schema#","properties":{"name":{"description":"Site name as shown by list_sites, e.g. my-portfolio. Provide name or siteId.","type":"string"},"siteId":{"description":"Site id from list_sites or get_site. Use instead of name.","type":"string"}},"type":"object"}
⟨53 unchanged words⟩ {"type":"null"}],"description":"Longhorn snapshotSnapshot takenimmediatelyjust BEFORE this entry's change(pre-deploy,pre-promote, pre-restore),so restoring it brings backthe content thatwhat was live before thisentry, not this entry's own content.entry. For manual-snapshot and staging entries it is the live content at that moment. Tobring backgettheancontentolderofdeploy'sanownoldercontentdeployback, use the snapshot of the next newer entry. Null if none was taken orit was pruned
List the team's sites (name, URL, status, last deploy), most recently updated first, up to 100. Use list_sites to find a site name; use get_site fortheoneteamsite'sthisfiles,connectionsourcebelongsstatusto.and history.
⟨4 unchanged words⟩ {"includeDeleted":{"description":"If true,includealso list soft-deleted sites stillininside theirplan-specificplan'srecoveryrestore window (status:'deleted').Defaults to false: deleted sites can't accept deploys, so an agent rarely wants them in a working list. Use true when you specifically need the recoveryDefaultview.false.","type":"boolean"}},"type":"object"}
List theLonghorn volumesnapshotsforof asite.site'sSnapshotsservedarefiles (point-in-timebackupsrestoreofpoints).theNO_VOLUMEsite'smeansservedthefiles.siteAnywasteamnevermemberdeployed.canRestoringlistasnapshots.snapshotReturnsisNO_VOLUMEdoneifby thesiteuserhasinnothevolumeVibeDeployyetdashboard(itwithinhastheneverplan'sbeenrestoredeployed).window.
{"$schema":"http://json-schema.org/draft-07/schema#","properties":{"name":{"description":"Site name as shown by list_sites, e.g. my-portfolio. Provide name or siteId.","type":"string"},"siteId":{"description":"Site id from list_sites or get_site. Use instead of name.","type":"string"}},"type":"object"}
ReturnList path, SHA-256+and sizeforof every file in the site's editable source tree (theplatform's copy of thestored pre-build code, not the serveddistfiles).Use BEFORE editing so you know which paths exist andRead-only.whichAhaven'tsitechangedwithoutsinceathesourcelasttreebuild.returnsautoPromoteSOURCE_NOT_STORED:truewill mirrorwrite theserved dist intosourcefor static-only sites whose source treewithiswrite_source_files,emptyor(doescopynothingplainifstatictheserveddistfileslookswithbuilt).promote_dist_to_source.
⟨3 unchanged words⟩ ,"properties":{"autoPromote":{"description":"If trueDeprecated andthe site has no source tree yet but its dist looks static, copy dist → sourceignored.onUsethepromote_dist_to_sourcefly.withDefault:modefalse.'auto'.","type":"boolean"},"forcePromote":{"description":"If true, mirror dist → source EVEN when dist looks built (e.g. minified Vite output). Use when the original source isn't recoverableDeprecated andyou're willing to edit the build artefact directly. Sets manifest.noBuild=true automatically when noignored.package.jsonUseispromote_dist_to_sourceinwiththe
{"$schema":"http://json-schema.org/draft-07/schema#","additionalProperties":false,"properties":{"autoPromoted":{"description":"Set to true when this call ran the auto-promote (dist → source) before listing. Lets the caller learn the source tree was just synthesised from the served dist.","type":"boolean"},"files":{"items":{"additionalProperties":false," ⟨14 unchanged words⟩ ,"type":"object"},"type":"array"},"hint":{"description":"Set when the deprecated autoPromote or forcePromote flag was passed.","type":"string"},"name":{"type":"string"} ⟨17 unchanged words⟩
Returnthe bytes ofone filecurrently served bythesite. Use this to inspectsiteorserveseditnow,existingascontenttext (callutf8)read_fileor→base64modifyfor→binaryupdate_sitefiles,mode:'patch')e.g.sotoaeditnewitchatandcansenditerateitonbackawithsiteupdate_sitewithoutmode:'patch'.re-uploading.UseFilesread_filelargerforthanthe5242880servedbytesfiles;can'tuseberead_source_filereadinsteadinforonethecall.editableUsesourcelisttreeof(get_site.sourceStored).pathsMaxfrom5242880get_site.filePathsbytes;toget_site.filePathsdiscoverlistswhat'stheavailable.paths.
⟨4 unchanged words⟩ :{"maxBytes":{"description":"Per-file sizecap.cap in bytes. Default 1048576,hardmax 5242880.If the file isA larger,the callfile fails with FILE_TOO_LARGEratherinsteadthanof returning truncatedbytes — splitting source mid-token would corrupt downstream edits.bytes.","exclusiveMinimum":0,"maximum":5242880,"type":"integer"},"name":{"description":"Site name(subdomain)asorshowncustombydomain.list_sites,Samee.g.lookup
⟨8 unchanged words⟩ :"string"},"encoding":{"description":"How to interpret `content`.utf8means the file is text and: `content` is therawtext. base64means: the file is binary (image/font/etc.image, font, ...) and `content` isbase64 —base64; decode before use.","enum":["utf8" ⟨46 unchanged words⟩
Batched version of read_file. PassRead up to 50paths;servedeachfilesisinfetchedoneindependentlycall, with the same per-file rules asread_file. The whole batch is cappedread_fileatand 8388608 bytestotal —inoncetotal;that'spathsexhausted,pastremainingthepathsbudget fail with BATCH_BUDGET_EXCEEDED, sothe agent can re-requestrequest them again in another call. Use read_source_files instead for the editable source tree.
⟨3 unchanged words⟩ properties":{"maxBytesPerFile":{"description":"Per-filecap.size cap in bytes. Default 1048576,hardmax 5242880.","exclusiveMinimum":0,"maximum":5242880,"type":"integer"},"name":{"description":"Site name as shown by list_sites, e.g. my-portfolio. Provide name or siteId.","type":"string"},"paths":{"description" ⟨18 unchanged words⟩ 1,"type":"array"},"siteId":{"description":"Site id from list_sites or get_site. Use instead of name.","type":"string"}},"required":[" ⟨3 unchanged words⟩
⟨34 unchanged words⟩ ":"One entry per requested path, inthe sameorder.Each entry is independent: aA missingfileor oversized file fails only its ownentry but does not abort the wholeentry;batch.entriesIfpast thecumulativebyte budgetis exhausted partway through, remaining entriesfail withcodeBATCH_BUDGET_EXCEEDED.","items":{"anyOf":[{" ⟨97 unchanged words⟩
Returnthe bytes ofonesourcefile(from theplatform'ssite's editablecopysourceoftree (the stored pre-build code),letting an AI inso anyfuturechatfetch andcan editcontentthewithoutsiteneedingwithout the original local files.Uselist_source_filesfirst toshowsdiscoverthe paths.ForUsetheread_source_fileservedfordist,source; use read_fileinstead.instead for the files the site serves.
⟨4 unchanged words⟩ :{"maxBytes":{"description":"Per-file sizecap.cap in bytes. Default 1048576,hardmax 5242880.","exclusiveMinimum":0,"maximum":5242880,"type":"integer"},"name":{"description":"Site name as shown by list_sites, e.g. my-portfolio. Provide name or siteId.","type":"string"},"path":{"description":"Site-relative pathPath inside the source tree, e.g. 'src/App.tsx'.","type":"string"},"siteId":{"description":"Site id from list_sites or get_site. Use instead of name.","type":"string"}},"required":[" ⟨3 unchanged words⟩
BatchedReadreadupacrossto 50 files from the editable source tree in one call (up8388608tobytes50inpathstotal). Eachentrypathissucceedsindependent:orafailsmissing/oversizedonfileitsfailsown;itspathsownpastslotthebutbudgetdoesn'tfailabortwiththeBATCH_BUDGET_EXCEEDED.batch.UseCumulativeread_source_filescapfor8388608source;bytes;useremainderread_filesfailsinsteadwithforBATCH_BUDGET_EXCEEDED.the files the site serves.
{"$schema":"http://json-schema.org/draft-07/schema#","properties":{"maxBytesPerFile":{"description":"Per-file size cap in bytes. Default 1048576, max 5242880.","exclusiveMinimum":0,"maximum":5242880,"type":"integer"},"name":{"description":"Site name as shown by list_sites, e.g. my-portfolio. Provide name or siteId.","type":"string"},"paths":{"description":"Paths inside the source tree, e.g. 'src/App.tsx' (1 to 50). Results keep this order.","items":{"type":"string"},"maxItems":50,"minItems":1,"type":"array"},"siteId":{"description":"Site id from list_sites or get_site. Use instead of name.","type":"string"}},"required":[" ⟨3 unchanged words⟩
⟨70 unchanged words⟩ applied atomically (patch mode). Images alreadyhostedonvibedeploy.bea VibeDeploy platform domain are skipped.
⟨4 unchanged words⟩ :{"name":{"description":"Site name(subdomain)as shown by list_sites, whose external imagesshould beare downloaded andrehostedstoredlocally.on the site.","type":"string"}},"required": ⟨3 unchanged words⟩
StopsStop every container serviceandofservesthe site; thesite'ssite serves its static files again. Volumes (database data) are kept unless deleteData is true, whichisdeletesirreversible.them for good. Use remove_app to stop only the containers; use delete_site to remove the whole site.
⟨18 unchanged words⟩ ,"type":"boolean"},"name":{"description":"Site name as shown by list_sites, e.g. my-portfolio. Provide name or siteId.","type":"string"},"siteId":{"description":"Site id from list_sites or get_site. Use instead of name.","type":"string"}},"type":"object"}
RemoveDetach a custom domain from a site. The site itself isunaffected;unaffectedonlyandthekeepscustomservinghostnameonisitsdetached.platformThesubdomain (e.g. {name}.vibedeploy.besubdomain keeps serving the site.).
⟨5 unchanged words⟩ :{"description":"The custom domain to remove,(e.g.'tester.subsite.site').'shop.example.com'. Provide thisORor recordId.","type":"string"},"recordId":{"description":"The recordId returned byadd_custom_domain.add_custom_domain or list_custom_domains. Provide thisORor domain.","type":"string"},"siteName" ⟨14 unchanged words⟩
Search every file of a site for a literal string orbasic regex across all filesainregulareitherexpression: the serveddistfiles by default, or the editable sourcetree. Use this BEFORE batch-reading files to find candidates — saves the 'readtree14withbatchestargetjust'source'.toUsefinditwhichbefore3reading filesmatter' round trip. Pass `target:in"source"`bulk, tosearchfind theeditable treeones(requiresthatSite.sourceStored=true).matter.
⟨3 unchanged words⟩ ,"properties":{"caseInsensitive":{"description":"Default: false. When true,Ignoreaddsupper/lower-icase.toDefaultgrep.false.","type":"boolean"},"glob":{"description":"FilenameFileglobname filter, e.g. '*.js' or '*.{js,html}'.Applied via find before grep so we don't read non-matching files.","type":"string"},"maxMatches":{ ⟨19 unchanged words⟩ ,"type":"integer"},"name":{"description":"Site name as shown by list_sites, e.g. my-portfolio. Provide name or siteId.","type":"string"},"pattern":{"description":"PatternText tosearch for. Treated literal by default; passfindregex:true(ASCII,tomax
⟨51 unchanged words⟩ ,"type":"string"},"enabled":{"description":"Send the confirmation email.","type":"boolean"},"message":{"description":"Text of the confirmation email.","maxLength":2000,"type":"string"},"subject":{"description":"Subject of the confirmation email.","maxLength":200,"type":"string"}}," ⟨55 unchanged words⟩ string"},{"properties":{"field":{"description":"Form field that holds the Reply-To address.","maxLength":100,"type":"string"}}," ⟨16 unchanged words⟩ \"<formField>\" }."},"requiredFields":{"description":"Form fields that must be filled in.","items":{"maxLength":100,"type":"string ⟨10 unchanged words⟩ email":{"description":"From address, e.g.support@serso.be. Onlysupport@example.com.honoredUsed once its domain is verified (verify_forms_sender_domain)ORor an smtpRelay is set;otherwise mailuntilfallsthenbackmailtouses the platform address.","type":"string"},"name":{"description":"Display name, e.g. \"Serso ServiceAcmePortal\Support\".","maxLength":100,"type":"string ⟨16 unchanged words⟩ Your server then owns SPF/DKIM. Recipients stay server-side,—so this is not an open relay.","properties ⟨70 unchanged words⟩ "none\" = plaintext, \"starttls\" =upgradeSTARTTLS on a plain connection, \"tls\" = implicit TLS.","enum ⟨19 unchanged words⟩ ,"type":"object"},"subject":{"description":"Subject of the lead email.","maxLength":200,"type":"string"},"template ⟨63 unchanged words⟩ ,"type":"array"},"footerText":{"description":"Text below the submitted fields.","maxLength":2000,"type":"string"},"headerText":{"description":"Text above the submitted fields.","maxLength":2000,"type":"string"}," ⟨60 unchanged words⟩
Applyone or moreliteral find/replace edits toa singleone fileon the site,in onetool call. Designedcall, fortinysmalleditschanges where uploading thefullwhole filewould be wasteful (one nav-button reference, one encoding fix, one env varisbump).wasteful. Each editmust specifystates how many matches it expects;mismatchesanyabortmismatchtheabortswholethe call withNOno writes.ForServed-file (dist) editsthe change goesgo liveimmediately;atforonce; source editsyoushipstillwithneedbuild_and_deploy.toUsecallapply_editsbuild_and_deploy.for several files.
⟨3 unchanged words⟩ properties":{"edits":{"description":"Orderedlist ofeditsto apply atomically. Each is`{find, replace, count?}`.`,Ifappliedanytogether;edit'sif any match countdoesn't equal its expected countdiffers,the whole call aborts withnothingnoiswrites.written.","items":{"properties":{"count":{"description":"Expectednumber of matches.matches:Defaultdefault 1 (failfailsifon
Patch or replaceChange files on an existing site.DefaultsDefaulttomodepatch'patch'mode:writes only the listed fileschange; everything else stays. Pass mode:'replace' to wipe-and-replace the wholeandsitekeeps(thelegacy behaviour, surfaced explicitly so it can't happen by accident). Userest; `delete: [paths]`inremovespatchfiles. mode:'replace'todeletesremoveeveryspecificfilefilesnotwithoutlisted.wipingPreviewthewithrest.dryRun:true. Use`dryRun:deploy_sitetrue`instead topreview the diff beforecreatecommitting.aLARGEnewFILES:site.aA 100-250 KB text file fits in one call with encoding:'gzip+base64' (gzip locally,base64 thethenresultbase64)—; prefer that over begin_deploy+plusadd_file_chunkadd_file_chunk.streaming.FailsErrorswithifSITE_NOT_FOUND when the site does not exist.
⟨3 unchanged words⟩ ,"properties":{"delete":{"description":"Patch-modePatch mode only: site-relative paths toremove from the pod. Files not in this list are kept. Reported back in `deletedFiles` listing only entriesremove;thatotheractuallyfilesexisted.stay. Combine with `files` toatomicallyrename in onecall (write new path + delete old path).call. Rejected inmode:'replace' sincereplacealready removes anything not in `files`.mode.","items":{"type":"string"},"type":"array"},"dryRun":{"description":"If true, validate input + introspect what would change but don't write or delete. Returns the same shapeValidatewithand`dryRun:previewtrue`
⟨30 unchanged words⟩ :"null"}],"description":"Result ofthe Netlify-style _headers sync: shipsyncingathe _headers file in the site rootto override(site-widedefault/* response headers(e.g. Permissions-Policy).Site-wide (/*) rules only."},"deletedFiles":{"description":"Files removed by thiscall. For patch mode this iscall: theentries from`delete`that actually existed;entriesforthatreplaceexistedmode(patch),it'sor everypre-existingfile not in`files`.`files` (replace).
Check the TXT recordthe user added at stepfrom1add_custom_domain and,ifwhenfound,itattachisthefound,domainstarttoserving thesite's ingress. If verification fails,sitetheonmostthatcommondomaincause(HTTPS isDNSissuedpropagationautomaticallydelay;withinwaitabouta30fews).minutesIfandittryfails,again.DNSOncehasverified,usuallythenotdomainpropagatedservesyet:thewaitsiteaimmediatelyfew(HTTPSminutesissuesandautomaticallycallwithinit~30s).again.
⟨46 unchanged words⟩ address. DNS can take a few minutes topropagate —propagate; re-run if it fails the first time. Not ⟨8 unchanged words⟩
StageWriteeditsortooverwriteafiles in the site's editable source tree (notthelive dist). Use list_source_filesfirstto discoverwritewhat'screatesthere.it). Thedist is unchanged until youservedre-deployfilesviadoupdate_sitenotorchangerununtilbuild_and_deploy.build_and_deploySitesruns.haveUsesourcelist_source_filesstoragefirstenabledtobyseedefault;whatifexists.aA legacy sitedoesn't, the callwithoutfailssourcewithstorageSOURCE_STORAGE_NOT_ENABLEDreturnsandSOURCE_STORAGE_NOT_ENABLED; the usershouldcancontactask VibeDeploy support to enable it.
⟨38 unchanged words⟩ "items":{"properties":{"content":{"description":"File content: text, or base64 as set by encoding.","type":"string"},"encoding":{"description":"utf8 (default)for plain text., base64for(binaryfiles. gzip+base64 for textfileswhere you want to fit ~3x more bytes per),toolorcall:gzip+base64 (gzipthe raw bytes firstlocally, thenbase64-encode. Server gunzips before writing. Useful for shipping bigger source filesbase64;whenfitsyou'reabouthitting3xthemoreper-call
Copy a site's served files into a new source tree — Create the editable source tree of a site that has none by copying the files it serves, so later changes can use write_source_files, apply_edits(target:'source') and build_and_deploy. The served files do not change, and a site that already has source is left as is. Use mode 'force' only after telling the user that build output (minified bundles) is not original source.
⟨213 unchanged words⟩ \"postgres://app:$(DB_PASSWORD)@db:5432/app\".SiteSecrets from outside (API keys, OAuth client secrets,settokens) never go in the config, the source or the chat: the user adds them in the VibeDeploy dashboardare(theinjectedsite's Settings tab, section Secrets; get_app_status returns the direct link as secrets.manageUrl). Every service gets them as env varstoo.and restarts automatically; an explicit env entry with the same name wins. get_app_status lists the secret names that are set, never their values. Volumes persist across deploys; everything else is recreated. ⟨57 unchanged words⟩
⟨9 unchanged words⟩ waiting/crash reasons, volumes), the stored config, the names of the site secrets that are set (never values) with the dashboard link where the user adds them, and optionally the recent logs of one service.