Class McpContextParams
/mcp/<owner>/<config>?CUSTOMER_ID=42), or under stdio as
MCP_CONTEXT_<NAME> environment variables, and that the generated server places in the
Oracle application context "MCP" for every tool call — so PL/SQL and curated
SQL can read SYS_CONTEXT('MCP','CUSTOMER_ID').
What this protects against is the agent, not the person. The URL never enters the
model's context and no tool can change it, so an agent cannot choose another customer. Anyone who
can edit the client's configuration can — an accepted risk, and why a value here must never be a
secret. See app/docs/mcp-per-caller-scoping-plan.md §0.
Lives in the runtime library, not the config model, because both ends need the same answer: the config editor refuses a name the generated server could never set, and the generated server refuses a value Oracle would reject. Copyright 2003-2026 ATB Consultancy Services Ltd (formerly Orinda Software Ltd, Dublin, Ireland)
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final classThe values one request (or, under stdio, the whole process) supplied, or the reason they cannot be used. -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final StringThe stdio source:MCP_CONTEXT_<NAME>=<value>.static final intThe longest name accepted. 30 is theDBMS_SESSION.SET_CONTEXTattribute limit on 12.1; later versions allow more, but a config that works on one box and not another is the failure this estate exists to catch, so the portable limit is the only limit.static final intTheDBMS_SESSION.SET_CONTEXTvalue limit, in bytes.static final StringThe Oracle application context namespace the values are set in.static final StringThe packageapp/db/mcp-context/install.sqlcreates, and the only code Oracle lets write the "MCP" namespace.static final StringThe config key family:MCP_CONTEXT_PARAM_<i>=<NAME>.static final StringThe key a generated server's HTTP transport files the parsed query string under, in the per-requestMcpTransportContextits tool handlers read back. -
Method Summary
Modifier and TypeMethodDescriptionstatic voidapplyToSession(Connection theConnection, Map<String, String> theValues) Replace this session's "MCP" context with exactly these values, in ONE round trip: clear everything, then set each pair.static McpContextParams.ResolvedThe values a stdio server takes from its environment:MCP_CONTEXT_<NAME>for each declared name.static McpContextParams.ResolvedfromQueryString(String theQuery, List<String> theDeclared) The values on one HTTP request's query string, checked against what the config declared.static StringlistProblem(List<String> theNames) Why this list of names cannot be declared together, or null when it can: each name must be valid, and no name may appear twice (after normalising, socustomer_idandCUSTOMER_IDare the same name).static StringnameProblem(String theName) Why this name cannot be declared, or null when it can.static StringThe canonical form of a name: trimmed and upper case.static StringnotInstalledReason(Throwable theFailure) What to tell an operator whenapplyToSession(java.sql.Connection, java.util.Map<java.lang.String, java.lang.String>)failed because the context is not there to set: the package missing, or this account not granted it.static StringvalueProblem(String theName, String theValue) Why this value cannot be set, or null when it can.
-
Field Details
-
PB2_KEY_PREFIX
The config key family:MCP_CONTEXT_PARAM_<i>=<NAME>.- See Also:
-
ENV_VARIABLE_PREFIX
The stdio source:MCP_CONTEXT_<NAME>=<value>.- See Also:
-
ORACLE_NAMESPACE
The Oracle application context namespace the values are set in.- See Also:
-
ORACLE_PACKAGE
-
TRANSPORT_CONTEXT_KEY
The key a generated server's HTTP transport files the parsed query string under, in the per-requestMcpTransportContextits tool handlers read back.- See Also:
-
MAX_NAME_LENGTH
public static final int MAX_NAME_LENGTHThe longest name accepted. 30 is theDBMS_SESSION.SET_CONTEXTattribute limit on 12.1; later versions allow more, but a config that works on one box and not another is the failure this estate exists to catch, so the portable limit is the only limit.- See Also:
-
MAX_VALUE_BYTES
public static final int MAX_VALUE_BYTESTheDBMS_SESSION.SET_CONTEXTvalue limit, in bytes.- See Also:
-
-
Method Details
-
normalise
-
nameProblem
Why this name cannot be declared, or null when it can. Checked afternormalise(java.lang.String), so lower case is accepted and stored upper.- Parameters:
theName- the name as typed- Returns:
- a sentence naming the problem, or null
-
listProblem
Why this list of names cannot be declared together, or null when it can: each name must be valid, and no name may appear twice (after normalising, socustomer_idandCUSTOMER_IDare the same name).- Parameters:
theNames- the names in declaration order- Returns:
- a sentence naming the first problem, or null
-
fromQueryString
The values on one HTTP request's query string, checked against what the config declared.Refused, naming the parameter: a name not declared (a typo must not run with the context unset); a name given twice (which one was meant?); a declared name missing or empty (Oracle stores '' as NULL); a value over
MAX_VALUE_BYTES. Names match case-insensitively. Read from the raw query string rather thangetParameter, which may parse a request body and does not report a repeated name as a repeat.- Parameters:
theQuery-HttpServletRequest.getQueryString(), possibly nulltheDeclared- the names the config declares, normalised- Returns:
- the values, or the reason to refuse
-
fromEnvironment
public static McpContextParams.Resolved fromEnvironment(Map<String, String> theEnvironment, List<String> theDeclared) The values a stdio server takes from its environment:MCP_CONTEXT_<NAME>for each declared name. Fixed for the life of the process. Only declared names are looked up, so an unrelated variable that happens to share the prefix is not a refusal.- Parameters:
theEnvironment- usuallySystem.getenv()theDeclared- the names the config declares, normalised- Returns:
- the values, or the reason to refuse
-
applyToSession
public static void applyToSession(Connection theConnection, Map<String, String> theValues) throws SQLExceptionReplace this session's "MCP" context with exactly these values, in ONE round trip: clear everything, then set each pair.Clear first, every time, including when the map is empty. Connections are pooled, so a session that served one caller is handed to the next; clearing only on the way out would leak the previous caller's values whenever that path did not run (a timeout, a thread killed mid-call). Clearing at the start cannot be skipped by anything that happened before.
Names and values are bound, never concatenated, and the package re-checks both, so a caller that skipped
nameProblem(java.lang.String)/valueProblem(java.lang.String, java.lang.String)still cannot set an invalid name or a NULL.- Parameters:
theConnection- the session to set them ontheValues- name to value, in the order to set them; names already normalised- Throws:
SQLException- when the package is missing or not granted (PLS-00201 inside an ORA-06550), or rejects a name or value (ORA-20901 / ORA-20902). The caller must not run the tool call on this session afterwards.
-
notInstalledReason
What to tell an operator whenapplyToSession(java.sql.Connection, java.util.Map<java.lang.String, java.lang.String>)failed because the context is not there to set: the package missing, or this account not granted it. Null for any other failure, which should be reported as it stands.Takes any throwable and walks its causes, because a pooled server reaches the database through a wrapper that re-throws the driver's exception inside its own.
- Parameters:
theFailure- whatapplyToSession(java.sql.Connection, java.util.Map<java.lang.String, java.lang.String>), or the borrow around it, threw- Returns:
- the sentence to log, or null
-
valueProblem
Why this value cannot be set, or null when it can. Missing and empty are both refused. Length is measured in UTF-8 bytes, because that is what Oracle's limit counts on an AL32UTF8 database; a value is refused rather than truncated, since a truncated customer id is a different customer.- Parameters:
theName- the parameter, for the messagetheValue- the value as supplied- Returns:
- a sentence naming the problem, or null
-