python-alfresco-mcp-server 1.2.0__tar.gz → 1.2.1__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 (71) hide show
  1. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/CHANGELOG.md +172 -161
  2. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/PKG-INFO +18 -4
  3. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/README.md +15 -1
  4. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/config.py +145 -139
  5. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/utils/connection.py +14 -2
  6. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/pyproject.toml +2 -2
  7. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/sample-dot-env.txt +63 -58
  8. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/.gitignore +0 -0
  9. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/LICENSE +0 -0
  10. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/__init__.py +0 -0
  11. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/fastmcp_server.py +0 -0
  12. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/prompts/__init__.py +0 -0
  13. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/prompts/search_and_analyze.py +0 -0
  14. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/resources/__init__.py +0 -0
  15. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/resources/repository_resources.py +0 -0
  16. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/tools/__init__.py +0 -0
  17. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/tools/core/__init__.py +0 -0
  18. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/tools/core/browse_repository.py +0 -0
  19. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/tools/core/cancel_checkout.py +0 -0
  20. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/tools/core/checkin_document.py +0 -0
  21. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/tools/core/checkout_document.py +0 -0
  22. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/tools/core/create_folder.py +0 -0
  23. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/tools/core/delete_node.py +0 -0
  24. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/tools/core/download_document.py +0 -0
  25. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/tools/core/get_node_properties.py +0 -0
  26. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/tools/core/update_node_properties.py +0 -0
  27. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/tools/core/upload_document.py +0 -0
  28. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/tools/search/__init__.py +0 -0
  29. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/tools/search/advanced_search.py +0 -0
  30. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/tools/search/cmis_search.py +0 -0
  31. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/tools/search/search_by_metadata.py +0 -0
  32. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/tools/search/search_content.py +0 -0
  33. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/utils/__init__.py +0 -0
  34. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/utils/file_type_analysis.py +0 -0
  35. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/alfresco_mcp_server/utils/json_utils.py +0 -0
  36. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/claude-desktop-configs/claude-desktop-config-pipx-macos.json +0 -0
  37. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/claude-desktop-configs/claude-desktop-config-pipx-windows.json +0 -0
  38. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/claude-desktop-configs/claude-desktop-config-uv-macos.json +0 -0
  39. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/claude-desktop-configs/claude-desktop-config-uv-windows.json +0 -0
  40. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/claude-desktop-configs/claude-desktop-config-uvx-macos.json +0 -0
  41. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/claude-desktop-configs/claude-desktop-config-uvx-windows.json +0 -0
  42. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/config.yaml +0 -0
  43. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/docs/README.md +0 -0
  44. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/docs/api_reference.md +0 -0
  45. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/docs/claude_desktop_setup.md +0 -0
  46. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/docs/client_configurations.md +0 -0
  47. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/docs/configuration_guide.md +0 -0
  48. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/docs/install_with_pip_pipx.md +0 -0
  49. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/docs/mcp_inspector_setup.md +0 -0
  50. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/docs/quick_start_guide.md +0 -0
  51. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/docs/testing_guide.md +0 -0
  52. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/docs/troubleshooting.md +0 -0
  53. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/examples/README.md +0 -0
  54. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/examples/batch_operations.py +0 -0
  55. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/examples/document_lifecycle.py +0 -0
  56. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/examples/error_handling.py +0 -0
  57. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/examples/examples_summary.md +0 -0
  58. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/examples/quick_start.py +0 -0
  59. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/examples/transport_examples.py +0 -0
  60. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/mcp-inspector-configs/mcp-inspector-http-pipx-config.json +0 -0
  61. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/mcp-inspector-configs/mcp-inspector-http-uv-config.json +0 -0
  62. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/mcp-inspector-configs/mcp-inspector-http-uvx-config.json +0 -0
  63. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/mcp-inspector-configs/mcp-inspector-stdio-pipx-config.json +0 -0
  64. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/mcp-inspector-configs/mcp-inspector-stdio-uv-config.json +0 -0
  65. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/mcp-inspector-configs/mcp-inspector-stdio-uvx-config.json +0 -0
  66. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/prompts-for-claude.md +0 -0
  67. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/pytest.ini +0 -0
  68. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/run_server.py +0 -0
  69. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/scripts/run_tests.py +0 -0
  70. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/scripts/test.bat +0 -0
  71. {python_alfresco_mcp_server-1.2.0 → python_alfresco_mcp_server-1.2.1}/uv.lock +0 -0
