Brownfield Cartographer

io.github.Sanoy24由 GitHub 帳號 Sanoy24 發布v0.10.0更新於 Nov 4, 2026

Local impact and table, column and Airflow lineage for SQL, dbt, Python and TypeScript repos.

概覽

AI 產生的概覽

唯讀 MCP 伺服器,根據本機分析結果回答 SQL、dbt、Python 與 TypeScript 儲存庫的變更影響與資料血緣問題。

可以做什麼
  • 檢視儲存庫架構概況,以字面比對尋找符號
  • 追蹤相依關係,分析某處變更可能影響哪些下游
  • 追溯資料表與欄位血緣,支援上游與下游方向,並附上檔案與行號證據
  • 取得符號或檔案的程式碼脈絡
  • 讀取先前建立的在本機索引,不呼叫模型,也不執行儲存庫程式碼
適用情境
適合在既有程式碼庫中需要理解跨語言資料相依性的情境,例如修改某個 dbt 模型、SQL 語句、Python 工作或 Airflow 任務會影響什麼,或某張資料表、某個欄位來自何處。
執行需求
以本機 stdio 程序執行(PyPI 套件 brownfield-cartographer,透過 uvx 或 cartographer-mcp 指令啟動),需要 Python 3.12+ 與 Git。儲存庫須先以 cartographer analyze 指令完成分析,並以儲存庫路徑參數指向該儲存庫。本機分析不需要 API 金鑰或網路存取。
安裝前請注意
結果為靜態且啟發式:影響分析列出的是潛在相依方,並不保證一定出錯;掃描不完整時應先查看已保存的覆蓋率與診斷資訊。常見的密鑰檔名會被排除,但一般原始碼中內嵌的密鑰不會被偵測。明確傳入 GitHub URL 會下載程式碼副本,而本機分析從不上傳原始碼。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Brownfield Cartographer,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

Brownfield Cartographer

[CI] [License: Apache-2.0] [Python 3.12+]

[Brownfield Cartographer MCP server]

What breaks if I change this? Cartographer finds the dependencies your language server can't see: a table written by a Python job, transformed in SQL, consumed by a dbt model. It maps them statically and locally, with file and line evidence, for you and your coding agent.

sh
cartographer analyze .cartographer impact models/staging/stg_orders.sql   # what is downstream of this file?cartographer lineage customers --direction upstream # where does this table come from?cartographer lineage customers::first_order          # which source columns feed this column?

Language servers and grep answer questions about code symbols. Cartographer answers questions that cross language boundaries through names in strings and configuration, starting with data lineage across Python, SQL and dbt. Every result carries source evidence and coverage, and unsupported cases are reported rather than guessed. It runs offline, needs no API key, and never executes repository code.

One query engine serves the CLI, a Python API, and a read-only MCP server for Claude Code, Codex and Cursor. The support table below lists current capabilities and known gaps.

Try it in 60 seconds

With uv installed, run it on dbt's public example project. Nothing is installed permanently, and analysis took 3 seconds here:

sh
git clone --depth 1 https://github.com/dbt-labs/jaffle_shop && cd jaffle_shopuvx --from brownfield-cartographer cartographer analyze .uvx --from brownfield-cartographer cartographer impact models/staging/stg_payments.sql
text
analyze_impact | complete | snapshot eefa28cd4e13┌───────────────┬──────────────┬──────────────────────────────────────┐│ Symbol / node │ Relationship │ Evidence                             │├───────────────┼──────────────┼──────────────────────────────────────┤│ stg_payments  │ PRODUCES     │ models/staging/stg_payments.sql:1-26 ││ orders        │ PRODUCES     │ models/orders.sql:1-57               ││ customers     │ PRODUCES     │ models/customers.sql:1-70            │└───────────────┴──────────────┴──────────────────────────────────────┘

Column lineage follows renames through each model:

sh
uvx --from brownfield-cartographer cartographer lineage customers::number_of_orders
text
trace_data_lineage | complete | snapshot eefa28cd4e13┌──────────────────────┬──────────────┬────────────────────────────────────┐│ Symbol / node        │ Relationship │ Evidence                           │├──────────────────────┼──────────────┼────────────────────────────────────┤│ stg_orders::order_id │ DERIVES      │ models/customers.sql:1-70          ││ raw_orders::id       │ DERIVES      │ models/staging/stg_orders.sql:1-24 │└──────────────────────┴──────────────┴────────────────────────────────────┘

In Claude Code, the plugin lets you ask the same questions in plain language.

Install and analyze

Requires Python 3.12+ and Git. Install the command-line tools from PyPI with uv or pipx:

