Skip to main content
Glama

DaVinci MCP Server

把 Vector DaVinci Configurator 6 / 5 与 DaVinci Developer Classic 的命令行工具,包装成一套面向 AI Agent 的 MCP 工具集。

Agent 可以直接说「校验这个工程、把错误修掉、生成代码」,而不需要记住 dvcfg-b / DVCfgCmd 的几十个参数、-p= 的写法、退出码含义和 Config Core 的并发限制。

同一套工具同时覆盖两代工程:.dvjson 走 dvcfg-b(CFG6),.dpa 走 DVCfgCmd(CFG5),由服务按后缀自动路由。 CFG5 没有 project create 这样的命令,因此工程创建用模板克隆实现:复制标准工程、重写工程名与路径、再跑一次校验。

还支持 Groovy Automation Interface:Agent 可以按模板生成 .dv.groovy、做静态与编译检查、执行任务, 把「只有 GUI 才能做的批量改配置 / 查询 / 出报告」变成可复用的脚本。 脚本怎么写不靠模型记忆——davinci_api_index 直接从安装目录的 JAR 里反射出真实的类与方法 (纯 Python 解析 class 文件,不需要 JDK),davinci_script_api 负责查;没有安装目录时退回 一份按能力域组织、每条都有官方出处的内置目录。写之前先查、写完再核对。 其中 DV_ON_GENERATION_START / DV_GENERATION_STEP 两类任务可以挂进 CFG5 的生成流程: 在生成前跑自定义检查,发现问题时用 resultSink 报 ERROR,直接中止生成。

再往上加了一层 ECUC 只读分析(可选依赖 py-armodel): 命令行只能整工程校验,看不了单个参数;这一层把 ARXML 解析成可查询的语义视图, 支持参数检索、两份配置的语义 diff、结构体检与清单导出,补上 CFG5 CLI 的空白。

最后补了一块 AUTOSAR 版本探测与模块资产:回答「这个工程 / 这个模块是按哪个 AUTOSAR 版本做的」, 并定位每个模块的 Vector User Manual 与静态代码,让参数级问题能「规范 → 手册 → 代码」三源对照。 版本对了,Agent 才能去查对应版本的规范;否则拿最新版文档解释旧工程,参数名和可选项早已变样。 探测不靠猜——只采信工程设置字段、ARXML 的 xsi:schemaLocation、模块 ADMIN-DATA 三类证据, 每条都带出处与置信度,探不到就返回 null。

还有一块 生成物清单:Agent 要改代码时,先得知道哪些文件是生成的、改了会不会被下次生成覆盖。 生成目录不是固定常量,工具从工程设置里取证定位(CFG6 的 Output、CFG5 的 Appl/GenData 都只是默认值), 再列出目录内的文件与文件夹,逐文件标注生成证据,而不是让模型猜「这个文件看起来像生成的」。

最后是 工程差异对比:给两个工程,按「文件 → 设置 → 输入文件 → ECUC 参数」四层比出差异。 回放分两条路:ECUC 参数用 Groovy(replay 默认 dryRun,确认后在 transaction 里写入; verify 只读核对,可放进 CI),输入文件(DBC/CDD/ECU Extract 等)用 DaVinci 命令行重新导入 (CFG5 DVCfgCmd -u --input / CFG6 project update -c)。为什么要分开:输入文件是配置的源头, 直接改派生出来的参数,下次导入就会被覆盖。生成物差异单独汇总,不会用几千个 .c/.h 淹掉真正的配置变更。

                    ┌──────────────────────────────┐
   Claude / Cursor  │        MCP Client            │
   VS Code / 自研   └──────────────┬───────────────┘
                                   │ JSON-RPC (stdio / sse)
                    ┌──────────────▼───────────────┐
                    │      davinci-mcp server      │
                    │  ┌────────────────────────┐  │
                    │  │ 工具层(62 个 MCP 工具)│  │
                    │  ├────────────────────────┤  │
                    │  │ 服务层:Configurator 6 / │  │
                    │  │ Configurator 5 /         │  │
                    │  │ Groovy / Developer /     │  │
                    │  │ Pipeline / ECUC / 版本   │  │
                    │  │ 生成物清单 / 工程差异    │  │
                    │  ├────────────────────────┤  │
                    │  │ 执行层:路径白名单、    │  │
                    │  │ argv 执行器、项目锁、   │  │
                    │  │ 后台作业、诊断解析      │  │
                    │  └───────────┬────────────┘  │
                    └──────────────┼───────────────┘
                          subprocess│argv(无 shell)
                    ┌──────────────▼───────────────┐
                    │ dvcfg-b   DVCfgCmd   dvdevc  │
                    │ CFG6      CFG5       Developer│
                    └──────────────────────────────┘
                                   ▲
                        只读解析  │  (不参与写操作)
                    ┌──────────────┴───────────────┐
                    │  ARXML  ── py-armodel ── 索引 │
                    └──────────────────────────────┘

1. 为什么需要它

直接用 CLI 的问题

本服务的处理

两代工具参数风格不同(-p= / -p、-g / project generate)

工具参数是结构化字段,服务层按工程后缀选择后端并拼装

生成一次十几分钟,工具调用会超时

超过 wait_seconds 自动转后台作业,返回 job_id

同一工程并发执行会写坏 Config Core

服务端按工程加锁,直接返回 project_busy

输出是给人看的,Agent 难以判断成败

解析出 diagnostics(错误/警告计数、文件、行号、模块)

退出码 1/2/130、dvdevc 的 3/7 含义不明

统一映射为 status + 中文说明 + 修复建议

Agent 可能把工程路径写到任意位置

路径白名单 + 扩展名校验 + 符号链接逃逸拦截

Automation Interface 脚本 API 多、易写错

内置模板 + 静态检查 + DaVinci 编译检查,先预检再执行

命令行只能「整工程校验」,说不清某个参数配了什么

可选 py-armodel 解析成 ECUC 语义索引,支持参数检索、变体 diff 与结构体检

Related MCP server: uml-atlas

2. 快速开始

2.1 环境要求

  • Python 3.10+

  • DaVinci Configurator Classic 6.2 及以上(提供 dvcfg-b)— 处理 .dvjson

  • 可选:DaVinci Configurator 5.x(提供 DVCfgCmd)— 处理 .dpa

  • 可选:DaVinci Developer Classic 4.17 SP2 及以上(提供 dvdevc)

  • 有效许可证 + 可用的 MICROSAR BSW 包

CFG5 的 CLI 通常不单独安装,而是随 SIP 交付在 <SIP>/DaVinciConfigurator/Core/DVCfgCmd.exe。 只需设置 DAVINCI_CFG5_SIP 或 DAVINCI_CFG5_BIN,无需迁移工程即可直接校验与生成。

2.2 安装

git clone <this-repo> davinci-mcp-server
cd davinci-mcp-server
python -m venv .venv && . .venv/bin/activate    # Windows: .venv\Scripts\activate
pip install -e .                 # 仅 CLI 相关能力
pip install -e ".[ecuc]"         # 追加 ECUC 只读分析(py-armodel)

ECUC 分析是可选能力:不装 py-armodel 时其余工具照常工作, 相关工具会返回 dependency_missing 并提示安装命令。

2.3 配置

所有配置都走环境变量,代码里没有任何硬编码安装路径。

变量

必填

说明

DAVINCI_DVCFG_BIN

建议

dvcfg-b / dvcfg-b.exe 绝对路径;不填则查 PATH 与常见安装目录

DAVINCI_DVDEVC_BIN

可选

dvdevc / dvdevc.exe 绝对路径

DAVINCI_CFG5_BIN

可选

DVCfgCmd / DVCfgCmd.exe 绝对路径(最高优先级)

DAVINCI_CFG5_HOME

可选

CFG5 安装根目录,服务会在其 Core/ 下找 DVCfgCmd

DAVINCI_CFG5_SIP

可选

SIP 根目录,服务会在 DaVinciConfigurator/Core/ 下找 DVCfgCmd

DAVINCI_HOME

可选

DaVinci 安装根(含 plugins/)。设置后 davinci_api_index 可省 home 参数,env_doctor 也能提示索引状态

DAVINCI_BSW_PACKAGE

建议

MICROSAR BSW 包根目录,设置后多数工具可省略 bsw_package

DAVINCI_MCP_ROOTS

必填

允许访问的工作根目录,多个用系统路径分隔符隔开(; / :)

DAVINCI_MCP_STRICT_PATHS

可选

1 时连只读输入(BSW、待导入 ARXML)也必须在根目录内

DAVINCI_MCP_TIMEOUT

可选

单条命令硬超时,默认 900 秒

DAVINCI_MCP_MAX_JOBS

可选

并发作业上限,默认 2(不建议调大)

DAVINCI_MCP_LOG_DIR

可选

作业日志目录,默认 ~/.cache/davinci-mcp/logs

DAVINCI_MCP_AUDIT_LOG

可选

审计日志(JSONL),记录每次 CLI 调用的 argv 与退出码

DAVINCI_MCP_FAIL_ON

可选

校验失败阈值,默认 ERROR(NONE / ERROR / WARNING)

DAVINCI_MCP_ECUC_TIMEOUT

可选

单个 ECUC 文件的解析超时,默认 120 秒(纯 Python,与 CLI 超时无关)

DAVINCI_MCP_ALLOW_RAW

可选

