Kalpana Docs
Batch MCP

Single jobs

Make a few files without a batch, up to ten jobs at a time.

A job is one page or flow filled with one set of values and rendered on its own: one creative without building a batch. Agents use them when the user wants a few files now. create_job saves up to 10 at once.

The job

get_job, update_job and get_batch_jobs return jobs in this shape. create_job and run_job return { status, jobs }, where status is processing while any job renders, pending while any waits for run_job, and done when each has finished.

type Job = {
  id: string;               // jobId for run_job, get_job and update_job
  status: "pending" | "processing" | "success" | "failed" | "cancelled";
  template: { id: string; name: string } | null;
  page: { id: string; name: string } | null;   // The page it renders; null for a video
  flow: { id: string; name: string } | null;   // The flow it renders as a video, if it does
  batch: string | null;     // The batch it is in; null for a job on its own
  modifications: Record<string, unknown> | null; // The values it renders, by layer; null for a job made in the Kalpana app
  output: {
    format: "png" | "jpeg" | "webp" | "mp4" | "gif";
    kind: "image" | "video";
  };
  creditCost: number;       // Credits the render spends when it succeeds
  error: string | null;     // Why the render failed
  file: {                   // null until the job succeeds
    creativeId: string;
    url: string;            // Link to the rendered file
    fileName: string;
    contentType: string;
    sizeBytes: number;
    width: number | null;
    height: number | null;
  } | null;
};

A job that has rendered, with its modifications as the server holds them (images resolved to their asset ids):

{
  "id": "0d3f9a7e-8b21-4c5d-a6e4-93b1c27f5d08",
  "status": "success",
  "template": { "id": "t9w2k5ce", "name": "Festive sale post" },
  "page": { "id": "k7fq2m8a", "name": "Square" },
  "flow": null,
  "batch": null,
  "modifications": {
    "Headline": "Diwali Sale",
    "Product photo": { "asset": "5f0c2a8e-3b1d-4c6a-9e7f-2d84a1b6c0e3", "name": "kurta-red.jpg" }
  },
  "output": { "format": "png", "kind": "image" },
  "creditCost": 1,
  "error": null,
  "file": {
    "creativeId": "e41b7a09-6c3d-4d85-b2f1-0a9c5e8d7b36",
    "url": "https://cdn.kalpana.one/creatives/diwali-sale.png",
    "fileName": "diwali-sale.png",
    "contentType": "image/png",
    "sizeBytes": 412873,
    "width": 1080,
    "height": 1080
  }
}

A job is editable while it is pending and has no file.


create_job

Saves up to 10 jobs, each filling one page (page) or one flow (flow, a video) with its own modifications and output: a few files without building a batch. batch adds them to an existing batch; without it they stand alone, named by output.fileName or else the template's name.

With run set to false they are saved as pending and spend nothing. With run set to true they render at once, spending their creditCost when they succeed (failed renders are not charged, and the whole request is refused when the credits do not cover it). The answer waits up to 30 seconds for the files; a job still rendering after that comes back with status: "processing", and get_job a few seconds later gets its file.

Every issue across the jobs comes back in one error, with nothing saved. Every call makes new jobs, so after an error check get_job or get_batch_jobs before calling again. For more rows use create_batch.

Needs templates:read and batches:create on the connection, and renders:create in the user's workspace role to run.

  • Annotations: readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false

  • Input Parameters:

    ParameterTypeRequiredDescription
    jobsArray<{ page | flow, modifications, output? }>Yes1 to 10 jobs. Each gives a page (from get_template_inputs pages) or a flow (a video, with a video output format), its modifications (keyed and valued as in validate_batch) and its output ({ format, fileName, stillTime }, png when omitted).
    batchstringNoUUID of a batch to add the jobs to.
    runbooleanNoRender them now, spending their creditCost. Defaults to false.
  • Output Schema: { status: "processing" | "pending" | "done", jobs: Array<Job> }.

A square post and a story from two templates, plus a video from a flow whose second visit to a page shows other copy, saved but not run:

{
  "jobs": [
    {
      "page": "k7fq2m8a",
      "modifications": { "Headline": "Diwali Sale", "Product photo": "kurta-red.jpg" },
      "output": { "format": "png", "fileName": "diwali-square" }
    },
    {
      "page": "p3x9d1we",
      "modifications": { "Headline": "Diwali Sale", "Badge": { "visible": false }, "Brand logo": null },
      "output": { "format": "jpeg" }
    },
    {
      "flow": "r2m6v0qb",
      "modifications": { "Headline": "Diwali Sale", "k7fq2m8a#2@Headline": "Last 3 days" },
      "output": { "format": "mp4", "fileName": "diwali-video" }
    }
  ],
  "run": false
}

With run, agents state the credit cost and get the user's confirmation first, as for run_batch.


run_job

Renders one pending or failed job (from create_job, or get_batch_jobs), spending its creditCost when it succeeds; failed renders are not charged, so a failed job can be run again. The answer waits up to 30 seconds for the file, and a job still rendering then comes back with status: "processing". A job already rendering, rendered or cancelled is refused, so repeating the call does not render or charge twice; get_job reports it.

Needs batches:create on the connection and renders:create in the user's workspace role.

  • Annotations: readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false

  • Input Parameters:

    ParameterTypeRequiredDescription
    jobIdstringYesJob ID from create_job or get_batch_jobs.
  • Output Schema: { status, jobs: [Job] }, as for create_job.


get_job

Returns one job's status, its modifications and, once it has rendered, its file: URL, file name, size and dimensions. It answers at once; agents call it a few seconds apart after create_job or run_job answered with a job still rendering. A pending job has nothing running; run_job starts it. For a batch's files use get_batch_outputs.

Needs batches:read, renders:read and creatives:read.

  • Annotations: readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false

  • Input Parameters:

    ParameterTypeRequiredDescription
    jobIdstringYesJob ID from create_job, run_job or get_batch_jobs.
  • Output Schema: the job.

Was this page helpful?

Updated 10 Nov 2026

On this page