OraViz MCP
OraViz MCP is a read-only, visualization-first MCP server for Oracle AI Database that lets you query, profile, and chart data.
execute_query – run read-only
SELECT/WITHqueries and get a compact markdown table with a metadata header and preview caps.list_tables – list tables and views in the current (or a specified) schema.
get_table_schema – get column names, types, length, nullability, and primary-key membership for a table/view.
sample_table_data – fetch a small sample of rows (default 10, configurable) from a table.
get_table_details – retrieve owner, tablespace, optimizer stats (e.g.,
NUM_ROWS,LAST_ANALYZED), and optionally an exact row count.profile_table – get per-column stats (non-null, distinct, min, max, avg) to decide which chart to use.
create_chart – run a read-only SQL query and render the result as a PNG chart (
bar,line,area,scatter,pie,histogram; README also describesvectorwith PCA), returning the image plus a short data preview.
All tools enforce read-only SQL, bounded result sizes, per-cell truncation, and context‑engineered output to keep agent token usage low.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@OraViz MCPprofile the sales table and show revenue by region as a bar chart"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
OraViz MCP is pab1it0/adx-mcp-server reimagined for Oracle AI Database -- a
deliberately tiny alternative to the broad official Oracle MCP servers. It speaks SQL, profiles tables, and turns result
sets into PNG charts any MCP client can show. Seven read-oriented tools, no Oracle client libraries (python-oracledb
thin mode talks straight to Oracle AI Database 26ai Free or any newer release).
Two ideas shape everything:
Visualization first. The headline tool runs your query and returns an actual chart image plus a short data preview -- not a wall of rows.
Context engineering. Agents pay for every token a tool returns, so OraViz never dumps a result set. Results are preview-capped, rendered as one compact markdown table with a metadata header, and large values (CLOB, BLOB, VECTOR) are summarised. Raw LOBs are never read.
Deploy with a dedicated Oracle reader account. Network transports require verified bearer tokens; stdio uses local OS trust. See SECURITY.md for the security boundaries and deployment checklist.
Visualization at a Glance
Related MCP server: Oracle ADB AI Agent MCP Server
Why OraViz?
Charts, not query dumps --
create_chartrenders bar, line, area, scatter, pie, histogram, and vector (PCA) charts with an Oracle-red palette and returns the PNG as MCP image content.Context-engineered results -- bounded previews with explicit
truncatedmetadata, one header per table instead of repeated JSON keys, CLOB/BLOB/VECTOR summarised, per-cell truncation.Profile before you plot --
profile_tablereturns per-column nulls, distinct counts, min/max/avg so the model can pick the right chart without fetching rows.Conservative query admission -- one
SELECT/WITHwith a reviewed built-in function allowlist; unreviewed calls with parentheses, writes, PL/SQL, database links, sequences, and locking are denied. Bare parameterless routines and routines inside views/synonyms can escape lexical detection. OracleREADgrants and review of inherited/PUBLICexecution privileges are essential.ORACLE_CALL_TIMEOUTbounds each database round trip.Controlled surface -- 7 tools with an operator allowlist, strict inputs, bounded concurrency, authenticated network transports, and metadata-only JSON audit logs on stderr (stdout stays clean for stdio).
Zero client install -- python-oracledb thin mode; no Oracle Instant Client, no
ORACLE_HOME, no tnsnames.
The Context Contract
Every row-returning tool follows the same rules, and the test suite asserts them:
Rule | Default | Env knob |
Query preview size ( | 25 rows |
|
Hard row cap per query (charts included) | 500 rows |
|
Longest cell before | 500 chars |
|
Database round-trip timeout (not a whole-tool deadline) | 60 s; range 1–300, cannot disable |
|
Result columns | 64; maximum 200 |
|
Combined text + serialized JSON structured content / PNG limit | 256,000 characters / 2,000,000 bytes | Fixed |
Concurrent tool calls per process | 4; range 1–32 |
|
Metadata header per result |
| -- |
A tool result therefore looks like this instead of a 25-dictionary JSON array:
4 row(s) | columns: REGION, REVENUE
| REGION | REVENUE |
|---|---|
| East | 573932 |
| North | 502897 |
| South | 432190 |
| West | 360759 |Raw CLOB/NCLOB/BLOB/BFILE locators render as <LOB> without reading their contents; byte values are
summarized, VECTOR(384) renders as <VECTOR(384)>, and midnight timestamps as dates. For more rows, pass
max_rows explicitly -- and the server still stops at the hard cap.
Numeric settings have bounded defaults (at most 5,000 rows and 4,096 characters per cell). Invalid numeric environment settings warn and fall back to defaults. Over-limit MCP responses are rejected, including when a rendered table was already truncated but the combined response exceeds the budget. Data mirrored in text and structured JSON counts in both representations. Row/output caps do not bound database CPU or total execution time; see resource limits.
Tools
Tool | Returns | Context cost |
| Read-only SQL result as a compact markdown table (preview-capped) | Bounded by preview cap |
| Tables and views in the current (or a given) schema | One small table |
| Columns, types, length, nullability, primary-key membership | One small table |
| First rows of a table |
|
| Owner, tablespace, optimizer stats ( | Single row |
| Per-column stats: non-null, nulls, distinct, min, max, avg | ~1 line per column |
| PNG chart image + short data preview | Image + ≤5 preview rows |
How create_chart maps columns
The first column is the x-axis (or the labels for pie and vector charts); numeric columns after it become series. That makes the chart contract simple and SQL-driven:
SELECT region, ROUND(SUM(revenue), 2) AS revenue
FROM oraviz.sales_demo
GROUP BY region
ORDER BY revenue DESCcreate_chart(sql=..., chart_type="bar", title="Revenue by region")SELECT product_name, embedding FROM oraviz.product_vectorscreate_chart(sql=..., chart_type="vector", title="Product embeddings")bar/line/area-- label column plus one or more numeric series (up to 8 series; bar values are annotated when the chart is small)scatter-- first two numeric columnspie-- label column plus one numeric column; more than 12 slices are grouped into "Other"histogram-- the first numeric column, auto-binnedvector-- the first VECTOR column is projected to two dimensions with PCA (dense and sparse vectors both work); the first non-vector column labels the points, and each axis names the share of variance its component explains
Quick Start
1. Start Oracle AI Database 26ai Free
# Disposable local development database; the admin password is NOT the MCP password.
read -rsp 'Database admin password: ' ORAVIZ_DB_ADMIN_PASSWORD
export ORAVIZ_DB_ADMIN_PASSWORD
docker compose up -d
unset ORAVIZ_DB_ADMIN_PASSWORDThe container takes a couple of minutes to initialize. docker ps shows (healthy) when it is ready.
The listener is published only on 127.0.0.1:1530. The database stores data in a named volume.
The floating database image is for this demo; pin a reviewed digest for controlled deployments.
2. (Optional) Load the demo schema
Create an owner only for setup, then give a separate reader access to the two demo tables. The SQL below uses password placeholders: replace them privately with separate generated passwords. Do not reuse the legacy passwords or broad grants in the demo script's historical header.
docker exec -it oraviz-oracle sqlplus -L system@//localhost:1521/FREEPDB1At the SQL prompt (admin use is limited to provisioning):
CREATE USER oraviz IDENTIFIED BY "REPLACE_WITH_OWNER_SECRET"
DEFAULT TABLESPACE USERS QUOTA 20M ON USERS;
GRANT CREATE SESSION, CREATE TABLE TO oraviz;
CREATE USER oraviz_reader IDENTIFIED BY "REPLACE_WITH_READER_SECRET";
GRANT CREATE SESSION TO oraviz_reader;
EXIT;Load the deterministic 96-row SALES_DEMO and six-row PRODUCT_VECTORS tables as the owner.
The script drops and recreates these tables; use it only in this disposable schema.
docker cp examples/demo-sales.sql oraviz-oracle:/tmp/oraviz-demo-sales.sql
docker exec -it oraviz-oracle sqlplus -L oraviz@//localhost:1521/FREEPDB1At the owner SQL prompt:
@/tmp/oraviz-demo-sales.sql
GRANT READ ON oraviz.sales_demo TO oraviz_reader;
GRANT READ ON oraviz.product_vectors TO oraviz_reader;
EXIT;The initial DROP TABLE statements can report missing tables on a fresh schema.
Only ORAVIZ_READER is used by the MCP server. For production, grant READ on
approved tables or reviewed views and audit inherited permissions; never use a schema owner or admin.
3. Point your MCP client at the server
Replace REVIEWED_COMMIT_SHA with an audited commit ID. Inject ORACLE_PASSWORD into the MCP host's
protected process environment; it is intentionally absent from the shareable client configuration.
{
"mcpServers": {
"oraviz": {
"command": "uvx",
"args": ["--from", "git+https://github.com/jasperan/oraviz-mcp@REVIEWED_COMMIT_SHA", "oraviz-mcp"],
"env": {
"ORACLE_USER": "oraviz_reader",
"ORACLE_DSN": "localhost:1530/FREEPDB1"
}
}
}
}{
"mcpServers": {
"oraviz": {
"command": "uv",
"args": ["--directory", "/path/to/oraviz-mcp", "run", "oraviz-mcp"],
"env": {
"ORACLE_USER": "oraviz_reader",
"ORACLE_DSN": "localhost:1530/FREEPDB1"
}
}
}
}docker build -t oraviz-mcp .{
"mcpServers": {
"oraviz": {
"command": "docker",
"args": ["run", "--rm", "-i", "--network", "host",
"-e", "ORACLE_USER", "-e", "ORACLE_PASSWORD", "-e", "ORACLE_DSN",
"oraviz-mcp"],
"env": {
"ORACLE_USER": "oraviz_reader",
"ORACLE_DSN": "localhost:1530/FREEPDB1"
}
}
}
}--network host is a Linux local-demo convenience for reaching the loopback database.
For a deployment, use a dedicated private network and restrict egress as described in SECURITY.md.
Inject the reader password at runtime, and use a reviewed image digest when distributing the image.
4. Ask for a chart
"Profile ORAVIZ.SALES_DEMO, then chart total revenue by region from ORAVIZ.SALES_DEMO."
The model will call profile_table, pick a chart type, run create_chart, and you get a rendered image back.
Configuration
Variable | Description | Default |
| Dedicated reader with | -- |
| Password for the user (required) | -- |
| Database hostname |
|
| Listener port |
|
| Service name |
|
| Full EZConnect descriptor; overrides host/port/service | -- |
| Wallet config directory (Autonomous Database / mTLS) | -- |
| Wallet location | -- |
| Wallet password | -- |
| Preview size, 1–5,000, also capped by max rows |
|
| Hard row cap per query, 1–5,000 |
|
| Per-cell truncation limit, 1–4,096 |
|
| Result column cap, 1–200 |
|
| Admitted calls per process, 1–32 |
|
| Comma-separated exact names from the seven tools above; empty/unknown entries reject startup | All seven |
| TCP connect timeout, seconds |
|
| Per database round-trip timeout, seconds, 1–300; cannot disable |
|
|
|
|
| Bind host for network transports |
|
| Bind port for network transports |
|
| Required network JWT issuer, HTTPS URL | -- |
| Required network JWT resource audience | -- |
| Required network signing-key endpoint, HTTPS URL | -- |
| Required network scopes, space-separated (e.g. | -- |
| Optional public HTTPS base URL for discovery, excluding | -- |
|
|
|
| structlog level number |
|
Copy .env.template to .env with umask 077 -- the server loads it via python-dotenv.
Keep it untracked, never source it as shell code, and use process environment injection for literal
secrets containing ${...}. Existing process environment settings take precedence.
All network transports (http, sse, streamable-http) require auth, including loopback and proxy use.
Bearer tokens need a valid RS256 signature, issuer, audience, expiry, nonempty signed sub, applicable nbf, and required scopes.
All authenticated users share the configured Oracle principal; this is not per-user or multitenant data
authorization. TLS, private networking, gateway limits, audit retention, and host approval for sensitive
reads/exports remain deployment responsibilities. See the network configuration example.
Architecture
oraviz-mcp
src/oraviz_mcp/
server.py # FastMCP app, config, Oracle client, validation, the 7 tools
charts.py # pure matplotlib rendering (bar/line/area/scatter/pie/histogram/vector -> PNG bytes)
main.py # entry point: env validation, transport selection
tests/
test_config.py # config dataclasses + env parsing
test_validation.py # SQL guard, identifiers, formatting, result rendering
test_charts.py # every chart type + validation errors
test_server_tools.py # all tools against a scripted fake cursor
test_main.py # entry point
integration/ # live Oracle tests (skipped without ORAVIZ_TEST_DSN)
examples/demo-sales.sql
docs/testing.mdData flow: the MCP client calls a tool -> server.py validates (validate_query / validate_table_name) ->
python-oracledb thin connection -> rows are narrowed (fetch cap) -> either rendered as a compact table
(render_rows) or handed to charts.py -> the model receives text, or an image plus a short preview.
Development
uv sync --extra dev # install everything (matplotlib, fastmcp, oracledb, pytest)
uv run pytest # hermetic unit suite (~98% line coverage; the 90% gate is enforced)
uv run pytest -k chart # focus on one area
# Live tests create/drop scratch objects: use a separate disposable test owner,
# not the MCP reader. Inject ORAVIZ_TEST_PASSWORD privately before this command.
ORAVIZ_TEST_DSN=localhost:1530/FREEPDB1 \
ORAVIZ_TEST_USER=oraviz \
uv run pytest tests/integration -v --no-cov
docker build -t oraviz-mcp . # container build (multi-stage, non-root)See docs/testing.md and tests/README.md for the testing story.
OraViz vs. the official Oracle MCP servers
Oracle ships rich, general-purpose MCP servers -- SQLcl's built-in MCP server
(run-sql, connect, schema-information, ...), ORDS MCP,
the OCI Database Tools MCP, and the reference servers in
oracle/mcp. Use those when you need breadth: DDL, transactions, RAC, RAG pipelines.
OraViz is the opposite bet: seven tools, read-only SQL, and a hard focus on turning data into pictures without flooding the model's context. If you want the database operated, use the official servers. If you want the database seen, use this one.
Benchmarks
Historical snapshot: the numbers, paper PDFs, and figures below were captured before security hardening. They are retained unchanged and have not been recomputed for the current schemas or limits. Current guarantees and limitations are in SECURITY.md; see also paper/README.md.
We measured the tokens an agent must process to answer the same questions through OraViz and through the
official SQLcl MCP server,
against the same 26ai Free database (tiktoken cl100k_base: tool schemas plus every tool result):
Stage | OraViz | SQLcl MCP | Savings |
Tool schemas (read once per session) | 862 | 2,139 | 59.7% |
Schema discovery | 69 | 354 | 80.5% |
Full 96-row dump | 825 | 2,136 | 61.4% |
Whole workflow (5 questions) | 2,337 | 5,006 | 53.3% |
The 10-row sample step trades ~55% more framing tokens than raw CSV, and that overhead cannot grow with
the result size. Rendering the aggregate as a chart costs 123 text tokens plus the PNG image. Full
methodology, step-by-step numbers, and reproduction commands: benchmarks/. The full
write-up is in paper/paper.pdf, the results deck in slides/, and a
live showcase at jasperan.github.io/oraviz-mcp.
Credits
pab1it0/adx-mcp-server-- the project this mirrors, tool for tool, for OracleOracle AI Database 26ai Free -- the database and its container image
python-oracledb -- thin-mode driver, no client libraries required
FastMCP and the Model Context Protocol
License
MIT -- see LICENSE.
Available Tools
7 toolscreate_chartCreate ChartA
Runs a read-only SQL query and renders the result as a chart image (PNG). chart_type is one of: bar, line, area, scatter, pie, histogram. The first column is the x-axis or labels; numeric columns after it become series. Returns the image plus a data preview.
| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes | ||
| title | No | ||
| x_label | No | ||
| y_label | No | ||
| chart_type | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the burden of behavioral disclosure. It does disclose that the query is read-only and that the output is an image plus a data preview, which is helpful. It stops short of describing limitations, error behavior, or how the image is represented.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three compact sentences deliver high-value information without filler. The read-only and chart-image purpose is front-loaded, followed by chart types and column mapping, then the return payload.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the core invocation details and return payload, but no output schema exists and the description does not specify how the PNG image is delivered (URL, base64, file path). It also leaves the label parameters undocumented, so the definition is workable but not fully complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate. It adds important meaning: the list of valid chart_type values, how columns map to axes and series, and the read-only nature of the sql parameter. The optional title, x_label, and y_label parameters are left to inference, but their names are largely self-explanatory.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action: run a read-only SQL query and render the result as a PNG chart. It clearly distinguishes itself from sibling tools like execute_query by emphasizing chart generation, not just raw query results.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The intended use is implied: use this tool when you need a visual chart from SQL results. However, it does not explicitly say when to prefer this over execute_query or other sibling tools, nor does it mention any exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
execute_queryExecute QueryA
Executes a read-only SELECT/WITH query and returns a compact markdown table plus a metadata line (row count, and whether more rows exist). Results are preview-capped by default to protect the caller's context: aggregate in SQL and only pass max_rows when the raw rows are really needed. Large cell values are summarised.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| max_rows | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It explicitly states read-only behavior, preview-capping, and summarisation of large cells, which are key behavioral traits. It also explains the rationale (protect caller's context). Missing details like error handling or timeout are minor for a query tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise (three sentences) and well-structured: purpose and return format first, then usage tips. Every sentence earns its place, and the key information about preview-capping is front-loaded. No fluff or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has an output schema, so return format is partly covered, but the description still explains the markdown table and metadata. It covers the essential aspects: read-only, preview cap, and summarisation. It lacks info on error behavior or limits, but for a straightforward query tool this is acceptable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It explains max_rows' purpose (when to pass it) but does not describe the 'query' parameter beyond implying SELECT/WITH syntax. The query is self-explanatory as a string, but the parameter semantics are not fully fleshed out for a schema that offers no descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool executes read-only SELECT/WITH queries and returns a markdown table with metadata. This distinguishes it from sibling tools like list_tables or sample_table_data, which serve different purposes. The verb 'executes' and resource 'query' are specific and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides practical usage guidance (e.g., aggregate in SQL, only pass max_rows when needed) but does not explicitly differentiate when to use this tool versus alternatives like sample_table_data. The context of being the primary query tool is implied, but not stated as a rule or recommendation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_table_detailsGet Table DetailsA
Retrieves table details: owner, tablespace, optimizer statistics (NUM_ROWS, BLOCKS, AVG_ROW_LEN, LAST_ANALYZED) and, optionally, an exact row count.
| Name | Required | Description | Default |
|---|---|---|---|
| table_name | Yes | ||
| exact_row_count | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description must carry the behavioral burden. It does disclose that exact_row_count is optional and that statistics are returned by default, which is useful. However, it does not mention potential performance costs of exact_row_count, permission requirements, or error behavior. It adds some value but not the full transparency expected without annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, efficient sentence that front-loads the main action and lists specific details. There is no fluff or repetition, and every word adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with two parameters and an output schema, the description is mostly complete. It specifies what data is returned and the optional flag. The only minor gap is the lack of notes on the cost or implications of exact_row_count, but this is not critical for basic use given the output schema exists.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It explicitly explains that exact_row_count yields an exact count instead of statistics, which goes beyond the bare boolean type. table_name is self-evident from its name, so the description covers the key parameter semantics adequately.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Retrieves' and the specific resource 'table details', listing the exact fields (owner, tablespace, optimizer statistics, optional row count). This distinguishes it from siblings like get_table_schema (schema structure) and profile_table (data profiling). The purpose is unambiguous and not a tautology.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives no guidance on when to use this tool versus alternatives. It does not mention, for example, 'use this instead of get_table_schema when you need statistics' or any exclusions. The agent is left to infer usage purely from the tool's name and description, which is minimal.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_table_schemaGet Table SchemaA
Retrieves the schema of a table or view as a compact markdown table: column name, data type, length, nullability, and whether the column is part of the primary key.
| Name | Required | Description | Default |
|---|---|---|---|
| table_name | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must disclose behavior. It states it returns a compact markdown table with specified fields, implying a read-only operation. However, it does not mention potential failure modes (e.g., nonexistent table), whether the result is ordered, or any access requirements. For a simple retrieval tool this is adequate but not rich.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, well-structured sentence that front-loads the action ('Retrieves the schema') and then details the output fields. There is no redundancy or filler; every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple tool with one parameter and an existing output schema, the description is mostly complete. It tells what is returned and covers both tables and views. The only minor gap is not addressing error behavior or naming conventions, but these are not critical for a straightforward retrieval tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has no descriptions for the single parameter 'table_name', and the description does not compensate. It does not specify whether the name should be fully qualified, case-sensitive, or how to reference views versus tables. With 0% schema coverage, the description carries the full burden and fails to add any parameter-level meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool retrieves the schema of a table or view, and specifies the exact components returned (column name, data type, length, nullability, primary key). This is a specific verb-resource pair that distinguishes it from siblings like get_table_details (which likely covers more than schema) and list_tables (which lists tables). The markdown format is an extra clarifying detail.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool versus alternatives such as get_table_details or execute_query. There is no mention of prerequisites, limitations, or scenarios where another tool would be more appropriate. The agent must infer usage from the tool name alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_tablesList TablesA
Retrieves a list of all tables and views available in the configured Oracle schema as a compact markdown table. Optionally takes a schema name.
| Name | Required | Description | Default |
|---|---|---|---|
| schema | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden of behavior disclosure. It communicates a read-only operation through 'Retrieves' and is open about the markdown output, but it doesn't mention permissions, auth needs, errors, or that no data is materially changed. This is acceptable for a listing tool but not rich.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence front-loads the core action and output format, then adds optional parameter detail. No filler redundancy or repeated title content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple with one optional parameter and an output schema present. The description covers purpose, scope, output format, and parameter optionality, which is nearly complete. The main missing piece is explicit behavior for providing versus omitting schema name, but this is minor at this complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% and the description was at least notes 'Optionally takes a schema name', which clarifies that schema is optional and what it refers to. However, it does not explain how the optional schema interacts with the configured schema or list filtering, and the property name already indicates 'schema', so the description adds limited semantic value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Retrieves a list'), the resource ('all tables and views'), the context ('configured Oracle schema'), and the output format ('compact markdown table'). It distinguishes naturally from siblings like get_table_schema, which targets a single table, and execute_query, which runs ad-hoc SQL.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The intended use in this case is implied by the purpose: use when you need to enumerate tables/views. The sibling tool names add context, but the description offers no explicit guidance on when to choose it over alternatives, or when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
profile_tableProfile TableB
Profiles a table for visualization: row count plus per-column statistics (non-null count, distinct count, min, max, average) to decide which chart fits the data.
| Name | Required | Description | Default |
|---|---|---|---|
| columns | No | ||
| table_name | Yes | ||
| max_columns | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure, but it does not state whether the tool is read-only, how expensive it could be, or how it handles empty/missing data. It lists outputs, but important behavioral traits like modification safety, performance, or error conditions are left unstated.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, tightly worded sentence packs a clear purpose and the core delivered statistics. There is no fluff—every word adds signal: it says what, what what purpose, and what kind of output.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the high-level goal but does not explain the parameter semantics or usage boundaries, which matters because the schema descriptions are empty. Even though an output schema exists, the tool cannot be reliably invoked with just this description plus schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description should compensate by explaining the three parameters. It only vaguely implies table_name via 'Profiles a table' and never explains columns or max_columns, including optionality, defaults, or effects. This is a critical gap for correct invocation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's specific function: profiling a table for visualization with row count and per-column statistics to guide chart selection. It distinguishes the tool from siblings like sample_table_data or get_table_schema by emphasizing the analytical/statistical output and visualization intent.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear context: this is used to determine an appropriate chart by inspecting table characteristics. It does not explicitly name alternatives or when not to use it, so it stops short of a 5, but the intended use case is sufficiently communicated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sample_table_dataSample Table DataA
Retrieves a small sample of rows from the specified table as a compact markdown table. sample_size controls how many rows to return (default: 10, capped by the server).
| Name | Required | Description | Default |
|---|---|---|---|
| table_name | Yes | ||
| sample_size | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations are absent, so the description carries the full burden of behavioral disclosure. It discloses that only a small sample is returned, that rows come as a markdown table, and that sample_size defaults to 10 and is server-capped. However, it doesn't state whether the sample is deterministic/random, whether the operation is read-only (though 'retrieves' implies so), or how errors like non-existent tables or permission failures behave. Adequate but not complete.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no filler. The main purpose and output format are front-loaded; the parameter behavior follows in the second sentence. Everything present contributes necessary information, and no word is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema available and a simple two-parameter input, the description covers the core behavior, sample mechanism, output format, and the default/cap behavior of sample_size. It is complete enough for an agent to successfully call the tool for a quick preview. The only missing-piece is a clarification about how this differs from execute_query when both could return rows, but that is more of an usage guideline than a completeness gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It clearly defines sample_size's effect ('controls how many rows to return'), the default (10), and server cap. It correctly identifies table_name as 'the specified table'. This adds meaningful semantics beyond the bare integer/string types. Slight gap: it does not specify table_name formatting or whether sample_size is inclusive or capped at a hard maximum.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear, specific action ('Retrieves a small sample of rows'), names the resource ('from the specified table'), and specifies the output format ('compact markdown table'). This is distinct from siblings like list_tables (lists table names), get_table_details (metadata), and profile_table (statistics); even execute_query is clearly different in scope ('a small sample' vs arbitrary query results). There is no ambiguity about what the tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for quick data previews but does not explicitly say when to choose this over execute_query or get_table_details. It states that sample_size is capped by the server, but it does not provide scenarios or compare to full-query retrieval, leaving the 'instead of' guidance to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
7 tool updates
v0.1.0- First observed
create_chart - First observed
execute_query - First observed
get_table_details - First observed
get_table_schema - First observed
list_tables - First observed
profile_table - First observed
sample_table_data
TDQS
Scored across 7 tools
Most tools target clearly distinct operations, but a few boundaries require careful reading: create_chart and execute_query both run SQL, and get_table_details and get_table_schema both describe table metadata. The descriptions clarify the outputs enough that an agent should usually pick correctly.
All tool names follow a consistent snake_case verb_noun pattern: execute_query, list_tables, get_table_schema, sample_table_data, get_table_details, profile_table, create_chart. The naming is predictable and uniform across the set.
Seven tools is well-scoped for an Oracle exploration and visualization server. Each tool serves a distinct discovery or charting purpose without unnecessary bloat or missing core functionality.
The server covers the full exploration-to-visualization workflow: listing objects, inspecting schema, sampling data, profiling columns, running queries, and creating charts. Minor gaps exist, such as no table DDL viewer or chart configuration options, but an agent can accomplish the intended tasks without dead ends.
Maintenance
Related MCP Connectors
Renders interactive Chart.js charts and dashboards inline in AI conversations.
Renders interactive Chart.js charts and dashboards inline in AI conversations. Supports bar, line, area, pie, doughnut, scatter, and radar charts with multi-chart dashboard grids.
List datasets, schemas, run APL queries, and use prompts for exploration, anomalies, and monitoring.
Query your org's data in natural language — read-only MCP access to SQL, NoSQL, files & warehouses.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables AI applications to run SQL queries and retrieve results from Oracle Database.8-
- FlicenseNot gradedqualityDmaintenanceEnables AI-powered database operations on Oracle Autonomous Database via natural language, including SQL translation, schema exploration, and API orchestration.4-
- FlicenseNot gradedqualityBmaintenanceEnables read-only exploration of Oracle databases through natural language, providing schema inspection and safe bounded SQL query execution.-
- FlicenseNot gradedqualityBmaintenanceEnables AI chatbots to securely answer natural-language questions against Oracle databases by discovering metadata, generating and validating read-only SQL, executing with limits, masking sensitive data, and logging all activity.-