@@ -1,162 +1,173 @@
1
- # Changelog
2
-
3
- All notable changes to this project will be documented in this file.
4
-
5
- The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
- and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
-
8
- ## [Unreleased]
9
-
10
- ## [1.2.0] - 2026-08-05
11
-
12
- ### Added
13
- - **Alfresco auth methods** (`ALFRESCO_AUTH_METHOD` = `basic` | `ticket` | `oauth2`): the server can now authenticate to Alfresco via HTTP Basic, a login ticket, or an OAuth2/OIDC bearer token (Alfresco `identity-service`), via `python-alfresco-api` 1.2.1+ `OAuth2AuthUtil`, configured with `ALFRESCO_OAUTH2_*` env vars. Documents the setup in the README **Authentication** section (addresses #2). Live-tested basic/ticket/oauth2 end-to-end.
14
- - **Optional MCP transport authentication** (`MCP_TRANSPORT_AUTH=true`): secures the MCP server itself — HTTP/SSE callers must present an OAuth2 bearer token, validated against an OIDC IdP's JWKS (FastMCP JWT verifier). Off by default; stdio unaffected. Env: `MCP_AUTH_JWKS_URI` / `MCP_AUTH_ISSUER` / `MCP_AUTH_AUDIENCE`.
15
- - **`download_document` `destination_dir`**: optional custom download folder (default `~/Downloads`). Thanks [@jeremie-lesage](https://github.com/jeremie-lesage) ([#1](https://github.com/stevereiner/python-alfresco-mcp-server/pull/1)).
16
-
17
- ### Changed
18
- - **Version 1.2.0** of this package; requires **python-alfresco-api >= 1.2.1** (OAuth2/OIDC auth, `VersionsClient` fix, and OAuth2 service-account `displayName` handling — see below).
19
- - **Config layout**: moved Claude Desktop sample configs into [`claude-desktop-configs/`](./claude-desktop-configs/) and MCP Inspector samples into [`mcp-inspector-configs/`](./mcp-inspector-configs/); docs and README updated accordingly.
20
- - **FastMCP 3 upgrade**: bumped dependency from FastMCP 2.x to `fastmcp>=3.4.5,<4`. Server code is compatible with FastMCP 3's API (`list_tools()` / `list_resources()` / `list_prompts()`); JWT transport auth now uses `JWTVerifier` directly. See [FastMCP 2 → 3 upgrade guide](https://gofastmcp.com/getting-started/upgrading/from-fastmcp-2).
21
- - **Packaging**: switched build backend from setuptools to hatchling (same as python-alfresco-api) for quieter `uv build` output.
22
-
23
- ### Fixed
24
- - **checkout_document**: local download filename puts the node ID before the extension (`name_<nodeId>.txt`) instead of after it (`name.txt_<nodeId>`), so editors keep the correct file type.
25
- - **OAuth2 service-account nodes** (via **python-alfresco-api 1.2.1**): Keycloak client-credentials authenticates as a JIT Alfresco user with no display name, so Alfresco returns `createdByUser` / `modifiedByUser` / `owner` without `displayName` and the generated `UserInfo.from_dict` raised `KeyError('displayName')` (breaking `download_document` and other `nodes.get` tools). Fixed upstream with a runtime shim (`python_alfresco_api/_compat.py`, applied at package import) that defaults missing `displayName` to `id` for core and search `UserInfo` — outside `raw_clients/` so it survives client re-generation. Basic/ticket and user-based OAuth2 tokens were unaffected.
26
-
27
- ## [1.1.0] - 2025-01-25
28
-
29
- ### Alfresco_MCP_Server dir code changes for v1.1
30
- - **Code Split**: Refactored from monolithic single file to modular structure with separate files
31
- - **Directory Structure**: Reorganized from flat to hierarchical structure
32
- - `tools/search/` - 4 search-related tools
33
- - `tools/core/` - 11 core management tools
34
- - `resources/` - Repository information
35
- - `prompts/` - AI templates
36
- - `utils/` - Shared utilities
37
- - fix: implement Windows UTF-8 encoding support (emoji character encoding)
38
- - get to work with python-alfresco-api 1.1.x
39
- - add imports and __all__ to get files included in packaging
40
-
41
- ### UV Package Management Support
42
- - **Rust-based Performance**: UV provides faster dependency resolution and package management
43
- - **Automatic Environment Management**: UV handles virtual environment creation and activation
44
- - **Simplified Installation**: One-command setup replaces multi-step manual process
45
- - **Cross-platform Compatibility**: Consistent behavior across Windows, macOS, and Linux
46
-
47
- ### PyPI Distribution
48
- - **Direct Installation**: Available via `pip install python-alfresco-mcp-server`
49
- - **UV Integration**: Compatible with `uv pip install python-alfresco-mcp-server`
50
- - **Immediate Usage**: Run server directly after installation without source code
51
-
52
- ### Update Tests for v1.1
53
- - `test: transform test suite from 76+ failures to 143/143 passing`
54
- - `test: add comprehensive live integration testing with 21 Alfresco tests`
55
- - `test: implement cross-platform emoji handling for Windows compatibility`
56
- - `test: enhance coverage reporting with HTML output`
57
- - `test: add automated testing for all manual scenarios`
58
- - `test: implement strip_emojis() function for Windows compatibility`
59
- - `test: add comprehensive unit test coverage (122 tests)`
60
- - `test: fix test import paths for modular architecture`
61
-
62
- ### MCP Clients: config files added for v1.1
63
- - Added Claude Desktop and MCP Inspector config files
64
- - `config: added claude-desktop-config-developer-windows.json with UV support`
65
- - `config: added claude-desktop-config-developer-macos.json with UV support`
66
- - `config: added claude-desktop-config-user-windows.json`
67
- - `config: added claude-desktop-config-user-macos.json`
68
- - `config: added Windows UTF-8 encoding variables to windows configs`
69
- - `config: added mcp-inspector-http-config.json for HTTP transport using uv`
70
- - `config: added mcp-inspector-stdio-config.json for STDIO transport using uv`
71
- - 'examples: prompts-for-claude.md has example prompt text to test tools
72
-
73
- ### Update docs for v1.1
74
- - `docs: create comprehensive CHANGELOG.md for v1.0.0 and v1.1.0`
75
- - `docs: update quick start guide for UV approach`
76
- - 'docs: api_reference.md added details for all tools, etc
77
- - `docs: added claude_desktop_setup.md, mcp_inspector_setup.md, and client_configurations.md
78
-
79
- ### Documentation Updates for v1.1
80
- - **Installation Instructions**: Added PyPI installation methods
81
- - **Configuration Examples**: Updated for UV approach
82
- - **Testing Procedures**: Comprehensive test execution guidance
83
- - **Troubleshooting**: Enhanced problem resolution guidance
84
-
85
- ### Update Readme for v1.1
86
- - added install from PyPI
87
- - added how to install UV package manager
88
- - added claude desktop and mcp inspector setup sections
89
- - reword technical sections for accuracy
90
- - add v1.1 list of changes, depend on python-alfresco 1.1.1, python 3.10+
91
- - added how to install Alfresco Community from github
92
-
93
- ### Update project files and misc root dir files for v1.1
94
- - gitignore now ignores cursor memory and memory-bank dir, keep .vscode/mcp.json
95
- - config.yaml has changed alfresco_url to have base_url, added timeout, added
96
- mcp server name and version confg
97
- - MANIFEST.in added for proper package distrubution config
98
- - pyproject.toml change to have v1.1.0 release, pypi distrib settings, remove
99
- fastMCP version restriction, update to require python 3.10 or greater, add
100
- pypi keyword and topic, settings, project urls for pypi, configure setuptools
101
- for includes, excludes
102
- - run_server.py script added
103
- - .vscode/mcp.json uses run_server.py for debugging mcp server
104
- - uv.lock add now that use uv, and uv lock --upgrade updated v0.12.5 from v0.12.4 of ruff
105
-
106
- ### Fixes for pyproject.toml for v1.1
107
- - require python-alfresco-api >= 1.1.1 not 1.0.0 in dependencies
108
- - have python 3.10 instead of 3.8 for tool.mypy, and py310 not py38 for tool.ruff and tool.black
109
-
110
- ### Example Code Updates for v1.1
111
- - `examples: update transport examples for UV approach`
112
- - `examples: enhance document lifecycle example`
113
- - `examples: add UV-specific installation examples`
114
- - `examples: update batch operations for improved performance`
115
- - `examples: refactor error handling patterns`
116
-
117
- ### Requirements
118
- - **Python Versions**: 3.10+ (unchanged)
119
- - **python-alfresco-api**: >= 1.1.1 (updated requirement)
120
- - **FastMCP**: Tested with v2.10.6
121
-
122
- ### Tested
123
- - **Alfresco Versions**: Community 25.1 (tested), Enterprise (not tested in v1.1)
124
- - **Operating Systems**:
125
- - Windows (tested)
126
- - macOS (needs testing)
127
- - Linux (needs testing, note: no Claude Desktop support on Linux)
128
- - **MCP Clients**:
129
- - Claude Desktop (tested and validated)
130
- - MCP Inspector (tested and validated)
131
- - Cursor (configuration provided, not tested in v1.1)
132
- - Claude Code (configuration provided, not tested in v1.1)
133
-
134
- ## [1.0.0] - 2024-06-24
135
-
136
- ### Added
137
- - Initial FastMCP 2.0 server implementation
138
- - 15 content management tools across search and core operations
139
- - Full text search with wildcard support
140
- - Advanced search using AFTS query language
141
- - Metadata search with property-based queries
142
- - CMIS SQL search capabilities
143
- - Complete document lifecycle management (upload, download, checkout, checkin)
144
- - Version management with major/minor version support
145
- - Folder operations and repository browsing
146
- - Property management for documents and folders
147
- - Multiple transport protocols (STDIO, HTTP, SSE)
148
- - Configuration via environment variables and .env files
149
- - Claude Desktop integration with Windows and macOS configs
150
- - MCP Inspector support for development testing
151
- - Comprehensive documentation and examples
152
- - Testing framework with unit and integration tests
153
- - Error handling and recovery patterns
154
- - Repository discovery and status reporting
155
-
156
- ### Technical Implementation
157
- - python-alfresco-api integration for content services access
158
- - Pydantic v2 models for type safety
159
- - Async support for concurrent operations
160
- - Connection pooling and authentication management
161
- - Progress reporting and context logging
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [1.2.1] - 2026-09-29
11
+
12
+ ### Added
13
+ - **`ALFRESCO_TICKET`**: with `ALFRESCO_AUTH_METHOD=ticket`, a login ticket you already hold is used as-is instead of being fetched from a username and password — so the server can run with no Alfresco password configured at all. Leave it unset and ticket auth behaves as before (acquired from `ALFRESCO_USERNAME` / `ALFRESCO_PASSWORD`). A supplied ticket is never renewed, so it stops working when it expires.
14
+
15
+ ### Changed
16
+ - Requires **python-alfresco-api >= 1.2.2** for the ticket pass-through above.
17
+
18
+ ### Fixed
19
+ - **Integration test `test_search_shared_folder`**: now passes `node_type="cm:folder"`. `search_content` searches documents (`cm:content`) by default, so the search never matched the Shared folder and the test failed.
20
+
21
+ ## [1.2.0] - 2026-08-05
22
+
23
+ ### Added
24
+ - **Alfresco auth methods** (`ALFRESCO_AUTH_METHOD` = `basic` | `ticket` | `oauth2`): the server can now authenticate to Alfresco via HTTP Basic, a login ticket, or an OAuth2/OIDC bearer token (Alfresco `identity-service`), via `python-alfresco-api` 1.2.1+ `OAuth2AuthUtil`, configured with `ALFRESCO_OAUTH2_*` env vars. Documents the setup in the README **Authentication** section (addresses #2). Live-tested basic/ticket/oauth2 end-to-end.
25
+ - **Optional MCP transport authentication** (`MCP_TRANSPORT_AUTH=true`): secures the MCP server itself — HTTP/SSE callers must present an OAuth2 bearer token, validated against an OIDC IdP's JWKS (FastMCP JWT verifier). Off by default; stdio unaffected. Env: `MCP_AUTH_JWKS_URI` / `MCP_AUTH_ISSUER` / `MCP_AUTH_AUDIENCE`.
26
+ - **`download_document` `destination_dir`**: optional custom download folder (default `~/Downloads`). Thanks [@jeremie-lesage](https://github.com/jeremie-lesage) ([#1](https://github.com/stevereiner/python-alfresco-mcp-server/pull/1)).
27
+
28
+ ### Changed
29
+ - **Version 1.2.0** of this package; requires **python-alfresco-api >= 1.2.1** (OAuth2/OIDC auth, `VersionsClient` fix, and OAuth2 service-account `displayName` handling — see below).
30
+ - **Config layout**: moved Claude Desktop sample configs into [`claude-desktop-configs/`](./claude-desktop-configs/) and MCP Inspector samples into [`mcp-inspector-configs/`](./mcp-inspector-configs/); docs and README updated accordingly.
31
+ - **FastMCP 3 upgrade**: bumped dependency from FastMCP 2.x to `fastmcp>=3.4.5,<4`. Server code is compatible with FastMCP 3's API (`list_tools()` / `list_resources()` / `list_prompts()`); JWT transport auth now uses `JWTVerifier` directly. See [FastMCP 2 → 3 upgrade guide](https://gofastmcp.com/getting-started/upgrading/from-fastmcp-2).
32
+ - **Packaging**: switched build backend from setuptools to hatchling (same as python-alfresco-api) for quieter `uv build` output.
33
+
34
+ ### Fixed
35
+ - **checkout_document**: local download filename puts the node ID before the extension (`name_<nodeId>.txt`) instead of after it (`name.txt_<nodeId>`), so editors keep the correct file type.
36
+ - **OAuth2 service-account nodes** (via **python-alfresco-api 1.2.1**): Keycloak client-credentials authenticates as a JIT Alfresco user with no display name, so Alfresco returns `createdByUser` / `modifiedByUser` / `owner` without `displayName` and the generated `UserInfo.from_dict` raised `KeyError('displayName')` (breaking `download_document` and other `nodes.get` tools). Fixed upstream with a runtime shim (`python_alfresco_api/_compat.py`, applied at package import) that defaults missing `displayName` to `id` for core and search `UserInfo` — outside `raw_clients/` so it survives client re-generation. Basic/ticket and user-based OAuth2 tokens were unaffected.
37
+
38
+ ## [1.1.0] - 2025-01-25
39
+
40
+ ### Alfresco_MCP_Server dir code changes for v1.1
41
+ - **Code Split**: Refactored from monolithic single file to modular structure with separate files
42
+ - **Directory Structure**: Reorganized from flat to hierarchical structure
43
+ - `tools/search/` - 4 search-related tools
44
+ - `tools/core/` - 11 core management tools
45
+ - `resources/` - Repository information
46
+ - `prompts/` - AI templates
47
+ - `utils/` - Shared utilities
48
+ - fix: implement Windows UTF-8 encoding support (emoji character encoding)
49
+ - get to work with python-alfresco-api 1.1.x
50
+ - add imports and __all__ to get files included in packaging
51
+
52
+ ### UV Package Management Support
53
+ - **Rust-based Performance**: UV provides faster dependency resolution and package management
54
+ - **Automatic Environment Management**: UV handles virtual environment creation and activation
55
+ - **Simplified Installation**: One-command setup replaces multi-step manual process
56
+ - **Cross-platform Compatibility**: Consistent behavior across Windows, macOS, and Linux
57
+
58
+ ### PyPI Distribution
59
+ - **Direct Installation**: Available via `pip install python-alfresco-mcp-server`
60
+ - **UV Integration**: Compatible with `uv pip install python-alfresco-mcp-server`
61
+ - **Immediate Usage**: Run server directly after installation without source code
62
+
63
+ ### Update Tests for v1.1
64
+ - `test: transform test suite from 76+ failures to 143/143 passing`
65
+ - `test: add comprehensive live integration testing with 21 Alfresco tests`
66
+ - `test: implement cross-platform emoji handling for Windows compatibility`
67
+ - `test: enhance coverage reporting with HTML output`
68
+ - `test: add automated testing for all manual scenarios`
69
+ - `test: implement strip_emojis() function for Windows compatibility`
70
+ - `test: add comprehensive unit test coverage (122 tests)`
71
+ - `test: fix test import paths for modular architecture`
72
+
73
+ ### MCP Clients: config files added for v1.1
74
+ - Added Claude Desktop and MCP Inspector config files
75
+ - `config: added claude-desktop-config-developer-windows.json with UV support`
76
+ - `config: added claude-desktop-config-developer-macos.json with UV support`
77
+ - `config: added claude-desktop-config-user-windows.json`
78
+ - `config: added claude-desktop-config-user-macos.json`
79
+ - `config: added Windows UTF-8 encoding variables to windows configs`
80
+ - `config: added mcp-inspector-http-config.json for HTTP transport using uv`
81
+ - `config: added mcp-inspector-stdio-config.json for STDIO transport using uv`
82
+ - 'examples: prompts-for-claude.md has example prompt text to test tools
83
+
84
+ ### Update docs for v1.1
85
+ - `docs: create comprehensive CHANGELOG.md for v1.0.0 and v1.1.0`
86
+ - `docs: update quick start guide for UV approach`
87
+ - 'docs: api_reference.md added details for all tools, etc
88
+ - `docs: added claude_desktop_setup.md, mcp_inspector_setup.md, and client_configurations.md
89
+
90
+ ### Documentation Updates for v1.1
91
+ - **Installation Instructions**: Added PyPI installation methods
92
+ - **Configuration Examples**: Updated for UV approach
93
+ - **Testing Procedures**: Comprehensive test execution guidance
94
+ - **Troubleshooting**: Enhanced problem resolution guidance
95
+
96
+ ### Update Readme for v1.1
97
+ - added install from PyPI
98
+ - added how to install UV package manager
99
+ - added claude desktop and mcp inspector setup sections
100
+ - reword technical sections for accuracy
101
+ - add v1.1 list of changes, depend on python-alfresco 1.1.1, python 3.10+
102
+ - added how to install Alfresco Community from github
103
+
104
+ ### Update project files and misc root dir files for v1.1
105
+ - gitignore now ignores cursor memory and memory-bank dir, keep .vscode/mcp.json
106
+ - config.yaml has changed alfresco_url to have base_url, added timeout, added
107
+ mcp server name and version confg
108
+ - MANIFEST.in added for proper package distrubution config
109
+ - pyproject.toml change to have v1.1.0 release, pypi distrib settings, remove
110
+ fastMCP version restriction, update to require python 3.10 or greater, add
111
+ pypi keyword and topic, settings, project urls for pypi, configure setuptools
112
+ for includes, excludes
113
+ - run_server.py script added
114
+ - .vscode/mcp.json uses run_server.py for debugging mcp server
115
+ - uv.lock add now that use uv, and uv lock --upgrade updated v0.12.5 from v0.12.4 of ruff
116
+
117
+ ### Fixes for pyproject.toml for v1.1
118
+ - require python-alfresco-api >= 1.1.1 not 1.0.0 in dependencies
119
+ - have python 3.10 instead of 3.8 for tool.mypy, and py310 not py38 for tool.ruff and tool.black
120
+
121
+ ### Example Code Updates for v1.1
122
+ - `examples: update transport examples for UV approach`
123
+ - `examples: enhance document lifecycle example`
124
+ - `examples: add UV-specific installation examples`
125
+ - `examples: update batch operations for improved performance`
126
+ - `examples: refactor error handling patterns`
127
+
128
+ ### Requirements
129
+ - **Python Versions**: 3.10+ (unchanged)
130
+ - **python-alfresco-api**: >= 1.1.1 (updated requirement)
131
+ - **FastMCP**: Tested with v2.10.6
132
+
133
+ ### Tested
134
+ - **Alfresco Versions**: Community 25.1 (tested), Enterprise (not tested in v1.1)
135
+ - **Operating Systems**:
136
+ - Windows (tested)
137
+ - macOS (needs testing)
138
+ - Linux (needs testing, note: no Claude Desktop support on Linux)
139
+ - **MCP Clients**:
140
+ - Claude Desktop (tested and validated)
141
+ - MCP Inspector (tested and validated)
142
+ - Cursor (configuration provided, not tested in v1.1)
143
+ - Claude Code (configuration provided, not tested in v1.1)
144
+
145
+ ## [1.0.0] - 2024-06-24
146
+
147
+ ### Added
148
+ - Initial FastMCP 2.0 server implementation
149
+ - 15 content management tools across search and core operations
150
+ - Full text search with wildcard support
151
+ - Advanced search using AFTS query language
152
+ - Metadata search with property-based queries
153
+ - CMIS SQL search capabilities
154
+ - Complete document lifecycle management (upload, download, checkout, checkin)
155
+ - Version management with major/minor version support
156
+ - Folder operations and repository browsing
157
+ - Property management for documents and folders
158
+ - Multiple transport protocols (STDIO, HTTP, SSE)
159
+ - Configuration via environment variables and .env files
160
+ - Claude Desktop integration with Windows and macOS configs
161
+ - MCP Inspector support for development testing
162
+ - Comprehensive documentation and examples
163
+ - Testing framework with unit and integration tests
164
+ - Error handling and recovery patterns
165
+ - Repository discovery and status reporting
166
+
167
+ ### Technical Implementation
168
+ - python-alfresco-api integration for content services access
169
+ - Pydantic v2 models for type safety
170
+ - Async support for concurrent operations
171
+ - Connection pooling and authentication management
172
+ - Progress reporting and context logging
162
173
  - Configuration validation and environment setup
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: python-alfresco-mcp-server
3
- Version: 1.2.0
3
+ Version: 1.2.1
4
4
  Summary: FastMCP 3 server for Alfresco Content Services integration
5
5
  Project-URL: Homepage, https://github.com/stevereiner/python-alfresco-mcp-server
6
6
  Project-URL: Repository, https://github.com/stevereiner/python-alfresco-mcp-server
@@ -27,7 +27,7 @@ Requires-Dist: fastmcp<4,>=3.4.5
27
27
  Requires-Dist: httpx>=0.24.0
28
28
  Requires-Dist: pydantic-settings>=2.0.0
29
29
  Requires-Dist: pydantic>=2.0.0
30
- Requires-Dist: python-alfresco-api>=1.2.1
30
+ Requires-Dist: python-alfresco-api>=1.2.2
31
31
  Requires-Dist: python-multipart>=0.0.6
32
32
  Requires-Dist: pyyaml>=6.0
33
33
  Provides-Extra: all
@@ -55,7 +55,7 @@ Requires-Dist: pytest-xdist>=3.0.0; extra == 'test'
55
55
  Requires-Dist: pytest>=7.0.0; extra == 'test'
56
56
  Description-Content-Type: text/markdown
57
57
 
58
- # Python Alfresco MCP Server v1.1 🚀
58
+ # Python Alfresco MCP Server v1.2 🚀
59
59
 
60
60
  [![PyPI version](https://img.shields.io/pypi/v/python-alfresco-mcp-server)](https://pypi.org/project/python-alfresco-mcp-server/)
61
61
  [![PyPI downloads](https://pepy.tech/badge/python-alfresco-mcp-server)](https://pepy.tech/project/python-alfresco-mcp-server)
@@ -70,6 +70,15 @@ Built with [FastMCP 3](https://github.com/PrefectHQ/fastmcp).
70
70
  Features complete documentation, examples, and
71
71
  config for various MCP clients (Claude Desktop, MCP Inspector, references to configuring others).
72
72
 
73
+ ## 🌟 What's New in v1.2
74
+
75
+ - **Alfresco authentication methods**: connect via **basic**, **ticket**, or **OAuth2/OIDC** (`ALFRESCO_AUTH_METHOD` + `ALFRESCO_OAUTH2_*`, backed by `python-alfresco-api` 1.2.1) — see [Authentication](#-authentication).
76
+ - **Optional MCP transport authentication**: secure the MCP server itself with an OAuth2 bearer token (`MCP_TRANSPORT_AUTH=true`), validated against your IdP's JWKS (HTTP/SSE transports; stdio unaffected).
77
+ - **FastMCP 3**: upgraded to `fastmcp>=3.4.5,<4` (transport auth uses `JWTVerifier`).
78
+ - **`download_document` custom folder**: optional `destination_dir` (default `~/Downloads`) — thanks [@jeremie-lesage](https://github.com/jeremie-lesage) ([#1](https://github.com/stevereiner/python-alfresco-mcp-server/pull/1)).
79
+ - **Packaging**: switched to the hatchling build backend.
80
+ - Requires **python-alfresco-api ≥ 1.2.1** (OAuth2/OIDC auth + OAuth2 service-account `displayName` fix).
81
+
73
82
  ## 🌟 What's New in v1.1
74
83
 
75
84
  ### **Modular Architecture & Enhanced Testing**
@@ -228,10 +237,15 @@ uv sync # Basic dependencies
228
237
  uv sync --extra dev # With development tools
229
238
  uv sync --extra test # With testing tools
230
239
  uv sync --extra all # Everything
240
+
241
+ # Or an editable install into the active virtual environment (pip-style):
242
+ uv pip install -e .
231
243
  ```
232
244
 
233
245
  ### 4. Configure Alfresco Connection
234
246
 
247
+ > The examples below use HTTP **Basic** auth. Alfresco also supports **ticket** and **OAuth2/OIDC** (`ALFRESCO_AUTH_METHOD` + `ALFRESCO_OAUTH2_*`), and you can optionally secure the MCP transport with an OAuth2 bearer (`MCP_TRANSPORT_AUTH`) — see the [Authentication](#-authentication) section for all methods.
248
+
235
249
  **Option 1: Environment Variables**
236
250
  ```bash
237
251
  # Linux/Mac
@@ -1,4 +1,4 @@
1
- # Python Alfresco MCP Server v1.1 🚀
1
+ # Python Alfresco MCP Server v1.2 🚀
2
2
 
3
3
  [![PyPI version](https://img.shields.io/pypi/v/python-alfresco-mcp-server)](https://pypi.org/project/python-alfresco-mcp-server/)
4
4
  [![PyPI downloads](https://pepy.tech/badge/python-alfresco-mcp-server)](https://pepy.tech/project/python-alfresco-mcp-server)
@@ -13,6 +13,15 @@ Built with [FastMCP 3](https://github.com/PrefectHQ/fastmcp).
13
13
  Features complete documentation, examples, and
14
14
  config for various MCP clients (Claude Desktop, MCP Inspector, references to configuring others).
15
15
 
16
+ ## 🌟 What's New in v1.2
17
+
18
+ - **Alfresco authentication methods**: connect via **basic**, **ticket**, or **OAuth2/OIDC** (`ALFRESCO_AUTH_METHOD` + `ALFRESCO_OAUTH2_*`, backed by `python-alfresco-api` 1.2.1) — see [Authentication](#-authentication).
19
+ - **Optional MCP transport authentication**: secure the MCP server itself with an OAuth2 bearer token (`MCP_TRANSPORT_AUTH=true`), validated against your IdP's JWKS (HTTP/SSE transports; stdio unaffected).
20
+ - **FastMCP 3**: upgraded to `fastmcp>=3.4.5,<4` (transport auth uses `JWTVerifier`).
21
+ - **`download_document` custom folder**: optional `destination_dir` (default `~/Downloads`) — thanks [@jeremie-lesage](https://github.com/jeremie-lesage) ([#1](https://github.com/stevereiner/python-alfresco-mcp-server/pull/1)).
22
+ - **Packaging**: switched to the hatchling build backend.
23
+ - Requires **python-alfresco-api ≥ 1.2.1** (OAuth2/OIDC auth + OAuth2 service-account `displayName` fix).
24
+
16
25
  ## 🌟 What's New in v1.1
17
26
 
18
27
  ### **Modular Architecture & Enhanced Testing**
@@ -171,10 +180,15 @@ uv sync # Basic dependencies
171
180
  uv sync --extra dev # With development tools
172
181
  uv sync --extra test # With testing tools
173
182
  uv sync --extra all # Everything
183
+
184
+ # Or an editable install into the active virtual environment (pip-style):
185
+ uv pip install -e .
174
186
  ```
175
187
 
176
188
  ### 4. Configure Alfresco Connection
177
189
 
190
+ > The examples below use HTTP **Basic** auth. Alfresco also supports **ticket** and **OAuth2/OIDC** (`ALFRESCO_AUTH_METHOD` + `ALFRESCO_OAUTH2_*`), and you can optionally secure the MCP transport with an OAuth2 bearer (`MCP_TRANSPORT_AUTH`) — see the [Authentication](#-authentication) section for all methods.
191
+
178
192
  **Option 1: Environment Variables**
179
193
  ```bash
180
194
  # Linux/Mac
@@ -1,140 +1,146 @@
1
- """
2
- Configuration management for MCP Server for Alfresco.
3
- """
4
-
5
- import os
6
- from typing import Optional
7
- from pydantic import BaseModel, Field
8
-
9
-
10
- class AlfrescoConfig(BaseModel):
11
- """Configuration for MCP Server for Alfresco."""
12
-
13
- # Alfresco server connection
14
- alfresco_url: str = Field(
15
- default_factory=lambda: os.getenv("ALFRESCO_URL", "http://localhost:8080"),
16
- description="Alfresco server URL"
17
- )
18
-
19
- # Authentication method: basic | ticket | oauth2
20
- auth_method: str = Field(
21
- default_factory=lambda: os.getenv("ALFRESCO_AUTH_METHOD", "basic").lower(),
22
- description="Alfresco auth method: basic | ticket | oauth2"
23
- )
24
-
25
- # Authentication (basic / ticket)
26
- username: str = Field(
27
- default_factory=lambda: os.getenv("ALFRESCO_USERNAME", "admin"),
28
- description="Alfresco username"
29
- )
30
-
31
- password: str = Field(
32
- default_factory=lambda: os.getenv("ALFRESCO_PASSWORD", "admin"),
33
- description="Alfresco password"
34
- )
35
-
36
- # OAuth2 (auth_method=oauth2) — Alfresco Identity Service / any OIDC IdP
37
- oauth2_client_id: Optional[str] = Field(
38
- default_factory=lambda: os.getenv("ALFRESCO_OAUTH2_CLIENT_ID"),
39
- description="OAuth2 client id"
40
- )
41
- oauth2_client_secret: Optional[str] = Field(
42
- default_factory=lambda: os.getenv("ALFRESCO_OAUTH2_CLIENT_SECRET"),
43
- description="OAuth2 client secret"
44
- )
45
- oauth2_token_endpoint: Optional[str] = Field(
46
- default_factory=lambda: os.getenv("ALFRESCO_OAUTH2_TOKEN_ENDPOINT"),
47
- description="OAuth2 token endpoint URL"
48
- )
49
- oauth2_grant_type: str = Field(
50
- default_factory=lambda: os.getenv("ALFRESCO_OAUTH2_GRANT_TYPE", "client_credentials"),
51
- description="OAuth2 grant type: client_credentials | refresh_token"
52
- )
53
- oauth2_scope: Optional[str] = Field(
54
- default_factory=lambda: os.getenv("ALFRESCO_OAUTH2_SCOPE"),
55
- description="OAuth2 scope"
56
- )
57
- oauth2_access_token: Optional[str] = Field(
58
- default_factory=lambda: os.getenv("ALFRESCO_OAUTH2_ACCESS_TOKEN"),
59
- description="Pre-obtained OAuth2 access token (optional)"
60
- )
61
- oauth2_refresh_token: Optional[str] = Field(
62
- default_factory=lambda: os.getenv("ALFRESCO_OAUTH2_REFRESH_TOKEN"),
63
- description="OAuth2 refresh token (optional)"
64
- )
65
-
66
- # Connection settings
67
- verify_ssl: bool = Field(
68
- default_factory=lambda: os.getenv("ALFRESCO_VERIFY_SSL", "false").lower() == "true",
69
- description="Verify SSL certificates"
70
- )
71
-
72
- timeout: int = Field(
73
- default_factory=lambda: int(os.getenv("ALFRESCO_TIMEOUT", "30")),
74
- description="Request timeout in seconds"
75
- )
76
-
77
- # MCP Server settings
78
- server_name: str = Field(
79
- default="python-alfresco-mcp-server",
80
- description="MCP server name"
81
- )
82
-
83
- server_version: str = Field(
84
- default="1.0.0",
85
- description="MCP server version"
86
- )
87
-
88
- # FastAPI settings (for HTTP transport)
89
- fastapi_host: str = Field(
90
- default_factory=lambda: os.getenv("FASTAPI_HOST", "localhost"),
91
- description="FastAPI host"
92
- )
93
-
94
- fastapi_port: int = Field(
95
- default_factory=lambda: int(os.getenv("FASTAPI_PORT", "8000")),
96
- description="FastAPI port"
97
- )
98
-
99
- fastapi_prefix: str = Field(
100
- default_factory=lambda: os.getenv("FASTAPI_PREFIX", "/mcp"),
101
- description="FastAPI URL prefix"
102
- )
103
-
104
- # Logging
105
- log_level: str = Field(
106
- default_factory=lambda: os.getenv("LOG_LEVEL", "INFO"),
107
- description="Logging level"
108
- )
109
-
110
- # Content settings
111
- max_file_size: int = Field(
112
- default_factory=lambda: int(os.getenv("MAX_FILE_SIZE", "100000000")), # 100MB
113
- description="Maximum file size for uploads in bytes"
114
- )
115
-
116
- allowed_extensions: list[str] = Field(
117
- default_factory=lambda: [
118
- ".txt", ".pdf", ".doc", ".docx", ".xls", ".xlsx",
119
- ".ppt", ".pptx", ".jpg", ".jpeg", ".png", ".gif",
120
- ".zip", ".xml", ".json", ".csv"
121
- ],
122
- description="Allowed file extensions for uploads"
123
- )
124
-
125
- class Config:
126
- env_prefix = "ALFRESCO_"
127
- case_sensitive = False
128
-
129
- def model_post_init(self, __context) -> None:
130
- """Normalize URLs after initialization."""
131
- if self.alfresco_url.endswith("/"):
132
- self.alfresco_url = self.alfresco_url.rstrip("/")
133
-
134
-
135
- def load_config() -> AlfrescoConfig:
136
- """Load configuration from environment variables and defaults."""
137
- return AlfrescoConfig()
138
-
139
- # Global config instance for import
1
+ """
2
+ Configuration management for MCP Server for Alfresco.
3
+ """
4
+
5
+ import os
6
+ from typing import Optional
7
+ from pydantic import BaseModel, Field
8
+
9
+
10
+ class AlfrescoConfig(BaseModel):
11
+ """Configuration for MCP Server for Alfresco."""
12
+
13
+ # Alfresco server connection
14
+ alfresco_url: str = Field(
15
+ default_factory=lambda: os.getenv("ALFRESCO_URL", "http://localhost:8080"),
16
+ description="Alfresco server URL"
17
+ )
18
+
19
+ # Authentication method: basic | ticket | oauth2
20
+ auth_method: str = Field(
21
+ default_factory=lambda: os.getenv("ALFRESCO_AUTH_METHOD", "basic").lower(),
22
+ description="Alfresco auth method: basic | ticket | oauth2"
23
+ )
24
+
25
+ # Authentication (basic / ticket)
26
+ username: str = Field(
27
+ default_factory=lambda: os.getenv("ALFRESCO_USERNAME", "admin"),
28
+ description="Alfresco username"
29
+ )
30
+
31
+ password: str = Field(
32
+ default_factory=lambda: os.getenv("ALFRESCO_PASSWORD", "admin"),
33
+ description="Alfresco password"
34
+ )
35
+
36
+ ticket: Optional[str] = Field(
37
+ default_factory=lambda: os.getenv("ALFRESCO_TICKET"),
38
+ description="Pre-obtained Alfresco login ticket; with auth_method=ticket it is "
39
+ "used as-is instead of being fetched from username/password"
40
+ )
41
+
42
+ # OAuth2 (auth_method=oauth2) — Alfresco Identity Service / any OIDC IdP
43
+ oauth2_client_id: Optional[str] = Field(
44
+ default_factory=lambda: os.getenv("ALFRESCO_OAUTH2_CLIENT_ID"),
45
+ description="OAuth2 client id"
46
+ )
47
+ oauth2_client_secret: Optional[str] = Field(
48
+ default_factory=lambda: os.getenv("ALFRESCO_OAUTH2_CLIENT_SECRET"),
49
+ description="OAuth2 client secret"
50
+ )
51
+ oauth2_token_endpoint: Optional[str] = Field(
52
+ default_factory=lambda: os.getenv("ALFRESCO_OAUTH2_TOKEN_ENDPOINT"),
53
+ description="OAuth2 token endpoint URL"
54
+ )
55
+ oauth2_grant_type: str = Field(
56
+ default_factory=lambda: os.getenv("ALFRESCO_OAUTH2_GRANT_TYPE", "client_credentials"),
57
+ description="OAuth2 grant type: client_credentials | refresh_token"
58
+ )
59
+ oauth2_scope: Optional[str] = Field(
60
+ default_factory=lambda: os.getenv("ALFRESCO_OAUTH2_SCOPE"),
61
+ description="OAuth2 scope"
62
+ )
63
+ oauth2_access_token: Optional[str] = Field(
64
+ default_factory=lambda: os.getenv("ALFRESCO_OAUTH2_ACCESS_TOKEN"),
65
+ description="Pre-obtained OAuth2 access token (optional)"
66
+ )
67
+ oauth2_refresh_token: Optional[str] = Field(
68
+ default_factory=lambda: os.getenv("ALFRESCO_OAUTH2_REFRESH_TOKEN"),
69
+ description="OAuth2 refresh token (optional)"
70
+ )
71
+
72
+ # Connection settings
73
+ verify_ssl: bool = Field(
74
+ default_factory=lambda: os.getenv("ALFRESCO_VERIFY_SSL", "false").lower() == "true",
75
+ description="Verify SSL certificates"
76
+ )
77
+
78
+ timeout: int = Field(
79
+ default_factory=lambda: int(os.getenv("ALFRESCO_TIMEOUT", "30")),
80
+ description="Request timeout in seconds"
81
+ )
82
+
83
+ # MCP Server settings
84
+ server_name: str = Field(
85
+ default="python-alfresco-mcp-server",
86
+ description="MCP server name"
87
+ )
88
+
89
+ server_version: str = Field(
90
+ default="1.0.0",
91
+ description="MCP server version"
92
+ )
93
+
94
+ # FastAPI settings (for HTTP transport)
95
+ fastapi_host: str = Field(
96
+ default_factory=lambda: os.getenv("FASTAPI_HOST", "localhost"),
97
+ description="FastAPI host"
98
+ )
99
+
100
+ fastapi_port: int = Field(
101
+ default_factory=lambda: int(os.getenv("FASTAPI_PORT", "8000")),
102
+ description="FastAPI port"
103
+ )
104
+
105
+ fastapi_prefix: str = Field(
106
+ default_factory=lambda: os.getenv("FASTAPI_PREFIX", "/mcp"),
107
+ description="FastAPI URL prefix"
108
+ )
109
+
110
+ # Logging
111
+ log_level: str = Field(
112
+ default_factory=lambda: os.getenv("LOG_LEVEL", "INFO"),
113
+ description="Logging level"
114
+ )
115
+
116
+ # Content settings
117
+ max_file_size: int = Field(
118
+ default_factory=lambda: int(os.getenv("MAX_FILE_SIZE", "100000000")), # 100MB
119
+ description="Maximum file size for uploads in bytes"
120
+ )
121
+
122
+ allowed_extensions: list[str] = Field(
123
+ default_factory=lambda: [
124
+ ".txt", ".pdf", ".doc", ".docx", ".xls", ".xlsx",
125
+ ".ppt", ".pptx", ".jpg", ".jpeg", ".png", ".gif",
126
+ ".zip", ".xml", ".json", ".csv"
127
+ ],
128
+ description="Allowed file extensions for uploads"
129
+ )
130
+
131
+ class Config:
132
+ env_prefix = "ALFRESCO_"
133
+ case_sensitive = False
134
+
135
+ def model_post_init(self, __context) -> None:
136
+ """Normalize URLs after initialization."""
137
+ if self.alfresco_url.endswith("/"):
138
+ self.alfresco_url = self.alfresco_url.rstrip("/")
139
+
140
+
141
+ def load_config() -> AlfrescoConfig:
142
+ """Load configuration from environment variables and defaults."""
143
+ return AlfrescoConfig()
144
+
145
+ # Global config instance for import
140
146
  config = load_config()
@@ -20,6 +20,9 @@ def get_alfresco_config() -> dict:
20
20
  'auth_method': os.getenv('ALFRESCO_AUTH_METHOD', 'basic').lower(), # basic | ticket | oauth2
21
21
  'username': os.getenv('ALFRESCO_USERNAME', 'admin'),
22
22
  'password': os.getenv('ALFRESCO_PASSWORD', 'admin'),
23
+ # A login ticket obtained elsewhere. With auth_method=ticket this replaces
24
+ # username/password entirely instead of being fetched from them.
25
+ 'ticket': os.getenv('ALFRESCO_TICKET', ''),
23
26
  'verify_ssl': os.getenv('ALFRESCO_VERIFY_SSL', 'false').lower() == 'true',
24
27
  'timeout': int(os.getenv('ALFRESCO_TIMEOUT', '30')),
25
28
  'oauth2': {
@@ -38,14 +41,23 @@ def _build_auth_util(config: dict):
38
41
  """Build a python-alfresco-api auth util for the configured auth_method.
39
42
 
40
43
  Returns None for basic auth (ClientFactory builds its own from username/password).
41
- - ticket: TicketAuthUtil self-fetches an Alfresco login ticket (Authorization: Basic base64(ticket)).
44
+ - ticket: either a caller-supplied login ticket (ALFRESCO_TICKET) used as-is, or one
45
+ TicketAuthUtil self-fetches from username/password. Either way the wire format is
46
+ Authorization: Basic base64(ticket).
42
47
  - oauth2: OAuth2AuthUtil (client_credentials/refresh, or a pre-obtained access_token → Bearer),
43
48
  e.g. against Alfresco Identity Service / Keycloak.
44
49
  """
45
50
  method = config.get('auth_method', 'basic')
46
51
  if method == 'ticket':
47
52
  from python_alfresco_api.auth_util import TicketAuthUtil
48
- logger.info(">> Using Alfresco ticket authentication")
53
+ ticket = config.get('ticket')
54
+ if ticket:
55
+ logger.info(">> Using Alfresco ticket authentication (caller-supplied ticket)")
56
+ return TicketAuthUtil(
57
+ base_url=config['alfresco_url'], ticket=ticket,
58
+ verify_ssl=config['verify_ssl'], timeout=config['timeout'],
59
+ )
60
+ logger.info(">> Using Alfresco ticket authentication (acquired from username/password)")
49
61
  return TicketAuthUtil(
50
62
  config['username'], config['password'],
51
63
  base_url=config['alfresco_url'],
@@ -35,7 +35,7 @@ exclude = [
35
35
 
36
36
  [project]
37
37
  name = "python-alfresco-mcp-server"
38
- version = "1.2.0"
38
+ version = "1.2.1"
39
39
  description = "FastMCP 3 server for Alfresco Content Services integration"
40
40
  authors = [{name = "Steve Reiner", email = "example@example.com"}]
41
41
  license = "Apache-2.0"
@@ -63,7 +63,7 @@ dependencies = [
63
63
  "fastmcp>=3.4.5,<4",
64
64
 
65
65
  # Alfresco integration
66
- "python-alfresco-api>=1.2.1",
66
+ "python-alfresco-api>=1.2.2",
67
67
 
68
68
  # Configuration and utilities
69
69
  "pydantic>=2.0.0",
@@ -1,59 +1,64 @@
1
- # Alfresco MCP Server Configuration
2
- # Copy this file to .env and customize for your environment
3
- # The .env file will be ignored by git for security
4
-
5
- # === REQUIRED: Alfresco Connection ===
6
- ALFRESCO_URL=http://localhost:8080
7
-
8
- # === Authentication ===
9
- # ALFRESCO_AUTH_METHOD: basic | ticket | oauth2 (default: basic)
10
- # basic = HTTP Basic (username/password below)
11
- # ticket = Alfresco login ticket (username/password below; a ticket is fetched and used
12
- # as Authorization: Basic base64(ticket) — password isn't sent on every request)
13
- # oauth2 = OIDC Bearer token via Alfresco Identity Service / Keycloak (see OAuth2 block)
14
- ALFRESCO_AUTH_METHOD=basic
15
- ALFRESCO_USERNAME=admin
16
- ALFRESCO_PASSWORD=admin
17
-
18
- # === OPTIONAL: OAuth2 (only when ALFRESCO_AUTH_METHOD=oauth2) ===
19
- # Requires Alfresco's identity-service subsystem configured against an OIDC IdP (Keycloak).
20
- # Either client_credentials (client id+secret+token endpoint) OR a pre-obtained access token.
21
- #ALFRESCO_OAUTH2_CLIENT_ID=flexible-graphrag
22
- #ALFRESCO_OAUTH2_CLIENT_SECRET=flexible-graphrag-secret
23
- #ALFRESCO_OAUTH2_TOKEN_ENDPOINT=http://localhost:8091/realms/alfresco/protocol/openid-connect/token
24
- #ALFRESCO_OAUTH2_GRANT_TYPE=client_credentials
25
- #ALFRESCO_OAUTH2_SCOPE=
26
- #ALFRESCO_OAUTH2_ACCESS_TOKEN=
27
- #ALFRESCO_OAUTH2_REFRESH_TOKEN=
28
-
29
- # === OPTIONAL: Connection Settings ===
30
- ALFRESCO_VERIFY_SSL=false
31
- ALFRESCO_TIMEOUT=30
32
-
33
- # === OPTIONAL: Server Settings ===
34
- LOG_LEVEL=INFO
35
- MAX_FILE_SIZE=100000000
36
-
37
- # === OPTIONAL: HTTP Transport Settings ===
38
- FASTAPI_HOST=localhost
39
- FASTAPI_PORT=8000
40
-
41
- # === OPTIONAL: MCP Transport Authentication (secures the MCP server itself) ===
42
- # Distinct from ALFRESCO_AUTH_METHOD (which is how the server authenticates TO Alfresco).
43
- # When enabled, HTTP/SSE clients (incl. MCP Inspector) must send Authorization: Bearer <token>.
44
- # stdio transport ignores this. RS256 bearer tokens are validated against the IdP's JWKS.
45
- MCP_TRANSPORT_AUTH=false
46
- # JWKS endpoint of your OIDC IdP (default = local Keycloak realm used for Alfresco identity-service)
47
- #MCP_AUTH_JWKS_URI=http://host.docker.internal:8091/realms/alfresco/protocol/openid-connect/certs
48
- # Optional strict issuer check. NOTE: the MCP SDK requires an HTTPS issuer URL (localhost excepted),
49
- # so leave unset for a local http Keycloak — the JWKS signature check still gates access.
50
- #MCP_AUTH_ISSUER=https://<your-idp>/realms/<realm>
51
- # Optional audience check (unset = don't validate aud)
52
- #MCP_AUTH_AUDIENCE=
53
-
54
- # === NOTES ===
55
- # - Environment variables take precedence over defaults
56
- # - python-alfresco-api may have its own configuration (check its docs)
57
- # - For production, use environment variables or secure secret management
58
- # - Boolean values: true/false (case insensitive)
1
+ # Alfresco MCP Server Configuration
2
+ # Copy this file to .env and customize for your environment
3
+ # The .env file will be ignored by git for security
4
+
5
+ # === REQUIRED: Alfresco Connection ===
6
+ ALFRESCO_URL=http://localhost:8080
7
+
8
+ # === Authentication ===
9
+ # ALFRESCO_AUTH_METHOD: basic | ticket | oauth2 (default: basic)
10
+ # basic = HTTP Basic (username/password below)
11
+ # ticket = Alfresco login ticket, sent as Authorization: Basic base64(ticket).
12
+ # Either set ALFRESCO_TICKET to a ticket you already have (no username or
13
+ # password needed at all), or leave it empty and a ticket is fetched from the
14
+ # username/password below so the password isn't sent on every request.
15
+ # oauth2 = OIDC Bearer token via Alfresco Identity Service / Keycloak (see OAuth2 block)
16
+ ALFRESCO_AUTH_METHOD=basic
17
+ ALFRESCO_USERNAME=admin
18
+ ALFRESCO_PASSWORD=admin
19
+ # A pre-obtained login ticket (only used when ALFRESCO_AUTH_METHOD=ticket). Set this and
20
+ # username/password are ignored; it is never re-fetched, so it stops working when it expires.
21
+ #ALFRESCO_TICKET=TICKET_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
22
+
23
+ # === OPTIONAL: OAuth2 (only when ALFRESCO_AUTH_METHOD=oauth2) ===
24
+ # Requires Alfresco's identity-service subsystem configured against an OIDC IdP (Keycloak).
25
+ # Either client_credentials (client id+secret+token endpoint) OR a pre-obtained access token.
26
+ #ALFRESCO_OAUTH2_CLIENT_ID=flexible-graphrag
27
+ #ALFRESCO_OAUTH2_CLIENT_SECRET=flexible-graphrag-secret
28
+ #ALFRESCO_OAUTH2_TOKEN_ENDPOINT=http://localhost:8091/realms/alfresco/protocol/openid-connect/token
29
+ #ALFRESCO_OAUTH2_GRANT_TYPE=client_credentials
30
+ #ALFRESCO_OAUTH2_SCOPE=
31
+ #ALFRESCO_OAUTH2_ACCESS_TOKEN=
32
+ #ALFRESCO_OAUTH2_REFRESH_TOKEN=
33
+
34
+ # === OPTIONAL: Connection Settings ===
35
+ ALFRESCO_VERIFY_SSL=false
36
+ ALFRESCO_TIMEOUT=30
37
+
38
+ # === OPTIONAL: Server Settings ===
39
+ LOG_LEVEL=INFO
40
+ MAX_FILE_SIZE=100000000
41
+
42
+ # === OPTIONAL: HTTP Transport Settings ===
43
+ FASTAPI_HOST=localhost
44
+ FASTAPI_PORT=8000
45
+
46
+ # === OPTIONAL: MCP Transport Authentication (secures the MCP server itself) ===
47
+ # Distinct from ALFRESCO_AUTH_METHOD (which is how the server authenticates TO Alfresco).
48
+ # When enabled, HTTP/SSE clients (incl. MCP Inspector) must send Authorization: Bearer <token>.
49
+ # stdio transport ignores this. RS256 bearer tokens are validated against the IdP's JWKS.
50
+ MCP_TRANSPORT_AUTH=false
51
+ # JWKS endpoint of your OIDC IdP (default = local Keycloak realm used for Alfresco identity-service)
52
+ #MCP_AUTH_JWKS_URI=http://host.docker.internal:8091/realms/alfresco/protocol/openid-connect/certs
53
+ # Optional strict issuer check. NOTE: the MCP SDK requires an HTTPS issuer URL (localhost excepted),
54
+ # so leave unset for a local http Keycloak — the JWKS signature check still gates access.
55
+ #MCP_AUTH_ISSUER=https://<your-idp>/realms/<realm>
56
+ # Optional audience check (unset = don't validate aud)
57
+ #MCP_AUTH_AUDIENCE=
58
+
59
+ # === NOTES ===
60
+ # - Environment variables take precedence over defaults
61
+ # - python-alfresco-api may have its own configuration (check its docs)
62
+ # - For production, use environment variables or secure secret management
63
+ # - Boolean values: true/false (case insensitive)
59
64
  # - File size in bytes (100000000 = 100MB)