immich-api 0.2.3__tar.gz → 0.2.4__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 (183) hide show
  1. immich_api-0.2.4/.bumpversion.cfg +8 -0
  2. {immich_api-0.2.3/immich_api.egg-info → immich_api-0.2.4}/PKG-INFO +4 -4
  3. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/__init__.py +8 -0
  4. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/connector_sources.py +0 -22
  5. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/mcp_server.py +9 -2
  6. {immich_api-0.2.3 → immich_api-0.2.4/immich_api.egg-info}/PKG-INFO +4 -4
  7. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api.egg-info/entry_points.txt +1 -1
  8. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api.egg-info/requires.txt +3 -3
  9. {immich_api-0.2.3 → immich_api-0.2.4}/pyproject.toml +5 -5
  10. {immich_api-0.2.3 → immich_api-0.2.4}/scripts/bootstrap_environment.py +24 -0
  11. {immich_api-0.2.3 → immich_api-0.2.4}/specs/connector-content/status.json +3 -1
  12. {immich_api-0.2.3 → immich_api-0.2.4}/specs/immich-api/status.json +4 -4
  13. immich_api-0.2.4/tests/test_default_content_surfaces.py +198 -0
  14. {immich_api-0.2.3 → immich_api-0.2.4}/tests/test_fleet_name.py +1 -1
  15. immich_api-0.2.3/.bumpversion.cfg +0 -12
  16. immich_api-0.2.3/tests/test_default_content_surfaces.py +0 -43
  17. {immich_api-0.2.3 → immich_api-0.2.4}/.config/spec-dashboard.json +0 -0
  18. {immich_api-0.2.3 → immich_api-0.2.4}/.github/workflows/connector-pr.yml +0 -0
  19. {immich_api-0.2.3 → immich_api-0.2.4}/.github/workflows/pages.yml +0 -0
  20. {immich_api-0.2.3 → immich_api-0.2.4}/.github/workflows/pipeline.yml +0 -0
  21. {immich_api-0.2.3 → immich_api-0.2.4}/.github/workflows/scanners.yml +0 -0
  22. {immich_api-0.2.3 → immich_api-0.2.4}/.github/workflows/windows-ci.yml +0 -0
  23. {immich_api-0.2.3 → immich_api-0.2.4}/.pipeline-theme/provenance.json +0 -0
  24. {immich_api-0.2.3 → immich_api-0.2.4}/.pipeline-theme/scripts/sync_mkdocs_theme.py +0 -0
  25. {immich_api-0.2.3 → immich_api-0.2.4}/.pipeline-theme/templates/mkdocs-theme/README.md +0 -0
  26. {immich_api-0.2.3 → immich_api-0.2.4}/.pipeline-theme/templates/mkdocs-theme/assets/brands/agent-connector-sdk-logo-v1.png +0 -0
  27. {immich_api-0.2.3 → immich_api-0.2.4}/.pipeline-theme/templates/mkdocs-theme/assets/brands/agent-terminal-ui-logo-v1.png +0 -0
  28. {immich_api-0.2.3 → immich_api-0.2.4}/.pipeline-theme/templates/mkdocs-theme/assets/brands/agent-utilities-logo-v1.png +0 -0
  29. {immich_api-0.2.3 → immich_api-0.2.4}/.pipeline-theme/templates/mkdocs-theme/assets/brands/agent-webui-logo-v1.png +0 -0
  30. {immich_api-0.2.3 → immich_api-0.2.4}/.pipeline-theme/templates/mkdocs-theme/assets/brands/epistemic-graph-logo-v1.png +0 -0
  31. {immich_api-0.2.3 → immich_api-0.2.4}/.pipeline-theme/templates/mkdocs-theme/assets/brands/geniusbot-logo-v1.png +0 -0
  32. {immich_api-0.2.3 → immich_api-0.2.4}/.pipeline-theme/templates/mkdocs-theme/assets/brands/graph-os-logo-v1.png +0 -0
  33. {immich_api-0.2.3 → immich_api-0.2.4}/.pipeline-theme/templates/mkdocs-theme/assets/favicon.svg +0 -0
  34. {immich_api-0.2.3 → immich_api-0.2.4}/.pipeline-theme/templates/mkdocs-theme/assets/graph-mark.svg +0 -0
  35. {immich_api-0.2.3 → immich_api-0.2.4}/.pipeline-theme/templates/mkdocs-theme/assets/runtime-architecture.mmd +0 -0
  36. {immich_api-0.2.3 → immich_api-0.2.4}/.pipeline-theme/templates/mkdocs-theme/assets/runtime-architecture.svg +0 -0
  37. {immich_api-0.2.3 → immich_api-0.2.4}/.pipeline-theme/templates/mkdocs-theme/base.mkdocs.yml +0 -0
  38. {immich_api-0.2.3 → immich_api-0.2.4}/.pipeline-theme/templates/mkdocs-theme/extra.css +0 -0
  39. {immich_api-0.2.3 → immich_api-0.2.4}/.pipeline-theme/templates/mkdocs-theme/glossary.md +0 -0
  40. {immich_api-0.2.3 → immich_api-0.2.4}/.pipeline-theme/templates/mkdocs-theme/overrides/main.html +0 -0
  41. {immich_api-0.2.3 → immich_api-0.2.4}/.pre-commit-config.yaml +0 -0
  42. {immich_api-0.2.3 → immich_api-0.2.4}/LICENSE +0 -0
  43. {immich_api-0.2.3 → immich_api-0.2.4}/MANIFEST.in +0 -0
  44. {immich_api-0.2.3 → immich_api-0.2.4}/README.md +0 -0
  45. {immich_api-0.2.3 → immich_api-0.2.4}/docker/Dockerfile +0 -0
  46. {immich_api-0.2.3 → immich_api-0.2.4}/docker/debug.Dockerfile +0 -0
  47. {immich_api-0.2.3 → immich_api-0.2.4}/docker/mcp.compose.yml +0 -0
  48. {immich_api-0.2.3 → immich_api-0.2.4}/docker/starship.toml +0 -0
  49. {immich_api-0.2.3 → immich_api-0.2.4}/docs/agent-readiness.json +0 -0
  50. {immich_api-0.2.3 → immich_api-0.2.4}/docs/agent-readiness.schema.json +0 -0
  51. {immich_api-0.2.3 → immich_api-0.2.4}/docs/architecture.md +0 -0
  52. {immich_api-0.2.3 → immich_api-0.2.4}/docs/assets/brands/agent-connector-sdk-logo-v1.png +0 -0
  53. {immich_api-0.2.3 → immich_api-0.2.4}/docs/assets/brands/agent-terminal-ui-logo-v1.png +0 -0
  54. {immich_api-0.2.3 → immich_api-0.2.4}/docs/assets/brands/agent-utilities-logo-v1.png +0 -0
  55. {immich_api-0.2.3 → immich_api-0.2.4}/docs/assets/brands/agent-webui-logo-v1.png +0 -0
  56. {immich_api-0.2.3 → immich_api-0.2.4}/docs/assets/brands/epistemic-graph-logo-v1.png +0 -0
  57. {immich_api-0.2.3 → immich_api-0.2.4}/docs/assets/brands/geniusbot-logo-v1.png +0 -0
  58. {immich_api-0.2.3 → immich_api-0.2.4}/docs/assets/brands/graph-os-logo-v1.png +0 -0
  59. {immich_api-0.2.3 → immich_api-0.2.4}/docs/assets/favicon.svg +0 -0
  60. {immich_api-0.2.3 → immich_api-0.2.4}/docs/assets/graph-mark.svg +0 -0
  61. {immich_api-0.2.3 → immich_api-0.2.4}/docs/assets/runtime-architecture.mmd +0 -0
  62. {immich_api-0.2.3 → immich_api-0.2.4}/docs/assets/runtime-architecture.svg +0 -0
  63. {immich_api-0.2.3 → immich_api-0.2.4}/docs/capabilities/api.json +0 -0
  64. {immich_api-0.2.3 → immich_api-0.2.4}/docs/capabilities/mcp.json +0 -0
  65. {immich_api-0.2.3 → immich_api-0.2.4}/docs/concepts.md +0 -0
  66. {immich_api-0.2.3 → immich_api-0.2.4}/docs/deployment.md +0 -0
  67. {immich_api-0.2.3 → immich_api-0.2.4}/docs/glossary.md +0 -0
  68. {immich_api-0.2.3 → immich_api-0.2.4}/docs/immich-capabilities.md +0 -0
  69. {immich_api-0.2.3 → immich_api-0.2.4}/docs/index.md +0 -0
  70. {immich_api-0.2.3 → immich_api-0.2.4}/docs/installation.md +0 -0
  71. {immich_api-0.2.3 → immich_api-0.2.4}/docs/openapi-parity.md +0 -0
  72. {immich_api-0.2.3 → immich_api-0.2.4}/docs/overview.md +0 -0
  73. {immich_api-0.2.3 → immich_api-0.2.4}/docs/platform.md +0 -0
  74. {immich_api-0.2.3 → immich_api-0.2.4}/docs/spec-delivery.md +0 -0
  75. {immich_api-0.2.3 → immich_api-0.2.4}/docs/stylesheets/extra.css +0 -0
  76. {immich_api-0.2.3 → immich_api-0.2.4}/docs/usage.md +0 -0
  77. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/__main__.py +0 -0
  78. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/album_metadata.py +0 -0
  79. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/api/__init__.py +0 -0
  80. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/api/api_client_system.py +0 -0
  81. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/auth.py +0 -0
  82. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/connectors/__init__.py +0 -0
  83. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/error_authority.py +0 -0
  84. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/error_rendering.py +0 -0
  85. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/immich_input_models.py +0 -0
  86. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/immich_response_models.py +0 -0
  87. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/kg_ingest.py +0 -0
  88. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/mcp/__init__.py +0 -0
  89. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/mcp/album_sample.py +0 -0
  90. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/mcp_config.json +0 -0
  91. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/ontology/__init__.py +0 -0
  92. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/ontology/immich.ttl +0 -0
  93. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/ontology/schema-provenance.json +0 -0
  94. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/ontology/shapes/immich.ttl +0 -0
  95. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/openapi_auth_scheme.py +0 -0
  96. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/openapi_contract.json +0 -0
  97. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/openapi_execution.py +0 -0
  98. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/openapi_inventory.json +0 -0
  99. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/openapi_request.py +0 -0
  100. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/openapi_response.py +0 -0
  101. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/openapi_runtime.py +0 -0
  102. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/parity/__init__.py +0 -0
  103. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/parity/check_openapi_parity.py +0 -0
  104. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/parity/openapi_discovery.py +0 -0
  105. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/parity/openapi_parity.py +0 -0
  106. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/parity/openapi_provider_evidence.py +0 -0
  107. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/parity/openapi_provider_overlay.py +0 -0
  108. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/parity/openapi_provider_responses.py +0 -0
  109. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/parity/openapi_schema.py +0 -0
  110. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/parity/openapi_schema_budget.py +0 -0
  111. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/parity/openapi_schema_inputs.py +0 -0
  112. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/parity/openapi_schema_types.py +0 -0
  113. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/parity/openapi_security.py +0 -0
  114. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/parity/openapi_source_parity.py +0 -0
  115. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/parity/openapi_transport_parity.py +0 -0
  116. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/parity/unicode_patterns.py +0 -0
  117. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/parity/unicode_properties.json +0 -0
  118. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/prompts/__init__.py +0 -0
  119. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/prompts/immich_album_review.json +0 -0
  120. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/prompts/immich_asset_metadata.json +0 -0
  121. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/prompts/immich_person_record.json +0 -0
  122. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/prompts/immich_specialist.json +0 -0
  123. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/prompts/main_agent.json +0 -0
  124. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/skills/__init__.py +0 -0
  125. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/skills/immich-album-review/SKILL.md +0 -0
  126. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/skills/immich-asset-metadata/SKILL.md +0 -0
  127. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/skills/immich-health/SKILL.md +0 -0
  128. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api/skills/immich-person-record/SKILL.md +0 -0
  129. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api.egg-info/SOURCES.txt +0 -0
  130. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api.egg-info/dependency_links.txt +0 -0
  131. {immich_api-0.2.3 → immich_api-0.2.4}/immich_api.egg-info/top_level.txt +0 -0
  132. {immich_api-0.2.3 → immich_api-0.2.4}/mkdocs.yml +0 -0
  133. {immich_api-0.2.3 → immich_api-0.2.4}/pytest.ini +0 -0
  134. {immich_api-0.2.3 → immich_api-0.2.4}/requirements.txt +0 -0
  135. {immich_api-0.2.3 → immich_api-0.2.4}/scripts/agent_readiness_tck.py +0 -0
  136. {immich_api-0.2.3 → immich_api-0.2.4}/scripts/bootstrap.sh +0 -0
  137. {immich_api-0.2.3 → immich_api-0.2.4}/scripts/bootstrap_sources.py +0 -0
  138. {immich_api-0.2.3 → immich_api-0.2.4}/scripts/check_connector_contract.py +0 -0
  139. {immich_api-0.2.3 → immich_api-0.2.4}/scripts/check_import_safety.py +0 -0
  140. {immich_api-0.2.3 → immich_api-0.2.4}/scripts/check_workspace_source_drift.py +0 -0
  141. {immich_api-0.2.3 → immich_api-0.2.4}/scripts/generate_agent_readiness.py +0 -0
  142. {immich_api-0.2.3 → immich_api-0.2.4}/scripts/generate_immich_content.py +0 -0
  143. {immich_api-0.2.3 → immich_api-0.2.4}/scripts/measure_operation_parity.py +0 -0
  144. {immich_api-0.2.3 → immich_api-0.2.4}/scripts/reviewed_secret_history.py +0 -0
  145. {immich_api-0.2.3 → immich_api-0.2.4}/scripts/security_sanitizer.py +0 -0
  146. {immich_api-0.2.3 → immich_api-0.2.4}/scripts/select_python.py +0 -0
  147. {immich_api-0.2.3 → immich_api-0.2.4}/scripts/upstream_evidence.py +0 -0
  148. {immich_api-0.2.3 → immich_api-0.2.4}/scripts/verify_api_integration.py +0 -0
  149. {immich_api-0.2.3 → immich_api-0.2.4}/scripts/workspace_sources.py +0 -0
  150. {immich_api-0.2.3 → immich_api-0.2.4}/setup.cfg +0 -0
  151. {immich_api-0.2.3 → immich_api-0.2.4}/specs/README.md +0 -0
  152. {immich_api-0.2.3 → immich_api-0.2.4}/specs/connector-content/plan.md +0 -0
  153. {immich_api-0.2.3 → immich_api-0.2.4}/specs/connector-content/requirements.md +0 -0
  154. {immich_api-0.2.3 → immich_api-0.2.4}/specs/connector-content/spec.md +0 -0
  155. {immich_api-0.2.3 → immich_api-0.2.4}/specs/connector-content/tasks.md +0 -0
  156. {immich_api-0.2.3 → immich_api-0.2.4}/specs/connector-content/test-spec.md +0 -0
  157. {immich_api-0.2.3 → immich_api-0.2.4}/specs/immich-api/plan.md +0 -0
  158. {immich_api-0.2.3 → immich_api-0.2.4}/specs/immich-api/requirements.md +0 -0
  159. {immich_api-0.2.3 → immich_api-0.2.4}/specs/immich-api/spec.md +0 -0
  160. {immich_api-0.2.3 → immich_api-0.2.4}/specs/immich-api/tasks.md +0 -0
  161. {immich_api-0.2.3 → immich_api-0.2.4}/specs/immich-api/test-spec.md +0 -0
  162. {immich_api-0.2.3 → immich_api-0.2.4}/tests/__init__.py +0 -0
  163. {immich_api-0.2.3 → immich_api-0.2.4}/tests/conftest.py +0 -0
  164. {immich_api-0.2.3 → immich_api-0.2.4}/tests/fixtures/native-client-budget.json +0 -0
  165. {immich_api-0.2.3 → immich_api-0.2.4}/tests/fixtures/operation-cases.json +0 -0
  166. {immich_api-0.2.3 → immich_api-0.2.4}/tests/operation_fixtures.py +0 -0
  167. {immich_api-0.2.3 → immich_api-0.2.4}/tests/parity_support.py +0 -0
  168. {immich_api-0.2.3 → immich_api-0.2.4}/tests/test_album_metadata.py +0 -0
  169. {immich_api-0.2.3 → immich_api-0.2.4}/tests/test_api_wrapper.py +0 -0
  170. {immich_api-0.2.3 → immich_api-0.2.4}/tests/test_auth.py +0 -0
  171. {immich_api-0.2.3 → immich_api-0.2.4}/tests/test_concept_parity.py +0 -0
  172. {immich_api-0.2.3 → immich_api-0.2.4}/tests/test_error_authority.py +0 -0
  173. {immich_api-0.2.3 → immich_api-0.2.4}/tests/test_immich_content.py +0 -0
  174. {immich_api-0.2.3 → immich_api-0.2.4}/tests/test_immich_mcp_validation.py +0 -0
  175. {immich_api-0.2.3 → immich_api-0.2.4}/tests/test_init_dynamics.py +0 -0
  176. {immich_api-0.2.3 → immich_api-0.2.4}/tests/test_kg_ingest.py +0 -0
  177. {immich_api-0.2.3 → immich_api-0.2.4}/tests/test_oauth_redirect_response.py +0 -0
  178. {immich_api-0.2.3 → immich_api-0.2.4}/tests/test_openapi_auth_provider.py +0 -0
  179. {immich_api-0.2.3 → immich_api-0.2.4}/tests/test_operation_parity.py +0 -0
  180. {immich_api-0.2.3 → immich_api-0.2.4}/tests/test_reviewed_secret_history.py +0 -0
  181. {immich_api-0.2.3 → immich_api-0.2.4}/tests/test_session_auth_isolation.py +0 -0
  182. {immich_api-0.2.3 → immich_api-0.2.4}/tests/test_startup.py +0 -0
  183. {immich_api-0.2.3 → immich_api-0.2.4}/tests/test_upstream_evidence.py +0 -0