sh
uv tool install brownfield-cartographer# or: pipx install brownfield-cartographercartographer --version
# Local analysis needs no network, API key, or model service.cartographer analyze /path/to/repository
# Force a fresh rebuild or choose an output root.cartographer analyze /path/to/repository --full -o ./results
# Optional: pin the SQL dialect instead of choosing the best fit per file.cartographer analyze /path/to/repository --dialect bigquery
# Optional: use a previously generated dbt v12 manifest.cartographer analyze /path/to/dbt-project --dbt-manifest target/manifest.json
# Optional: table columns from `dbt docs generate` for more column lineage.cartographer analyze /path/to/dbt-project --dbt-catalog target/catalog.json

To run from a source checkout instead, clone the repository, run uv sync --frozen, and prefix commands with uv run, as in the examples below.

An explicit GitHub URL input still downloads a checkout:

sh
cartographer analyze https://github.com/owner/repository

Local analysis never uploads source and never calls a model.

Outputs and queries

For a local checkout, artifacts default to <repository>/.cartography/<repository-name>/. With an explicit --output, local repositories use <output-root>/.cartography/<repository-name>--<path-hash>/ so same-named checkouts do not overwrite one another. The hash identifies the resolved checkout path; moving a checkout creates a separate index. The JSON analysis result includes artifact_directory, which can be passed to query commands as --index-dir. Existing custom-output indexes are left untouched; reanalyzing writes to the new directory. GitHub URL inputs use the current directory by default and an owner--repository folder name.

ArtifactPurpose
index.jsonComplete versioned graph, source locations, metadata, coverage
module_graph.jsonStructural graph view, including functions
lineage_graph.jsonDataset/transformation graph view
analysis_summary.jsonComplete/partial status, diagnostics and stage results
CODEBASE.mdStatic repository context
onboarding_brief.mdKey modules, data entry/exit points and change hotspots
cartography_trace.jsonlRetained run history with run IDs
state.jsonLast successful snapshot's content fingerprint

Explore interactively with cartographer query /path/to/repository. It accepts find, impact, deps, dependents, lineage, lineage-down, context, overview, help and quit, using the same engine as the commands below.

Or use individual commands with human-readable or JSON output:

sh
uv run --no-sync cartographer overview /path/to/repository --jsonuv run --no-sync cartographer find run --repo /path/to/repository --jsonuv run --no-sync cartographer impact producer.py --repo /path/to/repositoryuv run --no-sync cartographer lineage output --repo /path/to/repository --direction upstream --json

Use --index-dir for a custom output location. Python callers use brownfield_cartographer.query_api.QueryEngine.open(Path(repo)) and the same query methods. Responses carry snapshot identity, coverage, capped-output markers, and available source evidence. Ambiguous targets are rejected.

Review pull requests

cartographer diff reports what a branch changes and what that can affect, for a PR comment or a quick check before pushing:

sh
cartographer diff --base main          # Markdowncartographer diff --base main --json   # for scripts

Changed lines since the merge base with --base (committed, uncommitted and untracked) are mapped to functions, modules, SQL statements, dbt models, schema YAML and Airflow tasks, and their downstream dependents are listed with evidence. The merge base is analyzed too, so removed code counts: deleting a module, function or model reports the importers, callers and models that still use it.

To comment on every pull request, add a workflow:

yaml
on: pull_requestpermissions:  contents: read  pull-requests: writejobs:  impact:    runs-on: ubuntu-latest    steps:      - uses: actions/checkout@v5        with:          fetch-depth: 0   # the merge base must be available      - uses: Sanoy24/[email protected]

The action keeps one comment up to date and also writes the report to the job summary, which still works for pull requests from forks.

Connect your AI assistant

Claude Code plugin (needs uv; nothing else to install or configure):

text
/plugin marketplace add Sanoy24/the-brownfield-cartographer/plugin install brownfield-cartographer@brownfield-cartographer

The plugin starts the MCP server for the current project and adds a data-impact skill. Ask questions such as "what breaks if I change stg_orders?". If the project has not been analyzed yet, the tools say so and the assistant runs cartographer analyze (offline; repository code is never executed) before answering.

Any MCP host:

sh
cartographer analyze /absolute/path/to/repositorycartographer-mcp --repo /absolute/path/to/repository

The stdio server exposes get_architecture, find_symbol, trace_dependencies, analyze_impact, trace_data_lineage, and get_code_context. It reads a previously analyzed index inside a fixed repository scope and never calls a model. See MCP setup for Claude Code, Codex, and Cursor.

find is lexical matching. impact reports potential dependents, not a guarantee that every consumer will break. Read the persisted coverage and diagnostics before relying on results from an incomplete scan.

Analysis returns exit code 0 for complete/unchanged snapshots, 2 for partial coverage, and 1 for an input or fatal run error. A partial run does not advance the successful checkpoint. Changed working trees currently use full rebuilds; unchanged successful snapshots can reuse the complete index.

Support and safety

