内容
<div align="center">
[English](README.md) | [Español](README.es.md)
# 工具列表
[MCP](https://modelcontextprotocol.io) 服务器,适用于 **Oracle 数据库**,使用 Spring Boot 和 Spring AI 构建。
[](https://opensource.org/licenses/MIT)
[](https://openjdk.org/)
[](https://spring.io/projects/spring-boot)
[](https://spring.io/projects/spring-ai)
[](https://www.oracle.com/database/)
[](https://modelcontextprotocol.io)
[](https://github.com/zademy/mcp-oracle-database/commits/main)
[](https://deepwiki.com/zademy/mcp-oracle-database)
[](https://github.com/zademy/mcp-oracle-database/stargazers)
让任何与 MCP 兼容的客户端(Claude Desktop, Cursor, Cline, Continue, VS Code, Windsurf, …)**检查** Oracle 模式并**运行 SQL** — 安全。
</div>
<p align="center">
<a href="images/info.png"><img src="images/info.png" width="100%"></a>
</p>
---
## 为什么选择 mcp-oracle-db?
- **设计安全** — 唯一的权限障碍是一个**最小权限 Oracle 用户**。没有应用层 SQL 网关;Oracle 自己拒绝每个 `CREATE`/`ALTER`/`DROP`/`GRANT`/… 并返回 `ORA-01031`。
- **70 种工具**,涵盖模式检查、性能诊断、索引/查询建议、数据助手、DML、执行计划、模式图、PL/SQL 和系统。
- **无 Web 端口** — 仅 STDIO 传输。永远不会暴露 HTTP/SSE 服务器。
- **虚拟线程** — Java 26 虚拟线程,是阻塞 JDBC 的自然选择。
- **存储库中无秘密** — 凭证来自环境变量。
**适用于谁?** DBAs、后端开发人员和 AI 辅助工作流,需要一个本地的、读重型 Oracle 伴侣:探索模式、诊断性能、预览 DML,并让 LLM 运行即席 SQL,而无需冒着结构更改的风险。
## 它能做什么
**已执行**
- 模式读取 — 元数据、DDL 源、PL/SQL 源、序列、约束、分区、通过 `V$` 视图的性能诊断。
- DML — `INSERT`、`UPDATE`、`DELETE`、`MERGE` 在现有表上。
- PL/SQL 调用 — `call_procedure`(需要目标上的 `GRANT EXECUTE`)。
- 元数据注释 — `COMMENT ON ...`。
**被 Oracle 拒绝**(最小权限用户无 DDL/DCL 权限)
- 所有结构化 DDL — 所有 `CREATE ...` 表单、`ALTER`、`DROP`、`TRUNCATE`、`RENAME`。
- 所有 DCL — `GRANT`、`REVOKE`、`PURGE`、`FLASHBACK`、`LOCK TABLE`、`AUDIT`、`NOAUDIT`、`ANALYZE`。
## 目录
- [为什么选择 mcp-oracle-db?](#为什么选择mcp-oracle-db?)
- [它能做什么](#它能做什么)
- [需求](#需求)
- [快速入门](#快速入门)
- [1. 创建最小权限 Oracle 用户](#1-创建最小权限oracle用户)
- [2. 配置凭证(环境变量)](#2-配置凭证环境变量)
- [3. 构建](#3-构建)
- [4. 连接你的 MCP 客户端](#4-连接你的mcp客户端stdio)
- [快速首个会话](#快速首个会话)
- [MCP 客户端配置](#mcp客户端配置)
- [配置参考](#配置参考)
- [SQL 审计日志](#sql审计日志)
- [架构](#架构)
- [工具参考](#工具参考)
- [安全模型](#安全模型)
- [测试](#测试)
- [故障排除和 FAQ](#故障排除和faq)
- [限制和注意事项](#限制和注意事项)
- [贡献和代理工作流](#贡献和代理工作流)
- [许可证](#许可证)
## 需求
- **JDK 26**
- **Apache Maven 3.9+**(附带的 `mvnw` 包装器足够)
- **Oracle 数据库 12c+**(针对 19c / 23ai 驱动程序进行测试)
- 一个支持 STDIO 的 **MCP 客户端**(Claude Desktop, Cursor, Cline, Continue, VS Code, Windsurf, …)
## 快速入门
### 1. 创建最小权限 Oracle 用户
以 DBA 身份运行 `db/setup_least_privilege_user.sql`。首先编辑 `&` 占位符。
```bash
# Linux / macOS
sqlplus system/<dba-password>@//<host>:1521/<service> @db/setup_least_privilege_user.sql
```
```cmd
:: Windows (cmd / PowerShell)
sqlplus system/<dba-password>@//<host>:1521/<service> @db\setup_least_privilege_user.sql
```
它创建一个具有 `CREATE SESSION`、`SELECT_CATALOG_ROLE` 和针对目标模式表的逐个对象 `SELECT`/`INSERT`/`UPDATE`/`DELETE` 授予权限的用户(以及 `SELECT` 视图和序列)。它故意授予 **没有** DDL 和 **没有** 表空间配额。
### 2. 配置凭证(环境变量)
| 变量 | 含义 | 示例 |
| --- | --- | --- |
| `ORACLE_DB_URL` | 薄 JDBC URL | `jdbc:oracle:thin:@//db.host:1521/ORCLPDB1` |
| `ORACLE_DB_USERNAME` | 来自步骤 1 的最小权限用户 | `mcp_user` |
| `ORACLE_DB_PASSWORD` | 该用户的密码 | `s3cret` |
| `ORACLE_POOL_SIZE` | HikariCP 最大池大小(可选,默认 `7`) | `7` |
> **服务器使用哪个模式?** 没有 `schema` 设置。在 Oracle 中,模式等于连接的用户,因此默认模式是您配置的 `ORACLE_DB_USERNAME`。由于服务器通过 `ALL_*` 视图进行检查,因此它可以看到该用户具有授予权限的 **任何** 模式 — 将所需模式名称作为工具参数传递(例如 `list_tables(schema="HR")`)。哪些模式是可见的,完全由 `db/setup_least_privilege_user.sql` 中的授予权限控制。
### 3. 构建
```bash
# Linux / macOS
./mvnw clean package -DskipTests
```
```powershell
# Windows (PowerShell)
.\mvnw.cmd clean package -DskipTests
```
这会生成 `target/mcp-oracle-db-0.0.1-SNAPSHOT.jar`(Spring Boot 可执行 jar)。
### 4. 连接你的 MCP 客户端(STDIO)
下面的 JSON 形状是 Claude Desktop、Cursor、Cline、Windsurf 和 Continue 使用的事实上的标准。有关每种客户端的确切配置文件路径,请参见 [MCP 客户端配置](#mcp客户端配置)。
```json
{
"mcpServers": {
"oracle-db": {
"command": "/path/to/jdk/bin/java",
"args": ["-jar", "/absolute/path/mcp-oracle-db-0.0.1-SNAPSHOT.jar"],
"env": {
"ORACLE_DB_URL": "jdbc:oracle:thin:@//db.host:1521/ORCLPDB1",
"ORACLE_DB_USERNAME": "mcp_user",
"ORACLE_DB_PASSWORD": "s3cret"
}
}
}
}
```
保存后重启客户端。使用 `test_connection` 工具验证,该工具会报告数据库版本、名称、当前用户、当前模式和实例。
### 快速首个会话
一旦客户端显示服务器已连接,请按顺序尝试以下操作:
1. **`test_connection`** — 确认可达性和连接的用户/模式。
2. **`list_tables(schema="HR")`** — 查看您可以访问的表。
3. **`describe_table(schema="HR", table="EMPLOYEES")`** — 列、类型、可空性。
4. **`get_sample_data(schema="HR", table="EMPLOYEES")`** — 前 N 行,无风险。
5. **`run_query(sql="SELECT department_id, COUNT(*) FROM \"HR\".\"EMPLOYEES\" GROUP BY department_id")`**
— 即席 SQL,由 `max-rows` 限制。
## MCP 客户端配置
所有 STDIO 客户端共用同一个服务器块,如 [步骤 4](#4-连接你的mcp客户端stdio) 所示。它们的区别仅在于 **位置**:
| 客户端 | 配置文件 |
| --- | --- |
| **Claude Desktop** | macOS `~/Library/Application Support/Claude/claude_desktop_config.json` · Windows `%APPDATA%\Claude\claude_desktop_config.json` | `"mcpServers"` |
| **Cursor** | `.cursor/mcp.json`(项目)或 `~/.cursor/mcp.json`(全局) | `"mcpServers"` |
| **Cline**(VS Code) | `…/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json` | `"mcpServers"`,设置 `"disabled": false` |
| **Windsurf** | `~/.codeium/windsurf/mcp_config.json`(Windows:`%USERPROFILE%\.codeium\windsurf\mcp_config.json`) | `"mcpServers"` |
| **Continue** | `~/.continue/config.yaml`(或存储库中的 `.continue/config.json`) | `"mcpServers"` |
| **VS Code**(MCP,1.102+) | 工作区中的 `.vscode/mcp.json` | 使用 `"servers"`,并带有 `"type": "stdio"` |
> 路径可能会在客户端版本之间发生变化 — 如果不确定,请查看客户端自己的文档。重要的是 `command` / `args` / `env` 块对于所有客户端都是相同的。
**VS Code 注意事项** — 其模式使用 `servers` 代替 `mcpServers`,每个条目需要 `"type": "stdio"`:
```json
{
"servers": {
"oracle-db": {
"type": "stdio",
"command": "/path/to/jdk/bin/java",
"args": ["-jar", "/absolute/path/mcp-oracle-db-0.0.1-SNAPSHOT.jar"],
"env": {
"ORACLE_DB_URL": "jdbc:oracle:thin:@//db.host:1521/ORCLPDB1",
"ORACLE_DB_USERNAME": "mcp_user",
"ORACLE_DB_PASSWORD": "s3cret"
}
}
}
}
```
## 配置参考
可选的调优位于 `application.yaml` 下的 `oracle.mcp`:
| 属性 | 含义 | 默认值 |
| --- | --- | --- |
| `max-rows` | `SELECT` 返回的行数的全局上限 | `1000` |
| `query-timeout-seconds` | 每语句超时 | `120` |
| `default-sample-rows` | `get_sample_data` 返回的行数 | `10` |
通过 `LOG_LEVEL`(默认 `WARN`)和 `APP_LOG_LEVEL`(默认 `INFO`)进行日志记录级别。 请记住,**stdout 是 JSON-RPC 通道** — 日志记录到 stderr/file,永远不会输出到 stdout。
### SQL 审计日志
按需 SQL 审计日志。当启用时,发送到 Oracle 的每个 SQL 语句都追加到 `.txt` 文件 — 每个会话一个文件。
| 变量 | 含义 | 默认值 |
| --- | --- | --- |
| `MCP_AUDIT_ENABLED` | 启用审计子系统(`true`/`false`) | `false` |
| `MCP_AUDIT_DIR` | 审计日志文件目录 | `./mcp-audit-logs` |
#### 在 MCP 客户端中启用
将两个变量添加到 MCP 服务器条目的 `env` 块中 — 这是您需要修改的唯一位置。Claude Desktop / Cursor 的示例(`claude_desktop_config.json` 或 `.cursor/mcp.json`):
```json
{
"mcpServers": {
"oracle-db": {
"command": "/path/to/jdk/bin/java",
"args": ["-jar", "/absolute/path/mcp-oracle-db-0.0.1-SNAPSHOT.jar"],
"env": {
"ORACLE_DB_URL": "jdbc:oracle:thin:@//db.host:1521/ORCLPDB1",
"ORACLE_DB_USERNAME": "mcp_user",
"ORACLE_DB_PASSWORD": "s3cret",
"MCP_AUDIT_ENABLED": "true",
"MCP_AUDIT_DIR": "/var/log/mcp-oracle-db"
}
}
}
}
```
保存后 **重启客户端**,以便它重新启动具有新环境的 MCP 服务器。然后,在 `MCP_AUDIT_DIR` 中为每个会话创建一个 `.txt` 文件,并在每次服务器向 Oracle 启动 SQL 时追加。
在不使用客户端的情况下快速验证:直接运行 jar:
```bash
# Linux / macOS
MCP_AUDIT_ENABLED=true MCP_AUDIT_DIR=./mcp-audit-logs \
ORACLE_DB_URL=jdbc:oracle:thin:@//host:1521/SVC \
ORACLE_DB_USERNAME=mcp_user ORACLE_DB_PASSWORD=... \
java -jar target/mcp-oracle-db-0.0.1-SNAPSHOT.jar
```
```powershell
# Windows (PowerShell) — 在同一个 shell 中设置环境变量,然后启动
$env:MCP_AUDIT_ENABLED="true"; $env:MCP_AUDIT_DIR="./mcp-audit-logs"
$env:ORACLE_DB_URL="jdbc:oracle:thin:@//host:1521/SVC"
$env:ORACLE_DB_USERNAME="mcp_user"; $env:ORACLE_DB_PASSWORD="..."
java -jar target/mcp-oracle-db-0.0.1-SNAPSHOT.jar
```
文件名格式:`<serverName>-<dd-MM-yyyy>-<sessionId8>-log.txt`。
每个条目记录工具名称、参数、SQL 文本、结果、行数和持续时间:
```
===== 2026-06-27T14:30:52.884 =====================================
tool : get_sample_data
params : schema=HR, table=EMPLOYEES, rows=10
kind : Select
type : READ
sql : SELECT * FROM "HR"."EMPLOYEES" FETCH FIRST 10 ROWS ONLY
outcome : OK
rows : 10
duration : 23 ms
-------------------------------------------------------------------
```
**注意:**
- 审计文件包含 SQL 文本 **包括字面值和参数值** — 保护审计目录。
- 默认情况下禁用;关闭时零开销(无文件,无 I/O)。
- STDIO 安全 — 仅写入文件系统,从不输出到 stdout。
## 架构
严格分层。依赖关系指向内部(工具 → 服务 → 持久性)。审计方面观察每个到达 `OracleDataAccess` 的 SQL,而不修改 SQL 文本或结果。
```mermaid
flowchart TD
Client["MCP 客户端<br/>(Claude Desktop, Cursor, Cline, …)"]
subgraph Server["mcp-oracle-db (Spring Boot · STDIO)"]
Tools["@McpTool 端点<br/><i>tools/*Tools.java</i>"]
Services["服务<br/><i>Metadata · Query · DML · Plsql ·<br/>Performance · IndexAdvisor · Graph · …</i>"]
Access["OracleDataAccess<br/><i>JdbcTemplate · named-param · callable</i>"]
Audit["审计方面<br/><i>SqlAuditAspect · ToolAuditAspect (MDC)</i>"]
Tools --> Services --> Access
Audit -. 观察 .-> Access
end
Oracle[("Oracle 数据库<br/>最小权限用户<br/>= 唯一障碍")]
Client <-->|JSON-RPC via STDIO| Tools
Access --> Oracle
Oracle -. "ORA-01031 on DDL/DCL" .-> Access
```
## 工具参考
**70 种工具**,按类别分组。_只读_ 永远不会修改数据;_写入_ 在数据库上执行。
(待翻译)
### 架构自省 _(只读)_
| 工具 | 描述 |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `list_schemas` | 列出当前连接可见的所有 Oracle 架构(用户)。 |
| `list_tables` | 列出表;可选架构和不区分大小写的 LIKE 名称模式(默认为 `%`)。 |
| `list_views` | 列出视图;可选架构和 LIKE 名称模式。 |
| `describe_table` | 表的列:名称、数据类型、是否可为空、默认值和注释。在针对未经验证的表执行 SELECT/INSERT/UPDATE 之前调用。 |
| `list_indexes` | 表上的索引及其列、唯一性和状态。 |
| `list_constraints` | 表上的约束(主键、外键、唯一约束、检查约束)及其列和引用。 |
| `list_sequences` | 序列及其范围、增量、最后一个数字、循环标志和缓存大小(来自 `ALL_SEQUENCES`,而非 `DBA_SEQUENCES`)。可选架构。 |
| `get_sequence_info` | 一个序列的元数据(范围、增量、最后一个数字、缓存/顺序标志),来自 `ALL_SEQUENCES`。只读:不会消耗 `NEXTVAL`。 |
| `table_exists` | 如果表存在(通过 `ALL_TABLES`;不考虑视图),则返回 `true`。请代替 `run_query {SELECT 1 FROM ALL_TABLES ...}` 使用。 |
| `list_triggers` | 触发器及其类型、触发事件、目标表和状态。可选架构。 |
| `list_objects` | 数据库对象;可选架构和对象类型过滤器。 |
| `search_objects` | 通过不区分大小写的 LIKE 名称模式搜索对象;可选类型过滤器。 |
| `get_ddl` | 通过 `DBMS_METADATA` 获取对象的 DDL。所有 3 个参数均必填(`schema`、`name`、`type`);只读。类型:TABLE、VIEW、INDEX、SEQUENCE、PROCEDURE、FUNCTION、PACKAGE、PACKAGE BODY、TRIGGER、TYPE、SYNONYM、DB LINK。 |
| `describe_plsql` | PL/SQL 对象:其参数和完整源代码。 |
| `call_procedure` | _(写)_ 执行 PL/SQL 存储过程、函数或包子程序,带有类型化的 IN/OUT/INOUT 参数;支持 `SYS_REFCURSOR` OUT/返回值和函数返回值。PL/SQL BOOLEAN/RECORD/TABLE/VARRAY/OBJECT 被拒绝,并提供包装指导。需要目标对象上的 `GRANT EXECUTE` 权限。 |
### 扩展自省 _(只读)_
| 工具 | 描述 |
| ------------------------- | ---------------------------------------------------------------------------------- |
| `list_materialized_views` | 物化视图及其刷新模式、方法、最后刷新时间和陈旧度。 |
| `list_mview_logs` | 表上定义的物化视图日志。可选架构。 |
| `list_synonyms` | 私有和公共同义词及其解析的目标和数据库链接。 |
| `list_partitions` | 分区表的分区(名称、位置、高值、行数、压缩)。 |
| `list_subpartitions` | 复合分区表的子分区。 |
| `list_ind_partitions` | 表索引的分区(状态、叶块、不同键)。 |
| `list_db_links` | 当前用户可见的数据库链接。 |
| `list_procedures` | 存储过程、函数、包和类型;可选过滤器。 |
| `list_types` | 用户定义的类型及其类型代码、属性、方法和超类型。 |
| `list_dependencies` | 给定对象所依赖的对象(适用于影响分析)。 |
| `list_invalid_objects` | 状态为无效的对象(损坏的代码需要重新编译)。 |
| `list_external_tables` | 外部表及其访问驱动程序、目录、拒绝限制和参数。 |
| `list_directories` | Oracle 目录对象及其文件系统路径。 |
| `list_lob_columns` | LOB 列及其段、缓存、SECUREFILE 标志和保留。 |
| `list_scheduler_jobs` | `DBMS_SCHEDULER` 作业及其状态、运行/失败次数、下一次运行、重复间隔。 |
| `list_scheduler_job_runs` | 最近的 `DBMS_SCHEDULER` 作业运行详情:状态、持续时间、错误代码。 |
### PL/SQL 和优化器统计 _(只读)_
| 工具 | 描述 |
| ------------------- | -------------------------------------------------------------------------- |
| `get_plsql_errors` | PL/SQL 单元的编译错误。对于诊断损坏的代码至关重要。 |
| `get_table_stats` | 表的优化器统计信息(行数、块数、平均行长度、最后分析时间)。 |
| `get_column_stats` | 列的优化器统计信息(NDV、密度、空值、直方图类型)。 |
| `get_histogram` | 列的直方图端点(偏度基数)。 |
| `get_session_privs` | 当前连接的系统权限(直接 + 通过角色)。 |
| `get_session_roles` | 当前连接启用的角色,带有管理员/默认标志。 |
### 性能诊断 _(只读,V$ 视图)_
| 工具 | 描述 |
| ----------------------- | ------------------------------------------------------------------------------- |
| `list_active_sessions` | 当前活动的会话(用户、机器、程序、已用时间)。可选过滤器。 |
| `list_blocked_sessions` | 当前被阻塞的会话,带有阻塞器和等待事件。 |
| `list_locks` | 持有和请求的 DML/事务/用户锁,带有锁定对象和模式。 |
| `get_session_sql_text` | 会话执行的完整 SQL 文本(sid,serial#)。 |
| `list_top_sql` | 按 buffer_gets / disk_reads / elapsed / executions / cpu 排序的 top-N SQL。 |
| `get_wait_events` | 当前的等待事件,来自 `V$SESSION_WAIT`。可选 sid 和等待类过滤器。 |
| `get_session_longops` | 正在运行的长操作,带有进度 % 和预计时间。可选 sid。 |
| `get_instance_info` | 实例信息:名称、主机、版本、启动时间、状态。 |
| `get_database_info` | 数据库信息:名称、日志模式、打开模式、角色、闪回状态。 |
| `get_system_stats` | 来自 `V$SYSSTAT` 的累积系统统计信息。 |
| `get_db_time_model` | 来自 `V$SYS_TIME_MODEL` 的时间模型(DB CPU、DB 时间、解析时间)。 |
| `get_parameter` | 来自 `V$PARAMETER` 的初始化参数。可选名称 LIKE 模式。 |
| `list_datafile_io` | 数据文件及其大小、物理读取/写入和平均 IO 时间。 |
### 索引和查询建议 _(只读)_
| 工具 | 描述 |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `list_unused_indexes` | 带有列和最佳努力使用情况的索引(`likely_unused` 是/否/未知)。DBA 必须运行 `ALTER INDEX ... MONITORING USAGE` 才能获得明确答案。 |
| `suggest_index` | 通过 `EXPLAIN PLAN` 分析 SQL;提出一个 `CREATE INDEX` 作为文本(从不执行)。仅在 DBA 审查后手动应用。 |
| `run_sql_tuning_advisor` | 运行 `DBMS_SQLTUNE` 并返回其文本报告。需要 `ADVISOR` 权限(参见设置脚本,第 8 节);否则返回指导。 |
### 数据助手 _(读取/检测)_
| 工具 | 描述 |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `count_rows` | 表的总行数 — 适用于此任务的正确工具;不要使用 `run_query`。无谓词(无隐藏 SQL 表面)。对于过滤计数,请使用带 `SELECT COUNT(*) ... WHERE ...` 的 `run_query`。 |
| `get_next_sequence_value` | 序列的 `NEXTVAL`。**有副作用**:推进计数器,值无法重用。当 `cache_size` > 0 时,验证返回的值是否已存在于目标表中。 |
| `validate_fk_integrity` | 违反表上外键的孤行;每个外键的孤行计数(0 = 正常)。 |
| `find_duplicates` | 按列分组的重复行,带有计数。可选最小计数。 |
| `find_free_id` | 表列中不存在的最小可用正 id(1..maxRange);可选 `excludeTable` 检查第二个表(外键场景)。如果范围已满,返回 `null`。 |
### SQL 和数据 _(在数据库上执行)_
| 工具 | 描述 |
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `run_query` | 运行单个 `SELECT`(由 `max-rows` 限制;可选 `offset`/`limit` 进行分页)。`CONNECT BY`/`WITH`(CTE)可能被解析器拒绝;请优先使用 `MINUS` 或客户端计算。 |
| `execute_dml` | 运行单个 `INSERT`/`UPDATE`/`DELETE`/`MERGE` 并自动提交;返回受影响的行数。每调用一次一个语句(无 PL/SQL 块、多语句或 DDL)。 |
| `execute_dml_preview` | `UPDATE`/`DELETE` 的非执行试运行 — 行数 + 将受影响的示例行。 |
| `execute_dml_rollback_first` | 在立即回滚的事务中执行 DML;返回实际行数而不持久化。 |
| `get_sample_data` | 预览表的首 N 行。 |
| `explain_plan` | 通过 `DBMS_XPLAN` 返回 Oracle 执行计划。需要 `PLAN_TABLE`。 |
### 架构影响图 _(只读)_
| 工具 | 描述 |
| ---------------------- | ----------------------------------------------------------------------------------------------- |
| `get_fk_graph` | 架构(或一个表)的外键关系,以 JSON 边 + Mermaid 图显示。 |
| `get_dependency_graph` | 对象依赖图(引用或被对象引用的对象),以 JSON + Mermaid 显示。 |
### 元数据注释 _(写)_
| 工具 | 描述 |
| ------------------- | ------------------------------------------------- |
| `comment_on_table` | 添加/替换表的注释(自己的架构)。 |
| `comment_on_column` | 添加/替换列的注释(自己的架构)。 |
### 系统
| 工具 | 描述 |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `test_connection` | 验证连接性;报告版本、名称、用户、架构和实例。 |
| `oracle_mcp_health_report` | 五个独立的就绪性探测(连接性、版本、目录角色、无效对象、服务器配置);聚合 `UP` / `DEGRADED` / `DOWN`。 |
### MCP 资源 _(URI 可寻址,只读)_
| URI | 返回 |
| ---------------------------------------------- | ---------------------------------------------------------------------------------- |
| `oracle://schema/{schema}/table/{table}` | 列级描述(名称、类型、是否可为空、默认值、注释)。 |
| `oracle://schema/{schema}/object/{object}/ddl` | DDL 源(自动检测类型 — 表、视图、包、过程等)。 |
| `oracle://schema/{schema}/plsql/{object}` | PL/SQL 源代码。 |
| `oracle://audit/session/{id}` | 会话 SQL 审计日志(`id` = 8 字符十六进制;对活动会话使用 `current`)。 |
### MCP 提示 _(指导模板)_
| 名称 | 目的 |
| ------------------------ | --------------------------------------------------------------------------------------------------------------------- |
| `review-sql-performance` | 对 SQL 语句进行结构化的性能评审。 |
| `explain-schema` | 对 Oracle 模式(表、列、关系、关键对象)进行有指导的探索。 |
| `debug-invalid-plsql` | 诊断损坏的 PL/SQL — 无效对象、错误代码、源位置。 |
| `safe-dml-plan` | 安全地计划 DML 更改(预飞行、干燥运行、执行后)。 |
| `data-quality-audit` | 审计数据质量(完整性、唯一性、参照完整性、有效性)。 |
| `oracle-sql-style` | 服务器的规范 Oracle SQL 编写规则 — 防止常见的解析错误(ORA-00923/00936/00904/00911/00933)。 |
### MCP 补全 _(URI / 提示参数自动补全)_
共 13 种补全 — 模式名称(6)、表名称(3)、对象名称(3)和审计会话 ID(1)。根据 MCP 规范,补全仅限于资源 URI 变量和提示参数。
## 安全模型
单层安全:**最小权限 Oracle 用户是唯一的障碍。**
没有应用层 SQL 网关 — `SqlGuard` 被故意删除。
工具发送的每个语句都会逐字逐句地在 Oracle 上执行,Oracle 的权限模型决定了允许或拒绝。
服务器以专用的 Oracle 用户身份连接,拥有 `CREATE SESSION` + `SELECT_CATALOG_ROLE` + 每个对象的 `SELECT`/`INSERT`/`UPDATE`/`DELETE` 授予权限,
`EXECUTE` 权限授予特定的过程和包(按需),**没有** DDL/DCL 权限或表空间配额。任何 `CREATE`/`ALTER`/`DROP`/`GRANT`/`REVOKE`/`TRUNCATE` 操作都会返回 Oracle 错误(通常为 `ORA-01031: insufficient privileges`),并作为解释性消息返回给客户端。
```
AI SQL ──▶ OracleDataAccess ──▶ Oracle (最小权限用户)
│ │
│ Oracle 强制允许/拒绝
│ (DDL/DCL 操作返回 ORA-01031)
▼ ▼
结果 / 错误字符串返回给 MCP 客户端
```
所有内部元数据查询都使用带有命名参数(`:param`)的 `ALL_*` 视图。标识符会经过验证和双引号处理(请参见 `SqlIdentifiers`)。
每个工具调用一个语句 — 拒绝批处理。
## 测试
该套件是分层的,因此大部分测试在每次提交时运行,无需数据库,**且实时 Oracle 路径是可选的**。
**第一层 — 单元测试 + 烟雾测试(每次 `./mvnw test` 执行,无需数据库)。** 跨 `SqlIdentifiers`、`IndexAdvisor`、`Graph`、`SystemService` 运行健康检查、`AuditLog` 读取器 + 编写器、每个工具/资源/提示/补全,以及 `McpOracleDbApplicationSmokeTest`,它在内存 H2(Oracle 兼容)数据源上启动**完整**的 Spring 上下文,并断言所有 70 个 `@McpTool` 端点在 11 个工具主机上注册。启动回归(错误的 logback 配置、缺少的 bean、损坏的自动配置)在此处捕获。
**第二层 — 端到端 MCP STDIO 工具(可选,需要 Oracle)。** `McpStdioE2ETest` 将构建的 jar 作为子进程启动,进行真正的 MCP `initialize` 握手,列出工具,并对您配置的每个表运行仅限 SELECT 的检查(`describe_table`、`run_query`、`count_rows`),然后断言 Oracle 拒绝 `CREATE TABLE`(权限不足)。它是双重控制的,因此它不会意外运行:
1. 将 `src/test/resources/application-e2e.example.yaml` 复制到 `application-e2e.yaml`(gitignored)并填写 jar 路径、Oracle 凭证、模式和 `tables: [...]` 数组。
2. 使用 `mcp-e2e` 配置文件运行:
```bash
# Linux / macOS
./mvnw test -Pmcp-e2e # 或在 Windows 上运行 run-e2e.bat(首先构建 jar)
```
```powershell
# Windows (PowerShell)
.\mvnw.cmd test -Pmcp-e2e
```
**环境控制的集成测试。** 完整的上下文/集成测试(`McpOracleDbApplicationTests.contextLoads`)仅在设置 `ORACLE_DB_URL` 时运行,因此 `./mvnw test` 无需数据库即可通过。
```bash
ORACLE_DB_URL=... ORACLE_DB_USERNAME=... ORACLE_DB_PASSWORD=... ./mvnw test
```
## 故障排除和常见问题
**运行 `CREATE`/`ALTER`/`DROP`/`GRANT` 时出现 `ORA-01031: insufficient privileges` 错误。**
这是**设计如此**,不是错误。最小权限用户没有 DDL/DCL 权限和表空间配额,因此 Oracle 会拒绝该语句。如果您确实需要结构更改,请作为 DBA 运行 — **不要**扩大 MCP 用户的权限(参见[安全模型](#security-model))。
**出现 `ORA-12541: TNS:no listener` / `ORA-12514: TNS:listener … service` 错误。** `ORACLE_DB_URL` 中的 JDBC URL 错误或数据库无法访问。请检查主机、端口和服务名称。建议使用 EZ-connect 格式 `jdbc:oracle:thin:@//host:1521/SERVICE`(无需 `tnsnames.ora`)。
**客户端显示服务器“启动失败”/无输出。** 标准输出是 JSON-RPC 通道 — 任何 stray `System.out` 打印都会损坏帧。服务器出于这个原因禁用了 Spring 横幅(`spring.main.banner-mode=off`);如果您修改了配置,请保持关闭。日志仅输出到 stderr/文件。
**`explain_plan` 返回 Oracle 错误。** 它需要对 `PLAN_TABLE` 的写访问权限。授予它(参见可选行 `db/setup_least_privilege_user.sql`,第 5 节)或跳过该工具。
**数据库重启后连接池耗尽/挂起。** HikariCP 配置了 Oracle JDBC 套接字超时(`oracle.jdbc.readTimeout`)以回收死连接。如果您覆盖 `application.yaml`,请保持读取超时大于 `query-timeout-seconds` 但小于 MCP `request-timeout`(150s)。
**服务器内省哪个模式?** 没有 `schema` 设置 — 默认模式为 `ORACLE_DB_USERNAME`。将任何可访问的模式作为工具参数传递(例如 `describe_table(schema="HR", table="EMPLOYEES")`)。可见性受设置脚本中的授予权限限制。
**我可以在一个调用中运行多个 SQL 语句吗?** 不 — 每个工具调用一个语句。批处理、PL/SQL 块和`;` 链被拒绝。这使得执行模型可预测且连接池健康。
## 限制和注意事项
- 仅 STDIO 传输(本地使用)。不公开 HTTP/SSE 服务器。
- `explain_plan` 需要对 `PLAN_TABLE` 的写访问权限(参见设置脚本中的可选授予权限)。如果没有它,该工具将返回 Oracle 错误。
- 每个工具调用一个语句 — 拒绝批处理。
- 读取访问权限受限于最小权限用户在 `ALL_*` 视图中可以看到的内容。
- **JSqlParser 4.9 仅限尽力而为** — 它在 `DmlService` 中标记 DML 类型(`INSERT`/`UPDATE`/`DELETE`/`MERGE`,否则为 `UNKNOWN`)。它不再控制任何内容;Oracle 是权威的。
- **Oracle JDBC:** BOM 为 `com.oracle.database.jdbc:ojdbc-bom:23.26.2.0.0`。`orai18n` 不在 Central 下该组 — 它被省略;`ojdbc17` 单独工作。
## 许可证
[MIT](LICENSE) © Sadot Hdz. Moreno
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器