Skip to content

[Bug]: parent_id parameter in Confluence create_page and update_page tools not functioning as expected #389

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
2 tasks done
riteshganatra opened this issue May 6, 2025 · 6 comments · Fixed by #407
Closed
2 tasks done
Labels
bug Something isn't working

Comments

@riteshganatra
Copy link

Prerequisites

  • I have searched the existing issues to make sure this bug has not already been reported.
  • I have checked the README for relevant information.

Bug Description

1. Goal:
To create and update Confluence pages with a specified parent page, thereby establishing a hierarchical page structure using the parent_id parameter.

2. Tools and Parameters Used:

  • mcp_mcp-atlassian_confluence_create_page with the parent_id parameter.
  • mcp_mcp-atlassian_confluence_update_page with the parent_id parameter.

3. Expected Behavior:
The parent_id parameter in both mcp_mcp-atlassian_confluence_create_page and mcp_mcp-atlassian_confluence_update_page tools is defined to accept a string (page ID) or None (i.e., parent_id: str | None).
The unit tests within the sooperset/mcp-atlassian GitHub repository (specifically in tests/unit/confluence/test_pages.py, for example, test_create_page_success and test_update_page_with_parent_id) demonstrate that the underlying Python methods are designed and tested to correctly process a string parent_id to link to a parent page.
Therefore, providing a valid string page ID to the parent_id parameter of these tools should result in the page being created or updated under the specified parent.

4. Actual Behavior:
When a string value is provided for the parent_id parameter to either mcp_mcp-atlassian_confluence_create_page or mcp_mcp-atlassian_confluence_update_page, the tools consistently fail with the error:
Error calling tool: Parameter 'parent_id' must be of type undefined, got string

This occurred with valid parent page IDs that were confirmed to exist and could act as parents. For example, attempting to create a page with parent_id = "2745369565" (a valid page ID) resulted in this error.

5. Supporting Observations:

  • The mcp_mcp-atlassian_confluence_get_page_children tool successfully retrieves child pages when provided with the same string parent_id. This indicates that the page IDs are valid and the Confluence instance correctly supports page hierarchies.
  • Manually creating a child page in the Confluence UI under the target parent page works as expected, and its children can be retrieved using get_page_children.

6. Suspected Cause:
The issue does not seem to be with the fundamental capability of Confluence or the validity of the page IDs. Given that the underlying Python code in mcp-atlassian is tested to handle string parent_ids, the problem likely lies at a higher level:

  • Tool Schema/Definition Mismatch: The schema definition for these tools (as exposed to the AI assistant) might incorrectly specify that parent_id must be undefined when a value is expected, conflicting with the underlying Python implementation.
  • Request Validation Layer: There might be a validation layer for tool calls that incorrectly rejects a string parent_id before the request reaches the core Python logic of the mcp-atlassian server.
  • Discrepancy: There might be a discrepancy between the tested version of the code (e.g., on GitHub) and the version deployed in the environment handling the tool calls.

Recommendation:
Review the schema definition and request validation logic for the parent_id parameter within the mcp_mcp-atlassian_confluence_create_page and mcp_mcp-atlassian_confluence_update_page tools to ensure they correctly align with the underlying Python implementation's capability to accept string page IDs.

Steps to Reproduce

see above

Expected Behavior

see above

Actual Behavior

see above

mcp-atlassian Version

latest

Installation Method

Docker

Operating System

macOS

Python Version

3.11

Atlassian Instance Type

Confluence Cloud

Client Application

Cursor

Additional Context

No response

@riteshganatra riteshganatra added the bug Something isn't working label May 6, 2025
@sooperset
Copy link
Owner

Hi @riteshganatra,

Thank you for this detailed bug report! I've tested this in my environment and was able to successfully create and update pages using string values for parent_id.

Test Success Screenshot:
Image

This suggests that the core mcp-atlassian server logic can handle string parent_id values, but the error Parameter 'parent_id' must be of type undefined, got string might be coming from elsewhere in the stack.

To help diagnose this issue, could you please provide:

  1. Environment details:

    • Exact version of mcp-atlassian (image ID or digest if possible)
    • The complete docker run command you're using (excluding sensitive tokens)
    • Contents of any .env file if you're using --env-file
  2. Client information (Cursor):

    • Cursor version
    • JSON snippet showing how you've configured the MCP server in Cursor
  3. Request/response data:

    • The exact request payload sent to the MCP server when the error occurs
    • Full MCP server logs (ideally with debug logging enabled via -vv flag or MCP_VERY_VERBOSE=true)
    • The schema definition for confluence_create_page and confluence_update_page tools from the mcp_list_tools request

This information will help us pinpoint where the validation is failing and why your string parent_id is being rejected.

Thanks for your help!

@riteshganatra
Copy link
Author

  1. Request payload sent to the MCP server (from my perspective):
    When I attempt to call the tool, I construct a function call with arguments. Here's an example of a failed call to mcp_mcp-atlassian_confluence_create_page we made earlier:
    {
      "tool_name": "mcp_mcp-atlassian_confluence_create_page",
      "parameters": {
        "content": "# Final Test Child",
        "parent_id": "2745369565", // This is the string value
        "space_key": "AM",
        "title": "Final Test Child for Parent ID"
      }
    }
    This is the logical request I initiated. The actual raw HTTP request sent by the Cursor environment to your MCP server might have additional MCP protocol wrapping, but the core parameters I sent are above. The key is that parent_id was indeed a string.