预留的原始透传开关(默认关闭)

Windows 示例(PowerShell):

$env:DAVINCI_DVCFG_BIN   = "D:\Vector\DaVinciConfigurator\CLI\dvcfg-b.exe"
$env:DAVINCI_DVDEVC_BIN  = "D:\Vector\DaVinciDeveloper\Bin\dvdevc.exe"
$env:DAVINCI_CFG5_SIP    = "D:\Vector\SIP\MICROSAR_R22-11"
$env:DAVINCI_BSW_PACKAGE = "D:\Vector\MICROSAR\BSW"
$env:DAVINCI_MCP_ROOTS   = "D:\work\ecu"

Linux 示例:

export DAVINCI_DVCFG_BIN=/opt/vector/davinci-configurator/CLI/dvcfg-b
export DAVINCI_CFG5_BIN=/opt/vector/sip/DaVinciConfigurator/Core/DVCfgCmd
export DAVINCI_BSW_PACKAGE=/opt/vector/micrsar/bsw
export DAVINCI_MCP_ROOTS=/home/dev/ecu

2.4 接入 MCP 客户端

Claude Code / 通用 stdio 客户端(mcp.json 或 ~/.claude.json):

{
  "mcpServers": {
    "davinci": {
      "command": "davinci-mcp",
      "args": ["serve"],
      "env": {
        "DAVINCI_DVCFG_BIN": "D:/Vector/DaVinciConfigurator/CLI/dvcfg-b.exe",
        "DAVINCI_CFG5_SIP": "D:/Vector/SIP/MICROSAR_R22-11",
        "DAVINCI_BSW_PACKAGE": "D:/Vector/MICROSAR/BSW",
        "DAVINCI_MCP_ROOTS": "D:/work/ecu"
      }
    }
  }
}

VS Code(.vscode/mcp.json):

{
  "servers": {
    "davinci": {
      "type": "stdio",
      "command": "davinci-mcp",
      "args": ["serve"],
      "env": { "DAVINCI_MCP_ROOTS": "${workspaceFolder}" }
    }
  }
}

远程 / 多客户端(HTTP):

davinci-mcp serve --transport streamable-http --host 127.0.0.1 --port 8765

2.5 自检

davinci-mcp doctor        # 检查 dvcfg-b / DVCfgCmd / dvdevc / BSW / 根目录 / 许可证提示
davinci-mcp list-tools    # 列出注册的 62 个工具
davinci-mcp config        # 打印当前配置

3. 工具清单

3.1 环境与发现

工具

作用

davinci_env_doctor

环境自检,返回每项 pass/warn/fail 与修复建议(含 py-armodel 可选依赖状态)

davinci_version

查询 dvcfg-b / DVCfgCmd / dvdevc 版本(CFG5 优先读 branding jar)

davinci_list_projects

扫描 .dvjson / .dpa / .dcf,自动跳过 Output、GenData 等生成目录

davinci_project_info

工程结构摘要:目录布局、设置项、配置/生成物数量(识别 CFG5 布局)

davinci_scan_output

统计产物:文件数、扩展名分布、最新文件(只知道目录时用)

davinci_generation_roots

从工程设置定位生成目录,给出 source / confidence / exists 与文件数

davinci_generated_files

列出生成目录内的文件夹与文件,逐文件标注 generated / likely_generated / unverified

davinci_help

透传 <tool> <subcommand> --help,用于核对版本差异

3.2 Configurator 工程操作

工具

对应命令

会改工程

davinci_project_create

project create(CFG6)

新建

davinci_cfg5_project_create

模板克隆(CFG5 无对应命令)

新建

davinci_project_validate

project validate

否

davinci_project_generate

project generate

否(输出产物)

davinci_cfg5_validate

DVCfgCmd -v

否

davinci_cfg5_generate

DVCfgCmd -g

否(输出产物)

davinci_cfg5_update

DVCfgCmd -u

是(需 confirm=true)

davinci_cfg5_save

DVCfgCmd Save

是(需 confirm=true)

davinci_cfg5_run

受控透传

取决于参数

davinci_cfg5_report

解析 ExecutionReport XML

否

davinci_project_update

project update(.dpa 自动转到 DVCfgCmd -u)

是(需 confirm=true)

davinci_project_activate_rec_modules

project activate-rec-modules

是

davinci_project_derive_ecuc

project derive-ecuc

是

davinci_project_generate_swct

project generate-swct

否(输出头文件)

davinci_build

校验 → 更新 → 生成 → 导出

取决于参数

3.3 导入导出与运维

工具

对应命令

davinci_export_list / davinci_export_run

export list / export run

davinci_import_arxml

import arxml-artifacts(需 confirm=true)

davinci_automation_list / davinci_automation_run

automation list / automation run

davinci_console_status / davinci_console_stop

status / stop

davinci_job_status / davinci_job_logs / davinci_job_cancel

后台作业管理

3.4 CFG5(DVCfgCmd)

.dpa 工程由 CFG5 后端处理。通用工具 davinci_project_validate / generate / update 会按后缀自动路由, 因此大多数场景不需要区分版本;需要 CFG5 专有参数时再用下面这些工具。

工具

对应命令

说明

davinci_cfg5_project_create

模板克隆

从现有 .dpa 复制出新工程,重写名称/路径后可自动冒烟校验

davinci_cfg5_validate

DVCfgCmd -p <dpa> -v

解析 ExecutionReport XML,返回 counts / findings / gate

davinci_cfg5_generate

DVCfgCmd -p <dpa> -g

支持 -m/-x/--genType/--genArg/--saveProject

davinci_cfg5_update

DVCfgCmd -u <dpa>

支持 --input/--onlyEcuc/--onlyLegacyDiag

davinci_cfg5_save

DVCfgCmd Save [--module]

工作目录自动设为工程目录

davinci_cfg5_run

任意白名单参数

覆盖 import / export / 特定 SP 选项

davinci_cfg5_report

—

单独解析任意 ExecutionReport XML

CFG5 的 -v 是 validate(不是 verbose),-g 是 generate,-u 是 update——与 CFG6 的 project validate / generate / update 一一对应,但参数不能混用。

3.4.1 工程创建:为什么是「模板克隆」

CFG5(5.x)没有与 dvcfg-b project create 等价的结构化创建命令:

路径

能否自动化

说明

GUI → New ECU Project

否

必须选 SIP/BSW、MCU、编译器,要人工确认

DVCfgCmd(5.30 SP1+,Linux)

部分

Vector KB 标注 5.30 SP1 起支持 Linux 下的 project creation;选项随 SP 变化,旧 SIP 上没有

模板克隆(本工具)

是

复制 .dpa + Config,重写根路径与工程名,再跑一次 -v 冒烟

davinci_cfg5_project_create 的参数:

参数

说明

template_project

模板 .dpa,常用 SIP 的 Applications/SipAddon/StartApplication

output_dir / project_name

新工程建为 output_dir/project_name,.dpa 自动改名

copy_dirs

额外复制的一级目录,默认 ["Config"];Appl/GenData/Log 禁止复制

replacements

额外文本替换,用于换 BSW 路径,例如 {"D:/old/bsw": "D:/new/bsw"}

verify

创建后跑 -v,返回 verify.ok / counts / report_file

dry_run

只返回复制与改写计划,不落盘,也不需要 confirm

改写规则刻意保守:只替换「工程根路径」「<名字>.dpa」「>名字<」三类位置, 外加显式 replacements;其余字节不动,避免把模块前缀、版本号改坏。 建议先 dry_run=true 看一遍 files / skipped,再落盘。

davinci_help(binary="cfg5") 会额外返回 creation_capability:在本机 DVCfgCmd --help 文本里探测是否提到工程创建。它只做文本探测、不猜选项名, 真要用新版 CLI 的创建能力时以本机输出为准。

3.5 Groovy 脚本(Automation Interface)

DaVinci 的自动化脚本是 Groovy DSL(.dv.groovy),官方入口是 dvcfg-b automation setup / list / info / run。这组工具覆盖「写 → 查 → 检 → 跑」全流程。

工具

对应命令

说明

davinci_api_index

—

扫安装目录的 JAR,建本机 Java API 索引(class 文件解析,无需 JDK)

davinci_script_api

—

查 API:有索引查真实签名,否则查内置文档目录;也能核对脚本符号

davinci_script_templates

—

内置模板:空白、工程信息、校验、生成、ECUC 报告、Data Mining 查询、写参数、生成步骤、生成前钩子

davinci_script_create

—

从模板生成 .dv.groovy,自动补后缀

davinci_script_read

—

读取源码 + 任务/参数/静态检查结果

davinci_script_write

—

写入完整源码(覆盖需 confirm=true)

davinci_script_list

—

本地扫描脚本,列出任务与问题

davinci_script_tasks

automation list

让 DaVinci 真正加载脚本,列出权威任务清单

davinci_script_info

automation info

单个任务的类型、描述、用户参数

davinci_script_lint

—

静态规则;compile_check=true 时追加 DaVinci 加载检查

davinci_script_run

automation run

执行任务;dry_run=true 只编译不执行

davinci_script_setup

automation setup

创建 dvgroovy / Gradle 脚本工程脚手架

davinci_cfg5_script_install

—

把 .dvgroovy 安装到 CFG5 工程目录,供 GUI 加载

脚本结构与任务类型:

import static com.vector.cfg.automation.api.ScriptApi.*

