Class McpCallRecord
The generated server funnels every tool handler through a single call(...) helper, which
writes one of these afterwards. Before this existed the funnel logged nothing at all — a failure
went back to the caller as an error result and left no server-side trace, pool exhaustion included.
The format is a fixed prefix followed by a JSON object, so it can be grepped out of a mixed log and parsed without one:
MCP-CALL {"tool":"ob_gen_pkg_greet","outcome":"ok","ms":12,"args":["p_name"]}
Argument names, never argument values
Only the argument names are recorded. This is the one place where an MCP server differs sharply from an ordinary service: the values were chosen by a model rather than by a programmer, so they are the most interesting thing here and also the most dangerous — they can carry anything the caller put in front of the model, including personal data. Names give the shape of the call without that risk. Recording values should be a separate, explicit opt-in, and is deliberately not built.
This is not an audit trail. It is a diagnostic record written to a log that the process itself owns, so it has no durability, ordering or tamper-evidence guarantees. A real audit trail needs a sink that survives the container and cannot be rewritten by the thing being audited. Copyright 2003-2026 ATB Consultancy Services Ltd (formerly Orinda Software Ltd, Dublin, Ireland)
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final StringRefused before reaching the database: a URL context parameter was missing, empty, undeclared or repeated.static final StringThe database refused the work.static final StringOptimistic-lock clash: the document changed since it was read.static final StringAnything else, including a bug in the generated code.static final StringThe tool ran and found nothing — a normal answer, not a failure.static final StringThe tool ran and returned data.static final StringEvery pooled factory is checked out and the pool is at its ceiling.static final StringRefused by the configured rate limit — load shed by policy, not by saturation.static final StringMarks the line, so it can be found in a log carrying everything else too. -
Method Summary
-
Field Details
-
PREFIX
Marks the line, so it can be found in a log carrying everything else too.- See Also:
-
OUTCOME_OK
-
OUTCOME_NOT_FOUND
The tool ran and found nothing — a normal answer, not a failure.- See Also:
-
OUTCOME_DOCUMENT_CHANGED
Optimistic-lock clash: the document changed since it was read.- See Also:
-
OUTCOME_POOL_EXHAUSTED
Every pooled factory is checked out and the pool is at its ceiling. Load, not a fault.- See Also:
-
OUTCOME_RATE_LIMITED
Refused by the configured rate limit — load shed by policy, not by saturation.- See Also:
-
OUTCOME_DATABASE_ERROR
-
OUTCOME_CONTEXT_REFUSED
Refused before reaching the database: a URL context parameter was missing, empty, undeclared or repeated. The caller's configuration is wrong, not the server or the data.- See Also:
-
OUTCOME_ERROR
Anything else, including a bug in the generated code.- See Also:
-
-
Method Details
-
line
public static String line(String theToolName, Map<String, Object> theArguments, String theOutcome, long theMilliseconds) Build the record.- Parameters:
theToolName- the MCP tool that was invokedtheArguments- the call's arguments; only the keys are used, and null is finetheOutcome- one of theOUTCOME_constantstheMilliseconds- wall-clock duration of the call
-
line
public static String line(String theToolName, Map<String, Object> theArguments, String theOutcome, long theMilliseconds, Map<String, String> theContext) Build the record, with the URL context parameters the call ran under.Their VALUES are recorded, unlike the arguments': a model did not choose them, and "for which customer did this run" is the first thing an operator reading this line needs. They are identifiers, never secrets. Null or empty writes no
contextkey at all, so a server without context parameters writes exactly the line it wrote before they existed.- Parameters:
theContext- name to value, or null
-