Skip to main content
Glama
MuhDur

oraclemcp

by MuhDur

Governed, least-privilege Oracle Database access for AI agents — in pure Rust.

oraclemcp is a Model Context Protocol server that gives an AI agent governed, least-privilege access to an Oracle database. Every raw statement the agent submits is classified before it can reach Oracle: read tools admit only statements proven read-only, and non-read SQL runs only through an explicit, profile-gated path that rolls DML back by default and requires a preview-derived grant before commit. Session elevation is explicit, temporary, and capped by profile max_level. The engine-free SQL guard remains independent of PL/SQL intelligence; the default binary embeds the offline engine. All crates use #![forbid(unsafe_code)].

An independent open-source project — not affiliated with Oracle. See how it compares to Oracle's own MCP servers.

Drivers

oraclemcp connects through its own mature, pure-Rust Oracle driver as the primary path. The official oracledb crate from Oracle — whose crate name we handed to Oracle in a friendly handshake — is currently in beta, and therefore ships purely as a bounded, connect-time fallback for the rare case something goes awry. No Oracle Instant Client, ODPI-C, or C toolchain is required.

flowchart LR
    A["Connection request"] --> D["driver-cx<br/>pure-Rust · primary<br/>password · IAM · wallet · TCPS/PEM"]
    D -->|"basic-password<br/>connect fails"| O["oracledb<br/>Oracle · beta<br/>connect-time fallback"]
    D --> DB[("Oracle Database")]
    O --> DB

Only a failed basic-password connect ever falls back; IAM, wallet, and TCPS/PEM always stay on driver-cx, and a fallback never migrates a live session.

At a glance

Tools

43 governed MCP tools + 25 compatibility aliases, each with a real JSON Schema and MCP safety hints

Safety

fail-closed SQL classifier · 4-level ladder READ_ONLY → READ_WRITE → DDL → ADMIN · DML rollback-by-default · signed, hash-chained audit

Auth

username/password over TCP · IAM / OCI ADB token · TLS/TCPS + PEM · Oracle wallet (cwallet.sso)

Oracle

18c · 21c · 23ai — including governed native VECTOR search

Code

9 pure-Rust crates + binary · #![forbid(unsafe_code)] · ~3,300 tests + a differential fuzzer

Transports

stdio (default) + Streamable HTTP with rustls TLS/mTLS and optional OAuth

Related MCP server: Oracle DB MCP

Quick start

One line installs or updates on macOS and Linux (works pasted in a terminal or in a non-interactive agent run):

curl -fsSL "https://raw.githubusercontent.com/MuhDur/oraclemcp/main/install.sh?$(date +%s)" | bash

It verifies a SHA-256 digest (plus cosign signature/provenance when cosign is present) and installs oraclemcp and the short om alias into $HOME/.local. Also available: Windows (install.ps1), Docker (ghcr.io/muhdur/oraclemcp:latest), and cargo binstall oraclemcp. Air-gapped offline install, verification postures, and service install are documented via bash install.sh --help and docs/. No npm/npx channel is offered.

Onboard and connect a client:

oraclemcp setup --discover           # one READ_ONLY profile per tnsnames.ora entry — consent-gated, no secrets written to disk
oraclemcp doctor                     # offline diagnostics: driver, TNS/wallet, classifier, NLS
oraclemcp serve --profile db_ro --allow-no-auth    # stdio (local dev)

Wire it into an MCP client (e.g. Claude Desktop) over stdio:

{
  "mcpServers": {
    "oracle": {
      "command": "oraclemcp",
      "args": ["serve", "--profile", "db_ro", "--allow-no-auth"]
    }
  }
}

Several local MCP clients can use this same stdio configuration concurrently, including write-capable profiles. When service state is needed, clients automatically attach to one local broker that owns the audit writer and database pools. Each client retains its own session level, confirmation tokens, transaction and cancellation. The broker exits after 60 seconds without clients. HTTP also gives each client an isolated stateful session by default. HTTP and stdio clients share that same broker and state root. Each local client must resolve its own configured database credentials. Credentials that differ from the broker's receive ORACLEMCP_BROKER_CREDENTIAL_MISMATCH before opening a session.

Or run authenticated HTTP with a shown-once bearer, and open the local dashboard through a secret-free one-time pairing URL:

oraclemcp --json clients issue --label claude --scope oracle:read
oraclemcp serve --listen 127.0.0.1:7070 --client-credentials --profile db_ro
om dashboard

doctor output is safe to paste into agent sessions — it omits connect strings, usernames, credential references, passwords, wallet paths, IAM tokens, and server DNs while keeping structured failure classes and ORA codes.