scriptTask("Validate", DV_PROJECT) {
    taskDescription "Run validation with the project settings"
    code {
        generation { validate() }
        validation {
            def results = validationResults
            scriptLogger.info "Validation finished: ${results.size()} result(s)"
        }
    }
}
  • DV_PROJECT 需要先加载工程;DV_APPLICATION 可自行创建/打开工程; 另有 DV_GENERATION_STEP、DV_ON_GENERATION_END、DV_ON_FILE_PREPROCESSING_RESULT、 DV_ON_SUCCESSFUL_UPDATE_WORKFLOW、DV_EDITOR_SELECTION、DV_EDITOR_MULTI_SELECTION。

  • 用户参数用 newUserDefinedArgument("name", String, "help") 声明, CLI 通过 -a 'TaskName' -a '--name=value' 传入;本服务对应 task_args={"TaskName": "--name=value"}。

  • daVinci { } 只用于 IDE 代码补全,运行时可选。

3.5.1 Agent 怎么知道 Groovy 能做什么

模型对 Automation API 的先验知识不可靠,凭记忆写出来的调用有一半是幻觉。 这里用两层机制解决:优先查本机 JAR 里的真实签名,查不到才退回随包文档目录。

第一层:从安装目录的 JAR 反射(source="jar")
davinci_api_index(home="C:/Program Files/Vector/DaVinciConfigurator")
davinci_script_api(symbol="IValidationResultUI#isId")
davinci_script_api(query="validation result")
davinci_script_api(script="D:/work/Check.dv.groovy")

davinci_api_index 会扫安装目录的 plugins/*.jar,解析 .class 里的类、方法、字段、 泛型签名,存成本地索引。不需要 JDK(DaVinci 只带 JRE,现场也不会为查 API 装 JDK), 纯 Python 读 class 文件格式,跨平台。

能力

说明

类型

class / interface / enum / annotation / record,含嵌套类型(Outer.Inner)

方法

名称、参数、返回、修饰符;泛型保留,如 List<IValidationResultUI.SolvingAction> getSolvingActions()

字段

类型、修饰符、枚举常量

可见性

默认只收 public / protected,include_private=true 才全收

缓存按「JAR 路径 + 大小 + mtime」算指纹:装完 DaVinci 或换了 BSW 包,指纹变了会自动重建; rebuild=true 强制重建。

沙箱里用一个自造的 JAR(tests/data/java,非 Vector 真实签名)走通了全链路:

// davinci_script_api(symbol="IValidationResultUI#isId")
{"ok": true, "source": "jar", "name": "com.vector.cfg.automation.api.IValidationResultUI",
 "members": ["public abstract boolean isId(String, int)"]}

// davinci_script_api(script="Check.dv.groovy")
{"resolved": ["isId", "scriptTask"],
 "unresolved": ["autoFixEverything"],
 "unknown_types": ["NoSuchType"],
 "summary": "JAR 索引里解析到 2 个调用、0 个类型;未解析调用 2 个、未知类型 2 个"}

unresolved 的语义比文档目录硬得多:不是「我的快照里没写」,是「这个 JAR 里确实没有」。 脚本里 def 出来的自定义方法会被自动剔除,不会误报。

解析器用 JDK 20 的 java.base 做过一轮真实数据验证(2000 个 class,含 record、sealed、 复杂泛型):2000/2000 全部解析成功,10000 类/秒,5000 个类约 0.5 秒。复杂签名也能正确还原:

public abstract Iterator<E> iterator()                        // java.util.List
public <V> Function<V, R> compose(Function<? super V, ? extends T>)   // java.util.function.Function
public static <T> Optional<T> of(T)                           // java.util.Optional

真实 DaVinci 的 bundle 比这简单,索引一次通常在秒级;之后走缓存,查询是内存操作。

第二层:随包内置的文档目录(source="builtin")

安装目录拿不到时(CI 容器、只看代码不看机器)退回内置目录:8 个能力域、约 50 条入口, 每条都标了出处等级。

evidence

含义

doc-example

官方 API Reference 的示例代码里出现过,可以照抄结构

doc-mention

文档正文提到、但没有完整示例,签名需自行确认

template

本仓库模板已使用并核对过

它还显式列出 known_gaps:写模型的 setter、Data Mining 查询语法、UI 控件 API、 打开/创建工程的应用级 API——这些没有公开示例,目录不收录,避免让 Agent 以为它们存在。

选哪个

source 参数控制,默认 auto:

取值

行为

auto

有有效索引就用 JAR,否则用内置目录;返回值里 source / note 说明用了哪个

jar

只用 JAR,没有索引直接报 index_missing(适合 CI 里强制走真实签名)

builtin

只用内置目录(离线、对比、或想看清「我到底抄了哪些」)

两条路都不替代编译:静态解析看得见「有没有」,看不见「类型对不对」。 最终仍要 davinci_script_lint(compile_check=true)。

对应资源:davinci://groovy/api(能力地图,自动选源)。

3.6 Developer 工作区

工具

对应命令

davinci_dev_workspace_create

dvdevc project create

davinci_dev_workspace_link

dvdevc project link

davinci_dev_root_design_create

dvdevc model create-root-design

davinci_dev_workspace_update

dvdevc project update

davinci_dev_workspace_convert

dvdevc project convert(非 analysis-only 需确认)

davinci_dev_run

其他 dvdevc 子命令(白名单 + 确认)

3.7 ECUC 只读分析(py-armodel)

CFG5 的 DVCfgCmd 只有「整工程校验 / 生成 / 更新」三个粒度,回答不了下面这些问题:

  • DemEventParameter_0 的 DemEventId 到底配了几?

  • 这个变体和上个基线相比,哪些参数变了?

  • 配置里有没有指向已删除容器的引用?有没有留空的壳容器?

这组工具用 py-armodel 把 ECUC ARXML 解析成 「模块 → 容器 → 参数/引用」的语义索引,在其上做查询与对比。它只读,不写回 ARXML。

工具

作用

关键参数

davinci_ecuc_index

建立结构索引(模块/容器树/统计)

arxml(单文件或列表)、limit

davinci_ecuc_query

按路径通配/模块/容器/参数名/值片段检索

pattern、module、value_contains、kind

davinci_ecuc_diff

两份配置的参数级语义对比

before、after、max_changes

davinci_ecuc_audit

结构体检(空容器、类型不符、悬空引用、重名)

arxml、max_items

davinci_ecuc_export

导出扁平清单(CSV/JSON),供评审与影响分析

out_path、format、confirm

路径是跨文件稳定的键,构造规则:

/模块名/容器 short-name/子容器 short-name/参数定义名
/Dem/DemGeneral/DemEventParameter_0/DemEventId
/Dem/DemGeneral/DemEventParameters/DemEventParameter_0/DemEventId
  • 模块名取 DEFINITION-REF 的末段;容器用 short-name(AUTOSAR 保证同父唯一), 重名时追加 #2 并在 conflicts 中报告。

  • 参数名取定义路径末段;同名多值参数按出现顺序追加 #2、#3。

diff 的语义:容器按 (定义, short-name) 二次匹配,因此「把事件容器挪到新的父容器下」 只报一条 moved,不会刷出「删 4 个参数 + 加 4 个参数」。只有两侧都唯一时才判定为移动, 批量同名容器不做猜测。

{
  "counts": {"added": 0, "removed": 0, "changed": 1},
  "containers": {"added": 1, "removed": 2, "moved": 1},
  "changes": [
    {"kind": "moved", "path": "/Dem/DemGeneral/DemEventParameter_0",
     "after_path": "/Dem/DemGeneral/DemEventParameters/DemEventParameter_0"},
    {"kind": "changed", "path": "/Dem/DemGeneral/DemMaxNumberEvents",
     "before": 128, "after": 256, "type": "integer"}
  ],
  "summary": "参数变化:改值 1,新增容器 1,删除容器 2,移动容器 1"
}

为什么不做写回:py-armodel 的 writer 会重新序列化整个文档。实测往返后 ANNOTATION-TEXT 内嵌的 XHTML 会丢内容、元素顺序与命名空间前缀会重排, Vector 侧的增量识别和代码评审 diff 都会受污染。所以改配置仍然走 DVCfgCmd / GUI, 这一层只负责「看清现状」。真要批量改,用 Groovy(3.5)或 cfg5_update 导入。

已知边界(实测,py-armodel 1.9.8):

现象

处理

参数字面量与类型不符(整型写了文本)

py-armodel 直接抛异常,整文件解析失败;服务返回 parse_error 并提示先修正该值

数值统一按 float 承载

整型参数已归一为 int(128 不会显示成 128.0);0x80 会归一为 128,语义对比按数值而非字面量

只支持 AUTOSAR 4.x 的 ECUC

3.x 的 TOP-LEVEL-PACKAGES 结构不支持,会返回解析错误

引用指向 BSWMD/其他文件

标为 reference_out_of_scope(info),不算错误,避免误报

大工程

2.6 MB / 3000 容器 / 9000 参数约 0.3 秒、55 MB 内存;单文件超 50 MB 建议按模块拆分

3.8 AUTOSAR 版本探测与规范定位

回答「DemEventId 这个参数什么意思」「这个配置项能不能用」之前,先得知道工程是按哪个 AUTOSAR 版本做的。拿 R23-11 的文档解释一个 4.2.2 的工程,参数名、容器路径、可选项 都可能已经变了,结论会系统性偏错。

CFG5/CFG6 的 AUTOSAR 版本是工程级设置,工程文件里没有「每个模块一个版本字段」; 真正逐模块可测的是每个模块描述文件用了哪个版本的 schema 序列化。BSW 包、第三方 MCAL、OEM 提供的 ECUC 文件版本不一致时,这个差异会直接表现为「参数定义过期 / 校验 报不认识的定义」。所以工具同时给工程版本和逐模块证据,并把不一致的模块单列。

工具

作用

关键参数

davinci_ar_version

探测工程版本、逐模块版本证据、冲突清单

paths(目录/.dpa/.dvjson/ARXML)、deep、include_modules

davinci_spec_lookup

模块 + 版本 → SWS 文档名、ECUC 定义路径、检索式

module、release、topic

davinci://autosar/specs 资源暴露约 50 个常见模块与 SWS 文档的对照表,可先浏览再查。

证据分级(每条都带 source,能追到具体文件甚至压缩包内的条目):

证据

置信度

说明

工程设置里的显式字段

high

CFG6 Settings/General.json 的 autosarVersion、.dpa 内的工程设置条目

xsi:schemaLocation

medium

AUTOSAR TPS_ARXMLSerializationRules 要求必须声明,AUTOSAR_4-2-2.xsd 直接编码了序列化依据的版本

模块 ADMIN-DATA 的 SDG/SD

medium

厂商自定义,要求 GID 或内容本身提到 autosar/version 才采信,避免把文档修订号当版本

命名空间 r4.0

不投票

只说明「4.0 起的兼容序列」,区分不了 4.2.2 与 4.4.0;只用于给出 series: "4.x"

探不到就返回 null,并在 guidance 里说明可能原因(传了生成目录、文件被裁剪), 不会默认成最新版本——这是这块功能最重要的约束。

{
  "project": {"release": "4.2.2", "confidence": "high", "agreement": 0.67,
              "schema_major": "4.0",
              "evidence": [{"kind": "project-setting", "release": "4.2.2",
                            "source": ".../Settings/General.json",
                            "value": "general.autosarVersion=4.2.2"}]},
  "modules": [
    {"module": "Dem", "release": "4.2.2", "confidence": "medium", "inherited": true,
     "spec_document": "AUTOSAR_SWS_DiagnosticEventManager",
     "spec_query": "AUTOSAR_SWS_DiagnosticEventManager 4.2.2"},
    {"module": "NvM", "release": "4.0.3", "confidence": "medium", "inherited": true}
  ],
  "mismatches": [{"module": "NvM", "release": "4.0.3"}],
  "unresolved": [],
  "summary": "工程 AUTOSAR 版本 4.2.2(high),2 个模块,1 个模块版本不一致(NvM)"
}

mismatches 不是错误,而是该重新核对的清单:一个 4.0.3 的模块定义放进 4.2.2 工程, 通常还能跑,但新版本增加的参数它不认识,诊断时要单独提示。

规范定位:

davinci_spec_lookup(module="Dem", release="4.2.2", topic="DemEventId")
# → documents: [{"name": "AUTOSAR_SWS_DiagnosticEventManager", "layer": "SWS"}]
# → ecuc_definition: "/AUTOSAR/EcucDefs/Dem"
# → queries: ["AUTOSAR_SWS_DiagnosticEventManager 4.2.2 DemEventId",
#             "AUTOSAR SWS Dem 4.2.2 DemEventId", ...]
# → release_path: "R4.2.2",document_url_hint: .../standards/R4.2.2/CP/<doc>.pdf

文档名是按 AUTOSAR 发布命名整理的,条目里标了 origin: "curated";站点改版或模块拆分时 名字会变,所以查询结果始终附带检索式。检索式才是主路径,文件名只是加速。

扫描范围:传目录时默认找 *.dpa、*.dvjson、Settings/*.json、Config/**/*.arxml, 找不到就递归找 .arxml(BSW 包、MCAL 目录没有 Config/ 结构);deep=true 才连 Appl/GenData 等生成目录一起扫。要把「模块定义」和「工程配置」放在一起比,直接把两边都传进去:

