---
title: "MCP server"
description: "Connect Claude, ChatGPT or Cursor to IntoSQL over MCP. The hosted server converts files at public addresses; intosql mcp converts files on your computer."
canonical: https://intosql.com/docs/mcp
last_updated: 2026-10-15
---

# MCP server

IntoSQL has two MCP servers. Both let an AI assistant convert spreadsheets, CSV and JSON into SQL for PostgreSQL, MySQL, MariaDB, SQLite, SQL Server or Oracle, or into clean CSV or JSON.

|                   | Hosted server                                                                                               | Local server                                |
| ----------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------- |
| Address           | `https://intosql.com/mcp`                                                                                   | `intosql mcp`, over stdio                   |
| Where the file is | At a public HTTPS address                                                                                   | On your computer                            |
| Where it converts | On IntoSQL's servers                                                                                        | On your computer                            |
| Sign-in           | OAuth, or an API key                                                                                        | None                                        |
| Plan              | IntoSQL Pro                                                                                                 | Free, except loading into a database server |
| Tools             | `convert_file`, `get_conversion`, `list_conversions`, `cancel_conversion`, `delete_conversion`, `get_usage` | `inspect_file`, `convert_file`, `load_file` |

Use the hosted server when the assistant runs in the browser and the file is already online. Use the local server when the file is on your disk, or when it must not leave your computer.

## Hosted server

> **Pro:** The hosted server runs conversions on IntoSQL's servers, which is part of [IntoSQL Pro](/pricing). Without Pro, `convert_file` answers with "Remote conversions are part of IntoSQL Pro."

The server speaks MCP over streamable HTTP at:

```text
https://intosql.com/mcp
```

### Connect Claude

1. In Claude, open Settings, then Connectors.
2. Choose Add custom connector.
3. Paste `https://intosql.com/mcp` and add it.
4. Claude opens an IntoSQL page. Sign in and approve the access.

### Connect ChatGPT

1. In ChatGPT, open Settings, then Apps and connectors.
2. Choose Create.
3. Paste `https://intosql.com/mcp` and choose OAuth as the authentication.
4. Sign in to IntoSQL when asked and approve the access.

### Connect Cursor

Add the server to `mcp.json`:

```json
{
    "mcpServers": {
        "intosql": {
            "url": "https://intosql.com/mcp"
        }
    }
}
```

Cursor asks you to sign in to IntoSQL the first time it uses the server.

### Sign-in

The server accepts two kinds of credentials:

- **OAuth.** Claude, ChatGPT and Cursor use the authorization code flow. You sign in to IntoSQL in the browser and approve the client. The access token lasts one day and the client renews it with a refresh token, which lasts 90 days.
- **An API key.** A key from Settings, API keys works as a bearer token, for clients that send headers instead of signing in. See [API](/docs/api) for how to create one.

```json
{
    "mcpServers": {
        "intosql": {
            "url": "https://intosql.com/mcp",
            "headers": {
                "Authorization": "Bearer YOUR_API_KEY"
            }
        }
    }
}
```

Either way, the assistant sees the conversions of the account it signed in with, and nothing else. A suspended account is refused.

### How files reach the server

`convert_file` takes a public HTTPS address, such as a shared download link. IntoSQL's worker downloads the file from there. The hosted server doesn't accept uploads through MCP, and it can't read files on your computer. For those, use the [local server](#local-server).

The address must be HTTPS and reachable from the internet. Addresses on private networks or `localhost` are refused with "The file address must be HTTPS and reachable from the internet."

When the address doesn't end in a file name with an extension, pass `name` (for example `ventas.xlsx`) so the engine knows what it is reading.

### Tools

#### convert_file

Converts the file at a public HTTPS address. It waits up to 20 seconds for the result. If the conversion finishes in that time, the answer includes the download address. Otherwise it answers with the conversion's id and status, and the assistant calls `get_conversion` later.

| Input     | Required | Description                                                            |
| --------- | -------- | ---------------------------------------------------------------------- |
| `url`     | Yes      | A public HTTPS address of the file, up to 2048 characters.             |
| `dialect` | Yes      | `postgresql`, `mysql`, `mariadb`, `sqlite`, `sql_server` or `oracle`.  |
| `format`  | No       | `sql` (the default), `csv` or `json`.                                  |
| `table`   | No       | The table name. Made from the file name when absent.                   |
| `name`    | No       | The file name with its extension, when the address doesn't end in one. |