Why oraclemcp

  • Fail-closed by construction. A SELECT an agent dreams up can never silently become a DELETE. Read tools admit only proven read-only SELECT/WITH and dictionary introspection. Non-read execution is isolated in oracle_execute, bounded by the profile ceiling, rollback-by-default for DML, and explicit-confirm-before-commit. Forbidden constructs (multi-statement batches, string-concat dynamic SQL, an unproven function call inside a SELECT) are rejected before touching Oracle, with a typed envelope and a suggested safe alternative.

  • Agent-first UX. Every tool ships a real JSON Schema, title, and explicit MCP annotations (readOnlyHint, destructiveHint, idempotentHint, openWorldHint). Errors are structured ErrorEnvelopes with machine-stable classes, fuzzy suggestions, and next-step hints — never bare strings. A zero-arg oracle_capabilities tool lets an agent discover the surface.

  • Pure Rust, no unsafe. Every crate is #![forbid(unsafe_code)]; the fail-closed classifier is a real sqlparser AST classifier and carries a differential cargo-fuzz target.

  • Two transports. stdio (default) and Streamable HTTP (--listen) with fail-closed auth defaults, optional OAuth bearer enforcement, and native rustls TLS/mTLS.

How it compares

Oracle ships an official MCP built into SQLcl; ours is independent. On the axis that decides whether you can safely point an AI agent at a database — the guard between the agent and your data — here is the honest, evidence-backed contrast:

Oracle SQLcl MCP

oraclemcp

Default posture

Not read-only

Read-only, fail-closed

Write / DDL control

No in-server gate — relies on DB grants + a non-prod replica

In-server: classifier + READ_ONLY→ADMIN ladder + preview→confirm-token + rollback-by-default

Safety boundary

Your grant hygiene — a wrong grant or a clever prompt can write

The server itself — enforced regardless of grants

SQL handling

Free-form, tagged /* LLM in use */

Free-form, but classified before it reaches Oracle

Audit

DB-side log table (DBTOOLS$MCP_LOG)

Signed, hash-chained HMAC audit + verdict certificates

Runtime

Java — needs the JVM + a SQLcl install

One pure-Rust static binary — no JVM, C toolchain, or Instant Client

SQLcl-MCP rows reflect Oracle's own documentation (configure a minimum-privilege user, prefer a non-prod replica, audit via DBTOOLS$MCP_LOG); the oraclemcp rows are enforced in this repository. Oracle is the official, supported option, and its managed Autonomous MCP takes a different curated-report approach with per-user identity — strong for locked-down read-only BI.

Safety model

When a guarded request is refused, use the generated refusal catalogue for its typed safe next action; it never recommends bypassing the guard.

The core invariant is a fail-closed SQL guard — not "read-only forever." Operating levels form a ladder, READ_ONLY < READ_WRITE < DDL < ADMIN, surfaced through oracle_execute, oracle_compile_object, oracle_create_or_replace, oracle_patch_source, and oracle_set_session_level. Read-only is the default and the cap for unconfigured or protected profiles; a profile's max_level may permit escalation up to ADMIN. Every escalation is guarded:

  • a preview → confirmation-token step-up before any non-read statement runs,

  • a temporary, TTL-bounded elevation window,

  • the classifier still gating every statement at the current level,

  • DML rolling back by default, protected profiles pinned at READ_ONLY with an immutable ceiling, and OAuth scopes that can only lower the effective level,

  • a signed, append-only, HMAC-SHA256 hash-chained audit record for every privileged action.

flowchart LR
    A["Agent SQL"] --> C{"Fail-closed<br/>classifier"}
    C -->|"proven READ_ONLY"| R["Read tools · rows returned"]
    C -->|"forbidden / unparseable"| X["Refuse<br/>typed ErrorEnvelope"]
    C -->|"non-read"| L{"Operating-level gate<br/>READ_ONLY → READ_WRITE → DDL → ADMIN"}
    L -->|"above level / ceiling"| X
    L -->|"within profile ceiling"| P["Preview → confirmation token"]
    P --> E["Execute"]
    E -->|"DML"| RB["Rollback by default<br/>commit only with grant"]
    R --> AU[("Signed hash-chained audit")]
    E --> AU

An unparseable or unclassifiable statement fails closed. Statements can emit a verdict certificate bound to the classified bytes and the audit record; the routine-purity law it relies on is specified in proofs/purity-core/PurityCore.lean and pinned to the Rust classifier by a conformance test.

Governed dimensions

A database session is treated as a governed surface with several independent controls, each with an executable proof script:

Dimension