@@ -0,0 +1,8 @@
1
+ [bumpversion]
2
+ current_version = 0.2.4
3
+ commit = True
4
+ tag = True
5
+
6
+ [bumpversion:file:pyproject.toml]
7
+ search = version = "{current_version}"
8
+ replace = version = "{new_version}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: immich-api
3
- Version: 0.2.3
3
+ Version: 0.2.4
4
4
  Summary: Immich Api API + MCP Server
5
5
  Author: Repository Maintainers
6
6
  License: MIT
@@ -16,11 +16,11 @@ Requires-Dist: rfc3986-validator<0.2,>=0.1.1
16
16
  Requires-Dist: rfc3339-validator<0.2,>=0.1.4
17
17
  Requires-Dist: jsonschema<5,>=4.23
18
18
  Requires-Dist: regex>=2026.9.29
19
- Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.4.1
19
+ Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.5.5
20
20
  Provides-Extra: mcp
21
- Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.4.1; extra == "mcp"
21
+ Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.5.5; extra == "mcp"
22
22
  Provides-Extra: all
23
- Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.4.1; extra == "all"
23
+ Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.5.5; extra == "all"
24
24
  Provides-Extra: test
25
25
  Requires-Dist: pytest-xdist>=3.6.0; extra == "test"
26
26
  Requires-Dist: pytest; extra == "test"
