Skip to content

Commit 1e19462

Browse files
authored
Merge pull request #3191 from oracle-devrel/update-oac-mcp-server-text
Clean up OAC MCP server asset text
2 parents dc472db + de30268 commit 1e19462

4 files changed

Lines changed: 25 additions & 27 deletions

File tree

ai/gen-ai-agents/oci-enterprise-ai-agents-oac-mcp-server/README.md

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# OCI Enterprise AI Agents OAC MCP Server
1+
# OCI Enterprise AI Agents - OAC MCP Server
22

3-
A React assistant that lets [OCI Enterprise AI](https://www.oracle.com/artificial-intelligence/enterprise-ai/) query **governed Oracle Analytics Cloud data** through the **OAC MCP server**. The model reasons through the OCI Generative AI Responses API, the app executes the delegated OAC MCP tool calls, and every numeric result is rendered as a chart with the Logical SQL and the full tool timeline shown next to it.
3+
A React assistant that lets [OCI Enterprise AI](https://www.oracle.com/artificial-intelligence/enterprise-ai/) query **governed Oracle Analytics Cloud data** through the **OAC MCP server**. The model reasons through the OCI Generative AI Responses API, the app executes the delegated OAC MCP tool calls, and every numeric result is rendered as a chart - with the Logical SQL and the full tool timeline shown next to it.
44

55
Built with **Next.js 16**, **React 19**, **Recharts**, and a small **Python bridge**.
66

@@ -36,29 +36,29 @@ Open [http://localhost:3000](http://localhost:3000). Click the **Graph Demo** qu
3636
Create `files/.env` (copy `.env.example`):
3737

3838
```env
39-
# OCI Generative AI OpenAI-compatible Responses API for your region
39+
# OCI Generative AI - OpenAI-compatible Responses API for your region
4040
GENAI_BASE_URL=https://inference.generativeai.eu-frankfurt-1.oci.oraclecloud.com/openai/v1
4141
GENAI_API_KEY=<oci-genai-api-key>
4242
GENAI_PROJECT_ID=ocid1.generativeaiproject.oc1..xxxxx
4343
4444
# Oracle Analytics Cloud MCP endpoint of your instance
4545
OAC_MCP_SERVER_URL=https://<your-oac-instance>.analytics.ocp.oraclecloud.com/api/mcp
4646
47-
# Optional derived from OAC_MCP_SERVER_URL when not set
47+
# Optional - derived from OAC_MCP_SERVER_URL when not set
4848
# OAC_TOKEN_REFRESH_URL=https://<your-oac-instance>.analytics.ocp.oraclecloud.com/api/dv/api/v1/tokens/token/refresh
4949
50-
# Optional python used by the API route (default: files/.venv/bin/python, then python3)
50+
# Optional - python used by the API route (default: files/.venv/bin/python, then python3)
5151
# PYTHON_BIN=/usr/bin/python3
5252
```
5353

5454
### OAC authentication
5555

5656
Two options, in the order the bridge resolves them:
5757

58-
1. **Access token** set `OAC_ACCESS_TOKEN` (or `MCP_BEARER_TOKEN`) in `.env`, or paste a token in the UI. OAC access tokens expire after ~1 hour.
59-
2. **`tokens.json` (recommended)** in OAC go to **Profile → Mobile Authentication → Download token file** and save it as `files/tokens.json` (shape in `tokens.example.json`). The bridge reads it on every request and **refreshes it automatically** ~10 minutes before expiry, persisting the rotated refresh token back to the file. This survives well beyond the 1-hour access-token window.
58+
1. **Access token** - set `OAC_ACCESS_TOKEN` (or `MCP_BEARER_TOKEN`) in `.env`, or paste a token in the UI. OAC access tokens expire after ~1 hour.
59+
2. **`tokens.json` (recommended)** - in OAC go to **Profile → Mobile Authentication → Download token file** and save it as `files/tokens.json` (shape in `tokens.example.json`). The bridge reads it on every request and **refreshes it automatically** ~10 minutes before expiry, persisting the rotated refresh token back to the file. This survives well beyond the 1-hour access-token window.
6060

61-
> The refresh endpoint authenticates with the *access token itself*, so once a downloaded token file fully expires it cannot be refreshed download a fresh `tokens.json` from OAC.
61+
> The refresh endpoint authenticates with the *access token itself*, so once a downloaded token file fully expires it cannot be refreshed - download a fresh `tokens.json` from OAC.
6262
6363
---
6464

@@ -96,7 +96,7 @@ Follow-up questions keep `previous_response_id`, so "break that down by month" w
9696
![Home](images/01-home.png)
9797

9898
### Governed analytics through MCP
99-
The assistant discovers the right subject area or dataset, describes only the relevant metadata, and builds Logical SQL from the exact described column names including the `XSA('owner'.'Dataset')` syntax for uploaded datasets.
99+
The assistant discovers the right subject area or dataset, describes only the relevant metadata, and builds Logical SQL from the exact described column names - including the `XSA('owner'.'Dataset')` syntax for uploaded datasets.
100100

101101
### Automatic result charts
102102
Any executed Logical SQL result with at least one category column and one numeric measure is rendered as a bar chart. A **Graph Demo** quick prompt renders a deterministic local chart to verify the UI path with no OAC access at all.
@@ -105,7 +105,7 @@ Any executed Logical SQL result with at least one category column and one numeri
105105
Every MCP call is listed with status, arguments, and compacted output; all executed Logical SQL statements are shown verbatim.
106106

107107
### Token diagnostics
108-
On 401/403 the bridge reports the token source used, whether the JWT is readable/expired, and whether the token audience matches the OAC host the usual failure causes, stated directly in the error message.
108+
On 401/403 the bridge reports the token source used, whether the JWT is readable/expired, and whether the token audience matches the OAC host - the usual failure causes, stated directly in the error message.
109109

110110
### Display masking
111111
Dataset owner e-mails, OCIDs, and `XSA('owner'...)` identifiers are masked in the rendered UI so demo recordings don't leak identifiers.
@@ -145,15 +145,15 @@ oci-enterprise-ai-agents-oac-mcp-server/
145145

146146
1. UI POSTs `{action: "chat", prompt, previousResponseId, ...}` to `/api/oac-demo`
147147
2. The route spawns `scripts/oac_react_api.py` and writes the payload to stdin
148-
3. The bridge resolves an OAC token (see below) and preflights `initialize` against the OAC MCP endpoint 401/403 fail fast with token diagnostics
148+
3. The bridge resolves an OAC token (see below) and preflights `initialize` against the OAC MCP endpoint - 401/403 fail fast with token diagnostics
149149
4. The bridge lists the OAC MCP tools and exposes them to the model as function tools via the Responses API
150150
5. Each model tool call is executed by the bridge against OAC MCP (`tools/call`), compacted, and returned to the model; the loop repeats until the model produces a final answer
151151
6. The bridge extracts Logical SQL, builds the chart payload from the last SQL result rows, and emits one JSON object to stdout; the route returns it to the UI
152152

153153
### Token resolution order
154154

155155
1. `accessToken` pasted in the UI payload
156-
2. `files/tokens.json` used directly while valid, auto-refreshed (and persisted) when within 10 minutes of expiry
156+
2. `files/tokens.json` - used directly while valid, auto-refreshed (and persisted) when within 10 minutes of expiry
157157
3. `OAC_ACCESS_TOKEN` / `MCP_BEARER_TOKEN` environment variables
158158

159159
### Chart building
@@ -165,11 +165,11 @@ oci-enterprise-ai-agents-oac-mcp-server/
165165
## OCI API endpoints used
166166

167167
### Generative AI (inference)
168-
- `POST {GENAI_BASE_URL}/responses` model reasoning with function tools, chained via `previous_response_id` (OpenAI-compatible Responses API; authenticated with `GENAI_API_KEY` + `GENAI_PROJECT_ID`)
168+
- `POST {GENAI_BASE_URL}/responses` - model reasoning with function tools, chained via `previous_response_id` (OpenAI-compatible Responses API; authenticated with `GENAI_API_KEY` + `GENAI_PROJECT_ID`)
169169

170170
### Oracle Analytics Cloud
171-
- `POST {OAC_MCP_SERVER_URL}` MCP JSON-RPC 2.0: `initialize`, `tools/list`, `tools/call` (Bearer token)
172-
- `POST .../api/dv/api/v1/tokens/token/refresh` refreshes a downloaded token file: current access token in the `Authorization` header, refresh token as `text/plain` body; returns rotated `accessToken`/`refreshToken`
171+
- `POST {OAC_MCP_SERVER_URL}` - MCP JSON-RPC 2.0: `initialize`, `tools/list`, `tools/call` (Bearer token)
172+
- `POST .../api/dv/api/v1/tokens/token/refresh` - refreshes a downloaded token file: current access token in the `Authorization` header, refresh token as `text/plain` body; returns rotated `accessToken`/`refreshToken`
173173

174174
---
175175

@@ -217,12 +217,12 @@ The chart needs at least one text/category column and one numeric measure in the
217217

218218
## Tech Stack
219219

220-
- **Framework** Next.js 16 (App Router, Turbopack)
221-
- **UI** React 19, Lucide icons, CSS Modules
222-
- **Charts** Recharts
223-
- **Markdown** react-markdown + remark-gfm
224-
- **Bridge** Python 3, `openai` (OCI Responses API), `requests` (OAC MCP JSON-RPC + token refresh)
225-
- **Protocols** MCP (JSON-RPC 2.0 over streamable HTTP), OpenAI-compatible Responses API
220+
- **Framework** - Next.js 16 (App Router, Turbopack)
221+
- **UI** - React 19, Lucide icons, CSS Modules
222+
- **Charts** - Recharts
223+
- **Markdown** - react-markdown + remark-gfm
224+
- **Bridge** - Python 3, `openai` (OCI Responses API), `requests` (OAC MCP JSON-RPC + token refresh)
225+
- **Protocols** - MCP (JSON-RPC 2.0 over streamable HTTP), OpenAI-compatible Responses API
226226

227227
---
228228

@@ -233,5 +233,3 @@ Copyright (c) 2026 Oracle and/or its affiliates.
233233
Licensed under the Universal Permissive License (UPL), Version 1.0.
234234

235235
See [LICENSE](LICENSE) for more details.
236-
237-
ORACLE AND ITS AFFILIATES DO NOT PROVIDE ANY WARRANTY WHATSOEVER, EXPRESS OR IMPLIED, FOR ANY SOFTWARE, MATERIAL OR CONTENT OF ANY KIND CONTAINED OR PRODUCED WITHIN THIS REPOSITORY, AND IN PARTICULAR SPECIFICALLY DISCLAIM ANY AND ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. FURTHERMORE, ORACLE AND ITS AFFILIATES DO NOT REPRESENT THAT ANY CUSTOMARY SECURITY REVIEW HAS BEEN PERFORMED WITH RESPECT TO ANY SOFTWARE, MATERIAL OR CONTENT CONTAINED OR PRODUCED WITHIN THIS REPOSITORY. IN ADDITION, AND WITHOUT LIMITING THE FOREGOING, THIRD PARTIES MAY HAVE POSTED SOFTWARE, MATERIAL OR CONTENT TO THIS REPOSITORY WITHOUT ANY REVIEW. USE AT YOUR OWN RISK.

ai/gen-ai-agents/oci-enterprise-ai-agents-oac-mcp-server/files/.env.example

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# OCI Generative AI OpenAI-compatible Responses API endpoint for your region.
1+
# OCI Generative AI - OpenAI-compatible Responses API endpoint for your region.
22
# Example: https://inference.generativeai.eu-frankfurt-1.oci.oraclecloud.com/openai/v1
33
GENAI_BASE_URL=<oci-genai-openai-compatible-base-url>
44
GENAI_API_KEY=<oci-genai-api-key>

ai/gen-ai-agents/oci-enterprise-ai-agents-oac-mcp-server/files/src/app/layout.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import "./globals.css";
55

66
export const metadata = {
7-
title: "OCI Enterprise AI Agents OAC MCP Server",
7+
title: "OCI Enterprise AI Agents - OAC MCP Server",
88
description:
99
"React assistant that queries governed Oracle Analytics Cloud data through MCP and renders charts.",
1010
};

ai/gen-ai-agents/oci-enterprise-ai-agents-oac-mcp-server/files/src/app/page.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -416,9 +416,9 @@ function formatToolOutput(value) {
416416
function maskSensitive(value) {
417417
if (value == null) return value;
418418
let text = typeof value === "string" ? value : String(value);
419-
text = text.replace(/XSA\('[^']*'\./g, "XSA(''.");
419+
text = text.replace(/XSA\('[^']*'\./g, "XSA('...'.");
420420
text = text.replace(/[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g, "[hidden]");
421-
text = text.replace(/ocid1\.[a-z0-9._-]+/gi, "ocid1.");
421+
text = text.replace(/ocid1\.[a-z0-9._-]+/gi, "ocid1....");
422422
return text;
423423
}
424424

0 commit comments

Comments
 (0)