From 0fb7ec3071e3f4d3cafd5b75eb018093b5ea4f46 Mon Sep 17 00:00:00 2001
From: Youssef Erradi
- * Returns a list of available tools for Oracle JDBC Log Analyzer.
- * The tools provided include:
- *
- *
- *
The returned {@link McpServerFeatures.SyncToolSpecification SyncToolSpecification} + * instances describe the following logical analyzers:
* - * @return a list of {@link McpServerFeatures.SyncToolSpecification SyncToolSpecification} instances representing the available tools. + *All tool results are serialized in JSON format as defined by the individual tool + * implementations.
+ * + * @return an immutable list containing the JDBC and RDBMS/SQLNet analyzer tool specifications + * to be registered with an MCP server */ public static List- * Builds and returns a {@link SyncToolSpecification SyncToolSpecification} - * for the {@code get-jdbc-stats} tool, which retrieves high-level statistics from an Oracle JDBC thin log file. - * The tool gathers information such as error count, the number of sent and - * received packets, and byte counts from the specified log file. - *
- * - * @return a {@link SyncToolSpecification SyncToolSpecification} instance for the {@code get-jdbc-stats} tool. - */ - private static SyncToolSpecification getStatsTool() { + private static SyncToolSpecification getJDBCAnalyzerTool() { return SyncToolSpecification.builder() .tool(McpSchema.Tool.builder() - .name("get-jdbc-stats") - .title("Get JDBC Stats") - .description("Return aggregated stats (error count, packets, bytes) from an Oracle JDBC thin log.") - .inputSchema(ToolSchemas.FILE_PATH_SCHEMA) + .name("jdbc-analyzer") + .title("Oracle JDBC Log Analyzer") + .description(JDBC_ANALYZER_DESCRIPTION) + .inputSchema(ToolSchemas.JDBC_ANALYZER_SCHEMA) .build()) .callHandler((exchange, callReq) -> Utils.tryCall( () -> { - final var filePath = String.valueOf(callReq.arguments().get(FILE_PATH)); - final var stats = new JDBCLog(filePath).getStats(); - return McpSchema.CallToolResult.builder() - .addTextContent(stats.toJSONString()) - .isError(false) - .build(); - })) - .build(); - } + final var args = callReq.arguments(); + final var action = String.valueOf(args.get("action")); - /** - *- * Builds and returns a {@link SyncToolSpecification SyncToolSpecification} for the {@code get-jdbc-queries} tool. - * This tool extracts all executed SQL queries from an Oracle JDBC thin log file. - * For each query, it provides the corresponding timestamp, execution time, connection id and tenant. - *
- * - * @return a {@link SyncToolSpecification SyncToolSpecification} instance for the {@code get-jdbc-queries} tool. - */ - private static SyncToolSpecification getQueriesTool() { - return SyncToolSpecification.builder() - .tool(Tool.builder() - .name("get-jdbc-queries") - .title("Get JDBC Queries") - .description("Get all executed queries from an Oracle JDBC thin log file, including the timestamp and execution time.") - .inputSchema(ToolSchemas.FILE_PATH_SCHEMA) - .build()) - .callHandler((exchange, callReq) -> Utils.tryCall(() -> { - final var filePath = String.valueOf(callReq.arguments().get(FILE_PATH)); - final var queries = new JDBCLog(filePath).getQueries(); - String results = queries.stream() - .map(JDBCExecutedQuery::toJSONString) - .collect(Collectors.joining(",", "[", "]")); - return McpSchema.CallToolResult.builder() - .addTextContent(results) - .isError(false) - .build(); - })) - .build(); - } + return switch (action) { + case "stats" -> { + final String filePath = String.valueOf(args.get(FILE_PATH)); + final var stats = new JDBCLog(filePath).getStats(); + yield McpSchema.CallToolResult.builder() + .addTextContent(stats.toJSONString()) + .isError(false) + .build(); + } + case "queries" -> { + final var filePath = String.valueOf(callReq.arguments().get(FILE_PATH)); + final var queries = new JDBCLog(filePath).getQueries(); + final var json = queries.stream() + .map(JDBCExecutedQuery::toJSONString) + .collect(Collectors.joining(",", "[", "]")); + yield McpSchema.CallToolResult.builder() + .addTextContent(json) + .isError(false) + .build(); + } + case "errors" -> { + final var filePath = String.valueOf(callReq.arguments().get(FILE_PATH)); + final var errors = new JDBCLog(filePath).getLogErrors(); + final var json = errors.stream() + .map(LogError::toJSONString) + .collect(Collectors.joining(",", "[", "]")); + yield McpSchema.CallToolResult.builder() + .addTextContent(json) + .isError(false) + .build(); + } + case "connection-events" -> { + final var filePath = String.valueOf(args.get(FILE_PATH)); + final var events = new JDBCLog(filePath).getConnectionEvents(); + final var json = events.stream() + .map(JDBCConnectionEvent::toJSONString) + .collect(Collectors.joining(",", "[", "]")); + yield McpSchema.CallToolResult.builder() + .addTextContent(json) + .isError(false) + .build(); + } + case "compare" -> { + final var filePath = String.valueOf(callReq.arguments().get(FILE_PATH)); + final var secondFilePath = String.valueOf(callReq.arguments().get(SECOND_FILE_PATH)); + final var comparison = new JDBCLog(filePath).compareTo(secondFilePath); + yield McpSchema.CallToolResult.builder() + .addTextContent(comparison.toJSONString()) + .isError(false) + .build(); + } + case "list-files" -> { + final var directoryPath = String.valueOf(args.get(FILE_PATH)); + final var directory = new File(directoryPath); + final var files = directory.listFiles(); + if (files == null || files.length == 0) + throw new IOException("No files found in the specified directory."); - /** - *
- * Builds and returns a {@link SyncToolSpecification SyncToolSpecification} for the get-jdbc-errors tool.
- * This tool processes a specified Oracle JDBC thin log file and extracts all reported errors.
- * Each error record includes details such as the stack trace and additional log context.
- *
get-jdbc-errors tool.
- */
- private static SyncToolSpecification getErrorsTool() {
- return SyncToolSpecification.builder()
- .tool(Tool.builder()
- .name("get-jdbc-errors")
- .title("Get JDBC Errors")
- .description("Get all reported errors from an Oracle JDBC thin log file, including stacktrace and log context.")
- .inputSchema(ToolSchemas.FILE_PATH_SCHEMA)
- .build())
- .callHandler((exchange, callReq) -> Utils.tryCall(() -> {
- final var filePath = String.valueOf(callReq.arguments().get(FILE_PATH));
- final var errors = new JDBCLog(filePath).getLogErrors();
- String results = errors.stream()
- .map(LogError::toJSONString)
- .collect(Collectors.joining(",", "[", "]"));
- return McpSchema.CallToolResult.builder()
- .addTextContent(results)
- .isError(false)
- .build();
- }))
- .build();
- }
-
-
- /**
- * - * Builds and returns a {@link SyncToolSpecification SyncToolSpecification} for the {@code list-log-files-from-directory} tool. - * This tool lists all Oracle JDBC log files present in the specified directory path. - *
- * - * @return a {@link SyncToolSpecification SyncToolSpecification} for the {@code list-log-files-from-directory} tool. - */ - private static SyncToolSpecification getListLogsDirectoryTool() { - return SyncToolSpecification.builder() - .tool(Tool.builder() - .name("list-log-files-from-directory") - .title("List Log Files From Directory") - .description("List all visible files from a specified directory, which helps the user analyze multiple files with one prompt.") - .inputSchema(ToolSchemas.FILE_PATH_SCHEMA) - .build()) - .callHandler((exchange, callReq) -> Utils.tryCall(() -> { - final var directoryPath = String.valueOf(callReq.arguments().get(FILE_PATH)); - final var directory = new File(directoryPath); - final var files = directory.listFiles(); - if (files == null || files.length == 0) { - throw new IOException("No files found in the specified directory."); - } - String results =Arrays.stream(files) - .filter(file -> !file.isHidden() && file.isFile()) - .map(File::getName) - .collect(Collectors.joining(",", "[", "]")); + final var json =Arrays.stream(files) + .filter(file -> !file.isHidden() && file.isFile()) + .map(File::getName) + .collect(Collectors.joining(",", "[", "]")); - return McpSchema.CallToolResult.builder() - .addTextContent(results) - .isError(false) + yield McpSchema.CallToolResult.builder() + .addTextContent(json) + .isError(false) + .build(); + } + default -> McpSchema.CallToolResult.builder() + .addTextContent("Unsupported action: " + action) + .isError(true) .build(); + }; })) .build(); } - /** - *- * Builds and returns a {@link SyncToolSpecification SyncToolSpecification} for the {@code jdbc-log-comparison} tool. - * This tool enables comparison of two Oracle JDBC log files. It analyzes the specified log files and provides a JSON report - * highlighting differences and similarities in performance metrics, encountered errors, and network-related information. - *
- * - * @return a {@link SyncToolSpecification SyncToolSpecification} instance that defines the {@code jdbc-log-comparison} tool. - */ - private static SyncToolSpecification logComparisonTool() { - return SyncToolSpecification.builder() - .tool(Tool.builder() - .name("jdbc-log-comparison") - .title("JDBC Log Comparison") - .description("Compare two JDBC log files for performance metrics, errors, and network information.") - .inputSchema(ToolSchemas.FILE_COMPARISON_SCHEMA) - .build()) - .callHandler((exchange, callReq) -> Utils.tryCall(() -> { - final var filePath = String.valueOf(callReq.arguments().get(FILE_PATH)); - final var secondFilePath = String.valueOf(callReq.arguments().get(SECOND_FILE_PATH)); - final var comparison = new JDBCLog(filePath).compareTo(secondFilePath); - return McpSchema.CallToolResult.builder() - .addTextContent(comparison.toJSONString()) - .isError(false) - .build(); - })) - .build(); - } - /** - *- * Builds and returns a {@link SyncToolSpecification SyncToolSpecification} for the {@code get-jdbc-connection-events} tool. - *
- * - * @return a {@link SyncToolSpecification SyncToolSpecification} instance for the {@code get-jdbc-connection-events} tool. - */ - private static SyncToolSpecification getConnectionEventsTool() { - return SyncToolSpecification.builder() - .tool(Tool.builder() - .name("get-jdbc-connection-events") - .title("Get JDBC Connection Events") - .description("Retrieve opened and closed JDBC connection events from the log file with timestamp and connection details.") - .inputSchema(ToolSchemas.FILE_PATH_SCHEMA) - .build()) - .callHandler((exchange, callReq) -> Utils.tryCall(() -> { - final var filePath = String.valueOf(callReq.arguments().get(FILE_PATH)); - final var events = new JDBCLog(filePath).getConnectionEvents(); - String results = events.stream() - .map(JDBCConnectionEvent::toJSONString) - .collect(Collectors.joining(",", "[", "]")); - return McpSchema.CallToolResult.builder() - .addTextContent(results) - .isError(false) - .build(); - })) - .build(); - } - /** - *
- * Builds and returns a {@link SyncToolSpecification SyncToolSpecification} for the get-rdbms-errors tool.
- * This tool processes a specified Oracle RDBMS/SQLNet trace file to extract all reported errors.
- * Each extracted error record includes relevant details, such as error messages and context information,
- * and is serialized in JSON format.
- *
- * Builds and returns a {@link SyncToolSpecification SyncToolSpecification} for the get-rdbms-packet-dumps tool.
- * This tool extracts packet dump information from a specified RDBMS/SQLNet trace file that matches a given connection ID.
- * Each packet dump record includes its associated details and is serialized in JSON format.
- *
- * This schema requires a "filePath" property, which should be an absolute path or a URL to an Oracle JDBC log file. - */ - static final String FILE_PATH_SCHEMA = """ - { - "type": "object", - "properties": { - "filePath": { - "type": "string", - "description": "Absolute path or an URL to the Oracle JDBC log file." - } - }, - "required": ["filePath"] - } - """; - - /** - * JSON schema for file comparison operations. - *
- * This schema requires "filePath" and "secondFilePath" properties, which should be absolute paths or URLs to Oracle JDBC log files. - */ - static final String FILE_COMPARISON_SCHEMA = """ - { - "type": "object", - "properties": { - "filePath": { - "type": "string", - "description": "Absolute path or an URL to the 1st Oracle JDBC log file" - }, - "secondFilePath": { - "type": "string", - "description": "Absolute path or an URL to the 2nd Oracle JDBC log file" - } - }, - "required": ["filePath", "secondFilePath"] - } - """; + static final String JDBC_ANALYZER_SCHEMA = """ + { + "type": "object", + "properties": { + "action": { + "type": "string", + "enum": ["stats", "queries", "errors", "connection-events", "list-files", "compare"], + "description": "Operation to perform on JDBC logs." + }, + "filePath": { + "type": "string", + "description": "Absolute path or URL to an Oracle JDBC thin log file." + }, + "secondFilePath": { + "type": "string", + "description": "Absolute path or URL to the second Oracle JDBC thin log file (compare only)." + }, + "directoryPath": { + "type": "string", + "description": "Absolute path to a directory containing log files (list-files only)." + } + }, + "required": ["action"], + "oneOf": [ + { "properties": { "action": { "const": "compare" } }, "required": ["filePath", "secondFilePath"] }, + { "properties": { "action": { "const": "list-files" } }, "required": ["directoryPath"] }, + { "properties": { "action": { "const": "stats" } }, "required": ["filePath"] }, + { "properties": { "action": { "const": "queries" } }, "required": ["filePath"] }, + { "properties": { "action": { "const": "errors" } }, "required": ["filePath"] }, + { "properties": { "action": { "const": "connection-events" } }, "required": ["filePath"] } + ] + } + """; - /** - * JSON schema for RDBMS tools operations. - *
- * This schema requires "filePath" and "connectionId" properties, where "filePath" is an absolute path or a URL to an RDBMS/SQLNet trace file, and "connectionId" is a connection ID string.
- */
- static final String RDBMS_TOOLS_SCHEMA = """
- {
- "type": "object",
- "properties": {
- "filePath": {
- "type": "string",
- "description": "Absolute path or an URL to the RDBMS/SQLNet trace file"
- },
- "connectionId": {
- "type": "string",
- "description": "Connection ID string"
- }
- },
- "required": ["filePath", "connectionId"]
- }
- """;
+ static final String RDBMS_ANALYZER_SCHEMA = """
+ {
+ "type": "object",
+ "properties": {
+ "action": {
+ "type": "string",
+ "enum": ["errors", "packet-dumps"],
+ "description": "Operation to perform on an RDBMS/SQLNet trace file."
+ },
+ "filePath": {
+ "type": "string",
+ "description": "Absolute path or URL to the RDBMS/SQLNet trace file."
+ },
+ "connectionId": {
+ "type": "string",
+ "description": "Connection ID string (required for packet-dumps)."
+ }
+ },
+ "required": ["action", "filePath"],
+ "oneOf": [
+ { "properties": { "action": { "const": "packet-dumps" } }, "required": ["connectionId"] },
+ { "properties": { "action": { "const": "errors" } } }
+ ]
+ }
+ """;
/**
* JSON schema for similarity search operations.
From 2178da2fa8de72913c9e32e1803a5dae7caee5e7 Mon Sep 17 00:00:00 2001
From: Youssef Erradi log-analyzerJDBC and RDBMS log analysis
- get-jdbc-stats, get-jdbc-queries, get-jdbc-errors,
- get-jdbc-connection-events, list-log-files-from-directory,
- jdbc-log-comparison, get-rdbms-errors, get-rdbms-packet-dumps
+ jdbc-analyzer, rdbms-analyzer
@@ -153,7 +151,7 @@ _Note: Each tool belongs to exactly one built-in toolset. Enabling a toolset ena
**Common Configurations:**
- `-Dtools=mcp-admin` - Admin and runtime configuration tools
-- `-Dtools=log-analyzer` - Log analysis only (no database required)
+- `-Dtools=log-analyzer` - Oracle JDBC Log and RDBMS/SQLNet trace file analysis only (no database required)
- `-Dtools=database-operator` - Database operations and SQL execution
- `-Dtools=rag` – Vector similarity search
- `-Dtools=mcp-admin,log-analyzer` - Admin + log analysis
@@ -189,21 +187,25 @@ These tools help monitor database health and performance:
### 3.5. Oracle JDBC Log Analysis
-These tools operate on Oracle JDBC thin client logs:
+The `jdbc-analyzer` tool covers the Oracle JDBC thin client logs analysis using the `action` parameter, it supports the following values:
-* **`get-jdbc-stats`**: Extracts performance statistics including error counts, sent/received packets and byte counts.
-* **`get-jdbc-queries`**: Retrieves all executed SQL queries with timestamps and execution times.
-* **`get-jdbc-errors`**: Extracts all errors reported by both server and client.
-* **`get-jdbc-connection-events`**: Shows connection open/close events.
-* **`list-log-files-from-directory`**: List all visible files from a specified directory, which helps the user analyze multiple files with one prompt.
-* **`jdbc-log-comparison`**: Compares two log files for performance metrics, errors, and network information.
+* **`action=stats`**: Extracts performance statistics including error counts, sent/received packets and byte counts.
+* **`action=queries`**: Retrieves all executed SQL queries with timestamps and execution times.
+* **`action=errors`**: Extracts all errors reported by both server and client.
+* **`action=connection-events`**: Shows connection open/close events.
+* **`action=compare`**: Compares two log files for performance metrics, errors, and network information.
+* **`action=list-files`**: List all visible files from a specified directory, which helps the user analyze multiple files with one prompt.
+
+The tool returns results serialized in JSON format.
### 3.6. RDBMS/SQLNet Trace Analysis:
-These tools operate on RDBMS/SQLNet trace files:
+The `rdbms-analyzer` tool operate on RDBMS/SQLNet trace files based on the chosen `action`:
+
+* **`action=rdbms-errors`**: Extracts errors from RDBMS/SQLNet trace files.
+* **`action=packet-dumps`**: Extracts packet dumps for a specific connection ID.
-* **`get-rdbms-errors`**: Extracts errors from RDBMS/SQLNet trace files.
-* **`get-rdbms-packet-dumps`**: Extracts packet dumps for a specific connection ID.
+Each extracted record includes relevant details/context and is returned serialized in JSON format.
### 3.7. Vector Similarity Search (RAG)
@@ -332,7 +334,7 @@ This is the mode used by tools like Claude Desktop, where the client directly la
"-Ddb.url=jdbc:oracle:thin:@your-host:1521/your-service",
"-Ddb.user=your_user",
"-Ddb.password=your_password",
- "-Dtools=get-jdbc-stats,get-jdbc-queries",
+ "-Dtools=jdbc-analyzer",
"-Dojdbc.ext.dir=/path/to/extra-jars",
"-jar",
"
No
Comma-separated allow-list of tool or toolset names to enable (case-insensitive).
-
- You can pass individual tools (e.g. get-jdbc-stats, read-query) or any of the following built-in toolsets:
+ You can pass individual tools (e.g. jdbc-analyzer, read-query) or any of the following built-in toolsets:
You can also define your own YAML mcp-admin — server discovery and runtime configuration tools (list-tools, edit-tools)database-operator — database operations, transactions, monitoring, and execution plans (read-query, write-query, table, transaction, db-ping, db-metrics-range, explain-plan).log-analyzer — all JDBC log and RDBMS/SQLNet analysis tools (get-jdbc-stats, get-jdbc-queries, get-jdbc-errors, list-log-files-from-directory, jdbc-log-comparison, get-jdbc-connection-events, get-rdbms-errors, get-rdbms-packet-dumps)log-analyzer — all JDBC log and RDBMS/SQLNet analysis tools (jdbc-analyzer and rdbms-analyzer)rag — similarity-searchtoolsets: and reference them here.
Use * or all to enable everything. If omitted, all tools are enabled by default.
+ mcp-admin,log-analyzer or reportingmcp-admin, log-analyzer or reporting
@@ -681,7 +683,6 @@ podman run --rm \
-Dhttps.port=45451 \
-DcertificatePath=[path/to/certificate] \
-DcertificatePassword=[password] \
- -Dtools=get-jdbc-stats,get-jdbc-queries \
-Ddb.url=jdbc:oracle:thin:@your-host:1521/your-service \
-Ddb.user=your_user \
-Ddb.password=your_password" \
@@ -709,7 +710,6 @@ podman run --rm \
-e JAVA_TOOL_OPTIONS="\
-Dtransport=http \
-Dhttps.port=45451 \
- -Dtools=get-jdbc-stats,get-jdbc-queries \
-Ddb.url=jdbc:oracle:thin:@your-host:1521/your-service \
-Ddb.user=your_user \
-Ddb.password=your_password \
@@ -738,7 +738,7 @@ In this configuration, Claude Desktop runs `podman run --rm -i ...à and connect
"-i",
"-v", "/absolute/path/to/ext:/ext:ro",
"-e",
- "JAVA_TOOL_OPTIONS=-Dtools=get-jdbc-stats,get-jdbc-queries -Ddb.url=jdbc:oracle:thin:@your-host:1521/your-service -Ddb.user=your_user -Ddb.password=your_password -Dojdbc.ext.dir=/ext -DconfigFile=/config/config.yaml",
+ "JAVA_TOOL_OPTIONS=-Ddb.url=jdbc:oracle:thin:@your-host:1521/your-service -Ddb.user=your_user -Ddb.password=your_password -Dojdbc.ext.dir=/ext -DconfigFile=/config/config.yaml",
"oracle-db-mcp-toolkit:1.0.0"
]
}
ojdbc.ext.dir