davinci_ar_version(paths=[".../MyEcu", "D:/SIP/MICROSAR"])
# → project.release 取工程设置;模块的 release 各自来自它所在文件
# → mismatches 列出「BSW 包里的定义仍是 4.0.3」这类差异

单文件上限 64 MB,.dpa 解压总量上限 96 MB / 120 个条目,超了会在 notes 里说明, 不静默截断。纯标准库实现,不需要安装 py-armodel,也不需要 Vector 二进制。

3.8.1 模块资产:Vector User Manual 与静态代码

SWS 规范讲「参数在标准里是什么意思」,Vector User Manual 讲「Vector 实现里这个参数 怎么用、有哪些实现限制」,静态代码是最终事实。回答参数级问题要三源对照,缺了任何一环 都可能给出「规范里有、Vector 里没有」的答案。

工具

作用

关键参数

davinci_module_assets

定位模块的 User Manual、静态代码、模块定义 ARXML

project、module、bsw_package、allow_outside

定位按证据分层,与生成目录的思路一致:

证据

置信度

说明

bsw_package 参数

high

显式指定 BSW 包(MICROSAR 交付)根目录

工程设置里的 BSW 包路径

high

Settings/*.json、.dvjson、.dpa 内 JSON 中 key 含 bsw + package/path/dir/root

工程目录 / 父目录布局

medium

模块目录可能在工程内,Vector 交付也常与工程并排

白名单根目录推断

low

前面全落空时才用 DAVINCI_MCP_ROOTS

文档识别:文件名含模块名 + 手册词形(UserManual / UM / Handbook)且为 pdf/chm/html → manual(high);模块目录内 doc/ 下的文档 → doc(按是否含模块名 给 medium/low);交付根两层内的集中文档目录(Documentation/ 等)也参与匹配。

代码识别:模块目录下的 src/ / inc/ 里的 .c/.h;模块同名的文件(NvM.c、NvM.h) 作为 entry_points 单列。生成输出目录(GenData/、Output/ 等)里的同名 .c/.h 标成 generated_code,不算静态代码——生成物是配置的派生结果,不能当实现依据。 找模块目录时会跳过生成目录,避免 GenData/NvM 被当成模块交付。

// davinci_module_assets(project=".../MyEcu", module="NvM").static_code
{
  "module_dir": "D:/SIP/MICROSAR/BSW/NvM",
  "static_code": {
    "count": 42, "generated_code_count": 0,
    "roots": ["D:/SIP/MICROSAR/BSW/NvM/src", "D:/SIP/MICROSAR/BSW/NvM/inc"],
    "entry_points": ["D:/SIP/MICROSAR/BSW/NvM/src/NvM.c",
                     "D:/SIP/MICROSAR/BSW/NvM/inc/NvM.h"],
    "files": [{"kind": "code", "path": "...", "confidence": "medium",
               "source": "settings", "detail": "静态代码(src/)"}]
  },
  "documentation": {"count": 1, "files": [{"kind": "manual",
                   "path": "D:/SIP/MICROSAR/BSW/NvM/doc/NvM_UserManual.pdf",
                   "confidence": "high"}]}
}

工具只定位文件(stat,不读内容);拿到的路径直接用读文件工具打开。 找不到时对应清单为空、available=false 并说明原因——不会编造文档名。

3.9 生成物清单(哪些文件是生成的)

修改代码前必须先回答一个问题:这个文件是生成的,还是人写的? 生成文件手改后,下一次 generate 会被静默覆盖,改动等于没做。但生成目录不是固定常量:CFG6 可以改 Output, CFG5 可以改 Appl/GenData,有的工程把生成物放到工程目录之外。

所以工具不去猜一个路径,而是分三层取证:

证据

置信度

说明

工程设置里的显式字段

high

.dvjson / Settings/*.json 中的 outputFolder、generationDirectory 等;.dpa 内设置条目同样采信

DaVinci 默认布局

medium

CFG5 Appl/GenData / GenData,CFG6 Output

目录名推断

low

一级子目录名匹配 GenData、Output、Gen*;仅当前两层都没有结果时使用

工具

作用

关键参数

davinci_generation_roots

定位生成目录:路径、来源、置信度、是否存在、文件数/体积/最新时间

project、dirs、include_missing、allow_outside

davinci_generated_files

列文件夹与文件,并逐文件分类

project、view、pattern、exclude、max_depth、limit、classify

// davinci_generation_roots(project="D:/work/ecu/Demo.dvjson")
{
  "roots": [{
    "path": "D:/work/ecu/GenData", "exists": true,
    "source": "project-setting", "confidence": "high",
    "detail": "Demo.dvjson 的 generation.outputFolder(字段 outputFolder=GenData)",
    "file_count": 1842, "size_human": "12.3 MB", "latest": "2026-11-08 21:04:12"
  }],
  "notes": []
}

逐文件分类只有三档,且每档都带 evidence:

category

含义

generated

有明确证据:位于工程设置指定的生成目录、文件头写了 auto-generated / do not edit、或命名是 Rte_* / *_Cfg.*

likely_generated

位于默认生成目录,或文件本身只有命名线索,没有文件头佐证

unverified

目录是显式指定/按名字猜的,文件本身也没有生成标记——需要人工确认

// davinci_generated_files(project=".../Demo.dvjson", pattern=["*.h"], limit=100)
{
  "totals": {"files": 1842, "generated": 1790, "likely_generated": 40, "unverified": 12,
             "folders": 37, "size_human": "12.3 MB"},
  "trees": [{
    "folders": [{"rel_path": "Rte", "files": 128, "bytes": 912340,
                 "categories": {"generated": 128, "likely_generated": 0, "unverified": 0}}],
    "files": [{
      "rel_path": "Rte/Rte_Cfg.h", "bytes": 8123, "modified": "2026-11-08 21:04:12",
      "category": "generated",
      "evidence": ["位于工程设置指定的生成目录(来源:project-setting)",
                   "AUTOSAR RTE 生成文件命名(Rte_*)"]
    }]
  }]
}

几个使用要点:

  • *_Callout.c 是例外:它通常是生成器产出的桩,首次生成后由人工维护。返回值里的 hint 会提示,不要因为 category=generated 就认为它每次都会被覆盖。

  • view 可以省流量:folders 只看目录结构与每层文件数,files 只看文件,tree 两者都给。

  • 过滤:pattern=["*.h", "Rte/*"]、exclude=["*_Callout.c"];max_depth=0 只看根目录。

  • 大目录:默认统计最多 2 万个文件、文件头最多检查 2000 个,超出会在 notes 里说明; limit 只控制返回条目数,不影响统计。

  • 越界目录:工程设置指向 DAVINCI_MCP_ROOTS 之外时,该候选标为 blocked 并给出提示, 不影响其他目录;确认要读时传 allow_outside=true(DAVINCI_MCP_STRICT_PATHS=1 时无效)。

3.10 工程差异对比(ECUC → Groovy,输入文件 → 命令行)

两个工程之间「到底改了什么」,靠肉眼比 ARXML 不现实,靠纯文本 diff 又会被格式和生成物干扰。 这一层分四层取证,先给结论,再按「变更的性质」选回放方式。

层次

依据

能回答的问题

文件级

相对路径对齐、SHA-256 判内容、同哈希异路径判重命名

哪些文件新增 / 删除 / 改名 / 改内容

设置级

Settings/*.json、根 .dvjson、.dpa 内 JSON 展平成键路径

哪个设置项从什么改成了什么

输入文件级

设置引用(high)→ Input/ 布局(medium)→ 扩展名(low)

哪个 DBC / CDD / LDF / ECU Extract 变了

ECUC 语义级

py-armodel 索引(可选依赖)

哪个参数改值 / 新增 / 删除,容器是否移动

生成目录默认排除:生成物是配置的派生结果,GenData/ 下几千个文件全变并不代表配置改了。 需要时传 include_generated=true,或直接看 files.generated 里的计数与样本。

工具

作用

davinci_project_diff

四层差异:files / settings / inputs / ecuc,带计数、分类与截断标记

davinci_project_diff_script

mode=replay / verify 渲染 Groovy;mode=cli 渲染输入文件命令行回放

replay 只自动写「两侧都存在、标量、路径可解析」的 ECUC 参数,其余一律进 manual: 新增参数需要 OrCreate、删除参数没有公开 remove、容器移动无法用 .value 表达。 这不是偷懒,是避免生成一段跑起来必然报错的脚本。

// davinci_project_diff_script(mode="replay") 的关键片段
def changes = [
    [kind: 'changed', path: '/Dem/DemGeneral/DemMaxNumberEvents',
     wire_path: '/ActiveEcuC/Dem/DemGeneral/DemMaxNumberEvents',
     before: 128, after: 256],
]
def manual = [
    [kind: 'added', path: '/Dem/DemGeneral/DemNewParam',
     reason: '新增参数在目标工程里不存在,路径访问无法创建;用 GUI 或 OrCreate 访问器添加'],
]

if (dryRun.value) {
    // 逐条确认路径能否解析,提前暴露拼错或模型布局差异
    // ...
} else {
    transaction {
        changes.each { item ->
            mdfModel(AsrPath.create(item.wire_path)) { parameter ->
                parameter.value = item.after
            }
        }
    }
    saveProject()
}

写法有出处:mdfModel(AsrPath.create(...))、transaction 内改属性来自官方 Model API — Getting Started; saveProject() 与 parameter.value= 来自本仓库的 set_parameter 模板。默认 dryRun=true, 先跑一遍看 [resolved] / [unresolved],再决定是否写入。

verify 不开启事务,只按记录值读取并比较;--failOnDiff=true 时失配抛异常,适合放进 CI 回归。 两种脚本返回前都会过一遍 davinci_script_lint 用的那套静态规则。

输入文件:为什么不能写成 Groovy

DBC、CDD、LDF、FIBEX、ODX 和 ECU Extract 是配置的输入,不是配置本身。DaVinci 的流程是 「导入输入 → 派生 / 合并 ECUC → 生成代码」;直接改派生出来的参数,下一次导入就会把它们覆盖回去。 所以 inputs 层只回答「哪个文件变了」,回放交给 DaVinci 命令行。

识别分三层,和生成目录一样带证据:

证据

置信度

说明

工程设置里的显式引用

high

Settings/*.json、.dvjson、.dpa 内 JSON;键名要含 input / ifp / fileList / extract / diagnostic 等

Input/(含 Input/Preprocessing、Input/OEMInput/Preprocessing)

medium

CFG6 官方工程结构把 Input/ 定义为输入文件目录

扩展名兜底

low

.dbc / .cdd / .ldf / .fibex / .odx / .pdx / *_dvarjson.json

.arxml 只有落在 Input/ 下或被输入类设置引用时才算输入;Config/ 下的 ARXML 是配置本体。 输入文件同时会出现在 files 主表里,分类标为 input,不会和生成物混在一起。 工程目录外的引用只做 stat、不读内容,大小相同时记为 unverified,不会生成覆盖命令。 CFG5 工程目录里的 .dpa 也会按条目扫描(只读输入后缀、有大小与预算上限), 所以「输入在归档里」不会被漏掉;这类条目没有磁盘路径,回放会转人工。

回放按工程类型分流:

CFG5(.dpa)
  DVCfgCmd -u <left.dpa> --input "<right>/Input/Can.dbc,<right>/Input/Diag.cdd"
  # 一次 -u 可以带多个文件;改内容的合并成一条命令

CFG6(.dvjson)
  copy /Y "<right>/Input/Can.dbc" "<left>/Input/Can.dbc"   # 已存在先备份 .bak
  dvcfg-b project update -p "<left>.dvjson" -b "<bsw>" -c  # -c = apply ifp changes

-b 是 dvcfg-b project update 的必填项,工具先从左侧工程设置里找 bswPackage; 找不到就降级为人工项,而不是生成一条注定失败的命令。新增输入文件需要在 Input Files 助手里注册模块映射,删除也需要在助手里移除——公开命令没有对应开关,这两类都进 manual。

// davinci_project_diff(...).inputs.replay 的关键字段
{
  "variant": "cfg5",
  "commands": [
    {"kind": "update", "tool": "DVCfgCmd",
     "argv": ["DVCfgCmd", "-u", "D:/work/A/Demo.dpa",
              "--input", "D:/work/B/Input/Can.dbc,D:/work/B/Input/Diag.cdd"]}
  ],
  "manual": [
    {"kind": "added", "name": "New.ldf",
     "reason": "新增输入文件需要在 Input Files 助手里注册模块映射"}
  ],
  "counts": {"commands": 1, "update": 1, "manual": 1}
}

两个可选参数用于纠正环境推断:cli_path 指定 DVCfgCmd / dvcfg-b 的绝对路径, bsw_package 在工程设置里没有 bswPackage 时补上 CFG6 的 -b。两者都不猜默认安装位置。

mode="cli" 会把这套计划渲染成可执行脚本:.cmd / .bat 走 Windows 批处理, .sh 走 POSIX shell,.json 给自动化流水线。脚本默认带 DAVINCI_CLI 变量、 复制前备份、errorlevel 检查;它不会自动执行,与 Groovy 的 dryRun 一样, 先让人看清要改什么。

davinci_project_diff_script(left=..., right=..., mode="cli", out_path="replay.cmd", confirm=true)
davinci_project_diff_script(left=..., right=..., mode="replay")   # Groovy + input_replay 一起返回

几个边界:

  • 文件路径对齐依赖相同布局:目录 ↔ 目录最可靠;目录 ↔ .dpa、.dvjson ↔ .dpa 会在 notes 里提示类型不同,此时以 ECUC 语义差异为准。

  • .dpa 是归档:按条目比较;ARXML 解到临时目录交给 py-armodel 解析,不写回工程。 归档里的输入文件没有磁盘路径,CLI 回放会降级为人工项,需先解出到磁盘。

  • .dcf 不能回放输入文件:它不是 CFG5/CFG6 的工程容器,variant 返回 unknown, 只给人工清单,不猜命令行语法。

  • 没有 py-armodel:ecuc.available=false、reason=dependency_missing,文件、设置与输入结论照常返回。

  • 路径前缀:默认 /ActiveEcuC(官方示例写法)。工程自定义了活动 ECU 容器名时,改 active_root 重新生成;dryRun 的 [unresolved] 会直接暴露这个问题。

4. 典型工作流

4.1 从零把工程编译出代码

用户:把 D:/work/ecu/Demo.dvjson 校验一下,没问题就生成代码

Agent:
1. davinci_project_validate(project="D:/work/ecu/Demo.dvjson")
   → ok=false, errors=2, findings=[EcuC 未解析引用, Os 任务未分配]
2. 分析两条错误 → 建议执行 update 的 solve-all
3. davinci_project_update(..., actions=["solve-all"], confirm=true)
4. davinci_project_validate(...) → errors=0
5. davinci_project_generate(...) → status=running, job_id=job-a1b2
6. davinci_job_status("job-a1b2") → succeeded
7. davinci_generated_files(project=".../Demo.dvjson", view="folders")
   → 37 个目录、1284 个文件;生成根来自工程设置,不靠猜

或者一步到位:

davinci_build(project="D:/work/ecu/Demo.dvjson", update_first=true, update_confirmed=true)

4.2 修校验错误

davinci_project_validate(project, fail_on="WARNING")
→ top_modules: EcuC(12), Os(8), Dem(3)
→ diagnostics.findings 按 severity 排序,带 file/line/module

Agent 可以据此定位到具体 ARXML,而不是靠猜。

4.3 BSW 包升级

1. activate_rec_modules(project, bsw_package=新包)
2. project_update(confirm=true)          # 引用修正 / 输入变更 / RTE 配置
3. project_validate()                     # 重点看「参数已不存在」「新增必填参数」
4. project_generate()

内置提示词 davinci_bsw_update 固化了这个顺序。

4.4 CFG5(.dpa)工程

新建工程(以 SIP 自带工程为模板):

1. davinci_cfg5_project_create(
       template_project="D:/SIP/Applications/SipAddon/StartApplication/StartApplication.dpa",
       output_dir="D:/work/ecu", project_name="BodyEcu", dry_run=true)
   → file_count / skipped / 无写入
2. davinci_cfg5_project_create(..., confirm=true)
   → created=true, project_file="D:/work/ecu/BodyEcu/BodyEcu.dpa", verify.ok=true
用户:把 D:/work/ecu/Legacy.dpa 校验一下,没问题就生成

Agent:
1. davinci_cfg5_validate(project="D:/work/ecu/Legacy.dpa")
   → ok=true, counts={error:0}, gate.passed=true
2. davinci_cfg5_generate(project=..., modules=["Rte"], save_project=true)
   → status=running, job_id=job-5f6e
3. davinci_job_status("job-5f6e") → succeeded
4. davinci_cfg5_report(report_file=".../Log/davinci-mcp/Legacy.generate.*.xml")
   → generation.modules / files / failed_modules

也可以直接用通用工具,服务会按 .dpa 自动选 CFG5:

davinci_project_validate(project="D:/work/ecu/Legacy.dpa")   → backend="cfg5"

遇到未封装的选项时(示例为官方文档中的 Platform Function 导出):

davinci_cfg5_run(
    project="Legacy.dpa",
    arguments=["--exportDir", "D:/work/export",
               "--exportPlatformFunctions", "--syncContract"],
)

透传参数会做两件事:工程与输出路径照样过白名单;未知选项直接拒绝(先 davinci_cfg5_run(arguments=["--help"]) 确认)。

4.5 用 Groovy 做批量检查

用户:把 D:/work/ecu/Demo.dvjson 里所有 ECUC 报告导出来,存到 D:/work/report

Agent:
1. davinci_script_templates() → 选 ecuc_report
2. davinci_script_create(script_path="D:/work/ecu/Scripts/EcucReport", template="ecuc_report")
3. davinci_script_lint(script=..., project=..., compile_check=true)
   → ok=true,DaVinci 已成功加载
4. davinci_script_run(project=..., scripts=[...],
                      task_args={"EcucReport": "--output=D:/work/report/ecuc.html"},
                      no_save=true, confirm=true)
5. 检查 report 文件存在后,再用 no_save=false 正式执行

自定义逻辑时用 davinci_script_write 直接写源码;不要凭记忆猜 API—— 先 davinci_script_lint(compile_check=true),让 DaVinci 的 Groovy 编译器给出真实错误行号。

4.5.1 把检查嵌进生成流程(CFG5)

CFG5 的生成流程分三段:Calculation → Validation → Generation。Groovy 用三种任务类型接入:

任务类型

执行时机

能否阻止生成

注册方式

DV_ON_GENERATION_START

整个 GenerationProcess 开始前;参数 phasesToExecute, generators

否

Script Locations(Project scope)

DV_GENERATION_STEP

由工程配置决定;phase.calculation / phase.validation / phase.generation

是(resultSink 报 ERROR)

Script Locations + Project Settings > Generation > Generation Steps

DV_ON_GENERATION_END

生成结束后;参数 generationResult, generators

否

Script Locations(Project scope)

通常说的「pre-generation」对应 phase.validation:模型已算完、代码还没生成,正是做工程自定义检查的位置。 要更早介入(改模型、补派生数据)则用 phase.calculation。

scriptTask("PreGenerationCheck", DV_GENERATION_STEP) {
    code { phase, generationType, resultSink ->
        if (phase.validation) {
            validation {
                resultCreation {
                    def id = createValidationResultIdForScriptTask(
                        9001, "Pre-generation check", EValidationSeverityType.ERROR)
                    def builder = newResultBuilder(id, "Dem event id 冲突")
                    builder.addErrorObject(bswmdModel(EcuC.DefRef).single)
                    resultSink.reportValidationResult(builder.buildResult())
                }
            }
        }
    }
}

两个容易踩的点:

  • 定义 ≠ 生效:DV_GENERATION_STEP 必须在 Project Settings 的 Generation Steps 里被引用, 否则文件加载了也不会执行;DV_ON_GENERATION_START 需要在 Script Locations 里注册, 且 scope 选 Project(Session 只对当前 GUI 会话有效)。

  • 别用 System.exit 或抛异常来阻止生成:那会杀掉 Config Core,日志里只剩一次中断。 用 resultSink 报 ERROR,失败原因会进生成结果,CI 也能读到。

CFG5 的 DVCfgCmd 没有 automation run 这类命令,脚本注册只能在 GUI 里做一次 (Project scope 会把引用写进工程,之后随工程走)。davinci_script_create 生成这两类模板时 会返回 next_steps,按步骤操作即可。

4.6 配置变更评审(CFG5)

用户:比较这两个变体的 ECUC 配置,告诉我改了什么、有没有风险

Agent:
1. davinci_ecuc_diff(before=".../VariantA/Config/ECUC/Dem/Dem.arxml",
                     after =".../VariantB/Config/ECUC/Dem/Dem.arxml")
   → counts / containers / changes / summary
2. davinci_ecuc_query(arxml=目标文件, module="Dem", value_contains="...")
   → 查同一模块的相关参数,判断单点改动是否破坏成组约束
3. davinci_ecuc_audit(arxml=目标文件)
   → 空容器、类型不符、悬空引用
4. davinci_cfg5_validate(project=".../VariantB/VariantB.dpa")
   → Vector 侧校验,与静态体检结论交叉验证
5. davinci_ecuc_export(arxml=目标文件, out_path=".../review.csv", confirm=true)
   → 附上扁平清单,供人工评审
6. 输出变更表 + 风险点 + 建议回归范围(哪些模块需要重新生成)

配套提示词 davinci_ecuc_review 固化了这套顺序,可直接在客户端调用。

4.7 按版本查规范(避免新文档套旧工程)

用户:DemEventId 的取值范围和依赖关系是什么?

Agent:
1. davinci_ar_version(paths=".../MyEcu")
   → project.release = "4.2.2"(high,来自 Settings/General.json)
   → mismatches = [NvM 4.0.3]:先提示这个模块的配置项可能已过期
2. davinci_spec_lookup(module="Dem", release="4.2.2", topic="DemEventId")
   → AUTOSAR_SWS_DiagnosticEventManager + 检索式 + R4.2.2 下载路径
3. davinci_ecuc_query(arxml=".../Config/ECUC/Dem/Dem.arxml",
                      pattern="/Dem/**/DemEventId")
   → 工程里实际配了哪些值,作为规范结论的落点