@@ -52,3 +52,11 @@ for module_name, extra_name in OPTIONAL_MODULES.items():
52
52
  globals()[f"_{extra_name.upper()}_AVAILABLE"] = False
53
53
 
54
54
  __all__.extend(["_MCP_AVAILABLE"])
55
+
56
+
57
+ from agent_connector_sdk.connector import Connector
58
+
59
+ connector = Connector(
60
+ tools="immich_api.mcp",
61
+ instructions="Immich Api API + MCP Server",
62
+ )
@@ -8,8 +8,6 @@ from __future__ import annotations
8
8
 
9
9
  from typing import Any
10
10
 
11
- from agent_connector_sdk.ingest.sources import IngestSourceDeclaration, IngestSourceSpec
12
-
13
11
  CONNECTOR: str = "immich"
14
12
 
15
13
  SOURCES: tuple[Any, ...] = ()
@@ -123,23 +121,3 @@ RESOURCES: tuple[dict[str, str], ...] = (
123
121
  "name": "ImmichAssetStack",
124
122
  },
125
123
  )
126
-
127
-
128
- def declaration() -> IngestSourceDeclaration:
129
- """The declaration the server assembles from this module."""
130
- specs: list[IngestSourceSpec] = []
131
- for item in SOURCES:
132
- for entry in item["connector_sources"]:
133
- body: dict[str, Any] = {
134
- k: v for k, v in entry.items() if k not in ("tool", "mapping")
135
- }
136
- spec = {**body, "tools": (entry["tool"],)}
137
- specs.append(IngestSourceSpec.model_validate(spec))
138
- return IngestSourceDeclaration.model_validate(
139
- {
140
- "connector": CONNECTOR,
141
- "sources": specs,
142
- "schema_mappings": SCHEMA_MAPPINGS,
143
- "resources": RESOURCES,
144
- }
145
- )
@@ -1,22 +1,29 @@
1
1
  import sys