Image
"mcp-atlassian": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "-e", "CONFLUENCE_URL",
        "-e", "CONFLUENCE_USERNAME",
        "-e", "CONFLUENCE_API_TOKEN",
        "-e", "JIRA_URL",
        "-e", "JIRA_USERNAME",
        "-e", "JIRA_API_TOKEN",
        "ghcr.io/sooperset/mcp-atlassian:latest"
      ],
      "env": {
        "CONFLUENCE_URL": "https://my.atlassian.net/wiki",
        "CONFLUENCE_USERNAME": "my email",
        "CONFLUENCE_API_TOKEN": "aa",
        "JIRA_URL": "https://my.atlassian.net",
        "JIRA_USERNAME": "my email",
        "JIRA_API_TOKEN": "aa
      }
    }

no env file.

please help urgently

@sooperset
Copy link
Owner

Hi @riteshganatra,

Thank you for your detailed bug report and providing the additional information we requested.

After thorough investigation, I've determined this is likely a client-side issue specific to Cursor IDE. The same functionality works correctly when tested with Claude desktop and inspector environments, and our review of the underlying MCP and FastMCP codebase confirms the implementation is correct.

Since this appears to be an integration issue with Cursor IDE rather than a problem with our mcp-atlassian package, I'm going to close this issue. I recommend reaching out to the Cursor team about how their environment processes the parameter in tool calls.

If you discover any new information suggesting this is actually an issue with our implementation, please feel free to reopen this ticket or create a new one with those details.

Thanks for your understanding!

@sooperset
Copy link
Owner

let's keep opening this issue to track

@sooperset sooperset reopened this May 9, 2025
sooperset added a commit that referenced this issue May 9, 2025
Convert Union[str, None] to str with default="" in Confluence tools
to resolve client compatibility issues. Internally converts empty strings
to None to maintain library behavior.

Refs #389
sooperset added a commit that referenced this issue May 9, 2025
…405)

Convert Union[str, None] to str with default="" in Confluence tools
to resolve client compatibility issues. Internally converts empty strings
to None to maintain library behavior.

Refs #389
sooperset added a commit that referenced this issue May 10, 2025
This commit introduces a temporary workaround to improve compatibility with
MCP clients, notably Cursor IDE, that may not correctly handle optional
parameters defined with Union types (e.g., `str | None`) and `None`
defaults, often sending empty strings, dicts, or lists instead.

Changes:
- Introduced a new decorator `@convert_empty_defaults_to_none` in
  `src/mcp_atlassian/utils/decorators.py`. This decorator intercepts
  tool calls and converts specific empty default values (empty strings,
  empty dicts, empty lists) for designated optional parameters back to `None`
  before the tool's main logic is executed.
- Modified optional string parameters in Jira and Confluence tools (e.g.,
  `param: str | None = None`) to `param: str = ""` in the function
  signature, and `Field(default="")` in `Annotated` metadata.
- Modified optional dictionary parameters (e.g.,
  `param: dict | None = None`) to `param: dict = {}` (or
  `Field(default_factory=dict)`) in the function signature and
  `Annotated` metadata.
- Modified optional list parameters (e.g.,
  `param: list[str] | None = None`) to `param: list[str] = []` (or
  `Field(default_factory=list)`) in the function signature and
  `Annotated` metadata.
- Applied the `@convert_empty_defaults_to_none` decorator to all affected
  Jira and Confluence tool functions.
- Added `# noqa: B006` to specific lines where mutable default arguments
  (`{}` or `[]`) are used in function signatures to satisfy Ruff, as this
  is a deliberate, temporary measure for client compatibility.
- Included `TODO` comments highlighting that these changes are temporary
  and should be reverted once client-side issues are resolved.

This approach ensures that the generated MCP schema presents default
values (like `""`, `{}`, `[]`) that problematic clients can handle, while
the internal tool logic can still expect `None` for unprovided optional
parameters, maintaining cleaner business logic.

Refs: Issue #389
sooperset added a commit that referenced this issue May 10, 2025
#407)

* fix: Adapt optional tool parameters for wider MCP client compatibility

This commit introduces a temporary workaround to improve compatibility with
MCP clients, notably Cursor IDE, that may not correctly handle optional
parameters defined with Union types (e.g., `str | None`) and `None`
defaults, often sending empty strings, dicts, or lists instead.

Changes:
- Introduced a new decorator `@convert_empty_defaults_to_none` in
  `src/mcp_atlassian/utils/decorators.py`. This decorator intercepts
  tool calls and converts specific empty default values (empty strings,
  empty dicts, empty lists) for designated optional parameters back to `None`
  before the tool's main logic is executed.
- Modified optional string parameters in Jira and Confluence tools (e.g.,
  `param: str | None = None`) to `param: str = ""` in the function
  signature, and `Field(default="")` in `Annotated` metadata.
- Modified optional dictionary parameters (e.g.,
  `param: dict | None = None`) to `param: dict = {}` (or
  `Field(default_factory=dict)`) in the function signature and
  `Annotated` metadata.
- Modified optional list parameters (e.g.,
  `param: list[str] | None = None`) to `param: list[str] = []` (or
  `Field(default_factory=list)`) in the function signature and
  `Annotated` metadata.
- Applied the `@convert_empty_defaults_to_none` decorator to all affected
  Jira and Confluence tool functions.
- Added `# noqa: B006` to specific lines where mutable default arguments
  (`{}` or `[]`) are used in function signatures to satisfy Ruff, as this
  is a deliberate, temporary measure for client compatibility.
- Included `TODO` comments highlighting that these changes are temporary
  and should be reverted once client-side issues are resolved.

This approach ensures that the generated MCP schema presents default
values (like `""`, `{}`, `[]`) that problematic clients can handle, while
the internal tool logic can still expect `None` for unprovided optional
parameters, maintaining cleaner business logic.

Refs: Issue #389
@sooperset
Copy link
Owner

Hi @riteshganatra, I did the quick fix for Cursor in #407. Now this will be fine after releasing 0.10.5. Thanks for reporting!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants