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.
- {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/workspace.xml +12 -12
- {flarchitect-1.2.2 → flarchitect-1.2.3}/PKG-INFO +1 -1
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/mcp/server.py +206 -34
- {flarchitect-1.2.2 → flarchitect-1.2.3}/pyproject.toml +1 -1
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_mcp_server.py +12 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/.github/pull_request_template.md +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/.github/workflows/auto-pr-meta.yml +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/.github/workflows/branch-name-check.yml +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/.github/workflows/docs.yml +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/.github/workflows/release.yml +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/.github/workflows/run-unit-tests.yml +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/.github/workflows/semantic-preview.yml +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/.gitignore +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/.gitignore +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/aws.xml +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/copilot.data.migration.agent.xml +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/copilot.data.migration.ask.xml +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/copilot.data.migration.ask2agent.xml +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/copilot.data.migration.edit.xml +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/flarchitect.iml +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/inspectionProfiles/profiles_settings.xml +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/misc.xml +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/modules.xml +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/ruff.xml +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/shelf/delete_unused_files/shelved.patch +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/shelf/delete_unused_files.xml +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/.idea/vcs.xml +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/AGENTS.md +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/CHANGELOG.md +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/LICENSE +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/README.md +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/SUGGESTIONS.md +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/__init__.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/advanced_features/app.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/authentication/README.md +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/authentication/api_key_auth.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/authentication/app_base.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/authentication/basic_auth.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/authentication/custom_auth.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/authentication/helpers.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/authentication/jwt_auth.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/authentication/load.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/authentication/model/__init__.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/authentication/model/config.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/authentication/model/extensions.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/authentication/model/models.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/basic_factory/README.md +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/basic_factory/basic_factory/__init__.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/basic_factory/basic_factory/config.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/basic_factory/basic_factory/extensions.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/basic_factory/basic_factory/models.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/basic_factory/load.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/caching/README.md +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/caching/app.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/callbacks/callbacks.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/callbacks/helpers.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/callbacks/load.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/callbacks/model/__init__.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/callbacks/model/callbacks.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/callbacks/model/config.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/callbacks/model/extensions.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/callbacks/model/models.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/field_case/README.md +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/field_case/__init__.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/field_case/app.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/graphql/README.md +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/graphql/advanced_example.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/graphql/client_example.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/graphql/load.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/graphql/sample_queries.graphql +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/model_extension/helpers.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/model_extension/load.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/model_extension/model/__init__.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/model_extension/model/config.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/model_extension/model/extensions.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/model_extension/model/models.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/quickstart/load.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/scaffolding/__init__.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/scaffolding/load.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/scaffolding/module/__init__.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/scaffolding/module/config.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/scaffolding/module/extensions.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/scaffolding/module/models.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/soft_delete/helpers.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/soft_delete/load.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/soft_delete/soft_delete/__init__.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/soft_delete/soft_delete/config.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/soft_delete/soft_delete/extensions.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/soft_delete/soft_delete/models.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/utils/__init__.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/utils/constants.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/utils/helpers.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/validators/README.md +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/validators/__init__.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/demo/validators/app.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/.readthedocs.yaml +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/Makefile +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/config.xlsx +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/logo.png +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/logo.xcf +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/make.bat +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/requirements.txt +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/social-card.png +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/_configuration_table.rst +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/_static/colours.css +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/_static/custom.css +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/_static/favicon.ico +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/_static/version.svg +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/advanced_configuration.rst +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/advanced_demo.rst +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/auth_cookbook.rst +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/authentication.rst +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/conf.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/config_locations/global_.rst +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/config_locations/model.rst +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/config_locations/model_method.rst +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/configuration.rst +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/error_handling.rst +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/extensions.rst +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/faq.rst +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/getting_started.rst +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/graphql.rst +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/hooks_cheatsheet.rst +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/index.rst +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/installation.rst +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/manual_routes.rst +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/mcp_server.rst +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/models.rst +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/openapi.rst +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/plugins.rst +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/quickstart.rst +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/roadmap.rst +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/validation.rst +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/docs/source/websockets.rst +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/__init__.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/authentication/__init__.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/authentication/jwt.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/authentication/roles.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/authentication/token_store.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/authentication/user.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/authorization/roles.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/core/__init__.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/core/architect.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/core/routes.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/core/simple_cache.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/core/utils.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/core/websockets.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/database/__init__.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/database/inspections.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/database/operations.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/database/utils.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/exceptions.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/graphql/__init__.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/html/apispec.html +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/html/base_readme.MD +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/html/docs_login.html +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/html/redoc_templates/__init__.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/html/redoc_templates/aggregate.html +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/html/redoc_templates/fields.html +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/html/redoc_templates/filters.html +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/html/redoc_templates/group.html +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/html/redoc_templates/joins.html +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/html/redoc_templates/order.html +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/html/swagger.html +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/logging.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/mcp/__init__.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/mcp/index.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/plugins.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/schemas/__init__.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/schemas/auth.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/schemas/bases.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/schemas/models.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/schemas/utils.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/schemas/validators.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/specs/__init__.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/specs/base.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/specs/generator.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/specs/utils.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/utils/__init__.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/utils/config_helpers.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/utils/core_utils.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/utils/decorators.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/utils/general.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/utils/release.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/utils/response_filters.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/utils/response_helpers.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/utils/responses.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/flarchitect/utils/session.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/scripts/coverage.sh +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/AGENTS.md +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/__init__.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/authentication/test_token_persistence.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/authentication/test_token_store_session.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/conftest.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/core/test_simple_cache.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_api_filters.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_architect_helpers.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_auth_refresh_autoreg.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_authentication.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_authorization_roles.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_basic.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_cache.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_config_helpers_app_context.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_config_helpers_cache.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_core_utils_unit.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_cors.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_custom_http_exception.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_custom_spec_defaults.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_database_utils_extra.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_decimal_field_metadata.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_decorator_output_schema_none_and_filter.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_demo_advanced_features.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_demo_authentication.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_demo_caching.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_demo_scaffolding_imports.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_demo_validators.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_docs_password.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_docs_spec_route.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_dump_flags.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_exceptions.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_flask.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_flask_config.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_functions.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_general_extra.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_general_get_html_path.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_general_more.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_general_paths_and_xml.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_general_small_units.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_get_user_from_token.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_graphql.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_graphql_extras.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_graphql_relationships.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_handle_result.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_import_all_modules.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_inspections.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_join_groupby_aggregation.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_jwt_errors.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_jwt_hardening.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_jwt_helpers_extra.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_logging_unit.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_logging_utils.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_make_endpoint_description.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_mcp_index.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_model_meta/README.md +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_model_meta/helpers.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_model_meta/load.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_model_meta/model_meta/__init__.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_model_meta/model_meta/config.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_model_meta/model_meta/extensions.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_model_meta/model_meta/models.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_model_meta/model_meta/templates/readme.MD.j2 +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_models.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_mutable_defaults.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_nested_relationship.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_nested_schema_refs_case.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_nested_writes.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_openapi_examples.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_package_exports.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_paginate_query.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_plugin_manager_unit.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_plugins.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_plugins_more.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_rate_limit_services.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_rate_prerequisites.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_readme_generation.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_recursive_delete.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_related_schema_ref.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_relation_route_naming.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_relation_routes_unique.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_release_helpers.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_release_helpers_extra.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_reloader_detection.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_response_filters.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_response_final_callback.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_response_helpers.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_response_helpers_extra.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_roles_decorators_extra.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_roles_required.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_route_helpers.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_scaffolding_models.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_schemas_auth_extra.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_schemas_models_user_schema.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_schemas_utils_extra.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_serialization_detached.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_session_helper.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_soft_delete.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_spec_error_responses.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_spec_registration.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_spec_route.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_spec_tags.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_spec_url_prefix.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_specs_utils.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_swagger_ui.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_to_url_mapped_pk.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_token_rotation.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_utils_decorators.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_utils_responses_extra.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_validators.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_version.py +0 -0
- {flarchitect-1.2.2 → flarchitect-1.2.3}/tests/test_websockets_bus.py +0 -0
- {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="
|
|
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
|
-
<
|
|
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>
|
|
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>
|
|
1131
|
+
<line>206</line>
|
|
1132
1132
|
<option name="timeStamp" value="961" />
|
|
1133
1133
|
</line-breakpoint>
|
|
1134
1134
|
</breakpoints>
|
|
@@ -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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
|
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(
|
|
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":
|
|
352
|
+
"doc_id": resolved_id,
|
|
248
353
|
"title": record.title,
|
|
249
354
|
"heading": heading,
|
|
250
355
|
"content": content,
|
|
251
|
-
"url": _build_doc_url(
|
|
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
|
|
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,
|
|
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
|
|
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(
|
|
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":
|
|
521
|
+
"doc_id": resolved_id,
|
|
411
522
|
"title": record.title,
|
|
412
523
|
"heading": heading,
|
|
413
524
|
"content": content,
|
|
414
|
-
"url": _build_doc_url(
|
|
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
|
|
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
|
|
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(
|
|
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":
|
|
630
|
+
"doc_id": resolved_id,
|
|
513
631
|
"title": record.title,
|
|
514
632
|
"heading": heading,
|
|
515
633
|
"content": content,
|
|
516
|
-
"url": _build_doc_url(
|
|
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(
|
|
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":
|
|
963
|
+
"score": score,
|
|
792
964
|
"snippet": hit.snippet,
|
|
793
965
|
"line": hit.line_number,
|
|
794
966
|
}
|
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|