Replace JSONPath with CEL in COAZ MCP profile#466
Replace JSONPath with CEL in COAZ MCP profile#466alexolivier wants to merge 4 commits intoopenid:mainfrom
Conversation
- Replace JSONPath expressions with Common Expression Language (CEL) for mapping tool call parameters to AuthZen SARC model - Define CEL input variables: `params` (from tools/call JSON-RPC request) and `token` (decoded JWT claims), and CEL output semantics - Add non-normative example showing tools/call message to CEL variable resolution - Expand error handling with three categories: COAZ mapping errors (-32602), authorization denial (-32401), and PDP communication errors (-32603), aligned with MCP's protocol error model - Fix incomplete JSON examples that caused kramdown-rfc parse warnings - Add CEL as normative reference, remove unused RFC6901 (JSON Pointer) - Add Alex Olivier (Cerbos) as co-author Signed-off-by: Alex Olivier <alex@alexolivier.me>
baboulebou
left a comment
There was a problem hiding this comment.
Could you possibly also provide an additional, more complex and non-normative, example of what a CEL coaz mapping would look like, maybe using CEL conditions?
There was a problem hiding this comment.
Also a question...
If the MCP server is coaz enabled, but the external PEP (Gtwy) isn't, then the PEP will just ignore the mapping; OK. But in that case the MCP Tool is expected to enforce Access Control itself.
-> So how can we signal the MCP Tool/Resource that it must enforce access itself in that case?
-> We could say the Tool/Resource must enforce access in all cases. But if the external PEP (Gtwy) is coaz enabled, AND approved the request, then we'd get duplicate evaluations, an extra unnecessary latency hit...
Signed-off-by: Alex Olivier <alex@alexolivier.me>
Added as well as the string literal issue raised on todays call. re those scenarious The So the scenarios shake out like this:
The spec doesn't require the tool to enforce access as a fallback. I see that as outside COAZ's scope. COAZ defines the contract between a tool definition and a COAZ-aware PEP, wherever that PEP sits. If the concern is about guaranteeing that at least one PEP evaluates it, I think that's a deployment/configuration concern as @tulshi pointed out today rather than something the spec should mandate. |
| "name": "get_weather", | ||
| "coaz": true, | ||
| "title": "Weather Information Provider", | ||
| ... more response fields. |
There was a problem hiding this comment.
Swapped the ... more response fields placeholder for a full example with description and inputSchema filled in to be referenced in the mapping. Felt like the abbreviated version left too much to the reader's imagination. Happy to trim it back if you think it's too verbose
| ### CEL Output {#cel-output} | ||
|
|
||
| Each CEL expression MUST evaluate to a value. The value MAY be a scalar | ||
| (string, number, or boolean), a list, or a map. The resulting value is |
There was a problem hiding this comment.
A list can be converted easily into an array, but how does one convert a map to the array input of the evaluations API? Should we specify how to convert it?
There was a problem hiding this comment.
Each CEL expression targets a single field in a single evaluation mapping. So if you need multiple AuthZen requests via evaluations, you'd define separate mappings for each one. The CEL expression itself never needs to produce the full array; it's always scoped to one field of one request.
I can add a clarifying note to make that clearer if it'd help?
There was a problem hiding this comment.
Yeah, it'll be good to be unambiguous about how a list or map translates to various AuthZen calls.
We could include it in a non-normative "Security Considerations" section. |
|
@alexolivier I like how in your initial example of CEL you have the "tools/call" part spelled out. I think we should do the same for the single-valued and multi-valued examples. |
| <p id="section-4.2.3-4">And an access token with the following decoded claims:<a href="#section-4.2.3-4" class="pilcrow">¶</a></p> | ||
| <span id="name-example-decoded-access-toke"></span><div id="fig-token-claims"> | ||
| <figure id="figure-4"> | ||
| <div class="lang-json sourcecode" id="section-4.2.3-5.1"> |
There was a problem hiding this comment.
Another important claim in the case of MCP is the aud, since the agent or MCP host uses the OAuth resource parameter to identify the MCP server, for example, https://domain/mcp
Perhaps we could include this in the example.
This PR replaces JSONPath with Common Expression Language (CEL) as the expression language for mapping MCP tool call parameters to the AuthZen SARC model in the COAZ MCP profile.
Motivation
CEL is a widely adopted, well-specified expression language with implementations in Go, Java, C++, Rust, and other languages. It provides a more expressive and standardized alternative to JSONPath for evaluating mapping expressions, including support for complex return types (maps, lists), type checking, and well-defined error semantics.
Changes
Expression language: JSONPath → CEL
$properties['id'],$token['sub'], etc.) with CEL expressions (params.arguments.id,token.sub, etc.)CEL input variables
Two input variables are provided to every CEL expression:
paramstools/callJSON-RPCparamsobjectparams.name(tool name) andparams.arguments.*(caller-supplied values)tokentoken.sub,token.client_idCEL output
CEL expressions may return scalars (string, number, boolean), lists, or maps — enabling richer AuthZen request construction.
New non-normative example (§4.2.3)
Added an example showing a complete
tools/callJSON-RPC request and decoded token, with a resolution table mapping each CEL expression to its resolved value.Expanded error handling (§6)
Restructured into three subsections aligned with MCP's protocol error model:
-32602(Invalid Params)-32401(Unauthorized)-32603(Internal Error)Each error type includes a non-normative example response.