
深入解析 MCP Toolbox 的 neo4j-execute-cypher 工具任意 Cypher 执行与只读安全机制【免费下载链接】mcp-toolboxMCP Toolbox for Databases is an open source MCP server for databases.项目地址: https://gitcode.com/GitHub_Trending/ge/mcp-toolbox导读neo4j-execute-cypher是 MCP Toolbox for Databases 中面向 Neo4j 图数据库的通用查询工具它允许你以字符串参数的形式向 Neo4j 提交任意 Cypher 语句适用于预定义查询无法覆盖的动态交互场景。本文将完整讲解该工具的配置字段、cypher与dry_run两个运行时参数、只读模式的执行前安全拦截原理并结合仓库源码剖析 Cypher 查询分类器Query Classifier的实现细节帮助你在开发助手工作流中安全、灵活地集成 Neo4j 查询能力。About为什么需要一个通用 Cypher 执行工具在 neo4j-execute-cypher.md 的官方文档中该工具被定义为一个neo4j-execute-cypher工具会针对 Neo4j 数据库执行一个以字符串参数形式提供的任意 Cypher 查询。它被设计成一个灵活的工具用于在预定义查询不足以满足需求时与数据库交互。这意味着它与预编译的固定查询工具如工具集中的neo4j-cypher不同查询内容完全由调用方在运行时提供。从源码看该工具注册的资源类型为neo4j-execute-cypher见 neo4jexecutecypher.go并通过tools.Register机制挂载到工具箱中与neo4j-cypher、neo4j-schema共同构成 Neo4j 集成 的工具面。Cypher 采用标准 Neo4j Cypher 语法支持模式匹配pattern matching、过滤filtering、聚合aggregation等全部 Cypher 特性——例如MATCH (m:Movie {title: The Matrix}) RETURN m.released这样的查询可以直接透传给 Neo4j 执行。注意文档明确提示该工具面向带人参与human-in-the-loop的开发助手工作流不应用于生产环境的自主 Agent。因为任意 Cypher 执行天然具备数据修改能力需要在人工监督下使用。兼容的 Source 类型该工具只能绑定到neo4j类型的 source 上。源码通过接口约束实现这一校验见 neo4jexecutecypher.gotype compatibleSource interface { Neo4jDatabase() string // kept to ensure neo4j source RunQuery(context.Context, string, map[string]any, bool, bool) (any, error) }在ValidateSource中任何不实现该接口的 source 都会被拒绝并返回不是兼容类型的错误见 neo4jexecutecypher.go。这意味着该工具与 PostgreSQL、MySQL 等其他数据库 source 天然隔离你无需担心 Cypher 被误发送到非图数据库上。对应的neo4jsource 配置示例如下详见 source.mdkind: source name: my-neo4j-source type: neo4j uri: neo4js://xxxx.databases.neo4j.io:7687 user: ${USER_NAME} password: ${PASSWORD} database: neo4jfieldtyperequireddescriptiontypestringtrue必须为neo4juristringtrue连接 URI如bolt://localhost、neo4js://xxx.databases.neo4j.iouserstringtrue用于连接的 Neo4j 用户名如neo4jpasswordstringtrue该用户的密码如my-passworddatabasestringtrue要连接的 Neo4j 数据库名如neo4j从源码看neo4j.goConfig中五个字段全部带validate:required校验同时 newConfig 中把默认数据库设置为neo4j。初始化时会通过VerifyConnectivity验证连通性失败则关闭 driver 并报错见 neo4j.go。建议使用${ENV_NAME}环境变量替换语法存放用户名密码等敏感信息而不是把密钥硬编码进配置文件。配置一个 neo4j-execute-cypher 工具文档给出了完整的 YAML 配置示例。下面将其与源码字段逐一对齐并补充注解kind: tool name: query_neo4j type: neo4j-execute-cypher source: my-neo4j-prod-db readOnly: true description: | Use this tool to execute a Cypher query against the production database. Only read-only queries are allowed. Takes a single cypher parameter containing the full query string. Example: {{ cypher: MATCH (m:Movie {title: The Matrix}) RETURN m.released }}fieldtyperequireddescriptiontypestringtrue必须为neo4j-cypher注意文档原文此处为neo4j-cypher与 neo4j-cypher.md 页面对应从源码注册名看实际 type 应为neo4j-execute-cypher见 neo4jexecutecypher.gosourcestringtrue执行 Cypher 查询所绑定的 source 名称descriptionstringtrue传递给 LLM 的工具描述readOnlybooleanfalse若为true工具会拒绝 Cypher 查询中的任何写操作。默认false源码中Config的定义与之对应neo4jexecutecypher.go其中type、source为必填readOnly默认零值false还支持可选的annotations与继承自ConfigBase的authRequired字段。单元测试覆盖了基础配置与只读配置两种解析场景见 neo4jexecutecypher_test.go其中也展示了authRequired的用法kind: tool name: example_tool type: neo4j-execute-cypher source: my-neo4j-instance description: some tool description authRequired: - my-google-auth-service - other-auth-service工具初始化时neo4jexecutecypher.go会校验description非空随后注册两个运行时参数必填的字符串参数cypher和可选的布尔参数dry_run默认false。运行时参数cypher 与 dry_runcypher必填cypher是唯一的必填参数类型为字符串包含要执行的完整 Cypher 语句。调用时通过 JSON 传参例如{ cypher: MATCH (m:Movie {title: The Matrix}) RETURN m.released }在 Invoke 中工具会从参数表中取出cypher并做两次防御性校验若无法从参数表取出字符串类型返回 Agent 错误unable to cast cypher parameter ...若cypher为空字符串直接返回错误parameter cypher must be a non-empty string。dry_run可选dry_run是一个布尔参数默认false。置为true时工具会验证查询但不实际执行。底层实现是在 RunQuery 中给 Cypher 语句加上EXPLAIN前缀if dryRun { // Add EXPLAIN to the beginning of the query to validate it without executing cypherStr EXPLAIN cypherStr }EXPLAIN会让 Neo4j 生成执行计划而不真正执行语句因此 dry_run 模式适合在正式执行前校验语法、观察执行计划成本。dry_run 的返回结构为执行计划摘要见 neo4j.goexecPlan : map[string]any{ queryType: cf.Type.String(), statementType: summary.QueryType(), operator: plan.Operator(), arguments: plan.Arguments(), identifiers: plan.Identifiers(), childrenCount: len(plan.Children()), } if len(plan.Children()) 0 { execPlan[children] addPlanChildren(plan) }返回内容包含查询分类类型READ/WRITE、语句类型、根操作符、参数、标识符以及递归展开的子执行计划addPlanChildren递归收集每个子节点的 operator/arguments/identifiers/children_count可帮助开发者判断查询是否按预期走索引、成本是否可接受。注意dry_run 模式下分类classify与只读校验仍然先行执行因此对写查询同样会先被只读拦截见下文。只读模式与查询分类器执行前的安全拦截当readOnly: true时工具在执行前会分析传入的 Cypher 查询拒绝任何写操作如CREATE、MERGE、DELETE等。这一机制的完整调用链为Invoke(ctx, source, params) └─ source.RunQuery(ctx, cypher, nil, cfg.ReadOnly, dryRun) // neo4j.go └─ sourceClassifier.Classify(cypherStr) // classifier.go ├─ 规范化去注释、合并空白 ├─ 剔除字符串字面量 ├─ 统一多词关键字DETACH DELETE → DETACH_DELETE ├─ 提取 CALL 过程调用 ├─ 词法切分 → 对照读写关键词表/过程表 └─ 子查询 CALL { ... } 内的写操作检测 └─ if cf.Type WriteQuery readOnly → 报错拒绝关键拦截代码位于 neo4j.go// validate the cypher query before executing cf : sourceClassifier.Classify(cypherStr) if cf.Error ! nil { return nil, cf.Error } if cf.Type classifier.WriteQuery readOnly { return nil, fmt.Errorf(this tool is read-only and cannot execute write queries) }查询分类器实现在 classifier/classifier.go其设计原则在包注释中写得很明确采用保守策略默认把未知过程当作写操作以确保只读环境安全。识别的关键词范围内置的写关键词表classifier.goCREATE, MERGE, DELETE, DETACH DELETE, SET, REMOVE, FOREACH, CREATE INDEX, DROP INDEX, CREATE CONSTRAINT, DROP CONSTRAINT内置的读关键词表classifier.goMATCH, OPTIONAL MATCH, WITH, WHERE, RETURN, ORDER BY, SKIP, LIMIT, UNION, UNION ALL, UNWIND, CASE, WHEN, THEN, ELSE, END, SHOW, PROFILE, EXPLAIN注意DETACH DELETE、ORDER BY等多词关键字会被统一为下划线连接的单一 tokenDETACH_DELETE、ORDER_BY后再匹配且多词表按长度降序排列以保证长关键字优先替换、避免部分匹配误判见 populateKeywords。已知过程的读写归属除了关键字分类器还维护了两张过程前缀表按strings.HasPrefix前缀匹配写过程前缀classifier.goapoc.create, apoc.merge, apoc.refactor, apoc.atomic, apoc.trigger, apoc.periodic.commit, apoc.load.jdbc, apoc.load.json, apoc.load.csv, apoc.export, apoc.import, db.create, db.drop, db.index.create, db.constraints.create, dbms.security.create, gds.graph.create, gds.graph.drop读过程前缀classifier.goapoc.meta, apoc.help, apoc.version, apoc.text, apoc.math, apoc.coll, apoc.path, apoc.algo, apoc.date, db.labels, db.propertyKeys, db.relationshipTypes, db.schema, db.indexes, db.constraints, dbms.components, dbms.listConfig, gds.graph.list, gds.util保守兜底与置信度对于既不在读表也不在写表中的未知过程分类器采用启发式兜底过程名包含.get、.list、.show、.meta之一 → 判为读操作否则默认判为写操作并降低置信度至0.8防止只读环境下漏掉自定义插件的写过程见 classifier.go。分类结果带有置信度Confidence0.0~1.0单类型查询置信度 1.0混合读写如MATCH ... DELETE置信度降至 0.9未知过程判写时置信度 0.8。分类器还支持运行时扩展AddWriteProcedure/AddReadProcedure可动态注册自定义过程前缀适配带自定义插件的环境classifier.go。其他健壮性细节子查询检测查询包含CALL { ... }块时分类器用花括号配对定位子查询内容并对块内做整词写关键字匹配\bCREATE\b之类避免把ASSET里的SET误判为写操作见 hasWriteInSubquery。子查询内有写操作时即使外层是读语句也会整体判为 WRITE并追加WRITE_IN_SUBQUERY标记 token。忽略注释与字符串字面量规范化阶段先剔除//、/* ... */注释再把...、...字符串整体替换为STRING_LITERAL占位符避免关键词混在字符串内容中被误分类classifier.go。大小写不敏感统一转大写后匹配create、Create、CREATE均会被识别。测试用例覆盖了简单 MATCH、带 WHERE/ORDER BY/SKIP/LIMIT 的复杂读查询、UNION 查询、CREATE/MERGE/DETACH DELETE 写查询、CALL db.labels()读过程等典型场景见 classifier_test.go可作为理解分类行为的行为文档。完整示例从工具配置到执行流程结合 prebuilt-configs/tools/neo4j.yaml 的预置配置一个端到端的最小组合如下kind: source name: neo4j-source type: neo4j uri: ${NEO4J_URI} database: ${NEO4J_DATABASE} user: ${NEO4J_USERNAME} password: ${NEO4J_PASSWORD} --- kind: tool name: execute_cypher type: neo4j-execute-cypher source: neo4j-source description: Use this tool to execute Cypher queries. --- kind: tool name: get_schema type: neo4j-schema source: neo4j-source description: Use this tool to get the database schema. --- kind: toolset name: neo4j_database_tools tools: - execute_cypher - get_schema在这个配置中execute_cypher未设置readOnly默认允许写get_schema提供只读的库表结构探测两者组合成neo4j_database_tools工具集可一并暴露给 LLM。若改为readOnly: true则任何含写操作的调用都会在执行前被拦截并返回错误this tool is read-only and cannot execute write queries。完整的调用行为可归纳为MCP 请求携带cypher必填与可选的dry_run进入工具Invoke工具校验参数类型与非空转发给neo4jsource 的RunQuery分类器对 Cypher 做读/写分类含子查询与过程调用分析若readOnly且分类为 WRITE → 直接拒绝不触碰数据库若dry_run→ 前缀EXPLAIN后执行仅返回执行计划摘要否则正常执行逐条记录按列组装为map[string]any返回值经 helpers.ConvertValue 转换如节点、关系等图类型会被转换为可 JSON 化的表示。适用场景与限制适用场景开发助手需要动态构造查询如按对话内容拼 Cypher时用neo4j-execute-cypher覆盖任意查询需求需要对查询做先 EXPLAIN 后执行的成本预检时使用dry_run: true需要向 LLM 暴露受限的查询能力时设置readOnly: true防止数据被意外修改结合 neo4j-schema 工具先取 schema 再生成精确查询可显著降低无效调用。限制与注意点文档明确声明该工具面向 developer assistant human-in-the-loop 工作流不应用于生产环境的自主 Agent——任意 Cypher 执行意味着 LLM 拼出的语句可能触发非预期写操作分类器是关键词/前缀级别的静态分析无法替代数据库侧的权限控制。建议同时为 Neo4j 用户配置最小权限如只读账号形成纵深防御type字段在文档参考表中写作neo4j-cypher而源码注册名与配置文件实际使用的值均为neo4j-execute-cypherneo4jexecutecypher.go配置时请以源码实现为准未知自定义过程默认判写可能误伤只读的自定义过程——如需放行可通过分类器扩展点或选用neo4j-cypher等其他工具承载固定查询。延伸阅读工具定义与参数解析 neo4jexecutecypher.go查询执行与只读拦截 neo4j.go查询分类器实现 classifier.go分类器测试行为文档 classifier_test.goNeo4j source 文档 source.md预置配置示例 neo4j.yamlNeo4j 集成总览 docs/en/integrations/neo4j/_index.md【免费下载链接】mcp-toolboxMCP Toolbox for Databases is an open source MCP server for databases.项目地址: https://gitcode.com/GitHub_Trending/ge/mcp-toolbox创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考