Summary
confluence_get_space_page_tree raises TypeError: '<' not supported between instances of 'str' and 'int' against a Confluence Data Center / Server space whenever the space contains pages whose extensions.position is returned as a string (commonly the literal "none", but also numeric strings) instead of int/null.
The MCP tool surfaces this as:
Error calling tool 'get_space_page_tree': Failed to fetch page tree: '<' not supported between instances of 'str' and 'int'
Every other Confluence tool (confluence_search, confluence_get_page, ...) works fine against the same space, so this is specific to the tree builder's sort.
Environment
mcp-atlassian 0.21.1 (also reproducible in main at the time of writing — same code)
- Launched via
uvx mcp-atlassian (uv 0.11.9) from Cursor on Windows 11
- Python 3.13.2
- Atlassian backend: Confluence Data Center (on-prem), PAT auth
- Confluence REST v1 API responses include pages where
extensions.position is the string "none" mixed with integer positions (0, 1, 2, ...) within the same space
Repro
- Point
mcp-atlassian at a Confluence DC instance with PAT auth.
- Pick any space whose root page has no explicit ordering (so the v1 API returns
"position": "none" for it) and whose other pages have integer positions.
- Call:
{"name": "confluence_get_space_page_tree", "arguments": {"space_key": "<KEY>", "limit": 100}}
- Observe the error above.
Root cause
src/mcp_atlassian/confluence/pages.py, in ConfluencePages.get_space_page_tree, builds tuples for list.sort using position directly:
# current code (around lines 919-926 on main)
# Sort by depth first (breadth-first), then by position
# Note: position can be 0 (valid), so check for None explicitly
result_pages.sort(
key=lambda p: (
p["depth"],
p["position"] if p["position"] is not None else 999999,
p["title"],
)
)
The check guards against None, but Confluence DC's v1 API returns extensions.position as the string "none" (and sometimes numeric strings) for pages without an explicit ordering. Those values are not None, so they pass through into the sort key. Mixing str and int at the same tuple position raises TypeError in Python 3.
I confirmed this against a real space: of 100 pages returned, ~half had "position": "none" (str) and the rest had integer positions like 0, 1, 2, ....
Suggested fix
Coerce position to a sortable int (with a sentinel for missing/non-numeric values) before using it as a sort key. A minimal patch:
def _pos_sort_key(p: dict) -> int:
pos = p.get("position")
if pos is None:
return 999999
if isinstance(pos, int):
return pos
try:
return int(str(pos))
except (TypeError, ValueError):
return 999999 # e.g. "none"
result_pages.sort(
key=lambda p: (
p["depth"],
_pos_sort_key(p),
p["title"] or "",
)
)
(The p["title"] or "" is a small extra safety guard — title is normally a string but defending against None keeps the tuple comparable.)
Optionally, normalize position once when building result_pages so the field is always int | None in the returned payload too — currently callers see "position": "none" strings in the response, which is also surprising.
Workaround
I patched the locally cached copy in ~\AppData\Local\uv\cache\archive-v0\<hash>\Lib\site-packages\mcp_atlassian\confluence\pages.py with the snippet above and the tool now returns the full tree correctly.
Happy to send a PR if helpful.
Summary
confluence_get_space_page_treeraisesTypeError: '<' not supported between instances of 'str' and 'int'against a Confluence Data Center / Server space whenever the space contains pages whoseextensions.positionis returned as a string (commonly the literal"none", but also numeric strings) instead ofint/null.The MCP tool surfaces this as:
Every other Confluence tool (
confluence_search,confluence_get_page, ...) works fine against the same space, so this is specific to the tree builder's sort.Environment
mcp-atlassian0.21.1 (also reproducible inmainat the time of writing — same code)uvx mcp-atlassian(uv 0.11.9) from Cursor on Windows 11extensions.positionis the string"none"mixed with integer positions (0, 1, 2, ...) within the same spaceRepro
mcp-atlassianat a Confluence DC instance with PAT auth."position": "none"for it) and whose other pages have integer positions.{"name": "confluence_get_space_page_tree", "arguments": {"space_key": "<KEY>", "limit": 100}}Root cause
src/mcp_atlassian/confluence/pages.py, inConfluencePages.get_space_page_tree, builds tuples forlist.sortusingpositiondirectly:The check guards against
None, but Confluence DC's v1 API returnsextensions.positionas the string"none"(and sometimes numeric strings) for pages without an explicit ordering. Those values are notNone, so they pass through into the sort key. Mixingstrandintat the same tuple position raisesTypeErrorin Python 3.I confirmed this against a real space: of 100 pages returned, ~half had
"position": "none"(str) and the rest had integer positions like0, 1, 2, ....Suggested fix
Coerce
positionto a sortableint(with a sentinel for missing/non-numeric values) before using it as a sort key. A minimal patch:(The
p["title"] or ""is a small extra safety guard —titleis normally a string but defending againstNonekeeps the tuple comparable.)Optionally, normalize
positiononce when buildingresult_pagesso the field is alwaysint | Nonein the returned payload too — currently callers see"position": "none"strings in the response, which is also surprising.Workaround
I patched the locally cached copy in
~\AppData\Local\uv\cache\archive-v0\<hash>\Lib\site-packages\mcp_atlassian\confluence\pages.pywith the snippet above and the tool now returns the full tree correctly.Happy to send a PR if helpful.