djangorestframework-mcp-server 0.1.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 (213) hide show
  1. djangorestframework_mcp_server-0.1.0/.github/workflows/release.yml +110 -0
  2. djangorestframework_mcp_server-0.1.0/.github/workflows/tests.yml +169 -0
  3. djangorestframework_mcp_server-0.1.0/.gitignore +628 -0
  4. djangorestframework_mcp_server-0.1.0/.pre-commit-config.yaml +31 -0
  5. djangorestframework_mcp_server-0.1.0/CHANGELOG.md +130 -0
  6. djangorestframework_mcp_server-0.1.0/CLAUDE.md +171 -0
  7. djangorestframework_mcp_server-0.1.0/LICENSE +21 -0
  8. djangorestframework_mcp_server-0.1.0/Makefile +79 -0
  9. djangorestframework_mcp_server-0.1.0/PKG-INFO +151 -0
  10. djangorestframework_mcp_server-0.1.0/README.md +104 -0
  11. djangorestframework_mcp_server-0.1.0/docs/async.md +145 -0
  12. djangorestframework_mcp_server-0.1.0/docs/auth.md +295 -0
  13. djangorestframework_mcp_server-0.1.0/docs/concepts.md +229 -0
  14. djangorestframework_mcp_server-0.1.0/docs/index.md +73 -0
  15. djangorestframework_mcp_server-0.1.0/docs/observability.md +99 -0
  16. djangorestframework_mcp_server-0.1.0/docs/prompts.md +118 -0
  17. djangorestframework_mcp_server-0.1.0/docs/quickstart.md +156 -0
  18. djangorestframework_mcp_server-0.1.0/docs/recipes/async-auth-backend.md +101 -0
  19. djangorestframework_mcp_server-0.1.0/docs/recipes/custom-permission.md +53 -0
  20. djangorestframework_mcp_server-0.1.0/docs/recipes/expose-a-service.md +42 -0
  21. djangorestframework_mcp_server-0.1.0/docs/recipes/index.md +18 -0
  22. djangorestframework_mcp_server-0.1.0/docs/recipes/rate-limiting.md +150 -0
  23. djangorestframework_mcp_server-0.1.0/docs/recipes/redis-sse-broker.md +73 -0
  24. djangorestframework_mcp_server-0.1.0/docs/recipes/sse-replay-buffer.md +128 -0
  25. djangorestframework_mcp_server-0.1.0/docs/recipes/swap-session-store.md +60 -0
  26. djangorestframework_mcp_server-0.1.0/docs/recipes/toon-output.md +42 -0
  27. djangorestframework_mcp_server-0.1.0/docs/reference/auth.md +32 -0
  28. djangorestframework_mcp_server-0.1.0/docs/reference/index.md +10 -0
  29. djangorestframework_mcp_server-0.1.0/docs/reference/mcp-server.md +7 -0
  30. djangorestframework_mcp_server-0.1.0/docs/reference/output.md +8 -0
  31. djangorestframework_mcp_server-0.1.0/docs/reference/protocol.md +39 -0
  32. djangorestframework_mcp_server-0.1.0/docs/reference/registries.md +28 -0
  33. djangorestframework_mcp_server-0.1.0/mkdocs.yml +98 -0
  34. djangorestframework_mcp_server-0.1.0/pyproject.toml +156 -0
  35. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/__init__.py +80 -0
  36. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/_compat/__init__.py +3 -0
  37. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/_compat/acall.py +28 -0
  38. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/_compat/tracing.py +63 -0
  39. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/_compat/utils.py +39 -0
  40. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/adapters/__init__.py +4 -0
  41. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/adapters/selector_to_resource.py +71 -0
  42. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/adapters/service_to_tool.py +40 -0
  43. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/auth/__init__.py +19 -0
  44. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/auth/audience.py +28 -0
  45. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/auth/auth_backend.py +33 -0
  46. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/auth/backends/__init__.py +4 -0
  47. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/auth/backends/allow_any_backend.py +41 -0
  48. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/auth/backends/django_oauth_toolkit_backend.py +101 -0
  49. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/auth/insufficient_scope_response.py +20 -0
  50. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/auth/permissions/__init__.py +5 -0
  51. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/auth/permissions/django_perm_required.py +29 -0
  52. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/auth/permissions/mcp_permission.py +35 -0
  53. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/auth/permissions/scope_required.py +25 -0
  54. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/auth/protected_resource_metadata.py +35 -0
  55. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/auth/rate_limits/__init__.py +11 -0
  56. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/auth/rate_limits/fixed_window_rate_limit.py +83 -0
  57. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/auth/rate_limits/mcp_rate_limit.py +33 -0
  58. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/auth/rate_limits/sliding_window_rate_limit.py +91 -0
  59. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/auth/rate_limits/token_bucket_rate_limit.py +98 -0
  60. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/auth/token_info.py +36 -0
  61. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/auth/unauthenticated_response.py +20 -0
  62. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/conf.py +58 -0
  63. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/handlers/__init__.py +23 -0
  64. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/handlers/async_dispatch.py +35 -0
  65. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/handlers/context.py +31 -0
  66. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/handlers/dispatch.py +61 -0
  67. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/handlers/handle_initialize.py +56 -0
  68. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/handlers/handle_ping.py +18 -0
  69. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/handlers/handle_prompts_get.py +106 -0
  70. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/handlers/handle_prompts_get_async.py +103 -0
  71. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/handlers/handle_prompts_list.py +45 -0
  72. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/handlers/handle_resources_list.py +45 -0
  73. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/handlers/handle_resources_read.py +106 -0
  74. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/handlers/handle_resources_read_async.py +106 -0
  75. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/handlers/handle_resources_templates_list.py +42 -0
  76. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/handlers/handle_tools_call.py +203 -0
  77. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/handlers/handle_tools_call_async.py +151 -0
  78. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/handlers/handle_tools_list.py +52 -0
  79. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/handlers/pagination.py +63 -0
  80. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/handlers/render_prompt_messages.py +42 -0
  81. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/handlers/utils.py +113 -0
  82. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/output/__init__.py +6 -0
  83. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/output/encode_json.py +17 -0
  84. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/output/encode_toon.py +30 -0
  85. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/output/format.py +34 -0
  86. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/output/tool_result.py +58 -0
  87. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/protocol/__init__.py +47 -0
  88. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/protocol/client_capabilities.py +33 -0
  89. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/protocol/get_prompt_result.py +27 -0
  90. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/protocol/implementation.py +18 -0
  91. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/protocol/initialize_params.py +37 -0
  92. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/protocol/initialize_result.py +30 -0
  93. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/protocol/json_rpc_error.py +26 -0
  94. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/protocol/json_rpc_error_code.py +29 -0
  95. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/protocol/json_rpc_message.py +9 -0
  96. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/protocol/json_rpc_notification.py +24 -0
  97. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/protocol/json_rpc_request.py +25 -0
  98. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/protocol/json_rpc_response.py +28 -0
  99. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/protocol/jsonrpc_constants.py +7 -0
  100. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/protocol/parse_message.py +50 -0
  101. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/protocol/prompt.py +37 -0
  102. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/protocol/prompt_argument.py +29 -0
  103. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/protocol/prompt_message.py +29 -0
  104. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/protocol/resource.py +38 -0
  105. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/protocol/resource_contents.py +31 -0
  106. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/protocol/resource_template.py +35 -0
  107. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/protocol/server_capabilities.py +38 -0
  108. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/protocol/tool.py +36 -0
  109. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/protocol/tool_content_block.py +34 -0
  110. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/protocol/tool_result.py +35 -0
  111. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/registry/__init__.py +6 -0
  112. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/registry/prompt_binding.py +37 -0
  113. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/registry/prompt_registry.py +34 -0
  114. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/registry/resource_binding.py +55 -0
  115. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/registry/resource_registry.py +66 -0
  116. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/registry/tool_binding.py +47 -0
  117. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/registry/tool_registry.py +35 -0
  118. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/schema/__init__.py +4 -0
  119. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/schema/input_schema.py +32 -0
  120. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/schema/output_schema.py +28 -0
  121. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/schema/utils.py +122 -0
  122. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/server/__init__.py +3 -0
  123. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/server/mcp_server.py +451 -0
  124. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/server/mcp_service_view.py +33 -0
  125. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/transport/__init__.py +21 -0
  126. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/transport/async_streamable_http_view.py +276 -0
  127. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/transport/django_cache_session_store.py +35 -0
  128. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/transport/in_memory_session_store.py +29 -0
  129. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/transport/in_memory_sse_broker.py +63 -0
  130. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/transport/in_memory_sse_replay_buffer.py +68 -0
  131. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/transport/origin_validation.py +27 -0
  132. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/transport/protocol_version.py +24 -0
  133. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/transport/redis_sse_broker.py +158 -0
  134. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/transport/redis_sse_replay_buffer.py +117 -0
  135. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/transport/session_store.py +27 -0
  136. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/transport/sse_broker.py +40 -0
  137. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/transport/sse_replay_buffer.py +68 -0
  138. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/transport/sse_response.py +117 -0
  139. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/transport/streamable_http_view.py +226 -0
  140. djangorestframework_mcp_server-0.1.0/rest_framework_mcp/version.py +5 -0
  141. djangorestframework_mcp_server-0.1.0/tests/__init__.py +0 -0
  142. djangorestframework_mcp_server-0.1.0/tests/adapters/__init__.py +0 -0
  143. djangorestframework_mcp_server-0.1.0/tests/auth/__init__.py +0 -0
  144. djangorestframework_mcp_server-0.1.0/tests/auth/backends/__init__.py +0 -0
  145. djangorestframework_mcp_server-0.1.0/tests/auth/backends/test_allow_any_backend.py +39 -0
  146. djangorestframework_mcp_server-0.1.0/tests/auth/backends/test_django_oauth_toolkit_backend.py +218 -0
  147. djangorestframework_mcp_server-0.1.0/tests/auth/permissions/__init__.py +0 -0
  148. djangorestframework_mcp_server-0.1.0/tests/auth/permissions/test_django_perm_required.py +55 -0
  149. djangorestframework_mcp_server-0.1.0/tests/auth/permissions/test_scope_required.py +28 -0
  150. djangorestframework_mcp_server-0.1.0/tests/auth/rate_limits/__init__.py +0 -0
  151. djangorestframework_mcp_server-0.1.0/tests/auth/rate_limits/test_fixed_window_rate_limit.py +91 -0
  152. djangorestframework_mcp_server-0.1.0/tests/auth/rate_limits/test_sliding_window_rate_limit.py +112 -0
  153. djangorestframework_mcp_server-0.1.0/tests/auth/rate_limits/test_token_bucket_rate_limit.py +135 -0
  154. djangorestframework_mcp_server-0.1.0/tests/auth/test_audience.py +28 -0
  155. djangorestframework_mcp_server-0.1.0/tests/auth/test_response_builders.py +24 -0
  156. djangorestframework_mcp_server-0.1.0/tests/auth/test_token_info.py +23 -0
  157. djangorestframework_mcp_server-0.1.0/tests/conftest.py +81 -0
  158. djangorestframework_mcp_server-0.1.0/tests/conftest_settings.py +40 -0
  159. djangorestframework_mcp_server-0.1.0/tests/handlers/__init__.py +0 -0
  160. djangorestframework_mcp_server-0.1.0/tests/handlers/test_async_handler_branches.py +258 -0
  161. djangorestframework_mcp_server-0.1.0/tests/handlers/test_handler_branches.py +222 -0
  162. djangorestframework_mcp_server-0.1.0/tests/handlers/test_handler_error_paths.py +135 -0
  163. djangorestframework_mcp_server-0.1.0/tests/handlers/test_kwargs_providers.py +288 -0
  164. djangorestframework_mcp_server-0.1.0/tests/handlers/test_pagination.py +68 -0
  165. djangorestframework_mcp_server-0.1.0/tests/handlers/test_pagination_handlers.py +125 -0
  166. djangorestframework_mcp_server-0.1.0/tests/handlers/test_prompts.py +330 -0
  167. djangorestframework_mcp_server-0.1.0/tests/handlers/test_rate_limits.py +168 -0
  168. djangorestframework_mcp_server-0.1.0/tests/output/__init__.py +0 -0
  169. djangorestframework_mcp_server-0.1.0/tests/output/test_encode_json.py +33 -0
  170. djangorestframework_mcp_server-0.1.0/tests/output/test_encode_toon.py +28 -0
  171. djangorestframework_mcp_server-0.1.0/tests/output/test_format.py +22 -0
  172. djangorestframework_mcp_server-0.1.0/tests/output/test_tool_result.py +63 -0
  173. djangorestframework_mcp_server-0.1.0/tests/protocol/__init__.py +0 -0
  174. djangorestframework_mcp_server-0.1.0/tests/protocol/test_dataclasses.py +334 -0
  175. djangorestframework_mcp_server-0.1.0/tests/registry/__init__.py +0 -0
  176. djangorestframework_mcp_server-0.1.0/tests/registry/test_prompt_registry.py +28 -0
  177. djangorestframework_mcp_server-0.1.0/tests/registry/test_resource_registry.py +63 -0
  178. djangorestframework_mcp_server-0.1.0/tests/registry/test_tool_binding.py +12 -0
  179. djangorestframework_mcp_server-0.1.0/tests/registry/test_tool_registry.py +29 -0
  180. djangorestframework_mcp_server-0.1.0/tests/schema/__init__.py +0 -0
  181. djangorestframework_mcp_server-0.1.0/tests/schema/test_input_output_schema.py +62 -0
  182. djangorestframework_mcp_server-0.1.0/tests/schema/test_utils.py +200 -0
  183. djangorestframework_mcp_server-0.1.0/tests/server/__init__.py +0 -0
  184. djangorestframework_mcp_server-0.1.0/tests/server/test_mcp_server.py +126 -0
  185. djangorestframework_mcp_server-0.1.0/tests/server/test_mcp_server_notify.py +82 -0
  186. djangorestframework_mcp_server-0.1.0/tests/test_conf.py +27 -0
  187. djangorestframework_mcp_server-0.1.0/tests/test_endtoend.py +174 -0
  188. djangorestframework_mcp_server-0.1.0/tests/test_prompts_endtoend.py +86 -0
  189. djangorestframework_mcp_server-0.1.0/tests/test_re_exports.py +72 -0
  190. djangorestframework_mcp_server-0.1.0/tests/test_tracing.py +231 -0
  191. djangorestframework_mcp_server-0.1.0/tests/test_validation_value_echo.py +205 -0
  192. djangorestframework_mcp_server-0.1.0/tests/testapp/__init__.py +0 -0
  193. djangorestframework_mcp_server-0.1.0/tests/testapp/apps.py +9 -0
  194. djangorestframework_mcp_server-0.1.0/tests/testapp/async_urls.py +11 -0
  195. djangorestframework_mcp_server-0.1.0/tests/testapp/mcp.py +40 -0
  196. djangorestframework_mcp_server-0.1.0/tests/testapp/models.py +15 -0
  197. djangorestframework_mcp_server-0.1.0/tests/testapp/serializers.py +16 -0
  198. djangorestframework_mcp_server-0.1.0/tests/testapp/services.py +25 -0
  199. djangorestframework_mcp_server-0.1.0/tests/testapp/urls.py +11 -0
  200. djangorestframework_mcp_server-0.1.0/tests/transport/__init__.py +0 -0
  201. djangorestframework_mcp_server-0.1.0/tests/transport/test_async_streamable_http_view.py +447 -0
  202. djangorestframework_mcp_server-0.1.0/tests/transport/test_in_memory_sse_replay_buffer.py +103 -0
  203. djangorestframework_mcp_server-0.1.0/tests/transport/test_origin_validation.py +24 -0
  204. djangorestframework_mcp_server-0.1.0/tests/transport/test_protocol_version.py +21 -0
  205. djangorestframework_mcp_server-0.1.0/tests/transport/test_redis_sse_broker.py +135 -0
  206. djangorestframework_mcp_server-0.1.0/tests/transport/test_redis_sse_replay_buffer.py +116 -0
  207. djangorestframework_mcp_server-0.1.0/tests/transport/test_session_stores.py +31 -0
  208. djangorestframework_mcp_server-0.1.0/tests/transport/test_sse_broker.py +61 -0
  209. djangorestframework_mcp_server-0.1.0/tests/transport/test_sse_endpoint.py +194 -0
  210. djangorestframework_mcp_server-0.1.0/tests/transport/test_sse_response.py +181 -0
  211. djangorestframework_mcp_server-0.1.0/tests/transport/test_streamable_http_view.py +142 -0
  212. djangorestframework_mcp_server-0.1.0/tests/transport/test_streamable_http_view_branches.py +83 -0
  213. djangorestframework_mcp_server-0.1.0/uv.lock +1663 -0
