Skip to content

feat: Support mcp resources and prompts #244

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

Open
wants to merge 43 commits into
base: main
Choose a base branch
from

Conversation

StreetLamb
Copy link
Collaborator

@StreetLamb StreetLamb commented May 31, 2025

Summary by CodeRabbit

  • New Features

    • Added resource management capabilities, enabling agents to list and access structured resources from connected servers.
    • Enhanced prompt creation by allowing resources to be used as context in agent applications.
    • Introduced comprehensive support for resource handling across OpenAI, Anthropic, Azure, Bedrock, and Google LLM integrations with dedicated converters.
    • Added utility functions for content extraction, MIME type detection, resource file handling, and URI normalization.
    • Provided a new example MCP server and agent demonstrating resource and prompt usage with setup and usage instructions.
  • Documentation

    • Added detailed README and configuration files for the new MCP agent example.
    • Included setup instructions and example usage for connecting agents to custom MCP servers.
  • Bug Fixes

    • Corrected minor documentation and docstring errors.
  • Tests

    • Added extensive unit and integration tests for resource management, content utilities, MIME utilities, and multipart message conversions for all supported LLM providers.
    • Expanded LLM test coverage to verify handling of diverse input message types and structured output generation.

StreetLamb added 26 commits May 28, 2025 01:02
- Introduced methods for listing and reading resources from MCP servers.
- Enhanced MCPAggregator to handle resource mapping and initialization.
- Updated Agent class to utilize new resource functionalities.
…remove unused prompt/resource attachment methods
…add weather report functionality and update main.py to handle resource and prompt messages.
Copy link

coderabbitai bot commented May 31, 2025

## Walkthrough

This update introduces comprehensive support for resources as first-class entities in the MCP agent framework, alongside tools and prompts. It adds resource management APIs, utility modules for content and MIME handling, multipart message converters for all major LLM providers, extensive documentation, and a full suite of unit tests. Example scripts and configuration files demonstrate practical usage.

## Changes

| File(s)                                                                                     | Change Summary |
|---------------------------------------------------------------------------------------------|---------------|
| examples/mcp_primitives/mcp_basic_agent/README.md, demo_server.py, main.py, *.yaml, requirements.txt | New example: README, demo MCP server, agent usage script, config, secrets template, requirements. |
| src/mcp_agent/agents/agent.py                                                               | Agent class extended: resource listing/reading APIs, prompt creation with resources, new request models, resource maps, and aggregator integration. |
| src/mcp_agent/core/exceptions.py                                                            | Docstring fix for MCPAgentError. |
| src/mcp_agent/mcp/mcp_aggregator.py                                                         | Aggregator extended: resource discovery, caching, listing, reading, server/URI mapping, and new compound server handlers. |
| src/mcp_agent/utils/content_utils.py                                                        | New: Utility functions for extracting text, image data, and URIs from content objects; type-checking helpers. |
| src/mcp_agent/utils/mime_utils.py                                                           | New: MIME type detection/classification utilities for text, binary, and image content. |
| src/mcp_agent/utils/prompt_message_multipart.py                                             | New: PromptMessageMultipart class for grouping multi-part messages by role, conversion helpers, and text extraction. |
| src/mcp_agent/utils/resource_utils.py                                                       | New: Resource file discovery, content loading (with MIME/binary detection), URI normalization, and embedded resource creation utilities. |
| src/mcp_agent/workflows/llm/augmented_llm.py                                                | Refactored: Unified message type aliases; method signatures updated; simplified tracing span annotation. |
| src/mcp_agent/workflows/llm/augmented_llm_{anthropic,azure,bedrock,google,openai}.py        | Refactored: Unified message input handling using new converter classes; message conversion logic centralized. |
| src/mcp_agent/workflows/llm/multipart_converter_{anthropic,azure,bedrock,google,openai}.py  | New: Comprehensive converter classes for transforming MCP multipart messages and content into provider-specific API formats (Anthropic, Azure, Bedrock, Google, OpenAI). |
| tests/mcp/test_mcp_aggregator.py                                                            | Extended: Tests for aggregator resource loading and mapping. |
| tests/utils/test_content_utils.py, test_mime_utils.py, test_prompt_message_multipart.py, test_resource_utils.py | New: Unit tests for content, MIME, multipart message, and resource utility modules. |
| tests/utils/test_multipart_converter_{anthropic,azure,bedrock,google,openai}.py             | New: Unit tests for each multipart message converter class, covering all content types and edge cases. |
| tests/workflows/llm/test_augmented_llm_{anthropic,azure,bedrock,google,openai}.py           | Extended: Tests for LLM generate methods with various message input types (string, MCP, SDK, mixed). |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant User
    participant Agent
    participant MCPAggregator
    participant MCPServer

    User->>Agent: list_resources(server)
    Agent->>MCPAggregator: list_resources(server)
    MCPAggregator->>MCPServer: list_resources()
    MCPServer-->>MCPAggregator: resource list
    MCPAggregator-->>Agent: resource list
    Agent-->>User: resource list

    User->>Agent: read_resource(uri, server)
    Agent->>MCPAggregator: read_resource(uri, server)
    MCPAggregator->>MCPServer: read_resource(uri)
    MCPServer-->>MCPAggregator: resource content
    MCPAggregator-->>Agent: resource content
    Agent-->>User: resource content

    User->>Agent: create_prompt(prompt_name, args, resource_uris)
    Agent->>MCPAggregator: get_prompt(prompt_name, args, resource_uris)
    MCPAggregator->>MCPServer: get_prompt(...)
    MCPServer-->>MCPAggregator: prompt messages (may reference resources)
    MCPAggregator-->>Agent: prompt messages
    Agent->>MCPAggregator: read_resource(uri) (for each resource_uri)
    MCPAggregator->>MCPServer: read_resource(uri)
    MCPServer-->>MCPAggregator: resource content
    MCPAggregator-->>Agent: resource content
    Agent-->>User: combined prompt messages (with resource content)

Possibly related PRs

Suggested reviewers

  • saqadri

Poem

In a meadow of code, where resources grow,
The agent now gathers, with prompts in tow.
Text, images, blobs—each content type shines,
With MIME and URI, all neatly aligns.
Converters abound for LLMs galore,
And tests hop along, ensuring much more.
🐇✨ Hooray for resourceful leaps!


<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---



<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=lastmile-ai/mcp-agent&utm_content=244):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai explain this code block.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and explain its main purpose.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

…esources; remove get_resource_messages and get_prompt_messages methods
…; update tests to validate resource handling.
@StreetLamb StreetLamb marked this pull request as ready for review June 1, 2025 08:55
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 16

🔭 Outside diff range comments (3)
src/mcp_agent/utils/resource_utils.py (1)

200-223: 🛠️ Refactor suggestion

Improve exception handling and code structure.

The function works but has some structural issues that should be addressed.

+import os.path
+
 def extract_title_from_uri(uri: AnyUrl) -> str:
     """Extract a readable title from a URI."""
     # Simple attempt to get filename from path
-    uri_str = uri._url
+    uri_str = str(uri)  # Avoid accessing protected member
     try:
         # For HTTP(S) URLs
         if uri.scheme in ("http", "https"):
             # Get the last part of the path
             path_parts = uri.path.split("/")
             filename = next((p for p in reversed(path_parts) if p), "")
             return filename if filename else uri_str

-        # For file URLs or other schemes
-        elif uri.path:
-            import os.path
+        # For file URLs or other schemes
+        if uri.path:
             return os.path.basename(uri.path)

-    except Exception:
+    except (AttributeError, ValueError) as e:
         pass

     # Fallback to the full URI if parsing fails
     return uri_str

Move the os.path import to the top level and avoid catching generic exceptions.

🧰 Tools
🪛 Pylint (3.3.7)

[warning] 203-203: Access to a protected member _url of a client class

(W0212)


[warning] 218-218: Catching too general exception Exception

(W0718)


[refactor] 206-216: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[convention] 214-214: Import outside toplevel (os.path)

(C0415)

src/mcp_agent/workflows/llm/augmented_llm.py (1)

161-183: 🛠️ Refactor suggestion

Method signatures still accept MessageTypes, but helper now lags behind

You updated the public protocol & ABC signatures to take message: MessageTypes, 👍.
However, _annotate_span_for_generation_message (and a few other helpers) still declare:

def _annotate_span_for_generation_message(
        self,
        span: trace.Span,
        message: str | MessageParamT | List[MessageParamT],

That excludes PromptMessage and a list containing mixed types. The span annotation will therefore be typed incorrectly and MyPy might complain when the public methods pass a PromptMessage instance.

Diff-ready fix:

-    message: str | MessageParamT | List[MessageParamT],
+    message: MessageTypes,

(No other change to the body is needed because the runtime isinstance checks already work).

src/mcp_agent/agents/agent.py (1)

237-252: 🛠️ Refactor suggestion

Resource cache not fully populated – _namespaced_resource_map is left empty

initialize() correctly updates self._server_to_resource_map, but self._namespaced_resource_map is never populated.
Later helper utilities (or future agent-side look-ups) that expect the flat “all resources” map will silently see an empty dict.

@@
 self._server_to_prompt_map.update(result.server_to_prompt_map)

-# Missing for resources
-self._server_to_resource_map.clear()
-self._server_to_resource_map.update(result.server_to_resource_map)
+# Populate both maps, mirroring tools/prompts
+self._namespaced_resource_map.clear()
+self._namespaced_resource_map.update(result.namespaced_resource_map)
+
+self._server_to_resource_map.clear()
+self._server_to_resource_map.update(result.server_to_resource_map)

Please add the missing two lines (or remove the unused attribute altogether).

🧰 Tools
🪛 Pylint (3.3.7)

[warning] 237-237: TODO: saqadri - check if a lock is needed here

(W0511)

🧹 Nitpick comments (47)
examples/mcp_primitives/mcp_basic_agent/mcp_agent.config.yaml (1)

1-24: Configuration structure looks good with proper separation of concerns.

The configuration file is well-organized with clear sections for execution engine, logging, MCP servers, and OpenAI settings. The use of an external secrets file for API keys is a good security practice.

However, consider cleaning up the commented model line on line 22 before production deployment.

Apply this diff to clean up the commented line:

-  #  default_model: "o3-mini"
tests/mcp/test_mcp_aggregator.py (1)

645-651: Consider simplifying the conditional logic.

The nested if-elif-else structure could be simplified for better readability.

-    async def fake_fetch_capabilities(server_name):
-        if server_name == "srv1":
-            return ("srv1", [tool1], [prompt1], [resource1])
-        elif server_name == "srv2":
-            return ("srv2", [tool2], [prompt2], [resource2])
-        else:
-            raise ValueError("Unknown server")
+    async def fake_fetch_capabilities(server_name):
+        if server_name == "srv1":
+            return ("srv1", [tool1], [prompt1], [resource1])
+        if server_name == "srv2":
+            return ("srv2", [tool2], [prompt2], [resource2])
+        raise ValueError("Unknown server")
🧰 Tools
🪛 Pylint (3.3.7)

[refactor] 646-651: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)

examples/mcp_primitives/mcp_basic_agent/demo_server.py (3)

1-3: Fix import order for better code organization.

The standard library imports should come before third-party imports according to PEP 8.

-from mcp.server.fastmcp import FastMCP
-import datetime
-import json
+import datetime
+import json
+
+from mcp.server.fastmcp import FastMCP
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 1-1: Missing module docstring

(C0114)


[error] 1-1: Unable to import 'mcp.server.fastmcp'

(E0401)


[convention] 2-2: standard import "datetime" should be placed before third party import "mcp.server.fastmcp.FastMCP"

(C0411)


[convention] 3-3: standard import "json" should be placed before third party import "mcp.server.fastmcp.FastMCP"

(C0411)


5-6: Consider removing unused SERVER_START_TIME.

The SERVER_START_TIME variable is defined but never used in the code. Consider removing it or demonstrating its usage.

-# Store server start time
-SERVER_START_TIME = datetime.datetime.utcnow()

If this is intended for future use or demonstration purposes, consider adding a comment explaining its intended purpose.


16-16: Consider breaking long line for better readability.

The README content string exceeds the 100-character line limit.

-        "content": "# Demo Resource Server\n\nThis is a sample README resource provided by the demo MCP server.",
+        "content": (
+            "# Demo Resource Server\n\n"
+            "This is a sample README resource provided by the demo MCP server."
+        ),
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 16-16: Line too long (113/100)

(C0301)

src/mcp_agent/utils/mime_utils.py (2)

1-2: Add module docstring for better documentation.

The module is missing a docstring that would help explain its purpose and functionality.

+"""
+Utility functions for MIME type detection and content classification.
+
+This module provides functions to guess MIME types from file paths,
+determine if content is text-based or binary, and identify image types.
+"""
+
 # mime_utils.py
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 1-1: Missing module docstring

(C0114)


56-59: Simplify the return condition.

The static analysis correctly identifies that this can be simplified by returning the condition directly.

-    # Common text patterns
-    if any(mime_type.endswith(pattern) for pattern in TEXT_MIME_PATTERNS):
-        return True
-
-    return False
+    # Common text patterns
+    return any(mime_type.endswith(pattern) for pattern in TEXT_MIME_PATTERNS)
🧰 Tools
🪛 Ruff (0.11.9)

56-59: Return the condition directly

Inline condition

(SIM103)

src/mcp_agent/utils/prompt_message_multipart.py (2)

1-2: Add module docstring for better documentation.

The module is missing a docstring that would explain the purpose and usage of the PromptMessageMultipart class.

+"""
+Multipart prompt message utilities for MCP agent framework.
+
+This module provides the PromptMessageMultipart class for handling
+prompt messages with multiple content parts and conversion utilities.
+"""
+
 from typing import List, Optional, Union
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 1-1: Missing module docstring

(C0114)


115-118: Add docstring for the add_text method.

The method is missing a docstring as noted by the static analysis tool.

 def add_text(self, to_add: str) -> TextContent:
+    """
+    Add a text content item to this multipart message.
+    
+    Args:
+        to_add: Text content to append
+        
+    Returns:
+        The created TextContent object
+    """
     text = TextContent(type="text", text=to_add)
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 115-115: Missing function or method docstring

(C0116)

tests/utils/test_multipart_converter_azure.py (1)

1-2: Add module docstring for better documentation.

The test module would benefit from a docstring explaining what it tests and its purpose within the broader test suite.

+"""
+Unit tests for the Azure multipart message converter.
+
+Tests the AzureConverter class functionality for converting MCP multipart
+messages to Azure AI inference API message formats.
+"""
+
 from unittest.mock import Mock
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 1-1: Missing module docstring

(C0114)

tests/workflows/llm/test_augmented_llm_anthropic.py (1)

7-7: Fix import order for better code organization.

Third-party imports should be placed before first-party imports according to Python conventions.

Apply this diff to fix the import order:

+from mcp.types import TextContent, SamplingMessage, PromptMessage
+from anthropic.types import Message, TextBlock, ToolUseBlock, Usage
+
 from mcp_agent.config import AnthropicSettings
-
-from mcp.types import TextContent, SamplingMessage, PromptMessage
-from anthropic.types import Message, TextBlock, ToolUseBlock, Usage
🧰 Tools
🪛 Pylint (3.3.7)

[error] 7-7: Unable to import 'mcp.types'

(E0401)


[convention] 7-7: third party import "mcp.types.TextContent" should be placed before first party import "mcp_agent.config.AnthropicSettings"

(C0411)

src/mcp_agent/utils/content_utils.py (3)

19-42: Well-designed utility function with room for minor optimization.

The get_text function is well-documented and handles different content types appropriately.

Consider combining the nested if statements for better readability:

 def get_text(
     content: Union[TextContent, ImageContent, EmbeddedResource],
 ) -> Optional[str]:
     """
     Extract text content from a content object if available.

     Args:
         content: A content object (TextContent, ImageContent, or EmbeddedResource)

     Returns:
         The text content as a string or None if not a text content
     """
     if isinstance(content, TextContent):
         return content.text

     if isinstance(content, TextResourceContents):
         return content.text

-    if isinstance(content, EmbeddedResource):
-        if isinstance(content.resource, TextResourceContents):
-            return content.resource.text
+    if isinstance(content, EmbeddedResource) and isinstance(content.resource, TextResourceContents):
+        return content.resource.text

     return None
🧰 Tools
🪛 Ruff (0.11.9)

37-38: Use a single if statement instead of nested if statements

(SIM102)


44-66: Good implementation with minor optimization opportunity.

The get_image_data function correctly handles different content types and includes a helpful comment about the assumption regarding blob data.

Consider combining the nested if statements:

-    if isinstance(content, EmbeddedResource):
-        if isinstance(content.resource, BlobResourceContents):
-            # This assumes the blob might be an image, which isn't always true
-            # Consider checking the mimeType if needed
-            return content.resource.blob
+    if isinstance(content, EmbeddedResource) and isinstance(content.resource, BlobResourceContents):
+        # This assumes the blob might be an image, which isn't always true
+        # Consider checking the mimeType if needed
+        return content.resource.blob
🧰 Tools
🪛 Ruff (0.11.9)

59-60: Use a single if statement instead of nested if statements

(SIM102)


86-99: Optimize the isinstance checks for better performance.

The function logic is correct, but the isinstance calls can be merged for better efficiency.

Apply this diff to merge the isinstance calls:

-    return isinstance(content, TextContent) or isinstance(content, TextResourceContents)
+    return isinstance(content, (TextContent, TextResourceContents))
🧰 Tools
🪛 Ruff (0.11.9)

98-98: Multiple isinstance calls for content, merge into a single call

Merge isinstance calls for content

(SIM101)

🪛 Pylint (3.3.7)

[refactor] 98-98: Consider merging these isinstance calls to isinstance(content, (TextContent, TextResourceContents))

(R1701)

examples/mcp_primitives/mcp_basic_agent/README.md (1)

71-75: Minor language improvement for better readability.

The documentation is excellent and comprehensive. Consider adding a hyphen for better readability.

Apply this diff:

-Run the agent script which should auto install all necessary dependencies:
+Run the agent script which should auto-install all necessary dependencies:
🧰 Tools
🪛 LanguageTool

[uncategorized] ~71-~71: It appears that a hyphen is missing (if ‘auto’ is not used in the context of ‘cars’).
Context: ...mple Run the agent script which should auto install all necessary dependencies: ```bash uv...

(AUTO_HYPHEN)

tests/workflows/llm/test_augmented_llm_bedrock.py (4)

607-631: Address import redundancy.

The test logic is correct, but there are redundant imports within the function that should be moved to the top-level imports.

-    from mcp.types import PromptMessage, TextContent
-
     prompt_message = PromptMessage(
         role="user",
-        content=TextContent(type="text", text="This is a PromptMessage"),
+        content=TextContent(type="text", text="This is a PromptMessage"),
     )

Move the imports to the top of the file alongside the existing imports on line 7.

🧰 Tools
🪛 Pylint (3.3.7)

[warning] 613-613: Redefining name 'TextContent' from outer scope (line 7)

(W0621)


[error] 613-613: Unable to import 'mcp.types'

(E0401)


[warning] 613-613: Reimport 'TextContent' (imported line 7)

(W0404)


[convention] 613-613: Import outside toplevel (mcp.types.PromptMessage, mcp.types.TextContent)

(C0415)


632-653: Address import redundancy.

Same import issue as the previous test. The test logic and mixed message type handling is well implemented.

Move the from mcp.types import PromptMessage, TextContent to the top-level imports.

🧰 Tools
🪛 Pylint (3.3.7)

[warning] 638-638: Redefining name 'TextContent' from outer scope (line 7)

(W0621)


[error] 638-638: Unable to import 'mcp.types'

(E0401)


[warning] 638-638: Reimport 'TextContent' (imported line 7)

(W0404)


[convention] 638-638: Import outside toplevel (mcp.types.PromptMessage, mcp.types.TextContent)

(C0415)


654-675: Address import redundancy.

The test correctly validates generate_str with mixed types, but has the same import issue.

Move the imports to the top level to avoid redundancy.

🧰 Tools
🪛 Pylint (3.3.7)

[warning] 661-661: Redefining name 'TextContent' from outer scope (line 7)

(W0621)


[error] 661-661: Unable to import 'mcp.types'

(E0401)


[warning] 661-661: Reimport 'TextContent' (imported line 7)

(W0404)


[convention] 661-661: Import outside toplevel (mcp.types.PromptMessage, mcp.types.TextContent)

(C0415)


676-717: Address import redundancy and improve test structure.

The test logic for structured generation with mixed message types is sound, but there are multiple issues to address.

-    from pydantic import BaseModel
-    from mcp.types import PromptMessage, TextContent
-
-    class TestResponseModel(BaseModel):
+    class TestResponseModel(BaseModel):
         name: str
         value: int

Move the imports to the top level. Also, consider defining the TestResponseModel class at the module level to avoid recreating it in multiple tests.

🧰 Tools
🪛 Pylint (3.3.7)

[warning] 683-683: Redefining name 'BaseModel' from outer scope (line 5)

(W0621)


[warning] 684-684: Redefining name 'TextContent' from outer scope (line 7)

(W0621)


[error] 683-683: Unable to import 'pydantic'

(E0401)


[warning] 683-683: Reimport 'BaseModel' (imported line 5)

(W0404)


[convention] 683-683: Import outside toplevel (pydantic.BaseModel)

(C0415)


[error] 684-684: Unable to import 'mcp.types'

(E0401)


[warning] 684-684: Reimport 'TextContent' (imported line 7)

(W0404)


[convention] 684-684: Import outside toplevel (mcp.types.PromptMessage, mcp.types.TextContent)

(C0415)


[convention] 686-686: Missing class docstring

(C0115)


[refactor] 686-686: Too few public methods (0/2)

(R0903)

tests/utils/test_multipart_converter_google.py (2)

1-14: Add module docstring for better documentation.

The imports and structure are good, but the module is missing a docstring to describe its purpose.

+"""
+Tests for the GoogleConverter class which handles conversion of MCP multipart messages
+to Google API format.
+"""
 from unittest.mock import Mock, patch
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 1-1: Missing module docstring

(C0114)


[error] 2-10: Unable to import 'mcp.types'

(E0401)


[error] 12-12: Unable to import 'mcp_agent.utils.prompt_message_multipart'

(E0401)


[error] 13-13: Unable to import 'mcp_agent.workflows.llm.multipart_converter_google'

(E0401)


372-390: Fix import location for better code organization.

The test logic is correct, but the import should be moved to the top level.

+from pydantic import AnyUrl
+
 class TestGoogleConverter:
     # ... other tests ...
     
     def test_create_fallback_text_with_uri(self):
-        from pydantic import AnyUrl
-
         uri = "http://example.com/test"
🧰 Tools
🪛 Pylint (3.3.7)

[error] 372-372: Unable to import 'pydantic'

(E0401)


[convention] 372-372: Import outside toplevel (pydantic.AnyUrl)

(C0415)


[warning] 386-386: Access to a protected member _create_fallback_text of a client class

(W0212)


[warning] 388-388: Unused variable 'args'

(W0612)

tests/utils/test_multipart_converter_openai.py (2)

1-14: Add module docstring for better documentation.

Similar to the Google converter tests, this module needs a docstring to describe its purpose.

+"""
+Tests for the OpenAIConverter class which handles conversion of MCP multipart messages
+to OpenAI Chat API format.
+"""
 from unittest.mock import Mock
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 1-1: Missing module docstring

(C0114)


[error] 2-10: Unable to import 'mcp.types'

(E0401)


[error] 12-12: Unable to import 'mcp_agent.utils.prompt_message_multipart'

(E0401)


[error] 13-13: Unable to import 'mcp_agent.workflows.llm.multipart_converter_openai'

(E0401)


199-204: Fix line length for better readability.

The test logic is correct but there's a long line that exceeds the 100-character limit.

 assert (
     result["text"]
-    == "[PDF URL: https://example.com/document.pdf]\nOpenAI requires PDF files to be uploaded or provided as base64 data."
+    == "[PDF URL: https://example.com/document.pdf]\n"
+    "OpenAI requires PDF files to be uploaded or provided as base64 data."
 )
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 202-202: Line too long (130/100)

(C0301)

src/mcp_agent/utils/resource_utils.py (4)

1-19: Add module docstring and improve imports.

The functionality looks good but needs better documentation and import organization.

+"""
+Utility functions for resource file handling, content loading, and URI management.
+
+This module provides functions to locate resource files, load their content with 
+appropriate MIME type detection, and create various embedded resource objects
+for use in MCP agent workflows.
+"""
 import base64
 from pathlib import Path
 from typing import List, Optional, Tuple

 from mcp.types import (
     BlobResourceContents,
     EmbeddedResource,
     ImageContent,
     TextResourceContents,
 )
 from pydantic import AnyUrl

-import mcp_agent.utils.mime_utils as mime_utils
+from mcp_agent.utils import mime_utils
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 1-1: Missing module docstring

(C0114)


[error] 5-10: Unable to import 'mcp.types'

(E0401)


[error] 11-11: Unable to import 'pydantic'

(E0401)


[refactor] 13-13: Use 'from mcp_agent.utils import mime_utils' instead

(R0402)


[error] 13-13: Unable to import 'mcp_agent.utils.mime_utils'

(E0401)


91-91: Remove redundant imports inside function.

The imports are already available at the module level.

 def create_resource_reference(uri: str, mime_type: str) -> "EmbeddedResource":
-    from mcp.types import EmbeddedResource, TextResourceContents
-
     # Create a resource reference
🧰 Tools
🪛 Pylint (3.3.7)

[warning] 91-91: Redefining name 'EmbeddedResource' from outer scope (line 5)

(W0621)


[warning] 91-91: Redefining name 'TextResourceContents' from outer scope (line 5)

(W0621)


[error] 91-91: Unable to import 'mcp.types'

(E0401)


[warning] 91-91: Reimport 'EmbeddedResource' (imported line 5)

(W0404)


[warning] 91-91: Reimport 'TextResourceContents' (imported line 5)

(W0404)


[convention] 91-91: Import outside toplevel (mcp.types.EmbeddedResource, mcp.types.TextResourceContents)

(C0415)


116-132: Simplify conditional structure.

The else clause after return is unnecessary and can be simplified.

     if is_binary:
         return EmbeddedResource(
             type="resource",
             resource=BlobResourceContents(
                 **resource_args,
                 blob=content,
             ),
         )
-    else:
-        return EmbeddedResource(
-            type="resource",
-            resource=TextResourceContents(
-                **resource_args,
-                text=content,
-            ),
-        )
+    
+    return EmbeddedResource(
+        type="resource",
+        resource=TextResourceContents(
+            **resource_args,
+            text=content,
+        ),
+    )
🧰 Tools
🪛 Pylint (3.3.7)

[refactor] 116-131: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


171-198: Simplify conditional structure and improve URI handling.

The function logic is sound but can be streamlined.

     # If it's a simple filename or relative path, convert to file:// URI
     # Make sure it has three slashes for an absolute path
     if normalized_path.startswith("/"):
         return f"file://{normalized_path}"
-    else:
-        return f"file:///{normalized_path}"
+    
+    return f"file:///{normalized_path}"
🧰 Tools
🪛 Pylint (3.3.7)

[refactor] 194-197: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)

src/mcp_agent/workflows/llm/augmented_llm.py (1)

64-67: Type aliases are great – please expose them from the public module interface

Message / MessageTypes are useful and will be consumed by multiple sub-modules, yet they are defined inside this file only. Importing them elsewhere now requires reaching into the private path
mcp_agent.workflows.llm.augmented_llm.

Consider re-exporting through __all__ or an upper-level __init__.py so that call-sites can simply:

from mcp_agent.workflows.llm import Message, MessageTypes

This prevents tight coupling to the internal file layout.

tests/workflows/llm/test_augmented_llm_azure.py (1)

1088-1150: Repeated inline imports clutter tests

Every new mixed-type test block repeats:

from mcp.types import PromptMessage, TextContent

inside the function body. This re-imports the same names and triggers the PyLint W0404 / C0415 noise you saw in the static hints.
A quick tidy-up:

-        from mcp.types import PromptMessage, TextContent
+        # already imported at the module top – reuse

or move a single import to the module header next to the other mcp.types import.

🧰 Tools
🪛 Pylint (3.3.7)

[warning] 1132-1132: Redefining name 'TextContent' from outer scope (line 19)

(W0621)


[error] 1132-1132: Unable to import 'mcp.types'

(E0401)


[warning] 1132-1132: Reimport 'TextContent' (imported line 19)

(W0404)


[convention] 1132-1132: Import outside toplevel (mcp.types.PromptMessage, mcp.types.TextContent)

(C0415)

tests/workflows/llm/test_augmented_llm_google.py (1)

632-650: Same import-inside-function pattern as Azure tests

For consistency and to silence the identical PyLint warnings, lift the PromptMessage, TextContent, and google.genai.types imports to the module top (guarded by TYPE_CHECKING if run-time weight is a concern).
This reduces duplication and speeds up test collection slightly.

src/mcp_agent/workflows/llm/multipart_converter_bedrock.py (3)

271-283: Copy-paste artefact in doc-string

The function converts messages to Bedrock, but the docstring says Anthropic-compatible.

-        Convert a list of mixed messages to a list of Anthropic-compatible messages.
+        Convert mixed messages into Bedrock-compatible message dictionaries.

Helps future readers avoid confusion.


90-108: Long f-string breaks 100-char guideline & readability

The error text for unsupported image formats spans >110 chars. Consider splitting:

-                            "text": f"Image with unsupported format '{image_content.mimeType}' ({data_size} bytes)"
+                            "text": (
+                                f"Image with unsupported format "
+                                f"'{image_content.mimeType}' ({data_size} bytes)"
+                            )

Applies similarly to the later long message at line 185.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 102-102: Line too long (115/100)

(C0301)


138-156: Unnecessary elif after an unconditional return

Once the SVG branch hits return, subsequent branches never execute in that path.
Simplify the control flow to reduce pylint R1705 noise:

-        if mime_type == "image/svg+xml":
-            return BedrockConverter._convert_svg_resource(resource_content)
-
-        elif is_image_mime_type(mime_type):
+        if mime_type == "image/svg+xml":
+            return BedrockConverter._convert_svg_resource(resource_content)
+
+        if is_image_mime_type(mime_type):

No behavioural change, cleaner code.

🧰 Tools
🪛 Pylint (3.3.7)

[refactor] 138-174: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)

src/mcp_agent/agents/agent.py (1)

570-590: Error handling for resources – silent failures become empty messages

When read_resource() returns an error (isError=True) or empty contents, create_prompt() still appends nothing and gives no feedback. Consider:

if getattr(resource_result, "isError", False):
    raise ValueError(
        f"Error reading resource '{uri}': {resource_result.description}"
    )

before converting to PromptMessage.

src/mcp_agent/mcp/mcp_aggregator.py (3)

640-687: Missing return-type annotation and minor doc nit

list_resources() has no -> ListResourcesResult annotation, unlike sibling methods, breaking editor/IDE help and static analysis consistency.

-    async def list_resources(self, server_name: str | None = None):
+    async def list_resources(
+        self, server_name: str | None = None
+    ) -> ListResourcesResult:

Same applies to read_resource() further below (-> ReadResourceResult).

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 642-642: Line too long (104/100)

(C0301)


[convention] 674-674: Line too long (114/100)

(C0301)


688-783: Early return makes following else: redundant

The long else: after the early return (lines 740-783) is unnecessary and increases indentation depth.

-            if self.connection_persistence:
-                ...
-                return res
-            else:
-                logger.debug(...)
-                ...
-                return result
+            if self.connection_persistence:
+                ...
+                return res
+
+            logger.debug(...)
+            ...
+            return result

Removing the else improves readability (flagged by pylint R1705).

🧰 Tools
🪛 Pylint (3.3.7)

[warning] 745-745: TODO: jerron - annotate span for result

(W0511)


[warning] 782-782: TODO: jerron - annotate span for result

(W0511)


[warning] 730-730: Catching too general exception Exception

(W0718)


[refactor] 740-783: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


1184-1205: _find_server_name_from_uri performs O(N*M) linear scan

For large installations this could become expensive. Storing an auxiliary map
uri -> server_name when resources are loaded would give O(1) look-ups.

Not blocking, but worth considering if resource counts grow.

src/mcp_agent/workflows/llm/multipart_converter_anthropic.py (1)

487-508: Public API naming/documentation mismatch

Parameter is singular message, but doc-string and type hint say “list of mixed messages”.
Either rename to messages and accept an iterable or adjust the implementation.

src/mcp_agent/workflows/llm/multipart_converter_google.py (2)

336-347: Method name incorrect (_anthropic)

convert_mixed_messages_to_anthropic should be convert_mixed_messages_to_google for clarity and symmetry with other converters.


211-213: Protected attribute access

uri._url is used for display; this accesses a protected member. Use str(uri) instead to avoid static-analysis warnings.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 211-211: Line too long (115/100)

(C0301)


[warning] 211-211: Access to a protected member _url of a client class

(W0212)

src/mcp_agent/workflows/llm/multipart_converter_openai.py (3)

78-82: Minor style – Yoda condition

1 == len(multipart_msg.content) reads backwards. Prefer the conventional order for readability:

-if 1 == len(multipart_msg.content) and is_text_content(
+if len(multipart_msg.content) == 1 and is_text_content(
🧰 Tools
🪛 Ruff (0.11.9)

78-78: Yoda condition detected

Rewrite as len(multipart_msg.content) == 1

(SIM300)


240-257: Early returns remove need for elif/else

After returning a block you can omit subsequent elifs to reduce nesting. This will also satisfy the linter’s R1705 warnings.

🧰 Tools
🪛 Pylint (3.3.7)

[refactor] 250-256: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


462-496: Parameter naming mismatch

As with the Google converter, the parameter is singular (message) while the doc-string describes a collection. Reconcile to avoid confusion.

src/mcp_agent/workflows/llm/multipart_converter_azure.py (4)

1-15: Add a module-level docstring with purpose & usage context

This module is ~300 LOC and introduces non-trivial business logic plus public helpers (e.g. AzureConverter). A short docstring summarising the intent, external dependencies (Azure Inference SDK, MCP model types), and any noteworthy constraints (e.g. only certain MIME types supported, assistant text-only rule) will greatly improve discoverability and linters will stop flagging C0114.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 1-1: Missing module docstring

(C0114)


[error] 3-15: Unable to import 'azure.ai.inference.models'

(E0401)


70-74: Remove unnecessary else blocks after early return

Both branches return immediately, making the following else: superfluous and triggering Pylint R1705. Dropping the else also reduces indentation:

-    if not multipart_msg.content:
-        if role == "assistant":
-            return AssistantMessage(content="")
-        else:
-            return UserMessage(content="")
+    if not multipart_msg.content:
+        return (
+            AssistantMessage(content="")
+            if str(role).lower() == "assistant"
+            else UserMessage(content="")
+        )
🧰 Tools
🪛 Pylint (3.3.7)

[refactor] 71-74: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


133-146: Potential size explosion when embedding large images as data-URL

Images without an external URI are converted to data: URLs with base64 content. This may exceed Azure’s token / size limits and can degrade performance. Consider:

  • uploading the blob to temporary object storage and using an HTTPS URL, or
  • truncating / rejecting images above a configured size threshold.

Add at least a warning and size check.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 137-137: Line too long (112/100)

(C0301)


252-270: tool_use_id parameter is unused

Both the function signature and loop variable tool_use_id are ignored, flagged by Ruff (B007) and Pylint (W0613/W0612). Remove them or use them (e.g. prepend tool name in fallback text):

- def convert_tool_result_to_azure(tool_result: CallToolResult, tool_use_id: str) -> ChatResponseMessage:
+ def convert_tool_result_to_azure(tool_result: CallToolResult) -> ChatResponseMessage:
...
- for item in tool_result.content:
+ for item in tool_result.content:
🧰 Tools
🪛 Pylint (3.3.7)

[warning] 252-252: Unused argument 'tool_use_id'

(W0613)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f069e02 and cbbbd9c.

📒 Files selected for processing (39)
  • examples/mcp_primitives/mcp_basic_agent/README.md (1 hunks)
  • examples/mcp_primitives/mcp_basic_agent/demo_server.py (1 hunks)
  • examples/mcp_primitives/mcp_basic_agent/main.py (1 hunks)
  • examples/mcp_primitives/mcp_basic_agent/mcp_agent.config.yaml (1 hunks)
  • examples/mcp_primitives/mcp_basic_agent/mcp_agent.secrets.yaml.example (1 hunks)
  • examples/mcp_primitives/mcp_basic_agent/requirements.txt (1 hunks)
  • src/mcp_agent/agents/agent.py (9 hunks)
  • src/mcp_agent/core/exceptions.py (1 hunks)
  • src/mcp_agent/mcp/mcp_aggregator.py (14 hunks)
  • src/mcp_agent/utils/content_utils.py (1 hunks)
  • src/mcp_agent/utils/mime_utils.py (1 hunks)
  • src/mcp_agent/utils/prompt_message_multipart.py (1 hunks)
  • src/mcp_agent/utils/resource_utils.py (1 hunks)
  • src/mcp_agent/workflows/llm/augmented_llm.py (5 hunks)
  • src/mcp_agent/workflows/llm/augmented_llm_anthropic.py (2 hunks)
  • src/mcp_agent/workflows/llm/augmented_llm_azure.py (2 hunks)
  • src/mcp_agent/workflows/llm/augmented_llm_bedrock.py (2 hunks)
  • src/mcp_agent/workflows/llm/augmented_llm_google.py (2 hunks)
  • src/mcp_agent/workflows/llm/augmented_llm_openai.py (4 hunks)
  • src/mcp_agent/workflows/llm/multipart_converter_anthropic.py (1 hunks)
  • src/mcp_agent/workflows/llm/multipart_converter_azure.py (1 hunks)
  • src/mcp_agent/workflows/llm/multipart_converter_bedrock.py (1 hunks)
  • src/mcp_agent/workflows/llm/multipart_converter_google.py (1 hunks)
  • src/mcp_agent/workflows/llm/multipart_converter_openai.py (1 hunks)
  • tests/mcp/test_mcp_aggregator.py (1 hunks)
  • tests/utils/test_content_utils.py (1 hunks)
  • tests/utils/test_mime_utils.py (1 hunks)
  • tests/utils/test_multipart_converter_anthropic.py (1 hunks)
  • tests/utils/test_multipart_converter_azure.py (1 hunks)
  • tests/utils/test_multipart_converter_bedrock.py (1 hunks)
  • tests/utils/test_multipart_converter_google.py (1 hunks)
  • tests/utils/test_multipart_converter_openai.py (1 hunks)
  • tests/utils/test_prompt_message_multipart.py (1 hunks)
  • tests/utils/test_resource_utils.py (1 hunks)
  • tests/workflows/llm/test_augmented_llm_anthropic.py (2 hunks)
  • tests/workflows/llm/test_augmented_llm_azure.py (1 hunks)
  • tests/workflows/llm/test_augmented_llm_bedrock.py (1 hunks)
  • tests/workflows/llm/test_augmented_llm_google.py (1 hunks)
  • tests/workflows/llm/test_augmented_llm_openai.py (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (9)
src/mcp_agent/utils/prompt_message_multipart.py (1)
src/mcp_agent/utils/content_utils.py (1)
  • get_text (19-41)
tests/utils/test_content_utils.py (1)
src/mcp_agent/utils/content_utils.py (6)
  • get_image_data (44-65)
  • get_resource_uri (68-83)
  • get_text (19-41)
  • is_image_content (101-113)
  • is_resource_content (116-128)
  • is_text_content (86-98)
tests/utils/test_multipart_converter_google.py (3)
src/mcp_agent/utils/prompt_message_multipart.py (1)
  • PromptMessageMultipart (16-151)
src/mcp_agent/workflows/llm/multipart_converter_google.py (4)
  • GoogleConverter (39-370)
  • convert_to_google (55-73)
  • convert_prompt_message_to_google (76-87)
  • convert_tool_result_to_google (279-312)
tests/utils/test_multipart_converter_azure.py (14)
  • test_is_supported_image_type_supported (18-22)
  • test_is_supported_image_type_unsupported (24-27)
  • test_convert_embedded_resource_text (84-93)
  • test_convert_embedded_resource_svg (106-116)
  • test_convert_embedded_resource_image_unsupported (140-149)
  • test_convert_embedded_resource_image_missing_data (151-160)
  • test_determine_mime_type_from_resource_attribute (162-167)
  • test_determine_mime_type_from_uri (169-177)
  • test_determine_mime_type_blob_fallback (179-186)
  • test_determine_mime_type_default_fallback (188-195)
  • test_create_fallback_text_without_uri (216-222)
  • test_create_fallback_text_with_uri (224-234)
  • test_create_tool_results_message (259-273)
  • test_convert_tool_result_with_embedded_resource (275-289)
tests/utils/test_mime_utils.py (1)
src/mcp_agent/utils/mime_utils.py (4)
  • guess_mime_type (34-39)
  • is_binary_content (62-64)
  • is_image_mime_type (67-69)
  • is_text_mime_type (42-59)
src/mcp_agent/workflows/llm/multipart_converter_google.py (5)
src/mcp_agent/logging/logger.py (1)
  • get_logger (286-303)
src/mcp_agent/utils/content_utils.py (5)
  • get_image_data (44-65)
  • get_text (19-41)
  • is_image_content (101-113)
  • is_resource_content (116-128)
  • is_text_content (86-98)
src/mcp_agent/utils/mime_utils.py (3)
  • guess_mime_type (34-39)
  • is_image_mime_type (67-69)
  • is_text_mime_type (42-59)
src/mcp_agent/utils/prompt_message_multipart.py (1)
  • PromptMessageMultipart (16-151)
src/mcp_agent/utils/resource_utils.py (1)
  • extract_title_from_uri (200-222)
src/mcp_agent/workflows/llm/multipart_converter_bedrock.py (5)
src/mcp_agent/logging/logger.py (1)
  • get_logger (286-303)
src/mcp_agent/utils/content_utils.py (6)
  • get_image_data (44-65)
  • get_resource_uri (68-83)
  • get_text (19-41)
  • is_image_content (101-113)
  • is_resource_content (116-128)
  • is_text_content (86-98)
src/mcp_agent/utils/mime_utils.py (3)
  • guess_mime_type (34-39)
  • is_image_mime_type (67-69)
  • is_text_mime_type (42-59)
src/mcp_agent/utils/prompt_message_multipart.py (1)
  • PromptMessageMultipart (16-151)
src/mcp_agent/utils/resource_utils.py (1)
  • extract_title_from_uri (200-222)
src/mcp_agent/workflows/llm/multipart_converter_anthropic.py (5)
src/mcp_agent/logging/logger.py (2)
  • get_logger (286-303)
  • warning (125-133)
src/mcp_agent/utils/content_utils.py (6)
  • get_image_data (44-65)
  • get_resource_uri (68-83)
  • get_text (19-41)
  • is_image_content (101-113)
  • is_resource_content (116-128)
  • is_text_content (86-98)
src/mcp_agent/utils/mime_utils.py (3)
  • guess_mime_type (34-39)
  • is_image_mime_type (67-69)
  • is_text_mime_type (42-59)
src/mcp_agent/utils/prompt_message_multipart.py (1)
  • PromptMessageMultipart (16-151)
src/mcp_agent/utils/resource_utils.py (1)
  • extract_title_from_uri (200-222)
src/mcp_agent/workflows/llm/multipart_converter_azure.py (5)
src/mcp_agent/logging/logger.py (2)
  • get_logger (286-303)
  • warning (125-133)
src/mcp_agent/utils/content_utils.py (6)
  • get_image_data (44-65)
  • get_resource_uri (68-83)
  • get_text (19-41)
  • is_image_content (101-113)
  • is_resource_content (116-128)
  • is_text_content (86-98)
src/mcp_agent/utils/mime_utils.py (3)
  • guess_mime_type (34-39)
  • is_image_mime_type (67-69)
  • is_text_mime_type (42-59)
src/mcp_agent/utils/prompt_message_multipart.py (1)
  • PromptMessageMultipart (16-151)
src/mcp_agent/utils/resource_utils.py (1)
  • extract_title_from_uri (200-222)
tests/workflows/llm/test_augmented_llm_google.py (6)
tests/workflows/llm/test_augmented_llm_anthropic.py (1)
  • mock_llm (28-54)
tests/workflows/llm/test_augmented_llm_bedrock.py (1)
  • mock_llm (26-50)
tests/workflows/llm/test_augmented_llm_openai.py (1)
  • mock_llm (30-54)
tests/workflows/llm/test_augmented_llm_azure.py (1)
  • mock_llm (41-83)
tests/workflows/parallel/conftest.py (1)
  • mock_llm (32-40)
src/mcp_agent/workflows/llm/augmented_llm_google.py (3)
  • generate (75-193)
  • generate_str (195-221)
  • generate_structured (223-262)
🪛 Pylint (3.3.7)
tests/utils/test_prompt_message_multipart.py

[convention] 1-1: Missing module docstring

(C0114)


[error] 1-8: Unable to import 'mcp.types'

(E0401)


[error] 10-10: Unable to import 'mcp_agent.utils.prompt_message_multipart'

(E0401)


[convention] 13-13: Missing class docstring

(C0115)


[convention] 14-14: Missing function or method docstring

(C0116)


[convention] 20-20: Missing function or method docstring

(C0116)


[convention] 24-24: Missing function or method docstring

(C0116)


[convention] 35-35: Missing function or method docstring

(C0116)


[convention] 48-48: Missing function or method docstring

(C0116)


[convention] 68-68: Missing function or method docstring

(C0116)


[convention] 83-83: Missing function or method docstring

(C0116)


[convention] 93-93: Missing function or method docstring

(C0116)


[convention] 101-101: Missing function or method docstring

(C0116)


[convention] 111-111: Missing function or method docstring

(C0116)


[convention] 121-121: Missing function or method docstring

(C0116)


[convention] 129-129: Missing function or method docstring

(C0116)


[convention] 139-139: Missing function or method docstring

(C0116)


[convention] 147-147: Missing function or method docstring

(C0116)


[convention] 158-158: Missing function or method docstring

(C0116)


[convention] 173-173: Missing function or method docstring

(C0116)


[convention] 184-184: Missing function or method docstring

(C0116)


[convention] 188-188: Missing function or method docstring

(C0116)

examples/mcp_primitives/mcp_basic_agent/main.py

[convention] 1-1: Missing module docstring

(C0114)


[error] 4-4: Unable to import 'mcp_agent.app'

(E0401)


[error] 5-11: Unable to import 'mcp_agent.config'

(E0401)


[error] 12-12: Unable to import 'mcp_agent.agents.agent'

(E0401)


[error] 13-13: Unable to import 'mcp_agent.workflows.llm.augmented_llm_openai'

(E0401)


[convention] 36-36: Missing function or method docstring

(C0116)

tests/mcp/test_mcp_aggregator.py

[error] 632-632: Unable to import 'mcp.types'

(E0401)


[convention] 632-632: Import outside toplevel (mcp.types.Tool, mcp.types.Prompt, mcp.types.Resource)

(C0415)


[refactor] 646-651: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[warning] 660-660: Access to a protected member _namespaced_tool_map of a client class

(W0212)


[warning] 661-661: Access to a protected member _namespaced_prompt_map of a client class

(W0212)


[warning] 662-662: Access to a protected member _namespaced_resource_map of a client class

(W0212)


[warning] 665-665: Access to a protected member _namespaced_tool_map of a client class

(W0212)


[warning] 666-666: Access to a protected member _server_to_tool_map of a client class

(W0212)


[warning] 667-667: Access to a protected member _namespaced_prompt_map of a client class

(W0212)


[warning] 668-668: Access to a protected member _server_to_prompt_map of a client class

(W0212)


[warning] 669-669: Access to a protected member _namespaced_resource_map of a client class

(W0212)


[warning] 670-670: Access to a protected member _server_to_resource_map of a client class

(W0212)


[warning] 673-673: Access to a protected member _namespaced_tool_map of a client class

(W0212)


[warning] 674-674: Access to a protected member _namespaced_tool_map of a client class

(W0212)


[warning] 675-675: Access to a protected member _namespaced_resource_map of a client class

(W0212)


[warning] 676-676: Access to a protected member _namespaced_resource_map of a client class

(W0212)


[warning] 677-677: Access to a protected member _namespaced_prompt_map of a client class

(W0212)


[warning] 678-678: Access to a protected member _namespaced_prompt_map of a client class

(W0212)

examples/mcp_primitives/mcp_basic_agent/demo_server.py

[convention] 16-16: Line too long (113/100)

(C0301)


[convention] 1-1: Missing module docstring

(C0114)


[error] 1-1: Unable to import 'mcp.server.fastmcp'

(E0401)


[convention] 2-2: standard import "datetime" should be placed before third party import "mcp.server.fastmcp.FastMCP"

(C0411)


[convention] 3-3: standard import "json" should be placed before third party import "mcp.server.fastmcp.FastMCP"

(C0411)

tests/utils/test_multipart_converter_anthropic.py

[convention] 1-1: Missing module docstring

(C0114)


[error] 2-10: Unable to import 'mcp.types'

(E0401)


[error] 12-12: Unable to import 'mcp_agent.utils.prompt_message_multipart'

(E0401)


[error] 13-13: Unable to import 'mcp_agent.workflows.llm.multipart_converter_anthropic'

(E0401)


[convention] 16-16: Missing class docstring

(C0115)


[convention] 17-17: Missing function or method docstring

(C0116)


[warning] 18-18: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 19-19: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 20-20: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 21-21: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 23-23: Missing function or method docstring

(C0116)


[warning] 24-24: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 25-25: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 26-26: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 28-28: Missing function or method docstring

(C0116)


[convention] 35-35: Missing function or method docstring

(C0116)


[convention] 45-45: Missing function or method docstring

(C0116)


[convention] 57-57: Missing function or method docstring

(C0116)


[convention] 67-67: Missing function or method docstring

(C0116)


[convention] 80-80: Missing function or method docstring

(C0116)


[convention] 91-91: Missing function or method docstring

(C0116)


[warning] 97-97: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 108-108: Missing function or method docstring

(C0116)


[warning] 114-114: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 121-121: Missing function or method docstring

(C0116)


[warning] 127-127: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 136-136: Missing function or method docstring

(C0116)


[warning] 142-142: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 148-148: Missing function or method docstring

(C0116)


[warning] 154-154: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 160-160: Missing function or method docstring

(C0116)


[warning] 166-166: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 171-171: Missing function or method docstring

(C0116)


[warning] 175-175: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 178-178: Missing function or method docstring

(C0116)


[warning] 185-185: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 188-188: Missing function or method docstring

(C0116)


[warning] 194-194: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 197-197: Missing function or method docstring

(C0116)


[warning] 203-203: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 206-206: Missing function or method docstring

(C0116)


[warning] 210-210: Access to a protected member _convert_svg_resource of a client class

(W0212)


[convention] 216-216: Missing function or method docstring

(C0116)


[warning] 220-220: Access to a protected member _convert_svg_resource of a client class

(W0212)


[convention] 225-225: Missing function or method docstring

(C0116)


[warning] 228-228: Access to a protected member _create_fallback_text of a client class

(W0212)


[convention] 233-233: Missing function or method docstring

(C0116)


[convention] 248-248: Missing function or method docstring

(C0116)


[convention] 260-260: Missing function or method docstring

(C0116)


[refactor] 16-16: Too many public methods (24/20)

(R0904)

tests/utils/test_multipart_converter_azure.py

[convention] 1-1: Missing module docstring

(C0114)


[error] 2-10: Unable to import 'mcp.types'

(E0401)


[error] 11-11: Unable to import 'pydantic'

(E0401)


[error] 13-13: Unable to import 'mcp_agent.utils.prompt_message_multipart'

(E0401)


[error] 14-14: Unable to import 'mcp_agent.workflows.llm.multipart_converter_azure'

(E0401)


[convention] 17-17: Missing class docstring

(C0115)


[convention] 18-18: Missing function or method docstring

(C0116)


[warning] 19-19: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 20-20: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 21-21: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 22-22: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 24-24: Missing function or method docstring

(C0116)


[warning] 25-25: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 26-26: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 27-27: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 29-29: Missing function or method docstring

(C0116)


[convention] 36-36: Missing function or method docstring

(C0116)


[convention] 45-45: Missing function or method docstring

(C0116)


[convention] 54-54: Missing function or method docstring

(C0116)


[convention] 63-63: Missing function or method docstring

(C0116)


[convention] 74-74: Missing function or method docstring

(C0116)


[convention] 84-84: Missing function or method docstring

(C0116)


[warning] 90-90: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 95-95: Missing function or method docstring

(C0116)


[warning] 101-101: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 106-106: Missing function or method docstring

(C0116)


[warning] 112-112: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 118-118: Missing function or method docstring

(C0116)


[warning] 124-124: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 129-129: Missing function or method docstring

(C0116)


[warning] 135-135: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 140-140: Missing function or method docstring

(C0116)


[warning] 146-146: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 151-151: Missing function or method docstring

(C0116)


[warning] 157-157: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 162-162: Missing function or method docstring

(C0116)


[warning] 166-166: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 169-169: Missing function or method docstring

(C0116)


[warning] 176-176: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 179-179: Missing function or method docstring

(C0116)


[warning] 185-185: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 188-188: Missing function or method docstring

(C0116)


[warning] 194-194: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 197-197: Missing function or method docstring

(C0116)


[warning] 201-201: Access to a protected member _convert_svg_resource of a client class

(W0212)


[convention] 207-207: Missing function or method docstring

(C0116)


[warning] 211-211: Access to a protected member _convert_svg_resource of a client class

(W0212)


[convention] 216-216: Missing function or method docstring

(C0116)


[warning] 219-219: Access to a protected member _create_fallback_text of a client class

(W0212)


[convention] 224-224: Missing function or method docstring

(C0116)


[warning] 231-231: Access to a protected member _create_fallback_text of a client class

(W0212)


[convention] 236-236: Missing function or method docstring

(C0116)


[convention] 248-248: Missing function or method docstring

(C0116)


[convention] 259-259: Missing function or method docstring

(C0116)


[convention] 275-275: Missing function or method docstring

(C0116)


[convention] 291-291: Missing function or method docstring

(C0116)


[refactor] 17-17: Too many public methods (28/20)

(R0904)

src/mcp_agent/utils/mime_utils.py

[convention] 1-1: Missing module docstring

(C0114)

src/mcp_agent/utils/prompt_message_multipart.py

[convention] 1-1: Missing module docstring

(C0114)


[error] 3-10: Unable to import 'mcp.types'

(E0401)


[error] 11-11: Unable to import 'pydantic'

(E0401)


[error] 13-13: Unable to import 'mcp_agent.utils.content_utils'

(E0401)


[convention] 115-115: Missing function or method docstring

(C0116)

tests/utils/test_multipart_converter_bedrock.py

[convention] 1-1: Missing module docstring

(C0114)


[error] 2-10: Unable to import 'mcp.types'

(E0401)


[error] 11-11: Unable to import 'pydantic'

(E0401)


[error] 13-13: Unable to import 'mcp_agent.utils.prompt_message_multipart'

(E0401)


[error] 14-14: Unable to import 'mcp_agent.workflows.llm.multipart_converter_bedrock'

(E0401)


[convention] 17-17: Missing class docstring

(C0115)


[convention] 18-18: Missing function or method docstring

(C0116)


[warning] 19-19: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 20-20: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 22-22: Missing function or method docstring

(C0116)


[warning] 23-23: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 24-24: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 25-25: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 26-26: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 27-27: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 29-29: Missing function or method docstring

(C0116)


[convention] 36-36: Missing function or method docstring

(C0116)


[convention] 45-45: Missing function or method docstring

(C0116)


[convention] 56-56: Missing function or method docstring

(C0116)


[convention] 66-66: Missing function or method docstring

(C0116)


[convention] 76-76: Missing function or method docstring

(C0116)


[warning] 82-82: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 87-87: Missing function or method docstring

(C0116)


[warning] 93-93: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 102-102: Missing function or method docstring

(C0116)


[warning] 108-108: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 113-113: Missing function or method docstring

(C0116)


[warning] 119-119: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 125-125: Missing function or method docstring

(C0116)


[warning] 131-131: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 137-137: Missing function or method docstring

(C0116)


[warning] 143-143: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 148-148: Missing function or method docstring

(C0116)


[warning] 154-154: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 159-159: Missing function or method docstring

(C0116)


[warning] 165-165: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 170-170: Missing function or method docstring

(C0116)


[warning] 178-178: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 185-185: Missing function or method docstring

(C0116)


[warning] 189-189: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 192-192: Missing function or method docstring

(C0116)


[warning] 199-199: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 202-202: Missing function or method docstring

(C0116)


[warning] 208-208: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 211-211: Missing function or method docstring

(C0116)


[warning] 217-217: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 220-220: Missing function or method docstring

(C0116)


[warning] 224-224: Access to a protected member _convert_svg_resource of a client class

(W0212)


[convention] 230-230: Missing function or method docstring

(C0116)


[warning] 234-234: Access to a protected member _convert_svg_resource of a client class

(W0212)


[convention] 239-239: Missing function or method docstring

(C0116)


[warning] 242-242: Access to a protected member _create_fallback_text of a client class

(W0212)


[convention] 247-247: Missing function or method docstring

(C0116)


[warning] 254-254: Access to a protected member _create_fallback_text of a client class

(W0212)


[convention] 259-259: Missing function or method docstring

(C0116)


[convention] 273-273: Missing function or method docstring

(C0116)


[convention] 287-287: Missing function or method docstring

(C0116)


[convention] 302-302: Missing function or method docstring

(C0116)


[convention] 326-326: Missing function or method docstring

(C0116)


[convention] 344-344: Missing function or method docstring

(C0116)


[refactor] 17-17: Too many public methods (30/20)

(R0904)

tests/workflows/llm/test_augmented_llm_openai.py

[error] 14-14: Unable to import 'mcp.types'

(E0401)


[convention] 617-617: Missing class docstring

(C0115)


[refactor] 617-617: Too few public methods (0/2)

(R0903)

tests/utils/test_content_utils.py

[convention] 1-1: Missing module docstring

(C0114)


[error] 1-7: Unable to import 'mcp.types'

(E0401)


[error] 9-16: Unable to import 'mcp_agent.utils.content_utils'

(E0401)


[convention] 19-19: Missing class docstring

(C0115)


[convention] 20-20: Missing function or method docstring

(C0116)


[convention] 24-24: Missing function or method docstring

(C0116)


[convention] 30-30: Missing function or method docstring

(C0116)


[convention] 37-37: Missing function or method docstring

(C0116)


[convention] 46-46: Missing function or method docstring

(C0116)


[convention] 51-51: Missing class docstring

(C0115)


[convention] 52-52: Missing function or method docstring

(C0116)


[convention] 58-58: Missing function or method docstring

(C0116)


[convention] 65-65: Missing function or method docstring

(C0116)


[convention] 69-69: Missing function or method docstring

(C0116)


[convention] 77-77: Missing class docstring

(C0115)


[convention] 78-78: Missing function or method docstring

(C0116)


[convention] 85-85: Missing function or method docstring

(C0116)


[convention] 89-89: Missing function or method docstring

(C0116)


[convention] 94-94: Missing class docstring

(C0115)


[convention] 95-95: Missing function or method docstring

(C0116)


[convention] 99-99: Missing function or method docstring

(C0116)


[convention] 105-105: Missing function or method docstring

(C0116)


[convention] 109-109: Missing function or method docstring

(C0116)


[convention] 117-117: Missing class docstring

(C0115)


[convention] 118-118: Missing function or method docstring

(C0116)


[convention] 122-122: Missing function or method docstring

(C0116)


[convention] 126-126: Missing function or method docstring

(C0116)


[convention] 134-134: Missing class docstring

(C0115)


[convention] 135-135: Missing function or method docstring

(C0116)


[convention] 142-142: Missing function or method docstring

(C0116)


[convention] 146-146: Missing function or method docstring

(C0116)

src/mcp_agent/utils/content_utils.py

[error] 10-16: Unable to import 'mcp.types'

(E0401)


[refactor] 98-98: Consider merging these isinstance calls to isinstance(content, (TextContent, TextResourceContents))

(R1701)

tests/workflows/llm/test_augmented_llm_anthropic.py

[error] 7-7: Unable to import 'mcp.types'

(E0401)


[convention] 7-7: third party import "mcp.types.TextContent" should be placed before first party import "mcp_agent.config.AnthropicSettings"

(C0411)


[convention] 785-785: Missing class docstring

(C0115)


[refactor] 785-785: Too few public methods (0/2)

(R0903)

tests/utils/test_multipart_converter_openai.py

[convention] 202-202: Line too long (130/100)

(C0301)


[convention] 1-1: Missing module docstring

(C0114)


[error] 2-10: Unable to import 'mcp.types'

(E0401)


[error] 12-12: Unable to import 'mcp_agent.utils.prompt_message_multipart'

(E0401)


[error] 13-13: Unable to import 'mcp_agent.workflows.llm.multipart_converter_openai'

(E0401)


[convention] 16-16: Missing class docstring

(C0115)


[convention] 17-17: Missing function or method docstring

(C0116)


[warning] 18-18: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 19-19: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 20-20: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 21-21: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 23-23: Missing function or method docstring

(C0116)


[warning] 24-24: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 25-25: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 26-26: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 28-28: Missing function or method docstring

(C0116)


[convention] 35-35: Missing function or method docstring

(C0116)


[convention] 43-43: Missing function or method docstring

(C0116)


[convention] 66-66: Missing function or method docstring

(C0116)


[convention] 82-82: Missing function or method docstring

(C0116)


[warning] 90-90: Access to a protected member _concatenate_text_blocks of a client class

(W0212)


[convention] 99-99: Missing function or method docstring

(C0116)


[warning] 100-100: Access to a protected member _concatenate_text_blocks of a client class

(W0212)


[convention] 103-103: Missing function or method docstring

(C0116)


[convention] 112-112: Missing function or method docstring

(C0116)


[warning] 116-116: Access to a protected member _convert_image_content of a client class

(W0212)


[convention] 121-121: Missing function or method docstring

(C0116)


[warning] 129-129: Access to a protected member _convert_image_content of a client class

(W0212)


[convention] 134-134: Missing function or method docstring

(C0116)


[warning] 138-138: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 141-141: Missing function or method docstring

(C0116)


[warning] 146-146: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 149-149: Missing function or method docstring

(C0116)


[warning] 155-155: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 158-158: Missing function or method docstring

(C0116)


[warning] 164-164: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 167-167: Missing function or method docstring

(C0116)


[warning] 173-173: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 178-178: Missing function or method docstring

(C0116)


[warning] 184-184: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 189-189: Missing function or method docstring

(C0116)


[warning] 197-197: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 205-205: Missing function or method docstring

(C0116)


[warning] 211-211: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 217-217: Missing function or method docstring

(C0116)


[warning] 223-223: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 232-232: Missing function or method docstring

(C0116)


[warning] 238-238: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 247-247: Missing function or method docstring

(C0116)


[warning] 255-255: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 262-262: Missing function or method docstring

(C0116)


[warning] 263-263: Access to a protected member _extract_text_from_content_blocks of a client class

(W0212)


[convention] 266-266: Missing function or method docstring

(C0116)


[warning] 273-273: Access to a protected member _extract_text_from_content_blocks of a client class

(W0212)


[convention] 276-276: Missing function or method docstring

(C0116)


[warning] 277-277: Access to a protected member _extract_text_from_content_blocks of a client class

(W0212)


[convention] 280-280: Missing function or method docstring

(C0116)


[warning] 285-285: Access to a protected member _extract_text_from_content_blocks of a client class

(W0212)


[convention] 288-288: Missing function or method docstring

(C0116)


[convention] 298-298: Missing function or method docstring

(C0116)


[convention] 307-307: Missing function or method docstring

(C0116)


[convention] 328-328: Missing function or method docstring

(C0116)


[convention] 348-348: Missing function or method docstring

(C0116)


[refactor] 16-16: Too many public methods (31/20)

(R0904)

tests/utils/test_multipart_converter_google.py

[convention] 1-1: Missing module docstring

(C0114)


[error] 2-10: Unable to import 'mcp.types'

(E0401)


[error] 12-12: Unable to import 'mcp_agent.utils.prompt_message_multipart'

(E0401)


[error] 13-13: Unable to import 'mcp_agent.workflows.llm.multipart_converter_google'

(E0401)


[convention] 16-16: Missing class docstring

(C0115)


[convention] 17-17: Missing function or method docstring

(C0116)


[warning] 18-18: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 19-19: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 20-20: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 21-21: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 23-23: Missing function or method docstring

(C0116)


[warning] 24-24: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 25-25: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 26-26: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 28-28: Missing function or method docstring

(C0116)


[convention] 35-35: Missing function or method docstring

(C0116)


[convention] 50-50: Missing function or method docstring

(C0116)


[convention] 71-71: Missing function or method docstring

(C0116)


[warning] 85-85: Unused variable 'args'

(W0612)


[convention] 88-88: Missing function or method docstring

(C0116)


[warning] 102-102: Unused variable 'args'

(W0612)


[convention] 105-105: Missing function or method docstring

(C0116)


[convention] 121-121: Missing function or method docstring

(C0116)


[warning] 133-133: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 137-137: Missing function or method docstring

(C0116)


[warning] 149-149: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 152-152: Unused variable 'args'

(W0612)


[convention] 155-155: Missing function or method docstring

(C0116)


[warning] 169-169: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 176-176: Missing function or method docstring

(C0116)


[warning] 188-188: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 191-191: Unused variable 'args'

(W0612)


[convention] 194-194: Missing function or method docstring

(C0116)


[warning] 206-206: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 209-209: Unused variable 'args'

(W0612)


[convention] 213-213: Missing function or method docstring

(C0116)


[warning] 227-227: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 234-234: Missing function or method docstring

(C0116)


[warning] 246-246: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 249-249: Unused variable 'args'

(W0612)


[convention] 252-252: Missing function or method docstring

(C0116)


[warning] 264-264: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 267-267: Unused variable 'args'

(W0612)


[convention] 270-270: Missing function or method docstring

(C0116)


[warning] 284-284: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 287-287: Unused variable 'args'

(W0612)


[convention] 291-291: Missing function or method docstring

(C0116)


[warning] 295-295: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 298-298: Missing function or method docstring

(C0116)


[warning] 305-305: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 308-308: Missing function or method docstring

(C0116)


[warning] 314-314: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 317-317: Missing function or method docstring

(C0116)


[warning] 323-323: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 326-326: Missing function or method docstring

(C0116)


[warning] 336-336: Access to a protected member _convert_svg_resource of a client class

(W0212)


[warning] 338-338: Unused variable 'args'

(W0612)


[convention] 342-342: Missing function or method docstring

(C0116)


[warning] 352-352: Access to a protected member _convert_svg_resource of a client class

(W0212)


[warning] 354-354: Unused variable 'args'

(W0612)


[convention] 357-357: Missing function or method docstring

(C0116)


[warning] 366-366: Access to a protected member _create_fallback_text of a client class

(W0212)


[warning] 368-368: Unused variable 'args'

(W0612)


[convention] 371-371: Missing function or method docstring

(C0116)


[error] 372-372: Unable to import 'pydantic'

(E0401)


[convention] 372-372: Import outside toplevel (pydantic.AnyUrl)

(C0415)


[warning] 386-386: Access to a protected member _create_fallback_text of a client class

(W0212)


[warning] 388-388: Unused variable 'args'

(W0612)


[convention] 391-391: Missing function or method docstring

(C0116)


[convention] 407-407: Missing function or method docstring

(C0116)


[warning] 420-420: Unused variable 'args'

(W0612)


[convention] 425-425: Missing function or method docstring

(C0116)


[convention] 443-443: Missing function or method docstring

(C0116)


[convention] 467-467: Missing function or method docstring

(C0116)


[convention] 488-488: Missing function or method docstring

(C0116)


[refactor] 16-16: Too many public methods (31/20)

(R0904)

src/mcp_agent/workflows/llm/augmented_llm_openai.py

[refactor] 148-148: Too many local variables (27/15)

(R0914)


[refactor] 148-148: Too many branches (23/12)

(R0912)


[refactor] 148-148: Too many statements (93/50)

(R0915)

tests/workflows/llm/test_augmented_llm_bedrock.py

[warning] 613-613: Redefining name 'TextContent' from outer scope (line 7)

(W0621)


[error] 613-613: Unable to import 'mcp.types'

(E0401)


[warning] 613-613: Reimport 'TextContent' (imported line 7)

(W0404)


[convention] 613-613: Import outside toplevel (mcp.types.PromptMessage, mcp.types.TextContent)

(C0415)


[warning] 638-638: Redefining name 'TextContent' from outer scope (line 7)

(W0621)


[error] 638-638: Unable to import 'mcp.types'

(E0401)


[warning] 638-638: Reimport 'TextContent' (imported line 7)

(W0404)


[convention] 638-638: Import outside toplevel (mcp.types.PromptMessage, mcp.types.TextContent)

(C0415)


[warning] 661-661: Redefining name 'TextContent' from outer scope (line 7)

(W0621)


[error] 661-661: Unable to import 'mcp.types'

(E0401)


[warning] 661-661: Reimport 'TextContent' (imported line 7)

(W0404)


[convention] 661-661: Import outside toplevel (mcp.types.PromptMessage, mcp.types.TextContent)

(C0415)


[warning] 683-683: Redefining name 'BaseModel' from outer scope (line 5)

(W0621)


[warning] 684-684: Redefining name 'TextContent' from outer scope (line 7)

(W0621)


[error] 683-683: Unable to import 'pydantic'

(E0401)


[warning] 683-683: Reimport 'BaseModel' (imported line 5)

(W0404)


[convention] 683-683: Import outside toplevel (pydantic.BaseModel)

(C0415)


[error] 684-684: Unable to import 'mcp.types'

(E0401)


[warning] 684-684: Reimport 'TextContent' (imported line 7)

(W0404)


[convention] 684-684: Import outside toplevel (mcp.types.PromptMessage, mcp.types.TextContent)

(C0415)


[convention] 686-686: Missing class docstring

(C0115)


[refactor] 686-686: Too few public methods (0/2)

(R0903)

tests/utils/test_mime_utils.py

[convention] 1-1: Missing module docstring

(C0114)


[error] 1-6: Unable to import 'mcp_agent.utils.mime_utils'

(E0401)


[convention] 9-9: Missing class docstring

(C0115)


[convention] 10-10: Missing function or method docstring

(C0116)


[convention] 13-13: Missing function or method docstring

(C0116)


[convention] 16-16: Missing function or method docstring

(C0116)


[convention] 19-19: Missing function or method docstring

(C0116)


[convention] 22-22: Missing function or method docstring

(C0116)


[convention] 25-25: Missing function or method docstring

(C0116)


[convention] 28-28: Missing function or method docstring

(C0116)


[convention] 31-31: Missing function or method docstring

(C0116)


[convention] 35-35: Missing class docstring

(C0115)


[convention] 36-36: Missing function or method docstring

(C0116)


[convention] 39-39: Missing function or method docstring

(C0116)


[convention] 42-42: Missing function or method docstring

(C0116)


[convention] 45-45: Missing function or method docstring

(C0116)


[convention] 48-48: Missing function or method docstring

(C0116)


[convention] 51-51: Missing function or method docstring

(C0116)


[convention] 54-54: Missing function or method docstring

(C0116)


[convention] 57-57: Missing function or method docstring

(C0116)


[convention] 60-60: Missing function or method docstring

(C0116)


[convention] 63-63: Missing function or method docstring

(C0116)


[convention] 66-66: Missing function or method docstring

(C0116)


[convention] 69-69: Missing function or method docstring

(C0116)


[convention] 72-72: Missing function or method docstring

(C0116)


[convention] 75-75: Missing function or method docstring

(C0116)


[convention] 78-78: Missing function or method docstring

(C0116)


[convention] 81-81: Missing function or method docstring

(C0116)


[convention] 85-85: Missing class docstring

(C0115)


[convention] 86-86: Missing function or method docstring

(C0116)


[convention] 89-89: Missing function or method docstring

(C0116)


[convention] 92-92: Missing function or method docstring

(C0116)


[convention] 95-95: Missing function or method docstring

(C0116)


[convention] 98-98: Missing function or method docstring

(C0116)


[convention] 102-102: Missing class docstring

(C0115)


[convention] 103-103: Missing function or method docstring

(C0116)


[convention] 106-106: Missing function or method docstring

(C0116)


[convention] 109-109: Missing function or method docstring

(C0116)


[convention] 112-112: Missing function or method docstring

(C0116)


[convention] 115-115: Missing function or method docstring

(C0116)


[convention] 119-119: Missing function or method docstring

(C0116)


[convention] 122-122: Missing function or method docstring

(C0116)

src/mcp_agent/utils/resource_utils.py

[convention] 1-1: Missing module docstring

(C0114)


[error] 5-10: Unable to import 'mcp.types'

(E0401)


[error] 11-11: Unable to import 'pydantic'

(E0401)


[refactor] 13-13: Use 'from mcp_agent.utils import mime_utils' instead

(R0402)


[error] 13-13: Unable to import 'mcp_agent.utils.mime_utils'

(E0401)


[warning] 91-91: Redefining name 'EmbeddedResource' from outer scope (line 5)

(W0621)


[warning] 91-91: Redefining name 'TextResourceContents' from outer scope (line 5)

(W0621)


[error] 91-91: Unable to import 'mcp.types'

(E0401)


[warning] 91-91: Reimport 'EmbeddedResource' (imported line 5)

(W0404)


[warning] 91-91: Reimport 'TextResourceContents' (imported line 5)

(W0404)


[convention] 91-91: Import outside toplevel (mcp.types.EmbeddedResource, mcp.types.TextResourceContents)

(C0415)


[refactor] 116-131: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[refactor] 194-197: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[warning] 203-203: Access to a protected member _url of a client class

(W0212)


[warning] 218-218: Catching too general exception Exception

(W0718)


[refactor] 206-216: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[convention] 214-214: Import outside toplevel (os.path)

(C0415)

tests/utils/test_resource_utils.py

[convention] 1-1: Missing module docstring

(C0114)


[error] 7-7: Unable to import 'mcp.types'

(E0401)


[error] 8-8: Unable to import 'pydantic'

(E0401)


[error] 10-21: Unable to import 'mcp_agent.utils.resource_utils'

(E0401)


[convention] 24-24: Missing class docstring

(C0115)


[convention] 25-25: Missing function or method docstring

(C0116)


[convention] 41-41: Missing function or method docstring

(C0116)


[convention] 50-50: Missing function or method docstring

(C0116)


[convention] 75-75: Missing class docstring

(C0115)


[convention] 76-76: Missing function or method docstring

(C0116)


[convention] 94-94: Missing function or method docstring

(C0116)


[convention] 114-114: Missing function or method docstring

(C0116)


[convention] 126-126: Missing class docstring

(C0115)


[convention] 127-127: Missing function or method docstring

(C0116)


[convention] 131-131: Missing function or method docstring

(C0116)


[convention] 136-136: Missing class docstring

(C0115)


[convention] 137-137: Missing function or method docstring

(C0116)


[refactor] 136-136: Too few public methods (1/2)

(R0903)


[convention] 151-151: Missing class docstring

(C0115)


[convention] 152-152: Missing function or method docstring

(C0116)


[convention] 164-164: Missing function or method docstring

(C0116)


[convention] 178-178: Missing class docstring

(C0115)


[convention] 179-179: Missing function or method docstring

(C0116)


[refactor] 178-178: Too few public methods (1/2)

(R0903)


[convention] 190-190: Missing class docstring

(C0115)


[convention] 191-191: Missing function or method docstring

(C0116)


[refactor] 190-190: Too few public methods (1/2)

(R0903)


[convention] 205-205: Missing class docstring

(C0115)


[convention] 206-206: Missing function or method docstring

(C0116)


[refactor] 205-205: Too few public methods (1/2)

(R0903)


[convention] 218-218: Missing class docstring

(C0115)


[convention] 219-219: Missing function or method docstring

(C0116)


[convention] 222-222: Missing function or method docstring

(C0116)


[convention] 226-226: Missing function or method docstring

(C0116)


[convention] 230-230: Missing function or method docstring

(C0116)


[convention] 234-234: Missing function or method docstring

(C0116)


[convention] 238-238: Missing function or method docstring

(C0116)


[convention] 242-242: Missing function or method docstring

(C0116)


[convention] 247-247: Missing class docstring

(C0115)


[convention] 248-248: Missing function or method docstring

(C0116)


[warning] 253-253: Access to a protected member _url of a client class

(W0212)


[convention] 258-258: Missing function or method docstring

(C0116)


[warning] 263-263: Access to a protected member _url of a client class

(W0212)


[convention] 268-268: Missing function or method docstring

(C0116)


[warning] 273-273: Access to a protected member _url of a client class

(W0212)


[convention] 278-278: Missing function or method docstring

(C0116)


[warning] 283-283: Access to a protected member _url of a client class

(W0212)


[convention] 288-288: Missing function or method docstring

(C0116)


[warning] 293-293: Access to a protected member _url of a client class

(W0212)


[convention] 298-298: Missing function or method docstring

(C0116)


[warning] 303-303: Access to a protected member _url of a client class

(W0212)

src/mcp_agent/workflows/llm/multipart_converter_google.py

[convention] 115-115: Line too long (112/100)

(C0301)


[convention] 211-211: Line too long (115/100)

(C0301)


[warning] 156-156: TODO: jerron - check if these are needed

(W0511)


[convention] 1-1: Missing module docstring

(C0114)


[error] 4-4: Unable to import 'google.genai'

(E0401)


[error] 4-4: No name 'genai' in module 'google'

(E0611)


[error] 6-14: Unable to import 'mcp.types'

(E0401)


[refactor] 163-198: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 173-181: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[refactor] 193-198: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[warning] 211-211: Access to a protected member _url of a client class

(W0212)


[refactor] 142-142: Too many return statements (11/6)

(R0911)


[warning] 274-274: Access to a protected member _url of a client class

(W0212)

src/mcp_agent/workflows/llm/multipart_converter_bedrock.py

[convention] 102-102: Line too long (115/100)

(C0301)


[convention] 160-160: Line too long (103/100)

(C0301)


[convention] 185-185: Line too long (139/100)

(C0301)


[warning] 132-132: TODO: jerron - check if we need to handle URLs differently

(W0511)


[convention] 1-1: Missing module docstring

(C0114)


[error] 3-11: Unable to import 'mcp.types'

(E0401)


[refactor] 138-174: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 123-123: Too many return statements (11/6)

(R0911)

tests/workflows/llm/test_augmented_llm_azure.py

[warning] 1132-1132: Redefining name 'TextContent' from outer scope (line 19)

(W0621)


[error] 1132-1132: Unable to import 'mcp.types'

(E0401)


[warning] 1132-1132: Reimport 'TextContent' (imported line 19)

(W0404)


[convention] 1132-1132: Import outside toplevel (mcp.types.PromptMessage, mcp.types.TextContent)

(C0415)


[warning] 1157-1157: Redefining name 'TextContent' from outer scope (line 19)

(W0621)


[error] 1157-1157: Unable to import 'mcp.types'

(E0401)


[warning] 1157-1157: Reimport 'TextContent' (imported line 19)

(W0404)


[convention] 1157-1157: Import outside toplevel (mcp.types.PromptMessage, mcp.types.TextContent)

(C0415)


[warning] 1182-1182: Redefining name 'TextContent' from outer scope (line 19)

(W0621)


[error] 1182-1182: Unable to import 'mcp.types'

(E0401)


[warning] 1182-1182: Reimport 'TextContent' (imported line 19)

(W0404)


[convention] 1182-1182: Import outside toplevel (mcp.types.PromptMessage, mcp.types.TextContent)

(C0415)


[warning] 1208-1208: Redefining name 'BaseModel' from outer scope (line 17)

(W0621)


[warning] 1209-1209: Redefining name 'TextContent' from outer scope (line 19)

(W0621)


[error] 1208-1208: Unable to import 'pydantic'

(E0401)


[warning] 1208-1208: Reimport 'BaseModel' (imported line 17)

(W0404)


[convention] 1208-1208: Import outside toplevel (pydantic.BaseModel)

(C0415)


[error] 1209-1209: Unable to import 'mcp.types'

(E0401)


[warning] 1209-1209: Reimport 'TextContent' (imported line 19)

(W0404)


[convention] 1209-1209: Import outside toplevel (mcp.types.PromptMessage, mcp.types.TextContent)

(C0415)


[convention] 1211-1211: Missing class docstring

(C0115)


[refactor] 1211-1211: Too few public methods (0/2)

(R0903)

src/mcp_agent/workflows/llm/multipart_converter_anthropic.py

[convention] 129-129: Line too long (109/100)

(C0301)


[convention] 153-153: Line too long (113/100)

(C0301)


[convention] 188-188: Line too long (109/100)

(C0301)


[convention] 289-289: Line too long (116/100)

(C0301)


[convention] 370-370: Line too long (104/100)

(C0301)


[convention] 1-1: Missing module docstring

(C0114)


[error] 3-15: Unable to import 'anthropic.types'

(E0401)


[error] 16-24: Unable to import 'mcp.types'

(E0401)


[refactor] 205-275: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 234-249: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[warning] 289-289: Access to a protected member _url of a client class

(W0212)


[refactor] 179-179: Too many return statements (14/6)

(R0911)


[refactor] 179-179: Too many branches (13/12)

(R0912)


[warning] 352-352: Access to a protected member _url of a client class

(W0212)

src/mcp_agent/workflows/llm/multipart_converter_azure.py

[convention] 137-137: Line too long (112/100)

(C0301)


[convention] 215-215: Line too long (131/100)

(C0301)


[convention] 1-1: Missing module docstring

(C0114)


[error] 3-15: Unable to import 'azure.ai.inference.models'

(E0401)


[error] 16-24: Unable to import 'mcp.types'

(E0401)


[refactor] 71-74: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[refactor] 79-93: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[refactor] 175-204: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 155-155: Too many return statements (11/6)

(R0911)


[warning] 252-252: Unused argument 'tool_use_id'

(W0613)


[warning] 295-295: Unused variable 'tool_use_id'

(W0612)

tests/workflows/llm/test_augmented_llm_google.py

[error] 658-658: Unable to import 'google.genai'

(E0401)


[convention] 658-658: Import outside toplevel (google.genai.types)

(C0415)


[error] 658-658: No name 'genai' in module 'google'

(E0611)


[warning] 684-684: Redefining name 'TextContent' from outer scope (line 6)

(W0621)


[error] 684-684: Unable to import 'mcp.types'

(E0401)


[warning] 684-684: Reimport 'TextContent' (imported line 6)

(W0404)


[convention] 684-684: Import outside toplevel (mcp.types.PromptMessage, mcp.types.TextContent)

(C0415)


[warning] 706-706: Redefining name 'TextContent' from outer scope (line 6)

(W0621)


[error] 706-706: Unable to import 'mcp.types'

(E0401)


[warning] 706-706: Reimport 'TextContent' (imported line 6)

(W0404)


[convention] 706-706: Import outside toplevel (mcp.types.PromptMessage, mcp.types.TextContent)

(C0415)


[error] 707-707: Unable to import 'google.genai'

(E0401)


[convention] 707-707: Import outside toplevel (google.genai.types)

(C0415)


[error] 707-707: No name 'genai' in module 'google'

(E0611)


[warning] 732-732: Redefining name 'TextContent' from outer scope (line 6)

(W0621)


[error] 732-732: Unable to import 'mcp.types'

(E0401)


[warning] 732-732: Reimport 'TextContent' (imported line 6)

(W0404)


[convention] 732-732: Import outside toplevel (mcp.types.PromptMessage, mcp.types.TextContent)

(C0415)


[error] 733-733: Unable to import 'google.genai'

(E0401)


[convention] 733-733: Import outside toplevel (google.genai.types)

(C0415)


[error] 733-733: No name 'genai' in module 'google'

(E0611)


[warning] 757-757: Redefining name 'BaseModel' from outer scope (line 4)

(W0621)


[warning] 758-758: Redefining name 'TextContent' from outer scope (line 6)

(W0621)


[error] 757-757: Unable to import 'pydantic'

(E0401)


[warning] 757-757: Reimport 'BaseModel' (imported line 4)

(W0404)


[convention] 757-757: Import outside toplevel (pydantic.BaseModel)

(C0415)


[error] 758-758: Unable to import 'mcp.types'

(E0401)


[warning] 758-758: Reimport 'TextContent' (imported line 6)

(W0404)


[convention] 758-758: Import outside toplevel (mcp.types.PromptMessage, mcp.types.TextContent)

(C0415)


[error] 759-759: Unable to import 'google.genai'

(E0401)


[convention] 759-759: Import outside toplevel (google.genai.types)

(C0415)


[error] 759-759: No name 'genai' in module 'google'

(E0611)


[convention] 761-761: Missing class docstring

(C0115)


[refactor] 761-761: Too few public methods (0/2)

(R0903)

src/mcp_agent/agents/agent.py

[error] 7-7: Unable to import 'pydantic'

(E0401)


[convention] 544-544: Line too long (102/100)

(C0301)


[refactor] 979-979: Too few public methods (0/2)

(R0903)


[refactor] 988-988: Too few public methods (0/2)

(R0903)


[warning] 1060-1060: Access to a protected member _namespaced_resource_map of a client class

(W0212)


[warning] 1061-1061: Access to a protected member _server_to_resource_map of a client class

(W0212)

src/mcp_agent/workflows/llm/multipart_converter_openai.py

[convention] 264-264: Line too long (122/100)

(C0301)


[convention] 365-365: Line too long (105/100)

(C0301)


[convention] 1-1: Missing module docstring

(C0114)


[error] 3-9: Unable to import 'mcp.types'

(E0401)


[error] 10-10: Unable to import 'openai.types.chat'

(E0401)


[warning] 106-106: Catching too general exception Exception

(W0718)


[refactor] 250-256: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[refactor] 260-273: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 299-307: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 222-222: Too many return statements (10/6)

(R0911)


[refactor] 222-222: Too many branches (13/12)

(R0912)

src/mcp_agent/mcp/mcp_aggregator.py

[error] 4-4: Unable to import 'mcp'

(E0401)


[refactor] 66-66: Too few public methods (0/2)

(R0903)


[convention] 642-642: Line too long (104/100)

(C0301)


[convention] 674-674: Line too long (114/100)

(C0301)


[warning] 745-745: TODO: jerron - annotate span for result

(W0511)


[warning] 782-782: TODO: jerron - annotate span for result

(W0511)


[warning] 730-730: Catching too general exception Exception

(W0718)


[refactor] 740-783: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[warning] 1327-1327: Catching too general exception Exception

(W0718)

🪛 LanguageTool
examples/mcp_primitives/mcp_basic_agent/README.md

[uncategorized] ~71-~71: It appears that a hyphen is missing (if ‘auto’ is not used in the context of ‘cars’).
Context: ...mple Run the agent script which should auto install all necessary dependencies: ```bash uv...

