asap-protocol 2.4.0__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.
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/CHANGELOG.md +88 -6
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/PKG-INFO +15 -15
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/README.md +10 -10
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/pyproject.toml +27 -17
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/__init__.py +1 -1
- asap_protocol-2.5.0/src/asap/adapters/mcp/__init__.py +17 -0
- asap_protocol-2.5.0/src/asap/adapters/mcp/auth_middleware.py +33 -0
- asap_protocol-2.5.0/src/asap/adapters/mcp/capability_map.py +74 -0
- asap_protocol-2.5.0/src/asap/adapters/mcp/config.py +70 -0
- asap_protocol-2.5.0/src/asap/adapters/mcp/errors.py +32 -0
- asap_protocol-2.5.0/src/asap/adapters/mcp/jwt_extractor.py +52 -0
- asap_protocol-2.5.0/src/asap/adapters/mcp/protected_server.py +176 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/auth/jwks.py +10 -1
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/auth/middleware.py +19 -5
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/discovery/wellknown.py +1 -1
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/economics/delegation_storage.py +13 -2
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/economics/storage.py +2 -3
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/integrations/pydanticai.py +28 -11
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/integrations/smolagents.py +21 -18
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/mcp/client.py +19 -2
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/mcp/protocol.py +1 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/mcp/server.py +15 -3
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/registry/bot_pr.py +30 -35
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/transport/client.py +53 -20
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/.gitignore +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/LICENSE +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/schemas/entities/agent.schema.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/schemas/entities/artifact.schema.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/schemas/entities/conversation.schema.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/schemas/entities/manifest.schema.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/schemas/entities/message.schema.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/schemas/entities/state_snapshot.schema.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/schemas/entities/task.schema.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/schemas/envelope.schema.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/schemas/examples/shellclaw-jetson-capabilities.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/schemas/parts/data_part.schema.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/schemas/parts/file_part.schema.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/schemas/parts/resource_part.schema.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/schemas/parts/template_part.schema.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/schemas/parts/text_part.schema.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/schemas/payloads/artifact_notify.schema.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/schemas/payloads/mcp_resource_data.schema.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/schemas/payloads/mcp_resource_fetch.schema.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/schemas/payloads/mcp_tool_call.schema.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/schemas/payloads/mcp_tool_result.schema.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/schemas/payloads/message_send.schema.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/schemas/payloads/state_query.schema.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/schemas/payloads/state_restore.schema.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/schemas/payloads/task_cancel.schema.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/schemas/payloads/task_request.schema.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/schemas/payloads/task_response.schema.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/schemas/payloads/task_update.schema.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/adapters/__init__.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/adapters/openapi/__init__.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/adapters/openapi/approval.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/adapters/openapi/capability_mapper.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/adapters/openapi/factory.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/adapters/openapi/handler.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/adapters/openapi/spec_loader.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/auth/__init__.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/auth/agent_jwt.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/auth/approval.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/auth/capabilities.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/auth/claims.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/auth/identity.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/auth/introspection.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/auth/lifecycle.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/auth/oauth2.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/auth/oidc.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/auth/scopes.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/auth/self_auth.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/auth/utils.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/auth/webauthn.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/cli/__init__.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/cli/audit_export.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/cli/compliance_check.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/client/__init__.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/client/cache.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/client/http_client.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/client/market.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/client/revocation.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/client/trust.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/crypto/__init__.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/crypto/keys.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/crypto/models.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/crypto/signing.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/crypto/trust.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/crypto/trust_levels.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/discovery/__init__.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/discovery/dnssd.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/discovery/health.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/discovery/registry.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/discovery/validation.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/economics/__init__.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/economics/audit.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/economics/delegation.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/economics/hooks.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/economics/metering.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/economics/sla.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/economics/sla_storage.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/errors.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/examples/README.md +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/examples/__init__.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/examples/a2h_approval.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/examples/agent_failover.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/examples/auth_patterns.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/examples/coordinator.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/examples/echo_agent.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/examples/error_recovery.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/examples/long_running.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/examples/mcp_client_demo.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/examples/mcp_integration.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/examples/multi_step_workflow.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/examples/orchestration.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/examples/rate_limiting.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/examples/run_demo.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/examples/secure_agent.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/examples/secure_handler.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/examples/state_migration.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/examples/storage_backends.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/examples/streaming_agent.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/examples/streaming_response.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/examples/v1_3_0_showcase.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/examples/v1_4_0_showcase.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/examples/websocket_concept.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/handlers/__init__.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/handlers/hitl.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/integrations/__init__.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/integrations/a2h.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/integrations/crewai.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/integrations/langchain.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/integrations/llamaindex.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/integrations/openclaw.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/integrations/vercel_ai.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/mcp/__init__.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/mcp/serve.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/mcp/server_runner.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/models/__init__.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/models/base.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/models/constants.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/models/entities.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/models/enums.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/models/envelope.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/models/ids.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/models/parts.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/models/payloads.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/models/types.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/models/validators.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/observability/__init__.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/observability/dashboards/README.md +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/observability/dashboards/asap-detailed.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/observability/dashboards/asap-red.json +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/observability/logging.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/observability/metrics.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/observability/trace_parser.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/observability/trace_ui.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/observability/tracing.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/registry/__init__.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/registry/anti_spam.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/registry/auto_registration.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/registry/receipt_cache.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/schemas.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/state/__init__.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/state/machine.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/state/metering.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/state/snapshot.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/state/stores/__init__.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/state/stores/memory.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/state/stores/sqlite.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/testing/__init__.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/testing/asgi_factory.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/testing/assertions.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/testing/compliance.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/testing/fixtures.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/testing/mocks.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/transport/__init__.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/transport/_auth_helpers.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/transport/agent_routes.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/transport/cache.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/transport/capability_routes.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/transport/challenge.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/transport/circuit_breaker.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/transport/codecs/__init__.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/transport/codecs/lambda_codec.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/transport/compression.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/transport/delegation_api.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/transport/escalation_routes.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/transport/executors.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/transport/handlers.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/transport/jsonrpc.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/transport/middleware.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/transport/mtls.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/transport/rate_limit.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/transport/server.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/transport/sla_api.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/transport/usage_api.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/transport/validators.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/transport/webhook.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/transport/websocket.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/utils/__init__.py +0 -0
- {asap_protocol-2.4.0 → asap_protocol-2.5.0}/src/asap/utils/sanitization.py +0 -0
|
@@ -7,23 +7,105 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
### Follow-up (not in this release)
|
|
11
|
+
|
|
12
|
+
- `extra="forbid"` on ingress payload models (`TaskRequestConfig`, `CommonMetadata`)
|
|
13
|
+
- Opt-in protection for operator APIs (`/usage`, `/sla`, `/audit`)
|
|
14
|
+
- Redis-backed `JtiReplayCache` and distributed Next.js rate limits
|
|
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).
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## [2.4.1] - 2026-06-14
|
|
89
|
+
|
|
90
|
+
**Security hardening patch** — OAuth2 `iss`/`aud` validation, fail-closed identity
|
|
91
|
+
binding, web app SSRF/redirect fixes, and dependency bumps. Wire protocol and
|
|
92
|
+
manifest schemas are unchanged from v2.4.0.
|
|
93
|
+
|
|
10
94
|
### Security
|
|
11
95
|
|
|
12
96
|
- **OAuth2 middleware**: Validate JWT `iss` and `aud` when `ASAP_AUTH_ISSUER` / `ASAP_AUTH_AUDIENCE` (or `OAuth2Config.expected_issuer` / `expected_audience`) are set; refactored validation through `validate_jwt()` in `asap.auth.jwks`.
|
|
13
97
|
- **Identity binding**: Fail-closed when `manifest_id` is configured but neither custom claim nor `ASAP_AUTH_SUBJECT_MAP` allowlist matches (403 instead of warn-and-pass).
|
|
14
|
-
- **Web app (`apps/web`)**: Block open redirects on E2E fixture login routes via `resolveRedirectUrl`; harden SSRF on `/api/health-check` (127.0.0.0/8, DNS resolve4/6); Zod validation on API query params; rate-limit unit tests.
|
|
98
|
+
- **Web app (`apps/web`)**: Block open redirects on E2E fixture login routes via `resolveRedirectUrl`; harden SSRF on `/api/health-check` (127.0.0.0/8, DNS resolve4/6); Zod strict validation on public API query params (unknown keys return 400); rate-limit unit tests.
|
|
15
99
|
|
|
16
100
|
### Fixed
|
|
17
101
|
|
|
18
102
|
- **CI security (`pip-audit`)**: Bumped transitive pins (`langchain-core`, `langsmith`, `python-multipart`, `urllib3`, `pip`, `smolagents`) and adjusted documented `--ignore-vuln` flags (pygments + **smolagents** CVEs with no PyPI fix yet; pip ≥26.1 clears prior pip ignore). See [SECURITY.md](SECURITY.md).
|
|
19
103
|
- **FastAPI / Starlette**: Raised `fastapi` floor to `>=0.136.1` so `starlette>=1.0.1` resolves **PYSEC-2026-161** (Host header path injection) without a `pip-audit` ignore.
|
|
20
104
|
|
|
21
|
-
###
|
|
105
|
+
### Migration
|
|
22
106
|
|
|
23
|
-
-
|
|
24
|
-
|
|
25
|
-
- Redis-backed `JtiReplayCache` and distributed Next.js rate limits
|
|
26
|
-
- Bump optional `pydantic-ai` extra (CVE-2026-46678)
|
|
107
|
+
- **v2.4.0 → v2.4.1**: Security patch — bump dependencies; verify OAuth2 issuer/audience and identity binding if already configured. See
|
|
108
|
+
[migration guide](docs/migration.md#upgrading-from-v240-to-v241).
|
|
27
109
|
|
|
28
110
|
---
|
|
29
111
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: asap-protocol
|
|
3
|
-
Version: 2.
|
|
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
|
|
@@ -21,9 +21,9 @@ Classifier: Topic :: System :: Distributed Computing
|
|
|
21
21
|
Classifier: Typing :: Typed
|
|
22
22
|
Requires-Python: >=3.13
|
|
23
23
|
Requires-Dist: aiosqlite>=0.20
|
|
24
|
-
Requires-Dist: authlib<2,>=1.6.
|
|
24
|
+
Requires-Dist: authlib<2,>=1.6.12
|
|
25
25
|
Requires-Dist: brotli>=1.2.0
|
|
26
|
-
Requires-Dist: cryptography<
|
|
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
|
|
@@ -58,7 +58,7 @@ Requires-Dist: pytest>=9.0.3; extra == 'dev'
|
|
|
58
58
|
Requires-Dist: ruff>=0.14.14; extra == 'dev'
|
|
59
59
|
Requires-Dist: types-jsonschema>=4.0.0; extra == 'dev'
|
|
60
60
|
Provides-Extra: dns-sd
|
|
61
|
-
Requires-Dist: zeroconf>=0.
|
|
61
|
+
Requires-Dist: zeroconf>=0.149.5; extra == 'dns-sd'
|
|
62
62
|
Provides-Extra: docs
|
|
63
63
|
Requires-Dist: ghp-import>=2.1.0; extra == 'docs'
|
|
64
64
|
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
|
|
@@ -75,7 +75,7 @@ Requires-Dist: openapi-pydantic>=0.5; extra == 'openapi'
|
|
|
75
75
|
Provides-Extra: openclaw
|
|
76
76
|
Requires-Dist: openclaw-sdk>=2.0; extra == 'openclaw'
|
|
77
77
|
Provides-Extra: pydanticai
|
|
78
|
-
Requires-Dist: pydantic-ai>=0
|
|
78
|
+
Requires-Dist: pydantic-ai>=1.99.0; extra == 'pydanticai'
|
|
79
79
|
Provides-Extra: redis
|
|
80
80
|
Requires-Dist: redis>=5.0.0; extra == 'redis'
|
|
81
81
|
Provides-Extra: smolagents
|
|
@@ -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.
|
|
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
|
|
|
@@ -123,7 +123,7 @@ For simple point-to-point communication, a basic HTTP API might suffice; ASAP sh
|
|
|
123
123
|
- **Identity & capabilities (v2.2, WebAuthn real in v2.2.1)** — Per-runtime Host/Agent JWTs, capability grants with constraints (`max`, `min`, `in`, `not_in`), approval flows (device authorization / CIBA-style), real WebAuthn attestation/assertion for high-risk registration (opt-in via `asap-protocol[webauthn]`).
|
|
124
124
|
- **Streaming & wire protocol (v2.2)** — `POST /asap/stream` (SSE / `TaskStream`), JSON-RPC 2.0 batch on `POST /asap`, `ASAP-Version` negotiation, tamper-evident audit logging, Compliance Harness v2.
|
|
125
125
|
- **Adoption Multiplier (v2.3.0)** — OpenAPI → ASAP via `create_from_openapi` (`[openapi]` extra), official **`@asap-protocol/client`** on npm (Vercel AI / OpenAI / Anthropic adapters), optional **Auto-Registration** (`POST /registry/agents`), **capability escalation**, and **ASAP `WWW-Authenticate`** discovery challenges. All opt-in; wire protocol unchanged. See [docs/index.md](docs/index.md) and [docs/migration.md](docs/migration.md).
|
|
126
|
-
- **Edge-AI discovery (v2.4.0)** — Optional `manifest.capabilities.hardware` + `inference`, Lite Registry mirror, marketplace browse filters, and `@asap-protocol/client@2.4.
|
|
126
|
+
- **Edge-AI discovery (v2.4.0)** — Optional `manifest.capabilities.hardware` + `inference`, Lite Registry mirror, marketplace browse filters, and `@asap-protocol/client@2.4.1` discovery types. Wire protocol unchanged. See [Migration (v2.3.x → v2.4.0)](docs/migration.md#upgrading-from-v23x-to-v240) and [ShellClaw registry guide](docs/guides/shellclaw-registry.md).
|
|
127
127
|
- **Framework adapters (v2.3.1+, npm)** — **`@asap-protocol/mastra`** and **`@asap-protocol/openai-agents`** expose ASAP capabilities as Mastra tools and OpenAI Agents SDK `tool()` definitions. See [Migration (v2.3.0 → v2.3.1)](docs/migration.md#upgrading-from-v230-to-v231).
|
|
128
128
|
- **Economics** — Usage metering, delegation tokens, SLA framework with breach alerts.
|
|
129
129
|
|
|
@@ -144,16 +144,16 @@ Or with pip:
|
|
|
144
144
|
pip install asap-protocol
|
|
145
145
|
```
|
|
146
146
|
|
|
147
|
-
**npm** (TypeScript / JavaScript — [`@asap-protocol/client`](https://www.npmjs.com/package/@asap-protocol/client), **`2.4.
|
|
147
|
+
**npm** (TypeScript / JavaScript — [`@asap-protocol/client`](https://www.npmjs.com/package/@asap-protocol/client), **`2.4.1`**). The `latest` dist-tag matches **`npm view @asap-protocol/client version`**.
|
|
148
148
|
|
|
149
|
-
**npm** Mastra [**`@asap-protocol/mastra@2.4.
|
|
149
|
+
**npm** Mastra [**`@asap-protocol/mastra@2.4.1`**](https://www.npmjs.com/package/@asap-protocol/mastra) bridges ASAP capabilities onto **`@mastra/core`** tools; docs: [`docs/integrations/mastra.md`](docs/integrations/mastra.md), demo: [`apps/example-mastra/README.md`](apps/example-mastra/README.md).
|
|
150
150
|
|
|
151
|
-
**npm** OpenAI Agents SDK [**`@asap-protocol/openai-agents@2.4.
|
|
151
|
+
**npm** OpenAI Agents SDK [**`@asap-protocol/openai-agents@2.4.1`**](https://www.npmjs.com/package/@asap-protocol/openai-agents) exposes ASAP capabilities as **`@openai/agents`** `tool()` definitions — **not** the Chat Completions helper [`adapters/openai`](packages/typescript/client/src/adapters/openai.ts); docs: [`docs/integrations/openai-agents.md`](docs/integrations/openai-agents.md), demo: [`apps/example-openai-agents/README.md`](apps/example-openai-agents/README.md).
|
|
152
152
|
|
|
153
153
|
```bash
|
|
154
|
-
npm install @asap-protocol/client@2.4.
|
|
155
|
-
npm install @asap-protocol/mastra@2.4.
|
|
156
|
-
npm install @asap-protocol/openai-agents@2.4.
|
|
154
|
+
npm install @asap-protocol/client@2.4.1
|
|
155
|
+
npm install @asap-protocol/mastra@2.4.1 @asap-protocol/client @mastra/core zod
|
|
156
|
+
npm install @asap-protocol/openai-agents@2.4.1 @asap-protocol/client @openai/agents zod
|
|
157
157
|
```
|
|
158
158
|
|
|
159
159
|
📦 **Canonical listing:** **[https://pypi.org/project/asap-protocol/](https://pypi.org/project/asap-protocol/)** — package **`asap-protocol`** (`pip install asap-protocol`). Prefer `uv` for reproducible environments when possible.
|
|
@@ -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=
|
|
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.
|
|
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
|
|
|
@@ -35,7 +35,7 @@ For simple point-to-point communication, a basic HTTP API might suffice; ASAP sh
|
|
|
35
35
|
- **Identity & capabilities (v2.2, WebAuthn real in v2.2.1)** — Per-runtime Host/Agent JWTs, capability grants with constraints (`max`, `min`, `in`, `not_in`), approval flows (device authorization / CIBA-style), real WebAuthn attestation/assertion for high-risk registration (opt-in via `asap-protocol[webauthn]`).
|
|
36
36
|
- **Streaming & wire protocol (v2.2)** — `POST /asap/stream` (SSE / `TaskStream`), JSON-RPC 2.0 batch on `POST /asap`, `ASAP-Version` negotiation, tamper-evident audit logging, Compliance Harness v2.
|
|
37
37
|
- **Adoption Multiplier (v2.3.0)** — OpenAPI → ASAP via `create_from_openapi` (`[openapi]` extra), official **`@asap-protocol/client`** on npm (Vercel AI / OpenAI / Anthropic adapters), optional **Auto-Registration** (`POST /registry/agents`), **capability escalation**, and **ASAP `WWW-Authenticate`** discovery challenges. All opt-in; wire protocol unchanged. See [docs/index.md](docs/index.md) and [docs/migration.md](docs/migration.md).
|
|
38
|
-
- **Edge-AI discovery (v2.4.0)** — Optional `manifest.capabilities.hardware` + `inference`, Lite Registry mirror, marketplace browse filters, and `@asap-protocol/client@2.4.
|
|
38
|
+
- **Edge-AI discovery (v2.4.0)** — Optional `manifest.capabilities.hardware` + `inference`, Lite Registry mirror, marketplace browse filters, and `@asap-protocol/client@2.4.1` discovery types. Wire protocol unchanged. See [Migration (v2.3.x → v2.4.0)](docs/migration.md#upgrading-from-v23x-to-v240) and [ShellClaw registry guide](docs/guides/shellclaw-registry.md).
|
|
39
39
|
- **Framework adapters (v2.3.1+, npm)** — **`@asap-protocol/mastra`** and **`@asap-protocol/openai-agents`** expose ASAP capabilities as Mastra tools and OpenAI Agents SDK `tool()` definitions. See [Migration (v2.3.0 → v2.3.1)](docs/migration.md#upgrading-from-v230-to-v231).
|
|
40
40
|
- **Economics** — Usage metering, delegation tokens, SLA framework with breach alerts.
|
|
41
41
|
|
|
@@ -56,16 +56,16 @@ Or with pip:
|
|
|
56
56
|
pip install asap-protocol
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
**npm** (TypeScript / JavaScript — [`@asap-protocol/client`](https://www.npmjs.com/package/@asap-protocol/client), **`2.4.
|
|
59
|
+
**npm** (TypeScript / JavaScript — [`@asap-protocol/client`](https://www.npmjs.com/package/@asap-protocol/client), **`2.4.1`**). The `latest` dist-tag matches **`npm view @asap-protocol/client version`**.
|
|
60
60
|
|
|
61
|
-
**npm** Mastra [**`@asap-protocol/mastra@2.4.
|
|
61
|
+
**npm** Mastra [**`@asap-protocol/mastra@2.4.1`**](https://www.npmjs.com/package/@asap-protocol/mastra) bridges ASAP capabilities onto **`@mastra/core`** tools; docs: [`docs/integrations/mastra.md`](docs/integrations/mastra.md), demo: [`apps/example-mastra/README.md`](apps/example-mastra/README.md).
|
|
62
62
|
|
|
63
|
-
**npm** OpenAI Agents SDK [**`@asap-protocol/openai-agents@2.4.
|
|
63
|
+
**npm** OpenAI Agents SDK [**`@asap-protocol/openai-agents@2.4.1`**](https://www.npmjs.com/package/@asap-protocol/openai-agents) exposes ASAP capabilities as **`@openai/agents`** `tool()` definitions — **not** the Chat Completions helper [`adapters/openai`](packages/typescript/client/src/adapters/openai.ts); docs: [`docs/integrations/openai-agents.md`](docs/integrations/openai-agents.md), demo: [`apps/example-openai-agents/README.md`](apps/example-openai-agents/README.md).
|
|
64
64
|
|
|
65
65
|
```bash
|
|
66
|
-
npm install @asap-protocol/client@2.4.
|
|
67
|
-
npm install @asap-protocol/mastra@2.4.
|
|
68
|
-
npm install @asap-protocol/openai-agents@2.4.
|
|
66
|
+
npm install @asap-protocol/client@2.4.1
|
|
67
|
+
npm install @asap-protocol/mastra@2.4.1 @asap-protocol/client @mastra/core zod
|
|
68
|
+
npm install @asap-protocol/openai-agents@2.4.1 @asap-protocol/client @openai/agents zod
|
|
69
69
|
```
|
|
70
70
|
|
|
71
71
|
📦 **Canonical listing:** **[https://pypi.org/project/asap-protocol/](https://pypi.org/project/asap-protocol/)** — package **`asap-protocol`** (`pip install asap-protocol`). Prefer `uv` for reproducible environments when possible.
|
|
@@ -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=
|
|
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.
|
|
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,13 +23,13 @@ classifiers = [
|
|
|
23
23
|
dependencies = [
|
|
24
24
|
"aiosqlite>=0.20",
|
|
25
25
|
# Upper-bound majors per SECURITY.md dependency policy.
|
|
26
|
-
"cryptography>=
|
|
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",
|
|
30
30
|
"fastapi>=0.136.1",
|
|
31
31
|
"httpx[http2]>=0.28.1",
|
|
32
|
-
"authlib>=1.6.
|
|
32
|
+
"authlib>=1.6.12,<2",
|
|
33
33
|
"joserfc>=1.6.3,<2",
|
|
34
34
|
"uvicorn>=0.34",
|
|
35
35
|
"python-ulid>=3.0",
|
|
@@ -68,7 +68,7 @@ docs = [
|
|
|
68
68
|
"pymdown-extensions>=10.21.3",
|
|
69
69
|
]
|
|
70
70
|
dns-sd = [
|
|
71
|
-
"zeroconf>=0.
|
|
71
|
+
"zeroconf>=0.149.5",
|
|
72
72
|
]
|
|
73
73
|
# Redis: shared rate limit storage for multi-worker deployments (see rate_limit.py).
|
|
74
74
|
redis = [
|
|
@@ -95,7 +95,7 @@ smolagents = [
|
|
|
95
95
|
"smolagents>=1.24.0",
|
|
96
96
|
]
|
|
97
97
|
pydanticai = [
|
|
98
|
-
"pydantic-ai>=0
|
|
98
|
+
"pydantic-ai>=1.99.0",
|
|
99
99
|
]
|
|
100
100
|
openclaw = [
|
|
101
101
|
"openclaw-sdk>=2.0",
|
|
@@ -116,42 +116,52 @@ Issues = "https://github.com/adriannoes/asap-protocol/issues"
|
|
|
116
116
|
"PyPI" = "https://pypi.org/project/asap-protocol/"
|
|
117
117
|
|
|
118
118
|
# Override transitive dependencies for security fixes:
|
|
119
|
-
# - pyjwt>=2.
|
|
119
|
+
# - pyjwt>=2.13.0 for PYSEC-2026-175/177/178/179 (CVE-2026-32597 baseline at 2.12.0)
|
|
120
|
+
# - aiohttp>=3.14.0,<4 for CVE-2026-34993 / CVE-2026-47265 (transitive, e.g. openclaw/mcp stacks)
|
|
121
|
+
# - zeroconf>=0.149.5 for CVE-2026-47180/47183/47184 ([dns-sd] extra)
|
|
120
122
|
# - pyasn1>=0.6.3 for CVE-2026-30922 (DoS via unbounded recursion)
|
|
121
123
|
# - tinytag>=2.2.1 for CVE-2026-32889
|
|
122
|
-
# - cryptography>=
|
|
124
|
+
# - cryptography>=48.0.1 for GHSA-537c-gmf6-5ccf (CVE-2026-39892 / CVE-2026-34073 baseline at 46.0.7)
|
|
123
125
|
# - requests>=2.33.0 for CVE-2026-25645 (extract_zipped_paths temp file)
|
|
124
126
|
# - pillow>=12.2.0 for CVE-2026-40192 (transitive, e.g. pdf/vision stacks)
|
|
125
127
|
# - pytest>=9.0.3 for CVE-2025-71176 (dev)
|
|
126
|
-
# - python-multipart>=0.0.
|
|
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)
|
|
127
130
|
# - pygments>=2.20.0 for CVE-2026-4539
|
|
128
|
-
# - langsmith>=0.8.
|
|
131
|
+
# - langsmith>=0.8.18 for GHSA-f4xh-w4cj-qxq8 (prior: CVE-2026-45134 at >=0.8.0)
|
|
129
132
|
# - langchain-core>=1.3.3 for CVE-2026-44843
|
|
130
133
|
# - urllib3>=2.7.0 for CVE-2026-44431 / CVE-2026-44432
|
|
131
|
-
# - pip>=26.1 for CVE-2026-6357
|
|
134
|
+
# - pip>=26.1.2 for PYSEC-2026-196 (CVE-2026-6357 baseline at 26.1)
|
|
132
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)
|
|
133
138
|
# - idna>=3.15 for CVE-2026-45409 (DoS in idna.encode; transitive via httpx/requests)
|
|
134
139
|
# - markdown>=3.10.2 for PYSEC-2026-89 (DoS in html.parser during Markdown parse; mkdocs stack)
|
|
135
140
|
# - pymdown-extensions>=10.21.3 for CVE-2026-46338 (snippets base_path prefix bypass; mkdocs stack)
|
|
136
141
|
[tool.uv]
|
|
137
142
|
override-dependencies = [
|
|
138
|
-
"
|
|
143
|
+
"aiohttp>=3.14.0,<4",
|
|
144
|
+
"pyjwt>=2.13.0,<3",
|
|
139
145
|
"pyasn1>=0.6.3",
|
|
140
146
|
"tinytag>=2.2.1",
|
|
141
|
-
"cryptography>=
|
|
147
|
+
"cryptography>=48.0.1,<49",
|
|
142
148
|
"requests>=2.33.0",
|
|
143
149
|
"pillow>=12.2.0",
|
|
144
150
|
"pytest>=9.0.3",
|
|
145
|
-
"python-multipart>=0.0.
|
|
151
|
+
"python-multipart>=0.0.31",
|
|
152
|
+
"starlette>=1.3.1",
|
|
146
153
|
"pygments>=2.20.0",
|
|
147
|
-
"langsmith>=0.8.
|
|
154
|
+
"langsmith>=0.8.18",
|
|
148
155
|
"langchain-core>=1.3.3",
|
|
149
156
|
"urllib3>=2.7.0",
|
|
150
|
-
"pip>=26.1",
|
|
157
|
+
"pip>=26.1.2",
|
|
158
|
+
"zeroconf>=0.149.5",
|
|
151
159
|
"python-dotenv>=1.2.2",
|
|
152
160
|
"idna>=3.15",
|
|
153
161
|
"markdown>=3.10.2",
|
|
154
162
|
"pymdown-extensions>=10.21.3",
|
|
163
|
+
"pydantic-settings>=2.14.2",
|
|
164
|
+
"msgpack>=1.2.1",
|
|
155
165
|
]
|
|
156
166
|
|
|
157
167
|
[project.scripts]
|
|
@@ -302,7 +312,7 @@ addopts = [
|
|
|
302
312
|
"--strict-markers",
|
|
303
313
|
"--strict-config",
|
|
304
314
|
]
|
|
305
|
-
# Coverage options: use explicitly when needed (e.g., pytest --cov=
|
|
315
|
+
# Coverage options: use explicitly when needed (e.g., pytest --tb=short --cov=asap --cov-report=xml --cov-fail-under=85)
|
|
306
316
|
# NOT included in addopts to avoid conflicts with pytest-xdist (-n auto)
|
|
307
317
|
testpaths = ["tests"]
|
|
308
318
|
# Note: benchmarks/ excluded from testpaths - Locust monkey-patches gevent/ssl which
|
|
@@ -340,5 +350,5 @@ dev = [
|
|
|
340
350
|
"memory-profiler>=0.61",
|
|
341
351
|
"pytest-asyncio>=0.24",
|
|
342
352
|
"pytest-cov>=6.0",
|
|
343
|
-
"pip>=26.
|
|
353
|
+
"pip>=26.1.2",
|
|
344
354
|
]
|
|
@@ -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)
|