Skip to content

Data connections and CSV imports with MCP

11 min read · Updated 2 Nov 2026

Call astrato_data_create_connection with the connection name, driver, authentication profile and non-secret settings. If the user already supplied a username, include it as non-secret metadata; the secure form then asks only for the password or private key. Never put a password, PAT, access token, private key or service-account JSON in the tool call or conversation. If Nash recognises one in a chat message, it rejects the message before anything is stored, logged or sent to the model and asks the user to retry without the value. If older Nash history contains a value matched by an improved detector, Nash keeps the useful surrounding request but permanently replaces only that value with **[secret removed]** before displaying or reusing the message. If a credential has already been pasted into Claude or another MCP client, the server instructions tell that assistant to delete or forget the original value when its host supports removal. Otherwise it must disclose that removal cannot be guaranteed, disregard the value for later reasoning, never repeat it, and tell the user to rotate or revoke it. Detection is a safety net, not a reason to send credentials through chat. If credentials are required, the result includes a short-lived secure action with a complete Astrato URL for the signed-in person to open. The URL works directly from Claude and other MCP clients; inside Nash, the same action appears as a button that opens an Astrato modal without leaving the conversation. Astrato collects and encrypts those values in that browser page; they are not returned to the MCP client or added to chat history. Passwords, PATs and access tokens, private keys, and service-account documents are concealed by default. Each sensitive field has the same Show/Hide control so the person can visually verify it before submitting.

After the person finishes the form, call astrato_data_get_secure_action_status with its action id. A completed result contains only safe connection metadata. An expired or failed action must be started again. Authentication profile none completes immediately when the connector needs no secret input.

Clients using MCP 2026-07-28 can advertise URL elicitation in their per-request capabilities. Tools needing datasource authorization then return resultType: "input_required" with an elicitation/create URL request and opaque requestState. Open the Astrato URL with the person’s consent, then retry the original tool call with unchanged arguments, the exact requestState, and matching inputResponses. Acceptance means consent to the interaction; Astrato checks whether the browser action actually finished. A pending retry returns the same action instead of creating another connection. Declining or cancelling terminates a pending action. Clients without URL elicitation support continue to receive the secure-action URL and can use the status tool.

Secure actions use the same adapter across tools. Astrato checks the action’s owner and uses its stored URL, expiry and operation to determine the handoff and continuation behavior. Connection creation returns its completion receipt; confirmed authorization permits a read retry.

For OAuth connection creation, the secure form offers provider sign-in before validation. It is bound to the account selected during preparation. Astrato verifies matching authorization before saving; credentials and provider tokens are never returned through MCP.

Any MCP tool that requests remote data can encounter missing, expired or insufficient provider authorization. This includes connection tests and discovery, schema/table browsing, semantic-view imports, SQL and procedure execution, previews, exports, writeback, query preparation and execution, and join analysis. Astrato recognizes its structured DATASOURCE_AUTHORIZATION_REQUIRED response; ordinary permission denials and errors from a warehouse or exit node do not start this flow.

Astrato Auth checks the exact provider, account and required permissions when minting data access. It refreshes stored grants once before returning a public recovery descriptor on an authorization error. MCP consumes this descriptor without a separate identity or configuration preflight. A missing current grant can be repaired by an available sign-in flow. A federation without usable approval does not supply a sign-in flow by itself; Astrato also checks compatible OAuth connections. A usable federation can repair authorization without browser sign-in.

Contract 6.80.2 returns a tool error with code: "datasource_authorization_configuration_required" and status: 409 when no compatible option exists. No action is created. Ask a workspace administrator to configure a matching OAuth connection with the required permissions or repair federated authorization, then retry. Discovery failures remain upstream failures; retry instead of assuming configuration is absent. An older or malformed Auth authorization response without usable recovery metadata returns code: "datasource_authorization_discovery_failed" and status: 502. These are tool-result codes, separate from MCP HTTP status.

If configuration disappears after an action was offered, its browser page explains the missing configuration and blocks confirmation. You can still cancel a pending MCP interaction. Completing an action always checks current authorization; an earlier sign-in or elicitation acceptance is insufficient.

The returned browser action fixes the provider, account and required permissions. Complete sign-in and choose Confirm authorization. This action confirms authorization only; it does not create, validate or save a connection. Astrato checks current authorization independently of elicitation acceptance. When Astrato marks the operation replayable, a modern retry resumes a read after confirmation and refreshes cached data access. Otherwise, issue the read again manually. For a mutation, authorization completion does not replay the tool: earlier work may already have been applied. Re-read current state before issuing a fresh mutation request. Other clients, including Nash, receive the same secure-action URL and instructions for the next request.

Use the descriptor workflow to create or update a connection without putting credentials in chat or tool arguments. The existing astrato_data_create_connection tool also remains available for direct creation through its secure form.

  1. Call astrato_data_describe_connection_drivers. Use the returned field names, authentication methods, catalog labels and required context selectors. A field with sensitive: true belongs only in the secure browser form, including service-account JSON. Do not offer an authentication method listed in unavailableAuthMethods or a driver with unavailableReason.
  2. Call astrato_data_prepare_connection with non-secret settings. For an update, include the existing connectionId. Preparation checks metadata and returns preparationId, expectedRevision, and test.status: "needs-user-input"; it does not authenticate to the source. Supply required context such as the Snowflake warehouse in context, either here or in apply.
  3. Call astrato_data_apply_connection with operation: "create" or "update", the preparation ID and its exact revision. Creation also accepts a name and optional database/schema in source. The result is status: "needs_user_input" with a secureAction. Give the signed-in person secureAction.url; Nash can open the same form inside the product.
  4. After the person completes the form, call astrato_data_get_secure_action_status. The form validates the supplied credential and saves the bound connection. A completed result contains a safe receipt with the connection ID and revision. Never ask the person to relay the credential.
  5. Browse the saved connection using astrato_data_browse_connection_catalog, one database, schema, table or column level at a time. Tables report their object type, plus row count and comment when the source has them; columns report their data type. Each level returns up to 500 items: pass offset and limit, and follow pagination.nextOffset while hasMore is true. No semantic layer is needed. Use select-source to save a database/schema choice if needed.

The complete workflow requires both sl:read and workspace:write: list, descriptor and catalog tools require sl:read; preparation, apply and secure-action status require workspace:write. An existing external client with only sl:write must obtain a new authorization containing both scopes.

Preparations belong to their initiating user and tenant and expire fifteen minutes after creation; retries do not extend that time. Secure forms expire after five minutes. Validation failures before saving can be corrected and retried in the same form; completed or uncertain writes cannot be submitted again. If either expires, start again with non-secret metadata. Existing pending preparations from an older workflow cannot be resumed after an upgrade.

rename, select-source, retest and delete return a receipt directly. Pass the exact expectedRevision from the latest read. retest reports stored validity; it does not perform another authentication attempt. To test replacement credentials, use the secure update workflow. Revision checks detect a change that happened before the write; they do not lock out edits made through other Astrato clients while a request is running.

A completed create/update preparation cannot perform a different write. A concurrent attempt is refused; retry the same request to read its recorded outcome. If a write times out or its outcome cannot be established, inspect saved connections before starting another action: the write may already have succeeded. Do not automatically create a replacement connection.

OAuth setup and demo provisioning are unavailable in this workflow. See Data connections for the browser flow.

Use astrato_data_list_dynamic_connection_settings with a connectionId to read the users, non-secret settings, validity and mapping revision of an existing dynamic connection. Both dynamic-settings tools require workspace:write; Astrato also checks the connection permissions. Credentials and raw validation diagnostics are never returned.

Pass that exact revision as expectedRevision to astrato_data_apply_dynamic_connection_settings:

  • change: { operation: "upsert", users: [{ userId, settings }] } adds or edits those users and preserves users not named in the change. It returns a bound secure browser form for credentials. New users require a credential; leaving an existing user’s credential blank keeps it.
  • change: { operation: "delete", userIds: [userId] } removes only the named mappings. Confirm the intended removal with the person first: it can prevent those viewers from reading workbooks.

BigQuery settings use projectID. The dataset is shared: omit datasetID to inherit it; sending a different dataset is refused. ClickHouse settings use host, port and user. Both supported connectors use the same credential form and mutation checks. Adding a mapping does not grant resource access.

Poll astrato_data_get_secure_action_status after the form completes. If the revision changed, read the mappings again before planning another change. If an outcome is uncertain, inspect the saved mappings before doing anything else; never automatically repeat the write. The revision detects changes to visible settings and connection metadata, but cannot detect a credential-only change made elsewhere because credentials are not exposed.

Import a CSV file into a new table in a data connection, the same import the Astrato editor offers under Upload CSV. The connection must allow writes: Astrato creates a schema named Astrato in it, so a read-only connection is refused before any file is accepted.

The file’s bytes never have to pass through the conversation:

  1. Call astrato_data_prepare_import with the connection: its datasourceId, or a semanticLayerId to use that layer’s own connection. It returns an importId and an upload object with a short-lived url, valid for 15 minutes. Pass the file’s SHA-256 as sha256 when you can compute it: the URL then accepts only that file, so no one else who sees the URL can upload a different one first.
  2. Send the file to upload.url as the raw body of one HTTP PUT, for example from the assistant’s shell. The URL is the credential: send no authorization header, and do not use a multipart form.
  3. Call astrato_data_import_csv with the same connection and the importId. The upload can be imported once, only by the user who prepared it. A refused import — an unknown column type, an existing table name, a read-only connection — keeps the upload, so correct the call and import it again without re-sending the file. If the import was sent but no answer came back, the outcome is unknown: the upload is not reusable, and the table may exist, so check the source catalog before importing again.

A CSV attached in the Nash panel arrives the same way: the panel uploads it when the message is sent and opens the message with an Attached CSV file line carrying its importId, which Nash imports with astrato_data_import_csv. Such an upload keeps its file name and is bound to no connection until it is imported.

An assistant without a shell can pass a small file’s text to astrato_data_import_csv as content instead, up to 256 KB. Inline content is also the only path where the deployment cannot hold uploads; astrato_data_prepare_import then says so instead of returning an upload URL.

  • Limits. Up to 10 MB, 100,000 rows and 1,000 columns, as in the editor.
  • Columns. The delimiter, header row and column types are inferred the way the editor infers them. Set hasHeaders to false for a file without a header row, and columnTypes to override an inferred type by column name. Types are boolean, date, float, int, string, time and timestamp.
  • Table name. tableName defaults to fileName without .csv. An upload through astrato_data_prepare_import does not keep its local file name, so pass fileName (or tableName) to name the table after the file; with neither, it is upload. A Nash panel attachment keeps its name, so fileName is not needed for it. A name that already exists in the schema is refused; choose another.
  • Adding to a layer. With semanticLayerId, the table is also added to that layer as a view over all its columns, which needs sl:write as well as workspace:write. Pass addToLayer: false to import only.
  • Result. The table’s name, schema, database, row count and columns. Column names are the ones the table actually has, read back after the import: the importer can rename headers, for example Trade ID to trade_id, and a renamed column also carries its original header. If the table cannot be read back, columnNamesConfirmed is false and the names are the file’s headers. Use the returned names when adding the table to a semantic layer.