Skip to content

Add oracle-data-studio-mcp-server#223

Open
tsikinov wants to merge 5 commits intooracle:mainfrom
tsikinov:add-data-studio-mcp-server
Open

Add oracle-data-studio-mcp-server#223
tsikinov wants to merge 5 commits intooracle:mainfrom
tsikinov:add-data-studio-mcp-server

Conversation

@tsikinov
Copy link
Copy Markdown
Member

@tsikinov tsikinov commented May 7, 2026

Closes #222.

A Python MCP server providing 60 task-oriented composite tools for
three Oracle Data Studio services: Essbase, ADP (Autonomous Database
Data Platform), and Data Transforms.

Highlights

  • 60 high-level composite tools — 30 Essbase, 15 ADP, 15 Data
    Transforms — plus 1 prompt template. Each tool combines multiple SDK
    calls into a single LLM-friendly operation rather than exposing raw
    REST endpoints.
  • Oracle 23ai annotation-aware query routingadp_get_annotations
    reads ALL_ANNOTATIONS_USAGE; the adp_sql_with_annotations prompt
    teaches the assistant to use them as semantic hints (units,
    aggregations, join keys, time grain, PII).
  • Annotation-driven cube/AV/table routing — fact tables can declare
    cube='<app>.<db>' and analytic_view='<av>' annotations that
    deterministically route the LLM to the right query source. No
    name-matching, no guessing.
  • Three access profilesviewer / analyst / admin with
    verb-based filtering plus explicit deny lists.
  • Server instructions advertised on MCP handshake — every
    compliant client (Claude Desktop, Cursor, Codex) injects them into
    the LLM's system context.

Safety

  • Errors sanitised through a shared safe_err helper — strips DSN
    passwords, URL userinfo, Bearer tokens, OCID tails, absolute paths.
  • Reconnect rate-limit (3 attempts / 60s, 30s cooldown) and
    per-context lock around credential reuse.
  • streamable-http binds 127.0.0.1 by default; logs a warning when
    bound to 0.0.0.0.
  • No raw SQL execution by design — pair with the SQLcl MCP server for
    arbitrary SQL.

Validation

  • 109 unit tests passing — config loading, profile filtering,
    credential store, error sanitisation, reconnect rate-limit and
    locking, tool registration, mocked SDK dispatch.
  • Live A/B tested on Oracle Autonomous Database 23.26 with the
    MovieLens dataset and an Essbase cube of the same name.
    Annotation-aware SQL beat naive generation 5/5 across realistic
    failure modes (UNIT mismatch, GRAIN mismatch, AGGREGATE choice,
    JOIN_HINT, PII avoidance).

Test plan

  • uv sync --all-extras
  • uv run pytest oracle/data_studio_mcp_server/tests/test_unit.py → 109 passed
  • Live test against an annotated table (DDL example in README.md)
  • Configure ADP/Essbase/Data Transforms credentials, then connect Claude Desktop and verify the annotation-driven routing demo

A Python MCP server providing 60 task-oriented composite tools for
three Oracle Data Studio services: Essbase, ADP (Autonomous Database
Data Platform), and Data Transforms.

Features:
- 60 high-level composite tools (30 Essbase, 15 ADP, 15 Data
  Transforms) plus 1 prompt template — each tool combines multiple
  SDK calls into a single LLM-friendly operation.
- Oracle 23ai annotation-aware query routing: a new adp_get_annotations
  tool reads ALL_ANNOTATIONS_USAGE; the adp_sql_with_annotations
  prompt teaches the assistant to fetch annotations first and use
  them as semantic hints (units, aggregations, join keys, time
  grain, PII).
- Annotation-driven cube/AV/table routing: tables can declare
  `cube='<app>.<db>'` and `analytic_view='<av>'` annotations to tell
  the LLM which query source to use for aggregate questions —
  deterministic, no name-matching.
- Three access profiles (viewer / analyst / admin) with verb-based
  filtering plus explicit deny lists for tools that need finer
  control (calc-script content, log access, pipeline execution).
- Server-level instructions advertised on MCP handshake — every
  compliant client (Claude Desktop, Cursor, Codex) injects them
  into the LLM's system context.

Security/safety:
- Error messages sanitised through a shared safe_err helper —
  strips DSN passwords, URL userinfo, Bearer tokens, OCID tails,
  and absolute filesystem paths.
- Reconnect rate-limit (3 attempts / 60s, 30s cooldown) and
  per-context lock around credential reuse.
- streamable-http binds 127.0.0.1 by default (no built-in auth).

Validation: A/B tested on Oracle Autonomous Database 23.26 with
the MovieLens dataset — annotation-aware SQL generation beat naive
generation 5/5 across realistic failure modes (UNIT mismatch,
GRAIN mismatch, AGGREGATE choice, JOIN_HINT, PII avoidance).

Tests: 109 unit tests covering config loading, profile filtering,
credential store, helpers, error sanitisation, reconnect rate-limit
and locking, tool registration, and tool dispatch (mocked SDK).

Signed-off-by: Alexander Tsikinovsky <alexander.tsikinovsky@oracle.com>
@oracle-contributor-agreement oracle-contributor-agreement Bot added the OCA Verified All contributors have signed the Oracle Contributor Agreement. label May 7, 2026
tsikinov added 4 commits May 6, 2026 19:32
CI runs `uv run pytest --cov=. --cov-branch --cov-report=...`,
which fails to parse `--cov` flags without the pytest-cov plugin.

- pyproject.toml: add `pytest-cov>=7.0.0` to [dependency-groups].dev
- pyproject.toml: drop `fail_under` (informational coverage only for
  now; ~24% line coverage today, will be raised in follow-up PRs)
- uv.lock: regenerated to include pytest-cov + coverage transitively

Verified locally with the exact CI command: exit code 0, 109 tests
passing, HTML + term-missing reports generated.

Signed-off-by: Alexander Tsikinovsky <alexander.tsikinovsky@oracle.com>
Adds 111 new tests (109 → 220 total) across:

- cli_config: 0% → 90% — argparse builder + each sub-command handler
  (set with/without password prompt, server-no-password path, list,
  remove)
- credential_store: 28% → 81% — store/remove/list/load round-trips
  with tmp-path-isolated config files; password never lands on disk;
  keyring fallback when keyring module unavailable
- server.py lifespan: 29% → 75% — covers each branch of the startup
  context manager (no-config, Essbase token vs. user/password, ADP
  login success and failure path)
- adp_tools: 26% → 54% — bulk parametrised dispatch for every
  manage_* action (list/get/create/delete/etc.) per tool
- essbase_tools: 21% → 35% — bulk dispatch for application,
  database, files, locks, sessions, variables, scripts, connections,
  filters, jobs, datasources, drill_through, users
- dt_tools: 25% → 30% — schedule, variables, connection actions

Pattern: a small _adp_dispatch / _dt_dispatch / _ess_dispatch helper
takes (tool, kwargs, sdk_path) tuples and verifies the SDK method was
called for that action — prevents the param-leak class of bug
(B1, B2, M7 from earlier audit) from regressing.

Total: 220 tests, 44.20% line coverage, 17.61% branch coverage.

Verified locally with the exact CI command:
  uv run pytest --cov=. --cov-branch \
       --cov-report=html:htmlcov/oracle-data-studio-mcp-server \
       --cov-report=term-missing
→ 220 passed, exit code 0

Signed-off-by: Alexander Tsikinovsky <alexander.tsikinovsky@oracle.com>
Adds 95 more tests (256 → 351 total) covering bigger composite-tool
bodies and the auto-reconnect path:

