Search / io.github.maginaryai/maginary-mcp
maginary-mcp
R0· no sign-inAI image + video generation for agents: --flag prompt DSL, async generate/poll, x402 pay-per-use.
v0.3.18 · active · repository · website · descriptor JSON · versions
Search / io.github.maginaryai/maginary-mcp
R0· no sign-inAI image + video generation for agents: --flag prompt DSL, async generate/poll, x402 pay-per-use.
v0.3.18 · active · repository · website · descriptor JSON · versions
{
"mcpServers": {
"maginary-mcp": {
"type": "http",
"url": "https://mcp.maginary.ai/mcp"
}
}
}claude mcp add --transport http maginary-mcp https://mcp.maginary.ai/mcp[mcp_servers.maginary-mcp]
url = "https://mcp.maginary.ai/mcp"
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"maginary-mcp": {
"type": "remote",
"url": "https://mcp.maginary.ai/mcp",
"enabled": true
}
}
}{
"mcpServers": {
"maginary-mcp": {
"type": "http",
"url": "https://mcp.maginary.ai/mcp"
}
},
"deeplink": "cursor://anysphere.cursor-deeplink/mcp/install?name=maginary-mcp&config=eyJ0eXBlIjoiaHR0cCIsInVybCI6Imh0dHBzOi8vbWNwLm1hZ2luYXJ5LmFpL21jcCJ9"
}{
"servers": {
"maginary-mcp": {
"type": "http",
"url": "https://mcp.maginary.ai/mcp"
}
}
}{
"mcpServers": {
"maginary-mcp": {
"httpUrl": "https://mcp.maginary.ai/mcp"
}
}
}extensions:
"maginary-mcp":
enabled: true
name: "maginary-mcp"
type: streamable_http
uri: "https://mcp.maginary.ai/mcp"
timeout: 300
protocol.modernnewest supported version is 2025-11-25; 2026-07-28 not supported, older versions are deprecated until 2027-07-28protocol.statelessonly applies to 2026-07-28 serversprotocol.transportstreamable HTTPprotocol.list_ttlonly applies to 2026-07-28 serversauth.prm, auth.as_metadata, auth.cimdno remote uses OAuthauth.secret_in_urlno templated URLtools.descriptionsevery tool has a descriptiontools.description_length4 tools have descriptions over 1,024 characters, which crowds the contexttools.schemasevery tool has an object input schematools.annotations16 of 16 tools declare readOnlyHint or destructiveHinttools.directory_hintsevery tool declares readOnlyHint, destructiveHint, idempotentHint and openWorldHinttools.token_costabout 6,292 tokens to load every tooltools.api_dumptools are not a one-to-one API dumpstability.changes2 tool changes in 30 daysstability.rug_pullno tool changed its meaning under the same namedeps.known_vulnsno known advisory in 30 resolved packagesdeps.mcp_sdk_versionmcp 1.30.0, no known advisorydeps.resolvable[email protected] resolved: 30 packagesexecute_actionchangeddescription, input schemaRun a follow-up action on a completed generation's image. After ``generate`` → ``wait_for_generation``, the response's ``processing_result.available_actions`` lists what's possible per slot. Call this tool with one of those action types. Args: generation_uuid: UUID of the parent generation (from ``generate``). action_type: One of the values from ``available_actions`` — e.g. ``"upscale_2x"``, ``"upscale_1_5x"``, ``"vary_strong"``, ``"vary_subtle"``, ``"pan_left"``, ``"pan_right"``, ``"pan_up"``, ``"pan_down"``, ``"zoom_out_2x"``, ``"zoom_out_1_5x"``, ``"img2vid_basic"``, ``"reroll"``. parent_image_index: The slot index of the image to act on (0, 1, 2, or 3 for a 4-image grid). Required for per-slot actions; omit for ``"reroll"`` (global action). prompt: Optional replacement prompt. For ``vary_*`` you can steer the variation with a new prompt; for ``img2vid_basic`` you can describe the desired motion. callback_url: Optional webhook URL (same as ``generate``). Returns: The newly created child generation record (same shape as ``generate``'s return — poll it with ``wait_for_generation``). On failure, same ``isError`` contract as ``generate``: ``"auth"``, ``"payment_required"`` (with x402 challenge), or ``"failed"``.
Run a follow-up action on a completed generation's image. After ``generate`` → ``wait_for_generation``, the response's ``processing_result.available_actions`` lists what's possible per slot. Call this tool with one of those action types. Args: generation_uuid: UUID of the parent generation (from ``generate``). action_type: One of the values from ``available_actions`` — e.g. ``"upscale_2x"``, ``"upscale_1_5x"``, ``"vary_strong"``, ``"vary_subtle"``, ``"pan_left"``, ``"pan_right"``, ``"pan_up"``, ``"pan_down"``, ``"zoom_out_2x"``, ``"zoom_out_1_5x"``, ``"img2img_basic"``, ``"img2img_inpaint"``, ``"img2vid_basic"``, ``"reroll"``. parent_image_index: The slot index of the image to act on (0, 1, 2, or 3 for a 4-image grid). Required for per-slot actions; omit for ``"reroll"`` (global action). prompt: Required for ``img2img_basic``, where it is the edit instruction (e.g. ``"make the hat red"``; flags such as ``--2`` or ``--flagship`` may follow it), and for ``img2img_inpaint``, where it is the instruction followed by ``--mask <shapes>`` (e.g. ``"make the hat red --mask rect(.2,.1 .8,.4)"``; the instruction may be empty to just redo the area). Optional otherwise: for ``vary_*`` you can steer the variation with a new prompt; for ``img2vid_basic`` you can describe the desired motion. callback_url: Optional webhook URL (same as ``generate``). Returns: The newly created child generation record (same shape as ``generate``'s return — poll it with ``wait_for_generation``). On failure, same ``isError`` contract as ``generate``: ``"auth"``, ``"payment_required"`` (with x402 challenge), or ``"failed"``.
wait_for_generationchangeddescriptionPoll ``get_generation`` on a backoff until it reaches done / failed. Args: uuid: The UUID returned by ``generate``. timeout_s: Return after this many seconds even if still running. Default 45 stays under the 60 s per-call limit most MCP clients enforce; a ``timeout`` result just means "call again". Only raise it (e.g. for video) on clients you know allow long tool calls. Returns: The terminal generation record — which includes generations that failed server-side: those are SUCCESSFUL tool calls returning ``processing_state: "failed"`` with empty ``image_urls``, so always check the state. On tool failure, an ``isError`` result whose ``error`` field is ``"timeout"`` (``message`` names the last observed state — the generation keeps running server-side and can be re-fetched with ``get_generation`` later), ``"auth"``, or ``"failed"``. **Follow-up actions:** A ``done`` generation's ``processing_result.available_actions`` maps slot indices to valid action types — e.g. ``{"0": ["upscale_2x", "vary_strong", "pan_left", "zoom_out_2x", "img2vid_basic", ...], "global": ["reroll"]}``. Use ``execute_action`` with the ``uuid``, a chosen ``action_type``, and the ``parent_image_index`` (the slot key as an int) to run an action on a specific output image.
Poll ``get_generation`` on a backoff until it reaches done / failed. Args: uuid: The UUID returned by ``generate``. timeout_s: Return after this many seconds even if still running. Default 45 stays under the 60 s per-call limit most MCP clients enforce; a ``timeout`` result just means "call again". Only raise it (e.g. for video) on clients you know allow long tool calls. Returns: The terminal generation record — which includes generations that failed server-side: those are SUCCESSFUL tool calls returning ``processing_state: "failed"`` with empty ``image_urls``, so always check the state. On tool failure, an ``isError`` result whose ``error`` field is ``"timeout"`` (``message`` names the last observed state — the generation keeps running server-side and can be re-fetched with ``get_generation`` later), ``"auth"``, or ``"failed"``. **Follow-up actions:** A ``done`` generation's ``processing_result.available_actions`` maps slot indices to valid action types — e.g. ``{"0": ["upscale_2x", "vary_strong", "pan_left", "zoom_out_1_5x", "img2img_basic", "img2img_inpaint", "img2vid_basic", ...], "global": ["reroll"]}``. Use ``execute_action`` with the ``uuid``, a chosen ``action_type``, and the ``parent_image_index`` (the slot key as an int) to run an action on a specific output image.
Full history: list_changes · trend: quality JSON.
Checks run on what our credential-free, read-only probes observe; tools are never called and no code audit is performed. How it is computed.
+repository +namespace-matches-repo +website +reachable +uptime-100% ~updated-35d-ago
Derived from observable signals (official registry feed and our own credential-free probes); no code audit performed. How it is computed.
[email protected] PyPI29 dependencies, resolved · MCP SDK mcp 1.30.0 · advisories checked 2026-10-19
No known advisory affects this dependency graph.
Dependency graphs from deps.dev; advisories from OSV.dev, including the GitHub Advisory Database and the PyPI Advisory Database; all CC BY 4.0. The graph is what a clean install of this version resolves today; nothing was installed or run. How it is checked.
| remote | auth | reachable | uptime 30d | p50 | protocol | last ok |
|---|---|---|---|---|---|---|
https://mcp.maginary.ai/mcp streamable-http | none | yes | 100% | 482 ms | 2025-11-25 | 2026-10-20 |
| package | registry | version | runtime | secrets |
|---|---|---|---|---|
maginary-mcp | pypi | 0.3.18 | uvx | MAGINARY_API_KEY |
check_account_statusread-only | Check account verification status, credit balance, and API key count. Use this after ``create_account`` to poll whether the user has clicked the verification link. Pass ``email`` + ``password`` (from ``create_account``) for Basic auth, or omit both to use the configured API key. Args: email: Account email (for Basic auth). password: Account password (for Basic auth). Returns: Dict with ``verified`` (bool), ``email``, ``api_key_count``, ``credits_remaining``, ``uploads_remaining``. |
checkout | Create a Stripe checkout session for purchasing a product. Returns a ``checkout_url`` — the user must open it in a browser to complete payment. After payment, credits are provisioned automatically via webhook. **Present the URL exactly as returned, including the ``#fragment`` — do not truncate, reformat, or strip any part of it.** If the agent has a USDC wallet, skip this entirely — just call ``generate`` and the x402 protocol handles payment on-chain. Args: product_id: Product ID from ``get_products``. email: Account email (for Basic auth during onboarding). password: Account password (for Basic auth during onboarding). Returns: Dict with ``checkout_url``. On failure, an ``isError`` result — e.g. ``error: "email_not_verified"`` until the user clicks the verification link, or ``"auth"`` / ``"failed"``. |
configure_api_key | Activate an API key. Local (stdio) servers persist it; hosted does not. Call this after ``manage_api_key(action='create')`` returns a ``raw_key``. On a local server the key is saved to ``~/.config/maginary/api_key`` (chmod 600) and survives restarts. On the hosted server (mcp.maginary.ai) nothing can be stored — auth is per-request: the response will say ``persisted: false`` and the key must be sent as an ``Authorization: Bearer <key>`` header on every request (set it in the MCP client's connection config). Args: api_key: The full API key string returned by ``manage_api_key``. Returns: Confirmation dict. |
create_account | Create a new Maginary account for the given email address. Returns the auto-generated password — display it to the user ONCE so they can save it. A verification email is sent; the user must click the link before the account can generate images. After verification, use ``manage_api_key(action='create')`` with ``email`` + ``password`` to get an API key, then ``configure_api_key`` to activate it. Args: email: The user's email address. Returns: Dict with ``email``, ``password``, and ``message``. On failure, an ``isError`` result — e.g. ``error: "already_exists"`` (email taken: ask the user for their password or a different email), ``"rate_limited"``, or ``"failed"``. |
create_wallet_accountdestructive | Create (or access) a Maginary account using a wallet signature. Sign the message ``Maginary: authenticate <address> at <timestamp>. This does not move funds.`` with EIP-191 ``personal_sign`` and pass all three values. On success, an API key is returned immediately — no email verification needed. Use this when you have a wallet but no email. The returned ``api_key`` should be passed as ``Authorization: Bearer <key>`` in the MCP client config, or via ``configure_api_key`` (stdio) / ``_meta["maginary/api_key"]`` (hosted, per-call). If the wallet already has an account, returns the existing account with a fresh API key. Args: address: EVM wallet address (0x..., 42 chars). signature: Hex-encoded EIP-191 personal_sign of the auth message. timestamp: Unix epoch seconds used in the signed message (must be within the last 5 minutes). Returns: Dict with ``address``, ``api_key`` (full key — show once), ``key_prefix``, ``created`` (bool), ``message``. On failure: ``isError`` with ``error`` = ``"validation"``, ``"signature_failed"``, or ``"rate_limited"``. |
execute_action | Run a follow-up action on a completed generation's image. After ``generate`` → ``wait_for_generation``, the response's ``processing_result.available_actions`` lists what's possible per slot. Call this tool with one of those action types. Args: generation_uuid: UUID of the parent generation (from ``generate``). action_type: One of the values from ``available_actions`` — e.g. ``"upscale_2x"``, ``"upscale_1_5x"``, ``"vary_strong"``, ``"vary_subtle"``, ``"pan_left"``, ``"pan_right"``, ``"pan_up"``, ``"pan_down"``, ``"zoom_out_2x"``, ``"zoom_out_1_5x"``, ``"img2img_basic"``, ``"img2img_inpaint"``, ``"img2vid_basic"``, ``"reroll"``. parent_image_index: The slot index of the image to act on (0, 1, 2, or 3 for a 4-image grid). Required for per-slot actions; omit for ``"reroll"`` (global action). prompt: Required for ``img2img_basic``, where it is the edit instruction (e.g. ``"make the hat red"``; flags such as ``--2`` or ``--flagship`` may follow it), and for ``img2img_inpaint``, where it is the instruction followed by ``--mask <shapes>`` (e.g. ``"make the hat red --mask rect(.2,.1 .8,.4)"``; the instruction may be empty to just redo the area). Optional otherwise: for ``vary_*`` you can steer the variation with a new prompt; for ``img2vid_basic`` you can describe the desired motion. callback_url: Optional webhook URL (same as ``generate``). Returns: The newly created child generation record (same shape as ``generate``'s return — poll it with ``wait_for_generation``). On failure, same ``isError`` contract as ``generate``: ``"auth"``, ``"payment_required"`` (with x402 challenge), or ``"failed"``. |
generate | Kick off a generation via POST /api/gens/. Args: prompt: The user's words, passed through as-is. Do NOT add flags the user did not ask for — no ``--ar``, no ``--flagship``, no model flags. Every extra flag costs credits; adding them unrequested is wrong. Standard quality is the default and is cheap; ``--flagship`` is ~4× more expensive and must only be used when the user explicitly asks for best quality. If the user asks about quality or aspect ratio: ask them first (standard vs flagship, landscape vs portrait) before generating. Flags go at the END, only when the user asked: ``--1``/``--2``/``--3``/``--4`` = image count (default 4), ``--ar 16:9`` = aspect ratio, ``--flagship`` = best quality. Unknown flag: call ``get_parameter(name)`` first — never guess. Examples — user says "a fox": prompt is ``"a fox"``. User says "a fox, landscape, best quality": prompt is ``"a fox --ar 16:9 --flagship"``. **Image-to-image (img2img):** Place one or more public image URLs in the prompt, followed by editing instructions: ``"https://cdn.example.com/photo.webp reimagine as oil painting --ar 16:9"`` The engine extracts URLs automatically and switches to img2img mode. Multiple URLs trigger multi-input mode (compositing/combining). Use ``upload_image`` first if images aren't already hosted. **Image-to-video:** Place an image URL in the prompt AND add ``--mp4`` plus video flags (``--5sec``, ``--1080p``). Or use ``execute_action`` with ``action_type="img2vid_basic"`` on a completed generation's image. **Style reference (--sref) is NOT img2img:** ``--sref <url>`` copies the visual *style* of a reference image (colors, mood, composition) without using the image content as input. A bare URL in the prompt edits the actual image; ``--sref`` transfers style. callback_url: Optional HTTPS URL that will receive a webhook when the generation reaches done / failed. See https://maginary.ai/blog/webhooks-guide for signature verification. Returns: On success, the created generation record. Key fields: ``uuid`` (use to poll), ``action_type``, ``processing_state``, ``expected_output_count``. On failure, an ``isError`` result instead (nothing is raised), with a JSON body whose ``error`` field is one of: - ``"auth"`` — no/invalid API key. Surface the message directly to the human. - ``"payment_required"`` — out of credits. The body carries ``billing_url`` and top-level x402 fields (``accepts``, ``resource``): either send the human to ``billing_url`` to top up, or pay programmatically via x402 (settle ``accepts[0]`` with USDC on Base and retry). - ``"demo_not_found"`` — ``--demo`` prompt has no matching seeded generation. ``available_demos`` lists valid prompts. - ``"failed"`` — anything else (invalid prompt, rate limit, backend or network error); see ``message``. x402 over MCP: a ``payment_required`` result also carries the x402 fields at the top level (``accepts``, ``resource``); an x402-capable client signs ``accepts[0]`` and calls this tool again with the payment in ``_meta["x402/payment"]``. The settled call returns the generation with ``x402_receipt`` (and ``_meta["x402/payment-response"]``); a wallet's first settlement creates its account. Subsequent requests use wallet-signed auth headers (X-Wallet-Address/Signature/Timestamp) or pass an API key as ``_meta["maginary/api_key"]``. Every flag that exists, and its state: Flags, live (35): --ar, --output-count (--1/--2/--3/--4), --seed, --transparent, --sref, --sw, --png, --jpg, --webp, --svg, --2k, --4k, --upscale, --vary, --varysubtle, --varystrong, --panleft, --panright, --panup, --pandown, --zoomout, --mp4, --video-resolution (--480p/--540p/--720p/--1024p/--1080p/--2160p / --4k (4k, Seedance 2 Pro)/--480p24 / --480p24fps/--540p24 / --540p24fps/--720p24 / --720p24fps/--1024p30 / --1024p30fps/--1080p24 / --1080p24fps), --video-fps (--24fps/--30fps/--50fps/--60fps), --video-duration (--4s / --4sec/--5s / --5sec/--6s / --6sec/--8s / --8sec/--10s / --10sec/--12s / --12sec), --flagship, --sora, --soralite, --nanobananapro, --nb2, --gpt2, --gpt2high, --seedance2, --seedance2pro, --demo. Partial (4, only some models honour them): --no, --zoomout2x, --zoomoutexpand, --zoomoutexpand2x. Reserved (2, the parser rejects them): --cref, --cw. Any other --flag is rejected with `Unrecognized parameter`. Details: `get_parameter(name)`. |
get_balanceread-only | Check remaining credits and uploads for the authenticated account. Args: email: Account email (for Basic auth). password: Account password (for Basic auth). Returns: Dict with ``credits_remaining`` and ``uploads_remaining``. |
get_generationread-only | Fetch a generation by UUID (GET /api/gens/{uuid}/). Args: uuid: The UUID returned by ``generate``. Returns: The full generation record. If terminal, ``image_urls[]`` holds the finished outputs and ``processing_result.slots[]`` the per-slot detail. NOTE: a generation that failed server-side is a SUCCESSFUL tool call returning ``processing_state: "failed"`` — always check the state, never infer success from the absence of a tool error. **Follow-up actions:** A completed generation's ``processing_result.available_actions`` maps slot indices to valid action types. E.g. ``{"0": ["upscale_2x", "vary_strong", ...], "global": ["reroll"]}``. Use ``execute_action`` with the ``uuid``, a chosen ``action_type``, and the ``parent_image_index`` (the slot key as an int) to run an action. Hosted: a key obtained mid-session may be passed as ``_meta["maginary/api_key"]``. |
get_parameterread-only | Return the full record for a single parameter (canonical name or alias). Args: name: Parameter name with or without leading ``--`` (e.g. ``ar``, ``--ar``, ``aspect``). Case-insensitive. Returns: The parameter dict. Not-found is an ``isError`` result — surface it rather than fabricating a param. |
get_productsread-only | List available Maginary products/plans with pricing. No authentication required. Use this to present purchase options to the user. The ``novice_pack`` ($10, 150 credits) is the recommended starting point. Returns: Dict with ``count`` and ``products`` — each product carries ``id``, ``short_name``, ``title``, ``description``, ``price_cents``, ``credits``, ``uploads``, ``is_subscription``. (The backend sends a bare array; it is wrapped here because FastMCP validates tool output against the dict annotation and rejects a top-level list.) |
list_parametersread-only | List Maginary prompt-DSL parameters. Args: category: Restrict to one category (e.g. ``composition``, ``video``, ``model``, ``outpaint``). Call with no filters once — the response's ``categories`` / ``statuses`` maps are the full taxonomy. status: Restrict to one status (``live``, ``mostly-dead``, ``unimplemented``). include_reserved: When False (default) drop ``unimplemented`` (recognized-but-blocked) parameters from the result. Returns: A dict with ``count``, ``source`` (``live`` vs. ``bundled-snapshot``), ``categories`` / ``statuses`` (the filter taxonomy), and ``parameters`` (the array of matching entries). |
manage_api_keydestructive | Create, list, or revoke Maginary API keys (up to 10 per account). Auth: pass ``email`` + ``password`` for Basic auth (onboarding), or omit both to use the configured API key (normal operation). Args: action: One of ``create``, ``list``, ``revoke``. name: Key name (required for ``create``). key_prefix: 8-char prefix of the key to revoke (required for ``revoke``). email: Account email (for Basic auth). password: Account password (for Basic auth). Returns: For ``create``: dict with ``raw_key`` (the full key — show once, then use ``configure_api_key`` to activate it), ``key_prefix``, ``name``. For ``list``: dict with ``keys`` array. For ``revoke``: success/error message. |
search_parametersread-only | Text-search over parameter names, aliases, descriptions, values, examples. Args: query: Substring match, case-insensitive. category: Optional single-category restriction. include_reserved: Whether to include ``unimplemented`` parameters. Returns: Dict with ``count``, ``source`` (``live`` vs. ``bundled-snapshot``), and ``parameters`` (ordered as they appear in the catalog). |
upload_image | Upload a local image and get a CDN URL for img2img or ``--sref``. Only available on local (stdio) connections. On hosted/remote connections, place an existing image URL directly in the prompt. Place the returned ``url`` in a ``generate`` prompt: ``generate("https://cdn.maginary.ai/…/photo.webp reimagine as oil painting")`` Args: file_path: Path to an image file on disk (JPEG, PNG, WebP, HEIC). filename: Original filename. Inferred from ``file_path`` if omitted. Returns: Dict with ``url`` (the public CDN URL), ``exists`` (deduplicated), ``credits_deducted``, and ``message``. |
wait_for_generationread-only | Poll ``get_generation`` on a backoff until it reaches done / failed. Args: uuid: The UUID returned by ``generate``. timeout_s: Return after this many seconds even if still running. Default 45 stays under the 60 s per-call limit most MCP clients enforce; a ``timeout`` result just means "call again". Only raise it (e.g. for video) on clients you know allow long tool calls. Returns: The terminal generation record — which includes generations that failed server-side: those are SUCCESSFUL tool calls returning ``processing_state: "failed"`` with empty ``image_urls``, so always check the state. On tool failure, an ``isError`` result whose ``error`` field is ``"timeout"`` (``message`` names the last observed state — the generation keeps running server-side and can be re-fetched with ``get_generation`` later), ``"auth"``, or ``"failed"``. **Follow-up actions:** A ``done`` generation's ``processing_result.available_actions`` maps slot indices to valid action types — e.g. ``{"0": ["upscale_2x", "vary_strong", "pan_left", "zoom_out_1_5x", "img2img_basic", "img2img_inpaint", "img2vid_basic", ...], "global": ["reroll"]}``. Use ``execute_action`` with the ``uuid``, a chosen ``action_type``, and the ``parent_image_index`` (the slot key as an int) to run an action on a specific output image. |
Schemas: list_tools.
{
"name": "io.github.maginaryai/maginary-mcp",
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
"remotes": [
{
"url": "https://mcp.maginary.ai/mcp",
"type": "streamable-http"
}
],
"version": "0.3.18",
"packages": [
{
"version": "0.3.18",
"transport": {
"type": "stdio"
},
"identifier": "maginary-mcp",
"runtimeHint": "uvx",
"registryType": "pypi",
"registryBaseUrl": "https://pypi.org",
"environmentVariables": [
{
"name": "MAGINARY_API_KEY",
"isSecret": true,
"description": "Bearer token from https://app.maginary.ai/dashboard#api-keys. Optional: without it the server offers in-chat signup (create_account) or wallet signup (create_wallet_account); catalog tools always work."
}
]
}
],
"repository": {
"url": "https://github.com/maginaryai/maginary-mcp",
"source": "github"
},
"websiteUrl": "https://maginary.ai/mcp",
"description": "AI image + video generation for agents: --flag prompt DSL, async generate/poll, x402 pay-per-use."
}