2
+ from pathlib import Path
2
3
 
3
4
  from agent_connector_sdk.config import load_config
5
+ from agent_connector_sdk.connector_identity import connector_version
6
+ from agent_connector_sdk.mcp.content import ConnectorContent
4
7
  from agent_connector_sdk.mcp.server import create_mcp_server
5
8
  from agent_connector_sdk.mcp.tool_surface import register_tool_surface
6
9
 
7
10
  from . import mcp as tool_modules
8
11
 
9
- __version__ = "0.1.0"
12
+ __version__ = connector_version("immich_api")
10
13
 
11
14
 
12
15
  def get_mcp_instance(*, command_args=None):
13
16
  """Construct one SDK-governed server and its native package content."""
14
17
  load_config()
18
+ package_version = connector_version("immich_api")
15
19
  args, mcp, middlewares = create_mcp_server(
16
20
  name="Immich Api",
17
- version=__version__,
21
+ version=package_version,
18
22
  instructions="Immich Api API + MCP Server",
19
23
  command_args=command_args,
24
+ content=ConnectorContent.for_package(
25
+ "immich_api", Path(__file__).resolve().parent, package_version
26
+ ),
20
27
  )
21
28
  register_tool_surface(mcp, service="immich-api", tools_module=tool_modules)
22
29
  for middleware in middlewares:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: immich-api