(AUTO_HYPHEN)

🪛 Ruff (0.11.9)
src/mcp_agent/utils/mime_utils.py

56-59: Return the condition directly

Inline condition

(SIM103)

src/mcp_agent/utils/content_utils.py

37-38: Use a single if statement instead of nested if statements

(SIM102)


59-60: Use a single if statement instead of nested if statements

(SIM102)


98-98: Multiple isinstance calls for content, merge into a single call

Merge isinstance calls for content

(SIM101)

src/mcp_agent/workflows/llm/multipart_converter_azure.py

295-295: Loop control variable tool_use_id not used within loop body

Rename unused tool_use_id to _tool_use_id

(B007)

src/mcp_agent/workflows/llm/multipart_converter_openai.py

78-78: Yoda condition detected

Rewrite as len(multipart_msg.content) == 1

(SIM300)


190-191: Use a single if statement instead of nested if statements

(SIM102)


276-295: Combine if branches using logical or operator

Combine if branches

(SIM114)

🔇 Additional comments (80)
src/mcp_agent/core/exceptions.py (1)

8-8: LGTM! Documentation consistency improvement.

Good catch updating the docstring to reflect the correct project name "mcp-agent" instead of "FastAgent".

examples/mcp_primitives/mcp_basic_agent/mcp_agent.secrets.yaml.example (2)

3-7: LGTM! Well-structured secrets template.

The API key placeholders are clearly named and the YAML structure is clean. The .example extension appropriately indicates this is a template file to prevent accidental secret exposure.


1-1:

✅ Verification successful

Verify the schema path is correct.

The schema reference path ../../../schema/mcp-agent.config.schema.json should be validated to ensure it correctly points to the schema file from this location.


🏁 Script executed:

#!/bin/bash
# Description: Verify the schema path exists relative to this example file
# Expected: The schema file should exist at the specified path

# Check if the schema file exists at the referenced path
cd examples/mcp_primitives/mcp_basic_agent
if [ -f "../../../schema/mcp-agent.config.schema.json" ]; then
    echo "✓ Schema file found at: ../../../schema/mcp-agent.config.schema.json"
    ls -la "../../../schema/mcp-agent.config.schema.json"
else
    echo "✗ Schema file not found at: ../../../schema/mcp-agent.config.schema.json"
    echo "Looking for schema files in the repository:"
    fd -t f ".*schema.*\.json$"
fi

Length of output: 398


Schema path validated

The schema reference at examples/mcp_primitives/mcp_basic_agent/mcp_agent.secrets.yaml.example (line 1) correctly points to ../../../schema/mcp-agent.config.schema.json—the file exists at that location. No changes needed.

examples/mcp_primitives/mcp_basic_agent/requirements.txt (2)

5-6: LGTM! Dependencies align with the example's purpose.

The external dependencies anthropic and openai match the API key configurations in the secrets file, providing consistent support for both LLM providers in the example.


2-2:

✅ Verification successful

Verify the relative path to mcp-agent root.

The local dependency path file://../../../ should correctly point to the mcp-agent project root from this example's location.


🏁 Script executed:

#!/bin/bash
# Description: Verify the relative path to mcp-agent root is correct
# Expected: Should find setup.py or pyproject.toml at the referenced path

cd examples/mcp_primitives/mcp_basic_agent

# Check if the path leads to the project root
if [ -f "../../../setup.py" ] || [ -f "../../../pyproject.toml" ]; then
    echo "✓ Project root found at: ../../../"
    ls -la ../../../ | grep -E "(setup\.py|pyproject\.toml|src/)"
else
    echo "✗ Project root not found at: ../../../"
    echo "Current directory structure:"
    pwd
    ls -la ../../../
fi

Length of output: 322


Relative Path Validated – No Action Required

Verified that ../../../ from examples/mcp_primitives/mcp_basic_agent/requirements.txt correctly points to the mcp-agent project root (contains pyproject.toml). The local dependency reference is valid and no changes are needed.

src/mcp_agent/workflows/llm/augmented_llm_bedrock.py (2)

29-29: LGTM! Good refactoring to standardize message conversion.

The import of BedrockConverter aligns with the broader effort to standardize message handling across different LLM providers.


97-97:

✅ Verification successful

Verify the converter handles all message types correctly.

The replacement of manual message handling with BedrockConverter.convert_mixed_messages_to_bedrock(message) is a good consolidation. However, ensure the converter maintains the same functionality as the previous implementation.


🏁 Script executed:

#!/bin/bash
# Description: Verify BedrockConverter handles the same message types as before
# Expected: Should find comprehensive message type handling in the converter

# Check the BedrockConverter implementation
rg -A 10 -B 5 "convert_mixed_messages_to_bedrock" src/mcp_agent/workflows/llm/

# Look for message type handling patterns
rg -A 5 "isinstance.*message" src/mcp_agent/workflows/llm/multipart_converter_bedrock.py

# Check if the converter handles strings, lists, and other message types
ast-grep --pattern $'def convert_mixed_messages_to_bedrock($$$) {
  $$$
}'

Length of output: 3581


🏁 Script executed:

#!/bin/bash
# Show the full implementation of convert_mixed_messages_to_bedrock for complete coverage review
rg -n 'def convert_mixed_messages_to_bedrock' -A50 -B5 src/mcp_agent/workflows/llm/multipart_converter_bedrock.py

Length of output: 1611


🏁 Script executed:

#!/bin/bash
# Locate the definitions of MessageTypes and MessageUnionTypeDef
rg -n "MessageTypes" -g "src/**/*.py"
rg -n "MessageUnionTypeDef" -g "src/**/*.py"

# Find the PromptMessage class or alias
rg -n "class PromptMessage" -g "src/**/*.py"
rg -n "PromptMessage =" -g "src/**/*.py"

# Inspect convert_prompt_message_to_bedrock details
rg -n "def convert_prompt_message_to_bedrock" -A20 -B5 src/mcp_agent/workflows/llm/multipart_converter_bedrock.py

Length of output: 5591


🏁 Script executed:

#!/bin/bash
# Display imports and Message/MessageTypes definitions in augmented_llm.py
sed -n '1,80p' src/mcp_agent/workflows/llm/augmented_llm.py
rg -n "MessageTypes" -A2 -B10 src/mcp_agent/workflows/llm/augmented_llm.py

Length of output: 4705


BedrockConverter covers all original message types

I’ve confirmed that convert_mixed_messages_to_bedrock handles:

  • Plain strings (wrapped as {"role":"user","content":[{"text":…}]})
  • PromptMessage instances (via convert_prompt_message_to_bedrock)
  • Lists of str/PromptMessage/already-converted dicts
  • Any other dict-type messages (appended unchanged)

This matches the previous manual logic with no missing cases.

src/mcp_agent/workflows/llm/augmented_llm_azure.py (2)

60-60: Good addition of converter import for standardization.

The import of AzureConverter supports the refactoring to standardize message conversion logic across LLM providers.


156-156: Excellent refactoring to use dedicated converter class.

The replacement of manual conditional logic with AzureConverter.convert_mixed_messages_to_azure(message) improves consistency and maintainability across the codebase. This change aligns with similar refactorings in other LLM provider implementations.

src/mcp_agent/workflows/llm/augmented_llm_google.py (2)

32-32: Good addition of converter import for standardization.

The import of GoogleConverter supports the refactoring to standardize message conversion logic across LLM providers.


88-88:

❌ Incorrect review comment

Fix incorrect method name in converter call.

The method call GoogleConverter.convert_mixed_messages_to_anthropic(message) appears to be a copy-paste error. It should call a Google-specific conversion method, not an Anthropic one.

Apply this diff to fix the method name:

-        messages.extend(GoogleConverter.convert_mixed_messages_to_anthropic(message))
+        messages.extend(GoogleConverter.convert_mixed_messages_to_google(message))

Please verify that the GoogleConverter class has the correct method name by checking the converter implementation:


🏁 Script executed:

#!/bin/bash
# Search for GoogleConverter method definitions
ast-grep --pattern $'class GoogleConverter {
  $$$
  convert_mixed_messages_to_$_($$$) {
    $$$
  }
  $$$
}'

Length of output: 110


I wasn’t able to locate any GoogleConverter methods with the initial AST query. Let’s search the Python code directly:


🏁 Script executed:

#!/bin/bash
# Find the class and its methods
rg "class GoogleConverter" -n src
rg "convert_mixed_messages_to_" -n src

Length of output: 1393


Review comment isn’t applicable—no convert_mixed_messages_to_google exists
The GoogleConverter class in src/mcp_agent/workflows/llm/multipart_converter_google.py only defines:

def convert_mixed_messages_to_anthropic(…)

and no convert_mixed_messages_to_google method is implemented. The call in augmented_llm_google.py matches what’s actually defined, so applying the suggested diff would break the build.

If the intent is to add Google-specific conversion, you’ll need to implement a new convert_mixed_messages_to_google method (and then call it here); otherwise, the current convert_mixed_messages_to_anthropic call is correct.

Likely an incorrect or invalid review comment.

src/mcp_agent/workflows/llm/augmented_llm_anthropic.py (2)

59-59: Good addition of converter import for standardization.

The import of AnthropicConverter supports the refactoring to standardize message conversion logic across LLM providers.


158-160: Excellent refactoring to use dedicated converter class.

The replacement of manual conditional logic with AnthropicConverter.convert_mixed_messages_to_anthropic(message) improves consistency and maintainability. The method name is correctly aligned with the Anthropic provider and the multiline formatting enhances readability.

tests/mcp/test_mcp_aggregator.py (3)

631-643: LGTM! Resource support properly integrated into test framework.

The test enhancements correctly follow the existing pattern for tools and prompts. The addition of Resource imports and creation of test resource objects is well-structured and maintains consistency with the existing codebase.

🧰 Tools
🪛 Pylint (3.3.7)

[error] 632-632: Unable to import 'mcp.types'

(E0401)


[convention] 632-632: Import outside toplevel (mcp.types.Tool, mcp.types.Prompt, mcp.types.Resource)

(C0415)


656-662: Excellent resource integration testing.

The test properly validates that resources are loaded and stored in the correct maps, following the same pattern as tools and prompts. The assertions check both individual resource properties and map integration.

🧰 Tools
🪛 Pylint (3.3.7)

[warning] 660-660: Access to a protected member _namespaced_tool_map of a client class

(W0212)


[warning] 661-661: Access to a protected member _namespaced_prompt_map of a client class

(W0212)


[warning] 662-662: Access to a protected member _namespaced_resource_map of a client class

(W0212)


669-671: Resource map clearing correctly implemented.

The addition of resource map clearing before reloading servers ensures clean test state, maintaining consistency with existing tool and prompt map clearing.

🧰 Tools
🪛 Pylint (3.3.7)

[warning] 669-669: Access to a protected member _namespaced_resource_map of a client class

(W0212)


[warning] 670-670: Access to a protected member _server_to_resource_map of a client class

(W0212)

examples/mcp_primitives/mcp_basic_agent/main.py (3)

36-48: Well-structured agent initialization.

The agent setup with proper naming, instruction, and server configuration demonstrates good practices for MCP agent initialization.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 36-36: Missing function or method docstring

(C0116)


50-83: Excellent demonstration of new resource and prompt capabilities.

This section effectively showcases the key features:

  • Resource listing and URI mapping
  • Prompt listing
  • Combined resource and prompt usage
  • LLM integration with multipart messages

The code flow is logical and educational for users learning the framework.


86-92: Good timing measurement for performance awareness.

The execution timing provides useful feedback for users understanding the performance characteristics of MCP operations.

tests/utils/test_prompt_message_multipart.py (5)

13-18: Clean and straightforward initialization test.

The basic initialization test properly validates the core attributes of the PromptMessageMultipart class.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 13-13: Missing class docstring

(C0115)


[convention] 14-14: Missing function or method docstring

(C0116)


35-46: Excellent test for role-based content merging.

This test demonstrates the key functionality of merging consecutive messages with the same role, which is crucial for multipart message handling.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 35-35: Missing function or method docstring

(C0116)


68-81: Good validation of multipart to standard message conversion.

The from_multipart test ensures that the conversion back to individual messages works correctly, maintaining role and content integrity.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 68-68: Missing function or method docstring

(C0116)


101-109: Nice coverage of embedded resource text extraction.

Testing text extraction from embedded resources ensures the utility methods work with different content types, which is important for resource handling.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 101-101: Missing function or method docstring

(C0116)


184-191: Good edge case coverage for None and empty inputs.

Testing with None and empty message lists ensures robust error handling and prevents runtime issues in production code.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 184-184: Missing function or method docstring

(C0116)


[convention] 188-188: Missing function or method docstring

(C0116)

examples/mcp_primitives/mcp_basic_agent/demo_server.py (3)

11-31: Well-structured static resource definitions.

The STATIC_RESOURCES dictionary provides a clean way to organize resource metadata and content. The JSON formatting with indentation is a nice touch for readability.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 16-16: Line too long (113/100)

(C0301)


34-51: Excellent demonstration of resource handlers.

The resource handlers show both static (README, users) and dynamic (weather) resource patterns. The use of decorators makes the intent clear and the implementation straightforward.


54-60: Good example of prompt handler implementation.

The echo prompt handler provides a simple but effective demonstration of prompt functionality with clear documentation.

src/mcp_agent/utils/mime_utils.py (4)

5-10: MIME type initialization and extensions look good.

The initialization of the mimetypes database and addition of missing types is well-implemented. Adding Python and WebP support addresses common gaps in the standard library.


13-28: Well-curated list of text-based MIME types.

The comprehensive set of known text MIME types that don't start with "text/" is valuable for accurate content classification.


34-39: Simple and effective MIME type guessing.

The function correctly handles the case where mimetypes.guess_type returns None and provides a sensible fallback.


67-69: Smart image type detection with SVG exclusion.

Correctly excludes SVG images since they are text-based XML and should be handled differently from binary images.

src/mcp_agent/utils/prompt_message_multipart.py (4)

16-24: Well-designed multipart message class.

The class structure is clean with proper Pydantic modeling and clear type annotations. The content list supporting multiple content types provides good flexibility.


25-53: Robust message grouping logic.

The to_multipart method correctly groups consecutive messages by role, which is essential for proper multipart message handling.


62-77: Comprehensive text extraction with fallback.

The first_text method provides good error handling by returning a fallback message when no text content is found.


135-151: Safe handling of MCP server results.

The from_get_prompt_result method provides robust error handling for None or empty results, which is important for real-world usage.

tests/workflows/llm/test_augmented_llm_openai.py (7)

14-14: Good addition of PromptMessage import.

The import addition supports the new test cases that verify handling of MCP PromptMessage types.

🧰 Tools
🪛 Pylint (3.3.7)

[error] 14-14: Unable to import 'mcp.types'

(E0401)


463-491: Comprehensive test for string input handling.

The test properly verifies that string inputs are correctly converted to OpenAI message format. The assertions check both the response and the request payload structure.


492-523: Thorough test for MessageParamT input.

The test correctly validates handling of OpenAI message dictionary format, ensuring the conversion process works bidirectionally.


524-548: Excellent test for PromptMessage input.

This test verifies the integration with MCP message types, which is crucial for the framework's multipart message support.


550-578: Robust test for mixed message types.

This test is particularly valuable as it verifies that the system can handle heterogeneous input - a key requirement for the multipart message functionality.


580-607: Comprehensive coverage for generate_str with mixed types.

The test ensures that the string generation method properly handles diverse input types, maintaining consistency across the API.


609-643: Thorough test for structured generation.

The test properly verifies that structured output generation works with mixed message types, ensuring the entire pipeline functions correctly.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 617-617: Missing class docstring

(C0115)


[refactor] 617-617: Too few public methods (0/2)

(R0903)

tests/utils/test_multipart_converter_azure.py (5)

17-27: Comprehensive image type support testing.

The tests properly verify both supported and unsupported image types, ensuring the converter handles various MIME types correctly.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 17-17: Missing class docstring

(C0115)


[convention] 18-18: Missing function or method docstring

(C0116)


[warning] 19-19: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 20-20: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 21-21: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 22-22: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 24-24: Missing function or method docstring

(C0116)


[warning] 25-25: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 26-26: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 27-27: Access to a protected member _is_supported_image_type of a client class

(W0212)


[refactor] 17-17: Too many public methods (28/20)

(R0904)


29-73: Thorough content conversion testing.

The tests cover all major content types (empty, text, images) and properly verify the Azure-specific message format requirements, including the filtering of non-text content for assistant messages.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 29-29: Missing function or method docstring

(C0116)


[convention] 36-36: Missing function or method docstring

(C0116)


[convention] 45-45: Missing function or method docstring

(C0116)


[convention] 54-54: Missing function or method docstring

(C0116)


[convention] 63-63: Missing function or method docstring

(C0116)


84-161: Excellent embedded resource testing coverage.

The test suite comprehensively covers embedded resource conversion including text resources, PDFs, SVGs, and various image formats. The edge case handling (missing data, unsupported formats) is particularly well tested.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 84-84: Missing function or method docstring

(C0116)


[warning] 90-90: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 95-95: Missing function or method docstring

(C0116)


[warning] 101-101: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 106-106: Missing function or method docstring

(C0116)


[warning] 112-112: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 118-118: Missing function or method docstring

(C0116)


[warning] 124-124: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 129-129: Missing function or method docstring

(C0116)


[warning] 135-135: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 140-140: Missing function or method docstring

(C0116)


[warning] 146-146: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 151-151: Missing function or method docstring

(C0116)


[warning] 157-157: Access to a protected member _convert_embedded_resource of a client class

(W0212)


162-195: Robust MIME type determination testing.

The tests properly verify the MIME type detection logic with various fallback scenarios, ensuring reliable content classification.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 162-162: Missing function or method docstring

(C0116)


[warning] 166-166: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 169-169: Missing function or method docstring

(C0116)


[warning] 176-176: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 179-179: Missing function or method docstring

(C0116)


[warning] 185-185: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 188-188: Missing function or method docstring

(C0116)


[warning] 194-194: Access to a protected member _determine_mime_type of a client class

(W0212)


236-305: Comprehensive tool result conversion testing.

The test coverage for tool result conversion is excellent, including edge cases like empty content, mixed content types, and embedded resources. This ensures reliable integration with the broader MCP framework.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 236-236: Missing function or method docstring

(C0116)


[convention] 248-248: Missing function or method docstring

(C0116)


[convention] 259-259: Missing function or method docstring

(C0116)


[convention] 275-275: Missing function or method docstring

(C0116)


[convention] 291-291: Missing function or method docstring

(C0116)

tests/workflows/llm/test_augmented_llm_anthropic.py (1)

634-811: Excellent test coverage for mixed message type support!

The new test methods provide comprehensive coverage for the different message input types and mixed message scenarios. The tests are well-structured and follow the existing patterns in the codebase.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 785-785: Missing class docstring

(C0115)


[refactor] 785-785: Too few public methods (0/2)

(R0903)

src/mcp_agent/workflows/llm/augmented_llm_openai.py (2)

182-182: Excellent refactoring to centralize message conversion logic!

Replacing the manual message handling with OpenAIConverter.convert_mixed_messages_to_openai(message) is a great improvement. This delegates the complex task of handling mixed message types to a specialized converter class, making the code more maintainable and consistent with the pattern used across other LLM provider implementations.


62-62: Good addition of the OpenAIConverter import.

The import is properly placed and enables the message conversion refactoring in the generate method.

src/mcp_agent/utils/content_utils.py (1)

68-84: Clean and straightforward implementation.

The get_resource_uri function is well-implemented and handles the EmbeddedResource case correctly.

examples/mcp_primitives/mcp_basic_agent/README.md (1)

1-108: Excellent documentation for MCP primitives example!

