flarchitect 1.2.2__tar.gz → 1.2.3__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 (301) hide show
  1. {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/workspace.xml +12 -12
  2. {flarchitect-1.2.2 → flarchitect-1.2.3}/PKG-INFO +1 -1
  3. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/mcp/server.py +206 -34
  4. {flarchitect-1.2.2 → flarchitect-1.2.3}/pyproject.toml +1 -1
  5. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_mcp_server.py +12 -0
  6. {flarchitect-1.2.2 → flarchitect-1.2.3}/.github/pull_request_template.md +0 -0
  7. {flarchitect-1.2.2 → flarchitect-1.2.3}/.github/workflows/auto-pr-meta.yml +0 -0
  8. {flarchitect-1.2.2 → flarchitect-1.2.3}/.github/workflows/branch-name-check.yml +0 -0
  9. {flarchitect-1.2.2 → flarchitect-1.2.3}/.github/workflows/docs.yml +0 -0
  10. {flarchitect-1.2.2 → flarchitect-1.2.3}/.github/workflows/release.yml +0 -0
  11. {flarchitect-1.2.2 → flarchitect-1.2.3}/.github/workflows/run-unit-tests.yml +0 -0
  12. {flarchitect-1.2.2 → flarchitect-1.2.3}/.github/workflows/semantic-preview.yml +0 -0
  13. {flarchitect-1.2.2 → flarchitect-1.2.3}/.gitignore +0 -0
  14. {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/.gitignore +0 -0
  15. {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/aws.xml +0 -0
  16. {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/copilot.data.migration.agent.xml +0 -0
  17. {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/copilot.data.migration.ask.xml +0 -0
  18. {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/copilot.data.migration.ask2agent.xml +0 -0
  19. {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/copilot.data.migration.edit.xml +0 -0
  20. {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/flarchitect.iml +0 -0
  21. {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/inspectionProfiles/profiles_settings.xml +0 -0
  22. {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/misc.xml +0 -0
  23. {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/modules.xml +0 -0
  24. {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/ruff.xml +0 -0
  25. {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/shelf/delete_unused_files/shelved.patch +0 -0
  26. {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/shelf/delete_unused_files.xml +0 -0
  27. {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/vcs.xml +0 -0
  28. {flarchitect-1.2.2 → flarchitect-1.2.3}/AGENTS.md +0 -0
  29. {flarchitect-1.2.2 → flarchitect-1.2.3}/CHANGELOG.md +0 -0
  30. {flarchitect-1.2.2 → flarchitect-1.2.3}/LICENSE +0 -0
  31. {flarchitect-1.2.2 → flarchitect-1.2.3}/README.md +0 -0
  32. {flarchitect-1.2.2 → flarchitect-1.2.3}/SUGGESTIONS.md +0 -0
  33. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/__init__.py +0 -0
  34. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/advanced_features/app.py +0 -0
  35. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/authentication/README.md +0 -0
  36. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/authentication/api_key_auth.py +0 -0
  37. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/authentication/app_base.py +0 -0
  38. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/authentication/basic_auth.py +0 -0
  39. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/authentication/custom_auth.py +0 -0
  40. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/authentication/helpers.py +0 -0
  41. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/authentication/jwt_auth.py +0 -0
  42. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/authentication/load.py +0 -0
  43. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/authentication/model/__init__.py +0 -0
  44. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/authentication/model/config.py +0 -0
  45. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/authentication/model/extensions.py +0 -0
  46. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/authentication/model/models.py +0 -0
  47. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/basic_factory/README.md +0 -0
  48. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/basic_factory/basic_factory/__init__.py +0 -0
  49. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/basic_factory/basic_factory/config.py +0 -0
  50. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/basic_factory/basic_factory/extensions.py +0 -0
  51. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/basic_factory/basic_factory/models.py +0 -0
  52. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/basic_factory/load.py +0 -0
  53. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/caching/README.md +0 -0
  54. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/caching/app.py +0 -0
  55. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/callbacks/callbacks.py +0 -0
  56. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/callbacks/helpers.py +0 -0
  57. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/callbacks/load.py +0 -0
  58. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/callbacks/model/__init__.py +0 -0
  59. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/callbacks/model/callbacks.py +0 -0
  60. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/callbacks/model/config.py +0 -0
  61. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/callbacks/model/extensions.py +0 -0
  62. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/callbacks/model/models.py +0 -0
  63. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/field_case/README.md +0 -0
  64. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/field_case/__init__.py +0 -0
  65. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/field_case/app.py +0 -0
  66. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/graphql/README.md +0 -0
  67. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/graphql/advanced_example.py +0 -0
  68. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/graphql/client_example.py +0 -0
  69. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/graphql/load.py +0 -0
  70. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/graphql/sample_queries.graphql +0 -0
  71. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/model_extension/helpers.py +0 -0
  72. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/model_extension/load.py +0 -0
  73. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/model_extension/model/__init__.py +0 -0
  74. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/model_extension/model/config.py +0 -0
  75. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/model_extension/model/extensions.py +0 -0
  76. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/model_extension/model/models.py +0 -0
  77. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/quickstart/load.py +0 -0
  78. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/scaffolding/__init__.py +0 -0
  79. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/scaffolding/load.py +0 -0
  80. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/scaffolding/module/__init__.py +0 -0
  81. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/scaffolding/module/config.py +0 -0
  82. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/scaffolding/module/extensions.py +0 -0
  83. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/scaffolding/module/models.py +0 -0
  84. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/soft_delete/helpers.py +0 -0
  85. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/soft_delete/load.py +0 -0
  86. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/soft_delete/soft_delete/__init__.py +0 -0
  87. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/soft_delete/soft_delete/config.py +0 -0
  88. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/soft_delete/soft_delete/extensions.py +0 -0
  89. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/soft_delete/soft_delete/models.py +0 -0
  90. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/utils/__init__.py +0 -0
  91. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/utils/constants.py +0 -0
  92. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/utils/helpers.py +0 -0
  93. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/validators/README.md +0 -0
  94. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/validators/__init__.py +0 -0
  95. {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/validators/app.py +0 -0
  96. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/.readthedocs.yaml +0 -0
  97. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/Makefile +0 -0
  98. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/config.xlsx +0 -0
  99. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/logo.png +0 -0
  100. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/logo.xcf +0 -0
  101. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/make.bat +0 -0
  102. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/requirements.txt +0 -0
  103. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/social-card.png +0 -0
  104. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/_configuration_table.rst +0 -0
  105. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/_static/colours.css +0 -0
  106. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/_static/custom.css +0 -0
  107. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/_static/favicon.ico +0 -0
  108. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/_static/version.svg +0 -0
  109. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/advanced_configuration.rst +0 -0
  110. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/advanced_demo.rst +0 -0
  111. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/auth_cookbook.rst +0 -0
  112. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/authentication.rst +0 -0
  113. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/conf.py +0 -0
  114. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/config_locations/global_.rst +0 -0
  115. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/config_locations/model.rst +0 -0
  116. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/config_locations/model_method.rst +0 -0
  117. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/configuration.rst +0 -0
  118. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/error_handling.rst +0 -0
  119. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/extensions.rst +0 -0
  120. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/faq.rst +0 -0
  121. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/getting_started.rst +0 -0
  122. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/graphql.rst +0 -0
  123. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/hooks_cheatsheet.rst +0 -0
  124. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/index.rst +0 -0
  125. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/installation.rst +0 -0
  126. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/manual_routes.rst +0 -0
  127. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/mcp_server.rst +0 -0
  128. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/models.rst +0 -0
  129. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/openapi.rst +0 -0
  130. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/plugins.rst +0 -0
  131. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/quickstart.rst +0 -0
  132. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/roadmap.rst +0 -0
  133. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/validation.rst +0 -0
  134. {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/websockets.rst +0 -0
  135. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/__init__.py +0 -0
  136. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/authentication/__init__.py +0 -0
  137. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/authentication/jwt.py +0 -0
  138. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/authentication/roles.py +0 -0
  139. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/authentication/token_store.py +0 -0
  140. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/authentication/user.py +0 -0
  141. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/authorization/roles.py +0 -0
  142. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/core/__init__.py +0 -0
  143. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/core/architect.py +0 -0
  144. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/core/routes.py +0 -0
  145. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/core/simple_cache.py +0 -0
  146. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/core/utils.py +0 -0
  147. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/core/websockets.py +0 -0
  148. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/database/__init__.py +0 -0
  149. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/database/inspections.py +0 -0
  150. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/database/operations.py +0 -0
  151. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/database/utils.py +0 -0
  152. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/exceptions.py +0 -0
  153. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/graphql/__init__.py +0 -0
  154. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/html/apispec.html +0 -0
  155. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/html/base_readme.MD +0 -0
  156. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/html/docs_login.html +0 -0
  157. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/html/redoc_templates/__init__.py +0 -0
  158. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/html/redoc_templates/aggregate.html +0 -0
  159. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/html/redoc_templates/fields.html +0 -0
  160. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/html/redoc_templates/filters.html +0 -0
  161. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/html/redoc_templates/group.html +0 -0
  162. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/html/redoc_templates/joins.html +0 -0
  163. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/html/redoc_templates/order.html +0 -0
  164. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/html/swagger.html +0 -0
  165. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/logging.py +0 -0
  166. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/mcp/__init__.py +0 -0
  167. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/mcp/index.py +0 -0
  168. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/plugins.py +0 -0
  169. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/schemas/__init__.py +0 -0
  170. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/schemas/auth.py +0 -0
  171. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/schemas/bases.py +0 -0
  172. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/schemas/models.py +0 -0
  173. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/schemas/utils.py +0 -0
  174. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/schemas/validators.py +0 -0
  175. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/specs/__init__.py +0 -0
  176. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/specs/base.py +0 -0
  177. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/specs/generator.py +0 -0
  178. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/specs/utils.py +0 -0
  179. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/utils/__init__.py +0 -0
  180. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/utils/config_helpers.py +0 -0
  181. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/utils/core_utils.py +0 -0
  182. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/utils/decorators.py +0 -0
  183. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/utils/general.py +0 -0
  184. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/utils/release.py +0 -0
  185. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/utils/response_filters.py +0 -0
  186. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/utils/response_helpers.py +0 -0
  187. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/utils/responses.py +0 -0
  188. {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/utils/session.py +0 -0
  189. {flarchitect-1.2.2 → flarchitect-1.2.3}/scripts/coverage.sh +0 -0
  190. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/AGENTS.md +0 -0
  191. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/__init__.py +0 -0
  192. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/authentication/test_token_persistence.py +0 -0
  193. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/authentication/test_token_store_session.py +0 -0
  194. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/conftest.py +0 -0
  195. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/core/test_simple_cache.py +0 -0
  196. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_api_filters.py +0 -0
  197. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_architect_helpers.py +0 -0
  198. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_auth_refresh_autoreg.py +0 -0
  199. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_authentication.py +0 -0
  200. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_authorization_roles.py +0 -0
  201. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_basic.py +0 -0
  202. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_cache.py +0 -0
  203. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_config_helpers_app_context.py +0 -0
  204. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_config_helpers_cache.py +0 -0
  205. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_core_utils_unit.py +0 -0
  206. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_cors.py +0 -0
  207. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_custom_http_exception.py +0 -0
  208. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_custom_spec_defaults.py +0 -0
  209. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_database_utils_extra.py +0 -0
  210. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_decimal_field_metadata.py +0 -0
  211. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_decorator_output_schema_none_and_filter.py +0 -0
  212. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_demo_advanced_features.py +0 -0
  213. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_demo_authentication.py +0 -0
  214. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_demo_caching.py +0 -0
  215. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_demo_scaffolding_imports.py +0 -0
  216. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_demo_validators.py +0 -0
  217. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_docs_password.py +0 -0
  218. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_docs_spec_route.py +0 -0
  219. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_dump_flags.py +0 -0
  220. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_exceptions.py +0 -0
  221. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_flask.py +0 -0
  222. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_flask_config.py +0 -0
  223. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_functions.py +0 -0
  224. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_general_extra.py +0 -0
  225. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_general_get_html_path.py +0 -0
  226. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_general_more.py +0 -0
  227. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_general_paths_and_xml.py +0 -0
  228. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_general_small_units.py +0 -0
  229. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_get_user_from_token.py +0 -0
  230. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_graphql.py +0 -0
  231. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_graphql_extras.py +0 -0
  232. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_graphql_relationships.py +0 -0
  233. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_handle_result.py +0 -0
  234. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_import_all_modules.py +0 -0
  235. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_inspections.py +0 -0
  236. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_join_groupby_aggregation.py +0 -0
  237. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_jwt_errors.py +0 -0
  238. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_jwt_hardening.py +0 -0
  239. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_jwt_helpers_extra.py +0 -0
  240. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_logging_unit.py +0 -0
  241. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_logging_utils.py +0 -0
  242. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_make_endpoint_description.py +0 -0
  243. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_mcp_index.py +0 -0
  244. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_model_meta/README.md +0 -0
  245. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_model_meta/helpers.py +0 -0
  246. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_model_meta/load.py +0 -0
  247. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_model_meta/model_meta/__init__.py +0 -0
  248. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_model_meta/model_meta/config.py +0 -0
  249. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_model_meta/model_meta/extensions.py +0 -0
  250. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_model_meta/model_meta/models.py +0 -0
  251. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_model_meta/model_meta/templates/readme.MD.j2 +0 -0
  252. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_models.py +0 -0
  253. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_mutable_defaults.py +0 -0
  254. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_nested_relationship.py +0 -0
  255. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_nested_schema_refs_case.py +0 -0
  256. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_nested_writes.py +0 -0
  257. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_openapi_examples.py +0 -0
  258. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_package_exports.py +0 -0
  259. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_paginate_query.py +0 -0
  260. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_plugin_manager_unit.py +0 -0
  261. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_plugins.py +0 -0
  262. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_plugins_more.py +0 -0
  263. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_rate_limit_services.py +0 -0
  264. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_rate_prerequisites.py +0 -0
  265. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_readme_generation.py +0 -0
  266. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_recursive_delete.py +0 -0
  267. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_related_schema_ref.py +0 -0
  268. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_relation_route_naming.py +0 -0
  269. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_relation_routes_unique.py +0 -0
  270. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_release_helpers.py +0 -0
  271. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_release_helpers_extra.py +0 -0
  272. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_reloader_detection.py +0 -0
  273. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_response_filters.py +0 -0
  274. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_response_final_callback.py +0 -0
  275. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_response_helpers.py +0 -0
  276. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_response_helpers_extra.py +0 -0
  277. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_roles_decorators_extra.py +0 -0
  278. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_roles_required.py +0 -0
  279. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_route_helpers.py +0 -0
  280. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_scaffolding_models.py +0 -0
  281. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_schemas_auth_extra.py +0 -0
  282. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_schemas_models_user_schema.py +0 -0
  283. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_schemas_utils_extra.py +0 -0
  284. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_serialization_detached.py +0 -0
  285. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_session_helper.py +0 -0
  286. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_soft_delete.py +0 -0
  287. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_spec_error_responses.py +0 -0
  288. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_spec_registration.py +0 -0
  289. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_spec_route.py +0 -0
  290. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_spec_tags.py +0 -0
  291. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_spec_url_prefix.py +0 -0
  292. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_specs_utils.py +0 -0
  293. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_swagger_ui.py +0 -0
  294. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_to_url_mapped_pk.py +0 -0
  295. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_token_rotation.py +0 -0
  296. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_utils_decorators.py +0 -0
  297. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_utils_responses_extra.py +0 -0
  298. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_validators.py +0 -0
  299. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_version.py +0 -0
  300. {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_websockets_bus.py +0 -0
  301. {flarchitect-1.2.2 → flarchitect-1.2.3}/version.svg +0 -0
@@ -436,15 +436,7 @@
436
436
  <workItem from="1757337217017" duration="2000" />
437
437
  <workItem from="1757966306367" duration="1932000" />
438
438
  <workItem from="1758106398498" duration="6391000" />
439
- <workItem from="1758117871934" duration="6882000" />
440
- </task>
441
- <task id="LOCAL-00076" summary="docs intro change">
442
- <option name="closed" value="true" />
443
- <created>1755180090932</created>
444
- <option name="number" value="00076" />
445
- <option name="presentableId" value="LOCAL-00076" />
446
- <option name="project" value="LOCAL" />
447
- <updated>1755180090932</updated>
439
+ <workItem from="1758117871934" duration="10495000" />
448
440
  </task>
449
441
  <task id="LOCAL-00077" summary="docs intro change">
450
442
  <option name="closed" value="true" />
@@ -830,7 +822,15 @@
830
822
  <option name="project" value="LOCAL" />
831
823
  <updated>1758130078352</updated>
832
824
  </task>
833
- <option name="localTasksCounter" value="125" />
825
+ <task id="LOCAL-00125" summary="Huge changes to all aspects">
826
+ <option name="closed" value="true" />
827
+ <created>1758137645823</created>
828
+ <option name="number" value="00125" />
829
+ <option name="presentableId" value="LOCAL-00125" />
830
+ <option name="project" value="LOCAL" />
831
+ <updated>1758137645823</updated>
832
+ </task>
833
+ <option name="localTasksCounter" value="126" />
834
834
  <servers />
835
835
  </component>
836
836
  <component name="TypeScriptGeneratedFilesManager">
@@ -1123,12 +1123,12 @@
1123
1123
  </line-breakpoint>
1124
1124
  <line-breakpoint enabled="true" suspend="THREAD" type="python-line">
1125
1125
  <url>file://$PROJECT_DIR$/flarchitect/mcp/server.py</url>
1126
- <line>120</line>
1126
+ <line>207</line>
1127
1127
  <option name="timeStamp" value="960" />
1128
1128
  </line-breakpoint>
1129
1129
  <line-breakpoint enabled="true" suspend="THREAD" type="python-line">
1130
1130
  <url>file://$PROJECT_DIR$/flarchitect/mcp/server.py</url>
1131
- <line>119</line>
1131
+ <line>206</line>
1132
1132
  <option name="timeStamp" value="961" />
1133
1133
  </line-breakpoint>
1134
1134
  </breakpoints>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flarchitect
3
- Version: 1.2.2
3
+ Version: 1.2.3
4
4
  Summary: Automatic RESTful API generator with redoc
5
5
  Author-email: "arched.dev (Lewis Morris)" <hello@arched.dev>
6
6
  License-File: LICENSE
@@ -17,6 +17,7 @@ from .index import DocumentIndex, DocumentRecord, SearchHit
17
17
 
18
18
  PROTOCOL_VERSION = "2025-06-18"
19
19
  DOC_URI_PREFIX = "flarchitect-doc://"
20
+ _READ_ONLY_ANNOTATIONS = {"readOnlyHint": True}
20
21
 
21
22
  _SEARCH_INPUT_SCHEMA = {
22
23
  "type": "object",
@@ -48,17 +49,103 @@ _SECTION_INPUT_SCHEMA = {
48
49
  "required": ["doc_id"],
49
50
  }
50
51
 
51
- _TOOL_DEFINITIONS: tuple[tuple[str, str, dict[str, Any]], ...] = (
52
- (
53
- "search_docs",
54
- "Search flarchitect documentation for matching text.",
55
- _SEARCH_INPUT_SCHEMA,
56
- ),
57
- (
58
- "get_doc_section",
59
- "Return a full document or a named section by heading.",
60
- _SECTION_INPUT_SCHEMA,
61
- ),
52
+ _LIST_INPUT_SCHEMA = {
53
+ "type": "object",
54
+ "properties": {},
55
+ "additionalProperties": False,
56
+ }
57
+
58
+ _LIST_OUTPUT_SCHEMA = {
59
+ "type": "object",
60
+ "properties": {
61
+ "result": {
62
+ "type": "array",
63
+ "items": {
64
+ "type": "object",
65
+ "properties": {
66
+ "doc_id": {"type": "string"},
67
+ "title": {"type": "string"},
68
+ },
69
+ "required": ["doc_id", "title"],
70
+ "additionalProperties": False,
71
+ },
72
+ }
73
+ },
74
+ "required": ["result"],
75
+ "additionalProperties": False,
76
+ }
77
+
78
+ _SEARCH_OUTPUT_SCHEMA = {
79
+ "type": "object",
80
+ "properties": {
81
+ "result": {
82
+ "type": "array",
83
+ "items": {
84
+ "type": "object",
85
+ "properties": {
86
+ "doc_id": {"type": "string"},
87
+ "title": {"type": "string"},
88
+ "url": {"type": "string"},
89
+ "uri": {"type": "string"},
90
+ "score": {"type": "number"},
91
+ "snippet": {"type": "string"},
92
+ "line": {"type": "integer"},
93
+ "heading": {"type": ["string", "null"]},
94
+ },
95
+ "required": ["doc_id", "title", "url", "uri", "score", "snippet", "line"],
96
+ "additionalProperties": True,
97
+ },
98
+ }
99
+ },
100
+ "required": ["result"],
101
+ "additionalProperties": False,
102
+ }
103
+
104
+ _SECTION_OUTPUT_SCHEMA = {
105
+ "type": "object",
106
+ "properties": {
107
+ "result": {
108
+ "type": "object",
109
+ "properties": {
110
+ "doc_id": {"type": "string"},
111
+ "title": {"type": "string"},
112
+ "heading": {"type": ["string", "null"]},
113
+ "content": {"type": "string"},
114
+ "url": {"type": "string"},
115
+ },
116
+ "required": ["doc_id", "title", "content", "url"],
117
+ "additionalProperties": True,
118
+ }
119
+ },
120
+ "required": ["result"],
121
+ "additionalProperties": False,
122
+ }
123
+
124
+ _TOOL_DEFINITIONS: tuple[dict[str, Any], ...] = (
125
+ {
126
+ "name": "list_docs",
127
+ "description": "List indexed documentation files.",
128
+ "input_schema": _LIST_INPUT_SCHEMA,
129
+ "output_schema": _LIST_OUTPUT_SCHEMA,
130
+ "tags": {"docs", "list"},
131
+ "annotations": _READ_ONLY_ANNOTATIONS,
132
+ },
133
+ {
134
+ "name": "search_docs",
135
+ "description": "Search flarchitect documentation for matching text.",
136
+ "input_schema": _SEARCH_INPUT_SCHEMA,
137
+ "output_schema": _SEARCH_OUTPUT_SCHEMA,
138
+ "tags": {"docs", "search"},
139
+ "annotations": _READ_ONLY_ANNOTATIONS,
140
+ },
141
+ {
142
+ "name": "get_doc_section",
143
+ "description": "Return a full document or a named section by heading.",
144
+ "input_schema": _SECTION_INPUT_SCHEMA,
145
+ "output_schema": _SECTION_OUTPUT_SCHEMA,
146
+ "tags": {"docs", "section"},
147
+ "annotations": _READ_ONLY_ANNOTATIONS,
148
+ },
62
149
  )
63
150
 
64
151
 
@@ -195,9 +282,24 @@ def _configure_fastmcp(app: Any, config: ServerConfig, index: DocumentIndex) ->
195
282
  resource = _build_resource_payload(TextResource, TextResource, record, project_root)
196
283
  add_resource(resource)
197
284
 
285
+ @tool_decorator(
286
+ name="list_docs",
287
+ description="List indexed documentation files.",
288
+ tags={"docs", "list"},
289
+ output_schema=_LIST_OUTPUT_SCHEMA,
290
+ annotations=_READ_ONLY_ANNOTATIONS,
291
+ )
292
+ async def list_docs() -> Any:
293
+ items = [{"doc_id": record.doc_id, "title": record.title} for record in index.list_documents()]
294
+ structured = {"result": items}
295
+ return _build_tool_result(ToolResultCls, from_standard.tool_result, structured)
296
+
198
297
  @tool_decorator(
199
298
  name="search_docs",
200
299
  description="Search flarchitect documentation for matching text.",
300
+ tags={"docs", "search"},
301
+ output_schema=_SEARCH_OUTPUT_SCHEMA,
302
+ annotations=_READ_ONLY_ANNOTATIONS,
201
303
  )
202
304
  async def search_docs(
203
305
  query: Annotated[str, Field(description="Text to search for")],
@@ -217,6 +319,9 @@ def _configure_fastmcp(app: Any, config: ServerConfig, index: DocumentIndex) ->
217
319
  @tool_decorator(
218
320
  name="get_doc_section",
219
321
  description="Return a full document or a named section by heading.",
322
+ tags={"docs", "section"},
323
+ output_schema=_SECTION_OUTPUT_SCHEMA,
324
+ annotations=_READ_ONLY_ANNOTATIONS,
220
325
  )
221
326
  async def get_doc_section(
222
327
  doc_id: Annotated[
@@ -235,20 +340,20 @@ def _configure_fastmcp(app: Any, config: ServerConfig, index: DocumentIndex) ->
235
340
  if not doc_id:
236
341
  raise ValueError("'doc_id' is required")
237
342
  try:
238
- record = index.get(doc_id)
343
+ resolved_id, record = _resolve_document_record(index, doc_id)
239
344
  except KeyError as exc:
240
345
  raise ValueError(str(exc)) from exc
241
346
  try:
242
- content = index.get_section(doc_id, heading)
347
+ content = index.get_section(resolved_id, heading)
243
348
  except KeyError as exc:
244
349
  raise ValueError(str(exc)) from exc
245
350
  structured = {
246
351
  "result": {
247
- "doc_id": doc_id,
352
+ "doc_id": resolved_id,
248
353
  "title": record.title,
249
354
  "heading": heading,
250
355
  "content": content,
251
- "url": _build_doc_url(doc_id),
356
+ "url": _build_doc_url(resolved_id),
252
357
  }
253
358
  }
254
359
  return _build_tool_result(ToolResultCls, from_standard.tool_result, structured)
@@ -370,13 +475,13 @@ def _create_reference_server(config: ServerConfig, index: DocumentIndex):
370
475
  async def _read_resource(uri: str) -> str:
371
476
  doc_id = str(uri).replace(DOC_URI_PREFIX, "", 1)
372
477
  try:
373
- record = index.get(doc_id)
478
+ _, record = _resolve_document_record(index, doc_id)
374
479
  except KeyError as exc:
375
480
  raise ValueError(f"No document with id '{doc_id}'") from exc
376
481
  return record.content
377
482
 
378
483
  tool_definitions = [
379
- _build_tool_definition(mcp_types.Tool, *definition)
484
+ _build_tool_definition(mcp_types.Tool, **definition)
380
485
  for definition in _TOOL_DEFINITIONS
381
486
  ]
382
487
 
@@ -386,6 +491,12 @@ def _create_reference_server(config: ServerConfig, index: DocumentIndex):
386
491
 
387
492
  @server.call_tool()
388
493
  async def _call_tool(name: str, arguments: dict[str, Any]) -> tuple[list[Any], dict[str, Any]]:
494
+ if name == "list_docs":
495
+ items = [{"doc_id": record.doc_id, "title": record.title} for record in index.list_documents()]
496
+ structured = {"result": items}
497
+ text = mcp_types.TextContent(type="text", text=json.dumps(structured, indent=2))
498
+ return ([text], structured)
499
+
389
500
  if name == "search_docs":
390
501
  hits = index.search(str(arguments.get("query") or ""), limit=int(arguments.get("limit", 10)))
391
502
  structured = {"result": [_format_hit(index, hit) for hit in hits]}
@@ -397,21 +508,21 @@ def _create_reference_server(config: ServerConfig, index: DocumentIndex):
397
508
  if not doc_id:
398
509
  raise ValueError("'doc_id' is required")
399
510
  try:
400
- record = index.get(doc_id)
511
+ resolved_id, record = _resolve_document_record(index, doc_id)
401
512
  except KeyError as exc:
402
513
  raise ValueError(str(exc)) from exc
403
514
  heading = arguments.get("heading")
404
515
  try:
405
- content = index.get_section(doc_id, heading)
516
+ content = index.get_section(resolved_id, heading)
406
517
  except KeyError as exc:
407
518
  raise ValueError(str(exc)) from exc
408
519
  structured = {
409
520
  "result": {
410
- "doc_id": doc_id,
521
+ "doc_id": resolved_id,
411
522
  "title": record.title,
412
523
  "heading": heading,
413
524
  "content": content,
414
- "url": _build_doc_url(doc_id),
525
+ "url": _build_doc_url(resolved_id),
415
526
  }
416
527
  }
417
528
  text = mcp_types.TextContent(type="text", text=json.dumps(structured, indent=2))
@@ -472,7 +583,7 @@ def _create_reference_server(config: ServerConfig, index: DocumentIndex):
472
583
  raise ValueError("'uri' is required to read a resource")
473
584
  doc_id = str(uri).replace(DOC_URI_PREFIX, "", 1)
474
585
  try:
475
- record = index.get(doc_id)
586
+ resolved_id, record = _resolve_document_record(index, doc_id)
476
587
  except KeyError as exc:
477
588
  raise ValueError(f"No document with id '{doc_id}'") from exc
478
589
  contents = _build_text_contents_payload(from_standard.text_contents, uri, record)
@@ -480,7 +591,10 @@ def _create_reference_server(config: ServerConfig, index: DocumentIndex):
480
591
  return from_standard.read_resource_result(contents=[contents])
481
592
  return {"contents": [contents]}
482
593
 
483
- tool_definitions: list[Any] = []
594
+ tool_definitions: list[Any] = [
595
+ _build_tool_definition(from_standard.tool, **definition)
596
+ for definition in _TOOL_DEFINITIONS
597
+ ]
484
598
 
485
599
  @server.method("tools/list")
486
600
  async def _tools_list(_: Any): # type: ignore[name-defined]
@@ -490,6 +604,10 @@ def _create_reference_server(config: ServerConfig, index: DocumentIndex):
490
604
  async def _tools_call(request: CallToolRequest): # type: ignore[name-defined]
491
605
  tool_name = getattr(request, "name", None) or getattr(request, "tool", None)
492
606
  arguments = _extract_arguments(request)
607
+ if tool_name == "list_docs":
608
+ items = [{"doc_id": record.doc_id, "title": record.title} for record in index.list_documents()]
609
+ structured = {"result": items}
610
+ return _build_tool_result(None, from_standard.tool_result, structured)
493
611
  if tool_name == "search_docs":
494
612
  hits = index.search(str(arguments.get("query") or ""), limit=int(arguments.get("limit", 10)))
495
613
  structured = {"result": [_format_hit(index, hit) for hit in hits]}
@@ -499,31 +617,26 @@ def _create_reference_server(config: ServerConfig, index: DocumentIndex):
499
617
  if not doc_id:
500
618
  raise ValueError("'doc_id' is required")
501
619
  try:
502
- record = index.get(doc_id)
620
+ resolved_id, record = _resolve_document_record(index, doc_id)
503
621
  except KeyError as exc:
504
622
  raise ValueError(str(exc)) from exc
505
623
  heading = arguments.get("heading")
506
624
  try:
507
- content = index.get_section(doc_id, heading)
625
+ content = index.get_section(resolved_id, heading)
508
626
  except KeyError as exc:
509
627
  raise ValueError(str(exc)) from exc
510
628
  structured = {
511
629
  "result": {
512
- "doc_id": doc_id,
630
+ "doc_id": resolved_id,
513
631
  "title": record.title,
514
632
  "heading": heading,
515
633
  "content": content,
516
- "url": _build_doc_url(doc_id),
634
+ "url": _build_doc_url(resolved_id),
517
635
  }
518
636
  }
519
637
  return _build_tool_result(None, from_standard.tool_result, structured)
520
638
  raise ValueError(f"Unknown tool '{tool_name}'")
521
639
 
522
- for definition in _TOOL_DEFINITIONS:
523
- tool_definitions.append(
524
- _build_tool_definition(from_standard.tool, *definition)
525
- )
526
-
527
640
  return server
528
641
 
529
642
 
@@ -557,9 +670,18 @@ def _register_tool(
557
670
  name: str,
558
671
  description: str,
559
672
  input_schema: dict[str, Any],
673
+ output_schema: dict[str, Any] | None,
674
+ tags: set[str] | None,
675
+ annotations: dict[str, Any] | None,
560
676
  from_standard: _StandardModels,
561
677
  ) -> None:
562
678
  metadata = {"name": name, "description": description, "inputSchema": input_schema}
679
+ if output_schema is not None:
680
+ metadata["outputSchema"] = output_schema
681
+ if tags:
682
+ metadata["tags"] = sorted(tags)
683
+ if annotations:
684
+ metadata["annotations"] = annotations
563
685
  decorator = None
564
686
  try:
565
687
  decorator = hook(**metadata)
@@ -579,6 +701,9 @@ def _register_tool(
579
701
  name=name,
580
702
  description=description,
581
703
  input_schema=input_schema,
704
+ output_schema=output_schema,
705
+ tags=tags,
706
+ annotations=annotations,
582
707
  )
583
708
 
584
709
 
@@ -692,15 +817,30 @@ def _attach_tool_metadata(
692
817
  name: str,
693
818
  description: str,
694
819
  input_schema: dict[str, Any],
820
+ output_schema: dict[str, Any] | None,
821
+ tags: set[str] | None,
822
+ annotations: dict[str, Any] | None,
695
823
  ) -> None:
696
- func.definition = _build_tool_definition(tool_cls, name, description, input_schema) # type: ignore[attr-defined]
824
+ func.definition = _build_tool_definition( # type: ignore[attr-defined]
825
+ tool_cls,
826
+ name=name,
827
+ description=description,
828
+ input_schema=input_schema,
829
+ output_schema=output_schema,
830
+ tags=tags,
831
+ annotations=annotations,
832
+ )
697
833
 
698
834
 
699
835
  def _build_tool_definition(
700
836
  tool_cls: Any,
837
+ *,
701
838
  name: str,
702
839
  description: str,
703
840
  input_schema: dict[str, Any],
841
+ output_schema: dict[str, Any] | None = None,
842
+ tags: set[str] | None = None,
843
+ annotations: dict[str, Any] | None = None,
704
844
  ) -> Any:
705
845
  definition_payload = {
706
846
  "name": name,
@@ -709,6 +849,13 @@ def _build_tool_definition(
709
849
  "inputSchema": input_schema,
710
850
  "input_schema": input_schema,
711
851
  }
852
+ if output_schema is not None:
853
+ definition_payload["outputSchema"] = output_schema
854
+ definition_payload["output_schema"] = output_schema
855
+ if tags:
856
+ definition_payload["tags"] = sorted(tags)
857
+ if annotations:
858
+ definition_payload["annotations"] = annotations
712
859
  obj = _instantiate(tool_cls, definition_payload)
713
860
  if obj is not None:
714
861
  return obj
@@ -717,6 +864,9 @@ def _build_tool_definition(
717
864
  "title": description,
718
865
  "description": description,
719
866
  "inputSchema": input_schema,
867
+ **({"outputSchema": output_schema} if output_schema is not None else {}),
868
+ **({"tags": sorted(tags)} if tags else {}),
869
+ **({"annotations": annotations} if annotations else {}),
720
870
  }
721
871
 
722
872
 
@@ -733,6 +883,24 @@ def _build_doc_url(doc_id: str) -> str:
733
883
  return f"{DOC_URI_PREFIX}{doc_id}"
734
884
 
735
885
 
886
+ def _resolve_document_record(index: DocumentIndex, doc_id: str) -> tuple[str, DocumentRecord]:
887
+ candidates: list[str] = []
888
+ for candidate in (
889
+ doc_id,
890
+ doc_id.lower() if doc_id else doc_id,
891
+ f"{doc_id}.md" if doc_id else doc_id,
892
+ ):
893
+ if candidate and candidate not in candidates:
894
+ candidates.append(candidate)
895
+ for candidate in candidates:
896
+ try:
897
+ record = index.get(candidate)
898
+ return candidate, record
899
+ except KeyError:
900
+ continue
901
+ raise KeyError(f"No document with id '{doc_id}'")
902
+
903
+
736
904
  def _instantiate(cls: Any, payload: dict[str, Any]) -> Any | None:
737
905
  if cls is None:
738
906
  return None
@@ -783,12 +951,16 @@ def _format_hit(index: DocumentIndex, hit: SearchHit) -> dict[str, Any]:
783
951
  except KeyError: # pragma: no cover - defensive guard
784
952
  title = hit.path.stem.replace("_", " ").title()
785
953
  url = _build_doc_url(hit.doc_id)
954
+ line_number = hit.line_number or 0
955
+ if line_number < 0:
956
+ line_number = 0
957
+ score = 1.0 / (1 + line_number)
786
958
  item = {
787
959
  "doc_id": hit.doc_id,
788
960
  "title": title,
789
961
  "url": url,
790
962
  "uri": url,
791
- "score": 1.0,
963
+ "score": score,
792
964
  "snippet": hit.snippet,
793
965
  "line": hit.line_number,
794
966
  }
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
6
6
 
7
7
  [project]
8
8
  name = "flarchitect"
9
- version = "1.2.2"
9
+ version = "1.2.3"
10
10
  description = "Automatic RESTful API generator with redoc"
11
11
  readme = "README.md"
12
12
  requires-python = ">=3.10"
@@ -109,12 +109,24 @@ def test_fastmcp_backend_registration(monkeypatch, doc_index: DocumentIndex) ->
109
109
  assert first["url"].startswith("flarchitect-doc://")
110
110
  assert isinstance(first["score"], (int, float))
111
111
  assert first["snippet"]
112
+ assert pytest.approx(first["score"], rel=1e-6) == 0.5
112
113
  assert result.content[0]["type"] == "text"
113
114
 
114
115
  get_section_tool = fake_instance.tools["get_doc_section"]["func"]
115
116
  section = asyncio.run(get_section_tool(doc_id="docs/source/guide.rst", heading=None))
116
117
  assert "Guide" in section.structured_content["result"]["content"]
117
118
 
119
+ readme_section = asyncio.run(get_section_tool(doc_id="README", heading=None))
120
+ assert "Overview" in readme_section.structured_content["result"]["content"]
121
+
122
+ list_docs_tool = fake_instance.tools["list_docs"]["func"]
123
+ listed = asyncio.run(list_docs_tool())
124
+ docs_payload = listed.structured_content["result"]
125
+ titles = {item["title"] for item in docs_payload}
126
+ doc_ids = {item["doc_id"] for item in docs_payload}
127
+ assert "Guide" in titles
128
+ assert "README.md" in doc_ids
129
+
118
130
  # The server wrapper should call the run method when serve() is invoked.
119
131
  assert fake_instance.run_called is False
120
132
  server.serve()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes