Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ Prototypes and proofs-of-concept

| Project | Description |
|---------|-------------|
| [server](./server) | Example of MCP authentication using OCI IDCS and Oauth |
| [agent](./agent) | An example agent developed using LangGraph that drives the OCI CLI |
| [policy](./policy) | Demonstration of out-of-band policy enforcement for MCP servers/tools |
| [server](./server) | Example of MCP authentication using OCI IDCS and OAuth |

## Contributing

Expand Down
10 changes: 10 additions & 0 deletions agent/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ curl -s --request POST \
--header 'Content-Type: application/json' \
--data @payload.json
```
## License
Copyright (c) 2025 Oracle and/or its affiliates.

Released under the Universal Permissive License v1.0 as shown at
<https://oss.oracle.com/licenses/upl/>.

## Third-Party APIs

Developers choosing to distribute a binary implementation of this project are responsible for obtaining and providing all required licenses and copyright notices for the third-party code used in order to ensure compliance with their respective open source licenses.

## Disclaimer

Users are responsible for their local environment and credential safety. Different language model selections
Expand Down
3 changes: 3 additions & 0 deletions policy/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.venv/
venv/
bundles/
6 changes: 6 additions & 0 deletions policy/.mcphost/hooks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
hooks:
PreToolUse:
- matcher: "oci_*"
hooks:
- type: command
command: "uv run ./hooks/opa.py"
1 change: 1 addition & 0 deletions policy/.python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.13
13 changes: 13 additions & 0 deletions policy/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.PHONY: all build test test clean

all: build

build:
mkdir -p bundles
opa build -o bundles/bundle.tar.gz policies

test: .
opa test -v policies

clean:
rm -rf bundles/*
70 changes: 70 additions & 0 deletions policy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Policy

Demonstration of out-of-band policy enforcement for MCP servers/tools

## Getting started

### Install dependencies
```bash
brew install ollama python3 uv go opa podman podman-compose
```

### Create container VM for running containers via podman
```bash
podman machine init
podman machine start
```

### Build policies
```
make build
```

### Install Ollama and fetch model

Where `$MODEL` is the name of the model you prefer (ex: `gpt-oss`)

```bash
ollama pull $MODEL
```

### Install mcphost
```bash
go install github.com/mark3labs/mcphost@latest
export PATH=$PATH:~/.go/bin
```

### Authenticate

```bash
oci session authenticate --profile-name <profile name, ex: DEFAULT> --region <region name: us-sanjose-1>
```

### Start external policy engine (Open Policy Agent)
```bash
podman compose up -d
```

### Run mcphost

Where `$MODEL` is the name of the model you prefer (ex: `gpt-oss`)

```bash
OCI_CONFIG_PROFILE=<profile name, ex: DEFAULT> mcphost -m ollama:$MODEL --config ./mcp.json
```

You can now interact with the servers via the mcphost prompt:

```
what tools are available to you?
```
or
```
list my instances
```

## Testing

```bash
make test
```
37 changes: 37 additions & 0 deletions policy/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
version: "2"
services:
opa:
image: openpolicyagent/opa:latest
ports:
- 8181:8181
# WARNING: OPA is NOT running with an authorization policy configured. This
# means that clients can read and write policies in OPA. If you are
# deploying OPA in an insecure environment, be sure to configure
# authentication and authorization on the daemon. See the Security page for
# details: https://www.openpolicyagent.org/docs/security.html.
command:
- "run"
- "--server"
- "--addr=0.0.0.0:8181"
- "--log-format=json-pretty"
- "--set=decision_logs.console=true"
- "--set=services.nginx.url=http://bundle_server"
- "--set=bundles.nginx.service=nginx"
- "--set=bundles.nginx.resource=bundles/bundle.tar.gz"
depends_on:
- bundle_server
api_server:
image: openpolicyagent/demo-restful-api:0.3
ports:
- 5000:5000
environment:
- OPA_ADDR=http://opa:8181
- POLICY_PATH=/v1/data/httpapi/authz
depends_on:
- opa
bundle_server:
image: nginx:1.20.0-alpine
ports:
- 8888:80
volumes:
- ./bundles:/usr/share/nginx/html/bundles
22 changes: 22 additions & 0 deletions policy/hooks/opa.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import json
import sys

from opa_client.opa import OpaClient

# Initialize the OPA client
client = OpaClient(host="localhost", port=8181)

# Evaluate a policy
input_data = json.load(sys.stdin)
result = client.query_rule(input_data=input_data, package_path="mcp", rule_name="allow")
print(input_data)

print(result)

# Print the decision
if result.get("result"):
print("Access granted.")
sys.exit(0)
else:
print("Access denied.")
sys.exit(2)
11 changes: 11 additions & 0 deletions policy/mcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"mcpServers": {
"oracle-oci-api-mcp-server": {
"command": "uvx",
"args": [
"oracle.oci-api-mcp-server"
],
"transport": "stdio"
}
}
}
11 changes: 11 additions & 0 deletions policy/policies/mcp.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package mcp

default allow := false

allow if {
not contains(input.tool_name, "terminate")
every arg in input.tool_args {
not contains(arg, "terminate")
not contains(arg, "delete")
}
}
21 changes: 21 additions & 0 deletions policy/policies/test_mcp.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package mcp

test_tool_allowed if {
allow with input as {"tool_name": "safe", "tool_args": []}

allow with input as {
"tool_name": "oci",
"tool_args": ["compute", "instance", "create"]
}
}

test_tool_denied if {
not allow with input as {"tool_name": "terminate", "tool_args": []}
not allow with input as {"tool_name": "terminate_instance", "tool_args": []}
not allow with input as {"tool_name": "terminate something", "tool_args": []}
not allow with input as {"tool_name": "instance_terminate", "tool_args": []}

not allow with input as {"tool_name": "oci", "tool_args": ["compute", "instance", "terminate"]}
not allow with input as {"tool_name": "oci", "tool_args": ["compute", "terminate_instance"]}
not allow with input as {"tool_name": "oci", "tool_args": ["delete"]}
}
9 changes: 9 additions & 0 deletions policy/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[project]
name = "policy"
version = "0.1.0"
description = "Demonstration of out-of-band policy enforcement for MCP servers/tools"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
"opa-python-client>=2.0.3",
]
Loading