4. 回答时标注「AUTOSAR 4.2.2 SWS DiagnosticEventManager」;
   版本探不到就说无法确认,不拿最新版规范硬套

配套提示词 davinci_ar_spec_answer 固化了这套顺序。

4.8 判断一个文件该不该手改(生成物边界)

用户:Com_Cfg.h 里有个宏不对,我直接改这个文件行不行?

Agent:
1. davinci_generation_roots(project="D:/work/ecu/Demo.dvjson")
   → 生成目录 D:/work/ecu/GenData(source=project-setting,confidence=high)
2. davinci_generated_files(project=".../Demo.dvjson",
                           pattern=["**/Com_Cfg.h"], view="files")
   → category=generated
   → evidence: ["位于工程设置指定的生成目录", "配置生成文件命名(*_Cfg)"]
3. 结论:不要直接改。改 Config/ECUC 下的 Com 参数,再 davinci_project_generate
   重新生成;否则下次生成会被覆盖。
4. 如果命中 *_Callout.c 且 hint 提示「首次生成后可能人工维护」,
   才建议在生成目录里改,并说明它不会被下次生成覆盖。

配套提示词 davinci_generated_boundary 固化了这套判断顺序。

4.9 比较两个工程,把差异带回 DaVinci

用户:A 是上个版本,B 是这次改完的,看看改了哪些配置,给我一个能在 DaVinci 里跑的脚本。