The conversion uses the defaults: the first visible sheet, the header row and delimiter detected, `CREATE TABLE` included, `snake_case` column names, `INSERT` statements of 500 rows, dates read in the order the file proves, and leading zeros kept.

#### get_conversion

Reads one conversion.

| Input | Required | Description                          |
| ----- | -------- | ------------------------------------ |
| `id`  | Yes      | The id `convert_file` answered with. |

A failed conversion carries `errorCode`, the same stable code as `error.code` in the API ([Errors](/docs/api/errors)), and `error`, the explanation.

#### list_conversions

Lists the account's latest 20 conversions, newest first, under `conversions`. It takes no inputs.

#### cancel_conversion

Stops a conversion that hasn't ended and deletes its files. It stays listed as `canceled` and doesn't count toward the month. A conversion that already ended can't be canceled.

| Input | Required | Description          |
| ----- | -------- | -------------------- |
| `id`  | Yes      | The conversion's id. |

#### delete_conversion

Deletes a conversion's input and output files now, instead of after 24 hours. It answers "Deleted."

| Input | Required | Description          |
| ----- | -------- | -------------------- |
| `id`  | Yes      | The conversion's id. |

The record stays, so the month's usage still counts it.

#### get_usage

Answers how many bytes of conversions the plan includes this month, how many are used and how many are left:

```json
{
    "limit": 5368709120,
    "used": 18874368,
    "left": 5349834752
}
```

### What a conversion looks like

`convert_file`, `get_conversion` and each item of `list_conversions` answer with the same fields:

```json
{
    "id": "01jf3k8v2m9q4r7t1x5y6z0abc",
    "name": "ventas.xlsx",
    "status": "done",
    "dialect": "postgresql",
    "bytes": 1843200,
    "rows": 12480,
    "outputBytes": 2310144,
    "error": null,
    "createdAt": "2026-10-16T14:02:11+00:00",
    "finishedAt": "2026-10-16T14:02:19+00:00",
    "expiresAt": "2026-10-17T14:02:11+00:00",
    "download_url": "https://..."
}
```

| Field                     | Description                                                                                                                                 |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                      | The conversion's id.                                                                                                                        |
| `name`                    | The file name, from the address or from `name`.                                                                                             |
| `status`                  | `queued`, `running`, `done` or `failed`.                                                                                                    |
| `dialect`                 | The database the SQL is for.                                                                                                                |
| `bytes`                   | The size of the downloaded file. `0` until the download finishes.                                                                           |
| `rows`                    | Rows converted, once done.                                                                                                                  |
| `outputBytes`             | The size of the output.                                                                                                                     |
| `error`                   | Why it failed, when `status` is `failed`.                                                                                                   |
| `createdAt`, `finishedAt` | When it started and ended.                                                                                                                  |
| `expiresAt`               | When its files are deleted.                                                                                                                 |
| `download_url`            | Where to download the output. Present only when `status` is `done`, and valid for ten minutes. Call `get_conversion` again for a fresh one. |

### Limits

| Limit                             | Value                                                                  |
| --------------------------------- | ---------------------------------------------------------------------- |
| Conversions per month             | 5 GB of input files with Pro. Failed conversions don't count.          |
| Largest file                      | 50 GB, or what is left of the month's allowance, whichever is smaller. |
| Queued or running at once         | 5 per account.                                                         |
| Download of the file              | Up to 1 hour.                                                          |
| One conversion, download included | Up to 3 hours.                                                         |
| Requests                          | 120 per minute per account (per key with an API key).                  |
| File retention                    | 24 hours, then the input and output are deleted.                       |

When a limit is reached, the tool answers with an error the assistant can read, for example "5 conversions are already queued or running on this account. Start this one when one of them ends."

### Server card

The server describes itself at a well-known address, for clients and registries that discover MCP servers:

```text
https://intosql.com/.well-known/mcp/server-card.json
```

