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:
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:
Tools:
| Tool | Description |
|---|---|
query_adw(sql) |
Execute SQL against ADW and return row results |
get_schema(table_name) |
Return column definitions for a table |
test_connection() |
Verify ADW connectivity and wallet config |
whoami() |
Return the resolved IAM identity for the current token |
Key env vars: IAM_DB_DNS_NAME, IAM_WALLET_DIRECTORY, IDCS_DOMAIN, IDCS_CLIENT_ID
Start:
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:
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