puras

MCP tools

Every tool the purasbackend MCP server exposes, grouped by area.

The MCP server is a thin stdio wrapper over the Puras HTTP API. It loads ~/.purasbackend/config.json once per call and authenticates with the stored API key. Anything you can do here you can do over HTTP with the same key — the MCP is purely a convenience for AI coding agents.

Config

  • configure(api_base, api_key, project_id) -> str — persist credentials to ~/.purasbackend/config.json (chmod 600). Call this once per machine.
  • show_config() -> dict — return current config. Only the prefix of the API key is included, never the secret.

Deployments

  • push(project_dir, notes="", activate=true) -> dict — zip the directory (excluding .git, .venv, node_modules, etc.) and upload as a new deployment. The directory must contain a skills/ folder with at least one skills/<name>/skill.yaml inside; no root manifest is needed. Activates immediately by default; in-flight jobs keep running on the previous version.
  • list_deployments() -> list[dict] — newest first.
  • activate_deployment(deployment_id) -> dict — rolling switch to a specific deployment.
  • delete_deployment(deployment_id) -> str — cannot delete the currently active one.

Jobs

  • submit_job(skill, inputs={}, wait=false, timeout=30) -> dict — submit a job against the named skill in the active deployment. The worker reads skill.yaml and dispatches to the agent loop (.md entrypoint) or the deterministic Python runner (.py:func entrypoint) — same submission shape either way. Use wait=true only for skills you expect to finish in seconds; the hard ceiling is 60s and the row may still be non-terminal on return.
  • get_job(job_id) -> dict — current status + result.
  • list_jobs(status="", limit=25) -> list[dict] — filter by queued|running|succeeded|failed|cancelled or empty for all.
  • tail_job(job_id, max_seconds=60) -> dict — polls the events endpoint until the job terminates or the deadline hits. Returns { job, events, timed_out? }.
  • cancel_job(job_id) -> dict — marks the job cancelled. The worker checks for cancellation between agent steps; an in-flight tool call still completes.

The legacy submit_agentic_job and submit_function_job tools are kept as aliases for backwards compatibility — both now resolve to submit_job (the worker no longer needs a type hint, the skill's manifest is the source of truth). Prefer submit_job.

Feedback

End-user (or owner) thumbs-up / down + optional comment on a job result. One row per (job, end_user_id) — calling again with the same id overwrites in place. The dashboard renders this on the job detail page; your own frontend can hit the same endpoints with the project API key.

  • submit_job_feedback(job_id, rating=0, comment="", end_user_id="") -> dict — upsert. rating is -1 (down) / 0 (no thumb) / +1 (up). Either a non-zero rating or a non-empty comment is required.
  • list_job_feedback(job_id) -> list[dict] — newest first.
  • job_feedback_stats(job_id) -> dict{up, down, count, score}.

Secrets

  • list_secrets() -> list[dict] — names only. Values are never returned by the API.
  • set_secret(name, value) -> dict — create or overwrite. Name must match ^[A-Z_][A-Z0-9_]*$.
  • delete_secret(name) -> str.

Drive

  • drive_sign(path, ttl=3600) -> dict — mint a signed URL for a file under the project's drive. ttl in seconds.

Uploading and listing are HTTP-only (no MCP wrappers — multipart over stdio is awkward and AI agents push files via the API directly):

  • POST /v1/drive/upload — multipart upload, returns {drive_path, signed_url, ...}.
  • GET /v1/drive/list?prefix=... — list folders + files under a project subpath.

See inputs-and-drive for the upload + read pipeline.

Docs

  • list_docs() -> list[dict] — every doc page available locally to this MCP install (the ones you're reading).
  • read_doc(slug) -> str — full markdown body of a single page.
  • search_docs(query, limit=5) -> list[dict] — ranked hits with snippets.

Conventions an AI agent should follow

  • Always pass the full API key including the dot separator: puras_live_<prefix>.<secret>.
  • Prefer from puras import media inside skill code over raw HTTP to /v1/media/generate — same backend, but the SDK handles auth, drive paths, and billing context for you. See sdk-media.
  • Don't push partial bundles; a deployment is the whole project. If you want to ship one fix, that's still a new full deployment.
  • Don't assume wait=true returns terminal state. Long jobs need tail_job or repeated get_job.