3
- Version: 0.2.3
3
+ Version: 0.2.4
4
4
  Summary: Immich Api API + MCP Server
5
5
  Author: Repository Maintainers
6
6
  License: MIT
@@ -16,11 +16,11 @@ Requires-Dist: rfc3986-validator<0.2,>=0.1.1
16
16
  Requires-Dist: rfc3339-validator<0.2,>=0.1.4
17
17
  Requires-Dist: jsonschema<5,>=4.23
18
18
  Requires-Dist: regex>=2026.9.29
19
- Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.4.1
19
+ Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.5.5
20
20
  Provides-Extra: mcp
21
- Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.4.1; extra == "mcp"
21
+ Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.5.5; extra == "mcp"
22
22
  Provides-Extra: all
23
- Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.4.1; extra == "all"
23
+ Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.5.5; extra == "all"
24
24
  Provides-Extra: test
25
25
  Requires-Dist: pytest-xdist>=3.6.0; extra == "test"
26
26
  Requires-Dist: pytest; extra == "test"
@@ -1,5 +1,5 @@
1
1
  [agent_connector_sdk.connector]
2
- immich = immich_api
2
+ immich = immich_api:connector
3
3
 
4
4
  [agent_utilities.ontology_providers]
5
5
  immich-api = immich_api.ontology
@@ -2,13 +2,13 @@ rfc3986-validator<0.2,>=0.1.1
2
2
  rfc3339-validator<0.2,>=0.1.4
3
3
  jsonschema<5,>=4.23
4
4
  regex>=2026.9.29
5
- agent-connector-sdk[mcp]<1.0.0,>=0.4.1
5
+ agent-connector-sdk[mcp]<1.0.0,>=0.5.5
6
6
 
7
7
  [all]
8
- agent-connector-sdk[mcp]<1.0.0,>=0.4.1
8
+ agent-connector-sdk[mcp]<1.0.0,>=0.5.5
9
9
 
10
10
  [mcp]
11
- agent-connector-sdk[mcp]<1.0.0,>=0.4.1
11
+ agent-connector-sdk[mcp]<1.0.0,>=0.5.5
12
12
 
13
13
  [test]
14
14
  pytest-xdist>=3.6.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "immich-api"
7
- version = "0.2.3"
7
+ version = "0.2.4"
8
8
  description = "Immich Api API + MCP Server"
9
9
  readme = "README.md"
10
10
  classifiers = [ "Development Status :: 4 - Beta", "License :: OSI Approved :: MIT License", "Environment :: Console", "Operating System :: POSIX :: Linux", "Programming Language :: Python :: 3",]
@@ -14,7 +14,7 @@ dependencies = [
14
14
  "rfc3339-validator>=0.1.4,<0.2",
15
15
  "jsonschema>=4.23,<5",
16
16
  "regex>=2026.9.29",
17
- "agent-connector-sdk[mcp]>=0.4.1,<1.0.0",
17
+ "agent-connector-sdk[mcp]>=0.5.5,<1.0.0",
18
18
  ]
19
19
  [[project.authors]]
20
20
  name = "Repository Maintainers"
@@ -23,9 +23,9 @@ name = "Repository Maintainers"
23
23
  text = "MIT"
24
24
 
25
25
  [project.optional-dependencies]