What it governs

Proof

Cost

per-call max_query_cost + durable per-principal budget; over-ceiling estimates refused pre-execution

cost_gate.sh

Time

as_of flashback reads, cross-SCN/cross-DB oracle_diff, historical plan timelines

time_diff.sh

Egress

profile-scoped result masking applied before rows leave the server, with mask certificates (ADR 0008)

served_egress.sh

Proof

verdict certificates + async Rekor anchoring of audit heads (ADR 0010)

verdict_certificate.sh

Policy

per-profile deny/narrow-only SQL policy that can tighten but never widen the base classifier (ADR 0009)

sql_policy.sh

Living DB

CQN change notifications, oracle_orient freshness/drift, Arrow IPC output

living_db.sh

Vector search

bounded, fail-closed 23ai oracle_semantic_search through the full policy/masking/audit path

governed_rag.sh

Fleet

map or compare several MCP-visible profiles at once; unreachable targets become typed UNREACHABLE/FAIL_CLOSED lanes

fleet.sh

Reversible workspace

native SAVEPOINT checkpoints, held DML, oracle_undo_to, undo-aware oracle_preview_dml

reversible.sh

Editions

edition-based redefinition via an allowlist, persisted proposals, and an ADMIN-only merge

editions.sh

Incident capture

om incident capture/replay — redacted, deterministic bundles re-classified offline (ADR 0011)

incident.sh

Diagnostics

oracle_top_queries (free V$SQLSTATS) and a read-only oracle_db_health suite that degrades cleanly on least-privilege accounts (ADR 0005)

version-matrix lanes

What an agent sees depends on the active level and effective ceiling. At READ_ONLY, tools/list includes oracle_execute and execute_approved when the effective profile/OAuth ceiling permits READ_WRITE; their visibility grants no write authority. Other higher-level tools remain hidden until the session is elevated within the ceiling. A call to a not-yet-visible tool is refused with the same typed ErrorEnvelope as any other below-level statement.

Tools

The tables below are generated from the server's tool registry — the same descriptors tools/list serves — by scripts/docs_generate.sh (rendered from oraclemcp robot-docs tools --markdown). Do not hand-edit them; edit the registry and run bash scripts/docs_generate.sh --write.

Tool

Title

Purpose

Visible from

Destructive

oracle_list_profiles

Oracle List Profiles

List configured connection profiles without exposing connect strings, usernames, or credential references.

READ_ONLY

no

oracle_connection_info

Oracle Connection Info

Describe the active profile, its effective MCP access (operating level, profile max_level, protected status, and whether writes are permitted now), and Oracle connection state.

READ_ONLY

no

oracle_switch_profile

Oracle Switch Profile

Reconnect this MCP server to another configured profile by name and report that profile's effective MCP access.

READ_ONLY

no

oracle_set_session_level

Oracle Set Session Level

Preview or apply a temporary session operating-level elevation within the active profile ceiling, or drop back to READ_ONLY.

READ_ONLY

yes

oracle_query

Oracle Query

Run a read-only SELECT with positional binds; paginated and row/byte capped.

READ_ONLY

no

oracle_semantic_search

Oracle Semantic Search

Run a bounded, fail-closed 23ai vector search through the same policy, semantic-resolution, masking, and audit path as oracle_query.

READ_ONLY

no

oracle_diff

Oracle Diff

Diff one proven read-only SELECT across two Oracle SCNs, or across two databases.

READ_ONLY

no

oracle_preview_sql

Oracle Preview SQL

Classify SQL without executing it and bind the exact SQL, typed binds, commit/hold mode, output caps and timeout into any confirmation.

READ_ONLY

no

oracle_execute

Oracle Execute

Execute one non-read SQL statement through the classifier and active profile gate; DML rolls back by default.

READ_ONLY

yes

oracle_checkpoint

Oracle Checkpoint

Establish a named checkpoint (a native Oracle SAVEPOINT) on this session, opening the reversible workspace: oracle_execute with hold=true and a matching preview confirmation leaves DML pending instead of rolling it back, and oracle_undo_to walks it back.

READ_WRITE

yes

oracle_undo_to

Oracle Undo To

Undo the reversible workspace: ROLLBACK TO SAVEPOINT discards every held statement executed after that checkpoint and releases the checkpoints stacked above it, leaving the transaction open.

READ_WRITE

yes

oracle_preview_dml

Oracle Preview DML

Dry-run one DML statement: the server brackets it in its own savepoint, executes it, reads the rows it touched, then rolls back to that savepoint and presents the result — nothing is committed and nothing is left behind.

READ_WRITE

yes

