From time to time we get asked if Oracle REST Data Services ( ORDS ) can support certain formats or specifications such as YAML, OData or JSON-RPC. The simple answer is yes. Previously I provided an example plugin to convert the JSON response from ORDS into a YAML structure. A plugin is not the only option. One can create a user defined resource to implement almost anything. If using Oracle 23ai, that implementation can be in PL/SQL or JavaScript.
With the advent of a Model Context Protocol server for the Oracle Database it is timely to revisit the JSON-RPC options because MCP uses JSON-RPC as its transport wire format.
So let’s look at how one can use JSON-RPC with ORDS and Oracle 23ai in the hosted Oracle Autonomous Database.
JSON-RPC Protocol
The JSON-RPC protocol offers a minimal, transport-agnostic mechanism for structured remote procedure calls using JSON. It’s widely used in blockchain, embedded systems, and distributed APIs.
With Oracle Database 23ai, you can now implement a JSON-RPC endpoint directly inside the database using ORDS and the Multilingual Engine (MLE) with JavaScript — no extra middle tier or external Node.js runtime required.
In this post, we’ll build a standards-compliant JSON-RPC handler using ORDS MLE JavaScript, based on the canonical example from Wikipedia.
🧪 JSON-RPC Example
We’ll accept this standard JSON-RPC request:
{
"jsonrpc": "2.0",
"method": "subtract",
"params": { "minuend": 42, "subtrahend": 23 },
"id": 3
}
And return this result:
{
"jsonrpc": "2.0",
"result": 19,
"id": 3
}
The example implementation will just perform subtract, no other methods. However, this is essentially what the documented JSON-RPC V2 example is all about.
Using ORDS and Oracle 23ai with Autonomous Database
The entire example brings together a number of components and hosted services. One can accomplish all this on-premise, but it is more effort. Let’s briefly talk about those key constituents…
Oracle Autonomous Database (Serverless) is a fully managed, cloud-native database service on Oracle Cloud Infrastructure (OCI) that eliminates the complexity of database administration. It automatically handles provisioning, scaling, patching, tuning, backups, and security. The serverless deployment model allows developers to focus purely on data and logic without worrying about infrastructure or resource management.
Oracle Database 23ai introduces advanced AI and developer features, including the Multilingual Engine (MLE) — a lightweight JavaScript runtime embedded inside the database. MLE allows developers to write and run JavaScript code natively alongside SQL and PL/SQL, enabling modern use cases like JSON processing, protocol translation, and procedural logic without leaving the database.
Oracle REST Data Services (ORDS) is also hosted and managed within the Autonomous Database environment. ORDS enables developers to expose RESTful APIs directly from SQL, PL/SQL, or JavaScript (via MLE) using the Oracle 23ai database. It supports secure endpoints, OAuth2, pagination, OpenAPI integration, and more — without the need for an external application server.
Together, this stack allows developers to:
- Build microservices and APIs with JavaScript inside the database
- Expose data securely using REST over HTTPS via hosted ORDS
- Deploy completely serverless solutions on Oracle Cloud, fully managed and auto-scaled
Many of these are accessible for free in the OCI Free Tier. Yes for free.
Step by step
In this example I’ll start with an Oracle 23ai database in the Frankfurt region using the Free Tier. I have a REST Enabled database user called JSONRPCEXAMPLE with the standard roles to create a database session and resources in the database.

🔒 Step 1: Grant Required Privileges
Using Oracle 23ai is a necessity because it contains the Multi Language Engine for running JavaScript but each database user does require permission to use it. My JSONRPCEXAMPLE database user has been given that permission:
GRANT EXECUTE ON JAVASCRIPT TO JSONRPCEXAMPLE;
GRANT EXECUTE DYNAMIC MLE TO JSONRPCEXAMPLE;

In my hosted Oracle 23ai database I executed the above as the ADMIN user.
Now to connect as the REST Enabled JSONRPCEXAMPLE user and actually implement that User Defined Resource.
🚀 Step 2: Create the ORDS Module and Handler
There are plenty of options to get a connection to the database for running this SQL Script. The most popular options are sqlcl, SQL Developer for VS Code and Database Actions.
Use the following script to define the ORDS module, template, and MLE handler. This version is fully correct for Oracle 23ai and adheres to the format specified in the ORDS Developer Guide.
BEGIN
ORDS.DEFINE_MODULE(
p_module_name => 'jsonrpc',
p_base_path => '/rpc/',
p_comments => 'JSON-RPC endpoint'
);
ORDS.DEFINE_TEMPLATE(
p_module_name => 'jsonrpc',
p_pattern => 'handler'
);
ORDS.DEFINE_HANDLER(
p_module_name => 'jsonrpc',
p_pattern => 'handler',
p_method => 'POST',
p_source_type => ORDS.source_type_mle_javascript,
p_source => q'~
(req, resp) => {
let jsonrpc_response = {
jsonrpc: "2.0",
id: null
};
try {
const jsonrpc_request = req.body;
jsonrpc_response.id = jsonrpc_request.id ?? null;
if (jsonrpc_request.jsonrpc !== "2.0") {
jsonrpc_response.error = {
code: -32600,
message: "Invalid Request"
};
} else if (jsonrpc_request.method === "subtract") {
const { minuend, subtrahend } = jsonrpc_request.params;
jsonrpc_response.result = minuend - subtrahend;
} else {
jsonrpc_response.error = {
code: -32601,
message: "Method not found"
};
}
} catch (e) {
jsonrpc_response.error = {
code: -32700,
message: "Parse error",
data: e.message
};
}
resp.content_type("application/json");
resp.status(200);
resp.send(JSON.stringify(jsonrpc_response));
}
~',
p_comments => 'MLE JavaScript JSON-RPC handler'
);
COMMIT;
END;
/

Since this is only an implementation for subtract, you can take it on as an additional exercise to introduce more calculator operations.
Also consider moving the logic into an MLE Module or even using a predefined JavaScript Mathematics library for your calculator logic. See Transform your SQL Results with Mustache and ORDS JavaScript Handlers for an example of using JavaScript libraries through the MLE Module concept.
You have probably noticed that the handler always returns HTTP Status Code 200 even if there is an error. The JSON-RPC Error Object section of the specification does not state any expected behaviour around the transport protocol for an error scenario so you will have to determine what is appropriate for your organisation.
🧪Step 3: Test the Endpoint
Use curl, Postman, or any HTTP client:
curl -X POST \
https://my-db.oraclecloudapps.com/ords/jsonrpcexample/rpc/handler \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "subtract",
"params": { "minuend": 42, "subtrahend": 23 },
"id": 3
}'
You’ll get this JSON-RPC 2.0 response:
{
"jsonrpc": "2.0",
"result": 19,
"id": 3
}
Try it without specifying an id or without params to see how the implementation responds.
You will also note that this service is not secured and it would be best practice to restrict access to authorised users only. This can be achieved by defining an ORDS Privilege for the module or pattern of the service URI. Take a look at Configuring Secure Access to RESTful Services to find out more.
✅ Conclusion
Oracle Database 23ai’s MLE JavaScript support allows you to run lightweight protocol handlers—like JSON-RPC—directly in the database, without the need for a plugins. With just a few lines of code, ORDS becomes a smart, standards-compliant backend for modern APIs to meet your integration needs.
Key takeaways:
- Use
(req, resp) => {}function syntax for MLE JavaScript in ORDS. - Grant
EXECUTE ON JAVASCRIPTandEXECUTE DYNAMIC MLEto your user. - Validate incoming JSON-RPC payloads according to spec.
- Secure access using ORDS privileges.
One thought on “JSON-RPC in ORDS Using MLE JavaScript (Oracle 23ai)”