diff --git a/capiscio_mcp/_proto/capiscio/v1/mcp_pb2.py b/capiscio_mcp/_proto/capiscio/v1/mcp_pb2.py index b6ab3d9..f5c71b1 100644 --- a/capiscio_mcp/_proto/capiscio/v1/mcp_pb2.py +++ b/capiscio_mcp/_proto/capiscio/v1/mcp_pb2.py @@ -1,252 +1,86 @@ -""" -Placeholder for generated mcp_pb2.py. - -This module will be replaced by actual protobuf-generated code from -proto/capiscio/v1/mcp.proto when capiscio-core v2.5.0 is released. - -For now, we define the message classes and enums as Python classes -to support development and testing. -""" - -from __future__ import annotations - -from dataclasses import dataclass, field -from typing import List, Optional - - -# ============================================================================= -# Enums -# ============================================================================= - -# Decision enum -DECISION_UNSPECIFIED = 0 -ALLOW = 1 -DENY = 2 - -# AuthLevel enum -AUTH_LEVEL_UNSPECIFIED = 0 -ANONYMOUS = 1 -API_KEY = 2 -BADGE = 3 - -# DenyReason enum -DENY_REASON_UNSPECIFIED = 0 -TOOL_BADGE_MISSING = 1 -TOOL_BADGE_INVALID = 2 -TOOL_BADGE_EXPIRED = 3 -TOOL_BADGE_REVOKED = 4 -TOOL_TRUST_INSUFFICIENT = 5 -TOOL_NOT_ALLOWED = 6 -TOOL_ISSUER_UNTRUSTED = 7 -TOOL_POLICY_DENIED = 8 - -# ServerState enum -SERVER_STATE_UNSPECIFIED = 0 -VERIFIED_PRINCIPAL = 1 -DECLARED_PRINCIPAL = 2 -UNVERIFIED_ORIGIN = 3 - -# ServerErrorCode enum -SERVER_ERROR_NONE = 0 -SERVER_DID_INVALID = 1 -SERVER_BADGE_INVALID = 2 -SERVER_BADGE_EXPIRED = 3 -SERVER_BADGE_REVOKED = 4 -SERVER_TRUST_INSUFFICIENT = 5 -SERVER_ORIGIN_MISMATCH = 6 -SERVER_PATH_MISMATCH = 7 -SERVER_ISSUER_UNTRUSTED = 8 - - -# ============================================================================= -# Messages -# ============================================================================= - -@dataclass -class EvaluateConfig: - """Configuration for EvaluateToolAccess.""" - trusted_issuers: List[str] = field(default_factory=list) - min_trust_level: int = 0 - accept_level_zero: bool = False - allowed_tools: List[str] = field(default_factory=list) - require_badge: bool = False - - -@dataclass -class EvaluateToolAccessRequest: - """Request message for EvaluateToolAccess RPC.""" - tool_name: str = "" - params_hash: str = "" - server_origin: str = "" - badge_jws: str = "" # oneof caller_credential - api_key: str = "" # oneof caller_credential - policy_version: str = "" - config: Optional[EvaluateConfig] = None - - -@dataclass -class Timestamp: - """Protobuf Timestamp placeholder.""" - seconds: int = 0 - nanos: int = 0 - - -@dataclass -class EvaluateToolAccessResponse: - """Response message for EvaluateToolAccess RPC.""" - decision: int = DECISION_UNSPECIFIED - deny_reason: int = DENY_REASON_UNSPECIFIED - deny_detail: str = "" - agent_did: str = "" - badge_jti: str = "" - auth_level: int = AUTH_LEVEL_UNSPECIFIED - trust_level: int = 0 - evidence_json: str = "" - evidence_id: str = "" - timestamp: Optional[Timestamp] = None - - -@dataclass -class VerifyConfig: - """Configuration for VerifyServerIdentity.""" - trusted_issuers: List[str] = field(default_factory=list) - min_trust_level: int = 0 - accept_level_zero: bool = False - offline_mode: bool = False - skip_origin_binding: bool = False - - -@dataclass -class VerifyServerIdentityRequest: - """Request message for VerifyServerIdentity RPC.""" - server_did: str = "" - server_badge: str = "" - transport_origin: str = "" - endpoint_path: str = "" - config: Optional[VerifyConfig] = None - - -@dataclass -class VerifyServerIdentityResponse: - """Response message for VerifyServerIdentity RPC.""" - state: int = SERVER_STATE_UNSPECIFIED - trust_level: int = 0 - server_did: str = "" - badge_jti: str = "" - error_code: int = SERVER_ERROR_NONE - error_detail: str = "" - - -@dataclass -class HttpHeaders: - """HTTP headers for ParseServerIdentity.""" - capiscio_server_did: str = "" - capiscio_server_badge: str = "" - - -@dataclass -class JsonRpcMeta: - """JSON-RPC _meta for ParseServerIdentity.""" - meta_json: str = "" - - -@dataclass -class ParseServerIdentityRequest: - """Request message for ParseServerIdentity RPC.""" - http_headers: Optional[HttpHeaders] = None - jsonrpc_meta: Optional[JsonRpcMeta] = None - - -@dataclass -class ParseServerIdentityResponse: - """Response message for ParseServerIdentity RPC.""" - server_did: str = "" - server_badge: str = "" - identity_present: bool = False - - -@dataclass -class HealthRequest: - """Request message for Health RPC.""" - client_version: str = "" - - -@dataclass -class HealthResponse: - """Response message for Health RPC.""" - healthy: bool = True - core_version: str = "" - proto_version: str = "" - version_compatible: bool = True - - -# ============================================================================= -# RFC-005: Policy Decision Messages -# ============================================================================= - -@dataclass -class PolicySubject: - """Subject attributes for policy evaluation.""" - did: str = "" - badge_jti: str = "" - ial: str = "" - trust_level: str = "" - badge_exp: int = 0 - - -@dataclass -class PolicyAction: - """Action attributes for policy evaluation.""" - operation: str = "" - capability_class: str = "" - - -@dataclass -class PolicyResource: - """Resource attributes for policy evaluation.""" - identifier: str = "" - - -@dataclass -class PolicyConfig: - """PEP-level configuration for the policy decision.""" - pdp_endpoint: str = "" - pdp_timeout_ms: int = 0 - enforcement_mode: str = "" - pep_id: str = "" - workspace: str = "" - breakglass_public_key: bytes = b"" - - -@dataclass -class PolicyDecisionRequest: - """Request message for EvaluatePolicyDecision RPC.""" - subject: Optional[PolicySubject] = None - action: Optional[PolicyAction] = None - resource: Optional[PolicyResource] = None - config: Optional[PolicyConfig] = None - breakglass_token: str = "" - - -@dataclass -class MCPObligation: - """Obligation from policy decision.""" - type: str = "" - params_json: str = "" - - -@dataclass -class PolicyDecisionResponse: - """Response from centralized policy decision.""" - decision: str = "" - decision_id: str = "" - reason: str = "" - ttl: int = 0 - obligations: List["MCPObligation"] = field(default_factory=list) - enforcement_mode: str = "" - cache_hit: bool = False - breakglass_override: bool = False - breakglass_jti: str = "" - error_code: str = "" - pdp_latency_ms: int = 0 - txn_id: str = "" +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: capiscio/v1/mcp.proto +# Protobuf Python Version: 6.31.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 31, + 1, + '', + 'capiscio/v1/mcp.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x63\x61piscio/v1/mcp.proto\x12\x0b\x63\x61piscio.v1\x1a\x1fgoogle/protobuf/timestamp.proto\"\xbe\x03\n\x19\x45valuateToolAccessRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x13\n\x0bparams_hash\x18\x02 \x01(\t\x12\x15\n\rserver_origin\x18\x03 \x01(\t\x12\x13\n\tbadge_jws\x18\x04 \x01(\tH\x00\x12\x11\n\x07\x61pi_key\x18\x05 \x01(\tH\x00\x12\x16\n\x0epolicy_version\x18\x06 \x01(\t\x12+\n\x06\x63onfig\x18\x07 \x01(\x0b\x32\x1b.capiscio.v1.EvaluateConfig\x12\x18\n\x10\x65nforcement_mode\x18\x08 \x01(\t\x12\x18\n\x10\x63\x61pability_class\x18\n \x01(\t\x12\x13\n\x0b\x65nvelope_id\x18\x0b \x01(\t\x12\x18\n\x10\x64\x65legation_depth\x18\x0c \x01(\x05\x12\x18\n\x10\x63onstraints_json\x18\r \x01(\t\x12\x1f\n\x17parent_constraints_json\x18\x0e \x01(\t\x12\"\n\x15\x64\x65ny_on_unknown_class\x18\x0f \x01(\x08H\x01\x88\x01\x01\x42\x13\n\x11\x63\x61ller_credentialB\x18\n\x16_deny_on_unknown_classJ\x04\x08\t\x10\n\"t\n\x0e\x45valuateConfig\x12\x17\n\x0ftrusted_issuers\x18\x01 \x03(\t\x12\x17\n\x0fmin_trust_level\x18\x02 \x01(\x05\x12\x19\n\x11\x61\x63\x63\x65pt_level_zero\x18\x03 \x01(\x08\x12\x15\n\rallowed_tools\x18\x04 \x03(\t\"\xd3\x03\n\x1a\x45valuateToolAccessResponse\x12*\n\x08\x64\x65\x63ision\x18\x01 \x01(\x0e\x32\x18.capiscio.v1.MCPDecision\x12/\n\x0b\x64\x65ny_reason\x18\x02 \x01(\x0e\x32\x1a.capiscio.v1.MCPDenyReason\x12\x13\n\x0b\x64\x65ny_detail\x18\x03 \x01(\t\x12\x11\n\tagent_did\x18\x04 \x01(\t\x12\x11\n\tbadge_jti\x18\x05 \x01(\t\x12-\n\nauth_level\x18\x06 \x01(\x0e\x32\x19.capiscio.v1.MCPAuthLevel\x12\x13\n\x0btrust_level\x18\x07 \x01(\x05\x12\x15\n\revidence_json\x18\x08 \x01(\t\x12\x13\n\x0b\x65vidence_id\x18\t \x01(\t\x12-\n\ttimestamp\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1a\n\x12policy_decision_id\x18\x0b \x01(\t\x12\x17\n\x0fpolicy_decision\x18\x0c \x01(\t\x12\x18\n\x10\x65nforcement_mode\x18\r \x01(\t\x12/\n\x0bobligations\x18\x0e \x03(\x0b\x32\x1a.capiscio.v1.MCPObligation\"2\n\rMCPObligation\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x13\n\x0bparams_json\x18\x02 \x01(\t\"\xe3\x01\n\x15PolicyDecisionRequest\x12+\n\x07subject\x18\x01 \x01(\x0b\x32\x1a.capiscio.v1.PolicySubject\x12)\n\x06\x61\x63tion\x18\x02 \x01(\x0b\x32\x19.capiscio.v1.PolicyAction\x12-\n\x08resource\x18\x03 \x01(\x0b\x32\x1b.capiscio.v1.PolicyResource\x12)\n\x06\x63onfig\x18\x04 \x01(\x0b\x32\x19.capiscio.v1.PolicyConfig\x12\x18\n\x10\x62reakglass_token\x18\x05 \x01(\t\"d\n\rPolicySubject\x12\x0b\n\x03\x64id\x18\x01 \x01(\t\x12\x11\n\tbadge_jti\x18\x02 \x01(\t\x12\x0b\n\x03ial\x18\x03 \x01(\t\x12\x13\n\x0btrust_level\x18\x04 \x01(\t\x12\x11\n\tbadge_exp\x18\x05 \x01(\x03\";\n\x0cPolicyAction\x12\x11\n\toperation\x18\x01 \x01(\t\x12\x18\n\x10\x63\x61pability_class\x18\x02 \x01(\t\"$\n\x0ePolicyResource\x12\x12\n\nidentifier\x18\x01 \x01(\t\"\x98\x01\n\x0cPolicyConfig\x12\x14\n\x0cpdp_endpoint\x18\x01 \x01(\t\x12\x16\n\x0epdp_timeout_ms\x18\x02 \x01(\x05\x12\x18\n\x10\x65nforcement_mode\x18\x03 \x01(\t\x12\x0e\n\x06pep_id\x18\x04 \x01(\t\x12\x11\n\tworkspace\x18\x05 \x01(\t\x12\x1d\n\x15\x62reakglass_public_key\x18\x06 \x01(\x0c\"\xab\x02\n\x16PolicyDecisionResponse\x12\x10\n\x08\x64\x65\x63ision\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65\x63ision_id\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x0b\n\x03ttl\x18\x04 \x01(\x05\x12/\n\x0bobligations\x18\x05 \x03(\x0b\x32\x1a.capiscio.v1.MCPObligation\x12\x18\n\x10\x65nforcement_mode\x18\x06 \x01(\t\x12\x11\n\tcache_hit\x18\x07 \x01(\x08\x12\x1b\n\x13\x62reakglass_override\x18\x08 \x01(\x08\x12\x16\n\x0e\x62reakglass_jti\x18\t \x01(\t\x12\x12\n\nerror_code\x18\n \x01(\t\x12\x16\n\x0epdp_latency_ms\x18\x0b \x01(\x03\x12\x0e\n\x06txn_id\x18\x0c \x01(\t\"\xa6\x01\n\x1bVerifyServerIdentityRequest\x12\x12\n\nserver_did\x18\x01 \x01(\t\x12\x14\n\x0cserver_badge\x18\x02 \x01(\t\x12\x18\n\x10transport_origin\x18\x03 \x01(\t\x12\x15\n\rendpoint_path\x18\x04 \x01(\t\x12,\n\x06\x63onfig\x18\x05 \x01(\x0b\x32\x1c.capiscio.v1.MCPVerifyConfig\"\x91\x01\n\x0fMCPVerifyConfig\x12\x17\n\x0ftrusted_issuers\x18\x01 \x03(\t\x12\x17\n\x0fmin_trust_level\x18\x02 \x01(\x05\x12\x19\n\x11\x61\x63\x63\x65pt_level_zero\x18\x03 \x01(\x08\x12\x14\n\x0coffline_mode\x18\x04 \x01(\x08\x12\x1b\n\x13skip_origin_binding\x18\x05 \x01(\x08\"\xd1\x01\n\x1cVerifyServerIdentityResponse\x12*\n\x05state\x18\x01 \x01(\x0e\x32\x1b.capiscio.v1.MCPServerState\x12\x13\n\x0btrust_level\x18\x02 \x01(\x05\x12\x12\n\nserver_did\x18\x03 \x01(\t\x12\x11\n\tbadge_jti\x18\x04 \x01(\t\x12\x33\n\nerror_code\x18\x05 \x01(\x0e\x32\x1f.capiscio.v1.MCPServerErrorCode\x12\x14\n\x0c\x65rror_detail\x18\x06 \x01(\t\"\x90\x01\n\x1aParseServerIdentityRequest\x12\x33\n\x0chttp_headers\x18\x01 \x01(\x0b\x32\x1b.capiscio.v1.MCPHttpHeadersH\x00\x12\x33\n\x0cjsonrpc_meta\x18\x02 \x01(\x0b\x32\x1b.capiscio.v1.MCPJsonRpcMetaH\x00\x42\x08\n\x06source\"L\n\x0eMCPHttpHeaders\x12\x1b\n\x13\x63\x61piscio_server_did\x18\x01 \x01(\t\x12\x1d\n\x15\x63\x61piscio_server_badge\x18\x02 \x01(\t\"#\n\x0eMCPJsonRpcMeta\x12\x11\n\tmeta_json\x18\x01 \x01(\t\"a\n\x1bParseServerIdentityResponse\x12\x12\n\nserver_did\x18\x01 \x01(\t\x12\x14\n\x0cserver_badge\x18\x02 \x01(\t\x12\x18\n\x10identity_present\x18\x03 \x01(\x08\"*\n\x10MCPHealthRequest\x12\x16\n\x0e\x63lient_version\x18\x01 \x01(\t\"m\n\x11MCPHealthResponse\x12\x0f\n\x07healthy\x18\x01 \x01(\x08\x12\x14\n\x0c\x63ore_version\x18\x02 \x01(\t\x12\x15\n\rproto_version\x18\x03 \x01(\t\x12\x1a\n\x12version_compatible\x18\x04 \x01(\x08*Z\n\x0bMCPDecision\x12\x1c\n\x18MCP_DECISION_UNSPECIFIED\x10\x00\x12\x16\n\x12MCP_DECISION_ALLOW\x10\x01\x12\x15\n\x11MCP_DECISION_DENY\x10\x02*\x82\x01\n\x0cMCPAuthLevel\x12\x1e\n\x1aMCP_AUTH_LEVEL_UNSPECIFIED\x10\x00\x12\x1c\n\x18MCP_AUTH_LEVEL_ANONYMOUS\x10\x01\x12\x1a\n\x16MCP_AUTH_LEVEL_API_KEY\x10\x02\x12\x18\n\x14MCP_AUTH_LEVEL_BADGE\x10\x03*\xd3\x02\n\rMCPDenyReason\x12\x1f\n\x1bMCP_DENY_REASON_UNSPECIFIED\x10\x00\x12!\n\x1dMCP_DENY_REASON_BADGE_MISSING\x10\x01\x12!\n\x1dMCP_DENY_REASON_BADGE_INVALID\x10\x02\x12!\n\x1dMCP_DENY_REASON_BADGE_EXPIRED\x10\x03\x12!\n\x1dMCP_DENY_REASON_BADGE_REVOKED\x10\x04\x12&\n\"MCP_DENY_REASON_TRUST_INSUFFICIENT\x10\x05\x12$\n MCP_DENY_REASON_TOOL_NOT_ALLOWED\x10\x06\x12$\n MCP_DENY_REASON_ISSUER_UNTRUSTED\x10\x07\x12!\n\x1dMCP_DENY_REASON_POLICY_DENIED\x10\x08*\xac\x01\n\x0eMCPServerState\x12 \n\x1cMCP_SERVER_STATE_UNSPECIFIED\x10\x00\x12\'\n#MCP_SERVER_STATE_VERIFIED_PRINCIPAL\x10\x01\x12\'\n#MCP_SERVER_STATE_DECLARED_PRINCIPAL\x10\x02\x12&\n\"MCP_SERVER_STATE_UNVERIFIED_ORIGIN\x10\x03*\xd7\x02\n\x12MCPServerErrorCode\x12\x19\n\x15MCP_SERVER_ERROR_NONE\x10\x00\x12 \n\x1cMCP_SERVER_ERROR_DID_INVALID\x10\x01\x12\"\n\x1eMCP_SERVER_ERROR_BADGE_INVALID\x10\x02\x12\"\n\x1eMCP_SERVER_ERROR_BADGE_EXPIRED\x10\x03\x12\"\n\x1eMCP_SERVER_ERROR_BADGE_REVOKED\x10\x04\x12\'\n#MCP_SERVER_ERROR_TRUST_INSUFFICIENT\x10\x05\x12$\n MCP_SERVER_ERROR_ORIGIN_MISMATCH\x10\x06\x12\"\n\x1eMCP_SERVER_ERROR_PATH_MISMATCH\x10\x07\x12%\n!MCP_SERVER_ERROR_ISSUER_UNTRUSTED\x10\x08\x32\xf6\x03\n\nMCPService\x12\x65\n\x12\x45valuateToolAccess\x12&.capiscio.v1.EvaluateToolAccessRequest\x1a\'.capiscio.v1.EvaluateToolAccessResponse\x12\x61\n\x16\x45valuatePolicyDecision\x12\".capiscio.v1.PolicyDecisionRequest\x1a#.capiscio.v1.PolicyDecisionResponse\x12k\n\x14VerifyServerIdentity\x12(.capiscio.v1.VerifyServerIdentityRequest\x1a).capiscio.v1.VerifyServerIdentityResponse\x12h\n\x13ParseServerIdentity\x12\'.capiscio.v1.ParseServerIdentityRequest\x1a(.capiscio.v1.ParseServerIdentityResponse\x12G\n\x06Health\x12\x1d.capiscio.v1.MCPHealthRequest\x1a\x1e.capiscio.v1.MCPHealthResponseB;Z9github.com/capiscio/capiscio-core/pkg/rpc/gen/capiscio/v1b\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'capiscio.v1.mcp_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals['DESCRIPTOR']._loaded_options = None + _globals['DESCRIPTOR']._serialized_options = b'Z9github.com/capiscio/capiscio-core/pkg/rpc/gen/capiscio/v1' + _globals['_MCPDECISION']._serialized_start=3093 + _globals['_MCPDECISION']._serialized_end=3183 + _globals['_MCPAUTHLEVEL']._serialized_start=3186 + _globals['_MCPAUTHLEVEL']._serialized_end=3316 + _globals['_MCPDENYREASON']._serialized_start=3319 + _globals['_MCPDENYREASON']._serialized_end=3658 + _globals['_MCPSERVERSTATE']._serialized_start=3661 + _globals['_MCPSERVERSTATE']._serialized_end=3833 + _globals['_MCPSERVERERRORCODE']._serialized_start=3836 + _globals['_MCPSERVERERRORCODE']._serialized_end=4179 + _globals['_EVALUATETOOLACCESSREQUEST']._serialized_start=72 + _globals['_EVALUATETOOLACCESSREQUEST']._serialized_end=518 + _globals['_EVALUATECONFIG']._serialized_start=520 + _globals['_EVALUATECONFIG']._serialized_end=636 + _globals['_EVALUATETOOLACCESSRESPONSE']._serialized_start=639 + _globals['_EVALUATETOOLACCESSRESPONSE']._serialized_end=1106 + _globals['_MCPOBLIGATION']._serialized_start=1108 + _globals['_MCPOBLIGATION']._serialized_end=1158 + _globals['_POLICYDECISIONREQUEST']._serialized_start=1161 + _globals['_POLICYDECISIONREQUEST']._serialized_end=1388 + _globals['_POLICYSUBJECT']._serialized_start=1390 + _globals['_POLICYSUBJECT']._serialized_end=1490 + _globals['_POLICYACTION']._serialized_start=1492 + _globals['_POLICYACTION']._serialized_end=1551 + _globals['_POLICYRESOURCE']._serialized_start=1553 + _globals['_POLICYRESOURCE']._serialized_end=1589 + _globals['_POLICYCONFIG']._serialized_start=1592 + _globals['_POLICYCONFIG']._serialized_end=1744 + _globals['_POLICYDECISIONRESPONSE']._serialized_start=1747 + _globals['_POLICYDECISIONRESPONSE']._serialized_end=2046 + _globals['_VERIFYSERVERIDENTITYREQUEST']._serialized_start=2049 + _globals['_VERIFYSERVERIDENTITYREQUEST']._serialized_end=2215 + _globals['_MCPVERIFYCONFIG']._serialized_start=2218 + _globals['_MCPVERIFYCONFIG']._serialized_end=2363 + _globals['_VERIFYSERVERIDENTITYRESPONSE']._serialized_start=2366 + _globals['_VERIFYSERVERIDENTITYRESPONSE']._serialized_end=2575 + _globals['_PARSESERVERIDENTITYREQUEST']._serialized_start=2578 + _globals['_PARSESERVERIDENTITYREQUEST']._serialized_end=2722 + _globals['_MCPHTTPHEADERS']._serialized_start=2724 + _globals['_MCPHTTPHEADERS']._serialized_end=2800 + _globals['_MCPJSONRPCMETA']._serialized_start=2802 + _globals['_MCPJSONRPCMETA']._serialized_end=2837 + _globals['_PARSESERVERIDENTITYRESPONSE']._serialized_start=2839 + _globals['_PARSESERVERIDENTITYRESPONSE']._serialized_end=2936 + _globals['_MCPHEALTHREQUEST']._serialized_start=2938 + _globals['_MCPHEALTHREQUEST']._serialized_end=2980 + _globals['_MCPHEALTHRESPONSE']._serialized_start=2982 + _globals['_MCPHEALTHRESPONSE']._serialized_end=3091 + _globals['_MCPSERVICE']._serialized_start=4182 + _globals['_MCPSERVICE']._serialized_end=4684 +# @@protoc_insertion_point(module_scope) diff --git a/capiscio_mcp/_proto/capiscio/v1/mcp_pb2_grpc.py b/capiscio_mcp/_proto/capiscio/v1/mcp_pb2_grpc.py index df863b6..4618db1 100644 --- a/capiscio_mcp/_proto/capiscio/v1/mcp_pb2_grpc.py +++ b/capiscio_mcp/_proto/capiscio/v1/mcp_pb2_grpc.py @@ -1,140 +1,283 @@ -""" -Placeholder for generated mcp_pb2_grpc.py. +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc +import warnings -This module will be replaced by actual protobuf-generated code from -proto/capiscio/v1/mcp.proto when capiscio-core v2.5.0 is released. +from capiscio.v1 import mcp_pb2 as capiscio_dot_v1_dot_mcp__pb2 -For now, we define stub classes that can be mocked in tests. -""" +GRPC_GENERATED_VERSION = '1.76.0' +GRPC_VERSION = grpc.__version__ +_version_not_supported = False -from __future__ import annotations +try: + from grpc._utilities import first_version_is_lower + _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) +except ImportError: + _version_not_supported = True -from typing import TYPE_CHECKING +if _version_not_supported: + 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}.' + ) -if TYPE_CHECKING: - import grpc - from capiscio_mcp._proto.capiscio.v1 import mcp_pb2 - -class MCPServiceStub: - """ - Stub for MCPService gRPC client. - - This is a placeholder that will be replaced by actual generated code. - The stub provides async methods for all MCP RPCs. +class MCPServiceStub(object): + """MCPService provides unified MCP security operations (RFC-005, RFC-006, RFC-007) """ - - def __init__(self, channel: "grpc.aio.Channel") -> None: - """ - Initialize stub with gRPC channel. - + + def __init__(self, channel): + """Constructor. + Args: - channel: Async gRPC channel - """ - self._channel = channel - - async def EvaluateToolAccess( - self, - request: "mcp_pb2.EvaluateToolAccessRequest", - ) -> "mcp_pb2.EvaluateToolAccessResponse": - """ - Evaluate tool access (RFC-006). - - Single RPC returns decision + evidence atomically. + channel: A grpc.Channel. """ - raise NotImplementedError("Stub - replace with generated code") - - async def EvaluatePolicyDecision( - self, - request: "mcp_pb2.PolicyDecisionRequest", - ) -> "mcp_pb2.PolicyDecisionResponse": - """ - Evaluate policy decision (RFC-005). - - Centralized PDP decision logic. Returns policy outcome - including obligations — never raises gRPC errors for PDP issues. - """ - raise NotImplementedError("Stub - replace with generated code") - - async def VerifyServerIdentity( - self, - request: "mcp_pb2.VerifyServerIdentityRequest", - ) -> "mcp_pb2.VerifyServerIdentityResponse": - """ - Verify server identity (RFC-007). + self.EvaluateToolAccess = channel.unary_unary( + '/capiscio.v1.MCPService/EvaluateToolAccess', + request_serializer=capiscio_dot_v1_dot_mcp__pb2.EvaluateToolAccessRequest.SerializeToString, + response_deserializer=capiscio_dot_v1_dot_mcp__pb2.EvaluateToolAccessResponse.FromString, + _registered_method=True) + self.EvaluatePolicyDecision = channel.unary_unary( + '/capiscio.v1.MCPService/EvaluatePolicyDecision', + request_serializer=capiscio_dot_v1_dot_mcp__pb2.PolicyDecisionRequest.SerializeToString, + response_deserializer=capiscio_dot_v1_dot_mcp__pb2.PolicyDecisionResponse.FromString, + _registered_method=True) + self.VerifyServerIdentity = channel.unary_unary( + '/capiscio.v1.MCPService/VerifyServerIdentity', + request_serializer=capiscio_dot_v1_dot_mcp__pb2.VerifyServerIdentityRequest.SerializeToString, + response_deserializer=capiscio_dot_v1_dot_mcp__pb2.VerifyServerIdentityResponse.FromString, + _registered_method=True) + self.ParseServerIdentity = channel.unary_unary( + '/capiscio.v1.MCPService/ParseServerIdentity', + request_serializer=capiscio_dot_v1_dot_mcp__pb2.ParseServerIdentityRequest.SerializeToString, + response_deserializer=capiscio_dot_v1_dot_mcp__pb2.ParseServerIdentityResponse.FromString, + _registered_method=True) + self.Health = channel.unary_unary( + '/capiscio.v1.MCPService/Health', + request_serializer=capiscio_dot_v1_dot_mcp__pb2.MCPHealthRequest.SerializeToString, + response_deserializer=capiscio_dot_v1_dot_mcp__pb2.MCPHealthResponse.FromString, + _registered_method=True) + + +class MCPServiceServicer(object): + """MCPService provides unified MCP security operations (RFC-005, RFC-006, RFC-007) + """ + + def EvaluateToolAccess(self, request, context): + """RFC-006: Evaluate tool access and emit evidence atomically + Single RPC returns both decision and evidence to avoid partial failures """ - raise NotImplementedError("Stub - replace with generated code") - - async def ParseServerIdentity( - self, - request: "mcp_pb2.ParseServerIdentityRequest", - ) -> "mcp_pb2.ParseServerIdentityResponse": + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def EvaluatePolicyDecision(self, request, context): + """RFC-005: Centralized policy decision via PDP + Go core owns decision logic, cache, break-glass, telemetry. + SDK callers own obligation execution and response propagation. + NEVER returns an RPC error for PDP unreachability — encodes the outcome + in the response (ALLOW_OBSERVE + error_code) so SDKs don't need to + distinguish transport errors from policy outcomes. """ - Parse server identity from headers/meta. + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def VerifyServerIdentity(self, request, context): + """RFC-007: Verify server identity from disclosed DID + badge """ - raise NotImplementedError("Stub - replace with generated code") - - async def Health( - self, - request: "mcp_pb2.HealthRequest", - ) -> "mcp_pb2.HealthResponse": + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def ParseServerIdentity(self, request, context): + """RFC-007: Extract server identity from transport headers/meta """ - Health check for client supervision. + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def Health(self, request, context): + """Health check for client supervision and version handshake """ - raise NotImplementedError("Stub - replace with generated code") + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') -class MCPServiceServicer: - """ - Servicer base class for MCPService gRPC server. - - This is a placeholder that will be replaced by actual generated code. +def add_MCPServiceServicer_to_server(servicer, server): + rpc_method_handlers = { + 'EvaluateToolAccess': grpc.unary_unary_rpc_method_handler( + servicer.EvaluateToolAccess, + request_deserializer=capiscio_dot_v1_dot_mcp__pb2.EvaluateToolAccessRequest.FromString, + response_serializer=capiscio_dot_v1_dot_mcp__pb2.EvaluateToolAccessResponse.SerializeToString, + ), + 'EvaluatePolicyDecision': grpc.unary_unary_rpc_method_handler( + servicer.EvaluatePolicyDecision, + request_deserializer=capiscio_dot_v1_dot_mcp__pb2.PolicyDecisionRequest.FromString, + response_serializer=capiscio_dot_v1_dot_mcp__pb2.PolicyDecisionResponse.SerializeToString, + ), + 'VerifyServerIdentity': grpc.unary_unary_rpc_method_handler( + servicer.VerifyServerIdentity, + request_deserializer=capiscio_dot_v1_dot_mcp__pb2.VerifyServerIdentityRequest.FromString, + response_serializer=capiscio_dot_v1_dot_mcp__pb2.VerifyServerIdentityResponse.SerializeToString, + ), + 'ParseServerIdentity': grpc.unary_unary_rpc_method_handler( + servicer.ParseServerIdentity, + request_deserializer=capiscio_dot_v1_dot_mcp__pb2.ParseServerIdentityRequest.FromString, + response_serializer=capiscio_dot_v1_dot_mcp__pb2.ParseServerIdentityResponse.SerializeToString, + ), + 'Health': grpc.unary_unary_rpc_method_handler( + servicer.Health, + request_deserializer=capiscio_dot_v1_dot_mcp__pb2.MCPHealthRequest.FromString, + response_serializer=capiscio_dot_v1_dot_mcp__pb2.MCPHealthResponse.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'capiscio.v1.MCPService', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + server.add_registered_method_handlers('capiscio.v1.MCPService', rpc_method_handlers) + + + # This class is part of an EXPERIMENTAL API. +class MCPService(object): + """MCPService provides unified MCP security operations (RFC-005, RFC-006, RFC-007) """ - - async def EvaluateToolAccess( - self, - request: "mcp_pb2.EvaluateToolAccessRequest", - context: "grpc.aio.ServicerContext", - ) -> "mcp_pb2.EvaluateToolAccessResponse": - """Evaluate tool access (RFC-006).""" - raise NotImplementedError("Method not implemented!") - - async def EvaluatePolicyDecision( - self, - request: "mcp_pb2.PolicyDecisionRequest", - context: "grpc.aio.ServicerContext", - ) -> "mcp_pb2.PolicyDecisionResponse": - """Evaluate policy decision (RFC-005).""" - raise NotImplementedError("Method not implemented!") - - async def VerifyServerIdentity( - self, - request: "mcp_pb2.VerifyServerIdentityRequest", - context: "grpc.aio.ServicerContext", - ) -> "mcp_pb2.VerifyServerIdentityResponse": - """Verify server identity (RFC-007).""" - raise NotImplementedError("Method not implemented!") - - async def ParseServerIdentity( - self, - request: "mcp_pb2.ParseServerIdentityRequest", - context: "grpc.aio.ServicerContext", - ) -> "mcp_pb2.ParseServerIdentityResponse": - """Parse server identity from headers/meta.""" - raise NotImplementedError("Method not implemented!") - - async def Health( - self, - request: "mcp_pb2.HealthRequest", - context: "grpc.aio.ServicerContext", - ) -> "mcp_pb2.HealthResponse": - """Health check.""" - raise NotImplementedError("Method not implemented!") - - -def add_MCPServiceServicer_to_server( - servicer: MCPServiceServicer, - server: "grpc.aio.Server", -) -> None: - """Add MCPServiceServicer to a gRPC server.""" - raise NotImplementedError("Stub - replace with generated code") + + @staticmethod + def EvaluateToolAccess(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/capiscio.v1.MCPService/EvaluateToolAccess', + capiscio_dot_v1_dot_mcp__pb2.EvaluateToolAccessRequest.SerializeToString, + capiscio_dot_v1_dot_mcp__pb2.EvaluateToolAccessResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def EvaluatePolicyDecision(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/capiscio.v1.MCPService/EvaluatePolicyDecision', + capiscio_dot_v1_dot_mcp__pb2.PolicyDecisionRequest.SerializeToString, + capiscio_dot_v1_dot_mcp__pb2.PolicyDecisionResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def VerifyServerIdentity(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/capiscio.v1.MCPService/VerifyServerIdentity', + capiscio_dot_v1_dot_mcp__pb2.VerifyServerIdentityRequest.SerializeToString, + capiscio_dot_v1_dot_mcp__pb2.VerifyServerIdentityResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def ParseServerIdentity(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/capiscio.v1.MCPService/ParseServerIdentity', + capiscio_dot_v1_dot_mcp__pb2.ParseServerIdentityRequest.SerializeToString, + capiscio_dot_v1_dot_mcp__pb2.ParseServerIdentityResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def Health(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/capiscio.v1.MCPService/Health', + capiscio_dot_v1_dot_mcp__pb2.MCPHealthRequest.SerializeToString, + capiscio_dot_v1_dot_mcp__pb2.MCPHealthResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) diff --git a/capiscio_mcp/guard.py b/capiscio_mcp/guard.py index f72299c..fb2a132 100644 --- a/capiscio_mcp/guard.py +++ b/capiscio_mcp/guard.py @@ -244,6 +244,8 @@ async def evaluate_tool_access( params: dict[str, Any], credential: Optional[CallerCredential] = None, config: Optional[GuardConfig] = None, + capability_class: Optional[str] = None, + deny_on_unknown_class: Optional[bool] = None, ) -> GuardResult: """ Evaluate tool access via capiscio-core. @@ -255,6 +257,8 @@ async def evaluate_tool_access( params: Tool parameters (will be hashed, never sent raw) credential: Caller credential (default: from context) config: Guard configuration + capability_class: RFC-008 capability class for policy evaluation + deny_on_unknown_class: RFC-008 unknown class behavior (None/True=deny, False=allow) Returns: GuardResult with decision and evidence @@ -295,6 +299,12 @@ async def evaluate_tool_access( elif effective_credential.api_key: request.api_key = effective_credential.api_key # If neither: anonymous (implicit) + + # RFC-008: Set capability class fields + if capability_class: + request.capability_class = capability_class + if deny_on_unknown_class is not None: + request.deny_on_unknown_class = deny_on_unknown_class # Make RPC call response = await client.stub.EvaluateToolAccess(request) @@ -351,6 +361,8 @@ def guard( min_trust_level: Optional[int] = None, tool_name: Optional[str] = None, require_badge: bool = False, + capability_class: Optional[str] = None, + deny_on_unknown_class: Optional[bool] = None, ) -> Callable[[Callable[P, Coroutine[Any, Any, R]]], Callable[P, Coroutine[Any, Any, R]]]: ... @@ -362,6 +374,8 @@ def guard( min_trust_level: Optional[int] = None, tool_name: Optional[str] = None, require_badge: bool = False, + capability_class: Optional[str] = None, + deny_on_unknown_class: Optional[bool] = None, ) -> Union[ Callable[P, Coroutine[Any, Any, R]], Callable[[Callable[P, Coroutine[Any, Any, R]]], Callable[P, Coroutine[Any, Any, R]]], @@ -377,6 +391,8 @@ def guard( min_trust_level: Shorthand for config.min_trust_level tool_name: Override tool name (default: function name) require_badge: If True, deny anonymous/API key access + capability_class: RFC-008 capability class for policy evaluation + deny_on_unknown_class: RFC-008 unknown class behavior (None/True=deny, False=allow) Returns: Decorated function that enforces access control @@ -392,6 +408,11 @@ async def list_files() -> list[str]: async def execute_query(sql: str) -> list[dict]: ... + # With capability class enforcement + @guard(capability_class="invoice-management") + async def create_invoice(amount: float) -> dict: + ... + # With full configuration @guard(config=GuardConfig( min_trust_level=2, @@ -423,6 +444,8 @@ async def wrapper(*args: P.args, **kwargs: P.kwargs) -> R: tool_name=effective_tool_name, params=params, config=effective_config, + capability_class=capability_class, + deny_on_unknown_class=deny_on_unknown_class, ) # Check decision @@ -459,6 +482,8 @@ def guard_sync( min_trust_level: Optional[int] = None, tool_name: Optional[str] = None, require_badge: bool = False, + capability_class: Optional[str] = None, + deny_on_unknown_class: Optional[bool] = None, ) -> Union[Callable[P, R], Callable[[Callable[P, R]], Callable[P, R]]]: """ Sync decorator to guard MCP tool execution. @@ -499,6 +524,8 @@ async def run_eval(): tool_name=effective_tool_name, params=params, config=effective_config, + capability_class=capability_class, + deny_on_unknown_class=deny_on_unknown_class, ) try: