Documentation

Foundry exposes GPU notebooks to agents. Prefer the MCP connector when your client supports remote MCP; use the REST Agent API for scripts and custom integrations.

Base URL: https://foundry-mocha-ten.vercel.app

Getting started

  1. Create an account and verify your email.
  2. Open Settings → API keys and create a key. Copy the secret once — it starts with fdry_sk_.
  3. Connect via MCP (Settings → MCP has the connector URL), or call /api/v1 with the Bearer key.

MCP connector

MCP (Model Context Protocol) is a standard way for an agent client to discover and call tools on a remote server. Foundry hosts a remote MCP endpoint: your client opens a session to Foundry, authenticates with your API key, then lists tools such as create notebook, upload file, and start training. The agent never needs to hand-write HTTP paths for common jobs — it calls named tools and receives JSON results.

How the connection works

  1. Connector URL— a single HTTPS endpoint that speaks MCP over HTTP. Foundry's URL is:
    https://foundry-mocha-ten.vercel.app/api/mcp/mcp
  2. Auth header — every request includes Authorization: Bearer fdry_sk_…. The server verifies the key against your account (hashed at rest). Invalid keys get no tools.
  3. Session — the client initializes MCP, reads serverInfo.name = foundry, then lists tools. Each tool has a name, description, and JSON schema for arguments.
  4. Tool calls — when the agent decides to train, it invokes a tool (for example create_notebook). Foundry runs the same backend logic as the dashboard and REST API, then returns structured text/JSON in the tool result.
  5. Same account as the UI — notebooks created over MCP appear under Dashboard → Notebooks for that API key's user. Status and logs stay in sync.

Configure your client

In any MCP-capable client that supports a remote URL + custom headers, add a server entry like this (replace the key). You can also copy a ready-made config from Settings → MCP.

{
  "mcpServers": {
    "foundry": {
      "url": "https://foundry-mocha-ten.vercel.app/api/mcp/mcp",
      "headers": {
        "Authorization": "Bearer fdry_sk_…"
      }
    }
  }
}
  • Use the full path /api/mcp/mcp (not just /api/mcp).
  • Do not commit plaintext keys to git.
  • If tools do not appear, reconnect the server and confirm the key still exists in Settings.

Auth for remote connectors

Clients that only send a URL (no custom headers) use Foundry's OAuth sign-in: they discover /.well-known/oauth-authorization-server, register a client, then open the consent page. You paste your fdry_sk_… key once; Foundry returns an access token the connector stores. Clients that support custom headers can still send Authorization: Bearer fdry_sk_… directly.

MCP tools

Tools map 1:1 onto notebook operations. Arguments are validated; failures return an error field in the result payload.

ToolWhat it does
list_notebooksList notebooks for the authenticated account (id, title, status, gpu).
create_notebookCreate a notebook from a template (llm-lora, whisper, …) and GPU (cpu, T4, L4, A10G).
get_notebookFetch one notebook: cells, trainConfig, events, status.
set_noteAttach a dataset / training note (stored in trainConfig.datasetNote).
list_filesList files already in the notebook workspace (names, sizes, path).
upload_fileUpload a dataset file. Pass filename + content as utf8 text or base64. Max ~8 MB per call via MCP.
start_trainingRun the full train recipe on Modal GPUs (config → load → train → eval → export).
get_statusPoll status: idle | running | ready | failed (plus timestamps).
get_logsFetch recent run / training log lines for debugging.

upload_file details

Remote MCP cannot send multipart form data the way browsers do. Instead, pass the file body as a string:

  • encoding: "utf8" (default) — paste JSONL/CSV/TXT content directly into content.
  • encoding: "base64" — for binary or large-safe transfers; Foundry decodes to bytes on disk.
  • After upload, trainConfig.files and datasetPath update so training cells see the files.
  • For very large datasets over REST, use multipart POST /api/v1/notebooks/:id/files (up to ~200 MB per file).

MCP training loop

This is the recommended agent loop. Notebook runs do not spend account credits.

  1. create_notebook — pick template_id (usually llm-lora) and a GPU.
  2. upload_file — send train.jsonl (or similar) with utf8 content. Optionally call set_note to describe the data.
  3. start_training — kicks off Modal. This can take a while; the tool waits for the run orchestration to finish or error.
  4. get_status / get_logs — confirm ready or diagnose failed.
Agent checklist (MCP):
1. create_notebook  { title, template_id: "llm-lora", gpu: "T4" }
2. upload_file      { notebook_id, filename: "train.jsonl", content: "…", encoding: "utf8" }
3. set_note         { notebook_id, note: "Support FAQ pairs" }   # optional
4. start_training   { notebook_id }
5. get_status / get_logs until ready or failed

Connector: https://foundry-mocha-ten.vercel.app/api/mcp/mcp
Auth: Authorization: Bearer fdry_sk_…

For AI agents

If MCP is unavailable, drive Foundry with the REST Agent API. Give the agent these facts:

  • Host: https://foundry-mocha-ten.vercel.app
  • Auth: Authorization: Bearer fdry_sk_…
  • JSON for most calls; multipart form for file uploads (files=@path).
  • Loop: create → upload → train → poll status/logs. Notebooks do not debit credits.

Agent system brief

You have access to the Foundry Agent API.

Base URL: https://foundry-mocha-ten.vercel.app
Auth: Authorization: Bearer $FOUNDRY_API_KEY
(Key looks like fdry_sk_… — never print the full secret.)

Prefer MCP tools when connected. Otherwise:
1. POST /api/v1/notebooks  { "title":"…", "templateId":"llm-lora", "gpu":"T4" }
2. POST /api/v1/notebooks/{id}/files  multipart field "files" with dataset
3. PATCH /api/v1/notebooks/{id}  optional trainConfig (epochs, datasetNote, …)
4. POST /api/v1/notebooks/{id}/train  {}
5. Poll GET /api/v1/notebooks/{id}/status and /logs until status is ready or failed

Templates: llm-lora | whisper | handwriting | video | voice | robotics
GPUs: cpu | T4 | L4 | A10G

Notebook cell runs and training do not spend account credits.

Authentication

Every /api/v1/* and MCP request needs a Bearer token. Keys are hashed at rest; the plaintext secret is shown once at creation.

curl "https://foundry-mocha-ten.vercel.app/api/v1/notebooks" \
  -H "Authorization: Bearer $FOUNDRY_API_KEY"
  • Prefix: fdry_sk_
  • Max 5 active keys per account
  • Manage keys in Dashboard → Settings
  • Revoke or delete a key immediately if it leaks

Scopes

Keys can be limited to specific actions. New keys default to all scopes. MCP uses the same key; keep full notebook scopes enabled for training agents.

ScopeAllows
notebooks:readList notebooks, get status, read logs
notebooks:writeCreate, update, delete notebooks
notebooks:filesUpload / list / delete dataset files
notebooks:runRun cells (single or all)
notebooks:trainStart the train recipe on Modal

Missing scope → 403 with code: "forbidden". Bad or missing key → 401 unauthorized.

REST end-to-end

export FOUNDRY_API_KEY=fdry_sk_…
export HOST=https://foundry-mocha-ten.vercel.app

# 1) Create
curl -s -X POST "$HOST/api/v1/notebooks" \
  -H "Authorization: Bearer $FOUNDRY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title":"Agent train","templateId":"llm-lora","gpu":"T4"}'

# 2) Upload dataset (JSONL recommended)
curl -s -X POST "$HOST/api/v1/notebooks/NOTEBOOK_ID/files" \
  -H "Authorization: Bearer $FOUNDRY_API_KEY" \
  -F "files=@./train.jsonl"

# 3) Optional config tweak
curl -s -X PATCH "$HOST/api/v1/notebooks/NOTEBOOK_ID" \
  -H "Authorization: Bearer $FOUNDRY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"trainConfig":{"epochs":3,"datasetNote":"Support chat pairs"}}'

# 4) Train on Modal
curl -s -X POST "$HOST/api/v1/notebooks/NOTEBOOK_ID/train" \
  -H "Authorization: Bearer $FOUNDRY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

# 5) Poll
curl -s "$HOST/api/v1/notebooks/NOTEBOOK_ID/status" \
  -H "Authorization: Bearer $FOUNDRY_API_KEY"
curl -s "$HOST/api/v1/notebooks/NOTEBOOK_ID/logs" \
  -H "Authorization: Bearer $FOUNDRY_API_KEY"

Endpoints

All paths are under /api/v1. Responses are JSON unless noted.

GET/api/v1/notebooks

List your notebooks and remaining credits.

Scope: notebooks:read

curl "$HOST/api/v1/notebooks" -H "Authorization: Bearer $FOUNDRY_API_KEY"
POST/api/v1/notebooks

Create a notebook. Optional: title, description, gpu, templateId, trainConfig, cells.

Scope: notebooks:write

curl -X POST "$HOST/api/v1/notebooks" \
  -H "Authorization: Bearer $FOUNDRY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title":"My LoRA","templateId":"llm-lora","gpu":"T4"}'
GET/api/v1/notebooks/:id

Fetch full notebook: cells, trainConfig, events.

Scope: notebooks:read

PATCH/api/v1/notebooks/:id

Update title, description, gpu, cells, or trainConfig. Updating trainConfig refreshes the FOUNDRY_CONFIG cell.

Scope: notebooks:write

DELETE/api/v1/notebooks/:id

Delete a notebook.

Scope: notebooks:write

POST/api/v1/notebooks/:id/files

Upload dataset files. Multipart form field name: files (repeat for multiple). Max ~200 MB each.

Scope: notebooks:files

curl -X POST "$HOST/api/v1/notebooks/ID/files" \
  -H "Authorization: Bearer $FOUNDRY_API_KEY" \
  -F "files=@./train.jsonl"
GET/api/v1/notebooks/:id/files

List uploaded files and workspace path.

Scope: notebooks:files

DELETE/api/v1/notebooks/:id/files

Remove a file. Body: { "name": "train.jsonl" }.

Scope: notebooks:files

POST/api/v1/notebooks/:id/train

Apply optional config, then run the full recipe on Modal (config → load → train → eval → export).

Scope: notebooks:train

curl -X POST "$HOST/api/v1/notebooks/ID/train" \
  -H "Authorization: Bearer $FOUNDRY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
POST/api/v1/notebooks/:id/run

Run cells. Body actions: { "action":"run_all" } | { "action":"run_cell","cellId":"…" } | { "action":"add_cell","kind":"code" }.

Scope: notebooks:run

GET/api/v1/notebooks/:id/status

Lightweight poll: status, running, failed, lastRunAt, Modal readiness.

Scope: notebooks:read

GET/api/v1/notebooks/:id/logs

Live events + cell outputs/errors. Optional ?since=ISO8601 to fetch only newer lines.

Scope: notebooks:read

Templates

Pass templateId on create:

  • llm-loraChat / instruction LoRA
  • whisperSpeech recognition
  • handwritingHandwriting / vision
  • videoShort video adapters
  • voiceVoice clone
  • roboticsImitation learning

Errors

{
  "error": "Invalid or missing API key",
  "code": "unauthorized"
}
  • 401 unauthorized — missing/invalid Bearer key
  • 403 forbidden — key lacks required scope
  • 404 — notebook not found for this account
  • 400 — validation / Modal not configured / run failure message in error

Dataset format

Prefer JSONL: one example per line. Short, clean pairs beat giant dumps.

{"messages":[
  {"role":"user","content":"Do you deliver Sundays?"},
  {"role":"assistant","content":"Yes — Nairobi only, 10am–4pm."}
]}
{"messages":[
  {"role":"user","content":"Shipping time to Mombasa?"},
  {"role":"assistant","content":"2–3 business days with standard courier."}
]}

After upload, open the notebook in the dashboard or keep driving it via MCP / the Agent API.

Credits

Notebooks are free. Creating notebooks, uploading datasets, running cells, and training on Modal do not debit your account credits. Credits may still apply to other Foundry products (for example hosted AIs). See Pricing and Billing.

Ready to connect an agent?

Create an API key, add the MCP connector URL from Settings, and let the agent create notebooks and upload datasets for you.