Agent:
1. davinci_project_diff(left="D:/work/A", right="D:/work/B")
   → files: +2 -1 ~4 ↔1;settings 3 处;ECUC 改值 12 / 新增 1 / 删除 0
   → files.generated.counts.modified = 812:确认这是生成物,不进主表
2. 读 ecuc.auto(12 条可写)与 ecuc.manual(1 条新增参数、0 条删除)
   → 新增参数需要人工在 GUI 或 OrCreate 里添加
3. davinci_project_diff_script(left=..., right=..., mode="replay")
   → lint 0 error;assumptions 标出 /ActiveEcuC 路径前缀
4. 在 DaVinci 里先 dryRun:日志里全部 [resolved] 再传 --dryRun=false;
   出现 [unresolved] 时停下,检查 active_root 与容器 short-name
5. 需要回归时生成 mode="verify" 的脚本,CI 里加 --failOnDiff=true

配套提示词 davinci_project_diff_review 固化了这套顺序。

5. 安全模型

服务按「读宽松、写严格、改要确认」设计:

  1. 路径白名单:写入类路径必须位于 DAVINCI_MCP_ROOTS 内,.. 与符号链接在 resolve() 后校验,越界直接 path_rejected。只读输入(BSW 包、待导入 ARXML)默认允许外部路径,可用 DAVINCI_MCP_STRICT_PATHS=1 收紧。

  2. 无 shell:全部通过 subprocess.Popen(argv) 执行,参数中的 ;、|、$() 不会被解释。有单测覆盖注入场景。

  3. 扩展名校验:.dvjson / .dpa / .dcf / .arxml 分别对应不同操作;CFG5 服务拒绝非 .dpa 输入,避免拿错后端。

  4. 破坏性操作需确认:project update、cfg5 update/save、import arxml-artifacts、convert、stop --all、script run、cfg5 script install 必须 confirm=true。

  5. 单工程串行:同工程并发直接拒绝,防止 Config Core 写冲突。

  6. 超时与进程树清理:超时后 SIGTERM → SIGKILL 整个进程组(Windows 用 taskkill /T),不留僵尸 JVM。

  7. 审计:可选 JSONL 记录每次调用的 argv、cwd、退出码、耗时,便于团队追溯。

  8. 输出限流:stdout/stderr 上限可配,日志落盘后可分段读取,避免撑爆上下文。

  9. 脚本是任意代码:davinci_script_run 不做沙箱,只做路径白名单与确认;执行前先 dry_run=true,并确保工程已提交版本控制。

  10. ECUC 分析只读:只解析、不写回;导出文件必须落在 DAVINCI_MCP_ROOTS 内并需 confirm=true。解析在单线程中串行执行(py-armodel 用全局单例),带超时保护,不会卡住其他工具。

  11. 差异脚本默认不落地:davinci_project_diff_script 不传 out_path 时只返回文本;写文件必须 confirm=true。脚本自身默认 dryRun=true,即使被 davinci_script_run 执行也不会改工程。

6. 错误与退出码

所有工具返回统一信封,失败也不会抛 traceback:

{
  "ok": false,
  "action": "校验工程",
  "status": "failed",
  "exit_code": 1,
  "diagnostics": {"counts": {"error": 2, "warning": 1, "info": 1}},
  "top_modules": [{"module": "EcuC", "findings": 1}],
  "error": {"code": "failed", "message": "命令执行失败"},
  "hint": "优先查看 stderr_tail:常见原因是 license 未激活、BSW 包版本与工程不匹配、模型存在未解决引用。"
}

退出码

status

含义

0

ok

成功

1

failed

命令执行失败

2

usage_error

参数用法错误

6

usage_error

CFG5:命令行参数无效(模块路径无法识别)

130

cancelled

被取消

3

access_error

dvdevc:无法创建/修改路径

7

workspace_not_found

dvdevc:workspace 不存在

—

timed_out / spawn_error / project_busy / path_rejected / confirmation_required

服务层状态

7. 后台作业

davinci_project_generate(project, wait_seconds=120)
→ {"status": "running", "job_id": "job-1a2b3c4d", "log_path": "..."}

davinci_job_status("job-1a2b3c4d")
davinci_job_logs("job-1a2b3c4d", offset=0, max_chars=20000)   # 增量读取
davinci_job_cancel("job-1a2b3c4d")
  • 作业日志写在 DAVINCI_MCP_LOG_DIR,服务重启后日志仍在(内存中的作业记录会丢失)。

  • 并发上限 DAVINCI_MCP_MAX_JOBS,超出直接报错而不是排队——DaVinci 许可与 Config Core 都不适合高并发。

