# import_source

> Page: https://docs.plotwork.dev/mcp/tools/import-source. Index of every page: https://docs.plotwork.dev/llms.txt

Turns a file into a finished diagram in one call: a database schema, an API spec, infrastructure as code, manifests, a software catalog, a CI workflow, CSV or JSON data, a folder listing, or a git log. It is a workflow of the MCP server and the HTTP API, with the title "Import source".

## TL;DR

| Question | Answer |
|---|---|
| What is it? | A workflow: one call does the work of several tools and returns one combined answer. |
| What does it do? | Turns a file into a finished diagram in one call: a database schema, an API spec, infrastructure as code, manifests, a software catalog, a CI workflow, CSV or JSON data, a folder listing, or a git log. |
| What does it replace? | validate_diagram and outline_diagram. |
| How do I call it over HTTP? | [`POST /v1/import`](https://docs.plotwork.dev/api/post-v1-import.md) |
| Does it change anything? | No. It is read-only and idempotent, and it talks to nothing outside itself. It saves no file and returns its answer as data. |
| Which bounds apply? | `maxImportLength`, `maxImportLocalLength`, `maxImportTextLength`, `maxImportFiles`, `maxImportLocalFiles`, `maxImportParts`, `maxImportNodes`, `maxImportTables`, `maxImportRows`, `maxImportColumns`, `maxImportPoints`, `maxImportSeries`, `maxImportEntries`, `maxImportCommits`, `maxImportMessages`. See the bounds below. |
| Where do I read its schema as data? | An MCP client gets the name, description, and JSON Schema of every tool from `tools/list`. |

## What it does

Workflow. Turns a file into a finished diagram in one call: a database schema, an API spec, infrastructure as code, manifests, a software catalog, a CI workflow, CSV or JSON data, a folder listing, or a git log. get_diagram_syntax with topic import-formats says what each format reads, draws, and takes. Prefer it to drawing by hand whenever the person has such a file: send its text, never a path, or every file of a folder in files. Returns the source, diagnostics pointing into the file for anything left out, coverage, parts (every diagram of a split file), the validation, an outline, viewUrl, and saveCommand. It runs no code and reads no file or URL. Replaces validate_diagram and outline_diagram.

## Steps

| Operation | Runs | What it does |
|---|---|---|
| `importSource` | always | Read a file of another format (SQL, Prisma, Drizzle, OpenAPI, Terraform, a Terraform plan or state, Bicep, ARM, Pulumi, CloudFormation, CDK, Compose, Kubernetes, Helm, Kustomize, Backstage, Structurizr, AsyncAPI, GitHub Actions, GitLab CI/CD, Azure Pipelines, CSV, JSON, a tree, or a git log) into Plotwork source. |
| `validate` | only when needed | Parse the source and lint it: every error, and the quality, icon, and group-type warnings. |
| `outline` | only when needed | Describe a valid diagram as plain text. |

One call performs at most 26 operations.

## Example call

The arguments of the call, as JSON:

```json
{
  "format": "compose",
  "text": "services:\n  api:\n    build: ./api\n    ports: [\"8080:8080\"]\n    depends_on: [db, cache]\n  db:\n    image: postgres:16\n  cache:\n    image: redis:7\n"
}
```

The `text` argument, written out one line at a time:

```text
services:
  api:
    build: ./api
    ports: ["8080:8080"]
    depends_on: [db, cache]
  db:
    image: postgres:16
  cache:
    image: redis:7
```

## Prompts that lead to it

- Draw our database schema from this SQL.
- Make a diagram of this docker-compose file.
- Which roles can call which endpoints in this OpenAPI spec?
- Chart this CSV.

## Arguments

| Field | Type | Required | Description |
|---|---|---|---|
| `format` | `"sql" \| "prisma" \| "drizzle" \| "openapi" \| "terraform" \| "terraform-plan" \| "bicep" \| "arm" \| "pulumi" \| "cloudformation" \| "cdk" \| "compose" \| "kubernetes" \| "helm" \| "kustomize" \| "backstage" \| "structurizr" \| "asyncapi" \| "github-actions" \| "gitlab-ci" \| "azure-pipelines" \| "csv" \| "json" \| "tree" \| "git-log"` | yes | What the text is; get_diagram_syntax with topic import-formats describes each. |
| `text` | `string` | no | The file content, as text. Send text or files, not both. |
| `files` | `object[]` | no | The files of a folder, for a format that spans files; the others read the first. |
| `files[].path` | `string` | yes | The file path, such as infra/network.tf; diagnostics name it. at least 1 character; at most 300 characters. |
| `files[].text` | `string` | yes | The file content, as text. |
| `title` | `string` | no | The diagram title; taken from the file when left out. at most 200 characters. |
| `partsPage` | `integer` | no | Which page of parts to return when a split import has more than 24 diagrams: 1 (default) is the first 24. minimum 1; maximum 100000. |
| `options` | `object` | no | default {}. |
| `options.view` | `"endpoints" \| "map" \| "sequence" \| "git" \| "timeline" \| "context" \| "container" \| "component"` | no | The picture of a format drawn several ways. |
| `options.operationId` | `string` | no | openapi sequence: the operation. at most 200 characters. |
| `options.chart` | `"auto" \| "xychart" \| "pie" \| "sankey" \| "treemap" \| "matrix"` | no | csv, json: the chart; auto picks. |
| `options.tables` | `string[]` | no | Tables to draw, by name or prefix*. |
| `options.paths` | `string[]` | no | openapi: path prefixes to read. |
| `options.tags` | `string[]` | no | openapi: tags to read. |
| `options.varFiles` | `string[]` | no | Variables files to apply. |
| `options.groupBy` | `"module" \| "network" \| "file" \| "owner"` | no | How things are framed; module is the default. |
| `options.root` | `string` | no | The root, stack, or template of several to draw. at most 300 characters. |

## Result

| Field | Type | Required | Description |
|---|---|---|---|
| `ok` | `boolean` | yes | True when `source` is valid Plotwork source. False means nothing was imported and `source` is empty: read `diagnostics`. |
| `kind` | `string \| null` | yes | The kind of diagram the file became, or null when nothing was imported. |
| `format` | `string` | yes | The format the text was read as. |
| `source` | `string` | yes | The Plotwork source, or an empty string when nothing could be imported. |
| `diagnostics` | `Diagnostic[]` | yes | Everything left out, changed, or wrong, with a hint. Codes start with I and point into the text you sent: I1xx errors stopped the import, I2xx warnings did not. |
| `diagnostics[].code` | `"E100" \| "E101" \| "E110" \| "E111" \| "E120" \| "E121" \| "E122" \| "E123" \| "E124" \| "E125" \| "E130" \| "E131" \| "E132" \| "E133" \| "E134" \| "E135" \| "E136" \| "E137" \| "E138" \| "E139" \| "E140" \| "W200" \| "W201" \| "W202" \| "W203" \| "W204" \| "W205" \| "W206" \| "W207" \| "W500" \| "M100" \| "M101" \| "M102" \| "M103" \| "M104" \| "M110" \| "M200" \| "M201" \| "M202" \| "M203" \| "M204" \| "M205" \| "M206" \| "M207" \| "M208" \| "M209" \| "M210" \| "M211" \| "M212" \| "M213" \| "M214" \| "M215" \| "M216" \| "M217" \| "M218" \| "E300" \| "E301" \| "E302" \| "E303" \| "E304" \| "W300" \| "W301" \| "W302" \| "W303" \| "M120" \| "M220" \| "M221" \| "M222" \| "E340" \| "E341" \| "E342" \| "E343" \| "E344" \| "E345" \| "W320" \| "W321" \| "W322" \| "W323" \| "M240" \| "M241" \| "M242" \| "E360" \| "E361" \| "E362" \| "E363" \| "E364" \| "E365" \| "E366" \| "E367" \| "W330" \| "W331" \| "W332" \| "W333" \| "W334" \| "M250" \| "M251" \| "E400" \| "E401" \| "E402" \| "E403" \| "W350" \| "W351" \| "W352" \| "W353" \| "M270" \| "M271" \| "E420" \| "E421" \| "E422" \| "E423" \| "E424" \| "W360" \| "W361" \| "W362" \| "W363" \| "W364" \| "M180" \| "M280" \| "M281" \| "M282" \| "E320" \| "E321" \| "E322" \| "E323" \| "E324" \| "E325" \| "E326" \| "E327" \| "E328" \| "E329" \| "E330" \| "W310" \| "W311" \| "W312" \| "W313" \| "W314" \| "M130" \| "M131" \| "M132" \| "M230" \| "M231" \| "M232" \| "M233" \| "M234" \| "M235" \| "M236" \| "M237" \| "M238" \| "E380" \| "E381" \| "E382" \| "E383" \| "W340" \| "W341" \| "W342" \| "W343" \| "M260" \| "I100" \| "I101" \| "I102" \| "I103" \| "I104" \| "I105" \| "I200" \| "I201" \| "I202" \| "I203" \| "I204" \| "I206" \| "R100" \| "R101" \| "R200" \| "R201" \| "R202" \| "R203" \| "R204" \| "R205" \| "R206" \| "R207" \| "S100" \| "S200" \| "S101" \| "S102" \| "S103" \| "S104" \| "S201" \| "S202" \| "S203"` | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
| `diagnostics[].severity` | `"error" \| "warning"` | yes | Errors stop rendering; warnings never do. |
| `diagnostics[].message` | `string` | yes | What is wrong, in one sentence. |
| `diagnostics[].line` | `integer` | yes | 1-based line in the submitted source. minimum 1. |
| `diagnostics[].column` | `integer` | yes | 1-based column in that line. minimum 1. |
| `diagnostics[].length` | `integer` | yes | Number of characters the problem covers. minimum 1. |
| `diagnostics[].hint` | `string \| null` | yes | A concrete suggestion for fixing it, or null. |
| `stats` | `object` | yes |  |
| `stats.items` | `integer` | yes | Boxes, tables, rows, slices, places, entries, or commits written. |
| `stats.links` | `integer` | yes | Arrows, relations, messages, flows, or merges written. |
| `stats.groups` | `integer` | yes | Frames, sections, or folders written. |
| `stats.dropped` | `integer` | yes | Things in the file left out by a cap or because the picture has no place for them; each is in diagnostics. |
| `coverage` | `object \| null` | yes | How much of the file the picture shows; null when nothing was imported. When complete is false, the picture is not the whole file: say so. |
| `validation` | `object \| null` | yes | The Plotwork validator run on `source`; null when nothing was imported. |
| `parts` | `object[]` | yes | When the file is too big for one readable picture, the diagrams it was split into, in order, at most 24 a page; `source` is the first diagram of all. Show or draw each of them. Empty when the import is one diagram. |
| `parts[].title` | `string` | yes | What this diagram shows, such as one resource group or one tag of an API. |
| `parts[].kind` | `string` | yes | The kind of diagram. |
| `parts[].source` | `string` | yes | The Plotwork source of this diagram; draw it with draw_diagram. |
| `parts[].items` | `integer` | yes | The boxes, rows, or entries it draws. |
| `parts[].valid` | `boolean` | yes | True when the source has no Plotwork errors. |
| `parts[].warnings` | `Diagnostic[]` | yes | Plotwork quality warnings of this diagram. Lines and columns point into its source. |
| `parts[].warnings[].code` | `"E100" \| "E101" \| "E110" \| "E111" \| "E120" \| "E121" \| "E122" \| "E123" \| "E124" \| "E125" \| "E130" \| "E131" \| "E132" \| "E133" \| "E134" \| "E135" \| "E136" \| "E137" \| "E138" \| "E139" \| "E140" \| "W200" \| "W201" \| "W202" \| "W203" \| "W204" \| "W205" \| "W206" \| "W207" \| "W500" \| "M100" \| "M101" \| "M102" \| "M103" \| "M104" \| "M110" \| "M200" \| "M201" \| "M202" \| "M203" \| "M204" \| "M205" \| "M206" \| "M207" \| "M208" \| "M209" \| "M210" \| "M211" \| "M212" \| "M213" \| "M214" \| "M215" \| "M216" \| "M217" \| "M218" \| "E300" \| "E301" \| "E302" \| "E303" \| "E304" \| "W300" \| "W301" \| "W302" \| "W303" \| "M120" \| "M220" \| "M221" \| "M222" \| "E340" \| "E341" \| "E342" \| "E343" \| "E344" \| "E345" \| "W320" \| "W321" \| "W322" \| "W323" \| "M240" \| "M241" \| "M242" \| "E360" \| "E361" \| "E362" \| "E363" \| "E364" \| "E365" \| "E366" \| "E367" \| "W330" \| "W331" \| "W332" \| "W333" \| "W334" \| "M250" \| "M251" \| "E400" \| "E401" \| "E402" \| "E403" \| "W350" \| "W351" \| "W352" \| "W353" \| "M270" \| "M271" \| "E420" \| "E421" \| "E422" \| "E423" \| "E424" \| "W360" \| "W361" \| "W362" \| "W363" \| "W364" \| "M180" \| "M280" \| "M281" \| "M282" \| "E320" \| "E321" \| "E322" \| "E323" \| "E324" \| "E325" \| "E326" \| "E327" \| "E328" \| "E329" \| "E330" \| "W310" \| "W311" \| "W312" \| "W313" \| "W314" \| "M130" \| "M131" \| "M132" \| "M230" \| "M231" \| "M232" \| "M233" \| "M234" \| "M235" \| "M236" \| "M237" \| "M238" \| "E380" \| "E381" \| "E382" \| "E383" \| "W340" \| "W341" \| "W342" \| "W343" \| "M260" \| "I100" \| "I101" \| "I102" \| "I103" \| "I104" \| "I105" \| "I200" \| "I201" \| "I202" \| "I203" \| "I204" \| "I206" \| "R100" \| "R101" \| "R200" \| "R201" \| "R202" \| "R203" \| "R204" \| "R205" \| "R206" \| "R207" \| "S100" \| "S200" \| "S101" \| "S102" \| "S103" \| "S104" \| "S201" \| "S202" \| "S203"` | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
| `parts[].warnings[].severity` | `"error" \| "warning"` | yes | Errors stop rendering; warnings never do. |
| `parts[].warnings[].message` | `string` | yes | What is wrong, in one sentence. |
| `parts[].warnings[].line` | `integer` | yes | 1-based line in the submitted source. minimum 1. |
| `parts[].warnings[].column` | `integer` | yes | 1-based column in that line. minimum 1. |
| `parts[].warnings[].length` | `integer` | yes | Number of characters the problem covers. minimum 1. |
| `parts[].warnings[].hint` | `string \| null` | yes | A concrete suggestion for fixing it, or null. |
| `partsTotal` | `integer` | yes | How many diagrams the import was split into in all; 0 when it is one diagram. |
| `partsPage` | `integer` | yes | The page of parts this answer holds, from 1. |
| `partsPages` | `integer` | yes | How many pages of parts there are; call again with partsPage for the next one. |
| `outline` | `string[]` | yes | The diagram as plain text, to check it says what the file says; empty when nothing was imported. |
| `outlineTruncated` | `boolean` | yes | True when the outline was cut short at its summary length. |
| `viewUrl` | `string` | no | A link that shows a valid diagram in a browser; give it to the person who wants to look. The source is in the part after #, never sent to a server, but anyone with the link can read it. Absent when too long; next says so. |
| `pngUrl` | `string` | no | The viewUrl with &download=png: opening it in a browser saves the diagram as a PNG for Slack, email, or a wiki. The PNG is drawn in the person's browser, not on a server, so it is a link to open, not an image address to embed. Absent when too long. |
| `svgUrl` | `string` | no | The viewUrl with &download=svg: a person opens it to download the SVG. Not a file address for curl; use saveCommand. Absent when too long. |
| `saveCommand` | `string` | no | Run in a shell to save the SVG into the repository: the CLI decodes the link locally, fetches nothing, and embeds the source. Set --out to the path; add --theme dark for dark. Absent when too long. |
| `next` | `string` | yes | The next step in one sentence. |

## Behavior hints

| Hint | Value |
|---|---|
| `readOnlyHint` | true |
| `destructiveHint` | false |
| `idempotentHint` | true |
| `openWorldHint` | false |

## Bounds

A bound that is reached is reported in the result; nothing is cut silently.

| Bound | Value | What it limits |
|---|---|---|
| `maxImportLength` | 10000000 | Characters an import reads, not counting white space or lines that are only a comment. A longer text is answered with I102. |
| `maxImportLocalLength` | 100000000 | Characters of text in one call on the local server, which runs on your own machine. A guard on memory, not a cap a real project meets. |
| `maxImportTextLength` | 10485760 | Characters of text in one hosted call, comments and white space included, all files together. |
| `maxImportFiles` | 200 | Files in one hosted call. |
| `maxImportLocalFiles` | 20000 | Files in one call on the local server. |
| `maxImportParts` | 24 | Diagrams one import is split into when the file is too big for one picture; each is validated. |
| `maxImportNodes` | 40 | Boxes in an imported flow; the rest are left out with an I200 diagnostic. |
| `maxImportTables` | 20 | Tables in an imported schema. |
| `maxImportRows` | 20 | Rows of an imported matrix: endpoints, or rows of a table. |
| `maxImportColumns` | 8 | Columns of an imported matrix: roles, scopes, or schemes. |
| `maxImportPoints` | 60 | Places, slices, flows, or tiles in an imported chart. |
| `maxImportSeries` | 6 | Series in an imported XY chart. |
| `maxImportEntries` | 60 | Rows of an imported tree; a folder past it ends with an omitted line. |
| `maxImportCommits` | 40 | Commits of an imported git graph, the newest kept, and events of an imported timeline. |
| `maxImportMessages` | 30 | Messages of an imported sequence. |

## See also

| Doc | Why |
|---|---|
| [Tool reference](https://docs.plotwork.dev/mcp/tools.md) | Every tool, with the workflows first |
| [`POST /v1/import`](https://docs.plotwork.dev/api/post-v1-import.md) | The same operation over HTTP |
| [Language reference](https://docs.plotwork.dev/reference/language.md) | What the diagram source may contain |
| [Writing diagrams with an agent](https://docs.plotwork.dev/mcp/agent-loop.md) | The loop in practice |
