asap-protocol 2.4.1__tar.gz → 2.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (201) hide show
  1. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/CHANGELOG.md +70 -1
  2. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/PKG-INFO +5 -5
  3. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/README.md +3 -3
  4. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/pyproject.toml +15 -9
  5. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/__init__.py +1 -1
  6. asap_protocol-2.5.0/src/asap/adapters/mcp/__init__.py +17 -0
  7. asap_protocol-2.5.0/src/asap/adapters/mcp/auth_middleware.py +33 -0
  8. asap_protocol-2.5.0/src/asap/adapters/mcp/capability_map.py +74 -0
  9. asap_protocol-2.5.0/src/asap/adapters/mcp/config.py +70 -0
  10. asap_protocol-2.5.0/src/asap/adapters/mcp/errors.py +32 -0
  11. asap_protocol-2.5.0/src/asap/adapters/mcp/jwt_extractor.py +52 -0
  12. asap_protocol-2.5.0/src/asap/adapters/mcp/protected_server.py +176 -0
  13. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/auth/jwks.py +10 -1
  14. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/auth/middleware.py +19 -5
  15. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/economics/delegation_storage.py +13 -2
  16. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/economics/storage.py +2 -3
  17. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/mcp/client.py +19 -2
  18. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/mcp/protocol.py +1 -0
  19. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/mcp/server.py +15 -3
  20. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/registry/bot_pr.py +30 -35
  21. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/.gitignore +0 -0
  22. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/LICENSE +0 -0
  23. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/schemas/entities/agent.schema.json +0 -0
  24. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/schemas/entities/artifact.schema.json +0 -0
  25. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/schemas/entities/conversation.schema.json +0 -0
  26. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/schemas/entities/manifest.schema.json +0 -0
  27. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/schemas/entities/message.schema.json +0 -0
  28. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/schemas/entities/state_snapshot.schema.json +0 -0
  29. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/schemas/entities/task.schema.json +0 -0
  30. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/schemas/envelope.schema.json +0 -0
  31. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/schemas/examples/shellclaw-jetson-capabilities.json +0 -0
  32. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/schemas/parts/data_part.schema.json +0 -0
  33. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/schemas/parts/file_part.schema.json +0 -0
  34. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/schemas/parts/resource_part.schema.json +0 -0
  35. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/schemas/parts/template_part.schema.json +0 -0
  36. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/schemas/parts/text_part.schema.json +0 -0
  37. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/schemas/payloads/artifact_notify.schema.json +0 -0
  38. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/schemas/payloads/mcp_resource_data.schema.json +0 -0
  39. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/schemas/payloads/mcp_resource_fetch.schema.json +0 -0
  40. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/schemas/payloads/mcp_tool_call.schema.json +0 -0
  41. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/schemas/payloads/mcp_tool_result.schema.json +0 -0
  42. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/schemas/payloads/message_send.schema.json +0 -0
  43. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/schemas/payloads/state_query.schema.json +0 -0
  44. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/schemas/payloads/state_restore.schema.json +0 -0
  45. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/schemas/payloads/task_cancel.schema.json +0 -0
  46. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/schemas/payloads/task_request.schema.json +0 -0
  47. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/schemas/payloads/task_response.schema.json +0 -0
  48. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/schemas/payloads/task_update.schema.json +0 -0
  49. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/adapters/__init__.py +0 -0
  50. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/adapters/openapi/__init__.py +0 -0
  51. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/adapters/openapi/approval.py +0 -0
  52. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/adapters/openapi/capability_mapper.py +0 -0
  53. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/adapters/openapi/factory.py +0 -0
  54. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/adapters/openapi/handler.py +0 -0
  55. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/adapters/openapi/spec_loader.py +0 -0
  56. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/auth/__init__.py +0 -0
  57. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/auth/agent_jwt.py +0 -0
  58. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/auth/approval.py +0 -0
  59. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/auth/capabilities.py +0 -0
  60. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/auth/claims.py +0 -0
  61. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/auth/identity.py +0 -0
  62. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/auth/introspection.py +0 -0
  63. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/auth/lifecycle.py +0 -0
  64. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/auth/oauth2.py +0 -0
  65. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/auth/oidc.py +0 -0
  66. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/auth/scopes.py +0 -0
  67. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/auth/self_auth.py +0 -0
  68. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/auth/utils.py +0 -0
  69. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/auth/webauthn.py +0 -0
  70. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/cli/__init__.py +0 -0
  71. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/cli/audit_export.py +0 -0
  72. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/cli/compliance_check.py +0 -0
  73. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/client/__init__.py +0 -0
  74. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/client/cache.py +0 -0
  75. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/client/http_client.py +0 -0
  76. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/client/market.py +0 -0
  77. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/client/revocation.py +0 -0
  78. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/client/trust.py +0 -0
  79. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/crypto/__init__.py +0 -0
  80. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/crypto/keys.py +0 -0
  81. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/crypto/models.py +0 -0
  82. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/crypto/signing.py +0 -0
  83. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/crypto/trust.py +0 -0
  84. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/crypto/trust_levels.py +0 -0
  85. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/discovery/__init__.py +0 -0
  86. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/discovery/dnssd.py +0 -0
  87. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/discovery/health.py +0 -0
  88. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/discovery/registry.py +0 -0
  89. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/discovery/validation.py +0 -0
  90. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/discovery/wellknown.py +0 -0
  91. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/economics/__init__.py +0 -0
  92. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/economics/audit.py +0 -0
  93. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/economics/delegation.py +0 -0
  94. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/economics/hooks.py +0 -0
  95. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/economics/metering.py +0 -0
  96. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/economics/sla.py +0 -0
  97. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/economics/sla_storage.py +0 -0
  98. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/errors.py +0 -0
  99. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/examples/README.md +0 -0
  100. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/examples/__init__.py +0 -0
  101. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/examples/a2h_approval.py +0 -0
  102. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/examples/agent_failover.py +0 -0
  103. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/examples/auth_patterns.py +0 -0
  104. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/examples/coordinator.py +0 -0
  105. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/examples/echo_agent.py +0 -0
  106. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/examples/error_recovery.py +0 -0
  107. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/examples/long_running.py +0 -0
  108. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/examples/mcp_client_demo.py +0 -0
  109. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/examples/mcp_integration.py +0 -0
  110. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/examples/multi_step_workflow.py +0 -0
  111. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/examples/orchestration.py +0 -0
  112. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/examples/rate_limiting.py +0 -0
  113. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/examples/run_demo.py +0 -0
  114. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/examples/secure_agent.py +0 -0
  115. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/examples/secure_handler.py +0 -0
  116. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/examples/state_migration.py +0 -0
  117. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/examples/storage_backends.py +0 -0
  118. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/examples/streaming_agent.py +0 -0
  119. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/examples/streaming_response.py +0 -0
  120. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/examples/v1_3_0_showcase.py +0 -0
  121. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/examples/v1_4_0_showcase.py +0 -0
  122. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/examples/websocket_concept.py +0 -0
  123. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/handlers/__init__.py +0 -0
  124. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/handlers/hitl.py +0 -0
  125. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/integrations/__init__.py +0 -0
  126. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/integrations/a2h.py +0 -0
  127. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/integrations/crewai.py +0 -0
  128. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/integrations/langchain.py +0 -0
  129. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/integrations/llamaindex.py +0 -0
  130. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/integrations/openclaw.py +0 -0
  131. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/integrations/pydanticai.py +0 -0
  132. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/integrations/smolagents.py +0 -0
  133. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/integrations/vercel_ai.py +0 -0
  134. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/mcp/__init__.py +0 -0
  135. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/mcp/serve.py +0 -0
  136. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/mcp/server_runner.py +0 -0
  137. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/models/__init__.py +0 -0
  138. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/models/base.py +0 -0
  139. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/models/constants.py +0 -0
  140. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/models/entities.py +0 -0
  141. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/models/enums.py +0 -0
  142. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/models/envelope.py +0 -0
  143. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/models/ids.py +0 -0
  144. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/models/parts.py +0 -0
  145. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/models/payloads.py +0 -0
  146. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/models/types.py +0 -0
  147. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/models/validators.py +0 -0
  148. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/observability/__init__.py +0 -0
  149. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/observability/dashboards/README.md +0 -0
  150. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/observability/dashboards/asap-detailed.json +0 -0
  151. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/observability/dashboards/asap-red.json +0 -0
  152. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/observability/logging.py +0 -0
  153. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/observability/metrics.py +0 -0
  154. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/observability/trace_parser.py +0 -0
  155. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/observability/trace_ui.py +0 -0
  156. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/observability/tracing.py +0 -0
  157. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/registry/__init__.py +0 -0
  158. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/registry/anti_spam.py +0 -0
  159. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/registry/auto_registration.py +0 -0
  160. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/registry/receipt_cache.py +0 -0
  161. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/schemas.py +0 -0
  162. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/state/__init__.py +0 -0
  163. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/state/machine.py +0 -0
  164. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/state/metering.py +0 -0
  165. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/state/snapshot.py +0 -0
  166. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/state/stores/__init__.py +0 -0
  167. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/state/stores/memory.py +0 -0
  168. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/state/stores/sqlite.py +0 -0
  169. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/testing/__init__.py +0 -0
  170. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/testing/asgi_factory.py +0 -0
  171. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/testing/assertions.py +0 -0
  172. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/testing/compliance.py +0 -0
  173. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/testing/fixtures.py +0 -0
  174. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/testing/mocks.py +0 -0
  175. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/transport/__init__.py +0 -0
  176. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/transport/_auth_helpers.py +0 -0
  177. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/transport/agent_routes.py +0 -0
  178. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/transport/cache.py +0 -0
  179. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/transport/capability_routes.py +0 -0
  180. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/transport/challenge.py +0 -0
  181. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/transport/circuit_breaker.py +0 -0
  182. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/transport/client.py +0 -0
  183. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/transport/codecs/__init__.py +0 -0
  184. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/transport/codecs/lambda_codec.py +0 -0
  185. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/transport/compression.py +0 -0
  186. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/transport/delegation_api.py +0 -0
  187. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/transport/escalation_routes.py +0 -0
  188. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/transport/executors.py +0 -0
  189. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/transport/handlers.py +0 -0
  190. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/transport/jsonrpc.py +0 -0
  191. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/transport/middleware.py +0 -0
  192. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/transport/mtls.py +0 -0
  193. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/transport/rate_limit.py +0 -0
  194. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/transport/server.py +0 -0
  195. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/transport/sla_api.py +0 -0
  196. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/transport/usage_api.py +0 -0
  197. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/transport/validators.py +0 -0
  198. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/transport/webhook.py +0 -0
  199. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/transport/websocket.py +0 -0
  200. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/utils/__init__.py +0 -0
  201. {asap_protocol-2.4.1 → asap_protocol-2.5.0}/src/asap/utils/sanitization.py +0 -0
@@ -12,7 +12,76 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
12
12
  - `extra="forbid"` on ingress payload models (`TaskRequestConfig`, `CommonMetadata`)
13
13
  - Opt-in protection for operator APIs (`/usage`, `/sla`, `/audit`)
14
14
  - Redis-backed `JtiReplayCache` and distributed Next.js rate limits
15
- - Bump optional `pydantic-ai` extra (CVE-2026-46678)
15
+ - `@asap-protocol/mcp-auth` HTTP/SSE middleware (deferred from v2.5.0 — see [2.5.0] TypeScript note and [typescript-mcp-auth-spike.md](engineering/tasks/v2.5.0/typescript-mcp-auth-spike.md))
16
+
17
+ ### Fixed
18
+
19
+ - **CI security (`pip-audit`)**: Raised `cryptography` to `>=48.0.1,<49` (GHSA-537c-gmf6-5ccf), `python-multipart>=0.0.31` (CVE-2026-53538–53540), and `starlette>=1.3.1` (CVE-2026-54282 / CVE-2026-54283) via `pyproject.toml` floors and `tool.uv.override-dependencies`.
20
+ - **pydantic-ai (CVE-2026-46678)**: Optional `[pydanticai]` extra pins `pydantic-ai>=1.99.0`; removed obsolete `pip-audit` ignore from CI.
21
+
22
+ ---
23
+
24
+ ## [2.5.0] - 2026-06-24
25
+
26
+ **MCP Auth Bridge** — ASAP Host/Agent JWT and capability grants as an **opt-in**
27
+ authorization layer for native **stdio MCP** `tools/call` (Mode A). Unprotected
28
+ `MCPServer` usage is unchanged. No wire-protocol or manifest schema breaking
29
+ changes.
30
+
31
+ ### Added
32
+
33
+ - **feat(adapters): MCP Auth Bridge (`asap.adapters.mcp`)**
34
+ - **`protect_server(server, config)`** — wraps `MCPServer` via
35
+ `ProtectedMCPServer`; intercepts `_handle_tools_call` only (MCP-AUTH-006).
36
+ - **`MCPAuthConfig`** (`config.py`) — `host_store`, `agent_store`,
37
+ `capability_registry`, `tool_capability_map`, `public_tools`,
38
+ `enforce_grants`, `jwt_extractor`, `jti_replay_cache`, `expected_audience`.
39
+ - **Token carriage (stdio)** — Agent JWT in `tools/call` params
40
+ `_meta.asap_agent_jwt`; optional dev-only `ASAP_AGENT_JWT` when
41
+ `allow_env_jwt_fallback=True`.
42
+ - **Grant enforcement** — `verify_agent_jwt` + `CapabilityRegistry.check_grant`
43
+ with constraint validation on tool arguments; MCP-safe `asap:*` error codes
44
+ (`asap:auth_required`, `asap:invalid_token`, `asap:capability_denied`,
45
+ `asap:constraint_violation`).
46
+ - **Tool → capability mapping** — explicit `tool_capability_map`, register-time
47
+ metadata, or default identity (tool name == capability); optional startup
48
+ validation (`validate_tools_at_startup`).
49
+ - **Reference example** — `examples/mcp_auth_bridge/` (protected stdio server +
50
+ client, smoke tests in `tests/examples/test_mcp_auth_bridge_example.py`).
51
+ - **Docs** — [MCP Auth Bridge adapter](docs/adapters/mcp-auth-bridge.md);
52
+ [MCP integration](docs/mcp-integration.md) distinguishes Mode A (native MCP +
53
+ bridge) vs Mode B (MCP-over-ASAP envelope).
54
+ - **feat(compliance): `mcp-auth-bridge` profile** (`asap-compliance`) — stdio MCP
55
+ release gate: auth paths, grants, constraints, manifest tools ⊆ registered
56
+ tools (MCP-DISC-003). Requires `asap-protocol>=2.5.0`.
57
+ - **test(adapters/mcp)** — unit, grant, startup, and stdio integration coverage
58
+ (≥90% on `asap.adapters.mcp`).
59
+
60
+ ### Deferred (not in v2.5.0)
61
+
62
+ - **`hide_unauthorized_tools` / `tools/list` filtering** (MCP-MAP-004) — no
63
+ standard JWT carriage on stdio `tools/list` today; see
64
+ [design lock](engineering/tasks/v2.5.0/design-lock-mcp-auth-bridge.md).
65
+ - **`initialize` session-token handshake** (PRD §4.3 SHOULD) — clients pass JWT
66
+ on each protected `tools/call` in v2.5.0.
67
+
68
+ ### TypeScript
69
+
70
+ - **`@asap-protocol/mcp-auth` deferred to v2.5.0.1** — MCP-TS-001..003 (HTTP/SSE
71
+ Bearer middleware) are SHOULD-scope; v2.5.0 ships the Python stdio bridge as the
72
+ release gate. Rationale and implementation checklist:
73
+ [typescript-mcp-auth-spike.md](engineering/tasks/v2.5.0/typescript-mcp-auth-spike.md);
74
+ carry-over tracked in
75
+ [PRD v2.5.1 §3](product/prd/prd-v2.5.1-adapter-lab-ii.md#3-carry-over-from-v250-asap-protocolmcp-auth).
76
+ Existing `@asap-protocol/*` npm packages remain at **2.4.1** until a separate
77
+ publish.
78
+
79
+ ### Migration
80
+
81
+ - **v2.4.1 → v2.5.0**: **No breaking changes.** MCP servers without
82
+ `protect_server` behave as before. To enforce Agent JWT + capabilities on native
83
+ MCP, wrap your server with `protect_server` and configure grants — see
84
+ [MCP Auth Bridge adapter](docs/adapters/mcp-auth-bridge.md).
16
85
 
17
86
  ---
18
87
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: asap-protocol
3
- Version: 2.4.1
3
+ Version: 2.5.0
4
4
  Summary: Async Simple Agent Protocol - A streamlined protocol for agent-to-agent communication
5
5
  Project-URL: Homepage, https://github.com/adriannoes/asap-protocol
6
6
  Project-URL: Documentation, https://adriannoes.github.io/asap-protocol
@@ -23,7 +23,7 @@ Requires-Python: >=3.13
23
23
  Requires-Dist: aiosqlite>=0.20
24
24
  Requires-Dist: authlib<2,>=1.6.12
25
25
  Requires-Dist: brotli>=1.2.0
26
- Requires-Dist: cryptography<47,>=46.0.7
26
+ Requires-Dist: cryptography<49,>=48.0.1
27
27
  Requires-Dist: fastapi>=0.136.1
28
28
  Requires-Dist: httpx[http2]>=0.28.1
29
29
  Requires-Dist: jcs>=0.2.0
@@ -95,7 +95,7 @@ Description-Content-Type: text/markdown
95
95
 
96
96
  > A production-ready protocol for agent-to-agent communication and task coordination.
97
97
 
98
- **Quick Info**: `v2.4.1` (PyPI) · **npm TS [`2.4.1`](https://github.com/adriannoes/asap-protocol/releases/tag/v2.4.1)** | `Apache 2.0` | `Python 3.13+` | [Documentation](https://github.com/adriannoes/asap-protocol/blob/main/docs/index.md) | **[PyPI `asap-protocol`](https://pypi.org/project/asap-protocol/)** | **[npm `@asap-protocol/client`](https://www.npmjs.com/package/@asap-protocol/client)** | [Changelog](https://github.com/adriannoes/asap-protocol/blob/main/CHANGELOG.md)
98
+ **Quick Info**: `v2.5.0` (release branch; PyPI/npm publish on `v2.5.0` tag) · **npm TS [`2.4.1`](https://github.com/adriannoes/asap-protocol/releases/tag/v2.4.1)** (latest published) | `Apache 2.0` | `Python 3.13+` | [Documentation](https://github.com/adriannoes/asap-protocol/blob/main/docs/index.md) | **[PyPI `asap-protocol`](https://pypi.org/project/asap-protocol/)** | **[npm `@asap-protocol/client`](https://www.npmjs.com/package/@asap-protocol/client)** | [Changelog](https://github.com/adriannoes/asap-protocol/blob/main/CHANGELOG.md)
99
99
 
100
100
  > 📦 Install the ASAP **Python SDK / protocol** from **`https://pypi.org/project/asap-protocol/`** — package name **`asap-protocol`** on [PyPI](https://pypi.org/project/asap-protocol/).
101
101
 
@@ -176,10 +176,10 @@ uv run python -m asap.examples.run_demo
176
176
  uv run pytest -n auto --tb=short
177
177
  ```
178
178
 
179
- With coverage:
179
+ With coverage (separate run — do not combine with `-n auto`):
180
180
 
181
181
  ```bash
182
- uv run pytest --cov=src --cov-report=term-missing
182
+ uv run pytest --tb=short --cov=asap --cov-report=term-missing --cov-fail-under=85
183
183
  ```
184
184
 
185
185
  [Testing Guide](https://github.com/adriannoes/asap-protocol/blob/main/docs/testing.md) (structure, fixtures, property/load/chaos tests). [Contributing](https://github.com/adriannoes/asap-protocol/blob/main/CONTRIBUTING.md) (dev setup, CI).
@@ -7,7 +7,7 @@
7
7
 
8
8
  > A production-ready protocol for agent-to-agent communication and task coordination.
9
9
 
10
- **Quick Info**: `v2.4.1` (PyPI) · **npm TS [`2.4.1`](https://github.com/adriannoes/asap-protocol/releases/tag/v2.4.1)** | `Apache 2.0` | `Python 3.13+` | [Documentation](https://github.com/adriannoes/asap-protocol/blob/main/docs/index.md) | **[PyPI `asap-protocol`](https://pypi.org/project/asap-protocol/)** | **[npm `@asap-protocol/client`](https://www.npmjs.com/package/@asap-protocol/client)** | [Changelog](https://github.com/adriannoes/asap-protocol/blob/main/CHANGELOG.md)
10
+ **Quick Info**: `v2.5.0` (release branch; PyPI/npm publish on `v2.5.0` tag) · **npm TS [`2.4.1`](https://github.com/adriannoes/asap-protocol/releases/tag/v2.4.1)** (latest published) | `Apache 2.0` | `Python 3.13+` | [Documentation](https://github.com/adriannoes/asap-protocol/blob/main/docs/index.md) | **[PyPI `asap-protocol`](https://pypi.org/project/asap-protocol/)** | **[npm `@asap-protocol/client`](https://www.npmjs.com/package/@asap-protocol/client)** | [Changelog](https://github.com/adriannoes/asap-protocol/blob/main/CHANGELOG.md)
11
11
 
12
12
  > 📦 Install the ASAP **Python SDK / protocol** from **`https://pypi.org/project/asap-protocol/`** — package name **`asap-protocol`** on [PyPI](https://pypi.org/project/asap-protocol/).
13
13
 
@@ -88,10 +88,10 @@ uv run python -m asap.examples.run_demo
88
88
  uv run pytest -n auto --tb=short
89
89
  ```
90
90
 
91
- With coverage:
91
+ With coverage (separate run — do not combine with `-n auto`):
92
92
 
93
93
  ```bash
94
- uv run pytest --cov=src --cov-report=term-missing
94
+ uv run pytest --tb=short --cov=asap --cov-report=term-missing --cov-fail-under=85
95
95
  ```
96
96
 
97
97
  [Testing Guide](https://github.com/adriannoes/asap-protocol/blob/main/docs/testing.md) (structure, fixtures, property/load/chaos tests). [Contributing](https://github.com/adriannoes/asap-protocol/blob/main/CONTRIBUTING.md) (dev setup, CI).
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "asap-protocol"
3
- version = "2.4.1"
3
+ version = "2.5.0"
4
4
  description = "Async Simple Agent Protocol - A streamlined protocol for agent-to-agent communication"
5
5
  authors = [
6
6
  {name = "ASAP Protocol Contributors"}
@@ -23,7 +23,7 @@ classifiers = [
23
23
  dependencies = [
24
24
  "aiosqlite>=0.20",
25
25
  # Upper-bound majors per SECURITY.md dependency policy.
26
- "cryptography>=46.0.7,<47",
26
+ "cryptography>=48.0.1,<49",
27
27
  "jcs>=0.2.0",
28
28
  "jsonschema>=4.23.0",
29
29
  "pydantic>=2.12.5,<3",
@@ -121,17 +121,20 @@ Issues = "https://github.com/adriannoes/asap-protocol/issues"
121
121
  # - zeroconf>=0.149.5 for CVE-2026-47180/47183/47184 ([dns-sd] extra)
122
122
  # - pyasn1>=0.6.3 for CVE-2026-30922 (DoS via unbounded recursion)
123
123
  # - tinytag>=2.2.1 for CVE-2026-32889
124
- # - cryptography>=46.0.7 for CVE-2026-39892 / CVE-2026-34073 (name-constraint / peer identity)
124
+ # - cryptography>=48.0.1 for GHSA-537c-gmf6-5ccf (CVE-2026-39892 / CVE-2026-34073 baseline at 46.0.7)
125
125
  # - requests>=2.33.0 for CVE-2026-25645 (extract_zipped_paths temp file)
126
126
  # - pillow>=12.2.0 for CVE-2026-40192 (transitive, e.g. pdf/vision stacks)
127
127
  # - pytest>=9.0.3 for CVE-2025-71176 (dev)
128
- # - python-multipart>=0.0.27 for CVE-2026-42561 / CVE-2026-40347 (FastAPI stack)
128
+ # - python-multipart>=0.0.31 for CVE-2026-53538–53540 (FastAPI stack; prior floor 0.0.27)
129
+ # - starlette>=1.3.1 for CVE-2026-54282 / CVE-2026-54283 (FastAPI stack)
129
130
  # - pygments>=2.20.0 for CVE-2026-4539
130
- # - langsmith>=0.8.0 for CVE-2026-45134 (prior: GHSA-rr7j-v2q5-chgv)
131
+ # - langsmith>=0.8.18 for GHSA-f4xh-w4cj-qxq8 (prior: CVE-2026-45134 at >=0.8.0)
131
132
  # - langchain-core>=1.3.3 for CVE-2026-44843
132
133
  # - urllib3>=2.7.0 for CVE-2026-44431 / CVE-2026-44432
133
134
  # - pip>=26.1.2 for PYSEC-2026-196 (CVE-2026-6357 baseline at 26.1)
134
135
  # - python-dotenv>=1.2.2 for CVE-2026-28684 (transitive, e.g. pydantic-settings / uvicorn stacks)
136
+ # - pydantic-settings>=2.14.2 for GHSA-4xgf-cpjx-pc3j (transitive, e.g. langchain / mcp stacks)
137
+ # - msgpack>=1.2.1 for GHSA-6v7p-g79w-8964 (transitive, e.g. locust / cache stacks)
135
138
  # - idna>=3.15 for CVE-2026-45409 (DoS in idna.encode; transitive via httpx/requests)
136
139
  # - markdown>=3.10.2 for PYSEC-2026-89 (DoS in html.parser during Markdown parse; mkdocs stack)
137
140
  # - pymdown-extensions>=10.21.3 for CVE-2026-46338 (snippets base_path prefix bypass; mkdocs stack)
@@ -141,13 +144,14 @@ override-dependencies = [
141
144
  "pyjwt>=2.13.0,<3",
142
145
  "pyasn1>=0.6.3",
143
146
  "tinytag>=2.2.1",
144
- "cryptography>=46.0.7,<47",
147
+ "cryptography>=48.0.1,<49",
145
148
  "requests>=2.33.0",
146
149
  "pillow>=12.2.0",
147
150
  "pytest>=9.0.3",
148
- "python-multipart>=0.0.27",
151
+ "python-multipart>=0.0.31",
152
+ "starlette>=1.3.1",
149
153
  "pygments>=2.20.0",
150
- "langsmith>=0.8.0",
154
+ "langsmith>=0.8.18",
151
155
  "langchain-core>=1.3.3",
152
156
  "urllib3>=2.7.0",
153
157
  "pip>=26.1.2",
@@ -156,6 +160,8 @@ override-dependencies = [
156
160
  "idna>=3.15",
157
161
  "markdown>=3.10.2",
158
162
  "pymdown-extensions>=10.21.3",
163
+ "pydantic-settings>=2.14.2",
164
+ "msgpack>=1.2.1",
159
165
  ]
160
166
 
161
167
  [project.scripts]
@@ -306,7 +312,7 @@ addopts = [
306
312
  "--strict-markers",
307
313
  "--strict-config",
308
314
  ]
309
- # Coverage options: use explicitly when needed (e.g., pytest --cov=src --cov-report=xml)
315
+ # Coverage options: use explicitly when needed (e.g., pytest --tb=short --cov=asap --cov-report=xml --cov-fail-under=85)
310
316
  # NOT included in addopts to avoid conflicts with pytest-xdist (-n auto)
311
317
  testpaths = ["tests"]
312
318
  # Note: benchmarks/ excluded from testpaths - Locust monkey-patches gevent/ssl which
@@ -8,7 +8,7 @@ from __future__ import annotations
8
8
 
9
9
  from typing import Any
10
10
 
11
- __version__ = "2.4.1"
11
+ __version__ = "2.5.0"
12
12
 
13
13
  __all__ = ["__version__", "create_from_openapi"]
14
14
 
@@ -0,0 +1,17 @@
1
+ """MCP Auth Bridge adapter (v2.5.0).
2
+
3
+ Opt-in protection for native ``MCPServer`` via ``protect_server``.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ from asap.adapters.mcp.auth_middleware import protect_server
9
+ from asap.adapters.mcp.config import MCPAuthConfig, resolve_jwt_extractor
10
+ from asap.adapters.mcp.protected_server import ProtectedMCPServer
11
+
12
+ __all__ = [
13
+ "MCPAuthConfig",
14
+ "ProtectedMCPServer",
15
+ "protect_server",
16
+ "resolve_jwt_extractor",
17
+ ]
@@ -0,0 +1,33 @@
1
+ """MCP Auth Bridge middleware entry point (v2.5.0)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from asap.adapters.mcp.config import MCPAuthConfig, resolve_jwt_extractor
6
+ from asap.adapters.mcp.protected_server import ProtectedMCPServer
7
+ from asap.mcp.server import MCPServer
8
+
9
+ __all__ = ["MCPAuthConfig", "protect_server", "resolve_jwt_extractor"]
10
+
11
+
12
+ def protect_server(server: MCPServer, config: MCPAuthConfig) -> ProtectedMCPServer:
13
+ """Return an MCP server with JWT and capability enforcement on ``tools/call``.
14
+
15
+ Verifies Agent JWT extraction/verification, the ``public_tools`` allowlist, and
16
+ (when ``enforce_grants=True``) JWT capability claims plus
17
+ :meth:`~asap.auth.capabilities.CapabilityRegistry.check_grant`.
18
+
19
+ ``from_server`` copies register-time capability metadata onto the protected instance
20
+ without mutating ``config``.
21
+
22
+ See PRD v2.5.0 MCP Auth Bridge (``product/prd/prd-v2.5.0-mcp-auth-bridge.md``)
23
+ and design lock ADR (``engineering/tasks/v2.5.0/design-lock-mcp-auth-bridge.md``).
24
+
25
+ Args:
26
+ server: Native MCP server with registered tools.
27
+ config: Auth configuration (identity stores, capability registry, extractors).
28
+
29
+ Returns:
30
+ Protected server instance; unprotected ``MCPServer`` usage remains valid when
31
+ this function is not called.
32
+ """
33
+ return ProtectedMCPServer.from_server(server, config)
@@ -0,0 +1,74 @@
1
+ """Tool-to-capability resolution for MCP Auth Bridge (v2.5.0)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from asap.adapters.mcp.config import MCPAuthConfig
6
+ from asap.auth.capabilities import ConstraintViolation
7
+ from asap.mcp.server import MCPServer
8
+
9
+
10
+ def resolve_capability(
11
+ tool_name: str,
12
+ config: MCPAuthConfig,
13
+ *,
14
+ server: MCPServer | None = None,
15
+ ) -> str:
16
+ """Resolve an MCP tool name to an ASAP capability name.
17
+
18
+ Resolution order (MCP-MAP-001, MCP-MAP-002):
19
+
20
+ 1. ``config.tool_capability_map`` (explicit runtime override)
21
+ 2. ``server.get_tool_capability(tool_name)`` when register-time metadata is set
22
+ 3. Identity default: ``tool_name`` unchanged
23
+
24
+ Args:
25
+ tool_name: Registered MCP tool name from ``tools/call``.
26
+ config: MCP auth configuration including capability maps.
27
+ server: MCP server providing register-time capability metadata.
28
+
29
+ Returns:
30
+ ASAP capability name used for grant checks.
31
+
32
+ Example:
33
+ >>> from asap.adapters.mcp.config import MCPAuthConfig
34
+ >>> from asap.auth.capabilities import CapabilityRegistry
35
+ >>> from asap.auth.identity import InMemoryAgentStore, InMemoryHostStore
36
+ >>> from asap.mcp.server import MCPServer
37
+ >>> agents = InMemoryAgentStore()
38
+ >>> config = MCPAuthConfig(
39
+ ... host_store=InMemoryHostStore(agent_store=agents),
40
+ ... agent_store=agents,
41
+ ... capability_registry=CapabilityRegistry(),
42
+ ... tool_capability_map={"search": "web_search"},
43
+ ... )
44
+ >>> resolve_capability("search", config)
45
+ 'web_search'
46
+ >>> resolve_capability("echo", config)
47
+ 'echo'
48
+ """
49
+ if tool_name in config.tool_capability_map:
50
+ return config.tool_capability_map[tool_name]
51
+ if server is not None:
52
+ registered = server.get_tool_capability(tool_name)
53
+ if registered is not None:
54
+ return registered
55
+ return tool_name
56
+
57
+
58
+ def format_constraint_violations(violations: list[ConstraintViolation]) -> str:
59
+ """Format grant constraint violations for MCP ``tools/call`` error detail.
60
+
61
+ Args:
62
+ violations: Constraint failures from :meth:`CapabilityRegistry.check_grant`.
63
+
64
+ Returns:
65
+ Human-readable detail string joined with ``; ``.
66
+
67
+ Example:
68
+ >>> from asap.auth.capabilities import ConstraintViolation
69
+ >>> format_constraint_violations([
70
+ ... ConstraintViolation("tokens", "max", 100, 150, "tokens: 150 exceeds maximum 100"),
71
+ ... ])
72
+ 'tokens: 150 exceeds maximum 100'
73
+ """
74
+ return "; ".join(v.message for v in violations)
@@ -0,0 +1,70 @@
1
+ """MCP Auth Bridge configuration (v2.5.0)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Callable
6
+ from dataclasses import dataclass, field
7
+
8
+ from asap.adapters.mcp.jwt_extractor import default_jwt_extractor
9
+ from asap.auth.agent_jwt import JtiReplayCache
10
+ from asap.auth.capabilities import CapabilityRegistry
11
+ from asap.auth.identity import AgentStore, HostStore
12
+ from asap.mcp.protocol import CallToolRequestParams
13
+
14
+
15
+ MCP_COMPLIANCE_ENV_VAR = "ASAP_MCP_COMPLIANCE"
16
+
17
+
18
+ @dataclass
19
+ class MCPAuthConfig:
20
+ """Configuration for ASAP auth on a native MCP server.
21
+
22
+ JWT extraction: middleware MUST call :func:`resolve_jwt_extractor` (or
23
+ equivalent ``config.jwt_extractor or`` closure over
24
+ :func:`default_jwt_extractor` with ``allow_env_fallback=config.allow_env_jwt_fallback``).
25
+ Do not invoke a ``None`` extractor.
26
+
27
+ ``hide_unauthorized_tools`` is reserved for MCP-MAP-004 (deferred per design-lock §6);
28
+ stdio ``tools/list`` has no standard JWT carriage in v2.5.0.
29
+
30
+ Example:
31
+ >>> config = MCPAuthConfig(
32
+ ... host_store=host_store,
33
+ ... agent_store=agent_store,
34
+ ... capability_registry=registry,
35
+ ... )
36
+ """
37
+
38
+ host_store: HostStore
39
+ agent_store: AgentStore
40
+ capability_registry: CapabilityRegistry
41
+ tool_capability_map: dict[str, str] = field(default_factory=dict)
42
+ public_tools: frozenset[str] = frozenset()
43
+ enforce_grants: bool = True
44
+ hide_unauthorized_tools: bool = False
45
+ validate_tools_at_startup: bool = False
46
+ jwt_extractor: Callable[[CallToolRequestParams], str | None] | None = None
47
+ allow_env_jwt_fallback: bool = False
48
+ jti_replay_cache: JtiReplayCache | None = None
49
+ expected_audience: str | list[str] | None = None
50
+ manifest_url: str | None = None
51
+
52
+
53
+ def resolve_jwt_extractor(config: MCPAuthConfig) -> Callable[[CallToolRequestParams], str | None]:
54
+ """Return the JWT extractor for middleware (custom or default with config flags).
55
+
56
+ Args:
57
+ config: MCP auth configuration.
58
+
59
+ Returns:
60
+ Callable that extracts an Agent JWT from ``tools/call`` params.
61
+ """
62
+ if config.jwt_extractor is not None:
63
+ return config.jwt_extractor
64
+
65
+ allow_env = config.allow_env_jwt_fallback
66
+
67
+ def extract(params: CallToolRequestParams) -> str | None:
68
+ return default_jwt_extractor(params, allow_env_fallback=allow_env)
69
+
70
+ return extract
@@ -0,0 +1,32 @@
1
+ """MCP-facing ASAP auth error codes and result helpers (v2.5.0)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ from asap.mcp.protocol import CallToolResult, TextContent
8
+
9
+ AUTH_REQUIRED = "asap:auth_required"
10
+ INVALID_TOKEN = "asap:invalid_token"
11
+ CAPABILITY_DENIED = "asap:capability_denied"
12
+ CONSTRAINT_VIOLATION = "asap:constraint_violation"
13
+
14
+
15
+ def tool_error_result(code: str, detail: str | None = None) -> dict[str, Any]:
16
+ """Build a ``tools/call`` error payload with ``isError: true``.
17
+
18
+ Args:
19
+ code: ASAP-namespaced error code (e.g. ``asap:auth_required``).
20
+ detail: Optional human-readable detail appended after the code.
21
+
22
+ Returns:
23
+ Dict suitable for JSON-RPC ``result`` (``CallToolResult`` shape).
24
+
25
+ Example:
26
+ >>> tool_error_result(AUTH_REQUIRED)["isError"]
27
+ True
28
+ """
29
+ text = code if detail is None else f"{code}: {detail}"
30
+ result = CallToolResult(content=[TextContent(text=text).model_dump(by_alias=True)])
31
+ result.is_error = True
32
+ return result.model_dump(by_alias=True, exclude_none=True)
@@ -0,0 +1,52 @@
1
+ """JWT extraction helpers for MCP Auth Bridge (v2.5.0)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+
7
+ from asap.mcp.protocol import CallToolRequestParams
8
+
9
+ _META_JWT_KEY = "asap_agent_jwt"
10
+ _ENV_JWT_KEY = "ASAP_AGENT_JWT"
11
+
12
+
13
+ def default_jwt_extractor(
14
+ params: CallToolRequestParams,
15
+ *,
16
+ allow_env_fallback: bool = False,
17
+ ) -> str | None:
18
+ """Extract Agent JWT from ``tools/call`` params or optional dev-only environment.
19
+
20
+ Reads ``params.meta["asap_agent_jwt"]`` (MCP ``_meta`` field). When
21
+ ``allow_env_fallback`` is ``True``, falls back to ``ASAP_AGENT_JWT`` for
22
+ single-agent local testing only.
23
+
24
+ Args:
25
+ params: Parsed ``tools/call`` request parameters.
26
+ allow_env_fallback: When ``True``, read ``ASAP_AGENT_JWT`` if meta is absent.
27
+ Defaults to ``False`` so production cannot inherit a process-wide token.
28
+
29
+ Returns:
30
+ Stripped JWT string, or ``None`` when no token is present.
31
+
32
+ Example:
33
+ >>> from asap.mcp.protocol import CallToolRequestParams
34
+ >>> params = CallToolRequestParams.model_validate(
35
+ ... {"name": "t", "_meta": {"asap_agent_jwt": " token "}}
36
+ ... )
37
+ >>> default_jwt_extractor(params)
38
+ 'token'
39
+ """
40
+ meta = params.meta or {}
41
+ token = meta.get(_META_JWT_KEY)
42
+ if isinstance(token, str) and token.strip():
43
+ return token.strip()
44
+
45
+ if not allow_env_fallback:
46
+ return None
47
+
48
+ env_token = os.environ.get(_ENV_JWT_KEY)
49
+ if isinstance(env_token, str) and env_token.strip():
50
+ return env_token.strip()
51
+
52
+ return None