@@ -0,0 +1,110 @@
1
+ name: release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ # Each job runs only after the previous one succeeds, so a failed test or a
9
+ # rejected PyPI upload aborts the rest of the chain (no half-released versions).
10
+ concurrency:
11
+ group: release-${{ github.ref }}
12
+ cancel-in-progress: false
13
+
14
+ jobs:
15
+ build:
16
+ name: build wheel + sdist
17
+ runs-on: ubuntu-latest
18
+ permissions:
19
+ contents: read
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+ with:
23
+ fetch-depth: 0
24
+ - uses: astral-sh/setup-uv@v6
25
+ with:
26
+ enable-cache: true
27
+ - name: Install
28
+ run: uv sync --all-groups
29
+
30
+ - name: Tag version matches package version
31
+ # Compare the git tag (vX.Y.Z) against rest_framework_mcp.__version__.
32
+ # Any mismatch is a sign someone tagged without bumping version.py.
33
+ run: |
34
+ tag="${GITHUB_REF#refs/tags/}"
35
+ pkg_version="$(uv run python -c 'from rest_framework_mcp.version import __version__; print(__version__)')"
36
+ if [[ "$tag" != "v$pkg_version" ]]; then
37
+ echo "Tag $tag does not match package version v$pkg_version"
38
+ exit 1
39
+ fi
40
+
41
+ - name: Final test gate
42
+ run: uv run pytest
43
+
44
+ - name: Build distributions
45
+ run: uv build
46
+
47
+ - name: Upload dist
48
+ uses: actions/upload-artifact@v4
49
+ with:
50
+ name: dist
51
+ path: dist/
52
+
53
+ publish-pypi:
54
+ name: publish to PyPI
55
+ needs: build
56
+ runs-on: ubuntu-latest
57
+ environment:
58
+ name: pypi
59
+ url: https://pypi.org/p/djangorestframework-mcp-server
60
+ permissions:
61
+ # Required for OIDC trusted publishing — no API token in repo secrets.
62
+ id-token: write
63
+ steps:
64
+ - name: Download dist
65
+ uses: actions/download-artifact@v4
66
+ with:
67
+ name: dist
68
+ path: dist/
69
+ - name: Publish
70
+ uses: pypa/gh-action-pypi-publish@release/v1
71
+
72
+ publish-docs:
73
+ name: publish docs to GitHub Pages
74
+ needs: publish-pypi
75
+ runs-on: ubuntu-latest
76
+ # Docs deployment is best-effort: if mkdocs.yml is missing the step is
77
+ # skipped instead of failing the release.
78
+ permissions:
79
+ contents: write
80
+ pages: write
81
+ id-token: write
82
+ steps:
83
+ - uses: actions/checkout@v4
84
+ with:
85
+ fetch-depth: 0
86
+ - uses: astral-sh/setup-uv@v6
87
+ with:
88
+ enable-cache: true
89
+ - name: Check for mkdocs.yml
90
+ id: docs
91
+ run: |
92
+ if [[ -f mkdocs.yml ]]; then
93
+ echo "present=true" >> "$GITHUB_OUTPUT"
94
+ else
95
+ echo "present=false" >> "$GITHUB_OUTPUT"
96
+ echo "mkdocs.yml not found — skipping docs deploy."
97
+ fi
98
+ - name: Install with docs group
99
+ if: steps.docs.outputs.present == 'true'
100
+ run: uv sync --all-groups
101
+ - name: Configure git for gh-deploy
102
+ if: steps.docs.outputs.present == 'true'
103
+ run: |
104
+ git config user.name 'github-actions[bot]'
105
+ git config user.email '41898282+github-actions[bot]@users.noreply.github.com'
106
+ - name: Deploy to gh-pages
107
+ if: steps.docs.outputs.present == 'true'
108
+ run: |
109
+ DJANGO_SETTINGS_MODULE=tests.conftest_settings \
110
+ uv run mkdocs gh-deploy --force --clean --config-file mkdocs.yml
@@ -0,0 +1,169 @@
1
+ name: tests
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ concurrency:
9
+ group: tests-${{ github.ref }}
10
+ cancel-in-progress: true
11
+
12
+ jobs:
13
+ lint:
14
+ name: lint
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+ - uses: astral-sh/setup-uv@v6
19
+ with:
20
+ enable-cache: true
21
+ - name: Install
22
+ run: uv sync --all-groups
23
+ - name: ruff check
24
+ run: uv run ruff check .
25
+ - name: ruff format check
26
+ run: uv run ruff format --check --diff .
27
+ - name: ty
28
+ run: uv run ty check rest_framework_mcp
29
+
30
+ docs:
31
+ name: docs build
32
+ runs-on: ubuntu-latest
33
+ steps:
34
+ - uses: actions/checkout@v4
35
+ - uses: astral-sh/setup-uv@v6
36
+ with:
37
+ enable-cache: true
38
+ - name: Install with docs group
39
+ run: uv sync --all-groups
40
+ - name: mkdocs build --strict
41
+ # mkdocstrings imports the package, which transitively imports DRF;
42
+ # DRF reads ``settings.REST_FRAMEWORK`` at import time, so we point at
43
+ # the test settings module to keep the build hermetic.
44
+ run: DJANGO_SETTINGS_MODULE=tests.conftest_settings uv run mkdocs build --strict
45
+
46
+ test:
47
+ name: ${{ matrix.python-version }} / Django ${{ matrix.django-version }}
48
+ runs-on: ubuntu-latest
49
+ strategy:
50
+ fail-fast: false
51
+ matrix:
52
+ python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
53
+ django-version: ["4.2", "5.0", "5.1", "5.2", "6.0"]
54
+ exclude:
55
+ # Django 4.2 supports Python 3.8–3.12
56
+ - python-version: "3.13"
57
+ django-version: "4.2"
58
+ - python-version: "3.14"
59
+ django-version: "4.2"
60
+ # Django 5.0 supports Python 3.10–3.12
61
+ - python-version: "3.13"
62
+ django-version: "5.0"
63
+ - python-version: "3.14"
64
+ django-version: "5.0"
65
+ # Django 5.1 supports Python 3.10–3.13
66
+ - python-version: "3.14"
67
+ django-version: "5.1"
68
+ # Django 6.0 requires Python 3.12+
69
+ - python-version: "3.10"
70
+ django-version: "6.0"
71
+ - python-version: "3.11"
72
+ django-version: "6.0"
73
+
74
+ steps:
75
+ - uses: actions/checkout@v4
76
+ - uses: astral-sh/setup-uv@v6
77
+ with:
78
+ enable-cache: true
79
+ - name: Install Python ${{ matrix.python-version }}
80
+ run: uv python install ${{ matrix.python-version }}
81
+ - name: Sync dev deps
82
+ run: uv sync --all-groups --python ${{ matrix.python-version }}
83
+ - name: Pin Django ${{ matrix.django-version }}
84
+ run: uv pip install --reinstall-package django "django~=${{ matrix.django-version }}.0"
85
+ - name: pytest
86
+ run: uv run --no-sync pytest
87
+
88
+ smoke-no-extras:
89
+ name: smoke (no optional extras)
90
+ runs-on: ubuntu-latest
91
+ steps:
92
+ - uses: actions/checkout@v4
93
+ - uses: astral-sh/setup-uv@v6
94
+ with:
95
+ enable-cache: true
96
+ - name: Install base only (no [toon], no [oauth], no dev group)
97
+ run: |
98
+ uv venv --python 3.13 .venv-smoke
99
+ .venv-smoke/bin/python -m pip install --upgrade pip
100
+ .venv-smoke/bin/pip install -e .
101
+ - name: Confirm import + server build + TOON fallback
102
+ run: |
103
+ .venv-smoke/bin/python - <<'PY'
104
+ import warnings
105
+
106
+ import django
107
+ from django.conf import settings
108
+
109
+ settings.configure(
110
+ SECRET_KEY="x",
111
+ INSTALLED_APPS=[
112
+ "django.contrib.contenttypes",
113
+ "django.contrib.auth",
114
+ "rest_framework",
115
+ ],
116
+ DATABASES={"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}},
117
+ REST_FRAMEWORK_MCP={
118
+ "AUTH_BACKEND": "rest_framework_mcp.auth.backends.allow_any_backend.AllowAnyBackend",
119
+ "SESSION_STORE": "rest_framework_mcp.transport.in_memory_session_store.InMemorySessionStore",
120
+ "ALLOWED_ORIGINS": ["*"],
121
+ "SERVER_INFO": {},
122
+ },
123
+ )
124
+ django.setup()
125
+
126
+ from rest_framework_mcp import MCPServer
127
+ from rest_framework_mcp.output.encode_toon import encode_toon
128
+ from rest_framework_services.types.service_spec import ServiceSpec
129
+
130
+ server = MCPServer(name="smoke")
131
+ server.register_tool(name="noop", spec=ServiceSpec(service=lambda: None))
132
+ assert server.tools.get("noop") is not None
133
+
134
+ with warnings.catch_warnings(record=True) as caught:
135
+ warnings.simplefilter("always")
136
+ encode_toon({"a": 1})
137
+ assert any("python-toon" in str(item.message) for item in caught), (
138
+ "Expected TOON fallback warning when extra is missing"
139
+ )
140
+
141
+ # The OAuth backend module imports fine without oauth2_provider — the
142
+ # ImportError only fires if a request actually hits authenticate().
143
+ from rest_framework_mcp.auth.backends.django_oauth_toolkit_backend import (
144
+ DjangoOAuthToolkitBackend,
145
+ )
146
+ backend = DjangoOAuthToolkitBackend()
147
+ try:
148
+ import oauth2_provider # noqa: F401
149
+ raise SystemExit("smoke environment unexpectedly has oauth2_provider installed")
150
+ except ImportError:
151
+ pass
152
+
153
+ # The Redis SSE broker module imports fine without ``redis`` — the
154
+ # ImportError only fires inside ``RedisSSEBroker.__init__``.
155
+ from rest_framework_mcp.transport.redis_sse_broker import RedisSSEBroker
156
+ try:
157
+ RedisSSEBroker(client=object())
158
+ raise SystemExit("RedisSSEBroker construction should fail without redis")
159
+ except ImportError:
160
+ pass
161
+
162
+ # The OTel tracing helper falls back to a no-op span when the API
163
+ # isn't installed — handlers stay branch-free.
164
+ from rest_framework_mcp._compat.tracing import span
165
+ with span("mcp.smoke") as s:
166
+ s.set_attribute("k", "v")
167
+
168
+ print("SMOKE OK")
169
+ PY