Closed
Conversation
- Add explicit timeouts (5s connect, 20s read) to OAuth HTTP requests - Replace ADD with COPY in Dockerfile per best practices - Add HEALTHCHECK for HTTP transport modes Prevents indefinite hangs on slow Atlassian APIs (AIVSS 6.5). No breaking changes - fully backward compatible.
The latest pydantic version (2.12.0) is not compatible with the project's current usage. Updates dependency specification in `pyproject.toml` to "pydantic>=2.10.0,<2.12.0" to prevent runtime errors when using with uvx. Related to sooperset#721.
Add required OAuth scopes that were missing from the example: - read:jira-user: Required for Jira user operations - read:confluence-content.summary: Required for Confluence content - search:confluence: Required for Confluence search - read:page:confluence: Granular scope required for Confluence v2 API The read:page:confluence scope is particularly important as OAuth authentication uses the v2 API which requires this granular scope for page operations.
…ooperset#767) Self-hosted Confluence (especially older versions like 6.7.1) may return pages without body content, causing TypeError when accessing page["body"]["storage"]["value"]. This adds try/except handling with logging to gracefully handle None values in the body chain. Fixes sooperset#760 Github-Issue:sooperset#760
…operset#768) Add field_serializer to JiraChangelog model to ensure datetime fields are properly serialized to ISO 8601 format for JSON. This fixes the "Object of type datetime is not JSON serializable" error when using expand='changelog' with Jira search. - Add @field_serializer("created") to JiraChangelog - Update to_simplified_dict() to use isoformat() - Add regression tests for datetime serialization - Update existing test expectations for ISO 8601 format Fixes sooperset#749 Github-Issue:sooperset#749
The Jira Cloud v2 search API (/rest/api/*/search) has been deprecated and is now returning errors. This commit migrates Cloud deployments to the new v3 search endpoint (POST /rest/api/3/search/jql). Changes: - Cloud: Use POST /rest/api/3/search/jql with nextPageToken pagination - Server/DC: Continue using the v2 /rest/api/2/search endpoint unchanged - Updated tests to mock the new v3 API calls for Cloud scenarios The v3 API has some differences: - Uses JSON body instead of query parameters - Uses nextPageToken for pagination instead of startAt - Does not return total count (returns -1) - Max 100 results per request (was 50 for Server/DC) Fixes sooperset#720 Github-Issue:sooperset#720
Fixes sooperset#784, sooperset#785, sooperset#772 - ADF parsing for Jira Cloud descriptions and comments
…ooperset#774) Unintended Proxy or Intermediary ('Confused Deputy') : https://security.snyk.io/vuln/SNYK-PYTHON-FASTMCP-13776148
…t#794) Upgrade fastmcp from 2.3.x to 2.14.x to address high-severity OAuth vulnerability (SNYK-PYTHON-FASTMCP-13776148). Breaking API changes migrated: - FastMCP() `description` parameter renamed to `instructions` - `mount(prefix, server)` signature changed to `mount(server, prefix=)` - `sse_app()` replaced with `http_app(transport="sse")` - `streamable_http_app()` replaced with `http_app()` - Client `call_tool()` returns `CallToolResult` object (not list) - Tests restricted to asyncio backend (FastMCP client limitation)
Add comprehensive tests for the adf_to_text function that converts Atlassian Document Format to plain text. Test coverage includes: - Basic input handling (None, string, empty dict/list) - Text nodes (simple, empty, with marks) - HardBreak nodes - Paragraph and content processing - Full ADF documents with nested structures - Edge cases (unknown types, mixed content) - XFail tests for future node types (mention, emoji, date, status, inlineCard) 26 passing tests, 5 xfail tests for planned improvements.
… codeBlock nodes (sooperset#793) Expands the ADF parser to handle additional inline and block node types that were previously being silently dropped during text conversion. - mention: Extracts @username text or falls back to @{id} - emoji: Returns unicode character or shortName - date: Formats UNIX timestamp as YYYY-MM-DD - status: Wraps status text in brackets - inlineCard: Extracts URL from link cards - codeBlock: Wraps code content in markdown backticks Includes 38 unit tests covering all new node types and edge cases.
sooperset#795) - Add **kwargs to http_app() override for FastMCP 2.14.x json_response param - Rename _mcp_list_tools to _list_tools_mcp to match FastMCP expected method name - Update test references to use correct method name Fixes read-only mode which was not filtering write tools due to incorrect method override name.
Python 3.14 is not yet supported due to upstream pydantic-core limitations (PyO3 0.24.1 only supports up to Python 3.13). - Add requires-python upper bound - Document workaround in README Github-Issue:sooperset#776
When search returns attachments, use the container's page ID instead of the attachment ID for URL construction. - Check content type before URL construction - Use container.id for attachments - Keep using id for pages/blogposts - Add tests for attachment URL scenarios Fixes sooperset#790 Github-Issue:sooperset#790
Change indent formula from `ident // 4` to `ident // 2` to correctly handle 2-space indentation in markdown. - Fix bulleted list level calculation with proper regex for *, -, + - Fix numbered list level calculation with proper regex for any digit - Add tests for 2-space indented nested lists Fixes sooperset#717 Reported-by:@vkrasnoselskikh Github-Issue:sooperset#717
…ment-url fix(confluence): use parent page ID for attachment URLs
…nstraint fix(deps): add Python <3.14 version constraint
…tation fix(jira): fix multi-level bullet list indentation
Adds MCP tool annotations (readOnlyHint, destructiveHint, title) to all 42 tools. - 31 Jira tools annotated - 11 Confluence tools annotated - Helps LLMs understand tool behavior and make safer decisions
Adds include_folders parameter to get_page_children to return child folders alongside pages. - Default: include_folders=True for backward compatibility - Graceful error handling if folder API fails - 4 new tests added - Fixes sooperset#165
…eouts-docker-hardening Security: Add HTTP timeouts and Docker hardening
The HEALTHCHECK added in sooperset#755 assumes HTTP transport on port 8000, but the default transport is stdio (no network listener). This causes: - Docker to mark containers as unhealthy after 3 failed checks - Container orchestrators (k8s, Swarm) to restart containers - A restart loop for most users using the default configuration Remove the HEALTHCHECK entirely. If needed in the future, it should be conditional on transport mode via environment variable. Github-Issue: sooperset#755
fix(docker): remove HEALTHCHECK that breaks stdio transport
- Slim down README to ~105 lines as landing page - Make uvx the primary/default installation method - Create docs/ folder with detailed documentation: - installation.md: uvx, Docker, pip, from source - authentication.md: API tokens, PAT, OAuth, BYOT - configuration.md: IDE configs, env vars, filters - http-transport.md: SSE, streamable-http, multi-user - tools-reference.md: all Jira/Confluence tools - troubleshooting.md: common issues, debugging Github-Issue:sooperset#641
…set#806) Convert documentation to Mintlify MDX format for hosted docs site with automatic llms.txt and llms-full.txt generation.
Mintlify requires a favicon field in mint.json. Added simple SVG favicon with Atlassian blue color scheme.
fix(docs): add required favicon for Mintlify deployment
Mintlify updated their configuration format: - Rename mint.json to docs.json - Update schema URL to https://mintlify.com/docs.json - Update navigation structure to use tabs/groups format
…#858) (sooperset#954) Add regression tests verifying the fix for the OAuth refresh token failure that occurs when a server has ATLASSIAN_OAUTH_ENABLE=true globally but receives per-request PAT/Bearer tokens. The actual fixes were delivered in PR sooperset#952 (early return in configure_oauth_session) and PR sooperset#953 (bearer disambiguation fallback to PAT). Github-Issue:sooperset#858
…set#955) Add HTTP Basic authentication (email:api_token) support for multi-user scenarios, enabling each user to authenticate with their own Atlassian Cloud credentials via the Authorization: Basic header. Changes: - Parse Authorization: Basic <base64(email:api_token)> in middleware - Add 'basic' auth type to dependency injection layer - Create user-specific fetchers with per-request basic auth credentials - Validate email/token presence with clear error messages Based on the approach from PR sooperset#739 by @kangis89. Github-Issue:sooperset#380 Reported-by:kangis89
…operset#956) Fix service detection to recognize ATLASSIAN_OAUTH_ENABLE=true as a fallback when URL-based auth detection fails. Previously, the check was inside an `elif` branch only reached when no service URL was set. Now it acts as a fallback regardless of URL presence. This enables BYOT (Bring Your Own Token) mode where users provide OAuth tokens via per-request headers, with or without service URLs. Based on the approach from PR sooperset#699 by @nealedj. Github-Issue:sooperset#698 Reported-by:nealedj
… and BYOT (sooperset#957) Update AGENTS.md, CLI help text, and .env.example to reflect the new authentication capabilities added in Phase 3: OAuth 2.0 for Data Center, Basic Auth multi-user support, BYOT OAuth mode, service-specific OAuth env vars, and configurable HTTP timeouts.
…perset#958) fix(jira): use new createmeta endpoint for Server/DC (Jira 9.x+) The old `/rest/api/2/issue/createmeta?projectKeys=...&expand=...` endpoint was deprecated in Jira 9.x and broken in Jira 10.x, causing `jira_get_field_options`, `get_required_fields`, and `get_project_issue_types` to silently return empty results on Server/DC. Switch all three methods to the new paginated endpoints: - `/rest/api/2/issue/createmeta/{project}/issuetypes` (values format) - `/rest/api/2/issue/createmeta/{project}/issuetypes/{id}` (field meta) Also fix FieldOption model to fall back to `name` when `value` is empty, which is the case for system fields like priority on Server/DC.
…sooperset#948) Fix catastrophic backtracking in citation regex that caused jira_get_issue to hang on unmatched `??` markers. Replace overlapping alternation pattern with non-overlapping structure that operates in linear time. Thanks @johnny Prepared head SHA: 5677e26 Github-Issue:sooperset#948
Add server-level anyOf flattening to fix JSON Schema incompatibilities with Vertex AI / Google ADK (sooperset#640, sooperset#733), LiteLLM / OpenAI gateways (PR sooperset#938), and other AI platforms. Changes: - Add _sanitize_schema_for_compatibility() in main.py that collapses simple nullable unions (T | None → {type: T}) in tool schemas - Narrow 9 complex union params in jira.py to string-based types (visibility → JSON string, list → CSV, dict|str → str) - Extract _parse_visibility() helper for DRY visibility JSON parsing - Add name_filter param to get_link_types (fixes zero-arg tool issue) - Convert upload_attachments file_paths to CSV string in confluence.py - Add comprehensive schema compatibility test harness (314 tests) validating all 59 tools against platform constraints Validated against Gemini 2.5 Flash and Gemini 2.5 Pro APIs — all 59 tool schemas accepted and function calling works correctly. Github-Issue:sooperset#640 Github-Issue:sooperset#733
Add docs/compatibility.mdx with platform compatibility matrix, schema compatibility details, and platform-specific setup notes for GitHub Copilot, Vertex AI / Google ADK, and ChatGPT. Github-Issue:sooperset#541 Github-Issue:sooperset#484
- Remove unreleased version references (v0.18.0) — latest tag is v0.16.0 - Remove hardcoded tool count (59) that will become stale - Distinguish "Supported" (tested) from "Compatible" (untested) platforms
Remove legacy test_real_api_validation.py (1483 lines, always skipped in CI) and replace with two E2E test suites: - DC E2E (61 tests): Jira DC 10.3 + Confluence DC 9.2 in Docker, covering auth matrix (basic/PAT/BYO-OAuth), DC-specific operations, and MCP tool-level tests via FastMCPTransport - Cloud E2E (48 tests): Jira Cloud + Confluence Cloud, covering auth matrix (basic/BYO-OAuth), Cloud-specific behavior (accountId, analytics, subtask naming), and MCP tool-level tests Both suites auto-skip without their respective flags (--dc-e2e, --cloud-e2e). Includes Docker Compose infrastructure, health checks, PAT creation, and test data provisioning scripts.
…er URLs (sooperset#964) base_url already includes /wiki for Cloud instances (added by atlassian-python-api). Five URL constructions were prepending /wiki again, producing 404s for analytics views, page attachments, and attachment operations. Fixes: v2_adapter.py (4 URLs) and analytics.py (1 URL). Regression tests added for both files. Github-Issue:sooperset#962
…rset#967) When a project key matches a JQL reserved word (e.g., IF, AND, OR), Jira API returns "'IF' is a reserved JQL word" error. Add automatic quoting of reserved words in project = VALUE and project IN (...) patterns, mirroring the existing Confluence CQL pattern. - Add RESERVED_JQL_WORDS constant from official Atlassian docs - Add quote_jql_identifier_if_needed() and sanitize_jql_reserved_words() - Apply sanitization in search_issues() and get_board_issues() - Refactor projects_filter to use smart quoting (only when needed) Github-Issue:sooperset#966
…t#970) Epic link aliases (epicKey, epic_link, epicLink, "Epic Link") passed via additional_fields were silently dropped because _process_additional_fields only recognizes Jira field map names, not user-friendly aliases. Add _prepare_epic_link_fields() that discovers the real custom field ID via get_field_ids_to_epic() and falls back to the parent field on Cloud when no epic link custom field exists (team-managed projects). Also add explicit parent handling in update_issue, which previously skipped the parent kwarg entirely causing silent data loss. Github-Issue:sooperset#623
sooperset#978) - Track CLAUDE.md (@AGENTS.md) so worktrees get it automatically - Track .claude/settings.json for shared team permissions - Selectively gitignore .claude/worktrees/ and settings.local.json instead of the entire .claude/ directory - Add .worktreeinclude for .env and dev/ copying into worktrees - Add dev/ to .gitignore (local task documents)
…erset#973) The d57b7fd schema compatibility commit converted all dict-typed tool parameters to str for better AI platform compatibility, but missed the `fields` parameter in update_issue(). This caused a Pydantic validation error when an LLM passed fields as a JSON string instead of a dict. Fix by changing the type annotation to `dict[str, Any] | str` and routing through the existing `_parse_additional_fields()` helper, consistent with how additional_fields is handled in the same function. Co-authored-by: Henrik Teichmann <teichmann@strato-rz.de> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(jira): add jira_get_project_components tool * test(jira): add test for jira_get_project_components tool - Add import and registration for get_project_components in test fixture - Add test_get_project_components_tool test function * docs: add jira_get_project_components to tools reference --------- Co-authored-by: Ruslan Tabolin <ryutabolin@cloud.ru>
* fix: remove credential/token logging and harden security - Remove OAuth token exchange payload logging containing client_secret - Remove OAuth token response body logging containing access/refresh tokens - Replace partial access/refresh token logging with safe confirmation messages - Redact client_secret value in OAuth setup environment variable output - Redact partial token values in multi-user HTTP mode log messages - Remove SSL legacy renegotiation flags (OP_LEGACY_SERVER_CONNECT, OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) - Add path traversal guard to Jira attachment download - Sanitize JQL project filter interpolation to prevent injection via double-quote characters - Remove unused pprint import from oauth.py * fix: resolve CI failures — ruff-format line length and test mocks for path traversal guard - Wrap long raise ValueError() line to satisfy ruff-format 88-char limit - Add os.getcwd mock to test_download_attachment_success so /tmp path passes traversal check - Fix test_download_attachment_relative_path: use side_effect for abspath mock and separate os.getcwd mock to handle the second abspath call from the traversal guard * style: fix ruff-format lambda expression formatting * fix: address PR review comments - Fix JQL injection bypass: escape backslashes before double-quotes - Replace str.startswith() with Path.is_relative_to() for path traversal check - Add path traversal guard to download_issue_attachments() - Redact client_secret in VS Code config JSON blob * fix: address CI failures - Fix ruff-format: multi-line list comprehension in search.py - Replace Path.resolve() with direct Path.is_relative_to() to avoid breaking os.path mocks in tests (resolve() internally calls os.path.isabs on Python 3.12) - Add os.getcwd mocks to download_issue_attachments tests that use /tmp/attachments paths --------- Co-authored-by: JKAW <jkaw@demant.com>
…perset#979) * feat(jira): add service desk queue read tools Reported-by: Ilgar Dadashi * test(jira): add queue read unit coverage Reported-by: Ilgar Dadashi * docs(docs): document jira queue read tools Reported-by: Ilgar Dadashi * chore(jira): apply queue mixin formatting * fix(jira): enforce upper limit on service desk queue results --------- Co-authored-by: Ilgar <97271325+ilgaur@users.noreply.github.com>
* Upgrade python and dependencies to fix trivy scan issues. Upgraded python version in Dockerfile and dependencies (with `uv lock --upgrade`) to address vulnerabilities found in trivy scan: ``` docker run -v /var/run/docker.sock:/var/run/docker.sock -v $HOME/Library/Caches:/root/.cache/ aquasec/trivy:0.69.1 image ghcr.io/sooperset/mcp-atlassian:0.16.1 ``` Also modified ConfluencePreprocessor to add new ConfluenceSiteMetadata required by md2conf. * Update python in build container too.
The md2conf.metadata module was introduced in 0.3.4. The previous minimum >=0.3.0 could resolve to 0.3.0-0.3.3 which lack this module, causing ModuleNotFoundError at runtime. Follow-up to PR sooperset#977. Github-Issue: sooperset#977
…erset#981) - Update update_issue fields parameter description from 'Dictionary' to 'JSON string' to match the str type (follow-up to PR sooperset#973) - Add PROJECT_KEY_PATTERN validation to get_project_components for consistency with get_project_versions (follow-up to PR sooperset#873)
) - Add 'Server/Data Center only' to queue tool docstrings - Expand Cloud-rejection tests to cover all 3 queue methods - Add QueuesMixin to JiraFetcher docstring Follow-up to PR sooperset#971. Github-Issue: sooperset#971
…sanitization (sooperset#983) Add tests for security hardening from PR sooperset#949: - Path traversal rejection in attachment downloads (absolute and relative paths) - Path traversal rejection in issue attachment downloads (ValueError propagation) - JQL value escaping for backslash and double-quote characters (inline logic) - Integration tests for projects filter with malicious special characters - Combined backslash+quote escaping case for quote_jql_identifier_if_needed Follow-up to PR sooperset#949. Github-Issue: sooperset#949
…ooperset#987) Add validate_safe_path() utility that resolves symlinks via Path.resolve() and validates containment with is_relative_to(). Guard Confluence download_attachment() and download_content_attachments() against path traversal. Refactor Jira attachment guards to use the shared utility, strengthening them with symlink resolution. Addresses GHSA-xjgw-4wvw-rgm4. Reported-by: yotampe-pluto Github-Issue: sooperset#984
…perset#986) Add validate_url_for_ssrf() utility that checks scheme, blocks private/reserved IPs, resolves DNS to detect rebinding, and supports domain allowlisting via MCP_ALLOWED_URL_DOMAINS. Apply validation in ASGI middleware before URLs reach fetcher creation. Add redirect-based SSRF hook on header-based fetcher sessions to block 302 redirects to internal targets. Addresses GHSA-7r34-79r5-rcc9. Reported-by: yotampe-pluto Github-Issue: sooperset#985
…patibility (sooperset#985) * fix: sync OAuth tokens to base keyring username for load_tokens() compatibility When saving tokens, _save_tokens() uses _get_keyring_username() which includes cloud_id or base_url hash in the key. However, load_tokens() uses a simpler pattern (oauth-{client_id}) without the context suffix. This mismatch causes load_tokens() to return stale tokens from keyring after re-authentication, because the new tokens are saved under a different key. Fix: Also save tokens to the base oauth-{client_id} keyring entry when the context-specific username differs, ensuring load_tokens() always finds the latest tokens. Fixes sooperset#984 * test: update test_save_tokens_keyring_success to expect two keyring calls The _save_tokens() method now saves to both: 1. Context-specific key (oauth-{client_id}-cloud-{cloud_id}) 2. Base key (oauth-{client_id}) for load_tokens() compatibility Update the test to verify both keyring entries are created. * address review comments: add inline comment and DC test case - Add inline comment noting that base key may be overwritten if same client_id is used for both Cloud and DC (rare edge case) - Add test_save_tokens_keyring_success_dc to verify dual-write behavior for Data Center context with oauth-{client_id}-dc-{url_hash} pattern
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Fixes: #
Changes
Testing
[briefly describe]Checklist