Create and Manage MotherDuck Flights
Source Of Truth
- Non-negotiable ordering: when MotherDuck MCP is available, call
get_flight_guidebeforecreate_flight,update_flight, oredit_flight_source. The guide defines the current authoring contract, runtime limits, and tool semantics. get_flight_guidealso surfaces conventions from the reservedflightsGuide topic. Apply those conventions when they fit the requested workload.- Prefer current MotherDuck Flights docs over memory. Verify lifecycle status, runtime limits, and tool semantics instead of preserving them as durable prompt claims.
- Without MCP, the same operations exist as SQL functions (
MD_CREATE_FLIGHT,MD_RUN_FLIGHT,MD_LIST_FLIGHTS(), ...) that execute server-side on a MotherDuck connection. Parameter names differ slightly between the two surfaces; see the naming table inreferences/FLIGHTS_GUIDE.md.
Default Posture
- One Flight = one single-file Python script with
def main(): ...andif __name__ == "__main__": main(). No CLI args — every knob comes from env vars viaconfig(non-secret) orTYPE flightssecrets (sensitive). - Connect with
duckdb.connect("md:"); the runtime injectsMOTHERDUCK_TOKENautomatically. Never hardcode a token in source, config, or requirements. - Always pin dependencies in
requirements_txt. Resolve the highest MotherDuck-supported DuckDB version fromhttps://motherduck.com/docs/duckdb-versions.jsonbefore authoring a new Flight; use the tested pin in the included templates only when reproducing those examples. An unpinned or unsupportedduckdbcan fail at connect. - Each secret param is injected under a stable namespaced
<secret_name>_<PARAM>key and, when safe, a bare<PARAM>convenience alias. Prefer namespaced keys in deployed Flight code; bare aliases can collide, be overridden by config, and are withheld for reserved runtime keys. - Bulk-load, never row-by-row: stage to
/tmp/andread_csv_auto/read_json_auto/read_parquet, or one CTAS /INSERT ... SELECT. Noexecutemany()against MotherDuck. - Make every run idempotent:
CREATE OR REPLACE TABLEfull refresh, partitionDELETE+INSERT, or dltwrite_disposition="merge"with a primary key. Bootstrap withCREATE DATABASE IF NOT EXISTS/CREATE SCHEMA IF NOT EXISTSso the first run succeeds on a fresh account. - Validate any config-supplied identifier (database, schema, table names) against
[A-Za-z_][A-Za-z0-9_]*before interpolating it into DDL; bind all data values as?parameters. - Create the flight without a schedule first, trigger one on-demand run, read the logs, and only then attach
schedule_cron(5-field cron, UTC). - Set and validate
max_runtime_secwhen the workload needs an explicit cap; read the current plan limit fromget_flight_guideinstead of hardcoding it. - For production, use a service-account token via
access_token_nameand keep its database permissions as narrow as the workload allows. - Treat a Flight as orchestration and light processing, not a place to crunch large tables in Python memory. Push heavy compute into SQL and verify runtime capacity with
get_flight_guidebefore sizing disk- or memory-intensive work.
Workflow
- Classify the job: ingestion, transformation/refresh, export or alerting, or admin automation. If the job is interactive analysis or a one-off query, use
motherduck-queryinstead — no Flight needed. - Call
get_flight_guide(MCP) and confirm which database the flight writes to withmotherduck-explore. - Reuse a matching template in
references/FLIGHT_EXAMPLES.mdwhen it fits; otherwise write a focused script that preserves the runtime, secrets, and idempotency contracts. - Create any required
TYPE flightssecret first, thencreate_flightwithname,source_code, pinnedrequirements_txt,config, and secret names — noschedule_cronyet. run_flight, pollget_flight_runwhen available (orlist_flight_runsas a fallback) until terminal, and readget_flight_logs. Iterate withedit_flight_source(surgical) orupdate_flight(full field replacement); each content change creates a new version.- If scheduling was requested, set it only after a successful run with
update_flight(schedule_cron = ...)and state that cron is UTC. Clear it withschedule_cron = ""only when requested; preserve an existing schedule during unrelated edits.
For answer, review, or planning requests, do not create or schedule a Flight. For create or update requests, complete the requested in-scope deployment and on-demand validation; attaching a recurring schedule is authorized only when the request includes scheduling.
References
Read only the reference sections needed for the current task.
- Read
references/FLIGHTS_GUIDE.mdfor the full concept and operations reference: anatomy, runtime environment, config vs secrets, scheduling, versioning, run lifecycle, the complete MCP tool reference, MCP-vs-SQL naming, loading strategies by data volume, and troubleshooting. - Read
references/FLIGHT_EXAMPLES.mdfor three complete, best-practice flight templates (dlt ingestion, Postgres ingestion, scheduled S3 partition refresh) with theirrequirements.txt, secret setup, and deploy calls.
Related Skills
Load related skills only for missing capabilities; reuse established context.
motherduck-load-datafor choosing the ingestion SQL the flight will run (CTAS,INSERT ... SELECT, cloud-storage secrets)motherduck-queryfor validating the DuckDB SQL inside the flight before deploying itmotherduck-explorefor confirming target databases, schemas, and tables existmotherduck-build-data-pipelinewhen the work is a full raw/staging/analytics pipeline design and the flight is just its schedulermotherduck-cliwhen the agent has a shell and should keep Flight source in local filesmotherduck-manage-guidesfor reusable personal or organization Flight conventions