Skip to content

MCP Servers

Location: inception_mcp_servers/

Every MCP server follows the same 3-file pattern — keeping bootstrap, tool logic, and exposure control strictly separated.

server.py    ← loads env, creates FastMCP, configures auth, starts transport
registry.py  ← TOOL_REGISTRY: the only tools exposed to callers
tools.py     ← implements all callable tool functions

Request flow: Client POST → server routes → tools.py executes → OCI API called → response returned.

Authentication modes

Mode File Mechanism
Interactive OIDC server_oidc.py Browser-based OCI IAM OIDC flow
Token / JWT bearer server_token.py Authorization: Bearer <token> header

1. SQLcl MCP (src/mcp_sqlcl)

Endpoint: http://127.0.0.1:3001/mcp/

Exposes Oracle Database via SQLcl. Each call spawns a per-request SQLcl stdio session — no shared global state.

Tools:

Tool Description
execute_sql(query) Run SQL and return JSON results
schema_information() Return table/column schema
test_connection() Verify connectivity
whoami() Return calling user identity

Start:

.venv_mcp_servers/bin/python -m src.mcp_sqlcl.server_token

Key env vars: SQLCL_PATH, SQLCL_CONNECTION, MCP_PORT=3001, IDCS_DOMAIN, IDCS_CLIENT_ID, IDCS_CLIENT_SECRET

Add/remove tools — edit registry.py:

TOOL_REGISTRY = {
    "execute_sql": sqlcl_tools.execute_sql,
    "schema_information": sqlcl_tools.schema_information,
}

2. Object Storage MCP (src/mcp_server_os)

Endpoint: http://127.0.0.1:3002/mcp/

Exposes OCI Object Storage. Uses TokenExchangeSigner — IDCS token → OCI IAM token per request.

Tools:

Tool Description
get_os_namespace() Return tenancy namespace
upload_object_file(bucket, name, path) Upload a local file
list_objects(bucket) List bucket contents
delete_object(bucket, name) Delete an object
whoami() Return IAM identity

Key env vars: MCP_HOST_MCP_OS, MCP_PORT_MCP_OS=3002, IDCS_DOMAIN, IDCS_CLIENT_ID, IDCS_CLIENT_SECRET


3. ADW MCP (src/mcp_adw)

Endpoint: http://127.0.0.1:8003/mcp/

Exposes Autonomous Data Warehouse with full end-to-end IAM token propagation. Unlike the SQLcl server (which uses a per-request subprocess), the ADW MCP connects directly through the Oracle Python driver with wallet-based mTLS.

Token flow:

MCP Client (SSO token) → IAM exchange → DB token → Oracle ADB (wallet mTLS) → audit trail

Tools:

Tool Description
query_adw(select_statement, bind_params=None) Execute a read-only SELECT against ADW and return row results
execute_dml(statement, bind_params=None) Execute an INSERT/UPDATE against ADW under the same identity-propagated session as query_adw, return affected row count (added for united_health_pror_auth's prior-auth recipe — the first consumer needing per-user VPD-enforced writes, not just reads)
whoami() Return the resolved IAM identity and enabled Oracle session roles for the current token

Key env vars: IAM_DB_DNS_NAME, IAM_WALLET_DIRECTORY, IDCS_DOMAIN, IDCS_CLIENT_ID

Start:

nohup python src/backend/mcp_adw_server.py > logs/mcp_server.log 2>&1 &

4. OCI Database MCP (src/mcp_oci_control_plane_database)

Endpoint: http://127.0.0.1:8004/mcp/

Exposes OCI Database Cloud Service control-plane operations (list/administer database resources, not query rows in a schema). Uses TokenExchangeSigner — same auth model as Object Storage MCP, just handed to oci.database.DatabaseClient instead of ObjectStorageClient. Sibling to Object Storage MCP's control-plane pattern, not to ADW MCP's wallet-mTLS SQL pattern.

Tools:

Tool Description
list_autonomous_db_versions(compartment_id, db_workload=None, limit=None) Lists Autonomous Database versions supported in a compartment. Read-only.
whoami() Return the caller's identity claims from the verified bearer token
get_token() Return the caller's own access token (debugging/bootstrap use)

Start:

cd inception_mcp_servers/mcp_oci_control_plane_database
uv run python -m src.server

Key env vars: IAM_OCI_REGION, IAM_IDCS_CLIENT_ID, IAM_IDCS_CLIENT_SECRET, TOKEN_FACTORY_* (see the module's sample.env)

Add/remove tools — edit registry.py:

TOOL_REGISTRY = {
    "list_autonomous_db_versions": db_tools.list_autonomous_db_versions,
    "whoami": db_tools.whoami,
    "get_token": db_tools.get_token,
}

Full details, including the two-server (server.py / server_oidc.py) bootstrap flow and a dependency-pin gotcha (mcp==1.22.0), are in docs/mcp-servers/mcp-oci-control-plane-database.md.


Shared patterns

Per-request token validation

Every call validates the bearer token before executing any tool. There are no persistent authenticated sessions — if a token expires mid-session, the next call returns a 401 and the client must re-authenticate. This prevents stale sessions from retaining elevated access.

Explicit registry

Only tools listed in TOOL_REGISTRY are reachable. If a developer adds a new function to tools.py without registering it, it is never exposed — no accidental tool surface. This makes security audits straightforward: one registry file = complete capability inventory.

Stderr logging

MCP protocol uses stdout for JSON-framed tool responses. All server-side logs go to stderr to prevent protocol corruption. Route stderr to a log file:

python -m src.mcp_sqlcl.server_token 2>> logs/mcp_sqlcl.log

Testing and diagnostics

# Kill a stuck server on port 3001
lsof -ti tcp:3001 | xargs kill -9

# Interactive MCP Inspector (requires OIDC auth flow in browser)
fastmcp dev --server-spec src/mcp_sqlcl/server_oidc.py:mcp

# Direct API test (token mode)
export MCP_ACCESS_TOKEN="<your-token>"
python src/mcp_sqlcl/test_mcp_sqlcl.py --url http://127.0.0.1:3001/mcp/ --limit 5