InputCurrent support
PythonFunctions/classes, supported absolute/relative imports, and calls between repository functions (same-module names, imported names and modules, self/cls methods; calls on other objects and dynamic calls are not guessed); conservative literal I/O associations (pandas, Spark readers and writers). SQL passed to execute/executemany/executescript, .sql() and read_sql is parsed from literals and string constants (same module or imported from another repository module), including text() and DB-API placeholders. f-strings that interpolate only values (comparisons, IN, LIMIT, quoted literals) are resolved; SQL with interpolated table names or projections, concatenation or .format is reported as dynamic, not guessed
SQLSELECT/UNION, CTAS, INSERT, UPDATE, DELETE and MERGE; statement spans and table dependencies. DDL and transaction statements without table lineage are skipped; other statements, such as COPY, are reported individually without dropping the rest of the file. Each file is parsed with the best-fitting dialect (DuckDB, BigQuery, Snowflake, Postgres, MySQL, Spark, T-SQL, Trino), recorded as sql:<dialect> in evidence; --dialect pins one
dbtExplicit manifest v12 ingestion for models, seeds, snapshots and sources; basic SQL/YAML fallback without a manifest. Projects are found anywhere in the repository, including several per repository
ColumnsColumn-level lineage for CREATE ... AS, INSERT ... SELECT (including column lists) in SQL files, SQL embedded in Python, Airflow inline SQL, dbt models from a compiled manifest (--dbt-manifest, after dbt compile), and dbt source models whose only Jinja is ref/source/config/comments and literal set lists with for loops over them, and calls to the project's own macros with literal arguments. Each edge is copy (the value passes through unchanged) or derived (the column influences the value, including through CASE conditions, window PARTITION BY/ORDER BY keys and aggregates). SELECT * and unqualified columns in joins are resolved against the columns each table is known to have: from CREATE TABLE definitions and fully resolved CREATE ... AS statements and dbt models in the repository, and optionally a dbt catalog.json (--dbt-catalog). A column found in several sources, tables with unknown columns, and models with other Jinja (package macros, macros that call Python methods, filters) are counted as unresolved, not guessed
AirflowTasks from operators and @task functions in with DAG, @dag and dag= DAGs; order from >>/<<, lists, set_downstream, chain() and TaskFlow data passing, with line evidence. Tasks link to what they run: python_callable, @task functions, sql= files (including template_searchpath) and inline SQL lineage, and python x.py bash commands. Impact flows from code through tasks to downstream tasks. Tasks created in loops or with computed ids are reported, not guessed
JavaScript/TypeScript.js .mjs .cjs .jsx .ts .mts .cts .tsx: functions, arrow functions, class methods; ESM, type-only, require() and import() imports with literal relative specifiers and tsconfig/jsconfig paths/baseUrl aliases (nearest config, extends within the repository). Package imports are external

The shared scanner respects nested .gitignore and .cartographerignore, prunes build/environment directories, rejects symlinks/junctions, and caps file size, total bytes, file count, entry count and traversal depth. Conventional secret filenames are excluded; secrets embedded in normal source are not detected. Large, binary, unreadable or unsupported files are reported rather than treated as fully analyzed. No repository source code is executed by local analysis.

See dbt artifact ingestion for supported manifest versions, dataset identifiers, artifact freshness, and scanner limits.

The accuracy benchmark scores extraction against hand-written expected results for pinned dbt, Python and SQL corpora, including known gaps. It runs in CI.

Development and branching

sh
uv sync --frozenuv run --no-sync pytest -quv run --no-sync ruff check src tests scriptsuv run --no-sync mypy -p brownfield_cartographer.scanner -p brownfield_cartographer.persistence -p brownfield_cartographer.query_api -p brownfield_cartographer.analyzers.javascript_analyzer -p brownfield_cartographer.analyzers.embedded_sql -p brownfield_cartographer.analyzers.sql_lineage -p brownfield_cartographer.analyzers.airflow_dag -p brownfield_cartographer.analyzers.dbt_manifest -p brownfield_cartographer.diff -p brownfield_cartographer.analyzers.python_calls -p brownfield_cartographer.analyzers.jinja_lite --follow-imports=skipuv builduv run --no-sync python scripts/check_wheel.py

Use short-lived feat/, fix/, docs/, and chore/ branches and pull requests into stable main. Do not push feature work directly to main. See CONTRIBUTING.md for the workflow and release conventions, and CHANGELOG.md for release history.

Community and license

Participation is governed by the Code of Conduct. Report vulnerabilities privately as described in SECURITY.md.

Licensed under the Apache License 2.0.

來源:README.md,提交 397bd4a

工具

0
SourceWeft 曾在隔離沙箱中以無憑證方式啟動該軟體包一次,以列出其工具,但未能完成:軟體包安裝失敗。

版本歷史

3
  1. v0.10.0最新Nov 4, 2026
  2. v0.9.0Oct 25, 2026
  3. v0.8.0Oct 14, 2026

評分

已滿足適用檢查項的 50%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分

    請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。

  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分