AdAnvil
PYPI · ADANVIL
Lets an AI agent edit vertical 9:16 video ads from your footage, a reference ad or an idea.
Available components
Last scanned (20 hours ago)
Scores higher than 64% of PyPI servers
Category Design and Media
How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →
Supply Chain Security100
- No malware found by supply-chain analysis.Pass
- No known CVEs affecting this package version or its production dependencies.Pass
- Runs hatchling.build at install time, a recognised build step with no custom scripting around it. View diagnostics → Pass
- 1 of 31 dependencies flagged as unhealthy. View diagnostics → Partial
Provenance & Transparency48
- Source repository is publicly reachable at the declared URL. View diagnostics → Pass
- Provenance check failed: no build-provenance attestation is published. See how to fix → View diagnostics → Fail
- Clear OSI-approved license (MIT).Pass
- Actively maintained (last published 0 days ago).Pass
- Publishes a security disclosure policy (SECURITY.md).Pass
Schema Quality & AI Usability50
- AI-judged instruction clarity (good).Pass
- Context-footprint check failed: tool/resource definitions use about 11894 tokens (~276/item across 43 items; 43 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management10
- Stability observed for 3 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage67
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 0% of tool parameters carry a description.Fail
Tool Safety75
- No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
- 0 of 1 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation; "library_annotate" implies "merge" and declares no destructiveHint at all, which the MCP spec reads as destructive by default. See how to fix → Fail
- An AI judge read all 44 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a current MCP spec version (2026-07-28).Pass
Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 17 Oct 26 +1
- Security disclosure: fail → pass ▲ functional
- 16 Oct 26 +24
- Injection markers: unverified → pass ▲ security
- First check of Judged manipulation: pass security
- Tool safety: Tool safety not yet verified: we do not have a sandbox capture of the tool definitions this version of the package serves yet. security
- Stability: Stability not yet verified: we do not have a sandbox capture of the MCP schema this version of the package serves yet. security
- Tool coverage: unverified → 100 ▲ functional
- Stability: unverified → 0.07 ▲ functional
- MCP protocol: unverified → pass ▲ functional
- First check of Tool coverage: 0 functional
- First check of Schema quality: fail functional
- First check of Schema quality: fail functional
- First check of Destructive annotations: 0 functional
- First check of Schema quality: good functional
- Capabilities: Protocol version not yet verified: we do not have a sandbox capture of the MCP handshake this version of the package performs yet. functional
- Tool coverage: Tool coverage not yet verified: we do not have a sandbox capture of the tool definitions this version of the package serves yet. functional
- Schema quality: Schema quality not yet verified: we do not have a sandbox capture of the MCP schema this version of the package serves yet. functional
- Package version: 0.3.0 → 0.3.1 functional
- 15 Oct 26 0
- Stability: Stability not yet verified: this package installed, but its server did not start, so we have no schema to compare. security
- Tool safety: Tool safety not yet verified: this package installed, but its server did not start, so we have no tool text to scan. security
- Schema quality: Schema quality not yet verified: this package installed, but its server did not start, so we have no schema to assess. functional
- Capabilities: Protocol version not yet verified: this package installed, but its server did not start, so we never saw its MCP handshake. functional
- Tool coverage: Tool coverage not yet verified: this package installed, but its server did not start, so we have no tool definitions to assess. functional
- 14 Oct 26 0
- Injection markers: unverified → pass ▲ security
- First check of Judged manipulation: pass security
- Stability: Stability not yet verified: not enough scan history yet (needs a 30-day window). security
- Tool coverage: unverified → 100 ▲ functional
- MCP protocol: unverified → pass ▲ functional
- First check of Tool coverage: 0 functional
- First check of Schema quality: fail functional
- First check of Schema quality: fail functional
- First check of Destructive annotations: 0 functional
- First check of Schema quality: good functional
- Package version: 0.2.0 → 0.3.0 functional
- 13 Oct 26 39
First indexed and scored.
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 17 Oct 2026 · Analysed pypi/adanvil@0.3.1
Provenance No attestation
The registry publishes no build provenance for this version, so there is nothing to verify.
| Result | No attestation |
|---|---|
| Ecosystem | pypi |
| Reason | No attestation published |
Background: How many MCP packages publish verified provenance →
Install scripts 1 script
| Hook | Tier | Command |
|---|---|---|
| build_backend | allowlisted | hatchling.build |
Background: Why install scripts are a supply-chain risk →
Dependencies 31 packages
| Packages resolved | 31 |
|---|---|
| No linked repository | 1 |
| Tree resolution | Complete |
Background: SBOMs and build attestations, explained →
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
ad_score ~450
Score a rendered ad out of 100 for creative quality, with findings to fix. ``qc_run`` says the file is technically correct; this says whether the ad is any good: a first second that holds attention (motion or a cut, a face or the product, a text within 0.5 s, audio at once), a pacing without a dip in the middle, captions that can be read (0.25 s per word + 0.6 s, 7 words a line at most, contrast of 3:1 or more on the real frames), the problem before the product, a call to action and an end card in the last 4 s, overlays out of the platform interface (``platforms``: any of ``tiktok``, ``reels``, ``stories``, ``feed``; the first three by default, ``feed`` for a 4:5 or 1:1 video) and a clear loudness, a voice 6 dB over the music and no silence over 0.7 s. Pass the ``storyboard`` it was rendered from (object or saved path) for exact timings, words, roles and overlays; without it the checks that need them are listed in ``skipped``. The result has ``score``, ``sub_scores`` (hook, pacing, reading, story, safe_zones, audio), ``findings`` sorted by ``impact`` (each with ``time``, ``severity``, ``message`` and ``fix``), ``passed``, ``skipped``, the pixel boxes of the ``safe_zones`` and the ``thresholds`` (guidelines, not rules). Images: ``safe_zones_preview.jpg`` (the zones of each platform over a mid-ad frame, red where an overlay falls inside) and the frame of each top finding: LOOK at them. Run it before delivery, fix the top findings, render again, and aim for 80 or more.
| Name | Type | Req | Description |
|---|---|---|---|
| platforms | – | – | – |
| project_dir | string | yes | – |
| storyboard | – | – | – |
| video | string | yes | – |
No output schema declared.
No examples provided.
brand_get ~126
Read the current brand profile and brief. Use this before writing captions or storyboards so copy follows the brand defaults and constraints. ``brand.product_versions`` says how to tell the product versions apart (match it with the ``product_version`` annotation of library entries). ``brand.cta_image`` is the brand's ready-made call-to-action image, to use as the last segment. ``emoji_available`` lists the emoji characters of the brand's emoji folder, or is "all" for twemoji (and empty for none).
| Name | Type | Req | Description |
|---|---|---|---|
| project_dir | string | yes | – |
No output schema declared.
No examples provided.
brand_onboard ~142
Run brand onboarding step one or two. Use without answers to discover site facts and questions, then call with answers to write brand.yaml and brand_brief.md. Use open_questions to decide what the human must answer. ``facts`` is a compact summary of the site (title, colours, fonts, headings, prices, guarantee phrases, a few products); the complete facts are saved in ``facts_file`` (brand/site_facts.json): read it with project_read_text only when you need more. ``more`` counts what the summary left out.
| Name | Type | Req | Description |
|---|---|---|---|
| answers | – | – | – |
| project_dir | string | yes | – |
| url | – | – | – |
No output schema declared.
No examples provided.
caption_preview ~357
Render a caption or comment over a real 9:16 frame. Use it before rendering to inspect placement; the JSON reports bbox, fitted size, overflow and final lines. ``emoji`` takes the storyboard ``emoji`` values (twemoji, none or a project folder) so the preview matches the render; ``emoji_missing`` lists emoji absent from a folder. For a ``voice_captions`` overlay pass ``manifest``: the ``audio.voice`` path of your storyboard (voice/<name>/manifest.json); ``expanded`` lists the resulting captions once. A ``speech_captions`` overlay is built from the speech of the clips: pass ``chunk_index`` to pick the caption to draw and ``storyboard`` (a project path such as ``storyboards/<name>.json`` or the object) so the timeline is the one of your ad; without it the captions are those of ``source`` played whole. ``expanded`` lists them all. An animated caption (``animation`` ``karaoke``, ``word`` or ``pop``) is drawn in one of its states, to check where the highlight lands: put ``chunk_index`` and ``word_index`` in the overlay object to pick the chunk and the lit word, or leave them out to get the state on screen at timeline time ``t``. The result names the ``word_index``, the ``window`` of the state and how many ``states`` the chunk has.
| Name | Type | Req | Description |
|---|---|---|---|
| emoji | – | – | – |
| overlay | object | yes | – |
| project_dir | string | yes | – |
| source | string | yes | – |
| storyboard | – | – | – |
| t | number | yes | – |
No output schema declared.
No examples provided.
compare_pair ~302
Measure how different a before and an after look, to rank candidate pairs. ``before`` and ``after`` are project files: images, or clips (the frame at ``before_t`` / ``after_t`` seconds, the middle of the clip by default). ``before_crop`` / ``after_crop`` (``{x, y, w, h}`` in source pixels) cut one half out of a side-by-side composite, the same crop a ``reveal`` side takes. The comparison is made on the face when a skin-region heuristic finds one in both pictures (so a different distance still lines up), else on the whole frame after aligning sizes. ``visible_difference`` is 0 to 100 (under 12 not visible, under 30 subtle, under 55 visible, above that obvious at a glance); ``region`` says what was compared. The preview image shows the two pictures side by side: LOOK at it. Compare every available pair (photos, composites split with ``crop``, frames of before/after clips) and use the one whose difference is obvious; a still pair of the same pose beats moving clips for a reveal.
| Name | Type | Req | Description |
|---|---|---|---|
| after | string | yes | – |
| after_crop | – | – | – |
| after_t | – | – | – |
| before | string | yes | – |
| before_crop | – | – | – |
| before_t | – | – | – |
| project_dir | string | yes | – |
No output schema declared.
No examples provided.
editing_guide ~35
Return the editing doctrine for footage, copy, rendering and QC. Read it before the first storyboard and whenever a rule is unclear.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
end_card ~412
Compose a clean end card image from a real product photo. Use it only when the brand has no ready-made call-to-action image: when it has one (``brand.cta_image``, a ``cta/`` folder or ``brand/``), use that image as the last segment (``image``, ``zoom_in``, about 3 s) instead. It writes ``brand/endcards/<name>.png`` (1080x1920 unless ``spec.format`` says otherwise) and returns the path, the layout boxes and the image: LOOK at it. ``spec``: ``product_image`` (project path of a photo or a video, with ``t`` for the frame, optional ``crop`` {x,y,w,h} in the source's display pixels, before scaling: on a 1920x1080 frame ``{"x": 600, "y": 100, "w": 700, "h": 700}`` keeps a 700 px square; the result returns ``source_size`` [w, h] to measure it), ``pill``, ``title`` (a string or runs ``{text, accent}``), ``subline``, ``badges`` (up to 3, ``{text, icon: check|star|none}``), ``button`` (``{text, arrow: down|right|none}``), colours ``accent``, ``text``, ``muted``, ``background`` (two colours), ``family``, ``emoji``. Colours default to the brand's. Banned words of the brand on any text are an error. Use the PNG as the last segment: ``type: image``, ``motion: zoom_in``, about 3 s, label ``end_card``, no subtitles on it.
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | yes | – |
| project_dir | string | yes | – |
| spec | object | yes | – |
No output schema declared.
No examples provided.
frame_view ~213
Extract one full-resolution frame from a project video or image. Give the time ``t`` (seconds) or the frame number ``frame`` (video only, counted from 0). Returns the frame ON SCREEN at ``t`` (``floor(t * fps)``): at 2.87 s of a 30 fps video that is the frame starting at 2.867 s, not the next one at 2.900 s. A ``t`` within 1 ms of a frame boundary is that frame (10.9333 s at 30 fps is frame 328), so a time printed to four decimals lands on the right frame. ``frame_t`` is the frame's exact start time and ``frame`` its number (video only). Use it to inspect the exact moment behind a timecode; the saved frame is under cache/frames/.
| Name | Type | Req | Description |
|---|---|---|---|
| frame | – | – | – |
| project_dir | string | yes | – |
| source | string | yes | – |
| t | – | – | – |
No output schema declared.
No examples provided.
job_status ~259
Read a queued, running, completed or failed render, batch, voice, index or refine job. With ``wait_seconds`` greater than zero, wait in this call (up to 600 seconds) instead of polling from the client; if the connection drops, just call again, a restarted server still finds the job. Pass ``project_dir`` when it says "job not found". Completed index jobs carry the compact index summary; completed speech_refine jobs carry ``refine`` (refined clips, skipped clips with the reason, errors). Completed render jobs include the persisted RenderReport JSON; batch jobs (``render_batch``, ``render_formats``) carry ``batch``: one entry per render (status, file, format, duration, score, seconds, error) as they finish, then ``total_seconds``, ``cache_builds`` and the ``manifest`` path; completed voice jobs include each manifest line and its warnings. If a line is ``suspect``, an agent cannot listen to it: regenerate with slightly different wording, or accept it when the transcript differs only in punctuation.
| Name | Type | Req | Description |
|---|---|---|---|
| job_id | string | yes | – |
| project_dir | – | – | – |
| wait_seconds | number | – | – |
No output schema declared.
No examples provided.
library_annotate ~400
Merge annotations into one catalogue entry. Parameters: ``project_dir`` (str, absolute project path), ``entry_id`` (str, catalog entry id), ``description`` (str or null), ``tags`` (list[str] or null), ``people`` (list[str] or null), ``product_visible`` (bool or null), ``product_version`` (short free string such as ``current``, ``old`` or ``v2``, or null), ``emotion`` (list of what the faces express, a clip can show several: none, neutral, worried, frustrated, sad, tired, closed, skeptical, shocked, curious, relaxed, happy, satisfied; the same words as the breakdown, the segments and the search filter, anything else is refused; or null), ``quality`` (int 1-5 or null), ``usable`` (list of ``[start, end, note]``, ``[start, end]``, or objects with ``start``, ``end`` and ``note``; or null), ``notes`` (str or null), ``exclude`` (bool or null), and ``exclude_reason`` (str or null). Example: ``library_annotate('/abs/project', 'clip-a1b2c3', tags=['hero'], quality=5, usable=[[1.2, 3.4, 'clear demo']])``. Use after looking at the contact sheet; search can then filter by tags, people, product version, emotion, quality and exclusion.
| Name | Type | Req | Description |
|---|---|---|---|
| description | – | – | – |
| emotion | – | – | – |
| entry_id | string | yes | – |
| exclude | – | – | – |
| exclude_reason | – | – | – |
| notes | – | – | – |
| people | – | – | – |
| product_version | – | – | – |
| product_visible | – | – | – |
| project_dir | string | yes | – |
| quality | – | – | – |
| tags | – | – | – |
| usable | – | – | – |
No output schema declared.
No examples provided.
library_index ~655
Index or refresh media under a project-relative folder or file. Use it before selection. ``source`` is a folder or a single media file. Up to 8 new or changed files are indexed in this call; more than 8 run as a detached job and the call returns at once with ``job_id`` (wait with job_status(job_id, wait_seconds=90), progress is per file). The result is compact: counts, one line per new or updated entry (id, path, duration, people, product_visible, ``speech`` when the clip speaks) and errors. Contact sheets are not sent inline: use library_view, or library_search with full=true for entries in full. ``transcribe`` controls the speech of the clips: "auto" (default) transcribes, with word timestamps, the clips that have an audio stream that is not near-silent; true transcribes every clip with an audio stream; false does no speech work. It uses faster-whisper when installed, else the voice environment (adanvil voice-setup); with neither, entries get a clear ``speech`` status ("unavailable: ...") and indexing still succeeds. The model is ADANVIL_SPEECH_MODEL (default base: fast, good enough to search) and the language is the brand language, else auto-detected; the brand name, the product name and ``speech.vocabulary`` of brand.yaml are given to the transcriber. The speech of each file is saved as soon as that file is transcribed, so library_search(text=...) works while the job runs (stage "transcribing"). Words are right about nine times in ten: run speech_refine on the clips you will use before captioning. Audio files (.m4a, .wav, .mp3, .aac) are indexed as ``audio`` entries, with their speech, and can be used as ``audio_from`` sources. A video whose sound is silent gets the speech status ``silent_audio`` and, when audio files with a similar name are nearby, ``separate_audio_candidates``. The result has a ``speech`` count by status. ``vision`` controls the vision pass: with the vision environment installed (``adanvil vision-setup`` or the tool ``vision_setup``) each…
| Name | Type | Req | Description |
|---|---|---|---|
| project_dir | string | yes | – |
| source | string | – | – |
| transcribe | – | – | – |
| vision | – | – | – |
No output schema declared.
No examples provided.
library_overview ~159
Overview of the footage folders without indexing, plus a mosaic. Lists folders up to ``depth`` with file, video and image counts, total video seconds and first file names. With ``mosaic``, returns a labelled thumbnail mosaic of the media under ``path`` (48 per page, 6 columns); ``pages`` tells how many, call again with ``page`` to see the next ones. Run it on the whole footage tree (B-roll folders included) to find each shot type the reference breakdown needs, before choosing shots.
| Name | Type | Req | Description |
|---|---|---|---|
| depth | integer | – | – |
| mosaic | boolean | – | – |
| page | integer | – | – |
| path | string | – | – |
| project_dir | string | yes | – |
No output schema declared.
No examples provided.
library_search ~453
Search indexed footage using annotations and technical metadata. Use the returned entries to choose clips without rescanning the filesystem. Each result is one compact line (id, path, duration, people, product_visible, version, emotion, quality); ``full=true`` returns the entries in full. ``product_version`` and ``emotion`` (a list: every listed emotion must be on the clip) filter on what was set with library_annotate; without a human ``product_version`` annotation the guess made from the brand's reference photos is used (a human annotation always wins). ``auto_tags`` filters on the automatic tags of the vision pass (English labels such as ``bathroom`` or ``smiling``; common French, Spanish and German words are understood). ``query`` searches by SENTENCE across the whole library, with no sheet to open: ``query="a woman with a sad face touching her jaw"`` (any language) ranks SHOTS by text-image similarity and returns the best ``limit`` (default 12, at most 48) as ``results`` (entry, shot, start, end, time of the best frame, score) plus ONE mosaic image of those frames, numbered like the list. All the other filters apply first. It needs the vision environment (``vision_setup``) and entries indexed with it (``library_index``); ``missing_vision`` counts the entries that have no vision data yet. Look at the mosaic, then library_view the entry to confirm before choosing. The score is a centred match probability: 0.5 and more is a clear match, under 0.1 means nothing in the library looks like it.
| Name | Type | Req | Description |
|---|---|---|---|
| auto_tags | – | – | – |
| emotion | – | – | – |
| full | boolean | – | – |
| include_excluded | boolean | – | – |
| kind | – | – | – |
| limit | integer | – | – |
| min_duration | – | – | – |
| min_quality | – | – | – |
| people | – | – | – |
| product_version | – | – | – |
| product_visible | – | – | – |
| project_dir | string | yes | – |
| query | – | – | – |
| tags | – | – | – |
| text | – | – | – |
No output schema declared.
No examples provided.
library_view ~66
Return one catalogue entry and its contact sheet. Use it when a summary identifies a candidate; LOOK at the image before choosing a shot. An audio entry has no sheet: only its data is returned.
| Name | Type | Req | Description |
|---|---|---|---|
| entry_id | string | yes | – |
| project_dir | string | yes | – |
No output schema declared.
No examples provided.
music_beats ~197
Beat times of a music track, as it will play in the ad. ``path`` is a project file (audio, or a video whose soundtrack is the music). ``start`` is the storyboard's ``audio.start``: the times are in seconds from the start of the ad, so beat 0 of the result is the first beat heard. They come from the onset envelope and the estimated tempo, on a regular grid whose phase is aligned to the strongest onsets (within a few milliseconds on a steady beat). ``duration`` limits the analysis (default the first 120 s). A track without a steady beat (a piano, a pad) returns no beats. Cut on these times for a music-led ad, or let ``storyboard_snap`` do it.
| Name | Type | Req | Description |
|---|---|---|---|
| duration | – | – | – |
| path | string | yes | – |
| project_dir | string | yes | – |
| start | number | – | – |
No output schema declared.
No examples provided.
music_fetch ~265
Download a track from ``music_search`` into ``music/``, with its licence. ``source`` and ``id`` come from the search result. Writes ``music/<file>``, the record ``music/<file>.licence.json`` (source, id, URL, title, author, licence, licence URL, attribution text, fetch date) and a line in ``music/LICENCES.txt``, then profiles the track: the answer has ``path`` (the ``audio.music`` value), ``duration``, ``tempo_bpm``, ``feel`` and ``loudness_lufs``. A licence that is not CC0, PDM, CC BY or CC BY-SA is refused. An embedded cover picture is removed from the stored file. The render and ``ad_score`` read the record (the sidecar, else the track's line in ``LICENCES.txt``): ``music_licence_unknown`` when a track has neither, ``music_attribution_required`` (with the exact text) when it needs one. Freesound serves its high-quality MP3 preview (the original needs a login).
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | – |
| project_dir | string | yes | – |
| source | string | yes | – |
No output schema declared.
No examples provided.
music_generate ~193
Make an instrumental track locally (optional ACE-Step environment), as a job. Needs ``adanvil music-setup`` (about 3 GB of packages, then 8 GB of weights at the first run). ``prompt`` is a list of tags ("upbeat acoustic guitar, warm, 110 bpm, instrumental"); ``duration`` 10 to 120 s. On a CPU a 30 s track takes several minutes: poll ``job_status``; its ``music`` field has the ``path`` (the ``audio.music`` value), tempo, feel and loudness. The model and its weights are Apache-2.0: no attribution; the licence record is written next to the file like for a fetched track.
| Name | Type | Req | Description |
|---|---|---|---|
| duration | number | – | – |
| project_dir | string | yes | – |
| prompt | string | yes | – |
| seed | – | – | – |
| steps | integer | – | – |
No output schema declared.
No examples provided.
music_profile ~168
Tempo, loudness and energy of the music tracks, to match a reference. Without ``path``, profiles every audio file of ``music/``; with ``path`` (project-relative), one file, which may be a video such as the reference (its soundtrack mixes voice and music). Each track returns its duration, integrated loudness (LUFS), estimated tempo (``tempo_bpm``), ``energy`` (onsets per second and loudness range in LU) and ``feel``: calm, medium or energetic (thresholds in ``feel_thresholds``). Pick the library track whose profile is closest to the reference's: a calm track under a fast reference feels flat.
| Name | Type | Req | Description |
|---|---|---|---|
| path | – | – | – |
| project_dir | string | yes | – |
No output schema declared.
No examples provided.
music_search ~409
Find music whose licence lets an ad use it (commercial use and modification). Searches Openverse (no key; ``source="openverse"``), Freesound (``"freesound"``, only with the ``FREESOUND_API_KEY`` environment variable) or both (``"all"``; without the key the answer says so and still lists Openverse). Kept licences: CC0, PDM, CC BY, CC BY-SA; NC and ND are dropped. Each track returns ``source``, ``id``, ``title``, ``author``, ``licence``, ``duration`` (s), ``source_url``, ``preview_url`` (listen before fetching) and ``attribution_required`` (with the ``attribution_text`` to put in the ad's description). ``mood`` adds words to the query ("calm", "upbeat"). ``min_duration`` and ``max_duration`` filter in seconds. ``fit_to="storyboard"`` with ``storyboard`` (a project path such as ``storyboards/summer.json``) ranks for that ad: tracks at least as long as the ad first, then the wanted feel (``audio.music_feel``, or the ``feel`` argument: calm, medium, energetic) against ``fit.feel_guess``, a guess from the track's OWN title, tags and genres (``unknown`` when they say nothing; never copied from the wanted feel). The real feel, tempo and loudness come from ``music_fetch``: trust that, not the guess. Fetch the best ones, listen, and choose.
| Name | Type | Req | Description |
|---|---|---|---|
| feel | – | – | – |
| fit_to | – | – | – |
| limit | integer | – | – |
| max_duration | – | – | – |
| min_duration | – | – | – |
| mood | – | – | – |
| project_dir | string | yes | – |
| query | string | yes | – |
| source | string | – | – |
| storyboard | – | – | – |
No output schema declared.
No examples provided.
project_init ~51
Create an AdAnvil project skeleton. Use this first for a new absolute project directory, then inspect the returned folders before adding media.
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | yes | – |
| project_dir | string | yes | – |
No output schema declared.
No examples provided.
project_read_text ~213
Read a UTF-8 project text file using the project's safe path rules. Only AdAnvil's own files can be read: ``adanvil.json``, ``brand.yaml``, ``catalog.json`` and ``brand_brief.md`` at the top of the project, and the files under ``brand/``, ``reference/``, ``renders/``, ``music/``, ``storyboards/``, ``exports/``, ``cache/``, ``voice/``, ``sfx/`` and ``footage/`` (extensions .txt, .md, .json, .yaml, .yml, .csv). Any other file, and any name that starts with a dot, is refused. ``max_bytes`` (default 65536) is capped at 1 MB; a larger value is clamped and the result ``note`` says so.
| Name | Type | Req | Description |
|---|---|---|---|
| max_bytes | integer | – | – |
| path | string | yes | – |
| project_dir | string | yes | – |
No output schema declared.
No examples provided.
qc_run ~190
Run technical QC on a rendered project-relative video. Pass a job id or saved report path when available. Inspect the returned sheet, the end card frame (``end.jpg``) and up to four overlay crops before delivery. ``storyboard`` is the EFFECTIVE storyboard of that render (the one of its format after the re-layout: ``renders/<batch>/_storyboards/<name>.json``, found by itself next to a batch render): the overlay crops are then taken where its overlays really are (a caption moved by ``render_formats`` is not cut in half), and ``caption_on_face`` checks the rendered frames for a caption on a face (needs the vision environment; every format, 9:16 too).
| Name | Type | Req | Description |
|---|---|---|---|
| project_dir | string | yes | – |
| render_report | – | – | – |
| storyboard | – | – | – |
| video | string | yes | – |
No output schema declared.
No examples provided.
recipe_get ~35
Return one complete recipe, including rules and example. Use its checklist as the storyboard acceptance criteria.
| Name | Type | Req | Description |
|---|---|---|---|
| recipe_id | string | yes | – |
No output schema declared.
No examples provided.
recipe_list ~37
List available ad recipes with purpose and duration. Use this to shortlist a shape, then read its checklist with recipe_get before writing a storyboard.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
reference_breakdown ~302
Save the agent's shot-by-shot breakdown of a decoded reference. ``reference`` is the decode folder (reference/<slug>) or its reference.json. ``shots`` follows breakdown_template: one entry per shot, or one entry for consecutive shots (``"shots": [4, 5]``); every decoded shot must be covered exactly once. Controlled values: type, scale, role, motion, emotion, text_speaker, text_device (errors list the allowed ones); ``action`` is free short text: what the person does (for example "wipes the counter and sighs"). For every shot note what the person feels (``emotion``) and does, then pick a library shot with the same emotion and the same kind of action. text_speaker and text_device say who speaks in the on-screen text (an emoji or name, ":" and quotes is a character talking); subject is a short id (person_a, product, diagram), on_screen_text is read verbatim, replacement is a library entry id or "missing: ...". Returns type demand, scale mix, role sequence, repeated patterns, people, text shots, text_devices, dialogue, emotion_by_role (the emotions used for each role), pacing and missing shots. Use it before library_overview.
| Name | Type | Req | Description |
|---|---|---|---|
| project_dir | string | yes | – |
| reference | string | yes | – |
| shots | array | yes | – |
No output schema declared.
No examples provided.
reference_decode ~240
Decode a reference video into shots, pacing, text, speech and sheets. ``transcribe`` is true, false or "auto" (default: transcribe when the reference has audible sound and a transcriber is available). Returns the JSON, the overview sheet, then up to 6 shot sheets (one row per shot, three frames each). LOOK at every shot sheet and read the on-screen text, then call reference_breakdown with the filled breakdown_template before choosing footage. The JSON is compact: the per-word transcript and rms_per_second stay in reference.json (see ``files``); each shot has its ``spoken`` text and ``transcript_text`` holds the whole transcript. ``breakdown_vocabularies`` lists the allowed type, scale, role, motion, emotion, text_speaker and text_device values and how to read who speaks in the on-screen text; ``music_profile`` is the tempo and energy of the reference soundtrack (voice included).
| Name | Type | Req | Description |
|---|---|---|---|
| language | – | – | – |
| project_dir | string | yes | – |
| transcribe | – | – | – |
| video | string | yes | – |
No output schema declared.
No examples provided.
render_batch ~398
Queue ONE background job that renders several storyboards in order. ``quality``: ``final``, ``preview`` or ``draft`` (an alias of ``preview``: half-size ``*.preview.mp4`` files; the report and the manifest say ``preview``, and the manifest has a ``quality`` column because a preview scores lower than its final). ``storyboards``: objects or saved paths (typically the variants of ``variants_build``). The segment cache is shared, so a segment used by several variants (the body, the end card) is built once: the first render is the slow one. ``formats`` (any of ``"9:16"``, ``"4:5"``, ``"1:1"``) renders each storyboard in those ratios; when omitted each storyboard's own ``formats`` field is used, else it renders as it is. Files go to ``renders/<batch>/`` (``batch`` defaults to ``<first name>_batch``) named ``<name>[_9x16|_4x5|_1x1].mp4``, and ``renders/<batch>/manifest.csv`` lists them for an ads manager (file, variant ids, format, duration, score, hook text, CTA text). ``score`` runs ``ad_score`` on each final render for the manifest (with the safe zones of its placement). ``job_status`` shows the progress per render, each output as it finishes, and at the end ``total_seconds``, ``cache_builds`` and the manifest path. A storyboard that does not validate rejects the whole batch with its errors and no job.
| Name | Type | Req | Description |
|---|---|---|---|
| batch | – | – | – |
| formats | – | – | – |
| project_dir | string | yes | – |
| quality | string | – | – |
| score | boolean | – | – |
| storyboards | array | yes | – |
No output schema declared.
No examples provided.
render_formats ~308
Render one storyboard in several formats: ``9:16``, ``4:5``, ``1:1``. ``formats`` defaults to the storyboard's own ``formats`` field, else all three. One detached job (see ``render_batch``), one file per format: ``<name>_9x16.mp4``, ``<name>_4x5.mp4``, ``<name>_1x1.mp4`` in ``renders/<batch>/`` (``batch`` defaults to ``<name>_formats``). Each is the same ad laid out for its placement: the footage is re-cropped (face-aware with ``focus: "face"``, else by ``focus``); a still or an end card that does not fit is shown whole over its blurred copy; captions, stickers and images keep their place by bands (the part the platform leaves free is mapped onto the free part of the new frame, 4:5 and 1:1 being the Feed) and are pushed back inside when a block would leave it. ``ad_score`` uses the safe zones of the matching placement (``feed`` for 4:5 and 1:1). LOOK at each format's contact sheet before delivery.
| Name | Type | Req | Description |
|---|---|---|---|
| batch | – | – | – |
| formats | – | – | – |
| project_dir | string | yes | – |
| quality | string | – | – |
| score | boolean | – | – |
| storyboard | – | yes | – |
No output schema declared.
No examples provided.
render_start ~80
Validate and queue a background render. ``storyboard`` is the object or a saved path (``"storyboards/<name>.json"``). Use preview while iterating and final after QC. A rejected storyboard returns validation errors and creates no job.
| Name | Type | Req | Description |
|---|---|---|---|
| project_dir | string | yes | – |
| quality | string | – | – |
| storyboard | – | yes | – |
No output schema declared.
No examples provided.
sfx_list ~317
List the sound effects of the project's ``sfx/`` folder, and build the pack. ``fetch=true`` first builds the missing sounds of the pack (about 18: whoosh short and long, swoosh, swipe, pop, click, tap, ding, chime, notification, cash register, camera shutter, record scratch, typing, riser 1 s and 2 s, impact, boom). Each is downloaded from a pinned CC0 source (checked by SHA-1) or synthesised in code, trimmed and set to one level, with the source and licence in ``sfx/LICENCES.txt``. A download that fails is synthesised instead (``offline=true`` synthesises all of them). The files you drop in ``sfx/`` yourself are listed too. Each sound returns its ``name``, ``path`` (the ``source`` of an ``sfx`` overlay), ``duration`` and ``origin``. Use a sound in an ``sfx`` overlay (``{"type": "sfx", "source": "sfx/pop.wav", "at": 3.2, "volume": 0.8}``) or by name in ``audio.sfx_auto``. A riser is placed so that its end meets the moment it builds towards: ``at`` = that moment minus its duration.
| Name | Type | Req | Description |
|---|---|---|---|
| fetch | boolean | – | – |
| offline | boolean | – | – |
| project_dir | string | yes | – |
No output schema declared.
No examples provided.
speech_refine ~329
Transcribe chosen clips again with a stronger model and replace their words. Indexing transcribes fast with a small model, so about one key word per line can be misheard (names, numbers, rare words). Call this on the clips you will use in the ad (before cutting and captioning): ``sources`` lists project paths of indexed clips (a file, or a folder for every clip below it) or catalogue entry ids. It starts a detached job (wait with job_status(job_id, wait_seconds=90); progress counts clips) that transcribes them with ``model`` (one of tiny, base, small, medium, large-v2, large-v3, large-v3-turbo; default medium: slower, much more accurate; a medium model needs about 2 GB of memory) and the brand vocabulary (brand name, product name and ``speech.vocabulary`` of brand.yaml), then replaces the words of each clip in place (``speech_view`` reports the ``model``). A clip that fails keeps its previous words. The language is the brand's, else detected, unless ``language`` is given. The result of the finished job is ``refine`` in job_status (refined ids, skipped clips with the reason, errors). A word that is still wrong afterwards can be shown correctly with ``speech_captions.corrections`` (close spellings only).
| Name | Type | Req | Description |
|---|---|---|---|
| language | – | – | – |
| model | string | – | – |
| project_dir | string | yes | – |
| sources | array | yes | – |
No output schema declared.
No examples provided.
speech_takes ~263
Pick the best take of each line across several recordings of a script. Pass ``source`` (a project folder such as footage/hooks, or one file) and/or ``entry_ids``: the clips to compare, for example HOOK1.mov, HOOK1.1.mov and HOOK1.2.mov. Phrases that say the same line (normalised text similarity of at least 0.6, inside one file or across files) form a line; each take is ranked on fluency (no filler, no restart), a complete ending (last word not cut), a speech rate in the natural band (about 1.9 to 4.2 words per second) and the audio level. Returns ``lines``: for each, the ``best`` take (entry_id, source, start, end, text, score, ``why`` and ready-to-paste ``clean_segments``) and the ``others`` with the ``issues`` that put them behind. ``skipped`` lists clips without a transcript (run library_index with transcribe=true on them).
| Name | Type | Req | Description |
|---|---|---|---|
| entry_ids | – | – | – |
| max_pause | number | – | – |
| project_dir | string | yes | – |
| source | – | – | – |
No output schema declared.
No examples provided.
speech_view ~543
Read the speech of one indexed clip and get safe cuts for it. Pass ``entry_id`` (from library_index or library_search) or ``source`` (the project-relative path of a video or audio file). Needs the clip to be indexed with speech (library_index transcribes clips with sound). The output is compact: ``phrases`` (split on pauses longer than ``max_pause`` seconds and on sentence punctuation), each with ``start``, ``end``, ``text`` and ``flags`` (``restart``: the next phrase repeats it, a retake; ``filler``: it holds a hesitation; ``uncertain``: the transcriber doubted a word, so it may be misheard); ``fillers`` (euh, heu, hum, bah, ben, um, uh, er, and genre, du coup, like when said alone between pauses; the lists can be replaced in brand.yaml under ``speech.fillers`` and ``speech.isolated_fillers``); ``restarts`` (a phrase that repeats the start of the next one: a retake inside the file); and ``clean_segments``: clip segments ``{source, in, out}`` ready to paste into a storyboard, which keep the speech and drop pauses over ``max_pause`` and the fillers (0.06 s kept before a word, 0.10 s after, never cutting inside a word). Per-word data (start, end, text and ``filler`` for each word) only comes with ``words=true``. At most ``max_phrases`` phrases are returned (default 60) from ``first_phrase``: when there are more, ``note`` and ``next_first_phrase`` tell how to get the next ones, and the other lists are those of the phrases shown. With ``drop_restarts`` true the restart phrases are cut out of the clean segments too (they are only flagged by default, because a deliberate repetition looks the same). ``model`` says which transcription model made the words: if a clip is used in the ad, run speech_refine on it first. A clip whose sound is silent says ``speech_status: silent_audio`` and lists ``separate_audio_candidates``.
| Name | Type | Req | Description |
|---|---|---|---|
| drop_restarts | boolean | – | – |
| entry_id | – | – | – |
| first_phrase | integer | – | – |
| max_pause | number | – | – |
| max_phrases | integer | – | – |
| project_dir | string | yes | – |
| source | – | – | – |
| words | boolean | – | – |
No output schema declared.
No examples provided.
storyboard_patch ~233
Edit a saved storyboard in place: ``changes`` is a list of ``{path, value}``. A path walks the JSON with dots and indexes: ``segments.3.out`` (``segments[3].out`` works too). Setting a missing key of an object adds it; the index just past the end of a list, or ``-``, appends; ``{"path": "overlays.1", "remove": true}`` deletes. The changes apply in order to a copy: if one is wrong, nothing is saved and the error names it. When the changes rename the storyboard (``name``), its ``output.path`` follows if it was the default of the old name (a path set by hand stays). The file ``storyboards/<name>.json`` is rewritten and the result lists the schema problems left (``problems``, empty when the storyboard is valid; run ``storyboard_validate`` for the full check).
| Name | Type | Req | Description |
|---|---|---|---|
| changes | array | yes | – |
| name | string | yes | – |
| project_dir | string | yes | – |
No output schema declared.
No examples provided.
storyboard_save ~137
Save a storyboard in the project as ``storyboards/<name>.json`` and return its path. Send the storyboard object once, then pass the returned path (``"storyboards/<name>.json"``) as ``storyboard`` to ``storyboard_validate``, ``render_start`` and ``caption_preview`` instead of repeating the whole object (useful on a remote server). Saving again under the same name replaces the file. The object is stored as sent, not validated: ``storyboard_validate`` checks it.
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | yes | – |
| project_dir | string | yes | – |
| storyboard | object | yes | – |
No output schema declared.
No examples provided.
storyboard_schema ~30
Return the JSON Schema for Storyboard v1. Use it to construct agent-authored storyboards before validation.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
storyboard_snap ~346
Move the cuts of a storyboard onto the beats of its music. ``storyboard`` is the object or a saved path. Each cut within ``max_shift`` seconds (default 0.2) of a beat of ``audio.music`` (from ``audio.start``) moves to it: the ``out`` of the earlier clip (or the ``duration`` of an image) changes, ``in`` points and segment order never do, no segment ends up under 0.5 s (or shorter than it was), the other cuts and the total duration stay, and the captions, images and sounds that started on a moved cut move with it. With ``audio.clips`` the cuts of talking segments never move. The result lists ``moves``, the cuts ``kept`` with the reason, and how many cuts are on a beat before and after. It returns the new ``storyboard``, or with ``save_as`` (a name) writes ``storyboards/<name>.json`` and returns its path instead. The snapped storyboard has its own identity so a render never overwrites the original: with ``save_as`` its ``name`` is ``save_as``, without it the old name plus ``_snapped``, and ``output.path`` is ``renders/<that name>.mp4`` (the quality is kept). Run ``storyboard_validate`` afterwards: its ``beat_alignment`` info shows the share of cuts on a beat.
| Name | Type | Req | Description |
|---|---|---|---|
| max_shift | number | – | – |
| project_dir | string | yes | – |
| save_as | – | – | – |
| storyboard | – | yes | – |
| to | string | – | – |
No output schema declared.
No examples provided.
storyboard_validate ~217
Validate a storyboard object or project-relative JSON file. ``storyboard`` is the object, or the path saved by ``storyboard_save`` (``"storyboards/<name>.json"``). Every schema error is reported at once. The check covers Storyboard v1, its files, brand and recipe. Fix every error path before render_start; warnings are questions to review. With ``reference`` set, ``ref_*`` warnings and a ``reference_comparison`` block compare the edit with the reference breakdown. With ``score_check=true`` it also runs the quick pre-check of ``ad_score`` that needs no pixels, as warnings prefixed ``score_`` (reading time and line length, product too early, call to action, platform safe zones of the overlays); ``summary.score_precheck`` lists what passed and what could not be checked.
| Name | Type | Req | Description |
|---|---|---|---|
| project_dir | string | yes | – |
| recipe_id | – | – | – |
| score_check | boolean | – | – |
| storyboard | – | yes | – |
No output schema declared.
No examples provided.
timeline_export ~435
Export a storyboard as an editable timeline for DaVinci Resolve or Premiere Pro. Writes ``exports/<name>/`` with ``<name>.otio`` (OpenTimelineIO: video tracks, speed as a time warp, stills, captions as markers on V1, overlay pictures, voice, music and one audio track per sound effect), ``<name>.xml`` (Final Cut Pro 7 XML, read by Premiere Pro and Resolve, with the real rate, size and duration of each source, speed as Time Remap, music and sound effect levels and fades), ``<name>.edl`` (CMX 3600, video cuts only, the fallback), ``<name>.srt`` (every caption at its final time), ``overlays/`` (each caption, sticker and card as a full-canvas transparent PNG named after its storyboard overlay index, with its place in ``overlays.json``) and ``README.txt``. ``formats`` is any of ``otio``, ``fcp7xml``, ``edl``, ``srt`` (all by default). Media paths are absolute, as the project sees them; ``relative`` writes ``exports/<name>-relative/`` with paths relative to the folder (and a ``relink.txt``), ``copy_media`` writes ``exports/<name>-portable/`` with the used sources copied into ``media/``; ``media_root`` is the absolute folder a relative export will live in. A folder that holds an export of another media mode is only replaced with ``overwrite=true``. The result lists ``warnings`` (what is approximated) and ``not_exported`` (what no editor format here carries: grading, reframing, pop animations, split layout, loudness, the EDL audio).
| Name | Type | Req | Description |
|---|---|---|---|
| copy_media | boolean | – | – |
| formats | – | – | – |
| media_root | – | – | – |
| overwrite | boolean | – | – |
| project_dir | string | yes | – |
| relative | boolean | – | – |
| storyboard | – | yes | – |
No output schema declared.
No examples provided.
variants_build ~636
Build the matrix of variants of one storyboard: hooks x bodies x calls to action. ``base`` is a storyboard (object or ``"storyboards/<name>.json"``). ``variants`` is ``{axis: [{id, changes}]}`` for up to 3 axes (for example ``hook``, ``body``, ``cta``). ``changes`` is a list applied in order, each a ``storyboard_patch`` change (``{path, value}`` or ``{path, remove: true}``) or a SLOT REPLACEMENT ``{replace_label: "hook", segments: [...], overlays: [...]}``: it swaps every segment of that label (they must be next to each other) and shifts everything after it by the difference of duration (overlays, sounds and word times follow). The new ``overlays`` are timed from the start of the slot; the overlays that were on the replaced segments go away. A voice-over (``audio.voice``) laid on the timeline must still match: a change of duration while one is set is refused with the reason, as is an overlay that only partly overlaps the slot. An option with no ``changes`` (or ``[]``) is the control: the base unchanged. Timed sounds follow the slot: an ``sfx`` overlay after it shifts by the difference of duration, one inside it goes away when the new slot brings its own sounds (else it keeps its offset); each variant lists what moved under ``moved``. All the errors of all the variants come back at once (variant, path, message). Makes the cartesian product (at most 24, each validated), saves each as ``storyboards/<name>.json`` (``name_pattern`` uses ``{base}`` and the axis names; the default falls back to the axis ids in order when an axis is not hook or cta) and returns the list with the path, ids, duration and warnings of each, plus a contact sheet: the first 3 s (top row) and the last 3 s (bottom row, the call to action) of every variant (LOOK at it, a hook that does not read at that size will not read in the feed). A base that is itself a variant keeps its ids in the new ones (the manifest keeps ``hook=h2;cta=ca``). Then ``render_batch`` renders them with a shared cache. Vary…
| Name | Type | Req | Description |
|---|---|---|---|
| base | – | yes | – |
| contact_sheet | boolean | – | – |
| name_pattern | string | – | – |
| overwrite | boolean | – | – |
| project_dir | string | yes | – |
| variants | object | yes | – |
No output schema declared.
No examples provided.
vision_setup ~174
Install the optional vision environment (once, several minutes, about 2.5 GB). It makes its own Python environment in the AdAnvil cache folder with a small multilingual image and text embedding model (SigLIP 2, Apache-2.0) and a face detector (YuNet, MIT), both free for commercial use, and downloads their weights. It runs on the CPU. Afterwards ``library_index`` also looks at every image and video (shot search by sentence, automatic tags, product versions, faces for ``focus: "face"``). Without it everything else works as before. The environment is made from the default Python of this machine: to build it from another interpreter, a person runs ``adanvil vision-setup --python <path>`` in a terminal.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
voice_generate ~241
Queue a checked voice-over generation job. Poll job_status until it is done, then use each manifest line's ``start`` and ``duration`` to place shots. If a line is ``suspect``, regenerate it with slightly different wording or accept it when the transcript differs only by punctuation; agents cannot listen to audio. ``unmatched_words`` lists the key words (4+ letters) missing from the transcript: two or more make the line suspect, so reword them. A line is a string (said and shown) or ``{"say": ..., "show": ...}`` when captions must display something other than the spoken words (say "forty-nine dollars ninety", show "$49.90"). Calling again with an existing ``name`` replaces that voice (unchanged lines come from the cache); the job summary then has ``replaced: true``. ``language`` in the spec is optional: without it the ``language`` of brand.yaml is used, else ``en``.
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | yes | – |
| project_dir | string | yes | – |
| spec | object | yes | – |
No output schema declared.
No examples provided.
voice_view ~92
Read a voice manifest and suggest final-timeline shot boundaries. ``offset`` is the intended voice start on the final video timeline. Suspect lines should be regenerated with slightly different wording or accepted only when the transcript difference is punctuation. Each line's ``unmatched_words`` lists key words the transcript lacks.
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | yes | – |
| offset | number | – | – |
| project_dir | string | yes | – |
No output schema declared.
No examples provided.
How do I install the AdAnvil MCP server?
AdAnvil runs locally as a PyPI package, launched with uvx adanvil. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
pypi · adanvil
claude mcp add maxbuildog-adanvil -- uvx adanvil
What is the AdAnvil MCP server?
AdAnvil is an MCP server listed in the public MCP registry as io.github.maxbuildog/adanvil. Lets an AI agent edit vertical 9:16 video ads from your footage, a reference ad or an idea. This page covers its PyPI package (adanvil).
Is the AdAnvil MCP server safe to use?
AdAnvil scores 64 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 17 October 2026. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the AdAnvil MCP server expose?
AdAnvil exposes 43 tools: project_init, project_read_text, brand_onboard, brand_get, library_index, and 38 more. Their descriptions and schemas cost roughly 11,108 tokens of context every time the server is loaded.
Is the AdAnvil MCP server still maintained?
AdAnvil is still listed as active in the MCP registry. We last reached this channel on 17 October 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.
What licence is the AdAnvil MCP server under?
AdAnvil declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.