- _adp_connect: 65% → 95% — full run_adp paths (success, no-client,
  string-result formatter, expired-then-reconnect, non-expired error
  goes through safe_err, proactive reconnect on expired token,
  reconnect-already-done dedup)
- adp_tools: 54% → 72% — adp_search include_ddl walks DDL probes,
  adp_load_from_cloud full flow + progress-only path,
  adp_build_analytic_view all 4 SDK calls, adp_analyze_analytic_view
  walks quality + dimensions + measures, adp_generate_insights polls
  status + collects graph
- dt_tools: 36% → 63% — dt_describe_project full body (3 list calls),
  dt_describe_connection (details + test + schemas),
  dt_check_health walks all connections,
  dt_run_pipeline (dataflow), dt_browse_data with schema filter,
  dt_create_pipeline create-project-when-missing branch,
  dt_manage_dataload create with all load_types (truncate / append /
  recreate), dt_manage_workflow get, dt_manage_data_entities import
- essbase_tools: 35% → 66% — essbase_run_calculation inline calc
  flow, essbase_load_data dataload payload, essbase_describe_database
  multi-call, essbase_manage_security user + group paths,
  essbase_manage_filters create + update + auto-validate,
  essbase_manage_drill_through create with payload,
  essbase_manage_db_settings 'all' + per-category,
  essbase_outline_metadata category dispatch,
  essbase_browse_outline recursive walk,
  essbase_search_members ancestor enrichment,
  essbase_manage_users provision_app_role / provision_service_role,
  essbase_edit_outline BOE payload shape

Total: 351 tests, 70.52% line coverage, 25.83% branch coverage,
exit code 0 with the exact CI command.

Signed-off-by: Alexander Tsikinovsky <alexander.tsikinovsky@oracle.com>
…ew feedback

Two pre-emptive review-friendly tweaks:

- pyproject.toml: set fail_under = 75 — a regression gate slightly
  below current line coverage (79.25%) so a future PR can't silently
  lower it. The previous "no gate" was stylistically suspect.
- README.md: new section 'About the oracle-data-studio dependency'
  explaining the PyPI dep is the official Oracle Data Studio SDK
  maintained by the same team contributing this server, and that
  version 1.0.26+ is required for the annotation guidance and
  reconnect-safety features.

Test additions (155 more — 351 → 506 total):

- credential_store: 81% → 89% — keyring success/delete/missing paths
- adp_tools: 72% → 81% — full multi-call composite walks for
  load_from_cloud, build_analytic_view, analyze_analytic_view,
  generate_insights, search-with-DDL; bulk validation-error coverage
  for every manage_* tool's missing-arg branches
- dt_tools: 63% → 75% — schedule create across all 5 frequencies
  (immediate / hourly / daily / weekly / monthly), workflow
  check_exists, dataload create with all 3 load_types, browse_data
  with/without schema filter, full describe_project / describe_
  connection / check_health walks, plus bulk validation-error
  coverage
- essbase_tools: 66% → 75% — manage_filters create/update with
  validate, manage_drill_through create/update/execute, manage_
  database update/copy, manage_groups add_users / remove_users /
  add_subgroups, manage_users provision_app/service + deprovision +
  update + create, edit_outline payloads (add/remove/move),
  manage_files upload/download/copy/move, manage_db_settings 'all'
  + per-category, outline_metadata categories incl. export_xml +
  member, manage_jobs status/rerun, manage_locks unlock,
  manage_sessions kill/kill_all + bulk validation-error coverage
- server.py: 75% → 78% — Essbase login failure caught, DT config
  cached for lazy connect

Total: 506 tests, 79.25% line coverage, 23.58% branch coverage,
exit code 0 with the exact CI command + the new fail_under gate.

Signed-off-by: Alexander Tsikinovsky <alexander.tsikinovsky@oracle.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

OCA Verified All contributors have signed the Oracle Contributor Agreement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add oracle-data-studio-mcp-server (Essbase + ADP + Data Transforms)

1 participant