```json
{
    "$schema": "https://static.modelcontextprotocol.io/schemas/v1/server-card.schema.json",
    "name": "com.intosql/mcp",
    "title": "IntoSQL",
    "description": "Converts spreadsheets, CSV and JSON into SQL a database accepts on the first try.",
    "version": "1.0.0",
    "websiteUrl": "https://intosql.com/developers",
    "icons": [
        {
            "src": "https://intosql.com/icon-512.png",
            "mimeType": "image/png",
            "sizes": ["512x512"]
        }
    ],
    "remotes": [{ "type": "streamable-http", "url": "https://intosql.com/mcp" }]
}
```

The same card is also served at `https://intosql.com/mcp/server-card`.

## Local server

`intosql mcp` runs the IntoSQL engine as an MCP server over stdio. The assistant starts it, and it reads and writes files on your computer. Files are never uploaded: conversions are written to your disk, and loads go only to the database you name.

It comes with the [command line](/docs/cli). Install it first and check that it runs:

```shell
intosql version
```

You don't start the server yourself. The MCP client runs `intosql mcp` and talks to it. Run in a terminal on its own, it waits for a client on standard input.

### Connect Claude Desktop

Add the server to `claude_desktop_config.json`. On macOS the file is in `~/Library/Application Support/Claude/`; on Windows, in `%APPDATA%\Claude\`.

```json
{
    "mcpServers": {
        "intosql": {
            "command": "intosql",
            "args": ["mcp"]
        }
    }
}
```

Restart Claude Desktop. If it can't find `intosql`, use the full path that `which intosql` prints, such as `/opt/homebrew/bin/intosql`.

### Connect Cursor

Add the server to `mcp.json`, either `~/.cursor/mcp.json` for every project or `.cursor/mcp.json` in one project:

```json
{
    "mcpServers": {
        "intosql": {
            "command": "intosql",
            "args": ["mcp"]
        }
    }
}
```

### Local tools

Paths are absolute, or relative to the folder the server runs in. Every tool also takes the reading options in [Reading options](#reading-options).

#### inspect_file

Reads a file without converting it. Answers with its format and encoding, where the table is, each column's name and SQL type for the database, every correction the conversion would make, and a preview.

| Input          | Required | Description                                                                 |
| -------------- | -------- | --------------------------------------------------------------------------- |
| `path`         | Yes      | The spreadsheet, CSV, TSV, JSON or NDJSON file, or a MySQL or MariaDB dump. |
| `dialect`      | No       | The database the names and types are for. `postgresql` when absent.         |
| `preview_rows` | No       | Rows to preview. 10 when absent.                                            |

#### convert_file

Converts a file and writes the output to disk. Answers with `output_path`, `output_bytes` and `report`: rows converted and left out, column types, and every correction.

| Input          | Required | Description                                                                                                                                                                       |
| -------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `path`         | Yes      | The file to convert.                                                                                                                                                              |
| `output_path`  | No       | Where to write the output. Next to the file when absent: `ventas.csv` becomes `ventas.postgresql.sql`, `ventas.clean.csv` or `ventas.json`. It can't be the file being converted. |
| `dialect`      | No       | `postgresql` (when absent), `mysql`, `mariadb`, `sqlite`, `sql_server` or `oracle`.                                                                                               |
| `format`       | No       | `sql` (when absent), `csv` or `json`.                                                                                                                                             |
| `table`        | No       | The table name. Made from the file name when absent.                                                                                                                              |
| `schema`       | No       | The schema the table goes in.                                                                                                                                                     |
| `create_table` | No       | Write `CREATE TABLE`. `true` when absent.                                                                                                                                         |
| `copy`         | No       | Write PostgreSQL `COPY ... FROM stdin` instead of `INSERT`. The script then runs only in psql.                                                                                    |
| `batch_rows`   | No       | Rows per `INSERT`. 500 when absent.                                                                                                                                               |

#### load_file

Loads a file straight into a database: PostgreSQL with parallel `COPY`, MySQL, MariaDB or SQLite. It creates the table with the inferred types unless told the table exists, loads every row and answers with `report`. A failed load drops the table it created.

| Input          | Required | Description                                                                                                                  |
| -------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `path`         | Yes      | The file to load.                                                                                                            |
| `into`         | Yes      | A `postgres://`, `postgresql://`, `mysql://` or `mariadb://` URL, or a SQLite file ending in `.db`, `.sqlite` or `.sqlite3`. |
| `table`        | No       | The table name. Made from the file name when absent.                                                                         |
| `schema`       | No       | The schema the table goes in.                                                                                                |
| `create_table` | No       | Create the table. `true` when absent.                                                                                        |
| `connections`  | No       | PostgreSQL connections loading at once. 4 when absent.                                                                       |
| `unlogged`     | No       | Create the PostgreSQL table `UNLOGGED`: faster, but emptied after a crash.                                                   |
| `indexes`      | No       | Columns to index after the rows are in.                                                                                      |
| `batch_rows`   | No       | Rows per `INSERT` in MySQL and MariaDB. 500 when absent.                                                                     |