oracle_compile_object

Oracle Compile Object

Preview or compile one PL/SQL/view object through the active DDL profile gate; preview is the default and execution requires the returned confirmation token.

DDL

yes

oracle_create_or_replace

Oracle Create Or Replace

Preview or apply one CREATE OR REPLACE statement through the classifier and active DDL profile gate.

DDL

yes

oracle_patch_source

Oracle Patch Source

Preview or apply an exact old_text to new_text replacement against one stored source object; preview refetches the current source and execute uses the existing DDL confirmation gate.

DDL

yes

oracle_list_schemas

Oracle List Schemas

List schemas that own objects visible to this session, optionally filtered by name.

READ_ONLY

no

oracle_schema_inspect

Oracle Schema Inspect

List objects in the current schema, one owner, or all accessible schemas, with optional type/name filters.

READ_ONLY

no

oracle_search_objects

Oracle Search Objects

Unified read-only object search/inspection with a detail_level.

READ_ONLY

no

oracle_orient

Oracle Orient

Return bounded orientation evidence: by default one cacheable snapshot for the active profile; fleet=true maps every MCP-visible profile independently with schema, version, freshness, drift, and typed UNREACHABLE/FAIL_CLOSED lane status.

READ_ONLY

no

oracle_describe

Oracle Describe

Describe a table/view's columns and constraint metadata.

READ_ONLY

no

oracle_describe_index

Oracle Describe Index

Describe one index's metadata, indexed columns, and function-based expressions.

READ_ONLY

no

oracle_describe_trigger

Oracle Describe Trigger

Describe one trigger's timing, event, target table, status, and body.

READ_ONLY

no

oracle_describe_view

Oracle Describe View

Describe one view's definition metadata and columns.

READ_ONLY

no

oracle_get_ddl

Oracle Get DDL

Fetch an object's DDL via DBMS_METADATA.GET_DDL (allowlisted object types).

READ_ONLY

no

oracle_get_source

Oracle Get Source

Fetch an object's full source text or inclusive line range from ALL_SOURCE, or fetch a view definition from ALL_VIEWS.TEXT, with a character cap.

READ_ONLY

no

oracle_sample_rows

Oracle Sample Rows

Read arbitrary first rows of a table or view with a hard row cap.

READ_ONLY

no

oracle_read_clob

Oracle Read CLOB

Read one CLOB/NCLOB/text value by key with a character cap.

READ_ONLY

no

oracle_compile_errors

Oracle Compile Errors

Retrieve compile errors for the current schema, an owner, or one object (ALL_ERRORS).

READ_ONLY

no

oracle_search_source

Oracle Search Source

Full-text search across ALL_SOURCE for a needle (row- and line-capped).

READ_ONLY

no

oracle_plscope_inspect

Oracle PL/Scope Inspect

Inspect PL/Scope identifier and SQL statement metadata for one PL/SQL object when ALL_IDENTIFIERS/ALL_STATEMENTS are populated.

READ_ONLY

no

oracle_explain_plan

Oracle Explain Plan

Explicit diagnostic-write EXPLAIN PLAN for a vetted SELECT; writes PLAN_TABLE, requires READ_WRITE plus allow_plan_table_write, and is disabled on read-only standby.

READ_WRITE

yes

oracle_top_queries

Oracle Top Queries

Read-only top-SQL ranked by elapsed/CPU/buffer-gets/disk-reads over the free live cursor cache (V$SQLSTATS); live calls may narrow by exact sql_id or bounded sql_text.

READ_ONLY

no

oracle_plan_timeline

Oracle Plan Timeline

Read-only historical optimizer plan and relative-cost timeline from AWR snapshots for one SQL ID.

READ_ONLY

no

oracle_db_health

Oracle Db Health

Read-only DBA health-check suite.

READ_ONLY

no

oracle_plsql_parse

Oracle Plsql Parse

Parse PL/SQL source with the offline plsql-intelligence lowerer and return declaration and diagnostic counts.

READ_ONLY

no

oracle_plsql_analyze

Oracle Plsql Analyze

Run the offline plsql-intelligence engine over a local project root and return doctor summaries.

READ_ONLY

no

oracle_plsql_what_breaks

Oracle Plsql What Breaks

Predict invalidation and recompilation impact for a PL/SQL ChangeSet without touching Oracle.

READ_ONLY

no

oracle_plsql_lineage

Oracle Plsql Lineage

Run offline dependency-lineage traversal from a logical object id in a local PL/SQL project.

READ_ONLY

no

oracle_lineage

Oracle Lineage

Live-verified COLUMN lineage: cross-check source-derived owner.object.column edges against the guarded Oracle catalog and mark verified, missing, or type-mismatched drift.

READ_ONLY

no

oracle_plsql_sast

Oracle Plsql Sast

Run the offline plsql-sast rule harness over a local PL/SQL project and return findings plus skipped-rule evidence.

READ_ONLY

no

oracle_plsql_doc

Oracle Plsql Doc

Extract doc comments from source or render an existing plsql-doc DocSet.

READ_ONLY

no

oracle_plsql_live_snapshot

Oracle Plsql Live Snapshot

Extract live Oracle dictionary rowsets and normalize them through plsql-intelligence CatalogSnapshotBuilder.

READ_ONLY

no

oracle_plsql_blast_radius

Oracle Plsql Blast Radius

Extract a live catalog snapshot, then run the plsql-cicd change-impact predictor for a proposed ChangeSet.

READ_ONLY

no

Every advertised tool descriptor includes a human title plus explicit MCP annotations; these hints are advisory for clients, while the fail-closed classifier and operating-level gate remain the enforcement boundary. oracle_query and oracle_explain_plan also advertise outputSchema, and query results keep Oracle NUMBER cells as strings by default (opt into numbers_as_float=true explicitly). Beyond tools/*, initialize advertises resources, prompts, and completions (protocol 2025-11-25): resources/list exposes oracle://capabilities and oracle://tools, and read templates for oracle://schema/{owner} and oracle://object/{owner}/{type}/{name} route through the same safe dispatch path.

Compatibility aliases

For migrations from shorter Oracle MCP tool surfaces, the server advertises compatibility aliases that route to the guarded oracle_* tools and share their classifier, validation, and operating-level behavior. execute_approved, deploy_ddl, and read_patch_preview are wrappers rather than plain renames.

Alias

Routes to

current_database

oracle_connection_info

switch_database

oracle_switch_profile

enable_writes

oracle_set_session_level

disable_writes

oracle_set_session_level

query

oracle_query

preview_sql

oracle_preview_sql

execute_approved

oracle_execute

compile_object

oracle_compile_object

compile_with_warnings

oracle_compile_object

create_or_replace

oracle_create_or_replace

patch_package

oracle_patch_source

patch_view

oracle_patch_source

read_patch_preview

oracle_patch_source

deploy_ddl

oracle_create_or_replace

list_objects

oracle_schema_inspect

list_schemas

oracle_list_schemas

get_schema

oracle_schema_inspect

describe_table

oracle_describe

describe_index

oracle_describe_index

describe_trigger

oracle_describe_trigger

describe_view

oracle_describe_view

get_ddl

oracle_get_ddl

get_object_source

oracle_get_source

get_errors

oracle_compile_errors

get_clob

oracle_read_clob

Configuration

Connection profiles live in profiles.toml. No secrets are written to disk — credentials are references resolved at runtime through env:, file:, or keyring:. A minimal read-only profile:

[profiles.db_ro]
connect_string = "//db.example.com:1521/FREEPDB1"
username       = "APP_RO"
credential_ref = "env:ORACLE_APP_PASSWORD"
# default_level defaults to read_only and is the ceiling for this profile;
# set max_level to permit explicit, TTL-bounded elevation up to ADMIN.

The full field reference — HTTP TLS/mTLS/OAuth listeners, the signed audit chain, result-masking policy, fleet/monitor profiles, TCPS/wallet and IAM/DRCP/proxy auth, and per-call timeout/SDU budgets — is in docs/configuration.md.

Documentation

Build from source

This branch is pinned to nightly-2026-05-11 and has no stable MSRV (the pin arrives transitively through asupersync, and Windows needs windows_by_handle; see docs/toolchain.md). Prefer the verified release archive above; build from source only when you intend to:

rustup toolchain install nightly-2026-05-11 --component rustfmt --component clippy
cargo +nightly-2026-05-11 install oraclemcp

Live database access is built in through the pure-Rust thin driver — no Oracle Instant Client, ODPI-C, or C toolchain. Optionally set TNS_ADMIN for net-service-name connections. The default build embeds the offline PL/SQL engine; --no-default-features omits it.

License

Licensed under Apache-2.0 OR MIT. The Docker image and crates do not redistribute Oracle Instant Client.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Read-only MCP server that lets coding AI agents inspect Oracle Database schema through live metadata.
    -
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables read-only exploration of Oracle databases through natural language, providing schema inspection and safe bounded SQL query execution.
    -
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to connect to Oracle databases for schema exploration, PL/SQL source inspection, and read-only SQL queries, with optional write operations when explicitly enabled.
    -