26
- mcp = [ "agent-connector-sdk[mcp]>=0.4.1,<1.0.0",]
26
+ mcp = [ "agent-connector-sdk[mcp]>=0.5.5,<1.0.0",]
27
27
  all = [
28
- "agent-connector-sdk[mcp]>=0.4.1,<1.0.0",
28
+ "agent-connector-sdk[mcp]>=0.5.5,<1.0.0",
29
29
  ]
30
30
  test = [
31
31
  "pytest-xdist>=3.6.0", "pytest", "pytest-asyncio", "pytest-cov",]
@@ -48,7 +48,7 @@ immich-api = "immich_api.ontology"
48
48
 
49
49
  # The one declared connector identity: the fleet name (SDK-CONNECTOR-CONTROL-R071).
50
50
  [project.entry-points."agent_connector_sdk.connector"]
51
- immich = "immich_api"
51
+ immich = "immich_api:connector"
52
52
 
53
53
  [tool.uv.workspace]
54
54
  members = ["."]
@@ -45,6 +45,22 @@ def sync_commands(uv, python, bindings, *, root):
45
45
  ]
46
46
 
47
47
 
48
+ def install_project(root, python, uv, *, env):
49
+ """Install editable project metadata without resolving source dependencies."""
50
+ command = [
51
+ uv,
52
+ "pip",
53
+ "install",
54
+ "--python",
55
+ str(python),
56
+ "--no-deps",
57
+ "--editable",
58
+ str(root),
59
+ ]
60
+ subprocess.run(command, cwd=root, env=env, check=True)
61
+ return command
62
+
63
+
48
64
  def add_source_paths(root, python, sources, *, env):
49
65
  purelib = Path(
50
66
  run(
@@ -79,6 +95,10 @@ def inspect_environment(root, python, *, bindings, sources, env):
79
95
  probe = """
80
96
  import importlib, importlib.metadata, json, pathlib, sys
81
97
  expected = json.loads(sys.argv[1])
98
+ project = json.loads(sys.argv[3])
99
+ distribution = importlib.metadata.distribution(project["name"])
100
+ if distribution.version != project["version"]:
101
+ raise ValueError("Installed project metadata differs from reviewed pyproject.toml")
82
102
  prefix = pathlib.Path(sys.prefix).resolve()
83
103
  if prefix != pathlib.Path(sys.argv[2]).resolve():
84
104
  raise ValueError('Unexpected interpreter environment')
@@ -103,6 +123,9 @@ print(json.dumps({'executable': sys.executable, 'python': sys.version, 'source_i
103
123
  probe,
104
124
  json.dumps(expected),
105
125
  str(root / ".ci/connector-venv"),
126
+ json.dumps(
127
+ tomllib.loads((root / "pyproject.toml").read_text())["project"]
128
+ ),
106
129
  ],
107
130
  root=root,
108
131
  env=env,
@@ -189,6 +212,7 @@ def prepare(root, *, uv="uv", github=False):
189
212
  / "connector-venv"
190
213
  / ("Scripts/python.exe" if os.name == "nt" else "bin/python")
191
214
  )
215
+ commands.append(install_project(root, python, uv, env=env))
192
216
  add_source_paths(root, python, sources, env=env)
193
217
  environment = inspect_environment(
194
218
  root, python, bindings=bindings, sources=sources, env=env
@@ -12,10 +12,12 @@
12
12
  "title": "Default content",
13
13
  "delivery_state": "VERIFIED",
14
14
  "landed_in": [
15
+ "4ea81792f111",
16
+ "5f862f905963",
15
17
  "9c7f32a3d826"
16
18
  ],
17
19
  "verified_by": [
18
- "tests/test_default_content_surfaces.py:15"
20
+ "tests/test_default_content_surfaces.py:17"
19
21
  ]
20
22
  }
21
23
  ]
@@ -68,11 +68,11 @@
68
68
  "47656ecb1833"
69
69
  ],
70
70
  "verified_by": [
71
- "tests/test_generated_schema_policy.py:18",
72
71
  "tests/test_oauth_redirect_response.py:26",
73
- "tests/test_operation_parity.py:31",
72
+ "tests/test_operation_parity.py:34",
74
73
  "tests/test_reviewed_secret_history.py:13",
75
- "tests/test_session_auth_isolation.py:17"
74
+ "tests/test_session_auth_isolation.py:17",
75
+ "tests/test_upstream_evidence.py:14"
76
76
  ]
77
77
  },
78
78
  {
@@ -84,7 +84,7 @@
84
84
  "f155d6a2ee97"
85
85
  ],
86
86
  "verified_by": [
87
- "tests/test_fleet_name.py:35"
87
+ "tests/test_fleet_name.py:34"
88
88
  ]
89
89
  }
90
90
  ]
@@ -0,0 +1,198 @@
1
+ """CONN-IMMICH-API-CONNECTOR-CONTENT-R001: the server lists its packaged skills, ontology and prompts by default."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ import hashlib
7
+ import importlib
8
+ from importlib.metadata import version
9
+ from pathlib import Path
10
+
11
+ import pytest
12
+ from fastmcp import Client
13
+
14
+ PACKAGE = "immich_api"
15
+ ROOT = Path(list(importlib.import_module(PACKAGE).__path__)[0])
16
+
17
+ pytestmark = pytest.mark.spec("CONN-IMMICH-API-CONNECTOR-CONTENT-R001")
18
+
19
+
20
+ def _server():
21
+ from immich_api.mcp_server import build_server
22
+
23
+ return build_server(command_args=["--transport", "stdio", "--auth-type", "none"])
24
+
25
+
26
+ async def _listings():
27
+ async with Client(_server(), mode="legacy") as client:
28
+ initialized = await client.initialize()
29
+ assert initialized.server_info.version == version("immich-api")
30
+ resources = {str(r.uri) for r in await client.list_resources()}
31
+ prompts = {p.name for p in await client.list_prompts()}
32
+ for uri in resources:
33
+ if uri.startswith(("ontology://", "shapes://")):
34
+ relative = uri.split("/", 3)[-1]
35
+ directory = (
36
+ ROOT
37
+ / "ontology"
38
+ / ("shapes" if uri.startswith("shapes://") else "")
39
+ )
40
+ actual = await client.read_resource(uri)
41
+ assert actual[0].text.encode() == (directory / relative).read_bytes()
42
+ return resources, prompts
43
+
44
+
45
+ def test_default_content_surfaces() -> None:
46
+ resources, prompts = asyncio.run(_listings())
47
+ if list(ROOT.glob("skills/*/SKILL.md")):
48
+ assert any(u.startswith("skill://") for u in resources)
49
+ if list(ROOT.glob("ontology/*.ttl")):
50
+ assert any(u.startswith("ontology://immich/") for u in resources)
51
+ for path in ROOT.glob("prompts/*.json"):
52
+ if not path.name.startswith("_"):
53
+ assert path.stem in prompts
54
+
55
+
56
+ def test_publication_preserves_tools(monkeypatch) -> None:
57
+ module = importlib.import_module("immich_api.mcp_server")
58
+
59
+ async def tools(server):
60
+ async with Client(server) as client:
61
+ return [tool.model_dump(mode="json") for tool in await client.list_tools()]
62
+
63
+ published = asyncio.run(tools(_server()))
64
+ factory = module.create_mcp_server
65
+
66
+ def tools_only(*args, **kwargs):
67
+ kwargs.pop("content")
68
+ return factory(*args, **kwargs)
69
+
70
+ monkeypatch.setattr(module, "create_mcp_server", tools_only)
71
+ assert asyncio.run(tools(_server())) == published
72
+
73
+
74
+ def test_production_pack_includes_packaged_ontology_and_shapes() -> None:
75
+ from agent_connector_sdk.artifacts.pack import build_content_pack
76
+ from agent_connector_sdk.artifacts.resources import ResourceArtifactKind
77
+ from agent_connector_sdk.ports.session import TransportEndpoint
78
+ from agent_connector_sdk.transports.mcp import McpTransport
79
+
80
+ async def capture():
81
+ endpoint = TransportEndpoint(in_process=_server())
82
+ async with McpTransport().session(endpoint) as session:
83
+ return await build_content_pack(
84
+ session, connector="immich", kinds=(ResourceArtifactKind(),)
85
+ )
86
+
87
+ pack = asyncio.run(capture())
88
+ assert pack.server_package_version == version("immich-api")
89
+ uris = {str(entry.uri) for entry in pack.archive.entries}
90
+ for entry in pack.archive.entries:
91
+ if entry.uri.startswith(("ontology://", "shapes://")):
92
+ name = entry.uri.rsplit("/", 1)[-1]
93
+ directory = (
94
+ ROOT
95
+ / "ontology"
96
+ / ("shapes" if entry.uri.startswith("shapes://") else "")
97
+ )
98
+ assert (
99
+ entry.body.sha256
100
+ == hashlib.sha256((directory / name).read_bytes()).hexdigest()
101
+ )
102
+ for path in ROOT.glob("ontology/*.ttl"):
103
+ assert f"ontology://immich/{path.name}" in uris
104
+ for path in ROOT.glob("ontology/shapes/*.ttl"):
105
+ assert f"shapes://immich/{path.name}" in uris
106
+
107
+
108
+ @pytest.fixture(autouse=True)
109
+ def _no_outbound_network(monkeypatch):
110
+ import socket
111
+
112
+ def refuse(*_args, **_kwargs):
113
+ raise AssertionError("content publication must not contact an external system")
114
+
115
+ monkeypatch.setenv("MCP_FLEET_REGISTRATION", "false")
116
+ monkeypatch.setattr(socket.socket, "connect", refuse)
117
+
118
+
119
+ def test_sdk_floor_supports_content_identity_and_current_pack_protocol() -> None:
120
+ import tomllib
121
+
122
+ from packaging.requirements import Requirement
123
+
124
+ project = tomllib.loads((ROOT.parent / "pyproject.toml").read_text())["project"]
125
+ declared = list(project.get("dependencies", []))
126
+ for extra in project.get("optional-dependencies", {}).values():
127
+ declared.extend(extra)
128
+ sdk = [
129
+ Requirement(value)
130
+ for value in declared
131
+ if value.startswith("agent-connector-sdk")
132
+ ]
133
+ assert sdk
134
+ for requirement in sdk:
135
+ assert requirement.specifier.contains("0.5.5")
136
+ assert not requirement.specifier.contains("0.5.4")
137
+
138
+
139
+ def test_sdk_owned_declaration_survives_resource_and_pack_capture() -> None:
140
+ import json
141
+
142
+ from agent_connector_sdk.artifacts.pack import build_content_pack
143
+ from agent_connector_sdk.artifacts.resources import ResourceArtifactKind
144
+ from agent_connector_sdk.ingest.live_declaration import load_declaration
145
+ from agent_connector_sdk.ports.session import TransportEndpoint
146
+ from agent_connector_sdk.transports.mcp import McpTransport
147
+
148
+ from immich_api import connector_sources
149
+
150
+ assert connector_sources.SOURCES == ()
151
+ expected = {
152
+ "connector": "immich",
153
+ "sources": [],
154
+ "schema_mappings": connector_sources.SCHEMA_MAPPINGS,
155
+ "resources": list(connector_sources.RESOURCES),
156
+ }
157
+ assert (
158
+ load_declaration(PACKAGE).model_dump(mode="json", exclude_unset=True)
159
+ == expected
160
+ )
161
+
162
+ async def capture():
163
+ server = _server()
164
+ async with Client(server) as client:
165
+ live = json.loads(
166
+ (await client.read_resource("connector://resources"))[0].text
167
+ )
168
+ async with McpTransport().session(
169
+ TransportEndpoint(in_process=server)
170
+ ) as session:
171
+ pack = await build_content_pack(
172
+ session, connector="immich", kinds=(ResourceArtifactKind(),)
173
+ )
174
+ entry = next(
175
+ e for e in pack.archive.entries if e.uri == "connector://resources"
176
+ )
177
+ section = entry.body
178
+ packed = json.loads(
179
+ pack.archive.data[section.offset : section.offset + section.length]
180
+ )
181
+ return live, packed
182
+
183
+ for declaration in asyncio.run(capture()):
184
+ for key, value in expected.items():
185
+ assert declaration[key] == value
186
+
187
+
188
+ def test_declared_connector_preserves_the_production_tool_surface() -> None:
189
+ from agent_connector_sdk.connector import build_server
190
+
191
+ async def tools(server):
192
+ async with Client(server) as client:
193
+ return [tool.model_dump(mode="json") for tool in await client.list_tools()]
194
+
195
+ _, declared = build_server(
196
+ PACKAGE, command_args=["--transport", "stdio", "--auth-type", "none"]
197
+ )
198
+ assert asyncio.run(tools(declared)) == asyncio.run(tools(_server()))
@@ -35,7 +35,7 @@ def _call_connectors(path: Path) -> list[str]:
35
35
  def test_connector_name_is_the_fleet_name() -> None:
36
36
  pyproject = tomllib.loads((ROOT / "pyproject.toml").read_text(encoding="utf-8"))
37
37
  assert pyproject["project"]["entry-points"]["agent_connector_sdk.connector"] == {
38
- FLEET: "immich_api"
38
+ FLEET: "immich_api:connector"
39
39
  }
40
40
  assert connector_name("immich_api") == FLEET
41
41
  for module in sorted(PACKAGE.glob("*.py")):
@@ -1,12 +0,0 @@
1
- [bumpversion]
2
- current_version = 0.2.3
3
- commit = True
4
- tag = True
5
-
6
- [bumpversion:file:pyproject.toml]
7
- search = version = "{current_version}"
8
- replace = version = "{new_version}"
9
-
10
- [bumpversion:file(dockerpin0):docker/Dockerfile]
11
- search = immich-api[mcp]=={current_version}
12
- replace = immich-api[mcp]=={new_version}
@@ -1,43 +0,0 @@
1
- """CONN-IMMICH-API-CONNECTOR-CONTENT-R001: the server lists its packaged skills, ontology and prompts by default."""
2
-
3
- from __future__ import annotations
4
-
5
- import asyncio
6
- import importlib
7
- from pathlib import Path
8
-
9
- import pytest
10
- from fastmcp import Client
11
-
12
- PACKAGE = "immich_api"
13
- ROOT = Path(list(importlib.import_module(PACKAGE).__path__)[0])
14
-
15
- pytestmark = pytest.mark.spec("CONN-IMMICH-API-CONNECTOR-CONTENT-R001")
16
-
17
-
18
- def _server():
19
- namespace = {"__name__": PACKAGE + ".mcp_server"}
20
- exec(
21
- "from agent_connector_sdk.mcp.server import create_mcp_server\n"
22
- "result = create_mcp_server('immich', version='0', command_args=[])",
23
- namespace,
24
- )
25
- return namespace["result"][1]
26
-
27
-
28
- async def _listings():
29
- async with Client(_server()) as client:
30
- resources = {str(r.uri) for r in await client.list_resources()}
31
- prompts = {p.name for p in await client.list_prompts()}
32
- return resources, prompts
33
-
34
-
35
- def test_default_content_surfaces() -> None:
36
- resources, prompts = asyncio.run(_listings())
37
- if list(ROOT.glob("skills/*/SKILL.md")):
38
- assert any(u.startswith("skill://") for u in resources)
39
- if list(ROOT.glob("ontology/*.ttl")):
40
- assert any(u.startswith("ontology://immich/") for u in resources)
41
- for path in ROOT.glob("prompts/*.json"):
42
- if not path.name.startswith("_"):
43
- assert path.stem in prompts
File without changes
File without changes
File without changes
File without changes