8. 已知限制

  • 许可证无法离线校验:doctor 只能提示,真正校验发生在首次 project 命令。

  • 诊断解析是启发式:不同版本输出格式可能变化,解析失败时仍返回原始 stdout_tail / stderr_tail,不会丢信息。

  • CFG5 的工程创建是模板克隆,不是从零生成:模板里的 SIP/BSW、MCU、编译器与模块集会被完整继承;要换 BSW 路径用 replacements 或 GUI Project Settings,换 MCU 只能在 GUI 里改。

  • 模板克隆不改写 .dcf:Developer 工作区按原名复制,避免 .dpa 里的引用失效;需要改名请在 Developer 中另存。

  • CFG5 的选项覆盖以 -h 为准:-v/-g/-u/Save 已封装;import、export、--syncContract 等通过 davinci_cfg5_run 透传,参数需自行确认。

  • CFG5 校验不支持按模块过滤:DVCfgCmd -v 没有 -m/-x,通用工具传入时会返回 ignored_options 而不是静默丢弃。

  • CFG5 没有 build 流水线:davinci_build 会明确拒绝 .dpa,请依次调用 cfg5_validate → cfg5_update? → cfg5_generate。

  • project_info 不是完整模型视图:.dvjson 只读 Settings/General.json,.dpa 只统计目录与文件数;精确信息请以 DaVinci GUI 为准。

  • 生成目录定位是启发式:.dvjson / Settings/*.json 的字段名没有公开 schema,工具按「键名含 generation/output/target 且含 dir/folder/path」匹配,并要求路径真实存在。找不到字段时退回默认布局;两者都没有就返回空,不猜。字段命名很特殊的工程请用 dirs 显式指定。

  • .dpa 内设置条目不保证可读:按 zip 条目扫描 JSON/XML/INI,遇到加密或私有编码会退化;归档内即使包含 Appl/GenData 条目也只提示、不列出,清单只针对磁盘目录。

  • 生成物分类以位置为主:位于工程设置指定的生成目录时,目录内文件默认算 generated——这符合「生成器输出」的语义,但不排除有人往该目录里放了手写文件;要更严格请用 pattern 缩小范围并看 evidence。

  • 文件头只读前 4 KB / 后 1 KB:生成标记写在文件尾部很远的位置时可能漏检;此时仍可由目录位置与命名给出分类。

  • *_Callout.c 等桩文件不等于可安全覆盖:它们初次由生成器产出,之后常由人工维护;工具只在 hint 里提示,不做「可编辑/不可编辑」的硬判断。

  • CFG5 的 Groovy 没有公开的无头入口:Vector 文档只描述了 GUI 的 Script Locations;DVCfgCmd 的公开选项里没有脚本执行。davinci_cfg5_script_install 只负责安装,批量执行请迁移到 CFG6。

  • JAR 反射只看签名、不看语义:能回答「有没有这个方法、参数是什么」,回答不了「这个方法在这里能不能调」(受作用域与运行时状态限制);方法体不解析,注解值不还原。

  • JAR 索引依赖安装目录布局:默认扫 plugins/*.jar 等常见位置,并把包名前缀限定为 com.vector;定制安装或换了包名时用 jars= 或 package_prefix="" 兜底。

  • Groovy 能力目录不是全量 API 索引:只收录官方文档有出处的入口(约 50 条),写模型 setter、Data Mining 查询语法、UI 控件 API 因无公开示例而刻意不收录;目录外的符号可能是对的,最终由 compile_check 判定。

  • Groovy 静态检查不是编译器:括号、scriptTask、危险 API 等规则能提前发现问题,但类型与 API 是否真实存在由 compile_check=true 决定。

  • dvdevc 子命令覆盖以官方交互手册为准:davinci_dev_run 提供白名单透传,遇到新子命令无需改代码。

  • ECUC 分析与 Vector 校验不是一回事:py-armodel 只做静态结构检查,不判断模块间语义约束、不执行生成;结论要与 cfg5_validate 交叉验证。

  • ECUC 分析不写回:writer 往返会丢 ANNOTATION-TEXT 的 XHTML 等内容,因此只提供只读查询/对比/导出。批量修改请用 Groovy 或 cfg5_update。

  • ECUC 解析对非法值零容忍:单个参数的类型错误会让整个文件解析失败,这是 py-armodel 的实现方式;报错会指出文件,需人工定位该值。

  • 版本探测不是 AUTOSAR 权威判定:xsi:schemaLocation 反映的是文件序列化时依据的 schema,工具重新保存后可能被升级;命名空间只能给出 4.x 兼容序列。工程设置的显式字段最可信,但没有该字段时结论只能到 medium。

  • AUTOSAR_00046.xsd 这类新命名不映射 release:5 位编号是 schema 修订号,与 release 的对应表由 AUTOSAR 站点维护;工具原样返回 schema_revision,不猜。

  • 模块版本是「描述文件版本」,不是 BSW 包版本:它说明模块定义/配置按哪个 AUTOSAR 版本序列化,不等于 MICROSAR 包或 MCAL 驱动自身的版本号。

  • .dpa 内部结构不公开:按 zip 条目做通用扫描(设置类文件优先,ARXML 提模块),遇到加密或私有编码会退化为文本扫描,找不到就返回 null。

  • SWS 文档名对照表是人工整理的:约 50 个常见模块,标了 origin: "curated";站点改版或模块拆分时文件名会变,检索式才是主路径。

  • 文件差异不解析大文件内容:超过 8 MB 的文件不计算 SHA-256;单侧哈希总量上限 512 MB,超出后只按大小 + 修改时间判断,置信度降为 low,同大小同时间的内容变化会漏报。

  • 生成物排除沿用 §3.9 的启发式:生成目录被改到工程目录之外、或目录名不在默认清单里时可能漏排,主表会混入生成文件;此时用 max_changes 之外先看 by_category 判断。

  • ECUC 语义差异受 py-armodel 限制:单个非法值会让整个文件解析失败,此时 ecuc.available=false、reason=parse_error,文件级结论仍然有效。

  • 回放脚本只写标量参数:新增/删除参数、容器移动、设置与文件差异都只列清单。dryRun 能证明路径可解析,不能证明类型一定可赋值;第一次 --dryRun=false 请在测试工程上做。

  • 模型路径前缀需要确认:默认 /ActiveEcuC 来自官方示例;不同工程的 Active ECU 容器名可能不同,[unresolved] 全量出现时先改 active_root。

  • .dpa 回放要解包:ARXML 解到临时目录解析,单条目上限 16 MB、总量 128 MB、最多 200 个文件;超出部分不参与语义对比。

9. 开发与测试

pip install -e ".[dev,ecuc]"
pytest -q

ECUC 解析类用例用 pytest.importorskip 语义做条件跳过:没装 py-armodel 时 只跳过解析相关用例,索引对比/查询的纯逻辑仍然会跑。

测试不依赖真实 DaVinci 安装:tests/fake_bin/ 下有三个行为一致的假 CLI(共 307 个用例),覆盖:

  • argv 拼装是否与官方语法一致(CFG6 的 -p= / -m=a,b,CFG5 的 -p <dpa> -v/-g/-u)

  • 退出码 1/2/3/6/7 的映射

  • 诊断解析(去重、文件/行号/模块提取)与 CFG5 ExecutionReport XML(含命名空间)

  • .dpa 自动路由、CFG5 参数白名单、.dpa 后缀拒绝

  • 超时杀进程、输出截断、无 shell 注入

  • 路径逃逸拦截

  • 项目锁、确认机制

  • 异步作业生命周期

  • Groovy 模板渲染、静态规则、automation list 编译检查、任务执行与失败识别、生成钩子签名与注册提醒、CFG5 安装

  • Groovy 能力目录:域覆盖、检索(中英文/按域)、单符号解析、源码核对(含 import 与字符串剥离)、MCP 注册

  • JAR 反射:常量池/修饰符/泛型描述符解析、包前缀过滤、坏 JAR 与超大条目容错、指纹缓存、类#方法 查询

  • ECUC 索引统计、通配查询、整数归一化、语义 diff(含容器移动)、结构体检、CSV 导出、依赖缺失降级

  • CFG5 模板克隆(复制范围、身份重写、自定义替换、空目录/嵌套目录拒绝、冒烟校验)

  • AUTOSAR 版本探测(schemaLocation / 工程设置 / ADMIN-DATA / 命名空间四级证据、模块冲突、.dpa 压缩包、坏文件不中断、大量容器的流式解析、规范检索式)

  • 模块资产定位(设置/参数/布局三层候选根、手册词形匹配、src/inc 静态代码与 entry_points、 生成目录内的同名代码标 generated_code、找不到时不猜、MCP 端到端)

  • 生成物清单(工程设置/归档/默认布局/目录名四层取证、generationMode 不误判、越界目录拦截、文件头与命名分类、Callout 提示、过滤/深度/截断、二进制文件不按文本解码)

  • 工程差异对比(文件改名识别、生成物排除与回填、设置键值展平、输入文件三层取证与角色分类、 CFG5 -u --input / CFG6 复制+project update -c 回放、BSW 缺失与归档降级、 ECUC 增删改与可写判定、.dpa 归档对比、依赖缺失与无 ARXML 降级、脚本渲染与转义、 confirm 与扩展名校验、cmd/sh/json 三种 CLI 输出)

  • MCP 工具/资源/提示词注册与 call_tool 端到端

tests/
├── fake_bin/dvcfg-b      # 假 Configurator 6 CLI
├── fake_bin/DVCfgCmd     # 假 Configurator 5 CLI(生成 ExecutionReport XML)
├── fake_bin/dvdevc       # 假 Developer CLI
├── conftest.py           # 临时工程 + 假环境夹具
├── test_runner.py        # 执行器
├── test_paths.py         # 路径策略
├── test_parsing.py       # 输出解析
├── test_configurator.py  # Configurator 服务
├── test_cfg5.py          # CFG5 服务、报告解析、路由
├── test_cfg5_create.py   # CFG5 模板克隆创建
├── test_groovy.py        # Groovy 模板、静态检查、执行
├── test_groovy_api.py    # Groovy 能力目录与源码核对
├── test_java_index.py    # JAR 反射:class 解析、泛型、缓存、服务层
├── test_ecuc.py          # ECUC 索引/查询/对比/体检/导出
├── test_arversion.py     # AUTOSAR 版本探测与规范定位
├── test_modassets.py     # 模块资产:Vector 手册与静态代码定位
├── test_genfiles.py      # 生成目录发现与生成物清单
├── test_projdiff.py      # 工程差异对比、输入文件取证与 Groovy/CLI 回放
├── test_developer.py     # Developer 服务
├── test_server.py        # MCP 层
├── data/java/            # JAR 夹具源码 + 构建脚本(build.sh,需 JDK 16+)
└── data/arversion/       # 版本探测夹具(4.2.2 / 4.0.3 / ADMIN-DATA / 截断文件 / 工程目录)

10. 目录结构

src/davinci_mcp/
├── cfg5_create.py          # CFG5 工程创建(模板克隆 + 身份重写)
├── cfg5_report.py          # CFG5 ExecutionReport XML 解析
├── cli.py                  # davinci-mcp serve / doctor / list-tools / config
├── config.py               # 环境变量、可执行文件发现(含 DVCfgCmd)
├── ecuc.py                 # ECUC 索引/查询/对比/体检(不依赖 armodel 亦可导入)
├── errors.py               # 结构化错误
├── groovy.py               # Groovy 模板 + 静态分析
├── groovy_api.py           # Groovy 能力目录(官方 API 索引 + 源码核对)
├── java_index.py           # JAR 反射:class 解析 / 索引缓存 / 检索
├── jobs.py                 # 后台作业 + 项目锁
├── models.py               # CommandResult、退出码语义
├── arversion.py            # AUTOSAR 版本探测:证据采集、汇总、规范定位
├── modassets.py            # 模块资产定位:Vector User Manual 与静态代码
├── genfiles.py             # 生成目录发现、文件分类、目录清单
├── projdiff.py             # 工程差异:文件/设置/输入文件/ECUC 四层对比、Groovy 与 CLI 回放渲染
├── parsing.py              # 诊断/导出器/工程摘要/产物扫描
├── paths.py                # 路径白名单
├── runner.py               # argv 执行器
├── server.py               # MCP 工具/资源/提示词装配
├── service_base.py         # 统一信封 + 作业编排
├── service_cfg5.py         # DVCfgCmd(CFG5)
├── service_configurator.py # dvcfg-b(CFG6)
├── service_developer.py    # dvdevc
├── service_arversion.py    # 版本探测服务:目录展开、扫描编排
├── service_modassets.py    # 模块资产服务:BSW 包解析、白名单校验
├── service_genfiles.py     # 生成物清单服务:路径白名单、结果汇总
├── service_projdiff.py     # 差异对比服务:解析编排、依赖降级、脚本落盘
├── service_ecuc.py         # ECUC 只读分析(可选依赖 py-armodel)
├── service_groovy.py       # Groovy 脚本生命周期
└── service_pipeline.py     # 多步流水线

11. 参考资料

License

MIT。本项目只封装公开的命令行接口,不包含任何 Vector 源码或二进制。

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    Enables AI coding agents and IDEs to lint, compile, syntax-check, and simulate Verilog/SystemVerilog designs through structured, token-efficient MCP tools with isolated containerized toolchains.
    4
    15 npm
    Apache 2.0
  • A
    license
    Not graded
    quality
    B
    maintenance
    Provides MCP tools for terminal session control, serial/SSH/Shell connections, workspace configuration, J-Link debugging, RTT logging, and UI interaction, enabling AI hosts to collaboratively operate embedded development workflows.
    AGPL 3.0
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables driving any installed CODESYS 3.5 version (SP18–SP22) from a single MCP server, automatically selecting the right install from each project file's saved version. Exposes 127 tools covering project and POU authoring, compile, online/runtime control, devices and tasks, symbol configuration, multi-device projects, and a version plus git release pipeline.
    4
    MIT