Skip to main content

Async Python client for the Amazing Marvin API

Project description

amazing-marvin

Licence: MIT

Async Python client library for the Amazing Marvin API.

Async-first, fully typed, no global state, no blocking I/O. Suitable for any Python application — CLIs, web services, MCP servers, Home Assistant integrations, sync bridges, scheduled scripts.


Installation

pip install amazing-marvin

Requires Python 3.12+ and aiohttp>=3.9.


Quick Start

import asyncio
from amazing_marvin import MarvinClient

async def main():
    async with MarvinClient(api_token="your_token") as client:
        tasks = await client.get_today_items()
        for task in tasks:
            print(task.title, task.done)

asyncio.run(main())

When embedding inside a host that already manages an aiohttp.ClientSession (FastAPI, Home Assistant, an MCP server runtime), pass the existing session at construction so the client never owns or closes it:

client = MarvinClient(
    api_token=token,
    full_access_token=full_token,   # optional
    tz_offset=600,                  # AEST
    throttle=True,
    session=existing_session,       # borrowed; not closed by client
)
tasks = await client.get_today_items()
task = await client.mark_done(item_id)

Use Cases

The library is intentionally framework-agnostic. Common embeddings:

  • MCP servers — wrap each MarvinClient method as a tool; the typed dataclasses serialise cleanly to JSON.
  • Home Assistant integrations — use the borrowed-session pattern with async_get_clientsession(hass).
  • CLIs — pair with Typer or Click for terminal-driven task entry.
  • FastAPI / web dashboards — share the app's aiohttp session via lifespan.
  • Sync bridges — Notion, Todoist, Linear, calendar providers.
  • Scheduled scripts — cron, GitHub Actions, weekly reviews, exports.

Auth Setup

Amazing Marvin exposes two separate tokens, both found under Profile > Integrations > API in the Marvin app:

Token Constructor arg Required for
API Token api_token Read and write operations (most methods)
Full Access Token full_access_token Raw document access, reminders, admin ops

Methods that need a token you have not supplied will raise MarvinAuthError before making any HTTP request.


CouchDB Queries (optional)

If you run a local CouchDB replica of Marvin's database (Marvin's /pre?api page exposes your account's Cloudant credentials for pull replication), the client can query it directly — fast, searchable reads with no Marvin API rate limits:

async with MarvinClient(
    couch_url="http://couchdb:5984",
    couch_db="marvin",
    couch_user="marvin_sync",
    couch_password="...",
) as client:
    await client.ensure_couch_indexes()          # idempotent, run once
    tasks = await client.find_tasks(title_contains="invoice", done=False)
    today = await client.tasks_by_day("2026-07-07")
    overdue = await client.tasks_due_by("2026-07-07")

Helpers: find_tasks, tasks_by_day, tasks_due_by, planner_items, recurring_generators, categories_from_couch, plus raw couch_find for custom Mango selectors. Couch methods raise MarvinCouchError before any HTTP call when couch is unconfigured — HTTP-only users are unaffected.

find_tasks(title_contains=...) is a substring scan, not an indexed lookup: CouchDB narrows on db via the index, then regex-filters the remaining Task documents. It's bounded by limit (default 25) and fine for interactive search, but don't rely on it for large unbounded queries.

The replica is eventually consistent (replication lag of seconds). Treat it as read-only display state; never seed a write from it — fetch authoritative state with get_doc instead.


Rate Limits

The Amazing Marvin API enforces:

  • Burst: 1 request per 3 seconds
  • Daily cap: 1440 requests per calendar day (resets at midnight in your local timezone)

Pass throttle=True to have the client enforce these limits automatically using an internal asyncio lock. When the daily cap is hit, MarvinRateLimitError is raised with daily_cap_exceeded=True. When the server itself returns 429, MarvinRateLimitError is raised with the retry_after value from the response header (if present).


Timezone Handling

Marvin uses integer minutes east of UTC for timezone offsets. For example:

  • tz_offset=600 — AEST (UTC+10)
  • tz_offset=0 — UTC
  • tz_offset=-300 — EST (UTC-5)

Pass tz_offset at client construction for a default, or override it per-call on methods that accept tz_offset=. The offset affects which calendar day is considered "today" for scheduling and daily cap resets.


Licence

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

amazing_marvin-0.2.0.tar.gz (129.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

amazing_marvin-0.2.0-py3-none-any.whl (18.5 kB view details)

Uploaded Python 3

File details

Details for the file amazing_marvin-0.2.0.tar.gz.

File metadata

  • Download URL: amazing_marvin-0.2.0.tar.gz
  • Upload date:
  • Size: 129.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for amazing_marvin-0.2.0.tar.gz
Algorithm Hash digest
SHA256 c309dcdc0eb155fbfe54885282c2907da0757a35a1acb75b18a3a9207a4b8d53
MD5 9d0b88ec014efa9d651530d123b77e6f
BLAKE2b-256 04660c13d3dc5a5bbd3f3e7d0e42bb21c69526db115f1509235925ee895b2655

See more details on using hashes here.

Provenance

The following attestation bundles were made for amazing_marvin-0.2.0.tar.gz:

Publisher: release.yml on jjsmackay/py-amazing-marvin

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file amazing_marvin-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: amazing_marvin-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 18.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for amazing_marvin-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f24c4f41416edabc232532a14a97cb4b9fced5645448776df1ce13e0664c7541
MD5 03a7c775c05780ed8ddfafd91fce7824
BLAKE2b-256 0357d2c8a3f6a24bd19a3a33eef1202b944c408daf491fa580f54dd5ccfdeda7

See more details on using hashes here.

Provenance

The following attestation bundles were made for amazing_marvin-0.2.0-py3-none-any.whl:

Publisher: release.yml on jjsmackay/py-amazing-marvin

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page