> **Pro:** Loading into SQLite is free. Loading into PostgreSQL, MySQL or MariaDB needs IntoSQL Pro. Without a license, the first load starts a 14-day trial on this computer, and the answer carries a `notice` with the days left. Activate a license with `intosql license activate <license>`; see [Command line](/docs/cli).

The connection URL, password included, is passed to the tool by the assistant. Keep that in mind before you paste a production password into a chat.

### Reading options

All three local tools take these optional inputs:

| Input          | Description                                                                                                                                                 |
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `sheet`        | The sheet to read. The first visible one when absent.                                                                                                       |
| `header_row`   | The 1-based row holding the column names. Detected when absent.                                                                                             |
| `delimiter`    | The delimiter of a text file: `,`, `;`, `\|` or `tab`. Detected when absent.                                                                                |
| `encoding`     | The encoding of a text file, such as `windows-1252`. Detected when absent.                                                                                  |
| `locale`       | A BCP 47 tag such as `es-MX`. Decides ambiguous dates and decimal separators.                                                                               |
| `keep_headers` | Keep column names as the headers write them, quoted, instead of `snake_case`.                                                                               |
| `columns`      | Changes to single columns, each found by its 0-based `index`: a new `name`, `as_text` to keep every value as written, or `exclude` to leave the column out. |

For example, to rename the third column and keep the first as text:

```json
{
    "path": "/Users/ana/Downloads/clientes_2024.xlsx",
    "dialect": "mysql",
    "columns": [
        { "index": 2, "name": "signup_date" },
        { "index": 0, "as_text": true }
    ]
}
```

## Example prompts

**Hosted server**

- "Convert https://example.com/exports/ventas.csv to PostgreSQL." The assistant calls `convert_file` with the address and `dialect: postgresql`, then gives you the download address, or calls `get_conversion` until the conversion is done.
- "What did I convert this week, and how much of my allowance is left?" The assistant calls `list_conversions` and `get_usage`.
- "Stop the ventas conversion, I sent the wrong file." The assistant calls `cancel_conversion`.
- "Delete the ventas conversion now." The assistant finds its id with `list_conversions` and calls `delete_conversion`.

**Local server**

- "Look at ~/Downloads/clientes_2024.xlsx and tell me what IntoSQL would change." The assistant calls `inspect_file` and summarizes the column types and corrections.
- "Convert pedidos.json to a SQL Server script with the table name pedidos." The assistant calls `convert_file` with `dialect: sql_server` and `table: pedidos`, and tells you where `pedidos.sql_server.sql` was written and how many rows went in.
- "Load ventas.xlsx into postgres://ana@localhost:5432/tienda as ventas_2024." The assistant calls `load_file` and reports the rows loaded.

## Troubleshooting

**"Remote conversions are part of IntoSQL Pro."** The hosted server needs an active Pro plan on the account the assistant signed in with. See [Pricing](/pricing).

**"The file address must be HTTPS and reachable from the internet."** The address is `http://`, points to a private network, or can't be resolved. Share the file with a public HTTPS link, or use the local server.

**"The file couldn't be downloaded: ..."** IntoSQL's worker couldn't fetch the file. Some sharing links open a web page instead of the file; use the direct download link.

**"This month's remote conversions are used up."** The month's allowance is spent. `get_usage` shows the numbers. The local server has no allowance.

**The download address stopped working.** It lasts ten minutes. Ask the assistant to call `get_conversion` again for a new one. After 24 hours the files are gone; convert the file again.

**Claude Desktop doesn't show the local tools.** Check that `claude_desktop_config.json` is valid JSON, use the full path to `intosql`, and restart Claude Desktop.

**"The MCP server stopped."** `intosql mcp` exits when its client closes the connection. It isn't meant to run on its own in a terminal.