This README provides comprehensive coverage of the MCP primitives concept with a practical example. The structure is clear, the explanations are helpful, and it includes all necessary setup and usage instructions. The architecture diagram and step-by-step walkthrough make it easy for developers to understand and use the example.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~71-~71: It appears that a hyphen is missing (if ‘auto’ is not used in the context of ‘cars’).
Context: ...mple Run the agent script which should auto install all necessary dependencies: ```bash uv...

(AUTO_HYPHEN)

tests/utils/test_multipart_converter_anthropic.py (4)

16-27: Excellent test coverage for image type validation!

The tests correctly validate that Anthropic supports common image formats (JPEG, PNG, GIF, WebP) while properly rejecting unsupported formats like SVG and BMP. This ensures the converter will handle image content appropriately.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 16-16: Missing class docstring

(C0115)


[convention] 17-17: Missing function or method docstring

(C0116)


[warning] 18-18: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 19-19: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 20-20: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 21-21: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 23-23: Missing function or method docstring

(C0116)


[warning] 24-24: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 25-25: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 26-26: Access to a protected member _is_supported_image_type of a client class

(W0212)


[refactor] 16-16: Too many public methods (24/20)

(R0904)


67-79: Good validation of assistant role filtering behavior.

The test correctly verifies that assistant role messages filter out non-text content (like images), which aligns with typical LLM API constraints where assistant responses should only contain text.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 67-67: Missing function or method docstring

(C0116)


260-283: Comprehensive tool result aggregation testing.

The test properly validates that multiple tool results with different success/error states are correctly aggregated into a single Anthropic message format. This is crucial for multi-tool workflows.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 260-260: Missing function or method docstring

(C0116)


102-104:

✅ Verification successful

Verify URI parsing logic for edge cases.

The test expects an empty title due to "URI gets a trailing slash, resulting in empty title". This suggests potential issues with URI parsing logic in the converter.

Let me check how URI titles are extracted in the converter:


🏁 Script executed:

#!/bin/bash
# Description: Check URI title extraction logic in AnthropicConverter
# Expected: Find the implementation of title extraction from URIs

ast-grep --pattern 'def $_($$$) {
  $$$
  title = $$$
  $$$
}'

rg -A 10 -B 5 "title.*=" src/mcp_agent/workflows/llm/multipart_converter_anthropic.py

Length of output: 2153


🏁 Script executed:

#!/bin/bash
# Locate the implementation of extract_title_from_uri across the repository
grep -R "def extract_title_from_uri" -n .

Length of output: 135


🏁 Script executed:

#!/bin/bash
# Display the extract_title_from_uri function implementation
sed -n '180,260p' src/mcp_agent/utils/resource_utils.py

Length of output: 1349


🏁 Script executed:

#!/bin/bash
# Show lines around the assertion in the test file to understand context
sed -n '1,150p' tests/utils/test_multipart_converter_anthropic.py

Length of output: 6444


🏁 Script executed:

#!/bin/bash
# Display the full _convert_embedded_resource method in AnthropicConverter
awk '/def _convert_embedded_resource/,/def /' src/mcp_agent/workflows/llm/multipart_converter_anthropic.py | sed '$d'

Length of output: 119


Extracted title logic validated – behavior matches tests

The converter’s _convert_embedded_resource method calls:

title = extract_title_from_uri(uri) if uri else "resource"

and in src/mcp_agent/utils/resource_utils.py:

elif uri.path:
    return os.path.basename(uri.path)

Pydantic normalizes file://test.txt to file://test.txt/, so uri.path == "/" and os.path.basename("/") == "", which is exactly what the test asserts.

If your intent is to preserve the filename (e.g. "test.txt"), consider stripping trailing slashes before calling basename:

path = uri.path.rstrip("/")
return os.path.basename(path) or uri._url

Otherwise, the current behavior aligns with the tests.

tests/utils/test_multipart_converter_bedrock.py (4)

18-27: Correct validation of Bedrock's limited image support.

The tests properly reflect that Bedrock only supports JPEG and PNG images, rejecting GIF, WebP, SVG, and other formats. This is an important constraint that's correctly captured.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 18-18: Missing function or method docstring

(C0116)


[warning] 19-19: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 20-20: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 22-22: Missing function or method docstring

(C0116)


[warning] 23-23: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 24-24: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 25-25: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 26-26: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 27-27: Access to a protected member _is_supported_image_type of a client class

(W0212)


148-158: Good edge case testing for missing image data.

This test ensures graceful handling when image resources lack blob data, providing helpful fallback messages rather than failing silently.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 148-148: Missing function or method docstring

(C0116)


[warning] 154-154: Access to a protected member _convert_embedded_resource of a client class

(W0212)


170-184: Comprehensive binary fallback handling.

The test validates proper fallback behavior for unsupported binary content types, including size reporting ("10 characters"). This provides users with useful information about why content couldn't be processed.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 170-170: Missing function or method docstring

(C0116)


[warning] 178-178: Access to a protected member _convert_embedded_resource of a client class

(W0212)


326-342: Excellent test for embedded resource handling in tool results.

This test ensures that tool results containing embedded resources are properly converted to Bedrock format, which is crucial for complex tool workflows that return resource references.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 326-326: Missing function or method docstring

(C0116)

tests/utils/test_content_utils.py (3)

19-49: Comprehensive testing of text extraction functionality.

The TestGetText class properly tests text extraction from various content types including TextContent, TextResourceContents, and EmbeddedResource, while correctly handling cases where text extraction should return None.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 19-19: Missing class docstring

(C0115)


[convention] 20-20: Missing function or method docstring

(C0116)


[convention] 24-24: Missing function or method docstring

(C0116)


[convention] 30-30: Missing function or method docstring

(C0116)


[convention] 37-37: Missing function or method docstring

(C0116)


[convention] 46-46: Missing function or method docstring

(C0116)


51-75: Good coverage of image data extraction scenarios.

The tests correctly validate that image data can be extracted from ImageContent and embedded blob resources, while returning None for inappropriate content types.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 51-51: Missing class docstring

(C0115)


[convention] 52-52: Missing function or method docstring

(C0116)


[convention] 58-58: Missing function or method docstring

(C0116)


[convention] 65-65: Missing function or method docstring

(C0116)


[convention] 69-69: Missing function or method docstring

(C0116)


109-115:

✅ Verification successful

Verify type checking behavior for embedded resources.

The test expects is_text_content(embedded) to return False even when the embedded resource contains text content. This suggests the function only checks the top-level type, not the content within embedded resources.

Let me verify this behavior matches the implementation:


🏁 Script executed:

#!/bin/bash
# Description: Check is_text_content implementation logic
# Expected: Confirm it only checks top-level type, not embedded content

rg -A 15 "def is_text_content" src/mcp_agent/utils/content_utils.py

Length of output: 505


Confirmed: is_text_content only checks top‐level content types
The implementation returns True for TextContent and TextResourceContents and always False for EmbeddedResource, so the test is correct. If you intend to detect text inside an EmbeddedResource, you’ll need to update is_text_content to unwrap and inspect its resource.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 109-109: Missing function or method docstring

(C0116)

tests/utils/test_mime_utils.py (4)

9-33: Excellent coverage of MIME type guessing scenarios.

The tests comprehensively cover common file extensions and properly validate fallback behavior for unknown extensions and files without extensions, ensuring robust MIME type detection.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 9-9: Missing class docstring

(C0115)


[convention] 10-10: Missing function or method docstring

(C0116)


[convention] 13-13: Missing function or method docstring

(C0116)


[convention] 16-16: Missing function or method docstring

(C0116)


[convention] 19-19: Missing function or method docstring

(C0116)


[convention] 22-22: Missing function or method docstring

(C0116)


[convention] 25-25: Missing function or method docstring

(C0116)


[convention] 28-28: Missing function or method docstring

(C0116)


[convention] 31-31: Missing function or method docstring

(C0116)


35-83: Thorough testing of text MIME type classification.

The tests properly cover standard text types, application-specific text types, and custom MIME types with text suffixes. The edge case testing with empty strings and None values ensures robust error handling.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 35-35: Missing class docstring

(C0115)


[convention] 36-36: Missing function or method docstring

(C0116)


[convention] 39-39: Missing function or method docstring

(C0116)


[convention] 42-42: Missing function or method docstring

(C0116)


[convention] 45-45: Missing function or method docstring

(C0116)


[convention] 48-48: Missing function or method docstring

(C0116)


[convention] 51-51: Missing function or method docstring

(C0116)


[convention] 54-54: Missing function or method docstring

(C0116)


[convention] 57-57: Missing function or method docstring

(C0116)


[convention] 60-60: Missing function or method docstring

(C0116)


[convention] 63-63: Missing function or method docstring

(C0116)


[convention] 66-66: Missing function or method docstring

(C0116)


[convention] 69-69: Missing function or method docstring

(C0116)


[convention] 72-72: Missing function or method docstring

(C0116)


[convention] 75-75: Missing function or method docstring

(C0116)


[convention] 78-78: Missing function or method docstring

(C0116)


[convention] 81-81: Missing function or method docstring

(C0116)


115-118: Correct exclusion of SVG from image processing.

The test correctly validates that SVG files (image/svg+xml) are excluded from being considered images for processing purposes, which aligns with the comment explaining this design decision.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 115-115: Missing function or method docstring

(C0116)


81-83:

✅ Verification successful

Verify None handling in MIME type functions.

The test passes None to is_text_mime_type(), but the function signature suggests it expects a string. This could cause type issues.

Let me check the function signature and None handling:


🏁 Script executed:

#!/bin/bash
# Description: Check how MIME utility functions handle None values
# Expected: Verify proper type handling and None checking

rg -A 10 "def is_text_mime_type" src/mcp_agent/utils/mime_utils.py
rg -A 5 -B 5 "if not mime_type" src/mcp_agent/utils/mime_utils.py

Length of output: 720


is_text_mime_type correctly handles None input

The if not mime_type guard at the top of is_text_mime_type returns False when passed None, so there is no runtime error and the existing test is valid.

No changes required.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 81-81: Missing function or method docstring

(C0116)

tests/workflows/llm/test_augmented_llm_bedrock.py (2)

565-583: LGTM! Well-structured test for string input.

The test correctly verifies string input handling and validates both the response format and the request payload structure.


584-606: LGTM! Good test coverage for MessageParamT input.

The test properly validates that Bedrock message dict input is handled correctly and passes through the expected message structure.

tests/utils/test_multipart_converter_google.py (4)

16-27: LGTM! Comprehensive image type support testing.

The tests properly validate supported and unsupported image MIME types for Google's API requirements.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 16-16: Missing class docstring

(C0115)


[convention] 17-17: Missing function or method docstring

(C0116)


[warning] 18-18: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 19-19: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 20-20: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 21-21: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 23-23: Missing function or method docstring

(C0116)


[warning] 24-24: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 25-25: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 26-26: Access to a protected member _is_supported_image_type of a client class

(W0212)


[refactor] 16-16: Too many public methods (31/20)

(R0904)


28-49: LGTM! Well-structured conversion test with proper mocking.

The test correctly validates the conversion flow and uses appropriate mocking to isolate the unit under test.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 28-28: Missing function or method docstring

(C0116)


[convention] 35-35: Missing function or method docstring

(C0116)


50-87: LGTM! Good test coverage for image content handling.

The tests properly validate both supported image content conversion and fallback behavior for unsupported formats.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 50-50: Missing function or method docstring

(C0116)


[convention] 71-71: Missing function or method docstring

(C0116)


[warning] 85-85: Unused variable 'args'

(W0612)


391-514: LGTM! Comprehensive tool result conversion testing.

The tests provide excellent coverage of tool result conversion scenarios including error cases, empty content, embedded resources, and mixed content types.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 391-391: Missing function or method docstring

(C0116)


[convention] 407-407: Missing function or method docstring

(C0116)


[warning] 420-420: Unused variable 'args'

(W0612)


[convention] 425-425: Missing function or method docstring

(C0116)


[convention] 443-443: Missing function or method docstring

(C0116)


[convention] 467-467: Missing function or method docstring

(C0116)


[convention] 488-488: Missing function or method docstring

(C0116)

tests/utils/test_multipart_converter_openai.py (3)

16-42: LGTM! Good coverage of basic conversion scenarios.

The tests properly validate image type support and basic content conversion to OpenAI format.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 16-16: Missing class docstring

(C0115)


[convention] 17-17: Missing function or method docstring

(C0116)


[warning] 18-18: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 19-19: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 20-20: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 21-21: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 23-23: Missing function or method docstring

(C0116)


[warning] 24-24: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 25-25: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 26-26: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 28-28: Missing function or method docstring

(C0116)


[convention] 35-35: Missing function or method docstring

(C0116)


[refactor] 16-16: Too many public methods (31/20)

(R0904)


43-98: LGTM! Excellent test coverage for complex scenarios.

The tests thoroughly validate multiple content blocks, text concatenation, and mixed content handling which are important for OpenAI's message format.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 43-43: Missing function or method docstring

(C0116)


[convention] 66-66: Missing function or method docstring

(C0116)


[convention] 82-82: Missing function or method docstring

(C0116)


[warning] 90-90: Access to a protected member _concatenate_text_blocks of a client class

(W0212)


288-362: LGTM! Comprehensive tool result conversion testing.

The tests provide excellent coverage of OpenAI's tool result conversion including text-only, empty content, mixed content scenarios, and function result handling.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 288-288: Missing function or method docstring

(C0116)


[convention] 298-298: Missing function or method docstring

(C0116)


[convention] 307-307: Missing function or method docstring

(C0116)


[convention] 328-328: Missing function or method docstring

(C0116)


[convention] 348-348: Missing function or method docstring

(C0116)

src/mcp_agent/utils/resource_utils.py (2)

21-28: LGTM! Clean and straightforward file discovery logic.

The function properly searches for resources relative to prompt files with clear logic and error handling.


30-68: LGTM! Robust content loading with proper binary handling.

The function correctly handles both text and binary content with appropriate encoding. The docstring is comprehensive and the error handling is appropriate.

src/mcp_agent/workflows/llm/augmented_llm.py (1)

588-598: Span attributes now lose fidelity – is that intentional?

The previous implementation delegated to _extract_message_param_attributes_for_tracing, giving rich, structured tracing information (role, name, etc.).
The new logic collapses every non-str object to str(msg) which usually renders as the model’s repr. Down-stream trace consumers will therefore no longer be able to filter on e.g. role=user.

If the simplification is deliberate (maybe to shrink attribute size), please leave a brief comment and/or emit a single attribute such as message.{i}.role when hasattr(msg, "role") so that role filters keep working.

Otherwise consider restoring the richer behaviour.

src/mcp_agent/workflows/llm/multipart_converter_google.py (1)

160-179: Return early – unblock readability

After returning inside the image branch you can drop the else: to shrink one indentation level.

Comment on lines +87 to +99
# Filter blocks based on role (assistant can only have text blocks)
if role == "assistant":
text_blocks = []
for block in anthropic_blocks:
if block.get("type") == "text":
text_blocks.append(block)
else:
_logger.warning(
f"Removing non-text block from assistant message: {block.get('type')}"
)
anthropic_blocks = text_blocks

# Create the Anthropic message
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Assistant message may end up with an empty content list

If every non-text block is stripped, anthropic_blocks becomes empty and the SDK rejects the message (content must contain ≥1 blocks).
Consider generating a minimal text fallback or dropping the message entirely.

🤖 Prompt for AI Agents
In src/mcp_agent/workflows/llm/multipart_converter_anthropic.py around lines 87
to 99, after filtering out non-text blocks from the assistant message,
anthropic_blocks may become empty, causing the SDK to reject the message. To fix
this, check if anthropic_blocks is empty after filtering; if so, either generate
a minimal fallback text block to include or skip processing this message
entirely to ensure content always has at least one block.

Comment on lines +410 to +424
if not non_text_content:
return tool_message

# Process non-text content as a separate user message
non_text_multipart = PromptMessageMultipart(
role="user", content=non_text_content
)

# Convert to OpenAI format
user_message = OpenAIConverter.convert_to_openai(non_text_multipart)

# We need to add tool_call_id manually
user_message["tool_call_id"] = tool_call_id

return (tool_message, [user_message])
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Invalid field tool_call_id on user message

OpenAI chat schema does not allow tool_call_id on "user" messages.
Instead, include the non-text content as a separate user message after the tool message, without the extra field.

-        user_message["tool_call_id"] = tool_call_id
+        # The user message represents additional artefacts – no tool_call_id
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if not non_text_content:
return tool_message
# Process non-text content as a separate user message
non_text_multipart = PromptMessageMultipart(
role="user", content=non_text_content
)
# Convert to OpenAI format
user_message = OpenAIConverter.convert_to_openai(non_text_multipart)
# We need to add tool_call_id manually
user_message["tool_call_id"] = tool_call_id
return (tool_message, [user_message])
if not non_text_content:
return tool_message
# Process non-text content as a separate user message
non_text_multipart = PromptMessageMultipart(
role="user", content=non_text_content
)
# Convert to OpenAI format
user_message = OpenAIConverter.convert_to_openai(non_text_multipart)
# We need to add tool_call_id manually
# The user message represents additional artefacts – no tool_call_id
return (tool_message, [user_message])
🤖 Prompt for AI Agents
In src/mcp_agent/workflows/llm/multipart_converter_openai.py around lines 410 to
424, the code incorrectly adds a `tool_call_id` field to a user message, which
is not allowed by the OpenAI chat schema. To fix this, remove the line that sets
`user_message["tool_call_id"] = tool_call_id` and ensure the non-text content is
returned as a separate user message following the tool message without any extra
fields.

Comment on lines +155 to +218
def _convert_embedded_resource(
resource: EmbeddedResource,
) -> Optional[ContentItem]:
"""
Convert EmbeddedResource to appropriate Azure ContentItem.

Args:
resource: The embedded resource to convert

Returns:
An appropriate ContentItem for the resource, or None if not convertible
"""
resource_content = resource.resource
uri_str = get_resource_uri(resource)
uri = getattr(resource_content, "uri", None)
is_url: bool = uri and getattr(uri, "scheme", None) in ("http", "https")

mime_type = AzureConverter._determine_mime_type(resource_content)
title = extract_title_from_uri(uri) if uri else "resource"

if mime_type == "image/svg+xml":
return AzureConverter._convert_svg_resource(resource_content)

elif is_image_mime_type(mime_type):
if not AzureConverter._is_supported_image_type(mime_type):
return AzureConverter._create_fallback_text(
f"Image with unsupported format '{mime_type}'", resource
)

if is_url and uri_str:
return ImageContentItem(image_url=ImageUrl(url=uri_str))

image_data = get_image_data(resource)
if image_data:
data_url = f"data:{mime_type};base64,{image_data}"
return ImageContentItem(image_url=ImageUrl(url=data_url))

return AzureConverter._create_fallback_text("Image missing data", resource)

elif mime_type == "application/pdf":
# Azure does not support PDF as content item, fallback to text
return TextContentItem(text=f"[PDF resource: {title}]")

elif is_text_mime_type(mime_type):
text = get_text(resource)
if not text:
return TextContentItem(
text=f"[Text content could not be extracted from {title}]"
)
return TextContentItem(text=text)

text = get_text(resource)
if text:
return TextContentItem(text=text)

if isinstance(resource.resource, BlobResourceContents) and hasattr(
resource.resource, "blob"
):
blob_length = len(resource.resource.blob)
return TextContentItem(
text=f"Embedded Resource {getattr(uri, '_url', '')} with unsupported format {mime_type} ({blob_length} characters)"
)

return AzureConverter._create_fallback_text(
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

_convert_embedded_resource(): complexity & redundant branches

The method contains 11 return statements and nested conditionals, triggering Pylint R0911. Extract dedicated helpers for each MIME family (SVG, raster image, PDF, text, binary-other) and use early exits:

if mime == "image/svg+xml":
    return _handle_svg(...)
if is_image_mime_type(...):
    return _handle_image(...)
...
return _fallback(...)

This will improve readability and unit-testability.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 215-215: Line too long (131/100)

(C0301)


[refactor] 175-204: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 155-155: Too many return statements (11/6)

(R0911)

🤖 Prompt for AI Agents
In src/mcp_agent/workflows/llm/multipart_converter_azure.py between lines 155
and 218, the _convert_embedded_resource method has high complexity with many
return statements and nested conditionals. Refactor by extracting separate
helper functions for each MIME type category such as SVG, raster images, PDF,
text, and other binary types. Replace the nested if-else structure with a
sequence of early return statements that call these helpers, improving
readability and making each case easier to unit test.

Comment on lines 326 to 360
def convert_mixed_messages_to_azure(
message: MessageTypes,
) -> List[
Union[
SystemMessage, UserMessage, AssistantMessage, ToolMessage, DeveloperMessage
]
]:
"""
Convert a list of mixed messages to a list of Anthropic-compatible messages.

Args:
messages: List of mixed message objects

Returns:
A list of Anthropic-compatible MessageParam objects
"""
messages = []

# Convert message to ResponseMessage
if isinstance(message, str):
messages.append(UserMessage(content=message))
elif isinstance(message, PromptMessage):
messages.append(AzureConverter.convert_prompt_message_to_azure(message))
elif isinstance(message, list):
for m in message:
if isinstance(m, PromptMessage):
messages.append(AzureConverter.convert_prompt_message_to_azure(m))
elif isinstance(m, str):
messages.append(UserMessage(content=m))
else:
messages.append(m)
else:
messages.append(message)

return messages
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Variable shadowing & outdated docstring in convert_mixed_messages_to_azure

  1. The parameter message gets shadowed by a local variable with the same name (messages = []), hiding the outer scope and confusing readers.
  2. Docstring mentions “Anthropic-compatible messages” and “MessageParam” which is copy-paste residue.

Refactor:

- def convert_mixed_messages_to_azure(message: MessageTypes) -> List[...]:
+ def convert_mixed_messages_to_azure(input_msg: MessageTypes) -> List[...]:
     """
-    Convert a list of mixed messages to a list of Anthropic-compatible messages.
+    Convert mixed MCP types (str, PromptMessage, list, Azure SDK messages)
+    into Azure-compatible message objects.
     """
-    messages = []
+    result: list[...] = []

and return result.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/mcp_agent/workflows/llm/multipart_converter_azure.py around lines 326 to
360, the function convert_mixed_messages_to_azure has a local variable named
messages that shadows the input parameter message, causing confusion. Rename the
local list variable to something like result to avoid shadowing. Also, update
the docstring to correctly describe the function's behavior and return type,
removing references to "Anthropic-compatible messages" and "MessageParam" which
are outdated. Finally, ensure the function returns the renamed variable result
instead of messages.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🔭 Outside diff range comments (1)
src/mcp_agent/agents/agent.py (1)

238-252: ⚠️ Potential issue

_namespaced_resource_map never populated – leads to stale / empty cache

initialize() refreshes tool & prompt maps but only updates _server_to_resource_map.
Forgeting to refresh _namespaced_resource_map will break any future lookup by
namespaced key.

                 self._server_to_prompt_map.clear()
                 self._server_to_prompt_map.update(result.server_to_prompt_map)

+                # --- NEW: keep namespaced resource cache in sync ---
+                self._namespaced_resource_map.clear()
+                self._namespaced_resource_map.update(result.namespaced_resource_map)
+
                 self._server_to_resource_map.clear()
                 self._server_to_resource_map.update(result.server_to_resource_map)
♻️ Duplicate comments (6)
tests/utils/test_resource_utils.py (1)

160-160: ⚠️ Potential issue

Fix AnyUrl constructor usage to prevent test failures.

AnyUrl(url="...") will raise TypeError because Pydantic's AnyUrl expects the URL as a positional argument, not a keyword argument.

-        assert result.resource.uri == AnyUrl(url="resource://mcp-agent/test.txt")
+        assert str(result.resource.uri) == "resource://mcp-agent/test.txt"
-        assert result.resource.uri == AnyUrl(url="resource://mcp-agent/image.png")
+        assert str(result.resource.uri) == "resource://mcp-agent/image.png"
-        assert result.resource.uri == AnyUrl(url="file://test.bin")
+        assert str(result.resource.uri) == "file://test.bin"
-        assert result.resource.uri == AnyUrl(url="file://test.txt")
+        assert str(result.resource.uri) == "file://test.txt"

Also applies to: 173-173, 200-200, 213-213

src/mcp_agent/workflows/llm/multipart_converter_anthropic.py (1)

87-98: 🛠️ Refactor suggestion

Handle potential empty content list after filtering.

After filtering non-text blocks from assistant messages, anthropic_blocks could become empty, causing the Anthropic SDK to reject the message since content must contain at least one block.

        # Filter blocks based on role (assistant can only have text blocks)
        if role == "assistant":
            text_blocks = []
            for block in anthropic_blocks:
                if block.get("type") == "text":
                    text_blocks.append(block)
                else:
                    _logger.warning(
                        f"Removing non-text block from assistant message: {block.get('type')}"
                    )
            anthropic_blocks = text_blocks
+            
+            # Ensure we have at least one text block for assistant messages
+            if not anthropic_blocks:
+                anthropic_blocks = [TextBlockParam(type="text", text="[No content available]")]
src/mcp_agent/workflows/llm/multipart_converter_google.py (1)

235-235: ⚠️ Potential issue

Fix method call for URI serialization.

serialize_url is a method and should be called with parentheses, or use str(resource.uri) for consistency.

-            return guess_mime_type(resource.uri.serialize_url)
+            return guess_mime_type(str(resource.uri))
src/mcp_agent/workflows/llm/multipart_converter_azure.py (3)

68-76: ⚠️ Potential issue

role comparison still brittle when role is an Enum

Prior feedback noted that PromptMessage.role is often an Enum (e.g. Role.ASSISTANT).
Comparing directly to the literal string "assistant" mis-classifies Enum values and produces wrong Azure roles.

-        role = multipart_msg.role
+        # Normalise to lowercase str to support both `str` and Enum values
+        role = str(multipart_msg.role).lower()

-        if role == "assistant":
+        if role == "assistant":
🧰 Tools
🪛 Pylint (3.3.7)

[refactor] 71-74: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


156-219: 🛠️ Refactor suggestion

_convert_embedded_resource() remains very complex (11 returns, nested branches)

The previous review suggested extracting MIME-family specific helpers to reduce R0911 complexity and improve testability. Consider refactoring into small, focused helpers (_handle_svg, _handle_image, _handle_pdf, …).

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 216-216: Line too long (131/100)

(C0301)


[refactor] 176-205: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 156-156: Too many return statements (11/6)

(R0911)


327-361: 🛠️ Refactor suggestion

Shadowing the input parameter & inconsistent docstring

The function parameter is named message, but a local variable messages shadows it.
Additionally, the docstring still refers to “a list of mixed messages” while the signature accepts a single (MessageTypes) value that can itself be a list.

-    def convert_mixed_messages_to_azure(
-        message: MessageTypes,
+    def convert_mixed_messages_to_azure(
+        mixed_message: MessageTypes,
...
-        messages = []
+        azure_msgs: list[
+            SystemMessage | UserMessage | AssistantMessage | ToolMessage | DeveloperMessage
+        ] = []
...
-            messages.append(UserMessage(content=message))
+            azure_msgs.append(UserMessage(content=mixed_message))
...
-        return messages
+        return azure_msgs

Update the docstring accordingly.

🧹 Nitpick comments (10)
tests/utils/test_multipart_converter_google.py (1)

372-372: Move import to module level for consistency.

The pydantic import should be moved to the top of the file with other imports for better consistency and readability.

+from pydantic import AnyUrl
 from unittest.mock import Mock, patch
 from mcp.types import (
     BlobResourceContents,
     CallToolResult,
     EmbeddedResource,
     ImageContent,
     PromptMessage,
     TextContent,
     TextResourceContents,
 )

 from mcp_agent.utils.prompt_message_multipart import PromptMessageMultipart
 from mcp_agent.workflows.llm.multipart_converter_google import GoogleConverter

Then remove the import from inside the function:

 def test_create_fallback_text_with_uri(self):
-    from pydantic import AnyUrl
-
     uri = "http://example.com/test"
🧰 Tools
🪛 Pylint (3.3.7)

[error] 372-372: Unable to import 'pydantic'

(E0401)


[convention] 372-372: Import outside toplevel (pydantic.AnyUrl)

(C0415)

src/mcp_agent/workflows/llm/multipart_converter_bedrock.py (2)

271-282: Fix docstring inconsistency with parameter name.

The docstring mentions "messages: List of mixed message objects" but the parameter is singular "message: MessageTypes". This inconsistency could confuse users.

 @staticmethod
 def convert_mixed_messages_to_bedrock(
     message: MessageTypes,
 ) -> List[MessageUnionTypeDef]:
     """
-    Convert a list of mixed messages to a list of Bedrock-compatible messages.
+    Convert a mixed message to a list of Bedrock-compatible messages.

     Args:
-        messages: List of mixed message objects
+        message: A mixed message object (string, PromptMessage, or list)

     Returns:
         A list of Bedrock-compatible MessageParam objects
     """

132-133: Address or remove the TODO comment.

This TODO comment about URL handling should either be implemented or removed if it's not needed. Leaving TODO comments indefinitely can clutter the codebase.

If URL handling is not currently needed, consider removing the TODO:

-        # TODO: jerron - check if we need to handle URLs differently
-        # is_url: bool = uri and getattr(uri, "scheme", None) in ("http", "https")

If it is needed, consider creating a proper issue to track this work.

🧰 Tools
🪛 Pylint (3.3.7)

[warning] 132-132: TODO: jerron - check if we need to handle URLs differently

(W0511)

src/mcp_agent/utils/resource_utils.py (2)

116-131: Consider simplifying control flow.

The else statement after return is unnecessary and can be removed for cleaner code.

    if is_binary:
        return EmbeddedResource(
            type="resource",
            resource=BlobResourceContents(
                **resource_args,
                blob=content,
            ),
        )
-    else:
-        return EmbeddedResource(
-            type="resource",
-            resource=TextResourceContents(
-                **resource_args,
-                text=content,
-            ),
-        )
+    
+    return EmbeddedResource(
+        type="resource",
+        resource=TextResourceContents(
+            **resource_args,
+            text=content,
+        ),
+    )
🧰 Tools
🪛 Pylint (3.3.7)

[refactor] 116-131: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


218-219: Use more specific exception handling.

Catching the general Exception is too broad. Consider catching specific exceptions that might occur during URI parsing.

-    except Exception:
+    except (AttributeError, ValueError, TypeError):
🧰 Tools
🪛 Pylint (3.3.7)

[warning] 218-218: Catching too general exception Exception

(W0718)

src/mcp_agent/workflows/llm/multipart_converter_google.py (1)

156-158: Remove TODO comment or address the concern.

The TODO comment indicates uncertainty about whether the commented code is needed. Consider either removing the TODO and the commented code if they're not needed, or implementing them if they are.

Do you want me to help evaluate whether uri_str and is_url variables are needed for the Google converter implementation?

🧰 Tools
🪛 Pylint (3.3.7)

[warning] 156-156: TODO: jerron - check if these are needed

(W0511)

src/mcp_agent/workflows/llm/multipart_converter_azure.py (3)

1-15: Add a module-level docstring for clarity & PEP-257 compliance

A short sentence that states the purpose of the module (e.g. “Utility to convert MCP multipart messages into Azure SDK chat messages.”) helps IDEs and static analysers and becomes the first place maintainers look for context.

+"""
+multipart_converter_azure
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Utility helpers to translate MCP multipart prompt/message objects into the Azure
+`azure.ai.inference` SDK’s message classes (`UserMessage`, `AssistantMessage`,
+etc.).  Provides image / resource MIME handling and tool-result conversion.
+"""
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 1-1: Missing module docstring

(C0114)


[error] 3-15: Unable to import 'azure.ai.inference.models'

(E0401)


71-75: Remove the superfluous else after early return

When the if role == "assistant" branch returns, the control flow leaves the function; the else adds an unnecessary level of indentation and was flagged by Pylint R1705.

-            if role == "assistant":
-                return AssistantMessage(content="")
-            else:
-                return UserMessage(content="")
+            if role == "assistant":
+                return AssistantMessage(content="")
+            return UserMessage(content="")
🧰 Tools
🪛 Pylint (3.3.7)

[refactor] 71-74: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


296-304: Unused loop variable – switch to _ to silence B007 & improve readability

tool_use_id is iterated but never referenced.

-        for tool_use_id, result in tool_results:
+        for _tool_use_id, result in tool_results:
🧰 Tools
🪛 Ruff (0.11.9)

296-296: Loop control variable tool_use_id not used within loop body

Rename unused tool_use_id to _tool_use_id

(B007)

🪛 Pylint (3.3.7)

[warning] 296-296: Unused variable 'tool_use_id'

(W0612)

src/mcp_agent/agents/agent.py (1)

479-503: Nice wrapper, but consider caching results

list_resources() always performs an RPC even if nothing has changed. Mirroring the memoisation strategy used for prompts/tools would avoid round-trips in tight loops.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cbbbd9c and 2ba325f.

📒 Files selected for processing (11)
  • src/mcp_agent/agents/agent.py (11 hunks)
  • src/mcp_agent/utils/resource_utils.py (1 hunks)
  • src/mcp_agent/workflows/llm/augmented_llm_google.py (2 hunks)
  • src/mcp_agent/workflows/llm/multipart_converter_anthropic.py (1 hunks)
  • src/mcp_agent/workflows/llm/multipart_converter_azure.py (1 hunks)
  • src/mcp_agent/workflows/llm/multipart_converter_bedrock.py (1 hunks)
  • src/mcp_agent/workflows/llm/multipart_converter_google.py (1 hunks)
  • tests/utils/test_multipart_converter_anthropic.py (1 hunks)
  • tests/utils/test_multipart_converter_bedrock.py (1 hunks)
  • tests/utils/test_multipart_converter_google.py (1 hunks)
  • tests/utils/test_resource_utils.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/mcp_agent/workflows/llm/augmented_llm_google.py
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/mcp_agent/utils/resource_utils.py (1)
src/mcp_agent/utils/mime_utils.py (2)
  • guess_mime_type (34-39)
  • is_binary_content (62-64)
tests/utils/test_multipart_converter_bedrock.py (2)
src/mcp_agent/utils/prompt_message_multipart.py (1)
  • PromptMessageMultipart (16-151)
src/mcp_agent/workflows/llm/multipart_converter_bedrock.py (10)
  • BedrockConverter (47-303)
  • _is_supported_image_type (51-53)
  • convert_to_bedrock (56-68)
  • convert_prompt_message_to_bedrock (71-78)
  • _convert_embedded_resource (123-190)
  • _determine_mime_type (193-205)
  • _convert_svg_resource (208-215)
  • _create_fallback_text (218-227)
  • convert_tool_result_to_bedrock (230-245)
  • create_tool_results_message (248-268)
🪛 Pylint (3.3.7)
tests/utils/test_multipart_converter_anthropic.py

[convention] 1-1: Missing module docstring

(C0114)


[error] 2-10: Unable to import 'mcp.types'

(E0401)


[error] 11-11: Unable to import 'pydantic'

(E0401)


[error] 13-13: Unable to import 'mcp_agent.utils.prompt_message_multipart'

(E0401)


[error] 14-14: Unable to import 'mcp_agent.workflows.llm.multipart_converter_anthropic'

(E0401)


[convention] 17-17: Missing class docstring

(C0115)


[convention] 18-18: Missing function or method docstring

(C0116)


[warning] 19-19: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 20-20: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 21-21: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 22-22: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 24-24: Missing function or method docstring

(C0116)


[warning] 25-25: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 26-26: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 27-27: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 29-29: Missing function or method docstring

(C0116)


[convention] 36-36: Missing function or method docstring

(C0116)


[convention] 46-46: Missing function or method docstring

(C0116)


[convention] 58-58: Missing function or method docstring

(C0116)


[convention] 68-68: Missing function or method docstring

(C0116)


[convention] 81-81: Missing function or method docstring

(C0116)


[convention] 92-92: Missing function or method docstring

(C0116)


[warning] 98-98: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 109-109: Missing function or method docstring

(C0116)


[warning] 115-115: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 122-122: Missing function or method docstring

(C0116)


[warning] 128-128: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 137-137: Missing function or method docstring

(C0116)


[warning] 143-143: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 149-149: Missing function or method docstring

(C0116)


[warning] 155-155: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 161-161: Missing function or method docstring

(C0116)


[warning] 167-167: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 172-172: Missing function or method docstring

(C0116)


[warning] 176-176: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 179-179: Missing function or method docstring

(C0116)


[warning] 185-185: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 188-188: Missing function or method docstring

(C0116)


[warning] 194-194: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 197-197: Missing function or method docstring

(C0116)


[warning] 203-203: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 206-206: Missing function or method docstring

(C0116)


[warning] 210-210: Access to a protected member _convert_svg_resource of a client class

(W0212)


[convention] 216-216: Missing function or method docstring

(C0116)


[warning] 220-220: Access to a protected member _convert_svg_resource of a client class

(W0212)


[convention] 225-225: Missing function or method docstring

(C0116)


[warning] 228-228: Access to a protected member _create_fallback_text of a client class

(W0212)


[convention] 233-233: Missing function or method docstring

(C0116)


[convention] 248-248: Missing function or method docstring

(C0116)


[convention] 260-260: Missing function or method docstring

(C0116)


[refactor] 17-17: Too many public methods (24/20)

(R0904)

tests/utils/test_multipart_converter_google.py

[convention] 1-1: Missing module docstring

(C0114)


[error] 2-10: Unable to import 'mcp.types'

(E0401)


[error] 12-12: Unable to import 'mcp_agent.utils.prompt_message_multipart'

(E0401)


[error] 13-13: Unable to import 'mcp_agent.workflows.llm.multipart_converter_google'

(E0401)


[convention] 16-16: Missing class docstring

(C0115)


[convention] 17-17: Missing function or method docstring

(C0116)


[warning] 18-18: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 19-19: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 20-20: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 21-21: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 23-23: Missing function or method docstring

(C0116)


[warning] 24-24: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 25-25: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 26-26: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 28-28: Missing function or method docstring

(C0116)


[convention] 35-35: Missing function or method docstring

(C0116)


[convention] 50-50: Missing function or method docstring

(C0116)


[convention] 71-71: Missing function or method docstring

(C0116)


[warning] 85-85: Unused variable 'args'

(W0612)


[convention] 88-88: Missing function or method docstring

(C0116)


[warning] 102-102: Unused variable 'args'

(W0612)


[convention] 105-105: Missing function or method docstring

(C0116)


[convention] 121-121: Missing function or method docstring

(C0116)


[warning] 133-133: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 137-137: Missing function or method docstring

(C0116)


[warning] 149-149: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 152-152: Unused variable 'args'

(W0612)


[convention] 155-155: Missing function or method docstring

(C0116)


[warning] 169-169: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 176-176: Missing function or method docstring

(C0116)


[warning] 188-188: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 191-191: Unused variable 'args'

(W0612)


[convention] 194-194: Missing function or method docstring

(C0116)


[warning] 206-206: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 209-209: Unused variable 'args'

(W0612)


[convention] 213-213: Missing function or method docstring

(C0116)


[warning] 227-227: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 234-234: Missing function or method docstring

(C0116)


[warning] 246-246: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 249-249: Unused variable 'args'

(W0612)


[convention] 252-252: Missing function or method docstring

(C0116)


[warning] 264-264: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 267-267: Unused variable 'args'

(W0612)


[convention] 270-270: Missing function or method docstring

(C0116)


[warning] 284-284: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 287-287: Unused variable 'args'

(W0612)


[convention] 291-291: Missing function or method docstring

(C0116)


[warning] 295-295: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 298-298: Missing function or method docstring

(C0116)


[warning] 305-305: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 308-308: Missing function or method docstring

(C0116)


[warning] 314-314: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 317-317: Missing function or method docstring

(C0116)


[warning] 323-323: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 326-326: Missing function or method docstring

(C0116)


[warning] 336-336: Access to a protected member _convert_svg_resource of a client class

(W0212)


[warning] 338-338: Unused variable 'args'

(W0612)


[convention] 342-342: Missing function or method docstring

(C0116)


[warning] 352-352: Access to a protected member _convert_svg_resource of a client class

(W0212)


[warning] 354-354: Unused variable 'args'

(W0612)


[convention] 357-357: Missing function or method docstring

(C0116)


[warning] 366-366: Access to a protected member _create_fallback_text of a client class

(W0212)


[warning] 368-368: Unused variable 'args'

(W0612)


[convention] 371-371: Missing function or method docstring

(C0116)


[error] 372-372: Unable to import 'pydantic'

(E0401)


[convention] 372-372: Import outside toplevel (pydantic.AnyUrl)

(C0415)


[warning] 386-386: Access to a protected member _create_fallback_text of a client class

(W0212)


[warning] 388-388: Unused variable 'args'

(W0612)


[convention] 391-391: Missing function or method docstring

(C0116)


[convention] 419-419: Missing function or method docstring

(C0116)


[warning] 432-432: Unused variable 'args'

(W0612)


[convention] 437-437: Missing function or method docstring

(C0116)


[convention] 455-455: Missing function or method docstring

(C0116)


[convention] 479-479: Missing function or method docstring

(C0116)


[convention] 500-500: Missing function or method docstring

(C0116)


[refactor] 16-16: Too many public methods (31/20)

(R0904)

tests/utils/test_resource_utils.py

[convention] 1-1: Missing module docstring

(C0114)


[error] 7-7: Unable to import 'mcp.types'

(E0401)


[error] 8-8: Unable to import 'pydantic'

(E0401)


[error] 10-21: Unable to import 'mcp_agent.utils.resource_utils'

(E0401)


[convention] 24-24: Missing class docstring

(C0115)


[convention] 25-25: Missing function or method docstring

(C0116)


[convention] 41-41: Missing function or method docstring

(C0116)


[convention] 50-50: Missing function or method docstring

(C0116)


[convention] 75-75: Missing class docstring

(C0115)


[convention] 76-76: Missing function or method docstring

(C0116)


[convention] 94-94: Missing function or method docstring

(C0116)


[convention] 114-114: Missing function or method docstring

(C0116)


[convention] 126-126: Missing class docstring

(C0115)


[convention] 127-127: Missing function or method docstring

(C0116)


[convention] 131-131: Missing function or method docstring

(C0116)


[convention] 136-136: Missing class docstring

(C0115)


[convention] 137-137: Missing function or method docstring

(C0116)


[refactor] 136-136: Too few public methods (1/2)

(R0903)


[convention] 151-151: Missing class docstring

(C0115)


[convention] 152-152: Missing function or method docstring

(C0116)


[convention] 164-164: Missing function or method docstring

(C0116)


[convention] 178-178: Missing class docstring

(C0115)


[convention] 179-179: Missing function or method docstring

(C0116)


[refactor] 178-178: Too few public methods (1/2)

(R0903)


[convention] 190-190: Missing class docstring

(C0115)


[convention] 191-191: Missing function or method docstring

(C0116)


[refactor] 190-190: Too few public methods (1/2)

(R0903)


[convention] 205-205: Missing class docstring

(C0115)


[convention] 206-206: Missing function or method docstring

(C0116)


[refactor] 205-205: Too few public methods (1/2)

(R0903)


[convention] 218-218: Missing class docstring

(C0115)


[convention] 219-219: Missing function or method docstring

(C0116)


[convention] 222-222: Missing function or method docstring

(C0116)


[convention] 226-226: Missing function or method docstring

(C0116)


[convention] 230-230: Missing function or method docstring

(C0116)


[convention] 234-234: Missing function or method docstring

(C0116)


[convention] 238-238: Missing function or method docstring

(C0116)


[convention] 242-242: Missing function or method docstring

(C0116)


[convention] 247-247: Missing class docstring

(C0115)


[convention] 248-248: Missing function or method docstring

(C0116)


[warning] 253-253: Access to a protected member _url of a client class

(W0212)


[convention] 258-258: Missing function or method docstring

(C0116)


[warning] 263-263: Access to a protected member _url of a client class

(W0212)


[convention] 268-268: Missing function or method docstring

(C0116)


[warning] 273-273: Access to a protected member _url of a client class

(W0212)


[convention] 278-278: Missing function or method docstring

(C0116)


[warning] 283-283: Access to a protected member _url of a client class

(W0212)


[convention] 288-288: Missing function or method docstring

(C0116)


[warning] 293-293: Access to a protected member _url of a client class

(W0212)


[convention] 298-298: Missing function or method docstring

(C0116)


[warning] 303-303: Access to a protected member _url of a client class

(W0212)

src/mcp_agent/workflows/llm/multipart_converter_azure.py

[convention] 138-138: Line too long (112/100)

(C0301)


[convention] 216-216: Line too long (131/100)

(C0301)


[convention] 1-1: Missing module docstring

(C0114)


[error] 3-15: Unable to import 'azure.ai.inference.models'

(E0401)


[error] 16-24: Unable to import 'mcp.types'

(E0401)


[refactor] 71-74: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[refactor] 79-93: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[refactor] 176-205: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 156-156: Too many return statements (11/6)

(R0911)


[warning] 253-253: Unused argument 'tool_use_id'

(W0613)


[warning] 296-296: Unused variable 'tool_use_id'

(W0612)

src/mcp_agent/agents/agent.py

[error] 7-7: Unable to import 'pydantic'

(E0401)


[convention] 544-544: Line too long (102/100)

(C0301)


[refactor] 989-989: Too few public methods (0/2)

(R0903)


[refactor] 998-998: Too few public methods (0/2)

(R0903)


[warning] 1070-1070: Access to a protected member _namespaced_resource_map of a client class

(W0212)


[warning] 1071-1071: Access to a protected member _server_to_resource_map of a client class

(W0212)

src/mcp_agent/utils/resource_utils.py

[convention] 1-1: Missing module docstring

(C0114)


[error] 5-10: Unable to import 'mcp.types'

(E0401)


[error] 11-11: Unable to import 'pydantic'

(E0401)


[refactor] 13-13: Use 'from mcp_agent.utils import mime_utils' instead

(R0402)


[error] 13-13: Unable to import 'mcp_agent.utils.mime_utils'

(E0401)


[warning] 91-91: Redefining name 'EmbeddedResource' from outer scope (line 5)

(W0621)


[warning] 91-91: Redefining name 'TextResourceContents' from outer scope (line 5)

(W0621)


[error] 91-91: Unable to import 'mcp.types'

(E0401)


[warning] 91-91: Reimport 'EmbeddedResource' (imported line 5)

(W0404)


[warning] 91-91: Reimport 'TextResourceContents' (imported line 5)

(W0404)


[convention] 91-91: Import outside toplevel (mcp.types.EmbeddedResource, mcp.types.TextResourceContents)

(C0415)


[refactor] 116-131: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[refactor] 194-197: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[warning] 203-203: Access to a protected member _url of a client class

(W0212)


[warning] 218-218: Catching too general exception Exception

(W0718)


[refactor] 206-216: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[convention] 214-214: Import outside toplevel (os.path)

(C0415)

src/mcp_agent/workflows/llm/multipart_converter_anthropic.py

[convention] 129-129: Line too long (109/100)

(C0301)


[convention] 154-154: Line too long (113/100)

(C0301)


[convention] 198-198: Line too long (109/100)

(C0301)


[convention] 299-299: Line too long (116/100)

(C0301)


[convention] 380-380: Line too long (104/100)

(C0301)


[convention] 1-1: Missing module docstring

(C0114)


[error] 3-15: Unable to import 'anthropic.types'

(E0401)


[error] 16-24: Unable to import 'mcp.types'

(E0401)


[refactor] 215-285: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 244-259: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[warning] 299-299: Access to a protected member _url of a client class

(W0212)


[refactor] 189-189: Too many return statements (14/6)

(R0911)


[refactor] 189-189: Too many branches (13/12)

(R0912)


[warning] 362-362: Access to a protected member _url of a client class

(W0212)

src/mcp_agent/workflows/llm/multipart_converter_bedrock.py

[convention] 102-102: Line too long (115/100)

(C0301)


[convention] 160-160: Line too long (103/100)

(C0301)


[convention] 185-185: Line too long (139/100)

(C0301)


[warning] 132-132: TODO: jerron - check if we need to handle URLs differently

(W0511)


[convention] 1-1: Missing module docstring

(C0114)


[error] 3-11: Unable to import 'mcp.types'

(E0401)


[refactor] 138-174: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 123-123: Too many return statements (11/6)

(R0911)

src/mcp_agent/workflows/llm/multipart_converter_google.py

[convention] 115-115: Line too long (112/100)

(C0301)


[convention] 211-211: Line too long (115/100)

(C0301)


[warning] 156-156: TODO: jerron - check if these are needed

(W0511)


[convention] 1-1: Missing module docstring

(C0114)


[error] 4-4: Unable to import 'google.genai'

(E0401)


[error] 4-4: No name 'genai' in module 'google'

(E0611)


[error] 6-14: Unable to import 'mcp.types'

(E0401)


[refactor] 163-198: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 173-181: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[refactor] 193-198: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[warning] 211-211: Access to a protected member _url of a client class

(W0212)


[refactor] 142-142: Too many return statements (11/6)

(R0911)


[warning] 274-274: Access to a protected member _url of a client class

(W0212)

tests/utils/test_multipart_converter_bedrock.py

[convention] 1-1: Missing module docstring

(C0114)


[error] 2-10: Unable to import 'mcp.types'

(E0401)


[error] 11-11: Unable to import 'pydantic'

(E0401)


[error] 13-13: Unable to import 'mcp_agent.utils.prompt_message_multipart'

(E0401)


[error] 14-14: Unable to import 'mcp_agent.workflows.llm.multipart_converter_bedrock'

(E0401)


[convention] 17-17: Missing class docstring

(C0115)


[convention] 18-18: Missing function or method docstring

(C0116)


[warning] 19-19: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 20-20: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 22-22: Missing function or method docstring

(C0116)


[warning] 23-23: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 24-24: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 25-25: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 26-26: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 27-27: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 29-29: Missing function or method docstring

(C0116)


[convention] 36-36: Missing function or method docstring

(C0116)


[convention] 45-45: Missing function or method docstring

(C0116)


[convention] 56-56: Missing function or method docstring

(C0116)


[convention] 66-66: Missing function or method docstring

(C0116)


[convention] 76-76: Missing function or method docstring

(C0116)


[warning] 82-82: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 87-87: Missing function or method docstring

(C0116)


[warning] 93-93: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 102-102: Missing function or method docstring

(C0116)


[warning] 108-108: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 113-113: Missing function or method docstring

(C0116)


[warning] 119-119: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 125-125: Missing function or method docstring

(C0116)


[warning] 131-131: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 137-137: Missing function or method docstring

(C0116)


[warning] 143-143: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 148-148: Missing function or method docstring

(C0116)


[warning] 154-154: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 159-159: Missing function or method docstring

(C0116)


[warning] 165-165: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 170-170: Missing function or method docstring

(C0116)


[warning] 178-178: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 185-185: Missing function or method docstring

(C0116)


[warning] 189-189: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 192-192: Missing function or method docstring

(C0116)


[warning] 198-198: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 201-201: Missing function or method docstring

(C0116)


[warning] 207-207: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 210-210: Missing function or method docstring

(C0116)


[warning] 216-216: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 219-219: Missing function or method docstring

(C0116)


[warning] 223-223: Access to a protected member _convert_svg_resource of a client class

(W0212)


[convention] 229-229: Missing function or method docstring

(C0116)


[warning] 233-233: Access to a protected member _convert_svg_resource of a client class

(W0212)


[convention] 238-238: Missing function or method docstring

(C0116)


[warning] 241-241: Access to a protected member _create_fallback_text of a client class

(W0212)


[convention] 246-246: Missing function or method docstring

(C0116)


[warning] 253-253: Access to a protected member _create_fallback_text of a client class

(W0212)


[convention] 258-258: Missing function or method docstring

(C0116)


[convention] 272-272: Missing function or method docstring

(C0116)


[convention] 286-286: Missing function or method docstring

(C0116)


[convention] 301-301: Missing function or method docstring

(C0116)


[convention] 325-325: Missing function or method docstring

(C0116)


[convention] 343-343: Missing function or method docstring

(C0116)


[refactor] 17-17: Too many public methods (30/20)

(R0904)

🪛 Ruff (0.11.9)
src/mcp_agent/workflows/llm/multipart_converter_azure.py

296-296: Loop control variable tool_use_id not used within loop body

Rename unused tool_use_id to _tool_use_id

(B007)

🔇 Additional comments (8)
tests/utils/test_multipart_converter_anthropic.py (1)

1-283: Excellent comprehensive test coverage for AnthropicConverter!

This test suite provides thorough coverage of the AnthropicConverter functionality, including:

  • Image type validation for supported/unsupported formats
  • Content conversion scenarios (empty, text, images, embedded resources)
  • Edge cases like missing data and unsupported formats
  • MIME type determination logic
  • Tool result conversion and aggregation
  • Assistant message filtering

The test structure is well-organized and follows good testing practices.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 1-1: Missing module docstring

(C0114)


[error] 2-10: Unable to import 'mcp.types'

(E0401)


[error] 11-11: Unable to import 'pydantic'

(E0401)


[error] 13-13: Unable to import 'mcp_agent.utils.prompt_message_multipart'

(E0401)


[error] 14-14: Unable to import 'mcp_agent.workflows.llm.multipart_converter_anthropic'

(E0401)


[convention] 17-17: Missing class docstring

(C0115)


[convention] 18-18: Missing function or method docstring

(C0116)


[warning] 19-19: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 20-20: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 21-21: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 22-22: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 24-24: Missing function or method docstring

(C0116)


[warning] 25-25: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 26-26: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 27-27: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 29-29: Missing function or method docstring

(C0116)


[convention] 36-36: Missing function or method docstring

(C0116)


[convention] 46-46: Missing function or method docstring

(C0116)


[convention] 58-58: Missing function or method docstring

(C0116)


[convention] 68-68: Missing function or method docstring

(C0116)


[convention] 81-81: Missing function or method docstring

(C0116)


[convention] 92-92: Missing function or method docstring

(C0116)


[warning] 98-98: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 109-109: Missing function or method docstring

(C0116)


[warning] 115-115: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 122-122: Missing function or method docstring

(C0116)


[warning] 128-128: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 137-137: Missing function or method docstring

(C0116)


[warning] 143-143: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 149-149: Missing function or method docstring

(C0116)


[warning] 155-155: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 161-161: Missing function or method docstring

(C0116)


[warning] 167-167: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 172-172: Missing function or method docstring

(C0116)


[warning] 176-176: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 179-179: Missing function or method docstring

(C0116)


[warning] 185-185: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 188-188: Missing function or method docstring

(C0116)


[warning] 194-194: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 197-197: Missing function or method docstring

(C0116)


[warning] 203-203: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 206-206: Missing function or method docstring

(C0116)


[warning] 210-210: Access to a protected member _convert_svg_resource of a client class

(W0212)


[convention] 216-216: Missing function or method docstring

(C0116)


[warning] 220-220: Access to a protected member _convert_svg_resource of a client class

(W0212)


[convention] 225-225: Missing function or method docstring

(C0116)


[warning] 228-228: Access to a protected member _create_fallback_text of a client class

(W0212)


[convention] 233-233: Missing function or method docstring

(C0116)


[convention] 248-248: Missing function or method docstring

(C0116)


[convention] 260-260: Missing function or method docstring

(C0116)


[refactor] 17-17: Too many public methods (24/20)

(R0904)

tests/utils/test_multipart_converter_bedrock.py (1)

1-361: Comprehensive test suite with proper Bedrock API adaptations!

This test suite excellently covers BedrockConverter functionality with proper attention to Bedrock's specific requirements:

  • Correct image format support validation (JPEG/PNG only)
  • Bedrock-specific document format handling for PDFs
  • Thorough embedded resource conversion testing
  • Proper tool result formatting for Bedrock's API structure
  • Good coverage of fallback scenarios and error handling

The test organization and coverage are excellent.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 1-1: Missing module docstring

(C0114)


[error] 2-10: Unable to import 'mcp.types'

(E0401)


[error] 11-11: Unable to import 'pydantic'

(E0401)


[error] 13-13: Unable to import 'mcp_agent.utils.prompt_message_multipart'

(E0401)


[error] 14-14: Unable to import 'mcp_agent.workflows.llm.multipart_converter_bedrock'

(E0401)


[convention] 17-17: Missing class docstring

(C0115)


[convention] 18-18: Missing function or method docstring

(C0116)


[warning] 19-19: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 20-20: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 22-22: Missing function or method docstring

(C0116)


[warning] 23-23: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 24-24: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 25-25: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 26-26: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 27-27: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 29-29: Missing function or method docstring

(C0116)


[convention] 36-36: Missing function or method docstring

(C0116)


[convention] 45-45: Missing function or method docstring

(C0116)


[convention] 56-56: Missing function or method docstring

(C0116)


[convention] 66-66: Missing function or method docstring

(C0116)


[convention] 76-76: Missing function or method docstring

(C0116)


[warning] 82-82: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 87-87: Missing function or method docstring

(C0116)


[warning] 93-93: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 102-102: Missing function or method docstring

(C0116)


[warning] 108-108: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 113-113: Missing function or method docstring

(C0116)


[warning] 119-119: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 125-125: Missing function or method docstring

(C0116)


[warning] 131-131: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 137-137: Missing function or method docstring

(C0116)


[warning] 143-143: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 148-148: Missing function or method docstring

(C0116)


[warning] 154-154: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 159-159: Missing function or method docstring

(C0116)


[warning] 165-165: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 170-170: Missing function or method docstring

(C0116)


[warning] 178-178: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 185-185: Missing function or method docstring

(C0116)


[warning] 189-189: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 192-192: Missing function or method docstring

(C0116)


[warning] 198-198: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 201-201: Missing function or method docstring

(C0116)


[warning] 207-207: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 210-210: Missing function or method docstring

(C0116)


[warning] 216-216: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 219-219: Missing function or method docstring

(C0116)


[warning] 223-223: Access to a protected member _convert_svg_resource of a client class

(W0212)


[convention] 229-229: Missing function or method docstring

(C0116)


[warning] 233-233: Access to a protected member _convert_svg_resource of a client class

(W0212)


[convention] 238-238: Missing function or method docstring

(C0116)


[warning] 241-241: Access to a protected member _create_fallback_text of a client class

(W0212)


[convention] 246-246: Missing function or method docstring

(C0116)


[warning] 253-253: Access to a protected member _create_fallback_text of a client class

(W0212)


[convention] 258-258: Missing function or method docstring

(C0116)


[convention] 272-272: Missing function or method docstring

(C0116)


[convention] 286-286: Missing function or method docstring

(C0116)


[convention] 301-301: Missing function or method docstring

(C0116)


[convention] 325-325: Missing function or method docstring

(C0116)


[convention] 343-343: Missing function or method docstring

(C0116)


[refactor] 17-17: Too many public methods (30/20)

(R0904)

tests/utils/test_multipart_converter_google.py (1)

1-526: Excellent test coverage with comprehensive mocking strategy!

This test suite provides thorough coverage of GoogleConverter functionality with proper mocking of Google's API:

  • Comprehensive image and content conversion testing
  • Proper base64 decoding validation
  • Extensive tool result conversion testing
  • Good coverage of embedded resource handling
  • Appropriate use of mocking for external API dependencies

The test structure and coverage are excellent.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 1-1: Missing module docstring

(C0114)


[error] 2-10: Unable to import 'mcp.types'

(E0401)


[error] 12-12: Unable to import 'mcp_agent.utils.prompt_message_multipart'

(E0401)


[error] 13-13: Unable to import 'mcp_agent.workflows.llm.multipart_converter_google'

(E0401)


[convention] 16-16: Missing class docstring

(C0115)


[convention] 17-17: Missing function or method docstring

(C0116)


[warning] 18-18: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 19-19: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 20-20: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 21-21: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 23-23: Missing function or method docstring

(C0116)


[warning] 24-24: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 25-25: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 26-26: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 28-28: Missing function or method docstring

(C0116)


[convention] 35-35: Missing function or method docstring

(C0116)


[convention] 50-50: Missing function or method docstring

(C0116)


[convention] 71-71: Missing function or method docstring

(C0116)


[warning] 85-85: Unused variable 'args'

(W0612)


[convention] 88-88: Missing function or method docstring

(C0116)


[warning] 102-102: Unused variable 'args'

(W0612)


[convention] 105-105: Missing function or method docstring

(C0116)


[convention] 121-121: Missing function or method docstring

(C0116)


[warning] 133-133: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 137-137: Missing function or method docstring

(C0116)


[warning] 149-149: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 152-152: Unused variable 'args'

(W0612)


[convention] 155-155: Missing function or method docstring

(C0116)


[warning] 169-169: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 176-176: Missing function or method docstring

(C0116)


[warning] 188-188: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 191-191: Unused variable 'args'

(W0612)


[convention] 194-194: Missing function or method docstring

(C0116)


[warning] 206-206: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 209-209: Unused variable 'args'

(W0612)


[convention] 213-213: Missing function or method docstring

(C0116)


[warning] 227-227: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 234-234: Missing function or method docstring

(C0116)


[warning] 246-246: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 249-249: Unused variable 'args'

(W0612)


[convention] 252-252: Missing function or method docstring

(C0116)


[warning] 264-264: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 267-267: Unused variable 'args'

(W0612)


[convention] 270-270: Missing function or method docstring

(C0116)


[warning] 284-284: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 287-287: Unused variable 'args'

(W0612)


[convention] 291-291: Missing function or method docstring

(C0116)


[warning] 295-295: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 298-298: Missing function or method docstring

(C0116)


[warning] 305-305: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 308-308: Missing function or method docstring

(C0116)


[warning] 314-314: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 317-317: Missing function or method docstring

(C0116)


[warning] 323-323: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 326-326: Missing function or method docstring

(C0116)


[warning] 336-336: Access to a protected member _convert_svg_resource of a client class

(W0212)


[warning] 338-338: Unused variable 'args'

(W0612)


[convention] 342-342: Missing function or method docstring

(C0116)


[warning] 352-352: Access to a protected member _convert_svg_resource of a client class

(W0212)


[warning] 354-354: Unused variable 'args'

(W0612)


[convention] 357-357: Missing function or method docstring

(C0116)


[warning] 366-366: Access to a protected member _create_fallback_text of a client class

(W0212)


[warning] 368-368: Unused variable 'args'

(W0612)


[convention] 371-371: Missing function or method docstring

(C0116)


[error] 372-372: Unable to import 'pydantic'

(E0401)


[convention] 372-372: Import outside toplevel (pydantic.AnyUrl)

(C0415)


[warning] 386-386: Access to a protected member _create_fallback_text of a client class

(W0212)


[warning] 388-388: Unused variable 'args'

(W0612)


[convention] 391-391: Missing function or method docstring

(C0116)


[convention] 419-419: Missing function or method docstring

(C0116)


[warning] 432-432: Unused variable 'args'

(W0612)


[convention] 437-437: Missing function or method docstring

(C0116)


[convention] 455-455: Missing function or method docstring

(C0116)


[convention] 479-479: Missing function or method docstring

(C0116)


[convention] 500-500: Missing function or method docstring

(C0116)


[refactor] 16-16: Too many public methods (31/20)

(R0904)

src/mcp_agent/workflows/llm/multipart_converter_bedrock.py (1)

47-303: Well-implemented converter with excellent error handling!

The BedrockConverter class provides a robust implementation with:

  • Comprehensive content type handling (text, images, embedded resources)
  • Proper fallback mechanisms for unsupported formats
  • Good MIME type detection logic
  • Appropriate tool result conversion
  • Strong type safety with proper type hints

The implementation follows good practices and handles edge cases well.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 102-102: Line too long (115/100)

(C0301)


[convention] 160-160: Line too long (103/100)

(C0301)


[convention] 185-185: Line too long (139/100)

(C0301)


[warning] 132-132: TODO: jerron - check if we need to handle URLs differently

(W0511)


[refactor] 138-174: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 123-123: Too many return statements (11/6)

(R0911)

src/mcp_agent/workflows/llm/multipart_converter_anthropic.py (1)

322-323: Verify MIME type determination logic.

The code correctly uses str(resource.uri) which is good, but verify this handles all expected URI types properly.

The MIME type determination logic looks correct and uses the proper public API for URI string conversion.

src/mcp_agent/workflows/llm/multipart_converter_google.py (1)

305-316: Tool result content handling looks good.

The tool result content is now properly serialized and included in the function response, addressing the previous concern about unused content.

The implementation correctly serializes the content parts and includes them in the function response payload.

src/mcp_agent/agents/agent.py (2)

132-139: Great – resource maps added to the private state
The additional caches align resources with tools & prompts.


1222-1248: AgentTasks: list/read resource tasks wired correctly – LGTM
The aggregator delegation and error handling look solid.

Comment on lines +530 to +593
async def create_prompt(
self,
*,
prompt_name: str | None = None,
arguments: dict[str, str] | None = None,
resource_uris: list[str | AnyUrl] | str | AnyUrl | None = None,
server_name: str | None = None,
) -> list[PromptMessage]:
"""
Create prompt messages from a prompt name and/or resource URIs.

Args:
prompt_name: Name of the prompt to retrieve
arguments: Arguments for the prompt (only used with prompt_name)
resource_uris: URI(s) of the resource(s) to retrieve. Can be a single URI or list of URIs.
server_name: Optional server name to target

Returns:
List of PromptMessage objects. If both prompt_name and resource_uris are provided,
the results are combined with prompt messages first, then resource messages.

Raises:
ValueError: If neither prompt_name nor resource_uris are provided
"""
if prompt_name is None and resource_uris is None:
raise ValueError(
"Must specify at least one of prompt_name or resource_uris"
)

messages = []

# Get prompt messages if prompt_name is provided
if prompt_name is not None:
result = await self.get_prompt(
prompt_name, arguments, server_name=server_name
)
if getattr(result, "isError", False):
raise ValueError(
f"Error getting prompt '{prompt_name}': {result.description}"
)
messages.extend(result.messages)

# Get resource messages if resource_uris is provided
if resource_uris is not None:
# Normalize to list
if isinstance(resource_uris, (str, AnyUrl)):
uris_list = [resource_uris]
else:
uris_list = resource_uris

# Process each URI
for uri in uris_list:
resource_result = await self.read_resource(str(uri), server_name)
resource_messages = [
PromptMessage(
role="user",
content=EmbeddedResource(type="resource", resource=content),
)
for content in resource_result.contents
]
messages.extend(resource_messages)

return messages

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

create_prompt() ignores errors from read_resource

If read_resource() returns an error (e.g. network failure) the current code proceeds and will raise when trying to iterate resource_result.contents. Add an error guard similar to the prompt branch:

                resource_result = await self.read_resource(str(uri), server_name)
+                if getattr(resource_result, "isError", False):
+                    raise ValueError(
+                        f"Error reading resource '{uri}': {resource_result.description}"
+                    )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async def create_prompt(
self,
*,
prompt_name: str | None = None,
arguments: dict[str, str] | None = None,
resource_uris: list[str | AnyUrl] | str | AnyUrl | None = None,
server_name: str | None = None,
) -> list[PromptMessage]:
"""
Create prompt messages from a prompt name and/or resource URIs.
Args:
prompt_name: Name of the prompt to retrieve
arguments: Arguments for the prompt (only used with prompt_name)
resource_uris: URI(s) of the resource(s) to retrieve. Can be a single URI or list of URIs.
server_name: Optional server name to target
Returns:
List of PromptMessage objects. If both prompt_name and resource_uris are provided,
the results are combined with prompt messages first, then resource messages.
Raises:
ValueError: If neither prompt_name nor resource_uris are provided
"""
if prompt_name is None and resource_uris is None:
raise ValueError(
"Must specify at least one of prompt_name or resource_uris"
)
messages = []
# Get prompt messages if prompt_name is provided
if prompt_name is not None:
result = await self.get_prompt(
prompt_name, arguments, server_name=server_name
)
if getattr(result, "isError", False):
raise ValueError(
f"Error getting prompt '{prompt_name}': {result.description}"
)
messages.extend(result.messages)
# Get resource messages if resource_uris is provided
if resource_uris is not None:
# Normalize to list
if isinstance(resource_uris, (str, AnyUrl)):
uris_list = [resource_uris]
else:
uris_list = resource_uris
# Process each URI
for uri in uris_list:
resource_result = await self.read_resource(str(uri), server_name)
resource_messages = [
PromptMessage(
role="user",
content=EmbeddedResource(type="resource", resource=content),
)
for content in resource_result.contents
]
messages.extend(resource_messages)
return messages
for uri in uris_list:
resource_result = await self.read_resource(str(uri), server_name)
if getattr(resource_result, "isError", False):
raise ValueError(
f"Error reading resource '{uri}': {resource_result.description}"
)
resource_messages = [
PromptMessage(
role="user",
content=EmbeddedResource(type="resource", resource=content),
)
for content in resource_result.contents
]
messages.extend(resource_messages)
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 544-544: Line too long (102/100)

(C0301)

🤖 Prompt for AI Agents
In src/mcp_agent/agents/agent.py around lines 530 to 593, the create_prompt
method does not handle errors from read_resource, which can cause exceptions
when accessing resource_result.contents. Add a check after calling read_resource
to detect if the result indicates an error (similar to the prompt_name branch),
and raise a ValueError with a descriptive message if an error is present before
proceeding to process contents.

…ty; update example usage and tests accordingly.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

♻️ Duplicate comments (3)
examples/mcp_primitives/mcp_basic_agent/main.py (1)

25-28: Address the security concern with hardcoded API key.

This is the same issue flagged in the previous review. The hardcoded API key presents a security risk and should be replaced with environment variable usage.

tests/utils/test_resource_utils.py (1)

159-159: ⚠️ Potential issue

Fix AnyUrl constructor syntax to prevent test failures.

The AnyUrl(url="...") syntax is incorrect and will raise TypeError. Use positional argument instead.

-        assert result.resource.uri == AnyUrl(url="resource://mcp-agent/test.txt")
+        assert str(result.resource.uri) == "resource://mcp-agent/test.txt"

Apply similar fixes to lines 172, 199, and 212:

-        assert result.resource.uri == AnyUrl(url="resource://mcp-agent/image.png")
+        assert str(result.resource.uri) == "resource://mcp-agent/image.png"

-        assert result.resource.uri == AnyUrl(url="file://test.bin")
+        assert str(result.resource.uri) == "file://test.bin"

-        assert result.resource.uri == AnyUrl(url="file://test.txt")
+        assert str(result.resource.uri) == "file://test.txt"

Also applies to: 172-172, 199-199, 212-212

src/mcp_agent/workflows/llm/multipart_converter_openai.py (1)

426-428: tool_call_id on a "user" message is invalid – remove it
OpenAI chat schema rejects unknown fields on user messages. The exact same issue was pointed out in a previous review and is still present.

-        user_message["tool_call_id"] = tool_call_id

Instead, keep the extra artefacts as a plain user message without the extra key – the tool message already carries the identifier.

🧹 Nitpick comments (12)
examples/mcp_primitives/mcp_basic_agent/main.py (2)

1-1: Add module docstring for better documentation.

Consider adding a module-level docstring to explain the purpose and usage of this example script.

+"""
+Example script demonstrating MCP agent framework usage with resources and prompts.
+
+This script shows how to:
+- Configure an MCP application with settings
+- Connect to a demo MCP server
+- List and use resources and prompts
+- Generate responses using OpenAI LLM
+"""
 import asyncio
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 1-1: Missing module docstring

(C0114)


36-36: Add function docstring for example_usage.

The function lacks documentation explaining its purpose and workflow.

 async def example_usage():
+    """
+    Demonstrate the MCP agent capabilities including resource and prompt handling.
+    
+    This function showcases:
+    - Agent creation and server connection
+    - Resource and prompt listing
+    - Combined prompt creation with resources
+    - LLM integration for content generation
+    """
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 36-36: Missing function or method docstring

(C0116)

src/mcp_agent/utils/resource_utils.py (4)

1-1: Add comprehensive module docstring.

The module lacks documentation explaining its purpose and main functionalities.

+"""
+Resource utilities for MCP agent framework.
+
+This module provides utilities for:
+- Locating and loading resource files relative to prompt files
+- Determining MIME types and handling binary/text content
+- Creating resource URIs and embedded resource objects
+- Normalizing URIs and extracting titles
+
+The utilities support the broader MCP agent resource management capabilities
+and integrate with the multipart message conversion system.
+"""
 import base64
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 1-1: Missing module docstring

(C0114)


115-130: Simplify conditional structure.

The unnecessary else clause can be removed for better readability.

     if is_binary:
         return EmbeddedResource(
             type="resource",
             resource=BlobResourceContents(
                 **resource_args,
                 blob=content,
             ),
         )
-    else:
-        return EmbeddedResource(
-            type="resource",
-            resource=TextResourceContents(
-                **resource_args,
-                text=content,
-            ),
-        )
+    
+    return EmbeddedResource(
+        type="resource",
+        resource=TextResourceContents(
+            **resource_args,
+            text=content,
+        ),
+    )
🧰 Tools
🪛 Pylint (3.3.7)

[refactor] 115-130: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


213-213: Move import to module level.

The local import of os.path should be moved to the top of the module for better practice.

+import os.path
 import base64
 from pathlib import Path

Then remove the local import:

-            import os.path
-
             return os.path.basename(uri.path)
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 213-213: Import outside toplevel (os.path)

(C0415)


217-218: Use more specific exception handling.

Catching the general Exception is too broad and may hide unexpected errors.

-    except Exception:
+    except (AttributeError, ValueError, TypeError):
         pass
🧰 Tools
🪛 Pylint (3.3.7)

[warning] 217-217: Catching too general exception Exception

(W0718)

src/mcp_agent/workflows/llm/multipart_converter_anthropic.py (2)

1-1: Add comprehensive module docstring.

The module lacks documentation explaining its purpose in the MCP framework.

+"""
+Anthropic API message converter for MCP agent framework.
+
+This module provides the AnthropicConverter class which converts MCP message
+and content types into Anthropic API-compatible message formats. It handles:
+- Multipart prompt messages with mixed content types
+- Text, image, and embedded resource content
+- Tool call results and message aggregation
+- MIME type validation and fallback handling
+
+The converter ensures compatibility with Anthropic's message schema while
+preserving content fidelity where possible.
+"""
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 1-1: Missing module docstring

(C0114)


189-304: Consider refactoring complex function with many branches.

The _convert_embedded_resource function has 13 branches and 14 return statements, making it complex to maintain and test.

Consider breaking this into smaller, focused functions:

@staticmethod
def _convert_embedded_resource(resource: EmbeddedResource, document_mode: bool = True) -> ContentBlockParam:
    """Convert EmbeddedResource to appropriate Anthropic block type."""
    resource_content = resource.resource
    mime_type = AnthropicConverter._determine_mime_type(resource_content)
    
    # Delegate to specific handlers based on MIME type
    if mime_type == "image/svg+xml":
        return AnthropicConverter._handle_svg_resource(resource_content)
    elif is_image_mime_type(mime_type):
        return AnthropicConverter._handle_image_resource(resource, mime_type)
    elif mime_type == "application/pdf":
        return AnthropicConverter._handle_pdf_resource(resource, resource_content)
    elif is_text_mime_type(mime_type):
        return AnthropicConverter._handle_text_resource(resource, resource_content, document_mode)
    else:
        return AnthropicConverter._handle_unknown_resource(resource, mime_type)
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 198-198: Line too long (109/100)

(C0301)


[convention] 299-299: Line too long (116/100)

(C0301)


[refactor] 215-285: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 244-259: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 189-189: Too many return statements (14/6)

(R0911)


[refactor] 189-189: Too many branches (13/12)

(R0912)

src/mcp_agent/workflows/llm/multipart_converter_google.py (2)

340-374: Parameter shadowing & ambiguous API

convert_mixed_messages_to_google(message: MessageTypes) immediately re-uses the name messages for the local list, overwriting the incoming variable and reducing readability.

-        messages: list[types.Content] = []
+        converted_messages: list[types.Content] = []
 ...
-            messages.append(
+            converted_messages.append(
 ...
-        return messages
+        return converted_messages

Also, the docstring mentions “a list of messages” while the signature accepts a single message or list – clarify the wording.


156-156: Remove residual TODO comment

# TODO: jerron - check if these are needed is stale; either act on it or drop it to keep the codebase tidy.

🧰 Tools
🪛 Pylint (3.3.7)

[warning] 156-156: TODO: jerron - check if these are needed

(W0511)

src/mcp_agent/workflows/llm/multipart_converter_openai.py (2)

78-81: Avoid Yoda-style condition for readability

1 == len(...) reads backwards. Switch operands to the conventional order.

-        if 1 == len(multipart_msg.content) and is_text_content(
+        if len(multipart_msg.content) == 1 and is_text_content(
🧰 Tools
🪛 Ruff (0.11.9)

78-78: Yoda condition detected

Rewrite as len(multipart_msg.content) == 1

(SIM300)


1-1: Add module docstring

Both converter modules lack a top-level docstring, which hampers automated documentation generation.

"""Utilities to convert MCP multipart messages to OpenAI chat-completion payloads."""
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 1-1: Missing module docstring

(C0114)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2ba325f and 7a8ece7.

📒 Files selected for processing (6)
  • examples/mcp_primitives/mcp_basic_agent/main.py (1 hunks)
  • src/mcp_agent/utils/resource_utils.py (1 hunks)
  • src/mcp_agent/workflows/llm/multipart_converter_anthropic.py (1 hunks)
  • src/mcp_agent/workflows/llm/multipart_converter_google.py (1 hunks)
  • src/mcp_agent/workflows/llm/multipart_converter_openai.py (1 hunks)
  • tests/utils/test_resource_utils.py (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/mcp_agent/utils/resource_utils.py (1)
src/mcp_agent/utils/mime_utils.py (2)
  • guess_mime_type (34-39)
  • is_binary_content (62-64)
🪛 Pylint (3.3.7)
tests/utils/test_resource_utils.py

[convention] 1-1: Missing module docstring

(C0114)


[error] 6-6: Unable to import 'mcp.types'

(E0401)


[error] 7-7: Unable to import 'pydantic'

(E0401)


[error] 9-20: Unable to import 'mcp_agent.utils.resource_utils'

(E0401)


[convention] 23-23: Missing class docstring

(C0115)


[convention] 24-24: Missing function or method docstring

(C0116)


[convention] 40-40: Missing function or method docstring

(C0116)


[convention] 49-49: Missing function or method docstring

(C0116)


[convention] 74-74: Missing class docstring

(C0115)


[convention] 75-75: Missing function or method docstring

(C0116)


[convention] 93-93: Missing function or method docstring

(C0116)


[convention] 113-113: Missing function or method docstring

(C0116)


[convention] 125-125: Missing class docstring

(C0115)


[convention] 126-126: Missing function or method docstring

(C0116)


[convention] 130-130: Missing function or method docstring

(C0116)


[convention] 135-135: Missing class docstring

(C0115)


[convention] 136-136: Missing function or method docstring

(C0116)


[refactor] 135-135: Too few public methods (1/2)

(R0903)


[convention] 150-150: Missing class docstring

(C0115)


[convention] 151-151: Missing function or method docstring

(C0116)


[convention] 163-163: Missing function or method docstring

(C0116)


[convention] 177-177: Missing class docstring

(C0115)


[convention] 178-178: Missing function or method docstring

(C0116)


[refactor] 177-177: Too few public methods (1/2)

(R0903)


[convention] 189-189: Missing class docstring

(C0115)


[convention] 190-190: Missing function or method docstring

(C0116)


[refactor] 189-189: Too few public methods (1/2)

(R0903)


[convention] 204-204: Missing class docstring

(C0115)


[convention] 205-205: Missing function or method docstring

(C0116)


[refactor] 204-204: Too few public methods (1/2)

(R0903)


[convention] 217-217: Missing class docstring

(C0115)


[convention] 218-218: Missing function or method docstring

(C0116)


[convention] 221-221: Missing function or method docstring

(C0116)


[convention] 225-225: Missing function or method docstring

(C0116)


[convention] 229-229: Missing function or method docstring

(C0116)


[convention] 233-233: Missing function or method docstring

(C0116)


[convention] 237-237: Missing function or method docstring

(C0116)


[convention] 241-241: Missing function or method docstring

(C0116)


[convention] 246-246: Missing class docstring

(C0115)


[convention] 247-247: Missing function or method docstring

(C0116)


[convention] 253-253: Missing function or method docstring

(C0116)


[convention] 259-259: Missing function or method docstring

(C0116)


[convention] 265-265: Missing function or method docstring

(C0116)


[convention] 271-271: Missing function or method docstring

(C0116)


[convention] 277-277: Missing function or method docstring

(C0116)

examples/mcp_primitives/mcp_basic_agent/main.py

[convention] 1-1: Missing module docstring

(C0114)


[error] 4-4: Unable to import 'mcp_agent.app'

(E0401)


[error] 5-11: Unable to import 'mcp_agent.config'

(E0401)


[error] 12-12: Unable to import 'mcp_agent.agents.agent'

(E0401)


[error] 13-13: Unable to import 'mcp_agent.workflows.llm.augmented_llm_openai'

(E0401)


[convention] 36-36: Missing function or method docstring

(C0116)

src/mcp_agent/utils/resource_utils.py

[convention] 1-1: Missing module docstring

(C0114)


[error] 5-10: Unable to import 'mcp.types'

(E0401)


[error] 11-11: Unable to import 'pydantic'

(E0401)


[refactor] 13-13: Use 'from mcp_agent.utils import mime_utils' instead

(R0402)


[error] 13-13: Unable to import 'mcp_agent.utils.mime_utils'

(E0401)


[refactor] 115-130: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[refactor] 193-196: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[warning] 217-217: Catching too general exception Exception

(W0718)


[refactor] 205-215: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[convention] 213-213: Import outside toplevel (os.path)

(C0415)

src/mcp_agent/workflows/llm/multipart_converter_anthropic.py

[convention] 129-129: Line too long (109/100)

(C0301)


[convention] 154-154: Line too long (113/100)

(C0301)


[convention] 198-198: Line too long (109/100)

(C0301)


[convention] 299-299: Line too long (116/100)

(C0301)


[convention] 380-380: Line too long (104/100)

(C0301)


[convention] 1-1: Missing module docstring

(C0114)


[error] 3-15: Unable to import 'anthropic.types'

(E0401)


[error] 16-24: Unable to import 'mcp.types'

(E0401)


[refactor] 215-285: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 244-259: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 189-189: Too many return statements (14/6)

(R0911)


[refactor] 189-189: Too many branches (13/12)

(R0912)

src/mcp_agent/workflows/llm/multipart_converter_google.py

[convention] 115-115: Line too long (112/100)

(C0301)


[convention] 211-211: Line too long (115/100)

(C0301)


[warning] 156-156: TODO: jerron - check if these are needed

(W0511)


[convention] 1-1: Missing module docstring

(C0114)


[error] 4-4: Unable to import 'google.genai'

(E0401)


[error] 4-4: No name 'genai' in module 'google'

(E0611)


[error] 6-14: Unable to import 'mcp.types'

(E0401)


[refactor] 163-198: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 173-181: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[refactor] 193-198: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[refactor] 142-142: Too many return statements (11/6)

(R0911)

src/mcp_agent/workflows/llm/multipart_converter_openai.py

[convention] 269-269: Line too long (122/100)

(C0301)


[convention] 370-370: Line too long (105/100)

(C0301)


[convention] 1-1: Missing module docstring

(C0114)


[error] 3-9: Unable to import 'mcp.types'

(E0401)


[error] 10-10: Unable to import 'openai.types.chat'

(E0401)


[warning] 106-106: Catching too general exception Exception

(W0718)


[refactor] 255-261: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[refactor] 265-278: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 304-312: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 227-227: Too many return statements (10/6)

(R0911)


[refactor] 227-227: Too many branches (13/12)

(R0912)

🪛 Ruff (0.11.9)
src/mcp_agent/workflows/llm/multipart_converter_openai.py

78-78: Yoda condition detected

Rewrite as len(multipart_msg.content) == 1

(SIM300)


195-196: Use a single if statement instead of nested if statements

(SIM102)


281-300: Combine if branches using logical or operator

Combine if branches

(SIM114)

🔇 Additional comments (4)
tests/utils/test_resource_utils.py (1)

1-282: Excellent test coverage and structure.

The test suite provides comprehensive coverage of the resource utilities with good organization by functionality and thorough edge case testing.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 1-1: Missing module docstring

(C0114)


[error] 6-6: Unable to import 'mcp.types'

(E0401)


[error] 7-7: Unable to import 'pydantic'

(E0401)


[error] 9-20: Unable to import 'mcp_agent.utils.resource_utils'

(E0401)


[convention] 23-23: Missing class docstring

(C0115)


[convention] 24-24: Missing function or method docstring

(C0116)


[convention] 40-40: Missing function or method docstring

(C0116)


[convention] 49-49: Missing function or method docstring

(C0116)


[convention] 74-74: Missing class docstring

(C0115)


[convention] 75-75: Missing function or method docstring

(C0116)


[convention] 93-93: Missing function or method docstring

(C0116)


[convention] 113-113: Missing function or method docstring

(C0116)


[convention] 125-125: Missing class docstring

(C0115)


[convention] 126-126: Missing function or method docstring

(C0116)


[convention] 130-130: Missing function or method docstring

(C0116)


[convention] 135-135: Missing class docstring

(C0115)


[convention] 136-136: Missing function or method docstring

(C0116)


[refactor] 135-135: Too few public methods (1/2)

(R0903)


[convention] 150-150: Missing class docstring

(C0115)


[convention] 151-151: Missing function or method docstring

(C0116)


[convention] 163-163: Missing function or method docstring

(C0116)


[convention] 177-177: Missing class docstring

(C0115)


[convention] 178-178: Missing function or method docstring

(C0116)


[refactor] 177-177: Too few public methods (1/2)

(R0903)


[convention] 189-189: Missing class docstring

(C0115)


[convention] 190-190: Missing function or method docstring

(C0116)


[refactor] 189-189: Too few public methods (1/2)

(R0903)


[convention] 204-204: Missing class docstring

(C0115)


[convention] 205-205: Missing function or method docstring

(C0116)


[refactor] 204-204: Too few public methods (1/2)

(R0903)


[convention] 217-217: Missing class docstring

(C0115)


[convention] 218-218: Missing function or method docstring

(C0116)


[convention] 221-221: Missing function or method docstring

(C0116)


[convention] 225-225: Missing function or method docstring

(C0116)


[convention] 229-229: Missing function or method docstring

(C0116)


[convention] 233-233: Missing function or method docstring

(C0116)


[convention] 237-237: Missing function or method docstring

(C0116)


[convention] 241-241: Missing function or method docstring

(C0116)


[convention] 246-246: Missing class docstring

(C0115)


[convention] 247-247: Missing function or method docstring

(C0116)


[convention] 253-253: Missing function or method docstring

(C0116)


[convention] 259-259: Missing function or method docstring

(C0116)


[convention] 265-265: Missing function or method docstring

(C0116)


[convention] 271-271: Missing function or method docstring

(C0116)


[convention] 277-277: Missing function or method docstring

(C0116)

src/mcp_agent/workflows/llm/multipart_converter_anthropic.py (3)

87-98: Well-implemented assistant message filtering.

The filtering logic correctly handles the Anthropic constraint that assistant messages can only contain text blocks, with appropriate logging for removed content.


158-177: Robust image data validation and fallback handling.

The implementation properly validates image data availability and provides meaningful fallback text when data is missing, addressing previous concerns about empty data fields.


299-299: Correct usage of public API for URI access.

The code now properly uses str(uri) instead of accessing protected members, following best practices for stable API usage.

Also applies to: 362-362

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 299-299: Line too long (116/100)

(C0301)

Comment on lines +122 to +126
types.Part.from_bytes(
data=base64.b64decode(image_data),
mime_type=image_content.mimeType,
)
)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add safe-guard around base64.b64decode

If the incoming image_data is malformed or not padded correctly, binascii.Error will bubble up and break the whole request.
Consider wrapping the decode in a try/except and falling back to a text part on failure.

Also applies to: 175-177

🤖 Prompt for AI Agents
In src/mcp_agent/workflows/llm/multipart_converter_google.py around lines 122 to
126 and also lines 175 to 177, the base64.b64decode call on image_data can raise
a binascii.Error if the data is malformed or improperly padded, which would
break the request. Wrap the base64.b64decode call in a try/except block catching
binascii.Error, and in the except block, create and return a fallback text part
instead of the image part to safely handle decoding failures without crashing.

Comment on lines +106 to +108
except Exception as e:
_logger.warning(f"Error converting content item: {e}")
# Create a text block with information about the conversion error
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Catching bare Exception hides actionable errors

Catching the root Exception without re-raising or narrowing can mask programming mistakes (e.g., AttributeError, TypeError).
Consider catching the specific exceptions you expect from conversion utilities instead.

🧰 Tools
🪛 Pylint (3.3.7)

[warning] 106-106: Catching too general exception Exception

(W0718)

🤖 Prompt for AI Agents
In src/mcp_agent/workflows/llm/multipart_converter_openai.py around lines 106 to
108, the code catches a broad Exception which can hide important programming
errors. Refine the exception handling by catching only the specific exceptions
expected from the conversion utilities, such as ValueError or custom conversion
errors, and avoid catching generic Exception. This will prevent masking bugs and
allow other unexpected exceptions to propagate properly.

… improved compatibility; update tests to reflect changes in role assignments and message structures.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (10)
src/mcp_agent/workflows/llm/multipart_converter_openai.py (1)

427-428: ⚠️ Potential issue

Invalid tool_call_id on user message
OpenAI’s chat schema does not allow a tool_call_id on a "user" message. Remove this assignment to comply with the API.

Apply this diff:

-        user_message["tool_call_id"] = tool_call_id
examples/mcp_primitives/mcp_basic_agent/main.py (1)

15-29: Security concern: Hardcoded API key detected.

The hardcoded API key remains a security issue as previously identified.

tests/utils/test_multipart_converter_google.py (1)

17-525: Consider using public APIs instead of testing private methods

Similar to the Azure converter tests, this test class extensively tests private methods, creating tight coupling with implementation details.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 17-17: Missing class docstring

(C0115)


[convention] 18-18: Missing function or method docstring

(C0116)


[warning] 19-19: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 20-20: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 21-21: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 22-22: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 24-24: Missing function or method docstring

(C0116)


[warning] 25-25: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 26-26: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 27-27: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 29-29: Missing function or method docstring

(C0116)


[convention] 36-36: Missing function or method docstring

(C0116)


[convention] 51-51: Missing function or method docstring

(C0116)


[convention] 72-72: Missing function or method docstring

(C0116)


[warning] 86-86: Unused variable 'args'

(W0612)


[convention] 89-89: Missing function or method docstring

(C0116)


[warning] 103-103: Unused variable 'args'

(W0612)


[convention] 106-106: Missing function or method docstring

(C0116)


[convention] 122-122: Missing function or method docstring

(C0116)


[warning] 134-134: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 138-138: Missing function or method docstring

(C0116)


[warning] 150-150: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 153-153: Unused variable 'args'

(W0612)


[convention] 156-156: Missing function or method docstring

(C0116)


[warning] 170-170: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 177-177: Missing function or method docstring

(C0116)


[warning] 189-189: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 192-192: Unused variable 'args'

(W0612)


[convention] 195-195: Missing function or method docstring

(C0116)


[warning] 207-207: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 210-210: Unused variable 'args'

(W0612)


[convention] 214-214: Missing function or method docstring

(C0116)


[warning] 228-228: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 235-235: Missing function or method docstring

(C0116)


[warning] 247-247: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 250-250: Unused variable 'args'

(W0612)


[convention] 253-253: Missing function or method docstring

(C0116)


[warning] 265-265: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 268-268: Unused variable 'args'

(W0612)


[convention] 271-271: Missing function or method docstring

(C0116)


[warning] 285-285: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 288-288: Unused variable 'args'

(W0612)


[convention] 292-292: Missing function or method docstring

(C0116)


[warning] 296-296: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 299-299: Missing function or method docstring

(C0116)


[warning] 304-304: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 307-307: Missing function or method docstring

(C0116)


[warning] 313-313: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 316-316: Missing function or method docstring

(C0116)


[warning] 322-322: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 325-325: Missing function or method docstring

(C0116)


[warning] 335-335: Access to a protected member _convert_svg_resource of a client class

(W0212)


[warning] 337-337: Unused variable 'args'

(W0612)


[convention] 341-341: Missing function or method docstring

(C0116)


[warning] 351-351: Access to a protected member _convert_svg_resource of a client class

(W0212)


[warning] 353-353: Unused variable 'args'

(W0612)


[convention] 356-356: Missing function or method docstring

(C0116)


[warning] 365-365: Access to a protected member _create_fallback_text of a client class

(W0212)


[warning] 367-367: Unused variable 'args'

(W0612)


[convention] 370-370: Missing function or method docstring

(C0116)


[warning] 371-371: Redefining name 'AnyUrl' from outer scope (line 11)

(W0621)


[error] 371-371: Unable to import 'pydantic'

(E0401)


[warning] 371-371: Reimport 'AnyUrl' (imported line 11)

(W0404)


[convention] 371-371: Import outside toplevel (pydantic.AnyUrl)

(C0415)


[warning] 385-385: Access to a protected member _create_fallback_text of a client class

(W0212)


[warning] 387-387: Unused variable 'args'

(W0612)


[convention] 390-390: Missing function or method docstring

(C0116)


[convention] 418-418: Missing function or method docstring

(C0116)


[warning] 431-431: Unused variable 'args'

(W0612)


[convention] 436-436: Missing function or method docstring

(C0116)


[convention] 454-454: Missing function or method docstring

(C0116)


[convention] 478-478: Missing function or method docstring

(C0116)


[convention] 499-499: Missing function or method docstring

(C0116)


[refactor] 17-17: Too many public methods (31/20)

(R0904)

src/mcp_agent/workflows/llm/multipart_converter_google.py (2)

306-306: ⚠️ Potential issue

Part has to_dict() not to_json_dict() – will raise AttributeError

The Google GenAI types.Part class exposes to_dict() (and from_dict()), but not to_json_dict(). Calling a non-existent method will crash every time a tool result is converted.

Apply this fix:

-serialized_parts = [part.to_json_dict() for part in google_content]
+serialized_parts = [part.to_dict() for part in google_content]

122-126: ⚠️ Potential issue

Add safe-guard around base64.b64decode

If the incoming image data is malformed or not padded correctly, binascii.Error will bubble up and break the whole request.

Consider wrapping the decode in a try/except block:

+import binascii

# In _convert_content_items method around line 122:
-google_parts.append(
-    types.Part.from_bytes(
-        data=base64.b64decode(image_data),
-        mime_type=image_content.mimeType,
-    )
-)
+try:
+    decoded_data = base64.b64decode(image_data)
+    google_parts.append(
+        types.Part.from_bytes(
+            data=decoded_data,
+            mime_type=image_content.mimeType,
+        )
+    )
+except binascii.Error:
+    google_parts.append(
+        types.Part.from_text(
+            text=f"[Image data is corrupted or invalid for '{image_content.mimeType}']"
+        )
+    )

Apply similar error handling at lines 175-177 and 186.

Also applies to: 175-177, 186-186

src/mcp_agent/workflows/llm/multipart_converter_azure.py (5)

332-366: Clarify parameter naming to avoid confusion

While not technically shadowing, having a parameter named message and a local variable named messages can be confusing. Also, the docstring mentions "Anthropic-compatible messages" which appears to be copy-paste from another converter.

Consider renaming for clarity and fixing the docstring:

-def convert_mixed_messages_to_azure(
-    message: MessageTypes,
-) -> List[...]:
-    """
-    Convert a list of mixed messages to a list of Azure-compatible messages.
-    
-    Args:
-        messages: List of mixed message objects
-    
-    Returns:
-        A list of Azure-compatible MessageParam objects
-    """
-    messages = []
+def convert_mixed_messages_to_azure(
+    message: MessageTypes,
+) -> List[...]:
+    """
+    Convert mixed message types to Azure-compatible messages.
+    
+    Args:
+        message: A string, PromptMessage, list of messages, or Azure message object
+    
+    Returns:
+        A list of Azure-compatible message objects
+    """
+    result = []

And update all references from messages to result in the function body.


67-92: ⚠️ Potential issue

Role comparison may fail with Enum values

The code compares role directly to the string "assistant", but if PromptMessage.role is an Enum, this comparison will fail and incorrectly treat assistant messages as user messages.

Consider normalizing the role to handle both string and Enum inputs:

-if role == "assistant":
+if str(role).lower() == "assistant":

Apply the same fix at line 78.

🧰 Tools
🪛 Pylint (3.3.7)

[refactor] 70-73: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[refactor] 78-92: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


127-129: ⚠️ Potential issue

Guard against None text when creating TextContentItem

get_text can return None, but TextContentItem(text=None) will raise a validation error in the Azure SDK.

Add a null check:

-text = get_text(content_item)
-if text:
-    azure_blocks.append(TextContentItem(text=text))
+text = get_text(content_item)
+if text:
+    azure_blocks.append(TextContentItem(text=text))
+else:
+    # Skip empty text content
+    pass

155-220: 🛠️ Refactor suggestion

Refactor complex _convert_embedded_resource method

This method has 11 return statements and complex nested conditionals, making it difficult to read and maintain.

Consider extracting dedicated helper methods for each MIME type category:

@staticmethod
def _convert_embedded_resource(resource: EmbeddedResource) -> Optional[ContentItem]:
    """Convert EmbeddedResource to appropriate Azure ContentItem."""
    resource_content = resource.resource
    mime_type = AzureConverter._determine_mime_type(resource_content)
    
    if mime_type == "image/svg+xml":
        return AzureConverter._handle_svg_resource(resource_content)
    
    if is_image_mime_type(mime_type):
        return AzureConverter._handle_image_resource(resource, mime_type)
    
    if mime_type == "application/pdf":
        return AzureConverter._handle_pdf_resource(resource)
    
    if is_text_mime_type(mime_type):
        return AzureConverter._handle_text_resource(resource)
    
    return AzureConverter._handle_fallback_resource(resource, mime_type)

# Then implement each handler method separately
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 215-215: Line too long (131/100)

(C0301)


[refactor] 175-204: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 155-155: Too many return statements (11/6)

(R0911)


215-215: ⚠️ Potential issue

Use public API instead of protected member access

Accessing uri._url uses a protected member. Use str(uri) for a more stable public API.

Apply this fix:

-text=f"Embedded Resource {getattr(uri, '_url', '')} with unsupported format {mime_type} ({blob_length} characters)"
+text=f"Embedded Resource {str(uri) if uri else ''} with unsupported format {mime_type} ({blob_length} characters)"
-return TextContentItem(text=f"[{message}: {getattr(uri, '_url', '')}]")
+return TextContentItem(text=f"[{message}: {str(uri)}]")

Also applies to: 247-247

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 215-215: Line too long (131/100)

(C0301)

🧹 Nitpick comments (9)
src/mcp_agent/workflows/llm/multipart_converter_openai.py (5)

1-2: Add module docstring
A top-level docstring describing the purpose of this module would improve readability and satisfy Pylint’s missing-module-docstring check.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 1-1: Missing module docstring

(C0114)


78-80: Avoid Yoda condition for clarity
Replace if 1 == len(multipart_msg.content) with the more conventional if len(multipart_msg.content) == 1.

🧰 Tools
🪛 Ruff (0.11.9)

78-78: Yoda condition detected

Rewrite as len(multipart_msg.content) == 1

(SIM300)


106-108: Narrow exception handling
Catching bare Exception may hide programming errors. Consider catching only the expected exceptions (e.g. ValueError, custom conversion errors) so that unexpected issues bubble up.

🧰 Tools
🪛 Pylint (3.3.7)

[warning] 106-106: Catching too general exception Exception

(W0718)


195-200: Flatten nested if statements
Combine the nested hasattr checks into one condition to reduce indentation and improve readability. For example:

-        if hasattr(content, "annotations") and content.annotations:
-            if hasattr(content.annotations, "detail"):
-                detail = content.annotations.detail
-                if detail in ("auto", "low", "high"):
-                    image_url["detail"] = detail
+        if getattr(content, "annotations", None) and getattr(content.annotations, "detail", None) in {"auto", "low", "high"}:
+            image_url["detail"] = content.annotations.detail
🧰 Tools
🪛 Ruff (0.11.9)

195-196: Use a single if statement instead of nested if statements

(SIM102)


227-319: Refactor large _convert_embedded_resource method
This method spans nearly 100 lines, with many branches and return points. Consider splitting it into smaller handlers (e.g. _handle_image_resource, _handle_pdf_resource, _handle_text_resource) to reduce cognitive complexity and improve testability.

🧰 Tools
🪛 Ruff (0.11.9)

281-300: Combine if branches using logical or operator

Combine if branches

(SIM114)

🪛 Pylint (3.3.7)

[convention] 269-269: Line too long (122/100)

(C0301)


[refactor] 255-261: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[refactor] 265-278: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 304-312: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 227-227: Too many return statements (10/6)

(R0911)


[refactor] 227-227: Too many branches (13/12)

(R0912)

examples/mcp_primitives/mcp_basic_agent/main.py (2)

36-81: Add function documentation for better example clarity.

The example function logic is correct and the previous syntax error with model_dump() has been properly fixed. However, adding a docstring would improve the educational value of this example.

Add a docstring to document the example:

 async def example_usage():
+    """
+    Demonstrates basic MCP agent usage including:
+    - Connecting to an MCP server
+    - Listing available resources and prompts  
+    - Creating combined prompts with resources
+    - Using an LLM for response generation
+    """
     async with app.run() as agent_app:
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 36-36: Missing function or method docstring

(C0116)


1-1: Add module docstring for better example documentation.

Since this is an educational example, adding a module docstring would help users understand the purpose and scope of the demonstration.

Add a module docstring at the beginning:

+"""
+Example demonstrating basic MCP agent usage.
+
+This example shows how to:
+- Configure an MCP application with settings
+- Connect to an MCP server exposing resources and prompts
+- List and access available resources and prompts
+- Create combined prompts using both resources and prompts
+- Attach an LLM to generate responses based on the prompts
+"""
 import asyncio
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 1-1: Missing module docstring

(C0114)

tests/utils/test_multipart_converter_azure.py (1)

17-308: Consider using public APIs instead of testing private methods

The test class extensively tests private methods (prefixed with _) of the AzureConverter class. This creates tight coupling between tests and implementation details. Consider testing through the public API methods instead.

For example, instead of directly testing _is_supported_image_type, test the behavior through convert_to_azure with different image types:

-def test_is_supported_image_type_supported(self):
-    assert AzureConverter._is_supported_image_type("image/jpeg") is True
+def test_convert_to_azure_with_supported_image_types(self):
+    for mime_type in ["image/jpeg", "image/png", "image/gif", "image/webp"]:
+        content = [ImageContent(type="image", data="base64data", mimeType=mime_type)]
+        multipart = PromptMessageMultipart(role="user", content=content)
+        result = AzureConverter.convert_to_azure(multipart)
+        # Assert the image was properly converted, not fallback text
+        assert isinstance(result.content[0], ImageContentItem)
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 17-17: Missing class docstring

(C0115)


[convention] 18-18: Missing function or method docstring

(C0116)


[warning] 19-19: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 20-20: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 21-21: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 22-22: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 24-24: Missing function or method docstring

(C0116)


[warning] 25-25: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 26-26: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 27-27: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 29-29: Missing function or method docstring

(C0116)


[convention] 36-36: Missing function or method docstring

(C0116)


[convention] 45-45: Missing function or method docstring

(C0116)


[convention] 54-54: Missing function or method docstring

(C0116)


[convention] 63-63: Missing function or method docstring

(C0116)


[convention] 74-74: Missing function or method docstring

(C0116)


[convention] 84-84: Missing function or method docstring

(C0116)


[warning] 90-90: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 95-95: Missing function or method docstring

(C0116)


[warning] 101-101: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 106-106: Missing function or method docstring

(C0116)


[warning] 112-112: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 118-118: Missing function or method docstring

(C0116)


[warning] 124-124: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 129-129: Missing function or method docstring

(C0116)


[warning] 135-135: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 140-140: Missing function or method docstring

(C0116)


[warning] 146-146: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 151-151: Missing function or method docstring

(C0116)


[warning] 157-157: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 162-162: Missing function or method docstring

(C0116)


[warning] 166-166: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 169-169: Missing function or method docstring

(C0116)


[warning] 174-174: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 177-177: Missing function or method docstring

(C0116)


[warning] 183-183: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 186-186: Missing function or method docstring

(C0116)


[warning] 192-192: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 195-195: Missing function or method docstring

(C0116)


[warning] 199-199: Access to a protected member _convert_svg_resource of a client class

(W0212)


[convention] 205-205: Missing function or method docstring

(C0116)


[warning] 209-209: Access to a protected member _convert_svg_resource of a client class

(W0212)


[convention] 214-214: Missing function or method docstring

(C0116)


[warning] 217-217: Access to a protected member _create_fallback_text of a client class

(W0212)


[convention] 222-222: Missing function or method docstring

(C0116)


[warning] 229-229: Access to a protected member _create_fallback_text of a client class

(W0212)


[convention] 234-234: Missing function or method docstring

(C0116)


[convention] 246-246: Missing function or method docstring

(C0116)


[convention] 257-257: Missing function or method docstring

(C0116)


[convention] 277-277: Missing function or method docstring

(C0116)


[convention] 293-293: Missing function or method docstring

(C0116)


[refactor] 17-17: Too many public methods (28/20)

(R0904)

src/mcp_agent/workflows/llm/multipart_converter_google.py (1)

156-158: Address or remove the TODO comment

The TODO comment indicates unfinished work that should be addressed before merging.

The comment mentions checking if uri_str and is_url are needed. These variables are currently commented out and unused. Would you like me to help determine if these are necessary or can be removed entirely?

🧰 Tools
🪛 Pylint (3.3.7)

[warning] 156-156: TODO: jerron - check if these are needed

(W0511)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7a8ece7 and 5b47509.

📒 Files selected for processing (6)
  • examples/mcp_primitives/mcp_basic_agent/main.py (1 hunks)
  • src/mcp_agent/workflows/llm/multipart_converter_azure.py (1 hunks)
  • src/mcp_agent/workflows/llm/multipart_converter_google.py (1 hunks)
  • src/mcp_agent/workflows/llm/multipart_converter_openai.py (1 hunks)
  • tests/utils/test_multipart_converter_azure.py (1 hunks)
  • tests/utils/test_multipart_converter_google.py (1 hunks)
🧰 Additional context used
🪛 Pylint (3.3.7)
tests/utils/test_multipart_converter_azure.py

[convention] 1-1: Missing module docstring

(C0114)


[error] 2-10: Unable to import 'mcp.types'

(E0401)


[error] 11-11: Unable to import 'pydantic'

(E0401)


[error] 13-13: Unable to import 'mcp_agent.utils.prompt_message_multipart'

(E0401)


[error] 14-14: Unable to import 'mcp_agent.workflows.llm.multipart_converter_azure'

(E0401)


[convention] 17-17: Missing class docstring

(C0115)


[convention] 18-18: Missing function or method docstring

(C0116)


[warning] 19-19: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 20-20: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 21-21: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 22-22: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 24-24: Missing function or method docstring

(C0116)


[warning] 25-25: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 26-26: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 27-27: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 29-29: Missing function or method docstring

(C0116)


[convention] 36-36: Missing function or method docstring

(C0116)


[convention] 45-45: Missing function or method docstring

(C0116)


[convention] 54-54: Missing function or method docstring

(C0116)


[convention] 63-63: Missing function or method docstring

(C0116)


[convention] 74-74: Missing function or method docstring

(C0116)


[convention] 84-84: Missing function or method docstring

(C0116)


[warning] 90-90: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 95-95: Missing function or method docstring

(C0116)


[warning] 101-101: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 106-106: Missing function or method docstring

(C0116)


[warning] 112-112: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 118-118: Missing function or method docstring

(C0116)


[warning] 124-124: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 129-129: Missing function or method docstring

(C0116)


[warning] 135-135: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 140-140: Missing function or method docstring

(C0116)


[warning] 146-146: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 151-151: Missing function or method docstring

(C0116)


[warning] 157-157: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 162-162: Missing function or method docstring

(C0116)


[warning] 166-166: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 169-169: Missing function or method docstring

(C0116)


[warning] 174-174: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 177-177: Missing function or method docstring

(C0116)


[warning] 183-183: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 186-186: Missing function or method docstring

(C0116)


[warning] 192-192: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 195-195: Missing function or method docstring

(C0116)


[warning] 199-199: Access to a protected member _convert_svg_resource of a client class

(W0212)


[convention] 205-205: Missing function or method docstring

(C0116)


[warning] 209-209: Access to a protected member _convert_svg_resource of a client class

(W0212)


[convention] 214-214: Missing function or method docstring

(C0116)


[warning] 217-217: Access to a protected member _create_fallback_text of a client class

(W0212)


[convention] 222-222: Missing function or method docstring

(C0116)


[warning] 229-229: Access to a protected member _create_fallback_text of a client class

(W0212)


[convention] 234-234: Missing function or method docstring

(C0116)


[convention] 246-246: Missing function or method docstring

(C0116)


[convention] 257-257: Missing function or method docstring

(C0116)


[convention] 277-277: Missing function or method docstring

(C0116)


[convention] 293-293: Missing function or method docstring

(C0116)


[refactor] 17-17: Too many public methods (28/20)

(R0904)

tests/utils/test_multipart_converter_google.py

[convention] 1-1: Missing module docstring

(C0114)


[error] 2-10: Unable to import 'mcp.types'

(E0401)


[error] 11-11: Unable to import 'pydantic'

(E0401)


[error] 13-13: Unable to import 'mcp_agent.utils.prompt_message_multipart'

(E0401)


[error] 14-14: Unable to import 'mcp_agent.workflows.llm.multipart_converter_google'

(E0401)


[convention] 17-17: Missing class docstring

(C0115)


[convention] 18-18: Missing function or method docstring

(C0116)


[warning] 19-19: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 20-20: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 21-21: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 22-22: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 24-24: Missing function or method docstring

(C0116)


[warning] 25-25: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 26-26: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 27-27: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 29-29: Missing function or method docstring

(C0116)


[convention] 36-36: Missing function or method docstring

(C0116)


[convention] 51-51: Missing function or method docstring

(C0116)


[convention] 72-72: Missing function or method docstring

(C0116)


[warning] 86-86: Unused variable 'args'

(W0612)


[convention] 89-89: Missing function or method docstring

(C0116)


[warning] 103-103: Unused variable 'args'

(W0612)


[convention] 106-106: Missing function or method docstring

(C0116)


[convention] 122-122: Missing function or method docstring

(C0116)


[warning] 134-134: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 138-138: Missing function or method docstring

(C0116)


[warning] 150-150: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 153-153: Unused variable 'args'

(W0612)


[convention] 156-156: Missing function or method docstring

(C0116)


[warning] 170-170: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 177-177: Missing function or method docstring

(C0116)


[warning] 189-189: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 192-192: Unused variable 'args'

(W0612)


[convention] 195-195: Missing function or method docstring

(C0116)


[warning] 207-207: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 210-210: Unused variable 'args'

(W0612)


[convention] 214-214: Missing function or method docstring

(C0116)


[warning] 228-228: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 235-235: Missing function or method docstring

(C0116)


[warning] 247-247: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 250-250: Unused variable 'args'

(W0612)


[convention] 253-253: Missing function or method docstring

(C0116)


[warning] 265-265: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 268-268: Unused variable 'args'

(W0612)


[convention] 271-271: Missing function or method docstring

(C0116)


[warning] 285-285: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 288-288: Unused variable 'args'

(W0612)


[convention] 292-292: Missing function or method docstring

(C0116)


[warning] 296-296: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 299-299: Missing function or method docstring

(C0116)


[warning] 304-304: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 307-307: Missing function or method docstring

(C0116)


[warning] 313-313: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 316-316: Missing function or method docstring

(C0116)


[warning] 322-322: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 325-325: Missing function or method docstring

(C0116)


[warning] 335-335: Access to a protected member _convert_svg_resource of a client class

(W0212)


[warning] 337-337: Unused variable 'args'

(W0612)


[convention] 341-341: Missing function or method docstring

(C0116)


[warning] 351-351: Access to a protected member _convert_svg_resource of a client class

(W0212)


[warning] 353-353: Unused variable 'args'

(W0612)


[convention] 356-356: Missing function or method docstring

(C0116)


[warning] 365-365: Access to a protected member _create_fallback_text of a client class

(W0212)


[warning] 367-367: Unused variable 'args'

(W0612)


[convention] 370-370: Missing function or method docstring

(C0116)


[warning] 371-371: Redefining name 'AnyUrl' from outer scope (line 11)

(W0621)


[error] 371-371: Unable to import 'pydantic'

(E0401)


[warning] 371-371: Reimport 'AnyUrl' (imported line 11)

(W0404)


[convention] 371-371: Import outside toplevel (pydantic.AnyUrl)

(C0415)


[warning] 385-385: Access to a protected member _create_fallback_text of a client class

(W0212)


[warning] 387-387: Unused variable 'args'

(W0612)


[convention] 390-390: Missing function or method docstring

(C0116)


[convention] 418-418: Missing function or method docstring

(C0116)


[warning] 431-431: Unused variable 'args'

(W0612)


[convention] 436-436: Missing function or method docstring

(C0116)


[convention] 454-454: Missing function or method docstring

(C0116)


[convention] 478-478: Missing function or method docstring

(C0116)


[convention] 499-499: Missing function or method docstring

(C0116)


[refactor] 17-17: Too many public methods (31/20)

(R0904)

src/mcp_agent/workflows/llm/multipart_converter_azure.py

[convention] 137-137: Line too long (112/100)

(C0301)


[convention] 215-215: Line too long (131/100)

(C0301)


[convention] 1-1: Missing module docstring

(C0114)


[error] 3-14: Unable to import 'azure.ai.inference.models'

(E0401)


[error] 15-23: Unable to import 'mcp.types'

(E0401)


[refactor] 70-73: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[refactor] 78-92: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[refactor] 175-204: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 155-155: Too many return statements (11/6)

(R0911)

examples/mcp_primitives/mcp_basic_agent/main.py

[convention] 1-1: Missing module docstring

(C0114)


[error] 4-4: Unable to import 'mcp_agent.app'

(E0401)


[error] 5-11: Unable to import 'mcp_agent.config'

(E0401)


[error] 12-12: Unable to import 'mcp_agent.agents.agent'

(E0401)


[error] 13-13: Unable to import 'mcp_agent.workflows.llm.augmented_llm_openai'

(E0401)


[convention] 36-36: Missing function or method docstring

(C0116)

src/mcp_agent/workflows/llm/multipart_converter_google.py

[convention] 115-115: Line too long (112/100)

(C0301)


[convention] 211-211: Line too long (115/100)

(C0301)


[warning] 156-156: TODO: jerron - check if these are needed

(W0511)


[convention] 1-1: Missing module docstring

(C0114)


[error] 4-4: Unable to import 'google.genai'

(E0401)


[error] 4-4: No name 'genai' in module 'google'

(E0611)


[error] 6-14: Unable to import 'mcp.types'

(E0401)


[refactor] 163-198: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 173-181: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[refactor] 193-198: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[refactor] 142-142: Too many return statements (11/6)

(R0911)

src/mcp_agent/workflows/llm/multipart_converter_openai.py

[convention] 269-269: Line too long (122/100)

(C0301)


[convention] 370-370: Line too long (105/100)

(C0301)


[convention] 1-1: Missing module docstring

(C0114)


[error] 3-9: Unable to import 'mcp.types'

(E0401)


[error] 10-10: Unable to import 'openai.types.chat'

(E0401)


[warning] 106-106: Catching too general exception Exception

(W0718)


[refactor] 255-261: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[refactor] 265-278: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 304-312: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 227-227: Too many return statements (10/6)

(R0911)


[refactor] 227-227: Too many branches (13/12)

(R0912)

🪛 Ruff (0.11.9)
src/mcp_agent/workflows/llm/multipart_converter_openai.py

78-78: Yoda condition detected

Rewrite as len(multipart_msg.content) == 1

(SIM300)


195-196: Use a single if statement instead of nested if statements

(SIM102)


281-300: Combine if branches using logical or operator

Combine if branches

(SIM114)

🔇 Additional comments (4)
src/mcp_agent/workflows/llm/multipart_converter_openai.py (1)

60-61: Verify union type syntax compatibility
The return type annotation Dict[str, str | ContentBlock | List[ContentBlock]] uses PEP 604 | union syntax, which requires Python 3.10+. Ensure the runtime and typing tooling support this; otherwise switch to typing.Union.

examples/mcp_primitives/mcp_basic_agent/main.py (3)

1-13: Imports look well-organized and appropriate.

The imports correctly include all necessary modules for the MCP agent demonstration.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 1-1: Missing module docstring

(C0114)


[error] 4-4: Unable to import 'mcp_agent.app'

(E0401)


[error] 5-11: Unable to import 'mcp_agent.config'

(E0401)


[error] 12-12: Unable to import 'mcp_agent.agents.agent'

(E0401)


[error] 13-13: Unable to import 'mcp_agent.workflows.llm.augmented_llm_openai'

(E0401)


31-33: Good demonstration of configuration flexibility.

The comment and code effectively show both programmatic and file-based configuration approaches, which is helpful for users learning the framework.


83-89: Main execution is properly implemented.

The asyncio execution pattern and timing measurement are correctly implemented.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
tests/utils/test_multipart_converter_google.py (3)

86-87: Clean up unused variables in test assertions

Multiple test methods have unused args variables when unpacking call_args. This can be cleaned up for better code quality.

Replace the unused args variable with _ in these locations:

- args, kwargs = mock_types.Part.from_text.call_args
+ _, kwargs = mock_types.Part.from_text.call_args

Alternatively, you can access kwargs directly:

- args, kwargs = mock_types.Part.from_text.call_args
- assert "some_text" in kwargs["text"]
+ call_args = mock_types.Part.from_text.call_args
+ assert "some_text" in call_args.kwargs["text"]

Also applies to: 103-104, 153-154, 192-193, 210-211, 250-251, 268-269, 288-289, 337-338, 353-354, 367-368, 385-386, 429-430

🧰 Tools
🪛 Pylint (3.3.7)

[warning] 86-86: Unused variable 'args'

(W0612)


370-386: Inconsistent AnyUrl constructor usage

There's an inconsistency in how AnyUrl is instantiated compared to other parts of the test file.

For consistency with line 302, use the url parameter:

- resource_content = TextResourceContents(
-     uri=AnyUrl(uri), mimeType="text/plain", text="test"
- )
+ resource_content = TextResourceContents(
+     uri=AnyUrl(url=uri), mimeType="text/plain", text="test"
+ )
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 370-370: Missing function or method docstring

(C0116)


[warning] 383-383: Access to a protected member _create_fallback_text of a client class

(W0212)


[warning] 385-385: Unused variable 'args'

(W0612)


17-523: Consider breaking down the large test class

The TestGoogleConverter class has 31 test methods, which exceeds typical recommendations for test class size and makes it harder to navigate.

Consider organizing the tests into smaller, focused test classes:

class TestGoogleConverterImageHandling:
    # Image-related tests (lines 18-28, 51-88, etc.)

class TestGoogleConverterResourceHandling:
    # Resource conversion tests (lines 122-291)

class TestGoogleConverterToolResults:
    # Tool result conversion tests (lines 388-523)

class TestGoogleConverterUtilities:
    # MIME type and utility method tests (lines 292-387)

This would improve test organization and make it easier to run specific test subsets.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 17-17: Missing class docstring

(C0115)


[convention] 18-18: Missing function or method docstring

(C0116)


[warning] 19-19: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 20-20: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 21-21: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 22-22: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 24-24: Missing function or method docstring

(C0116)


[warning] 25-25: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 26-26: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 27-27: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 29-29: Missing function or method docstring

(C0116)


[convention] 36-36: Missing function or method docstring

(C0116)


[convention] 51-51: Missing function or method docstring

(C0116)


[convention] 72-72: Missing function or method docstring

(C0116)


[warning] 86-86: Unused variable 'args'

(W0612)


[convention] 89-89: Missing function or method docstring

(C0116)


[warning] 103-103: Unused variable 'args'

(W0612)


[convention] 106-106: Missing function or method docstring

(C0116)


[convention] 122-122: Missing function or method docstring

(C0116)


[warning] 134-134: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 138-138: Missing function or method docstring

(C0116)


[warning] 150-150: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 153-153: Unused variable 'args'

(W0612)


[convention] 156-156: Missing function or method docstring

(C0116)


[warning] 170-170: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 177-177: Missing function or method docstring

(C0116)


[warning] 189-189: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 192-192: Unused variable 'args'

(W0612)


[convention] 195-195: Missing function or method docstring

(C0116)


[warning] 207-207: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 210-210: Unused variable 'args'

(W0612)


[convention] 214-214: Missing function or method docstring

(C0116)


[warning] 228-228: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 235-235: Missing function or method docstring

(C0116)


[warning] 247-247: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 250-250: Unused variable 'args'

(W0612)


[convention] 253-253: Missing function or method docstring

(C0116)


[warning] 265-265: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 268-268: Unused variable 'args'

(W0612)


[convention] 271-271: Missing function or method docstring

(C0116)


[warning] 285-285: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 288-288: Unused variable 'args'

(W0612)


[convention] 292-292: Missing function or method docstring

(C0116)


[warning] 296-296: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 299-299: Missing function or method docstring

(C0116)


[warning] 304-304: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 307-307: Missing function or method docstring

(C0116)


[warning] 313-313: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 316-316: Missing function or method docstring

(C0116)


[warning] 322-322: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 325-325: Missing function or method docstring

(C0116)


[warning] 335-335: Access to a protected member _convert_svg_resource of a client class

(W0212)


[warning] 337-337: Unused variable 'args'

(W0612)


[convention] 341-341: Missing function or method docstring

(C0116)


[warning] 351-351: Access to a protected member _convert_svg_resource of a client class

(W0212)


[warning] 353-353: Unused variable 'args'

(W0612)


[convention] 356-356: Missing function or method docstring

(C0116)


[warning] 365-365: Access to a protected member _create_fallback_text of a client class

(W0212)


[warning] 367-367: Unused variable 'args'

(W0612)


[convention] 370-370: Missing function or method docstring

(C0116)


[warning] 383-383: Access to a protected member _create_fallback_text of a client class

(W0212)


[warning] 385-385: Unused variable 'args'

(W0612)


[convention] 388-388: Missing function or method docstring

(C0116)


[convention] 416-416: Missing function or method docstring

(C0116)


[warning] 429-429: Unused variable 'args'

(W0612)


[convention] 434-434: Missing function or method docstring

(C0116)


[convention] 452-452: Missing function or method docstring

(C0116)


[convention] 476-476: Missing function or method docstring

(C0116)


[convention] 497-497: Missing function or method docstring

(C0116)


[refactor] 17-17: Too many public methods (31/20)

(R0904)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5b47509 and 6242777.

📒 Files selected for processing (1)
  • tests/utils/test_multipart_converter_google.py (1 hunks)
🧰 Additional context used
🪛 Pylint (3.3.7)
tests/utils/test_multipart_converter_google.py

[convention] 1-1: Missing module docstring

(C0114)


[error] 2-10: Unable to import 'mcp.types'

(E0401)


[error] 11-11: Unable to import 'pydantic'

(E0401)


[error] 13-13: Unable to import 'mcp_agent.utils.prompt_message_multipart'

(E0401)


[error] 14-14: Unable to import 'mcp_agent.workflows.llm.multipart_converter_google'

(E0401)


[convention] 17-17: Missing class docstring

(C0115)


[convention] 18-18: Missing function or method docstring

(C0116)


[warning] 19-19: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 20-20: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 21-21: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 22-22: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 24-24: Missing function or method docstring

(C0116)


[warning] 25-25: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 26-26: Access to a protected member _is_supported_image_type of a client class

(W0212)


[warning] 27-27: Access to a protected member _is_supported_image_type of a client class

(W0212)


[convention] 29-29: Missing function or method docstring

(C0116)


[convention] 36-36: Missing function or method docstring

(C0116)


[convention] 51-51: Missing function or method docstring

(C0116)


[convention] 72-72: Missing function or method docstring

(C0116)


[warning] 86-86: Unused variable 'args'

(W0612)


[convention] 89-89: Missing function or method docstring

(C0116)


[warning] 103-103: Unused variable 'args'

(W0612)


[convention] 106-106: Missing function or method docstring

(C0116)


[convention] 122-122: Missing function or method docstring

(C0116)


[warning] 134-134: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 138-138: Missing function or method docstring

(C0116)


[warning] 150-150: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 153-153: Unused variable 'args'

(W0612)


[convention] 156-156: Missing function or method docstring

(C0116)


[warning] 170-170: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 177-177: Missing function or method docstring

(C0116)


[warning] 189-189: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 192-192: Unused variable 'args'

(W0612)


[convention] 195-195: Missing function or method docstring

(C0116)


[warning] 207-207: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 210-210: Unused variable 'args'

(W0612)


[convention] 214-214: Missing function or method docstring

(C0116)


[warning] 228-228: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[convention] 235-235: Missing function or method docstring

(C0116)


[warning] 247-247: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 250-250: Unused variable 'args'

(W0612)


[convention] 253-253: Missing function or method docstring

(C0116)


[warning] 265-265: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 268-268: Unused variable 'args'

(W0612)


[convention] 271-271: Missing function or method docstring

(C0116)


[warning] 285-285: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 288-288: Unused variable 'args'

(W0612)


[convention] 292-292: Missing function or method docstring

(C0116)


[warning] 296-296: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 299-299: Missing function or method docstring

(C0116)


[warning] 304-304: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 307-307: Missing function or method docstring

(C0116)


[warning] 313-313: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 316-316: Missing function or method docstring

(C0116)


[warning] 322-322: Access to a protected member _determine_mime_type of a client class

(W0212)


[convention] 325-325: Missing function or method docstring

(C0116)


[warning] 335-335: Access to a protected member _convert_svg_resource of a client class

(W0212)


[warning] 337-337: Unused variable 'args'

(W0612)


[convention] 341-341: Missing function or method docstring

(C0116)


[warning] 351-351: Access to a protected member _convert_svg_resource of a client class

(W0212)


[warning] 353-353: Unused variable 'args'

(W0612)


[convention] 356-356: Missing function or method docstring

(C0116)


[warning] 365-365: Access to a protected member _create_fallback_text of a client class

(W0212)


[warning] 367-367: Unused variable 'args'

(W0612)


[convention] 370-370: Missing function or method docstring

(C0116)


[warning] 383-383: Access to a protected member _create_fallback_text of a client class

(W0212)


[warning] 385-385: Unused variable 'args'

(W0612)


[convention] 388-388: Missing function or method docstring

(C0116)


[convention] 416-416: Missing function or method docstring

(C0116)


[warning] 429-429: Unused variable 'args'

(W0612)


[convention] 434-434: Missing function or method docstring

(C0116)


[convention] 452-452: Missing function or method docstring

(C0116)


[convention] 476-476: Missing function or method docstring

(C0116)


[convention] 497-497: Missing function or method docstring

(C0116)


[refactor] 17-17: Too many public methods (31/20)

(R0904)

🔇 Additional comments (5)
tests/utils/test_multipart_converter_google.py (5)

1-15: LGTM: Clean import structure

The imports are well-organized and comprehensive, covering all necessary MCP types and internal modules for testing the GoogleConverter functionality.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 1-1: Missing module docstring

(C0114)


[error] 2-10: Unable to import 'mcp.types'

(E0401)


[error] 11-11: Unable to import 'pydantic'

(E0401)


[error] 13-13: Unable to import 'mcp_agent.utils.prompt_message_multipart'

(E0401)


[error] 14-14: Unable to import 'mcp_agent.workflows.llm.multipart_converter_google'

(E0401)


51-71: Verify base64 decoding logic

The test correctly validates that base64-encoded image data is properly decoded before being passed to the Google API.

The base64 string "YmFzZTY0ZGF0YQ==" correctly decodes to "base64data" as expected in the assertion on line 68.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 51-51: Missing function or method docstring

(C0116)


235-252: Clarify intentional use of invalid MIME type

The test uses mimeType="image/jif" which appears to be an intentionally invalid format to test the unsupported image handling path.

This correctly tests the fallback behavior for unsupported image formats, though the MIME type "image/jif" is not standard (perhaps intentionally to ensure it's treated as unsupported).

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 235-235: Missing function or method docstring

(C0116)


[warning] 247-247: Access to a protected member _convert_embedded_resource of a client class

(W0212)


[warning] 250-250: Unused variable 'args'

(W0612)


388-415: Well-designed tool result conversion test

The test effectively validates the conversion of tool results to Google's format, including the correct handling of content serialization through to_json_dict().

The test properly mocks the conversion pipeline and verifies that the response structure matches Google's expected format.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 388-388: Missing function or method docstring

(C0116)


497-523: Comprehensive multipart content testing

The test thoroughly validates handling of mixed content types (text and images) in tool results, ensuring both content types are processed correctly.

The test verifies that both text content and base64-decoded image data are properly converted and included in the tool result response.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 497-497: Missing function or method docstring

(C0116)

@StreetLamb StreetLamb requested a review from saqadri June 2, 2025 14:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant