oracle-mcp-common 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- oracle_mcp_common-0.1.0/.gitignore +39 -0
- oracle_mcp_common-0.1.0/PKG-INFO +290 -0
- oracle_mcp_common-0.1.0/README.md +275 -0
- oracle_mcp_common-0.1.0/oracle_mcp_common/__init__.py +30 -0
- oracle_mcp_common-0.1.0/oracle_mcp_common/auth.py +587 -0
- oracle_mcp_common-0.1.0/oracle_mcp_common/tests/test_auth.py +629 -0
- oracle_mcp_common-0.1.0/pyproject.toml +49 -0
- oracle_mcp_common-0.1.0/uv.lock +1483 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
**/__pycache__/**
|
|
2
|
+
|
|
3
|
+
# Virtual environment
|
|
4
|
+
venv/
|
|
5
|
+
.env/
|
|
6
|
+
.venv/
|
|
7
|
+
ENV/
|
|
8
|
+
env/
|
|
9
|
+
env.bak/
|
|
10
|
+
venv.bak/
|
|
11
|
+
|
|
12
|
+
# Python uv
|
|
13
|
+
.python-version
|
|
14
|
+
|
|
15
|
+
# VScode
|
|
16
|
+
.vscode
|
|
17
|
+
|
|
18
|
+
# Mac files
|
|
19
|
+
.DS_Store
|
|
20
|
+
|
|
21
|
+
#IDE
|
|
22
|
+
.idea
|
|
23
|
+
|
|
24
|
+
# test environments
|
|
25
|
+
.env
|
|
26
|
+
|
|
27
|
+
.coverage*
|
|
28
|
+
htmlcov/
|
|
29
|
+
|
|
30
|
+
# Maven
|
|
31
|
+
**/target/
|
|
32
|
+
|
|
33
|
+
# GoldenGate MCP local runtime artifacts
|
|
34
|
+
**/logs/
|
|
35
|
+
**/oracle-goldengate-mcp-server.env
|
|
36
|
+
**/build/**
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
.csis
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: oracle-mcp-common
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Shared utilities for Oracle MCP Python servers
|
|
5
|
+
Project-URL: Documentation, https://github.com/oracle/mcp
|
|
6
|
+
Author-email: Oracle MCP <237432095+oracle-mcp@users.noreply.github.com>
|
|
7
|
+
License-Expression: UPL-1.0
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Classifier: Programming Language :: Python
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
11
|
+
Requires-Python: >=3.13
|
|
12
|
+
Requires-Dist: fastmcp<4.0.0,>=3.2.4
|
|
13
|
+
Requires-Dist: oci>=2.179.0
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# Oracle MCP Common
|
|
17
|
+
|
|
18
|
+
`oracle-mcp-common` is the shared Python library for Oracle MCP servers. It
|
|
19
|
+
provides reusable components that belong in more than one server while keeping
|
|
20
|
+
server-specific tools, client lifecycles, and service behavior in each server.
|
|
21
|
+
|
|
22
|
+
The library currently provides OCI SDK authentication through
|
|
23
|
+
`oracle_mcp_common.auth`. Future shared modules should follow the same
|
|
24
|
+
server-agnostic approach and expose a focused, documented public API.
|
|
25
|
+
|
|
26
|
+
## Package requirements
|
|
27
|
+
|
|
28
|
+
- Python 3.13 or later
|
|
29
|
+
- OCI Python SDK 2.179.0 or later
|
|
30
|
+
- FastMCP 3.4.2 for the optional HTTP IDCS authentication API
|
|
31
|
+
|
|
32
|
+
An adopting server normally declares a bounded dependency on this package:
|
|
33
|
+
|
|
34
|
+
```toml
|
|
35
|
+
dependencies = [
|
|
36
|
+
"oracle-mcp-common>=0.1.0,<0.2.0",
|
|
37
|
+
]
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Authentication module
|
|
41
|
+
|
|
42
|
+
`oracle_mcp_common.auth` resolves outbound authentication for OCI Python SDK
|
|
43
|
+
clients. It chooses a supported authentication type and returns the SDK-native
|
|
44
|
+
ingredients needed to create a service client.
|
|
45
|
+
|
|
46
|
+
The module owns credential resolution only. Each server continues to own its
|
|
47
|
+
OCI client type, retry and circuit-breaker policy, `additional_user_agent`, and
|
|
48
|
+
client lifecycle.
|
|
49
|
+
|
|
50
|
+
### Quick start
|
|
51
|
+
|
|
52
|
+
Set up OCI credentials for the authentication type you intend to use, then
|
|
53
|
+
build a context and pass its config and signer to the OCI SDK client.
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
import oci
|
|
57
|
+
|
|
58
|
+
from oracle_mcp_common import build_auth_context
|
|
59
|
+
|
|
60
|
+
auth_context = build_auth_context()
|
|
61
|
+
config = {
|
|
62
|
+
**auth_context.config,
|
|
63
|
+
"additional_user_agent": "oci-example-mcp/1.2.3",
|
|
64
|
+
}
|
|
65
|
+
client = oci.object_storage.ObjectStorageClient(config, signer=auth_context.signer)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The returned `AuthContext` contains:
|
|
69
|
+
|
|
70
|
+
| Field | Meaning |
|
|
71
|
+
| --- | --- |
|
|
72
|
+
| `auth_type` | The selected `AuthType`; `auto` is resolved to `api_key` or `security_token`. |
|
|
73
|
+
| `config` | An OCI SDK config dictionary. It contains the resolved `region` when one is available. |
|
|
74
|
+
| `signer` | The OCI SDK signer to pass to a client constructor. |
|
|
75
|
+
| `tenancy_id` | Tenancy metadata when the selected signer or profile supplies it. |
|
|
76
|
+
| `region` | The resolved client region, if available. |
|
|
77
|
+
| `profile_name` | The selected profile for profile-backed authentication; otherwise `None`. |
|
|
78
|
+
|
|
79
|
+
### Select an authentication type
|
|
80
|
+
|
|
81
|
+
Set `OCI_MCP_AUTH_TYPE`, or pass `AuthOptions(auth_type=...)` to
|
|
82
|
+
`build_auth_context()`. The supported values are:
|
|
83
|
+
|
|
84
|
+
| Type | Credential source | Notes |
|
|
85
|
+
| --- | --- | --- |
|
|
86
|
+
| `auto` | Selected OCI config profile | Uses `security_token` only if the selected profile directly declares `security_token_file`; otherwise uses `api_key`. |
|
|
87
|
+
| `api_key` | Selected OCI config profile | Requires `tenancy`, `user`, `fingerprint`, and `key_file`. The library logs a one-time recommendation to use session-token authentication. |
|
|
88
|
+
| `security_token` | Selected OCI config profile | Requires `security_token_file` directly in the selected profile, plus the API-key fields required to construct its signer. |
|
|
89
|
+
| `identity_domain_upst` | Identity Domains JWT-to-UPST token exchange | Uses file-backed JWT and client-secret inputs. See [Identity Domains token exchange](#identity-domains-token-exchange). |
|
|
90
|
+
| `instance_principal` | OCI instance principal | Intended for OCI compute instances. |
|
|
91
|
+
| `resource_principal` | OCI resource principal | Intended for supported OCI managed-resource environments. |
|
|
92
|
+
| `instance_principal_delegation` | Instance principal and delegation token | Requires a delegation-token file. |
|
|
93
|
+
| `resource_principal_delegation` | Resource principal and delegation token | Requires a delegation-token file. |
|
|
94
|
+
| `oke_workload_identity` | OKE workload identity | Uses the OCI SDK's default service-account token unless an override is supplied. |
|
|
95
|
+
|
|
96
|
+
`auto` intentionally does not probe instance, resource, delegation, or OKE
|
|
97
|
+
principal environments. Select those types explicitly so a deployment's OCI
|
|
98
|
+
identity remains predictable.
|
|
99
|
+
|
|
100
|
+
### Configuration precedence
|
|
101
|
+
|
|
102
|
+
An explicit non-empty `AuthOptions` value wins over its canonical environment
|
|
103
|
+
variable. Empty strings are treated as unset.
|
|
104
|
+
|
|
105
|
+
| Setting | Precedence, highest first |
|
|
106
|
+
| --- | --- |
|
|
107
|
+
| Authentication type | `AuthOptions.auth_type` → `OCI_MCP_AUTH_TYPE` → supported legacy aliases → `auto` |
|
|
108
|
+
| Config file | `AuthOptions.config_file` → `OCI_CONFIG_FILE` → OCI SDK default location |
|
|
109
|
+
| Profile | `AuthOptions.profile_name` → `OCI_CONFIG_PROFILE` → `ORACLE_MCP_AUTH_PROFILE` → OCI SDK default profile |
|
|
110
|
+
| Region | `AuthOptions.region` → `OCI_REGION` → profile- or signer-derived region |
|
|
111
|
+
| Other type-specific inputs | Their matching `AuthOptions` field → canonical `OCI_MCP_*` variable → documented legacy alias, if one exists |
|
|
112
|
+
|
|
113
|
+
`OCI_REGION` changes the region used for the returned SDK client config. It
|
|
114
|
+
does not change the selected profile, tenancy, signing key, or principal
|
|
115
|
+
credential source.
|
|
116
|
+
|
|
117
|
+
#### Profile-backed authentication
|
|
118
|
+
|
|
119
|
+
`auto`, `api_key`, and `security_token` honor the usual OCI CLI-compatible
|
|
120
|
+
variables: `OCI_CONFIG_FILE` and `OCI_CONFIG_PROFILE`.
|
|
121
|
+
|
|
122
|
+
For safety, `security_token_file` must be declared in the selected profile's
|
|
123
|
+
own section. A value inherited from `[DEFAULT]` is not treated as a session
|
|
124
|
+
token for another profile. This prevents an inherited setting from silently
|
|
125
|
+
changing the OCI principal used by a named API-key profile.
|
|
126
|
+
|
|
127
|
+
Once a selected profile directly declares a session token, the library reports
|
|
128
|
+
an unreadable token or incomplete session configuration instead of falling
|
|
129
|
+
back to API-key authentication.
|
|
130
|
+
|
|
131
|
+
### Type-specific inputs
|
|
132
|
+
|
|
133
|
+
| Authentication type | Required inputs | Optional inputs |
|
|
134
|
+
| --- | --- | --- |
|
|
135
|
+
| `identity_domain_upst` | `OCI_MCP_IDENTITY_DOMAIN_URL`, `OCI_MCP_UPST_JWT_FILE`, `OCI_MCP_IDENTITY_DOMAIN_CLIENT_ID`, `OCI_MCP_IDENTITY_DOMAIN_CLIENT_SECRET_FILE`, and a region | Explicit `AuthOptions` equivalents |
|
|
136
|
+
| `*_delegation` | `OCI_MCP_DELEGATION_TOKEN_FILE` | Deprecated `OCI_MCP_DELEGATION_TOKEN` compatibility input |
|
|
137
|
+
| `oke_workload_identity` | None | `OCI_MCP_OKE_SERVICE_ACCOUNT_TOKEN_PATH`; deprecated inline-token compatibility input |
|
|
138
|
+
| Principal types | None | `OCI_MCP_TENANCY_ID_OVERRIDE` when signer metadata does not provide a tenancy ID |
|
|
139
|
+
|
|
140
|
+
All file-backed secret values are read as UTF-8 and surrounding whitespace is
|
|
141
|
+
trimmed. The library reports the variable name when a value is absent,
|
|
142
|
+
unreadable, or empty, without including secret contents in the error.
|
|
143
|
+
|
|
144
|
+
### Identity Domains token exchange
|
|
145
|
+
|
|
146
|
+
Use `identity_domain_upst` when a file-backed Identity Domains service-bearer
|
|
147
|
+
JWT must be exchanged for an OCI User Principal Security Token (UPST).
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
export OCI_MCP_AUTH_TYPE=identity_domain_upst
|
|
151
|
+
export OCI_MCP_IDENTITY_DOMAIN_URL=https://example.identity.oraclecloud.com
|
|
152
|
+
export OCI_MCP_UPST_JWT_FILE=/var/run/secrets/identity/jwt
|
|
153
|
+
export OCI_MCP_IDENTITY_DOMAIN_CLIENT_ID=example-client-id
|
|
154
|
+
export OCI_MCP_IDENTITY_DOMAIN_CLIENT_SECRET_FILE=/var/run/secrets/identity/client-secret
|
|
155
|
+
export OCI_REGION=us-chicago-1
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
The URL must be an absolute `https://` URL with a host. The Identity Domain
|
|
159
|
+
must have an Identity Propagation Trust that accepts the JWT and an OAuth client
|
|
160
|
+
authorized for token exchange.
|
|
161
|
+
|
|
162
|
+
The JWT file is read again when the OCI SDK refreshes the UPST, so a rotated JWT
|
|
163
|
+
at the same path can be observed by an existing signer. The client secret is
|
|
164
|
+
read when the signer is created; rotating that secret requires a controlled
|
|
165
|
+
process restart that recreates the signer and every cached OCI client. A
|
|
166
|
+
replacement process should complete an initial token exchange before it accepts
|
|
167
|
+
traffic.
|
|
168
|
+
|
|
169
|
+
This outbound token-exchange type is independent of inbound HTTP MCP OAuth.
|
|
170
|
+
It does not read request access tokens or FastMCP transport configuration.
|
|
171
|
+
|
|
172
|
+
### HTTP IDCS authentication
|
|
173
|
+
|
|
174
|
+
Use the HTTP IDCS API when an HTTP MCP server must authenticate each caller
|
|
175
|
+
through OCI IAM and make OCI SDK calls as that caller. This is intentionally a
|
|
176
|
+
different path from `build_auth_context()`: stdio continues to use the flexible
|
|
177
|
+
OCI profile, principal, and service-bearer authentication modes above.
|
|
178
|
+
|
|
179
|
+
At startup, build the HTTP policy with the scopes required by the server and
|
|
180
|
+
assign its provider to FastMCP. During an authenticated request, pass the
|
|
181
|
+
request token explicitly to create an OCI SDK context.
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
import oci
|
|
185
|
+
from fastmcp.server.dependencies import get_access_token
|
|
186
|
+
|
|
187
|
+
from oracle_mcp_common import build_idcs_http_auth
|
|
188
|
+
|
|
189
|
+
http_auth = build_idcs_http_auth(
|
|
190
|
+
["openid", "profile", "email", "oci_mcp.example.invoke"]
|
|
191
|
+
)
|
|
192
|
+
mcp.auth = http_auth.provider
|
|
193
|
+
|
|
194
|
+
# Call only while handling an authenticated HTTP request.
|
|
195
|
+
request_token = get_access_token()
|
|
196
|
+
request_auth = http_auth.context_for(request_token.token)
|
|
197
|
+
config = {
|
|
198
|
+
**request_auth.config,
|
|
199
|
+
"additional_user_agent": "oci-example-mcp/1.2.3",
|
|
200
|
+
}
|
|
201
|
+
client = oci.object_storage.ObjectStorageClient(config, signer=request_auth.signer)
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
`build_idcs_http_auth()` validates the provider configuration before it creates
|
|
205
|
+
FastMCP's `OCIProvider`. It does not inspect `ORACLE_MCP_HOST` or
|
|
206
|
+
`ORACLE_MCP_PORT`, start the listener, assign `mcp.auth`, read FastMCP request
|
|
207
|
+
context, create a service client, or set `additional_user_agent`; the adopting
|
|
208
|
+
server owns each of those steps.
|
|
209
|
+
|
|
210
|
+
| Setting | Purpose |
|
|
211
|
+
| --- | --- |
|
|
212
|
+
| `IDCS_DOMAIN` | Identity Domains host, such as `example.identity.oraclecloud.com`, or an absolute `https://` origin. |
|
|
213
|
+
| `IDCS_CLIENT_ID` / `IDCS_CLIENT_SECRET` | OAuth client used for the provider and request-token exchange. Keep the secret in the deployment secret store. |
|
|
214
|
+
| `IDCS_AUDIENCE` | Audience configured for the MCP OAuth client. |
|
|
215
|
+
| `ORACLE_MCP_BASE_URL` | Absolute public HTTP or HTTPS server URL; include a mount path when applicable. Register `${ORACLE_MCP_BASE_URL}/auth/callback` with the OCI IAM confidential application. |
|
|
216
|
+
| `OCI_REGION` | Region used for the returned OCI SDK context, unless `context_for(..., region=...)` supplies one explicitly. |
|
|
217
|
+
|
|
218
|
+
The HTTP access token is required for `context_for()` and is never read from a
|
|
219
|
+
global FastMCP context by the library. Treat each returned signer and any OCI
|
|
220
|
+
client built with it as caller-specific: do not cache it globally or reuse it
|
|
221
|
+
for another request. Provider configuration and token-exchange errors identify
|
|
222
|
+
missing settings but never include access-token or client-secret values.
|
|
223
|
+
|
|
224
|
+
### Delegation and OKE token inputs
|
|
225
|
+
|
|
226
|
+
For delegation types, use a mounted file:
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
export OCI_MCP_AUTH_TYPE=instance_principal_delegation
|
|
230
|
+
export OCI_MCP_DELEGATION_TOKEN_FILE=/var/run/secrets/oci/delegation-token
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Do not set both the file and inline token inputs. Inline delegation tokens are
|
|
234
|
+
compatibility-only because environment variables are more easily exposed in
|
|
235
|
+
process inspection and diagnostics.
|
|
236
|
+
|
|
237
|
+
For OKE workload identity, the default OCI SDK token discovery needs no
|
|
238
|
+
configuration. To use a non-default mounted token, set
|
|
239
|
+
`OCI_MCP_OKE_SERVICE_ACCOUNT_TOKEN_PATH`. Do not set both the path and the
|
|
240
|
+
deprecated inline token input.
|
|
241
|
+
|
|
242
|
+
### Compatibility aliases
|
|
243
|
+
|
|
244
|
+
Canonical `OCI_MCP_*` inputs take precedence. The following aliases are
|
|
245
|
+
accepted only during the migration window and emit a one-time deprecation
|
|
246
|
+
warning when used:
|
|
247
|
+
|
|
248
|
+
| Canonical input | Supported legacy aliases |
|
|
249
|
+
| --- | --- |
|
|
250
|
+
| `OCI_MCP_AUTH_TYPE` | `OCI_IOT_AUTH_TYPE`, `OCI_AUTH_TYPE`, `ORACLE_MCP_AUTH_METHOD` |
|
|
251
|
+
| `OCI_CONFIG_PROFILE` | `ORACLE_MCP_AUTH_PROFILE` |
|
|
252
|
+
| `OCI_MCP_DELEGATION_TOKEN_FILE` | `OCI_IOT_DELEGATION_TOKEN` (inline token) |
|
|
253
|
+
| `OCI_MCP_OKE_SERVICE_ACCOUNT_TOKEN_PATH` | `OCI_IOT_OKE_SERVICE_ACCOUNT_TOKEN_PATH` |
|
|
254
|
+
| Deprecated OKE inline token | `OCI_IOT_OKE_SERVICE_ACCOUNT_TOKEN` |
|
|
255
|
+
| `OCI_MCP_TENANCY_ID_OVERRIDE` | `OCI_IOT_TENANCY_ID_OVERRIDE`, `TENANCY_ID_OVERRIDE` |
|
|
256
|
+
|
|
257
|
+
The compatibility window begins with version 0.1.0 and ends no earlier than the
|
|
258
|
+
later of 180 days or two published adopter-server release waves. Removals are
|
|
259
|
+
planned no earlier than version 0.2.0.
|
|
260
|
+
|
|
261
|
+
### Public API
|
|
262
|
+
|
|
263
|
+
```python
|
|
264
|
+
from oracle_mcp_common import (
|
|
265
|
+
AuthContext,
|
|
266
|
+
AuthOptions,
|
|
267
|
+
AuthType,
|
|
268
|
+
build_auth_context,
|
|
269
|
+
profile_declares_security_token,
|
|
270
|
+
)
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Use `profile_declares_security_token(config_file, profile_name)` when a caller
|
|
274
|
+
needs the same inheritance-safe classification without constructing an OCI SDK
|
|
275
|
+
signer. For example, an OCI CLI wrapper can use it to decide whether an
|
|
276
|
+
explicit `--auth` flag is appropriate.
|
|
277
|
+
|
|
278
|
+
## Development
|
|
279
|
+
|
|
280
|
+
From the repository root, run the package test suite with:
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
make test project=common
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Run the repository Python lint check after source changes:
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
make lint
|
|
290
|
+
```
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
# Oracle MCP Common
|
|
2
|
+
|
|
3
|
+
`oracle-mcp-common` is the shared Python library for Oracle MCP servers. It
|
|
4
|
+
provides reusable components that belong in more than one server while keeping
|
|
5
|
+
server-specific tools, client lifecycles, and service behavior in each server.
|
|
6
|
+
|
|
7
|
+
The library currently provides OCI SDK authentication through
|
|
8
|
+
`oracle_mcp_common.auth`. Future shared modules should follow the same
|
|
9
|
+
server-agnostic approach and expose a focused, documented public API.
|
|
10
|
+
|
|
11
|
+
## Package requirements
|
|
12
|
+
|
|
13
|
+
- Python 3.13 or later
|
|
14
|
+
- OCI Python SDK 2.179.0 or later
|
|
15
|
+
- FastMCP 3.4.2 for the optional HTTP IDCS authentication API
|
|
16
|
+
|
|
17
|
+
An adopting server normally declares a bounded dependency on this package:
|
|
18
|
+
|
|
19
|
+
```toml
|
|
20
|
+
dependencies = [
|
|
21
|
+
"oracle-mcp-common>=0.1.0,<0.2.0",
|
|
22
|
+
]
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Authentication module
|
|
26
|
+
|
|
27
|
+
`oracle_mcp_common.auth` resolves outbound authentication for OCI Python SDK
|
|
28
|
+
clients. It chooses a supported authentication type and returns the SDK-native
|
|
29
|
+
ingredients needed to create a service client.
|
|
30
|
+
|
|
31
|
+
The module owns credential resolution only. Each server continues to own its
|
|
32
|
+
OCI client type, retry and circuit-breaker policy, `additional_user_agent`, and
|
|
33
|
+
client lifecycle.
|
|
34
|
+
|
|
35
|
+
### Quick start
|
|
36
|
+
|
|
37
|
+
Set up OCI credentials for the authentication type you intend to use, then
|
|
38
|
+
build a context and pass its config and signer to the OCI SDK client.
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
import oci
|
|
42
|
+
|
|
43
|
+
from oracle_mcp_common import build_auth_context
|
|
44
|
+
|
|
45
|
+
auth_context = build_auth_context()
|
|
46
|
+
config = {
|
|
47
|
+
**auth_context.config,
|
|
48
|
+
"additional_user_agent": "oci-example-mcp/1.2.3",
|
|
49
|
+
}
|
|
50
|
+
client = oci.object_storage.ObjectStorageClient(config, signer=auth_context.signer)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The returned `AuthContext` contains:
|
|
54
|
+
|
|
55
|
+
| Field | Meaning |
|
|
56
|
+
| --- | --- |
|
|
57
|
+
| `auth_type` | The selected `AuthType`; `auto` is resolved to `api_key` or `security_token`. |
|
|
58
|
+
| `config` | An OCI SDK config dictionary. It contains the resolved `region` when one is available. |
|
|
59
|
+
| `signer` | The OCI SDK signer to pass to a client constructor. |
|
|
60
|
+
| `tenancy_id` | Tenancy metadata when the selected signer or profile supplies it. |
|
|
61
|
+
| `region` | The resolved client region, if available. |
|
|
62
|
+
| `profile_name` | The selected profile for profile-backed authentication; otherwise `None`. |
|
|
63
|
+
|
|
64
|
+
### Select an authentication type
|
|
65
|
+
|
|
66
|
+
Set `OCI_MCP_AUTH_TYPE`, or pass `AuthOptions(auth_type=...)` to
|
|
67
|
+
`build_auth_context()`. The supported values are:
|
|
68
|
+
|
|
69
|
+
| Type | Credential source | Notes |
|
|
70
|
+
| --- | --- | --- |
|
|
71
|
+
| `auto` | Selected OCI config profile | Uses `security_token` only if the selected profile directly declares `security_token_file`; otherwise uses `api_key`. |
|
|
72
|
+
| `api_key` | Selected OCI config profile | Requires `tenancy`, `user`, `fingerprint`, and `key_file`. The library logs a one-time recommendation to use session-token authentication. |
|
|
73
|
+
| `security_token` | Selected OCI config profile | Requires `security_token_file` directly in the selected profile, plus the API-key fields required to construct its signer. |
|
|
74
|
+
| `identity_domain_upst` | Identity Domains JWT-to-UPST token exchange | Uses file-backed JWT and client-secret inputs. See [Identity Domains token exchange](#identity-domains-token-exchange). |
|
|
75
|
+
| `instance_principal` | OCI instance principal | Intended for OCI compute instances. |
|
|
76
|
+
| `resource_principal` | OCI resource principal | Intended for supported OCI managed-resource environments. |
|
|
77
|
+
| `instance_principal_delegation` | Instance principal and delegation token | Requires a delegation-token file. |
|
|
78
|
+
| `resource_principal_delegation` | Resource principal and delegation token | Requires a delegation-token file. |
|
|
79
|
+
| `oke_workload_identity` | OKE workload identity | Uses the OCI SDK's default service-account token unless an override is supplied. |
|
|
80
|
+
|
|
81
|
+
`auto` intentionally does not probe instance, resource, delegation, or OKE
|
|
82
|
+
principal environments. Select those types explicitly so a deployment's OCI
|
|
83
|
+
identity remains predictable.
|
|
84
|
+
|
|
85
|
+
### Configuration precedence
|
|
86
|
+
|
|
87
|
+
An explicit non-empty `AuthOptions` value wins over its canonical environment
|
|
88
|
+
variable. Empty strings are treated as unset.
|
|
89
|
+
|
|
90
|
+
| Setting | Precedence, highest first |
|
|
91
|
+
| --- | --- |
|
|
92
|
+
| Authentication type | `AuthOptions.auth_type` → `OCI_MCP_AUTH_TYPE` → supported legacy aliases → `auto` |
|
|
93
|
+
| Config file | `AuthOptions.config_file` → `OCI_CONFIG_FILE` → OCI SDK default location |
|
|
94
|
+
| Profile | `AuthOptions.profile_name` → `OCI_CONFIG_PROFILE` → `ORACLE_MCP_AUTH_PROFILE` → OCI SDK default profile |
|
|
95
|
+
| Region | `AuthOptions.region` → `OCI_REGION` → profile- or signer-derived region |
|
|
96
|
+
| Other type-specific inputs | Their matching `AuthOptions` field → canonical `OCI_MCP_*` variable → documented legacy alias, if one exists |
|
|
97
|
+
|
|
98
|
+
`OCI_REGION` changes the region used for the returned SDK client config. It
|
|
99
|
+
does not change the selected profile, tenancy, signing key, or principal
|
|
100
|
+
credential source.
|
|
101
|
+
|
|
102
|
+
#### Profile-backed authentication
|
|
103
|
+
|
|
104
|
+
`auto`, `api_key`, and `security_token` honor the usual OCI CLI-compatible
|
|
105
|
+
variables: `OCI_CONFIG_FILE` and `OCI_CONFIG_PROFILE`.
|
|
106
|
+
|
|
107
|
+
For safety, `security_token_file` must be declared in the selected profile's
|
|
108
|
+
own section. A value inherited from `[DEFAULT]` is not treated as a session
|
|
109
|
+
token for another profile. This prevents an inherited setting from silently
|
|
110
|
+
changing the OCI principal used by a named API-key profile.
|
|
111
|
+
|
|
112
|
+
Once a selected profile directly declares a session token, the library reports
|
|
113
|
+
an unreadable token or incomplete session configuration instead of falling
|
|
114
|
+
back to API-key authentication.
|
|
115
|
+
|
|
116
|
+
### Type-specific inputs
|
|
117
|
+
|
|
118
|
+
| Authentication type | Required inputs | Optional inputs |
|
|
119
|
+
| --- | --- | --- |
|
|
120
|
+
| `identity_domain_upst` | `OCI_MCP_IDENTITY_DOMAIN_URL`, `OCI_MCP_UPST_JWT_FILE`, `OCI_MCP_IDENTITY_DOMAIN_CLIENT_ID`, `OCI_MCP_IDENTITY_DOMAIN_CLIENT_SECRET_FILE`, and a region | Explicit `AuthOptions` equivalents |
|
|
121
|
+
| `*_delegation` | `OCI_MCP_DELEGATION_TOKEN_FILE` | Deprecated `OCI_MCP_DELEGATION_TOKEN` compatibility input |
|
|
122
|
+
| `oke_workload_identity` | None | `OCI_MCP_OKE_SERVICE_ACCOUNT_TOKEN_PATH`; deprecated inline-token compatibility input |
|
|
123
|
+
| Principal types | None | `OCI_MCP_TENANCY_ID_OVERRIDE` when signer metadata does not provide a tenancy ID |
|
|
124
|
+
|
|
125
|
+
All file-backed secret values are read as UTF-8 and surrounding whitespace is
|
|
126
|
+
trimmed. The library reports the variable name when a value is absent,
|
|
127
|
+
unreadable, or empty, without including secret contents in the error.
|
|
128
|
+
|
|
129
|
+
### Identity Domains token exchange
|
|
130
|
+
|
|
131
|
+
Use `identity_domain_upst` when a file-backed Identity Domains service-bearer
|
|
132
|
+
JWT must be exchanged for an OCI User Principal Security Token (UPST).
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
export OCI_MCP_AUTH_TYPE=identity_domain_upst
|
|
136
|
+
export OCI_MCP_IDENTITY_DOMAIN_URL=https://example.identity.oraclecloud.com
|
|
137
|
+
export OCI_MCP_UPST_JWT_FILE=/var/run/secrets/identity/jwt
|
|
138
|
+
export OCI_MCP_IDENTITY_DOMAIN_CLIENT_ID=example-client-id
|
|
139
|
+
export OCI_MCP_IDENTITY_DOMAIN_CLIENT_SECRET_FILE=/var/run/secrets/identity/client-secret
|
|
140
|
+
export OCI_REGION=us-chicago-1
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
The URL must be an absolute `https://` URL with a host. The Identity Domain
|
|
144
|
+
must have an Identity Propagation Trust that accepts the JWT and an OAuth client
|
|
145
|
+
authorized for token exchange.
|
|
146
|
+
|
|
147
|
+
The JWT file is read again when the OCI SDK refreshes the UPST, so a rotated JWT
|
|
148
|
+
at the same path can be observed by an existing signer. The client secret is
|
|
149
|
+
read when the signer is created; rotating that secret requires a controlled
|
|
150
|
+
process restart that recreates the signer and every cached OCI client. A
|
|
151
|
+
replacement process should complete an initial token exchange before it accepts
|
|
152
|
+
traffic.
|
|
153
|
+
|
|
154
|
+
This outbound token-exchange type is independent of inbound HTTP MCP OAuth.
|
|
155
|
+
It does not read request access tokens or FastMCP transport configuration.
|
|
156
|
+
|
|
157
|
+
### HTTP IDCS authentication
|
|
158
|
+
|
|
159
|
+
Use the HTTP IDCS API when an HTTP MCP server must authenticate each caller
|
|
160
|
+
through OCI IAM and make OCI SDK calls as that caller. This is intentionally a
|
|
161
|
+
different path from `build_auth_context()`: stdio continues to use the flexible
|
|
162
|
+
OCI profile, principal, and service-bearer authentication modes above.
|
|
163
|
+
|
|
164
|
+
At startup, build the HTTP policy with the scopes required by the server and
|
|
165
|
+
assign its provider to FastMCP. During an authenticated request, pass the
|
|
166
|
+
request token explicitly to create an OCI SDK context.
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
import oci
|
|
170
|
+
from fastmcp.server.dependencies import get_access_token
|
|
171
|
+
|
|
172
|
+
from oracle_mcp_common import build_idcs_http_auth
|
|
173
|
+
|
|
174
|
+
http_auth = build_idcs_http_auth(
|
|
175
|
+
["openid", "profile", "email", "oci_mcp.example.invoke"]
|
|
176
|
+
)
|
|
177
|
+
mcp.auth = http_auth.provider
|
|
178
|
+
|
|
179
|
+
# Call only while handling an authenticated HTTP request.
|
|
180
|
+
request_token = get_access_token()
|
|
181
|
+
request_auth = http_auth.context_for(request_token.token)
|
|
182
|
+
config = {
|
|
183
|
+
**request_auth.config,
|
|
184
|
+
"additional_user_agent": "oci-example-mcp/1.2.3",
|
|
185
|
+
}
|
|
186
|
+
client = oci.object_storage.ObjectStorageClient(config, signer=request_auth.signer)
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
`build_idcs_http_auth()` validates the provider configuration before it creates
|
|
190
|
+
FastMCP's `OCIProvider`. It does not inspect `ORACLE_MCP_HOST` or
|
|
191
|
+
`ORACLE_MCP_PORT`, start the listener, assign `mcp.auth`, read FastMCP request
|
|
192
|
+
context, create a service client, or set `additional_user_agent`; the adopting
|
|
193
|
+
server owns each of those steps.
|
|
194
|
+
|
|
195
|
+
| Setting | Purpose |
|
|
196
|
+
| --- | --- |
|
|
197
|
+
| `IDCS_DOMAIN` | Identity Domains host, such as `example.identity.oraclecloud.com`, or an absolute `https://` origin. |
|
|
198
|
+
| `IDCS_CLIENT_ID` / `IDCS_CLIENT_SECRET` | OAuth client used for the provider and request-token exchange. Keep the secret in the deployment secret store. |
|
|
199
|
+
| `IDCS_AUDIENCE` | Audience configured for the MCP OAuth client. |
|
|
200
|
+
| `ORACLE_MCP_BASE_URL` | Absolute public HTTP or HTTPS server URL; include a mount path when applicable. Register `${ORACLE_MCP_BASE_URL}/auth/callback` with the OCI IAM confidential application. |
|
|
201
|
+
| `OCI_REGION` | Region used for the returned OCI SDK context, unless `context_for(..., region=...)` supplies one explicitly. |
|
|
202
|
+
|
|
203
|
+
The HTTP access token is required for `context_for()` and is never read from a
|
|
204
|
+
global FastMCP context by the library. Treat each returned signer and any OCI
|
|
205
|
+
client built with it as caller-specific: do not cache it globally or reuse it
|
|
206
|
+
for another request. Provider configuration and token-exchange errors identify
|
|
207
|
+
missing settings but never include access-token or client-secret values.
|
|
208
|
+
|
|
209
|
+
### Delegation and OKE token inputs
|
|
210
|
+
|
|
211
|
+
For delegation types, use a mounted file:
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
export OCI_MCP_AUTH_TYPE=instance_principal_delegation
|
|
215
|
+
export OCI_MCP_DELEGATION_TOKEN_FILE=/var/run/secrets/oci/delegation-token
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Do not set both the file and inline token inputs. Inline delegation tokens are
|
|
219
|
+
compatibility-only because environment variables are more easily exposed in
|
|
220
|
+
process inspection and diagnostics.
|
|
221
|
+
|
|
222
|
+
For OKE workload identity, the default OCI SDK token discovery needs no
|
|
223
|
+
configuration. To use a non-default mounted token, set
|
|
224
|
+
`OCI_MCP_OKE_SERVICE_ACCOUNT_TOKEN_PATH`. Do not set both the path and the
|
|
225
|
+
deprecated inline token input.
|
|
226
|
+
|
|
227
|
+
### Compatibility aliases
|
|
228
|
+
|
|
229
|
+
Canonical `OCI_MCP_*` inputs take precedence. The following aliases are
|
|
230
|
+
accepted only during the migration window and emit a one-time deprecation
|
|
231
|
+
warning when used:
|
|
232
|
+
|
|
233
|
+
| Canonical input | Supported legacy aliases |
|
|
234
|
+
| --- | --- |
|
|
235
|
+
| `OCI_MCP_AUTH_TYPE` | `OCI_IOT_AUTH_TYPE`, `OCI_AUTH_TYPE`, `ORACLE_MCP_AUTH_METHOD` |
|
|
236
|
+
| `OCI_CONFIG_PROFILE` | `ORACLE_MCP_AUTH_PROFILE` |
|
|
237
|
+
| `OCI_MCP_DELEGATION_TOKEN_FILE` | `OCI_IOT_DELEGATION_TOKEN` (inline token) |
|
|
238
|
+
| `OCI_MCP_OKE_SERVICE_ACCOUNT_TOKEN_PATH` | `OCI_IOT_OKE_SERVICE_ACCOUNT_TOKEN_PATH` |
|
|
239
|
+
| Deprecated OKE inline token | `OCI_IOT_OKE_SERVICE_ACCOUNT_TOKEN` |
|
|
240
|
+
| `OCI_MCP_TENANCY_ID_OVERRIDE` | `OCI_IOT_TENANCY_ID_OVERRIDE`, `TENANCY_ID_OVERRIDE` |
|
|
241
|
+
|
|
242
|
+
The compatibility window begins with version 0.1.0 and ends no earlier than the
|
|
243
|
+
later of 180 days or two published adopter-server release waves. Removals are
|
|
244
|
+
planned no earlier than version 0.2.0.
|
|
245
|
+
|
|
246
|
+
### Public API
|
|
247
|
+
|
|
248
|
+
```python
|
|
249
|
+
from oracle_mcp_common import (
|
|
250
|
+
AuthContext,
|
|
251
|
+
AuthOptions,
|
|
252
|
+
AuthType,
|
|
253
|
+
build_auth_context,
|
|
254
|
+
profile_declares_security_token,
|
|
255
|
+
)
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Use `profile_declares_security_token(config_file, profile_name)` when a caller
|
|
259
|
+
needs the same inheritance-safe classification without constructing an OCI SDK
|
|
260
|
+
signer. For example, an OCI CLI wrapper can use it to decide whether an
|
|
261
|
+
explicit `--auth` flag is appropriate.
|
|
262
|
+
|
|
263
|
+
## Development
|
|
264
|
+
|
|
265
|
+
From the repository root, run the package test suite with:
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
make test project=common
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Run the repository Python lint check after source changes:
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
make lint
|
|
275
|
+
```
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) 2026, Oracle and/or its affiliates.
|
|
3
|
+
Licensed under the Universal Permissive License v1.0 as shown at
|
|
4
|
+
https://oss.oracle.com/licenses/upl.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .auth import (
|
|
8
|
+
AuthContext,
|
|
9
|
+
AuthType,
|
|
10
|
+
AuthOptions,
|
|
11
|
+
IDCSHttpAuth,
|
|
12
|
+
IDCSHttpAuthContext,
|
|
13
|
+
IDCSHttpAuthOptions,
|
|
14
|
+
build_auth_context,
|
|
15
|
+
build_idcs_http_auth,
|
|
16
|
+
profile_declares_security_token,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
"AuthContext",
|
|
21
|
+
"AuthType",
|
|
22
|
+
"AuthOptions",
|
|
23
|
+
"IDCSHttpAuth",
|
|
24
|
+
"IDCSHttpAuthContext",
|
|
25
|
+
"IDCSHttpAuthOptions",
|
|
26
|
+
"build_auth_context",
|
|
27
|
+
"build_idcs_http_auth",
|
|
28
|
+
"profile_declares_security_token",
|
|
29
|
+
]
|
|
30
|
+
__version__ = "0.1.0"
|