You can connect Oracle OPERA Cloud to Claude today, but not with a toggle. Oracle exposes OPERA Cloud through the Oracle Hospitality Integration Platform, OHIP, a catalog of more than 3,100 REST operations covering reservations, housekeeping, profiles, and front office. There is no official Oracle MCP server for hospitality as of July 2026, so the bridge is a small Model Context Protocol server you run yourself, authenticated with OAuth 2.0 client credentials and an application key. The code is an afternoon. The access is the real project: OHIP registration, environment credentials, and property-level authorization from the hotel. This guide covers both honestly.
The enterprise reality, upfront
OPERA Cloud is the PMS that large and chain hotels actually run, and its API surface is bigger and more open than its reputation suggests. But it is priced and gated like the enterprise system it is. According to Oracle's OHIP datasheet (2025), a hotel's access to OHIP is included in OPERA Cloud Property Management Foundation, while the party consuming the APIs is billed monthly in arrears, starting at $10 for up to 10,000 REST API transactions per month. Oracle has also published the full REST API specifications as an open-source project on GitHub, with Postman collections containing over 1,000 sample messages, so you can read every endpoint before you spend a dollar.
OHIP REST API pricing starts at $10 for up to 10,000 transactions per month, billed in arrears with no upfront commitment, per Oracle's OHIP datasheet. A Claude session asking a few dozen questions a day rounds to pocket change.
Oracle counts over 3,100 available operations in the OHIP catalog: reservations, housekeeping, CRM profiles, front office, inventory, cashiering, and more.
Per Oracle, hotels decide exactly who has access to what APIs in their environment. No property authorization, no data, no matter how good your code is.
What you'll be able to ask Claude
These map directly to the tools in the server below, which sit on OPERA Cloud's Housekeeping and Reservation APIs.
One caveat worth naming: OPERA's room status is a code someone set, not evidence. A room can read Inspected while the shower drain is clogged. Status tells you a human signed off; it cannot tell you what the room looks like. That gap between recorded status and physical condition is the problem RapidEye exists for: it reads the actual room photos and flags damage and cleaning misses that status codes never carry.
The architecture, layer by layer
Four layers. You own the middle two; Oracle and Anthropic own the ends. Nothing in this chain stores OPERA data at rest, and the OPERA credentials never touch Claude itself, only your local MCP server process.
x-app-key, and your application's API subscriptions, then routes the call. Tokens come from POST /oauth/v1/tokens on the same gateway.x-hotelid header. The hotel assigns which APIs your application may reach in its environment.Prerequisites: the five values you need
Two routes into OHIP. If you work at a hotel running OPERA Cloud, your property already has OHIP entitlement through OPERA Cloud Foundation; work with whoever administers your Oracle environment. If you are an outside vendor, Oracle's onboarding docs describe self-registering through the Oracle Store or submitting a partner registration form via hospitality-integrations_ww@oracle.com. Either way, before writing any code, you need five values out of the OHIP developer portal and your hotel:
| Value | Where it comes from | Used as |
|---|---|---|
OHIP_CLIENT_ID / OHIP_CLIENT_SECRET | OAuth client credentials for the environment, obtained through the OHIP developer portal | Basic auth header on the token request |
OHIP_APP_KEY | Issued when you register an application in the developer portal | x-app-key header on every call |
OHIP_HOTEL_ID | The property code for the OPERA Cloud environment you are targeting | x-hotelid header and URL path |
OHIP_GATEWAY_URL | The environment's gateway URL, shown when the environment is added in the portal | Base URL for tokens and all API calls |
OHIP_SCOPE | Assigned scope for your integration, required with the client_credentials grant | Body parameter on the token request |
Plus the usual pair: Claude Desktop (download) or the Claude Code CLI, and Node.js 18+ (node --version to check). Oracle also runs a non-production OPERA Cloud sandbox that is API-only and charged per call, which the OHIP datasheet positions as a cheap alternative to maintaining your own lab. Build against sandbox first.
Get OHIP access and collect your credentials
This is the step that takes calendar time, so start it first. Oracle's own documentation describes the flow for partners: choose an onboarding route (Oracle Store checkout or the partner registration form), activate the Oracle Cloud account when the activation email arrives, then use the OHIP developer portal to register an application, get an application key, subscribe the application to the APIs you need, and obtain credentials for the OPERA Cloud environment you are connecting to.
- Hotel-side reader: your property's OHIP entitlement is already part of OPERA Cloud Foundation. You need whoever owns your Oracle environment to add you to the developer portal and provision environment credentials.
- Vendor-side reader: self-registration gets you portal access, but a live hotel still has to authorize your application's API access in its environment. Per Oracle, the hotel remains in control by assigning the appropriate API access. Budget for that conversation.
- For this guide, subscribe your application to at least the Housekeeping (
hsk) and Reservation (rsv) APIs.
While you wait, read the API specs. Oracle publishes them all in the open-source oracle/hospitality-api-docs repo (Universal Permissive License), including the exact Swagger files this guide's endpoints were verified against.
Set up the Node.js project
Two dependencies: the MCP SDK and zod. OHIP is plain REST, so raw fetch is all we need.
mkdir opera-mcp
cd opera-mcp
npm init -y
npm install @modelcontextprotocol/sdk zod
Add "type": "module" to package.json:
{
"name": "opera-mcp",
"version": "1.0.0",
"type": "module",
"main": "index.js",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.0.0",
"zod": "^3.22.0"
}
}
Create the MCP server file
Save the following as index.js. It mints an OAuth token with the client_credentials grant (Basic auth of ClientID:ClientSecret plus x-app-key, exactly as Oracle's OAuth API spec describes), caches it until shortly before expiry, and exposes four read-only tools against endpoints from Oracle's published Swagger specs.
#!/usr/bin/env node
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const GATEWAY = process.env.OHIP_GATEWAY_URL; // e.g. https://your-env.hospitality-api.us-....oraclecloud.com
const CLIENT_ID = process.env.OHIP_CLIENT_ID;
const CLIENT_SECRET = process.env.OHIP_CLIENT_SECRET;
const APP_KEY = process.env.OHIP_APP_KEY;
const HOTEL_ID = process.env.OHIP_HOTEL_ID;
const SCOPE = process.env.OHIP_SCOPE; // assigned scope for the client_credentials grant
for (const [name, v] of Object.entries({ GATEWAY, CLIENT_ID, CLIENT_SECRET, APP_KEY, HOTEL_ID })) {
if (!v) { console.error(`Missing OHIP_${name} environment variable`); process.exit(1); }
}
// --- OAuth: POST {gateway}/oauth/v1/tokens, Basic auth + x-app-key ---
let cachedToken = null;
let tokenExpiresAt = 0;
async function getToken() {
if (cachedToken && Date.now() < tokenExpiresAt - 60_000) return cachedToken;
const body = new URLSearchParams({ grant_type: "client_credentials" });
if (SCOPE) body.set("scope", SCOPE);
const basic = Buffer.from(`${CLIENT_ID}:${CLIENT_SECRET}`).toString("base64");
const res = await fetch(`${GATEWAY}/oauth/v1/tokens`, {
method: "POST",
headers: {
Authorization: `Basic ${basic}`,
"x-app-key": APP_KEY,
"Content-Type": "application/x-www-form-urlencoded",
Accept: "application/json",
},
body,
});
if (!res.ok) {
throw new Error(`OHIP token request failed ${res.status}: ${await res.text()}`);
}
const data = await res.json();
cachedToken = data.access_token;
tokenExpiresAt = Date.now() + (data.expires_in ? data.expires_in * 1000 : 50 * 60_000);
return cachedToken;
}
async function ohipGet(path, params = {}) {
const token = await getToken();
const url = new URL(`${GATEWAY}${path}`);
for (const [k, v] of Object.entries(params)) {
if (v !== undefined && v !== null && v !== "") url.searchParams.append(k, String(v));
}
const res = await fetch(url.toString(), {
headers: {
Authorization: `Bearer ${token}`,
"x-app-key": APP_KEY,
"x-hotelid": HOTEL_ID,
Accept: "application/json",
},
});
if (!res.ok) {
throw new Error(`OHIP API ${res.status} on ${path}: ${await res.text()}`);
}
return res.json();
}
const server = new McpServer({ name: "opera-cloud", version: "1.0.0" });
// Tool 1: Housekeeping room status overview
server.tool(
"get-housekeeping-overview",
"Get the housekeeping status of rooms at the property: clean, dirty, inspected, pickup, plus front office status and room assignment. Supports filtering by housekeeping or front office room status. Use this for any 'what state are the rooms in' question.",
{
housekeepingRoomStatus: z.string().optional()
.describe("Optional filter, e.g. Clean, Dirty, Inspected, Pickup"),
limit: z.number().optional().describe("Max rooms to return (default 50)"),
},
async ({ housekeepingRoomStatus, limit }) => {
const data = await ohipGet(`/hsk/v1/hotels/${HOTEL_ID}/housekeepingOverview`, {
housekeepingRoomStatus,
limit: limit ?? 50,
});
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
}
);
// Tool 2: Housekeeping vs front office discrepancies
server.tool(
"get-room-discrepancies",
"List rooms where the housekeeping status does not match the front office status (skips and sleeps). These are the rooms most likely to cause a bad check-in. Returns the discrepancy type per room.",
{},
async () => {
const data = await ohipGet(`/hsk/v1/hotels/${HOTEL_ID}/housekeepingDiscrepancies`);
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
}
);
// Tool 3: Out of order rooms
server.tool(
"get-out-of-order-rooms",
"List rooms currently Out of Order at the property, with reason codes and date ranges. Out of Order rooms are removed from inventory entirely.",
{},
async () => {
const data = await ohipGet(`/hsk/v1/hotels/${HOTEL_ID}/rooms/outOfOrderRooms`);
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
}
);
// Tool 4: Search reservations
server.tool(
"search-reservations",
"Search reservations at the property by arrival date range. Returns guest, room type, status, and stay dates. Use with get-housekeeping-overview to compare arrivals against room readiness.",
{
arrivalStartDate: z.string().optional().describe("YYYY-MM-DD, start of arrival window"),
arrivalEndDate: z.string().optional().describe("YYYY-MM-DD, end of arrival window"),
limit: z.number().optional().describe("Max reservations to return (default 50)"),
},
async ({ arrivalStartDate, arrivalEndDate, limit }) => {
const data = await ohipGet(`/rsv/v1/hotels/${HOTEL_ID}/reservations`, {
arrivalStartDate,
arrivalEndDate,
limit: limit ?? 50,
});
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
}
);
const transport = new StdioServerTransport();
await server.connect(transport);
Endpoint honesty: the paths above (/hsk/v1/.../housekeepingOverview, /hsk/v1/.../housekeepingDiscrepancies, /hsk/v1/.../rooms/outOfOrderRooms, /rsv/v1/.../reservations, /oauth/v1/tokens) were verified against the Swagger specs in Oracle's hospitality-api-docs repo at OPERA Cloud release 26.2. Query parameters and response shapes can shift between OPERA Cloud releases, so if a filter is rejected, diff against the spec version matching your environment. Note that the similarly-named /rooms/status endpoint is a PUT (it changes room status); the read path for status is housekeepingOverview.
Register the server with Claude Desktop
Open your Claude Desktop config file:
~/Library/Application Support/Claude/claude_desktop_config.json
%APPDATA%\Claude\claude_desktop_config.json
Add the OPERA entry (merge into an existing mcpServers block if you have other guides from this series set up):
{
"mcpServers": {
"opera-cloud": {
"command": "node",
"args": ["/absolute/path/to/opera-mcp/index.js"],
"env": {
"OHIP_GATEWAY_URL": "https://your-environment-gateway-url",
"OHIP_CLIENT_ID": "your_client_id",
"OHIP_CLIENT_SECRET": "your_client_secret",
"OHIP_APP_KEY": "your_application_key",
"OHIP_HOTEL_ID": "YOURHOTELCODE",
"OHIP_SCOPE": "your_assigned_scope"
}
}
}
}
Replace every value, then fully quit and reopen Claude Desktop. Closing the window is not enough; the config is only read at startup. Remember each of these calls is a billable OHIP transaction, at the datasheet's $10-per-10,000 rate.
Try it
Doesn't Oracle have its own AI for OPERA?
It does now, and it is worth being precise about what it is. On June 16, 2026, Oracle announced OPERA Cloud Assistant, described in the press release as AI capabilities embedded natively in OPERA Cloud: AI-assisted room assignment, AI-generated rate code descriptions, multilingual translation, and a conversational assistant for operational procedures and Oracle documentation, available worldwide at no additional cost to OPERA Cloud customers.
What the announcement does not include is any external agent access: no Model Context Protocol server, no connector for Claude, ChatGPT, or Copilot, no way to point a general-purpose assistant at your property data. OPERA Cloud Assistant lives inside OPERA's own screens. If you want an assistant that can join OPERA data with things outside OPERA, your spreadsheets, your inspection reports, your other systems, the OHIP-plus-MCP route in this guide is, as of July 2026, the way to get it. For how OPERA compares to Mews, Cloudbeds, apaleo, and ten other platforms on exactly this axis, see our hotel PMS open API scorecard.
Troubleshooting
Token request fails with 400 or 401
Check the three parts Oracle's OAuth spec requires: a Basic authorization header that is the base64 of ClientID:ClientSecret (with the colon, no spaces), the x-app-key header, and a form-encoded body with grant_type=client_credentials. With the client_credentials grant, the scope body parameter is required; a missing or wrong scope is the most common silent failure.
Token works, but API calls return 403
A 403 with a valid token usually means an authorization gap, not an authentication one. Confirm your application is subscribed to the specific API module you are calling (hsk and rsv for this guide) in the developer portal, and that the hotel has actually granted your application access to those APIs in its environment. Oracle's model puts that control with the property.
404 or empty results on a path that should exist
Verify the x-hotelid header and the {hotelId} in the URL path match the property code for the environment behind your gateway URL. A wrong hotel code fails in unhelpful ways. Also confirm your gateway URL has no trailing slash, since the code concatenates paths directly.
A filter parameter is rejected or ignored
OPERA Cloud API specs are versioned with the platform (the specs this guide used are marked compatible with release 26.2). Download the spec matching your environment's release from the oracle/hospitality-api-docs GitHub repo and check the parameter list for your exact version before assuming a bug.
Claude doesn't see any OPERA tools
Claude Desktop reads the config only at startup. Fully quit (Cmd+Q on macOS, right-click tray icon and Quit on Windows) and relaunch. If it is still missing, check for invalid JSON in the config, a wrong absolute path to index.js, or node not being on the PATH Claude launches with.
I want Claude to update room statuses, not just read them
The write operations exist: for example, PUT /hsk/v1/hotels/{hotelId}/rooms/status changes room status in the Housekeeping API. This guide ships read-only on purpose. If you add writes, run them as a separate MCP server with its own credentials and scopes, so an exploratory conversation can never mutate a live property by accident.
FAQ
Does Oracle OPERA Cloud have an official MCP server?
No. As of July 2026, Oracle has not published a Model Context Protocol server for OPERA Cloud or any Oracle Hospitality product. The June 2026 OPERA Cloud Assistant announcement is embedded AI inside OPERA's own workflows, not external agent access. Connecting Claude means running a thin MCP server of your own on the OHIP REST APIs, which is what this guide builds.
Is OHIP free?
For the hotel, yes in the sense that matters: according to Oracle's OHIP datasheet, a hotel's access to OHIP is included in OPERA Cloud Property Management Foundation, with no per-interface fees. The API consumer pays for usage, starting at $10 for up to 10,000 REST transactions per month, billed monthly in arrears with no upfront commitment. Business Events streaming is priced separately at $10 for up to 100,000 events per month.
Do I need to join the Oracle Partner Network?
Oracle's OHIP onboarding docs describe self-registration through the Oracle Store or a partner registration form, without listing OPN membership as a gate for OHIP itself. If you work at the hotel, you do not need any partner status; your property's existing OPERA Cloud subscription carries the entitlement. Vendors pursuing a formal validated-integration listing should expect more process than plain API access.
Can Claude change data in OPERA through this setup?
Not with this server. All four tools are GET requests. The OHIP catalog does contain write operations, so treat that as a deliberate second project with separate credentials, not a flag you flip.
How long does this take end to end?
The MCP server is an afternoon. The access is the project: OHIP registration is self-service and the developer portal is available on signup, but reaching a live property requires environment credentials and the hotel authorizing your application's API access. If you control the property, plan in days. If you are a vendor waiting on a hotel's IT queue, plan in weeks. Anyone who tells you OPERA-to-AI is a ten-minute setup has not done it.
Other guides in this series
We maintain a library of Claude connection guides for the hotel and vacation rental stack, and a RapidEye API if you want inspection results in the same conversation.

