oci-secrets-mcp
by kevinwengh
README.md
# OCI Secrets MCP
An MCP server for OCI Vault's documented public Secrets control-plane and
data-plane APIs.
## Install
```sh
git clone https://github.com/kevinwengh/oci-secrets-mcp.git
cd oci-secrets-mcp
uv sync
```
## OCI authentication
The server signs outbound requests with the OCI Python SDK. It never accepts private keys, bearer tokens, or authorization headers from MCP tools.
| Mode | Required configuration |
| --- | --- |
| `api_key` (default) | `~/.oci/config`, optionally `OCI_CONFIG_FILE` and `OCI_CONFIG_PROFILE` |
| `security_token` | OCI config profile configured with a security token |
| `instance_principal` | `OCI_REGION` and an OCI compute instance principal |
| `instance_principal_delegation_token` | `OCI_REGION` and `OCI_DELEGATION_TOKEN_FILE` |
| `resource_principal` | `OCI_REGION` and a supported OCI resource-principal environment |
| `resource_principal_delegation_token` | `OCI_REGION`, a resource principal, and `OCI_DELEGATION_TOKEN_FILE` |
| `oke_workload_identity` | `OCI_REGION` and an OKE workload-identity environment |
Select a non-default provider with `OCI_SECRETS_MCP_AUTH_MODE`.
For security-token and delegation-token modes, refresh the token file with the normal OCI tooling. If OCI returns `401 NotAuthenticated`, the server rebuilds both SDK clients from the current credential source and retries the request once.
### API-key example
An OCI user Auth Token intended for services such as Container Registry or SMTP cannot sign OCI SDK requests. Use an API signing key pair instead: upload the public key to the OCI user and keep the matching private key outside this repository.
Save the private key with user-only permissions outside the repository, for
example:
```text
/absolute/path/to/.oci/oci-secrets-mcp-api-key.pem
```
Do not paste the private key into this README or the MCP client configuration.
Add a profile like this to your OCI configuration file, replacing every
placeholder with your own value:
```ini
[OCI_SECRETS_MCP]
user=<USER_OCID>
fingerprint=<KEY_FINGERPRINT>
tenancy=<TENANCY_OCID>
region=<OCI_REGION>
key_file=/absolute/path/to/.oci/oci-secrets-mcp-api-key.pem
```
Configure your MCP client to select that profile. The configuration format is
client-specific.
### Claude Desktop
Claude Desktop uses JSON. Add the following server entry to its MCP
configuration:
```json
{
"mcpServers": {
"oci-secrets": {
"command": "uv",
"args": [
"--directory",
"/absolute/path/to/oci-secrets-mcp",
"run",
"oci-secrets-mcp"
],
"env": {
"OCI_SECRETS_MCP_AUTH_MODE": "api_key",
"OCI_CONFIG_FILE": "/absolute/path/to/.oci/config",
"OCI_CONFIG_PROFILE": "OCI_SECRETS_MCP"
}
}
}
}
```
Restart Claude Desktop after changing its configuration.
### Codex
Codex uses TOML. Add the following to `~/.codex/config.toml`, or to
`.codex/config.toml` in a trusted project:
```toml
[mcp_servers.oci-secrets]
command = "uv"
args = [
"--directory",
"/absolute/path/to/oci-secrets-mcp",
"run",
"oci-secrets-mcp",
]
[mcp_servers.oci-secrets.env]
OCI_SECRETS_MCP_AUTH_MODE = "api_key"
OCI_CONFIG_FILE = "/absolute/path/to/.oci/config"
OCI_CONFIG_PROFILE = "OCI_SECRETS_MCP"
```
Restart Codex after changing its configuration, then verify that the server is
registered:
```sh
codex mcp list
```
The environment variables above belong to the MCP client configuration. They
are applied when Claude Desktop or Codex launches the server. If you run
`uv run oci-secrets-mcp` directly in a shell, export the same variables first;
otherwise the server uses its defaults, including the `DEFAULT` OCI profile.
The tenancy OCID can also be used as the root compartment ID. For example, call `list_secrets` with:
```json
{
"compartment_id": "<TENANCY_OR_COMPARTMENT_OCID>",
"vault_id": "<VAULT_OCID>"
}
```
## Run
Stdio is the default transport and is suitable for local MCP clients:
```sh
uv run oci-secrets-mcp
```
The optional streamable HTTP transport is restricted to loopback:
```sh
uv run oci-secrets-mcp --transport streamable-http --host 127.0.0.1 --port 8000
```
> [!WARNING]
> The streamable HTTP transport does not authenticate callers or validate
> browser origins. Loopback binding reduces network exposure, but it does not
> protect against untrusted local processes or every DNS-rebinding scenario.
> Any caller that reaches the endpoint can use the server's configured OCI
> identity to retrieve secret content and can submit state-changing calls with
> `confirm=true`. Prefer stdio unless you have separately isolated and secured
> the HTTP endpoint.
The server does not permit a non-loopback bind, including behind a gateway.
See the separate Claude Desktop and Codex configuration examples above for
stdio client setup.
## Safety and IAM
All state-changing tools have MCP destructive annotations and require `confirm=true`; this includes creation, updates, rotation, compartment moves, and deletion/rotation scheduling or cancellation. Secret-bundle retrieval returns secret content, so grant the executing OCI principal only the Vault permissions it requires and treat MCP responses as sensitive.
The `confirm=true` check is a guard against accidental changes, not an
authentication or authorization boundary. OCI IAM and MCP client access policy
remain the security boundaries.
Create and update requests use typed MCP schemas with snake_case field names and are converted to OCI SDK models before transmission. Successful results contain:
- `data`: the OCI SDK response model converted to JSON.
- `opc_request_id`: OCI's request identifier.
- `headers`: allowlisted pagination, ETag, work-request, location, and retry metadata when present.
- `status`: the HTTP response status.
## Verification
```sh
uv run ruff check .
uv run pytest
```
## License
Licensed under the [MIT License](LICENSE).
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues