Documentation · Oracle
Creating an Oracle user with minimal privileges
Every caller shares one Oracle account. The generated server authenticates to the database,
not its callers — Oracle sees one service account no matter which agent called. Per-caller
attribution lives in the proxy’s access records, not in V$SESSION.
That makes this account’s grants the real boundary. Curation decides what tools exist; the grant decides what those tools can do if anything ever goes wrong with the first answer. Use both.
The shape of it
CREATE USER mcp_agent IDENTIFIED BY "..."
DEFAULT TABLESPACE users
QUOTA UNLIMITED ON users; -- only if it writes
GRANT CREATE SESSION TO mcp_agent;
-- One line per object you actually exposed. Not an inherited role, not ANY privilege.
GRANT SELECT ON payroll.employee TO mcp_agent;
GRANT EXECUTE ON payroll.js_admin TO mcp_agent;
GRANT SELECT ON payroll.job_id_seq TO mcp_agent;
Rules worth keeping
- Grant per object, and only the operations the tools need. If a table is exposed read-only in
the config, do not grant
INSERTon it — then the two answers agree. - No
ANYprivileges, noDBA, noSELECT ANY TABLE. They defeat the point. - A role is fine if you build it for this one server, holding exactly the grants above and
nothing else — the same list with a handle on it, and one
REVOKEtakes it all back mid-incident. What to avoid is inheriting somebody else’s:CONNECT,RESOURCE, or an application role whose contents change without you. Note that privileges held through a role are invisible inside definer’s-rights PL/SQL and toCREATE VIEW; if the account needs either, grant it directly. RESOURCEno longer impliesUNLIMITED TABLESPACEon 12c and later. If the account writes, grant quota explicitly, or the first insert fails withORA-01950.- The generator needs dictionary access at design time, which is not the same account’s job at run time. You can use a different, better-privileged account to introspect and a narrow one to run.