feat: surface structured rejection fields from gRPC response (RFC-008 B8)#61
feat: surface structured rejection fields from gRPC response (RFC-008 B8)#61
Conversation
… B8) - Regenerate mcp_pb2.py from updated proto with error_code, rejection_detail, requested_capability, presented_capability fields (15-18) and SCOPE_INSUFFICIENT enum value (9) - Add SCOPE_INSUFFICIENT to deny_reason_map in evaluate_tool_access() - Return error_code, requested_capability, presented_capability in the evaluate_tool_access() result dict - Restore try/except TypeError handler for descriptor pool collisions
|
✅ Documentation validation passed!
|
|
✅ All checks passed! Ready for review. |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Pull request overview
This PR updates the SDK’s MCP gRPC surface area to reflect recent capiscio-core proto changes (RFC-008 B8), aiming to expose structured rejection details from EvaluateToolAccessResponse via the Python evaluate_tool_access() return dict.
Changes:
- Regenerates MCP protobuf/grpc stubs to include new request/response fields, a new deny reason enum value, and a new
EvaluatePolicyDecisionRPC. - Extends
evaluate_tool_access()deny-reason mapping to includeSCOPE_INSUFFICIENT. - Adds new structured fields (
error_code,requested_capability,presented_capability) to theevaluate_tool_access()return payload.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| capiscio_sdk/_rpc/gen/capiscio/v1/mcp_pb2.py | Regenerated protobuf module; adds new MCP message fields/enums and additional policy-related messages. |
| capiscio_sdk/_rpc/gen/capiscio/v1/mcp_pb2_grpc.py | Regenerated gRPC stubs; adds EvaluatePolicyDecision and introduces a grpcio version gate. |
| capiscio_sdk/_rpc/client.py | Extends MCP client return mapping and exposes additional structured rejection fields. |
| # @@protoc_insertion_point(imports) | ||
|
|
||
| _sym_db = _symbol_database.Default() | ||
|
|
||
|
|
||
| from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 | ||
|
|
||
|
|
There was a problem hiding this comment.
Fixed in f586b58 — removed the duplicated import block.
| # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! | ||
| """Client and server classes corresponding to protobuf-defined services.""" | ||
| import grpc | ||
| import warnings |
There was a problem hiding this comment.
Fixed in f586b58 — removed the warnings import and the entire grpcio version gate block.
| raise RuntimeError( | ||
| f'The grpc package installed is at version {GRPC_VERSION},' | ||
| + ' but the generated code in capiscio/v1/mcp_pb2_grpc.py depends on' | ||
| + f' grpcio>={GRPC_GENERATED_VERSION}.' | ||
| + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' | ||
| + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' |
There was a problem hiding this comment.
Fixed in f586b58 — removed the grpcio>=1.76.0 version gate entirely. The SDK's grpcio>=1.60.0 floor is preserved.
| "timestamp": timestamp_str, | ||
| "error_code": response.error_code, | ||
| "requested_capability": response.requested_capability, | ||
| "presented_capability": response.presented_capability, | ||
| } |
There was a problem hiding this comment.
Fixed in f586b58 — rejection_detail is now included in the return dict.
| "decision": decision_map.get(response.decision, "unspecified"), | ||
| "deny_reason": deny_reason_map.get(response.deny_reason, ""), | ||
| "deny_detail": response.deny_detail, | ||
| "agent_did": response.agent_did, | ||
| "badge_jti": response.badge_jti, | ||
| "auth_level": auth_level_map.get(response.auth_level, "unspecified"), | ||
| "trust_level": response.trust_level, | ||
| "evidence_json": response.evidence_json, | ||
| "evidence_id": response.evidence_id, | ||
| "timestamp": timestamp_str, | ||
| "error_code": response.error_code, | ||
| "requested_capability": response.requested_capability, | ||
| "presented_capability": response.presented_capability, | ||
| } |
There was a problem hiding this comment.
Acknowledged — skipping docstring update in this PR to keep it focused on implementation. Will address in a follow-up docs pass.
| "error_code": response.error_code, | ||
| "requested_capability": response.requested_capability, | ||
| "presented_capability": response.presented_capability, |
There was a problem hiding this comment.
Fixed in f586b58 — added tests/unit/test_mcp_structured_fields.py with 3 tests covering: deny response with structured fields, allow response with empty fields, and presence of all expected keys.
|
✅ SDK server contract tests passed (test_server_integration.py). Cross-product scenarios are validated in capiscio-e2e-tests. |
- Remove duplicated import block in mcp_pb2.py - Remove grpcio>=1.76.0 version gate from mcp_pb2_grpc.py (SDK supports grpcio>=1.60.0) - Remove unused warnings import from mcp_pb2_grpc.py - Add rejection_detail to evaluate_tool_access() return dict - Add unit tests for structured rejection fields
|
✅ Documentation validation passed!
|
|
✅ All checks passed! Ready for review. |
|
✅ SDK server contract tests passed (test_server_integration.py). Cross-product scenarios are validated in capiscio-e2e-tests. |
Summary
Surfaces the RFC-008 structured rejection fields from the gRPC
EvaluateToolAccessResponseinto the Python SDK'sevaluate_tool_access()return dict.Changes
Proto regeneration (
mcp_pb2.py,mcp_pb2_grpc.py)mcp.protowhich includes:error_code(field 15),rejection_detail(field 16),requested_capability(field 17),presented_capability(field 18)MCP_DENY_REASON_SCOPE_INSUFFICIENT = 9enum valuetry/except TypeErrorhandler for descriptor pool collisions (capiscio-mcp co-loading)Client (
client.py)MCP_DENY_REASON_SCOPE_INSUFFICIENT: "scope_insufficient"todeny_reason_maperror_code,requested_capability,presented_capabilityto theevaluate_tool_access()return dictTesting
test_find_binary_system_pathfailure unrelated to this PR)RFC-008 Sub-task
This implements B8 from the RFC-008 implementation plan.