foley.agent.mcp#
The MCP surface — foley’s façade as agent-callable tools (py2mcp, #12, report 05/10).
Exposes the SELECT→preview→WEAVE loop to an LLM agent (or any MCP client) as a set of
JSON-safe tools built with py2mcp (mk_mcp_server over stdio). The single rule:
tools take/return only JSON (ids, scores, license summaries, timeline dicts, store keys) —
never a Candidate, a WeaveResult, or numpy
audio. Heavy objects stay server-side; audio is referenced by a byte-store key.
The tool functions are thin wrappers over the existing façade (a single seam, three
surfaces: Python / CLI / MCP): they resolve the shared foley.index.SoundLibrary
and per-session foley.agent.session.SessionStore (both injectable for tests).
py2mcp / fastmcp are imported LAZILY inside build_mcp_server() only, so
import foley and import foley.agent stay dol-only.
Module Attributes
The full JSON-safe tool surface (SSOT), in a stable order. |
Functions
|
Build the foley MCP server (lazy |
What foley can do here — keys / extras / system deps / offline / sources / degraded. |
|
|
Remove a previously-picked sound from the session. |
|
Find verified, license-clean sound candidates for a narrative passage. |
|
Generate a sound from a text prompt (local backends only when offline). |
How to sound-design a narration with foley — the operating playbook for an agent. |
|
|
The sounds picked in this session (the 'persist picks' read side). |
|
Shift a timeline item's onset by |
|
Accept a sound into the session (persisted); |
|
Fold picks (or explicit candidate ids) into a JSON sound-design timeline. |
|
Produce a short audition of a sound; returns its store key (never audio bytes). |
|
Relevance-feedback refinement: expand the query, boost picks, drop rejects, re-rank. |
|
Reject a sound (feeds |
|
Score a narration passage → an editable sound-design timeline + a per-event rationale. |
|
Hybrid (CLAP + keyword) search of the library for a text query; returns candidate rows. |
|
Set a timeline item's gain (dB); returns the new timeline. |
|
Set the timeline's master target (LUFS / true-peak); returns the new timeline. |
|
"More like this" — the library neighbours of a sound (by id); returns candidate rows. |
|
The current runtime posture + this session's pick/reject counts. |
|
Swap a timeline item's clip; returns the new timeline. |
|
Export SDH captions for a timeline ( |
|
Mute/unmute a timeline item; returns the new timeline. |
|
Render a timeline under the narration; returns the mix by store key + captions + credits. |
|
Build a bearer-auth-gated ASGI app serving the foley MCP tools over streamable HTTP. |
|
Build and run the foley MCP server over stdio (blocks); enforces an offline posture. |
|
Build and serve the foley MCP tools over authenticated streamable HTTP (blocks). |
- foley.agent.mcp.TOOLS = [<function foley_find>, <function foley_search>, <function foley_similar_to>, <function foley_preview>, <function foley_refine>, <function foley_pick>, <function foley_drop_pick>, <function foley_reject>, <function foley_list_picks>, <function foley_generate>, <function foley_plan>, <function foley_weave>, <function foley_swap_clip>, <function foley_set_gain>, <function foley_nudge>, <function foley_toggle>, <function foley_set_master>, <function foley_timeline_captions>, <function foley_score>, <function foley_guide>, <function foley_capabilities>, <function foley_status>]#
The full JSON-safe tool surface (SSOT), in a stable order.
- foley.agent.mcp.build_mcp_server(*, library=None, session='default', runtime=None, byte_store=None, include=None, name='foley', max_usd=None)[source]#
Build the foley MCP server (lazy
py2mcp); registers the JSON-safe tool surface.Validates that every source declares a
data_egress(fail-closed), binds the injectable library / runtime / byte-store, and hands the resolved tool functions topy2mcp.mk_mcp_server. Never starts a server or touches the network.- Parameters:
library – The
foley.index.SoundLibrary(default: the shared one).session (
str) – The default session id.runtime – A
foley.runtime.RuntimeConfig(default: the active one).byte_store – A
MutableMapping[str, bytes]for previews / rendered mixes.include (
Optional[list[str]]) – Optional subset of tool names to expose.name (
str) – The MCP server name.max_usd (
Optional[float]) – The server’s cumulative spend cap across every paid tool call, for its lifetime (defaultfoley.cost.default_max_usd(): $1, or $3 under$FOLEY_LLM=anthropic).
- Returns:
A
fastmcp.FastMCPserver.
- foley.agent.mcp.foley_capabilities()[source]#
What foley can do here — keys / extras / system deps / offline / sources / degraded.
- Return type:
- foley.agent.mcp.foley_drop_pick(sound_id, session='default')[source]#
Remove a previously-picked sound from the session.
- Return type:
- foley.agent.mcp.foley_find(context, max_events=6, verify='listen', commercial_ok=True, k=10, session='default')[source]#
Find verified, license-clean sound candidates for a narrative passage.
Caches the full candidates in the session so
foley_plan/foley_weavecan rehydrate them by id. Returns compact candidate rows.- Return type:
- foley.agent.mcp.foley_generate(prompt, backend='stable_audio', commercial_ok=True, session='default')[source]#
Generate a sound from a text prompt (local backends only when offline).
- Return type:
- foley.agent.mcp.foley_guide()[source]#
How to sound-design a narration with foley — the operating playbook for an agent.
Call this first if you are unsure of the workflow: it returns the tool order, the taste heuristics (restraint, layering, ducking, licensing), and the offline posture.
- Return type:
- foley.agent.mcp.foley_list_picks(session='default')[source]#
The sounds picked in this session (the ‘persist picks’ read side).
- Return type:
- foley.agent.mcp.foley_nudge(timeline, item_id, delta_s)[source]#
Shift a timeline item’s onset by
delta_sseconds; returns the new timeline.- Return type:
- foley.agent.mcp.foley_pick(sound_id, session='default', layer=None, onset=None)[source]#
Accept a sound into the session (persisted);
foley_planfolds picks into a timeline.- Return type:
- foley.agent.mcp.foley_plan(session='default', transcript=None, candidate_ids=None)[source]#
Fold picks (or explicit candidate ids) into a JSON sound-design timeline.
Each pick’s explicit
layer/onset(set viafoley_pick()) is overlaid onto its candidate’sSoundEventsoplanhonors the agent’s placement choices — a numericonsetbecomes an absolute-seconds anchor (seefoley.weave.anchor.parse_symbolic_anchor()).- Return type:
- foley.agent.mcp.foley_preview(sound_id, seconds=6, session='default')[source]#
Produce a short audition of a sound; returns its store key (never audio bytes).
- Return type:
- foley.agent.mcp.foley_refine(session='default', query=None, picked_ids=None, rejected_ids=None, hint=None, k=10)[source]#
Relevance-feedback refinement: expand the query, boost picks, drop rejects, re-rank.
- Return type:
- foley.agent.mcp.foley_reject(sound_id, session='default', reason=None)[source]#
Reject a sound (feeds
foley_refinerelevance feedback).- Return type:
- foley.agent.mcp.foley_score(context, commercial_ok=True, verify='listen', max_events=6, session='default')[source]#
Score a narration passage → an editable sound-design timeline + a per-event rationale.
The one-call SELECT→plan entry for an agent: pass the narration text and get back a JSON timeline plus a rationale for each chosen sound. Weaving (rendering the mastered mix) is a separate step (
foley_weave) so you can review / edit the timeline first — swap a clip, nudge an onset, drop a cue — before committing to a render.- Return type:
- foley.agent.mcp.foley_search(query, k=10, commercial_ok=True, ucs_category=None, rerank=False, session='default')[source]#
Hybrid (CLAP + keyword) search of the library for a text query; returns candidate rows.
- Return type:
- foley.agent.mcp.foley_set_gain(timeline, item_id, gain_db)[source]#
Set a timeline item’s gain (dB); returns the new timeline.
- Return type:
- foley.agent.mcp.foley_set_master(timeline, target_lufs=None, peak_dbfs=None)[source]#
Set the timeline’s master target (LUFS / true-peak); returns the new timeline.
Either field may be set independently — omitting one keeps the podcast default for that field (so
peak_dbfs=-2.0alone tightens only the true-peak ceiling).- Return type:
- foley.agent.mcp.foley_similar_to(sound_id, k=10, commercial_ok=True, session='default')[source]#
“More like this” — the library neighbours of a sound (by id); returns candidate rows.
- Return type:
- foley.agent.mcp.foley_status(session='default')[source]#
The current runtime posture + this session’s pick/reject counts.
- Return type:
- foley.agent.mcp.foley_swap_clip(timeline, item_id, sound_id)[source]#
Swap a timeline item’s clip; returns the new timeline.
- Return type:
- foley.agent.mcp.foley_timeline_captions(timeline, fmt='vtt')[source]#
Export SDH captions for a timeline (
fmt='vtt'|'srt').- Return type:
- foley.agent.mcp.foley_toggle(timeline, item_id, enabled)[source]#
Mute/unmute a timeline item; returns the new timeline.
- Return type:
- foley.agent.mcp.foley_weave(narration, timeline, session='default')[source]#
Render a timeline under the narration; returns the mix by store key + captions + credits.
- Return type:
- foley.agent.mcp.make_http_app(*, auth, path='/mcp', json_response=False, library=None, runtime=None, byte_store=None, include=None, name='foley')[source]#
Build a bearer-auth-gated ASGI app serving the foley MCP tools over streamable HTTP.
HTTP exposes the tool surface to the network, so
authis **required and fail-closed**: passauth={'bearer_tokens': [...]}(a non-empty iterable of accepted tokens) — a request without a matchingAuthorization: Bearer <token>header gets a401. The returned app (a Starlette/ASGI callable) mounts in any ASGI host (uvicorn, gunicorn, a parent FastAPI).py2mcp/fastmcpare imported lazily insidebuild_mcp_server(), soimport foleystays dol-only.- Parameters:
auth (
dict) –{'bearer_tokens': [...]}— required; empty/missing raises (fail-closed).path (
str) – The MCP HTTP mount path.json_response (
bool) – Return a single JSON response instead of an SSE stream (simple clients).name (
str) – Asbuild_mcp_server().
- Returns:
An ASGI application (the bearer-gated MCP HTTP app).
- Raises:
ValueError – If
authcarries no bearer tokens (no anonymous HTTP access).
- foley.agent.mcp.serve(*, name='foley', runtime=None, **kwargs)[source]#
Build and run the foley MCP server over stdio (blocks); enforces an offline posture.
- Return type:
- foley.agent.mcp.serve_http(*, host='127.0.0.1', port=8000, auth, path='/mcp', **kwargs)[source]#
Build and serve the foley MCP tools over authenticated streamable HTTP (blocks).
Wraps
make_http_app()and runs it with uvicorn.authis required (fail-closed).- Return type: