Connect a source via the Source Picker
The MapCraft walkthrough assumed your project already had a source schema attached (from StructScan). This tutorial covers the other way to put a source onto a MapCraft project: the Source Picker — a tabbed dialog that ingests from a file, a sample blob, an OpenAPI URL, a live database, a SaaS app, a webhook capture, or a PDF / HTML document.
Every tab ends the same way: a Schema is materialized under the SOURCE
role on your project, stamped with a source_origin so the rest of MapCraft
(provenance chip on the Schema panel, the compiler, and FlowBridge) knows
where it came from.
By the end of this page you will have:
- Opened the Source Picker for an existing project.
- Materialized a source schema via at least one connector (File or Paste Sample is the fastest first run).
- Seen the
source_originprovenance chip on the Schema panel. - Learned where to go next for each of the other six connector types.
- An open MapCraft project at
/mapcraft/{projectId}. (If you don't have one yet, follow the MapCraft walkthrough first.) - One of the following on hand: a JSON/CSV/XML/XSD file, a paste-able JSON or CSV sample, an OpenAPI URL, a read-only DB DSN, OAuth access to a SaaS tenant, or a PDF / HTML document.
Step 1 — Open the Source Picker
From the project page, click Add Source Schema in the toolbar (or Replace Source Schema if a source is already attached). The Source Picker dialog opens with seven tabs across the top:
| Tab | Use when… |
|---|---|
| File | You already have a JSON / XML / XSD / CSV file (≤ 100 MB). |
| URL / OpenAPI | You have a Swagger 2 / OpenAPI 3.0 / 3.1 spec (JSON or YAML). |
| Paste Sample | You only have raw payloads (JSON or CSV) — no schema doc. |
| Database | You want to introspect a live Postgres / MySQL / SQL Server / Snowflake / BigQuery / Databricks table. |
| SaaS | You want to pull objects from Salesforce or HubSpot via OAuth. |
| Webhook | You want to capture live events from a producer (Stripe, GitHub, Shopify…) and infer a schema from them. |
| PDF / HTML | You have a document (spec PDF, vendor portal page) and want MapCraft to extract a field list — including via vision fallback for scanned PDFs. |
The dialog defaults to the File tab every time it opens.
Step 2 — Run the golden path (File or Paste Sample)
Pick whichever you have on hand. Both finish in under a minute.
- File
- Paste Sample
- Drag-and-drop a file (or click to choose). Supported: JSON, XML, XSD, CSV, max 100 MB.
- The picker validates the file client-side and shows a parsed-field preview.
- Click Upload. The file is sent to the backend, parsed by the matching
StructScanparser, and persisted as aSchemawith roleSOURCE.
After upload, the dialog closes and the project's Source panel populates.
The source_origin chip on the Schema panel header shows the file type
(e.g. json, xml).
- Switch to the Paste Sample tab.
- Pick a format hint: Auto-detect, JSON, or CSV. Auto is fine for most cases — the picker sniffs the first sample.
- Paste one or more sample blobs in the Sample 1, Sample 2, … boxes. Use Add another sample for variants — the inference unions their shapes and observed types.
- Click Infer schema. The picker calls the backend, which runs the deterministic shape-union pass and (when available) layers LLM enrichment on top — enum closure, format hints, one-line descriptions.
- Review the field table. Each row shows:
- The JSON path (e.g.
customer.email). - Observed types (
string,integer, …). - A purple AI chip if LLM enrichment merged a proposal for that field.
- A green check or amber warning from the verifier (mismatch between LLM proposal and observed evidence).
- The JSON path (e.g.
- Set Schema name (defaults to
Inferred schema) and click Use this schema.
The materialized schema lands on the project with source_origin.kind = "paste-sample"
and llm_enriched: true | false recorded for audit.
The purple AI-enriched banner only appears when the LLM proposed and the verifier accepted at least one enum, format, or description. Rejected proposals don't change the schema and don't trigger the banner. Hover any field's AI chip to see the rationale.
Step 3 — Pick a connector for "real" sources
The File and Paste Sample paths are great for prototypes. For production work you usually want a connector that talks to the real system. The next five sections each walk through one connector. Skim straight to the one you need — they're independent.
3a. URL / OpenAPI
- Switch to the URL / OpenAPI tab.
- Paste a spec URL — Swagger 2.0, OpenAPI 3.0, or 3.1; JSON or YAML.
- (Optional) Add auth headers as chips, e.g.
Authorization: Bearer …. - Click Fetch. The picker downloads, parses, and resolves
$refchains acrosscomponents.schemasand inline path schemas. - Pick the component or operation you want from the searchable list and click Use this schema.
Private/loopback URLs are blocked by default by an SSRF guard. To allow
them in self-hosted dev environments only, set
MAPCRAFT_ALLOW_PRIVATE_URLS=true on the backend. Never enable this in
shared environments.
3b. Database
The Database tab is a three-stage flow: Connect → Browse → Materialize.
Connect.
- Pick a Dialect tile: Postgres, MySQL, SQL Server, Snowflake, BigQuery, or Databricks.
- Paste a DSN. The placeholder shows the expected format per dialect, e.g.:
postgresql://reader:[email protected]:5432/salessnowflake://user:[email protected]/sales?warehouse=COMPUTE_WH&role=READERbigquery://my-project?dataset=analytics&location=US
- Give the connection a Save as (label) — e.g.
prod-postgres. - Click Test connection. On success you'll see
Connected · <dialect_version>. If the dialect supports it, the picker also confirmsREAD ONLYenforcement; if not, you'll see an amber "READ ONLY pragma not confirmed — defense-in-depth disabled" warning. - Click Save & use. The credentials are encrypted (column-level Fernet via the credential vault) and the connection chip appears under Saved connections for next time.
Browse. The picker lists schemas — it auto-picks the first non
information_schema one. Use the Filter tables… box, then click a
row. Tables show column count and (where the dialect can answer cheaply)
a row estimate.
Materialize. Edit the Schema name (defaults to schema.table) and
click Use this table. The picker calls the backend, which introspects
columns, primary keys, and foreign keys, and writes a Schema with
source_origin.kind = "db".
Every query the introspection runs is wrapped in a read-only session and capped at a 10-second statement timeout. The DSN you paste is not echoed back after Save — subsequent calls use the connection ID.
3c. SaaS (Salesforce + HubSpot)
- Switch to the SaaS tab.
- Pick Salesforce or HubSpot.
- Choose OAuth (preferred — pops the provider's consent flow) or Manual token for offline / CI use.
- After auth, the picker shows an object grid with chips marking
customobjects and (for Salesforce)queryableones. - Click an object → click Use this object.
Field-prefix clusters (Billing*, Shipping*, Mailing* on Salesforce
addresses) are auto-grouped in the materialized schema so the canvas
stays readable.
3d. Webhook
- Switch to the Webhook tab.
- Click Mint URL. A single-use receiver URL (
/hooks/{token}) is minted and copied to your clipboard. - Point your producer at the URL and trigger a few events. The picker
polls every ~2 seconds and shows captured events as they arrive,
tagged with known-source header hints (
x-github-event,x-stripe-event,x-shopify-topic). - When you have enough samples, click Finalize. The captured events funnel through the same inference engine as the Paste Sample tab, so you get LLM enrichment "for free".
The minted URL is single-use — after Finalize it stops accepting events. Re-open the tab to mint a new one.
3e. PDF / HTML
- Switch to the PDF / HTML tab.
- Drag-drop a file (PDF or HTML) or paste a public URL.
- (Optional) Override the document type if auto-detection guesses wrong.
- Click Extract. Text-mode (
pypdffor PDFs,lxml.htmlfor HTML) runs first. If text extraction returns empty — typically a scanned PDF — the picker automatically falls back to vision mode via Anthropic's multimodal endpoint. - Review the extracted field list with per-field rationale. An amber Vision chip appears on the result header when vision mode fired.
- Set the schema name and click Use this schema.
Step 4 — Confirm provenance landed
Whichever connector you used, MapCraft stamped the new schema with a
source_origin discriminator and re-rendered the Schema panel.
In the project, look at the source side. The panel header now shows a
source-type chip — file (with file-type suffix), openapi, paste-sample,
db (with dialect), salesforce / hubspot, webhook, or pdf (with a
Vision modifier if vision mode fired). Hover the chip for the full
provenance tooltip.
Verify
Your source connection worked end-to-end if all of the following are true.
| Check | Where to look |
|---|---|
| The Source Picker closed itself after Use this schema/table/object | Dialog dismisses; project page refreshes. |
| The Schema panel populated with fields | Left side of the canvas / table view shows source fields, not "No source schema attached". |
A source_origin chip is rendered on the Schema panel | Tooltip shows the connector key (db, paste-sample, …) plus its specifics (dialect, table, sample count). |
| For Database: the saved connection chip is listed at the top of the Database tab next time you open the picker | Re-open Source Picker → Database tab → chip with your label is selectable. |
| For Paste Sample / Webhook: when LLM enrichment fired, the AI-enriched banner is present in the preview | Visible before you click Use this schema; recorded as llm_enriched: true on the resulting schema. |
If any of these are missing, see Troubleshooting below.
Troubleshooting
"Failed: SSRF — private address blocked" (URL / OpenAPI).
The URL resolves to a private, loopback, or link-local address. This is
intentional. Either expose the spec on a public URL or — for self-hosted
dev only — set MAPCRAFT_ALLOW_PRIVATE_URLS=true on the backend.
"READ ONLY pragma not confirmed" (Database).
Your dialect doesn't surface a session-level READ ONLY flag the picker
can read back. The 10-second statement timeout is still in force, but
defense-in-depth is one layer thinner. Prefer a database role that's
read-only at the grant level.
Inference returned 0 fields (Paste Sample). The samples couldn't be parsed under the selected format hint. Switch Format from Auto-detect to JSON or CSV to force the parser, or paste a smaller, well-formed sample.
Webhook capture page is stuck on "Waiting for events".
The minted URL accepts only the first N events and is single-use. Confirm
your producer is hitting /hooks/{token} exactly (no trailing slash
issues) and that the token hasn't been finalized yet. If in doubt,
Mint URL again.
PDF extraction returns a Vision chip but missing fields (PDF / HTML). Vision mode is best-effort for scanned PDFs. Try splitting the PDF to one section per page, or run Extract on the highest-resolution version of the file.
What's next
- MapCraft walkthrough — auto-map, lookups, rules, versioning, and DAG compile, starting from the source you just connected.
- FlowBridge walkthrough — run the compiled DAG against the live source connector.
- StructScan overview — when you want StructScan to profile a file before it becomes a MapCraft source.