Skip to content

Add configurable NFT page size and slice responses #126

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

Merged

Conversation

akolotov
Copy link
Collaborator

@akolotov akolotov commented Jul 4, 2025

Summary

  • add nft_page_size to configuration and environment files
  • slice results of nft_tokens_by_address using the new config
  • update pagination logic and unit tests
  • document new pagination pattern

Closes #124


https://chatgpt.com/codex/tasks/task_b_6868533fa4688323b3b5260a94066d97

Summary by CodeRabbit

  • New Features

    • Introduced a unified, context-aware pagination strategy using opaque cursors and configurable page sizes for NFT tokens, logs, transactions, and advanced filters.
    • Added environment variables and configuration options to control page sizes per tool.
    • Implemented multi-page fetching for filtered transaction queries to ensure sufficient data is returned despite filtering.
  • Bug Fixes

    • Improved pagination accuracy by slicing returned data and generating cursors from the last returned item to avoid skipping or duplicating items.
  • Documentation

    • Enhanced pagination documentation with detailed guidance on context conservation, cursor usage, and multi-page fetching strategies.
  • Tests

    • Expanded test coverage for pagination logic, including default and custom page sizes, multi-page fetching, and cursor encoding consistency.
    • Updated integration tests to enforce page size limits and verify pagination metadata presence.

Copy link

coderabbitai bot commented Jul 4, 2025

Walkthrough

The codebase introduces a configurable page size for the nft_tokens_by_address tool, limiting the number of items returned per page and generating pagination cursors based on the last item in the returned slice. Configuration, documentation, and tests are updated to support and verify the new pagination mechanism.

Changes

File(s) Change Summary
blockscout_mcp_server/config.py, .env.example, Dockerfile Added nft_page_size config variable with default 10; updated env var docs and Dockerfile ENV accordingly.
blockscout_mcp_server/tools/address_tools.py Refactored nft_tokens_by_address to slice API results to nft_page_size and generate cursor from last slice item.
tests/tools/test_address_tools_2.py Enhanced and added tests for pagination slicing, cursor generation, and custom page size handling.
tests/integration/test_address_tools_integration.py Updated integration test to assert response size is ≤ 10.
SPEC.md, .cursor/rules/110-new-mcp-tool.mdc Revised documentation to clarify new pagination slicing and cursor derivation behavior.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant MCP_Server
    participant Blockscout_API

    Client->>MCP_Server: Request NFT tokens (with/without cursor)
    MCP_Server->>Blockscout_API: Fetch full page (e.g., 50 items)
    Blockscout_API-->>MCP_Server: Return items (up to 50)
    MCP_Server->>MCP_Server: Slice items to page size (e.g., 10)
    MCP_Server->>MCP_Server: Generate cursor from last item in slice
    MCP_Server-->>Client: Return sliced items + pagination cursor
Loading

Assessment against linked issues

Objective Addressed Explanation
Add nft_page_size config variable to config.py with default 10 (#124)
Update Dockerfile and .env.example with BLOCKSCOUT_NFT_PAGE_SIZE env variable (#124)
Refactor nft_tokens_by_address to slice response and generate cursor from last item in slice (#124)
Update/expand unit and integration tests for slicing, cursor, and custom page size (#124)
Update documentation in SPEC.md and .cursor/rules/110-new-mcp-tool.mdc for new pagination pattern (#124)

Poem

In the garden of code, a page size was set,
Ten tokens per nibble, no more to beget.
The cursor now follows the last in the row,
So clients stay happy, and paginated flows grow.
🐇✨
"Hop, hop! Sliced neat, pagination's a treat!"

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • 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 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 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 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 for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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 (2)
SPEC.md (2)

235-235: Markdown-lint warning: missing fenced-code language

markdownlint flags this fence (MD040). Although the block starts earlier with json, the closing fence is indented and the linter treats it as a new fence without a language. Out-dent the closing or add a dummy language to silence the warning.

Example:

-      ```
+```

237-244: New slicing section is clear but missing env-var cross-reference

Good explanation of the slicing logic. Consider explicitly linking the config key (nft_page_size) to its environment variable (BLOCKSCOUT_NFT_PAGE_SIZE) in this paragraph for quicker discoverability.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 8bc668d and 638ecd9.

📒 Files selected for processing (2)
  • .cursor/rules/110-new-mcp-tool.mdc (1 hunks)
  • SPEC.md (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • .cursor/rules/110-new-mcp-tool.mdc
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.652Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Truncate large data fields in API responses and flag the truncation, providing guidance on how to retrieve the full data.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.652Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, do not expose individual pagination parameters; use a single, opaque cursor string and handle it with apply_cursor_to_params.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.652Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, include the exact notice '**SUPPORTS PAGINATION**: If response includes 'pagination' field, use the provided next_call to get additional pages.' in the docstring.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.449Z
Learning: Applies to tests/integration/test_*_integration.py : Integration tests for cursor-based pagination must perform a two-step test: (1) call the tool without a cursor and extract the cursor from the response, (2) call the tool again with the cursor and assert that the second page's data is different from the first.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.449Z
Learning: Applies to tests/integration/test_*_integration.py : Integration tests for paginated tools must use a loop with a max_pages_to_check limit to search across pages, and skip the test with a clear message if the target data is not found within the limit.
SPEC.md (13)
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.652Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, do not expose individual pagination parameters; use a single, opaque cursor string and handle it with apply_cursor_to_params.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.652Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, include the exact notice '**SUPPORTS PAGINATION**: If response includes 'pagination' field, use the provided next_call to get additional pages.' in the docstring.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.652Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Truncate large data fields in API responses and flag the truncation, providing guidance on how to retrieve the full data.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/900-rules-maintenance.mdc:0-0
Timestamp: 2025-07-04T20:35:06.699Z
Learning: Applies to .cursor/AGENTS.md : Update the corresponding guidance in the 'Rule Application Guidelines' section of `.cursor/AGENTS.md` to reflect the changes made to the rule file.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/130-version-management.mdc:0-0
Timestamp: 2025-07-04T20:25:11.247Z
Learning: Applies to blockscout_mcp_server/__init__.py : When updating the version of the MCP server, update the `__version__` variable in `blockscout_mcp_server/__init__.py`.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.652Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Simplify address objects in API responses to a single address string to save LLM context.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.652Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Recursively truncate nested data structures in API responses, replacing long strings with a structured object to signal truncation.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/000-role-and-task.mdc:0-0
Timestamp: 2025-07-04T20:18:25.785Z
Learning: Applies to **/*.py : The MCP server must wrap Blockscout APIs and expose blockchain data (balances, tokens, NFTs, contract metadata) via the Model Context Protocol (MCP)
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/130-version-management.mdc:0-0
Timestamp: 2025-07-04T20:25:11.247Z
Learning: Update both `pyproject.toml` and `blockscout_mcp_server/__init__.py` simultaneously to maintain consistency across the codebase.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-04T20:16:41.158Z
Learning: Read the project technical description in `SPEC.md` to clearly understand how the MCP server communicates with counterparties and important aspects of the server implementation before responding to a user request
Learnt from: CR
PR: blockscout/mcp-server#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-04T20:16:41.158Z
Learning: Read `.cursor/rules/010-implementation-rules.mdc` for general coding instructions before responding to a user request
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.449Z
Learning: Applies to tests/integration/test_*_integration.py : Integration tests for cursor-based pagination must perform a two-step test: (1) call the tool without a cursor and extract the cursor from the response, (2) call the tool again with the cursor and assert that the second page's data is different from the first.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.652Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For tools that query Blockscout API, use dynamic chain resolution via get_blockscout_base_url and make_blockscout_request.
🪛 markdownlint-cli2 (0.17.2)
SPEC.md

235-235: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Docker build and docker push
🔇 Additional comments (2)
SPEC.md (2)

205-206: Mechanism paragraph – looks good

Clear, technically accurate text that matches the implementation (apply_cursor_to_params). No action needed.


179-180: Invalid JSON example – extra brace breaks tooling copy-paste

The sample JSON now has one closing brace too many. Anyone copying it into a linter / example request will get a parse error.

-      }
-      ```
+    }
+    ```

Removing the superfluous brace keeps the example syntactically valid.

Likely an incorrect or invalid review comment.

@akolotov akolotov requested a review from Copilot July 4, 2025 23:01
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR introduces a configurable page size for the nft_tokens_by_address tool, slices API responses accordingly, and updates all related tests, docs, and environment settings.

  • Adds nft_page_size to configuration, .env, and Dockerfile
  • Implements response slicing and custom cursor generation in address_tools.py
  • Updates unit/integration tests and SPEC.md to reflect the new pagination pattern

Reviewed Changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/tools/test_address_tools_2.py Adjusted unit tests to cover default slicing and custom page sizes
tests/integration/test_address_tools_integration.py Tightened integration test to assert slice length ≤ page size
blockscout_mcp_server/tools/address_tools.py Added slicing logic based on config.nft_page_size and new cursor logic
blockscout_mcp_server/config.py Introduced nft_page_size setting
SPEC.md Documented the response slicing and context-aware pagination pattern
Dockerfile Exposed BLOCKSCOUT_NFT_PAGE_SIZE environment variable
.env.example Added example entry for BLOCKSCOUT_NFT_PAGE_SIZE
.cursor/rules/110-new-mcp-tool.mdc Updated example code snippet to illustrate per-tool pagination
Comments suppressed due to low confidence (2)

tests/tools/test_address_tools_2.py:346

  • Add an assertion on len(result.data) (e.g., assert len(result.data) == config.nft_page_size) to verify that the slicing behavior returns the expected number of items.
        result = await nft_tokens_by_address(chain_id=chain_id, address=address, ctx=mock_ctx)

.cursor/rules/110-new-mcp-tool.mdc:400

  • The example snippet still uses a hard-coded PAGE_SIZE. Consider showing how to read a per-tool page size from your configuration (e.g., config.nft_page_size) to align with project conventions.
    PAGE_SIZE = 10 # This should be a configurable value per-tool

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

🔭 Outside diff range comments (2)
tests/tools/test_transaction_tools_3.py (2)

319-319: Fix inconsistent variable naming.

The variable should be renamed from hash to tx_hash to maintain consistency with the rest of the file and avoid shadowing the built-in hash() function.

Apply this diff to fix the inconsistency:

-    hash = "0xabc123"
+    tx_hash = "0xabc123"

327-327: Update the function call to use the renamed variable.

Since the variable should be renamed to tx_hash, update the function call accordingly.

Apply this diff:

-            await get_transaction_logs(chain_id=chain_id, transaction_hash=hash, cursor=invalid_cursor, ctx=mock_ctx)
+            await get_transaction_logs(chain_id=chain_id, transaction_hash=tx_hash, cursor=invalid_cursor, ctx=mock_ctx)
♻️ Duplicate comments (1)
blockscout_mcp_server/tools/address_tools.py (1)

205-220: NFT pagination correctly implements configurable page size.

The implementation properly slices items based on the configured nft_page_size and constructs pagination parameters from the last item in the sliced list.

Note: The hard-coded value 50 on line 218 has been previously flagged and will be addressed in a future update.

🧹 Nitpick comments (3)
.cursor/rules/110-new-mcp-tool.mdc (1)

356-397: Well-designed pagination pattern that balances API efficiency with LLM context constraints.

The new context conservation strategy and page size configuration approach is excellent. The separation between API fetch size and LLM response size addresses a real problem.

Consider adding guidance on choosing appropriate page sizes based on typical item complexity (e.g., "For simple items like addresses, 20-30 is reasonable; for complex items with nested data, 5-10 may be better").

blockscout_mcp_server/tools/transaction_tools.py (2)

122-208: Excellent implementation of smart pagination for sparse filtered data.

The function elegantly handles the challenge of accumulating enough filtered items across multiple API pages. The progress reporting integration and the logic for determining has_more_pages are well-thought-out.

Consider making max_pages_to_fetch configurable via config to allow tuning for different deployment scenarios:

+    max_pages_to_fetch: int = config.smart_pagination_max_pages,  # Default could be 10 in config
-    max_pages_to_fetch: int = 10,  # Prevent infinite loops

585-602: Consider simplifying the address extraction logic for better readability.

While the current logic is correct, it could be more readable.

-        address_value = (
-            item.get("address", {}).get("hash") if isinstance(item.get("address"), dict) else item.get("address")
-        )
+        address_obj = item.get("address")
+        address_value = address_obj.get("hash") if isinstance(address_obj, dict) else address_obj
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 638ecd9 and 157ef08.

📒 Files selected for processing (19)
  • .cursor/rules/110-new-mcp-tool.mdc (3 hunks)
  • .cursor/rules/210-unit-testing-guidelines.mdc (3 hunks)
  • .env.example (1 hunks)
  • AGENTS.md (3 hunks)
  • Dockerfile (1 hunks)
  • SPEC.md (4 hunks)
  • blockscout_mcp_server/config.py (1 hunks)
  • blockscout_mcp_server/tools/address_tools.py (7 hunks)
  • blockscout_mcp_server/tools/common.py (2 hunks)
  • blockscout_mcp_server/tools/transaction_tools.py (9 hunks)
  • tests/integration/test_address_tools_integration.py (2 hunks)
  • tests/integration/test_transaction_tools_integration.py (4 hunks)
  • tests/tools/test_address_logs.py (3 hunks)
  • tests/tools/test_common.py (2 hunks)
  • tests/tools/test_transaction_tools.py (15 hunks)
  • tests/tools/test_transaction_tools_2.py (4 hunks)
  • tests/tools/test_transaction_tools_3.py (19 hunks)
  • tests/tools/test_transaction_tools_helpers.py (1 hunks)
  • tests/tools/test_transaction_tools_pagination.py (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • tests/tools/test_transaction_tools_2.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • Dockerfile
  • blockscout_mcp_server/config.py
  • tests/integration/test_address_tools_integration.py
🧰 Additional context used
📓 Path-based instructions (13)
`.env.example`: Add new API environment variables to .env.example when introducing a new endpoint.

.env.example: Add new API environment variables to .env.example when introducing a new endpoint.

📄 Source: CodeRabbit Inference Engine (.cursor/rules/110-new-mcp-tool.mdc)

List of files the instruction was applied to:

  • .env.example
`.cursor/rules/*.mdc`: When you create, modify, or delete any `.mdc` file in `.cursor/rules/`, you MUST update `.cursor/AGENTS.md` accordingly.

.cursor/rules/*.mdc: When you create, modify, or delete any .mdc file in .cursor/rules/, you MUST update .cursor/AGENTS.md accordingly.

📄 Source: CodeRabbit Inference Engine (.cursor/rules/900-rules-maintenance.mdc)

List of files the instruction was applied to:

  • .cursor/rules/210-unit-testing-guidelines.mdc
  • .cursor/rules/110-new-mcp-tool.mdc
`**/*.py`: The MCP server must be implemented in Python The MCP server must wrap...

**/*.py: The MCP server must be implemented in Python
The MCP server must wrap Blockscout APIs and expose blockchain data (balances, tokens, NFTs, contract metadata) via the Model Context Protocol (MCP)
The MCP server must communicate with AI agents or chat applications through stdin

📄 Source: CodeRabbit Inference Engine (.cursor/rules/000-role-and-task.mdc)

List of files the instruction was applied to:

  • tests/tools/test_transaction_tools_helpers.py
  • tests/tools/test_common.py
  • tests/integration/test_transaction_tools_integration.py
  • tests/tools/test_address_logs.py
  • blockscout_mcp_server/tools/address_tools.py
  • tests/tools/test_transaction_tools_3.py
  • tests/tools/test_transaction_tools_pagination.py
  • blockscout_mcp_server/tools/common.py
  • blockscout_mcp_server/tools/transaction_tools.py
  • tests/tools/test_transaction_tools.py
`**/*.py`: Regular Python modules should generally not exceed 500 lines of code ...

**/*.py: Regular Python modules should generally not exceed 500 lines of code (LOC). If a module approaches this limit, consider splitting it into multiple focused modules (e.g., address_tools.py and address_tools_advanced.py) to maintain readability and logical organization.
ALL import statements must be placed at the top of the Python module, immediately after the module docstring (if present) and before any other code. Never insert imports inline near where the functionality is used. Follow PEP 8 import order.
ALL linting and formatting issues must be resolved before committing or pushing code. Use the Ruff rules defined in .cursor/rules/300-ruff-lint-and-format.mdc to identify and fix issues.

📄 Source: CodeRabbit Inference Engine (.cursor/rules/010-implementation-rules.mdc)

List of files the instruction was applied to:

  • tests/tools/test_transaction_tools_helpers.py
  • tests/tools/test_common.py
  • tests/integration/test_transaction_tools_integration.py
  • tests/tools/test_address_logs.py
  • blockscout_mcp_server/tools/address_tools.py
  • tests/tools/test_transaction_tools_3.py
  • tests/tools/test_transaction_tools_pagination.py
  • blockscout_mcp_server/tools/common.py
  • blockscout_mcp_server/tools/transaction_tools.py
  • tests/tools/test_transaction_tools.py
`tests/tools/test_*.py`: Create or update the appropriate unit test file when adding or modifying tool functions: tests/tools/test_{tool_module}.py

tests/tools/test_*.py: Create or update the appropriate unit test file when adding or modifying tool functions: tests/tools/test_{tool_module}.py

📄 Source: CodeRabbit Inference Engine (.cursor/rules/200-development-testing-workflow.mdc)

List of files the instruction was applied to:

  • tests/tools/test_transaction_tools_helpers.py
  • tests/tools/test_common.py
  • tests/tools/test_address_logs.py
  • tests/tools/test_transaction_tools_3.py
  • tests/tools/test_transaction_tools_pagination.py
  • tests/tools/test_transaction_tools.py
`tests/tools/*.py`: Use the `mock_ctx` pytest fixture from `tests/conftest.py` f...

tests/tools/*.py: Use the mock_ctx pytest fixture from tests/conftest.py for mocking the MCP Context object in tests; do not create a manual MagicMock for the context within your test functions.
For tools returning a ToolResponse object, do not parse JSON from string results in your test; instead, mock the serialization function (json.dumps) if used internally, and make assertions on the structured ToolResponse object and its attributes.
When testing tools that transform a list of items, programmatically generate the expected_result from the mock_api_response instead of writing out large, repetitive expected results.
Always verify the number of calls to mock_ctx.report_progress in your assertions to ensure progress tracking is tested.
Assert that mocked API helper functions (such as make_blockscout_request) are called exactly once with the correct api_path and params in your tests.
For tools using make_request_with_periodic_progress, mock the wrapper itself and assert that it was called with the correct arguments (request_function, request_args, etc.).
Unit test files must not exceed 500 lines of code (LOC); if a file approaches this limit, split tests into multiple files (e.g., test_some_tools_1.py, test_some_tools_2.py) to maintain readability and focus.
Ensure all external API calls are properly mocked using unittest.mock.patch and AsyncMock.
Group related tests using descriptive class names or clear function naming patterns.

📄 Source: CodeRabbit Inference Engine (.cursor/rules/210-unit-testing-guidelines.mdc)

List of files the instruction was applied to:

  • tests/tools/test_transaction_tools_helpers.py
  • tests/tools/test_common.py
  • tests/tools/test_address_logs.py
  • tests/tools/test_transaction_tools_3.py
  • tests/tools/test_transaction_tools_pagination.py
  • tests/tools/test_transaction_tools.py
`**/*.py`: Always run `ruff check . --fix` and `ruff format .` on generated code...

**/*.py: Always run ruff check . --fix and ruff format . on generated code before suggesting commits or opening a PR
Avoid using # noqa: E501 for ordinary code lines; split long lines instead. Only use # noqa: E501 for docstrings or string literals that must exceed 120 characters.
Ruff enforces a 120-character line length limit by default (Black-compatible style)

📄 Source: CodeRabbit Inference Engine (.cursor/rules/300-ruff-lint-and-format.mdc)

List of files the instruction was applied to:

  • tests/tools/test_transaction_tools_helpers.py
  • tests/tools/test_common.py
  • tests/integration/test_transaction_tools_integration.py
  • tests/tools/test_address_logs.py
  • blockscout_mcp_server/tools/address_tools.py
  • tests/tools/test_transaction_tools_3.py
  • tests/tools/test_transaction_tools_pagination.py
  • blockscout_mcp_server/tools/common.py
  • blockscout_mcp_server/tools/transaction_tools.py
  • tests/tools/test_transaction_tools.py
`tests/integration/test_*_integration.py`: Add integration tests in tests/integr...

tests/integration/test_*_integration.py: Add integration tests in tests/integration/test_{tool_module}_integration.py when adding or modifying tool functions that interact with live APIs

📄 Source: CodeRabbit Inference Engine (.cursor/rules/200-development-testing-workflow.mdc)

List of files the instruction was applied to:

  • tests/integration/test_transaction_tools_integration.py
`tests/integration/test_*_integration.py`: Tool-level integration tests targetin...

tests/integration/test_*_integration.py: Tool-level integration tests targeting high-level MCP tool functions (e.g., get_latest_block, get_tokens_by_address) must be located in files matching tests/integration/test_*_integration.py and should validate data extraction and schema against live API responses.
Integration tests for paginated tools must use a loop with a max_pages_to_check limit to search across pages, and skip the test with a clear message if the target data is not found within the limit.
Integration tests for cursor-based pagination must perform a two-step test: (1) call the tool without a cursor and extract the cursor from the response, (2) call the tool again with the cursor and assert that the second page's data is different from the first.

📄 Source: CodeRabbit Inference Engine (.cursor/rules/220-integration-testing-guidelines.mdc)

List of files the instruction was applied to:

  • tests/integration/test_transaction_tools_integration.py
`tests/integration/*`: Integration tests must use stable, non-volatile data poin...

tests/integration/*: Integration tests must use stable, non-volatile data points such as historical blocks, famous addresses, or established ENS names to ensure reliability across runs.
Every integration test function must be decorated with @pytest.mark.integration.
Integration tests should be resilient to temporary network issues by implementing retry logic and skipping the test with a clear message if connectivity cannot be established after several attempts.
Do not hardcode environment-specific URLs in integration test assertions; instead, dynamically resolve URLs using the same helper functions as the code under test.
Integration test files must not exceed 500 lines of code (LOC); if a file approaches this limit, split tests into multiple focused files to maintain readability and logical organization.
Group related integration tests using descriptive class names or clear function naming patterns, use descriptive test names indicating the contract/schema being validated, separate helper-level and tool-level tests into different files when appropriate, and include clear comments explaining the choice of test data.

📄 Source: CodeRabbit Inference Engine (.cursor/rules/220-integration-testing-guidelines.mdc)

List of files the instruction was applied to:

  • tests/integration/test_transaction_tools_integration.py
`blockscout_mcp_server/tools/*.py`: Create or modify a tool module file in block...

blockscout_mcp_server/tools/*.py: Create or modify a tool module file in blockscout_mcp_server/tools/ for each new tool, choosing an existing module or creating a new one as appropriate.
All tools MUST return a strongly-typed ToolResponse[YourDataModel] instead of generic ToolResponse[dict].
For tools that query Blockscout API, use dynamic chain resolution via get_blockscout_base_url and make_blockscout_request.
For tools that use fixed API endpoints (like BENS), use the appropriate request helper (e.g., make_bens_request).
All tools MUST return a standardized ToolResponse[YourDataModel] object using the build_tool_response helper.
Avoid returning ToolResponse[dict] or ToolResponse[Any]; always prefer specific ToolResponse[YourDataModel].
For paginated tools, do not expose individual pagination parameters; use a single, opaque cursor string and handle it with apply_cursor_to_params.
For paginated tools, include the exact notice 'SUPPORTS PAGINATION: If response includes 'pagination' field, use the provided next_call to get additional pages.' in the docstring.
Simplify address objects in API responses to a single address string to save LLM context.
Truncate large data fields in API responses and flag the truncation, providing guidance on how to retrieve the full data.
Recursively truncate nested data structures in API responses, replacing long strings with a structured object to signal truncation.
Always raise exceptions for error conditions; never return error messages in ToolResponse notes.
Use the report_and_log_progress helper from tools/common.py for all progress reporting instead of calling ctx.report_progress directly.
When making multiple independent API calls, use asyncio.gather with return_exceptions=True and handle exceptions appropriately.

📄 Source: CodeRabbit Inference Engine (.cursor/rules/110-new-mcp-tool.mdc)

List of files the instruction was applied to:

  • blockscout_mcp_server/tools/address_tools.py
  • blockscout_mcp_server/tools/common.py
  • blockscout_mcp_server/tools/transaction_tools.py
`blockscout_mcp_server/tools/common.py`: Create a request helper function for new APIs in blockscout_mcp_server/tools/common.py.

blockscout_mcp_server/tools/common.py: Create a request helper function for new APIs in blockscout_mcp_server/tools/common.py.

📄 Source: CodeRabbit Inference Engine (.cursor/rules/110-new-mcp-tool.mdc)

List of files the instruction was applied to:

  • blockscout_mcp_server/tools/common.py
`AGENTS.md`: Update AGENTS.md documentation to reflect new or modified tool modules, including updates to the project structure and examples sections.

AGENTS.md: Update AGENTS.md documentation to reflect new or modified tool modules, including updates to the project structure and examples sections.

📄 Source: CodeRabbit Inference Engine (.cursor/rules/110-new-mcp-tool.mdc)

List of files the instruction was applied to:

  • AGENTS.md
🧠 Learnings (16)
📓 Common learnings
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Truncate large data fields in API responses and flag the truncation, providing guidance on how to retrieve the full data.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, do not expose individual pagination parameters; use a single, opaque cursor string and handle it with apply_cursor_to_params.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, include the exact notice '**SUPPORTS PAGINATION**: If response includes 'pagination' field, use the provided next_call to get additional pages.' in the docstring.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_*_integration.py : Integration tests for cursor-based pagination must perform a two-step test: (1) call the tool without a cursor and extract the cursor from the response, (2) call the tool again with the cursor and assert that the second page's data is different from the first.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_*_integration.py : Integration tests for paginated tools must use a loop with a max_pages_to_check limit to search across pages, and skip the test with a clear message if the target data is not found within the limit.
.env.example (6)
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to .env.example : Add new API environment variables to .env.example when introducing a new endpoint.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to Dockerfile : Add new API environment variables to the Dockerfile when introducing a new endpoint.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, include the exact notice '**SUPPORTS PAGINATION**: If response includes 'pagination' field, use the provided next_call to get additional pages.' in the docstring.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, do not expose individual pagination parameters; use a single, opaque cursor string and handle it with apply_cursor_to_params.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For tools that query Blockscout API, use dynamic chain resolution via get_blockscout_base_url and make_blockscout_request.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For tools that use fixed API endpoints (like BENS), use the appropriate request helper (e.g., make_bens_request).
.cursor/rules/210-unit-testing-guidelines.mdc (23)
Learnt from: CR
PR: blockscout/mcp-server#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-04T20:16:41.182Z
Learning: Read `.cursor/rules/200-development-testing-workflow.mdc` for instructions related to unit and integration testing applicable when a new helper function or MCP tool function is added or modified
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/* : Group related integration tests using descriptive class names or clear function naming patterns, use descriptive test names indicating the contract/schema being validated, separate helper-level and tool-level tests into different files when appropriate, and include clear comments explaining the choice of test data.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : Unit test files must not exceed 500 lines of code (LOC); if a file approaches this limit, split tests into multiple files (e.g., `test_some_tools_1.py`, `test_some_tools_2.py`) to maintain readability and focus.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : Group related tests using descriptive class names or clear function naming patterns.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/900-rules-maintenance.mdc:0-0
Timestamp: 2025-07-04T20:35:06.726Z
Learning: Applies to .cursor/AGENTS.md : Update the corresponding guidance in the 'Rule Application Guidelines' section of `.cursor/AGENTS.md` to reflect the changes made to the rule file.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/* : Integration test files must not exceed 500 lines of code (LOC); if a file approaches this limit, split tests into multiple focused files to maintain readability and logical organization.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/200-development-testing-workflow.mdc:0-0
Timestamp: 2025-07-04T20:28:28.716Z
Learning: Applies to tests/test_server.py : Create or update the unit test file tests/test_server.py when adding or modifying server functionality
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : Ensure all external API calls are properly mocked using `unittest.mock.patch` and `AsyncMock`.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/200-development-testing-workflow.mdc:0-0
Timestamp: 2025-07-04T20:28:28.716Z
Learning: Applies to tests/test_common.py : Create or update the unit test file tests/test_common.py when adding or modifying common utilities
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : Always verify the number of calls to `mock_ctx.report_progress` in your assertions to ensure progress tracking is tested.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : Use the `mock_ctx` pytest fixture from `tests/conftest.py` for mocking the MCP Context object in tests; do not create a manual MagicMock for the context within your test functions.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_*_integration.py : Tool-level integration tests targeting high-level MCP tool functions (e.g., get_latest_block, get_tokens_by_address) must be located in files matching tests/integration/test_*_integration.py and should validate data extraction and schema against live API responses.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Write tests covering success scenarios, error cases, and edge cases.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : For tools returning a `ToolResponse` object, do not parse JSON from string results in your test; instead, mock the serialization function (`json.dumps`) if used internally, and make assertions on the structured `ToolResponse` object and its attributes.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/200-development-testing-workflow.mdc:0-0
Timestamp: 2025-07-04T20:28:28.716Z
Learning: Run integration tests (pytest -m integration) when you have added or modified any existing MCP tool function, modified helper functions in tools/common.py, added or changed any integration test, or changed data extraction or transformation logic
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : For tools using `make_request_with_periodic_progress`, mock the wrapper itself and assert that it was called with the correct arguments (`request_function`, `request_args`, etc.).
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : Assert that mocked API helper functions (such as `make_blockscout_request`) are called exactly once with the correct `api_path` and `params` in your tests.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : When testing tools that transform a list of items, programmatically generate the `expected_result` from the `mock_api_response` instead of writing out large, repetitive expected results.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/200-development-testing-workflow.mdc:0-0
Timestamp: 2025-07-04T20:28:28.716Z
Learning: Always run the unit test suite before and after making changes using pytest
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Avoid returning ToolResponse[dict] or ToolResponse[Any]; always prefer specific ToolResponse[YourDataModel].
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : All tools MUST return a standardized ToolResponse[YourDataModel] object using the build_tool_response helper.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : All tools MUST return a strongly-typed ToolResponse[YourDataModel] instead of generic ToolResponse[dict].
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/200-development-testing-workflow.mdc:0-0
Timestamp: 2025-07-04T20:28:28.716Z
Learning: Applies to tests/integration/test_*_integration.py : Add integration tests in tests/integration/test_{tool_module}_integration.py when adding or modifying tool functions that interact with live APIs
tests/tools/test_transaction_tools_helpers.py (5)
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/200-development-testing-workflow.mdc:0-0
Timestamp: 2025-07-04T20:28:28.716Z
Learning: Applies to tests/integration/test_common_helpers.py : Add integration tests in tests/integration/test_common_helpers.py when modifying helper functions in tools/common.py
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/200-development-testing-workflow.mdc:0-0
Timestamp: 2025-07-04T20:28:28.716Z
Learning: Applies to tests/integration/test_*_integration.py : Add integration tests in tests/integration/test_{tool_module}_integration.py when adding or modifying tool functions that interact with live APIs
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_*_integration.py : Tool-level integration tests targeting high-level MCP tool functions (e.g., get_latest_block, get_tokens_by_address) must be located in files matching tests/integration/test_*_integration.py and should validate data extraction and schema against live API responses.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : When testing tools that transform a list of items, programmatically generate the `expected_result` from the `mock_api_response` instead of writing out large, repetitive expected results.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/200-development-testing-workflow.mdc:0-0
Timestamp: 2025-07-04T20:28:28.716Z
Learning: Applies to tests/tools/test_*.py : Create or update the appropriate unit test file when adding or modifying tool functions: tests/tools/test_{tool_module}.py
tests/tools/test_common.py (13)
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_*_integration.py : Integration tests for cursor-based pagination must perform a two-step test: (1) call the tool without a cursor and extract the cursor from the response, (2) call the tool again with the cursor and assert that the second page's data is different from the first.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/200-development-testing-workflow.mdc:0-0
Timestamp: 2025-07-04T20:28:28.716Z
Learning: Applies to tests/integration/test_common_helpers.py : Add integration tests in tests/integration/test_common_helpers.py when modifying helper functions in tools/common.py
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, do not expose individual pagination parameters; use a single, opaque cursor string and handle it with apply_cursor_to_params.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_*_integration.py : Integration tests for paginated tools must use a loop with a max_pages_to_check limit to search across pages, and skip the test with a clear message if the target data is not found within the limit.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/200-development-testing-workflow.mdc:0-0
Timestamp: 2025-07-04T20:28:28.716Z
Learning: Applies to tests/integration/test_*_integration.py : Add integration tests in tests/integration/test_{tool_module}_integration.py when adding or modifying tool functions that interact with live APIs
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : When testing tools that transform a list of items, programmatically generate the `expected_result` from the `mock_api_response` instead of writing out large, repetitive expected results.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-04T20:16:41.182Z
Learning: Read `.cursor/rules/200-development-testing-workflow.mdc` for instructions related to unit and integration testing applicable when a new helper function or MCP tool function is added or modified
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : Ensure all external API calls are properly mocked using `unittest.mock.patch` and `AsyncMock`.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, include the exact notice '**SUPPORTS PAGINATION**: If response includes 'pagination' field, use the provided next_call to get additional pages.' in the docstring.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/200-development-testing-workflow.mdc:0-0
Timestamp: 2025-07-04T20:28:28.716Z
Learning: Run integration tests (pytest -m integration) when you have added or modified any existing MCP tool function, modified helper functions in tools/common.py, added or changed any integration test, or changed data extraction or transformation logic
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Recursively truncate nested data structures in API responses, replacing long strings with a structured object to signal truncation.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Truncate large data fields in API responses and flag the truncation, providing guidance on how to retrieve the full data.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : Assert that mocked API helper functions (such as `make_blockscout_request`) are called exactly once with the correct `api_path` and `params` in your tests.
tests/integration/test_transaction_tools_integration.py (10)
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_*_integration.py : Integration tests for paginated tools must use a loop with a max_pages_to_check limit to search across pages, and skip the test with a clear message if the target data is not found within the limit.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/200-development-testing-workflow.mdc:0-0
Timestamp: 2025-07-04T20:28:28.716Z
Learning: Applies to tests/integration/test_*_integration.py : Add integration tests in tests/integration/test_{tool_module}_integration.py when adding or modifying tool functions that interact with live APIs
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_*_integration.py : Tool-level integration tests targeting high-level MCP tool functions (e.g., get_latest_block, get_tokens_by_address) must be located in files matching tests/integration/test_*_integration.py and should validate data extraction and schema against live API responses.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_*_integration.py : Integration tests for cursor-based pagination must perform a two-step test: (1) call the tool without a cursor and extract the cursor from the response, (2) call the tool again with the cursor and assert that the second page's data is different from the first.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/200-development-testing-workflow.mdc:0-0
Timestamp: 2025-07-04T20:28:28.716Z
Learning: Applies to tests/integration/test_common_helpers.py : Add integration tests in tests/integration/test_common_helpers.py when modifying helper functions in tools/common.py
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/200-development-testing-workflow.mdc:0-0
Timestamp: 2025-07-04T20:28:28.716Z
Learning: Run integration tests (pytest -m integration) when you have added or modified any existing MCP tool function, modified helper functions in tools/common.py, added or changed any integration test, or changed data extraction or transformation logic
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : When testing tools that transform a list of items, programmatically generate the `expected_result` from the `mock_api_response` instead of writing out large, repetitive expected results.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : Always verify the number of calls to `mock_ctx.report_progress` in your assertions to ensure progress tracking is tested.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/* : Group related integration tests using descriptive class names or clear function naming patterns, use descriptive test names indicating the contract/schema being validated, separate helper-level and tool-level tests into different files when appropriate, and include clear comments explaining the choice of test data.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : Ensure all external API calls are properly mocked using `unittest.mock.patch` and `AsyncMock`.
tests/tools/test_address_logs.py (22)
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : Ensure all external API calls are properly mocked using `unittest.mock.patch` and `AsyncMock`.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_*_integration.py : Integration tests for cursor-based pagination must perform a two-step test: (1) call the tool without a cursor and extract the cursor from the response, (2) call the tool again with the cursor and assert that the second page's data is different from the first.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : When testing tools that transform a list of items, programmatically generate the `expected_result` from the `mock_api_response` instead of writing out large, repetitive expected results.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/200-development-testing-workflow.mdc:0-0
Timestamp: 2025-07-04T20:28:28.716Z
Learning: Applies to tests/integration/test_*_integration.py : Add integration tests in tests/integration/test_{tool_module}_integration.py when adding or modifying tool functions that interact with live APIs
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : Always verify the number of calls to `mock_ctx.report_progress` in your assertions to ensure progress tracking is tested.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_*_integration.py : Integration tests for paginated tools must use a loop with a max_pages_to_check limit to search across pages, and skip the test with a clear message if the target data is not found within the limit.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/200-development-testing-workflow.mdc:0-0
Timestamp: 2025-07-04T20:28:28.716Z
Learning: Applies to tests/integration/test_common_helpers.py : Add integration tests in tests/integration/test_common_helpers.py when modifying helper functions in tools/common.py
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : Use the `mock_ctx` pytest fixture from `tests/conftest.py` for mocking the MCP Context object in tests; do not create a manual MagicMock for the context within your test functions.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, include the exact notice '**SUPPORTS PAGINATION**: If response includes 'pagination' field, use the provided next_call to get additional pages.' in the docstring.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : For tools using `make_request_with_periodic_progress`, mock the wrapper itself and assert that it was called with the correct arguments (`request_function`, `request_args`, etc.).
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For tools that query Blockscout API, use dynamic chain resolution via get_blockscout_base_url and make_blockscout_request.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For tools that use fixed API endpoints (like BENS), use the appropriate request helper (e.g., make_bens_request).
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Simplify address objects in API responses to a single address string to save LLM context.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_*_integration.py : Tool-level integration tests targeting high-level MCP tool functions (e.g., get_latest_block, get_tokens_by_address) must be located in files matching tests/integration/test_*_integration.py and should validate data extraction and schema against live API responses.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Avoid returning ToolResponse[dict] or ToolResponse[Any]; always prefer specific ToolResponse[YourDataModel].
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/config.py : Add new API endpoint configuration to blockscout_mcp_server/config.py when introducing a new external API endpoint.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, do not expose individual pagination parameters; use a single, opaque cursor string and handle it with apply_cursor_to_params.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_common_helpers.py : Helper-level integration tests targeting low-level helper functions in tools/common.py (e.g., make_blockscout_request, get_blockscout_base_url) must be located in tests/integration/test_common_helpers.py and verify basic network connectivity and response structure.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : All tools MUST return a standardized ToolResponse[YourDataModel] object using the build_tool_response helper.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : All tools MUST return a strongly-typed ToolResponse[YourDataModel] instead of generic ToolResponse[dict].
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : Assert that mocked API helper functions (such as `make_blockscout_request`) are called exactly once with the correct `api_path` and `params` in your tests.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : For tools returning a `ToolResponse` object, do not parse JSON from string results in your test; instead, mock the serialization function (`json.dumps`) if used internally, and make assertions on the structured `ToolResponse` object and its attributes.
blockscout_mcp_server/tools/address_tools.py (19)
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, do not expose individual pagination parameters; use a single, opaque cursor string and handle it with apply_cursor_to_params.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, include the exact notice '**SUPPORTS PAGINATION**: If response includes 'pagination' field, use the provided next_call to get additional pages.' in the docstring.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Simplify address objects in API responses to a single address string to save LLM context.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Truncate large data fields in API responses and flag the truncation, providing guidance on how to retrieve the full data.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_*_integration.py : Integration tests for cursor-based pagination must perform a two-step test: (1) call the tool without a cursor and extract the cursor from the response, (2) call the tool again with the cursor and assert that the second page's data is different from the first.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Recursively truncate nested data structures in API responses, replacing long strings with a structured object to signal truncation.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_*_integration.py : Integration tests for paginated tools must use a loop with a max_pages_to_check limit to search across pages, and skip the test with a clear message if the target data is not found within the limit.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/000-role-and-task.mdc:0-0
Timestamp: 2025-07-04T20:18:25.795Z
Learning: Applies to **/*.py : The MCP server must wrap Blockscout APIs and expose blockchain data (balances, tokens, NFTs, contract metadata) via the Model Context Protocol (MCP)
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/models.py : When defining BaseModel subclasses for external API responses, use ConfigDict(extra="allow").
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/config.py : Add new API endpoint configuration to blockscout_mcp_server/config.py when introducing a new external API endpoint.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/130-version-management.mdc:0-0
Timestamp: 2025-07-04T20:25:11.277Z
Learning: Update both `pyproject.toml` and `blockscout_mcp_server/__init__.py` simultaneously to maintain consistency across the codebase.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/models.py : Create a specific Pydantic data model for each new tool's data payload in blockscout_mcp_server/models.py, using Field(description=...) for every attribute.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/server.py : Register each new tool in blockscout_mcp_server/server.py by importing the tool function and registering it with the @mcp.tool() decorator.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : Use the `mock_ctx` pytest fixture from `tests/conftest.py` for mocking the MCP Context object in tests; do not create a manual MagicMock for the context within your test functions.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For tools that query Blockscout API, use dynamic chain resolution via get_blockscout_base_url and make_blockscout_request.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For tools that use fixed API endpoints (like BENS), use the appropriate request helper (e.g., make_bens_request).
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/common.py : Create a request helper function for new APIs in blockscout_mcp_server/tools/common.py.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : When making multiple independent API calls, use asyncio.gather with return_exceptions=True and handle exceptions appropriately.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Create or modify a tool module file in blockscout_mcp_server/tools/ for each new tool, choosing an existing module or creating a new one as appropriate.
tests/tools/test_transaction_tools_3.py (23)
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : Ensure all external API calls are properly mocked using `unittest.mock.patch` and `AsyncMock`.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_*_integration.py : Integration tests for cursor-based pagination must perform a two-step test: (1) call the tool without a cursor and extract the cursor from the response, (2) call the tool again with the cursor and assert that the second page's data is different from the first.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/200-development-testing-workflow.mdc:0-0
Timestamp: 2025-07-04T20:28:28.716Z
Learning: Applies to tests/integration/test_*_integration.py : Add integration tests in tests/integration/test_{tool_module}_integration.py when adding or modifying tool functions that interact with live APIs
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : When testing tools that transform a list of items, programmatically generate the `expected_result` from the `mock_api_response` instead of writing out large, repetitive expected results.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : Always verify the number of calls to `mock_ctx.report_progress` in your assertions to ensure progress tracking is tested.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/200-development-testing-workflow.mdc:0-0
Timestamp: 2025-07-04T20:28:28.716Z
Learning: Applies to tests/integration/test_common_helpers.py : Add integration tests in tests/integration/test_common_helpers.py when modifying helper functions in tools/common.py
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_*_integration.py : Tool-level integration tests targeting high-level MCP tool functions (e.g., get_latest_block, get_tokens_by_address) must be located in files matching tests/integration/test_*_integration.py and should validate data extraction and schema against live API responses.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : Group related tests using descriptive class names or clear function naming patterns.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_*_integration.py : Integration tests for paginated tools must use a loop with a max_pages_to_check limit to search across pages, and skip the test with a clear message if the target data is not found within the limit.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, include the exact notice '**SUPPORTS PAGINATION**: If response includes 'pagination' field, use the provided next_call to get additional pages.' in the docstring.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For tools that query Blockscout API, use dynamic chain resolution via get_blockscout_base_url and make_blockscout_request.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For tools that use fixed API endpoints (like BENS), use the appropriate request helper (e.g., make_bens_request).
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, do not expose individual pagination parameters; use a single, opaque cursor string and handle it with apply_cursor_to_params.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Avoid returning ToolResponse[dict] or ToolResponse[Any]; always prefer specific ToolResponse[YourDataModel].
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : All tools MUST return a strongly-typed ToolResponse[YourDataModel] instead of generic ToolResponse[dict].
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : All tools MUST return a standardized ToolResponse[YourDataModel] object using the build_tool_response helper.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/000-role-and-task.mdc:0-0
Timestamp: 2025-07-04T20:18:25.795Z
Learning: Applies to **/*.py : The MCP server must wrap Blockscout APIs and expose blockchain data (balances, tokens, NFTs, contract metadata) via the Model Context Protocol (MCP)
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : When making multiple independent API calls, use asyncio.gather with return_exceptions=True and handle exceptions appropriately.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Use the report_and_log_progress helper from tools/common.py for all progress reporting instead of calling ctx.report_progress directly.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : Assert that mocked API helper functions (such as `make_blockscout_request`) are called exactly once with the correct `api_path` and `params` in your tests.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : For tools using `make_request_with_periodic_progress`, mock the wrapper itself and assert that it was called with the correct arguments (`request_function`, `request_args`, etc.).
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : For tools returning a `ToolResponse` object, do not parse JSON from string results in your test; instead, mock the serialization function (`json.dumps`) if used internally, and make assertions on the structured `ToolResponse` object and its attributes.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Truncate large data fields in API responses and flag the truncation, providing guidance on how to retrieve the full data.
tests/tools/test_transaction_tools_pagination.py (12)
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_*_integration.py : Integration tests for cursor-based pagination must perform a two-step test: (1) call the tool without a cursor and extract the cursor from the response, (2) call the tool again with the cursor and assert that the second page's data is different from the first.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/200-development-testing-workflow.mdc:0-0
Timestamp: 2025-07-04T20:28:28.716Z
Learning: Applies to tests/integration/test_*_integration.py : Add integration tests in tests/integration/test_{tool_module}_integration.py when adding or modifying tool functions that interact with live APIs
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : Ensure all external API calls are properly mocked using `unittest.mock.patch` and `AsyncMock`.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_*_integration.py : Integration tests for paginated tools must use a loop with a max_pages_to_check limit to search across pages, and skip the test with a clear message if the target data is not found within the limit.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_*_integration.py : Tool-level integration tests targeting high-level MCP tool functions (e.g., get_latest_block, get_tokens_by_address) must be located in files matching tests/integration/test_*_integration.py and should validate data extraction and schema against live API responses.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, include the exact notice '**SUPPORTS PAGINATION**: If response includes 'pagination' field, use the provided next_call to get additional pages.' in the docstring.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/200-development-testing-workflow.mdc:0-0
Timestamp: 2025-07-04T20:28:28.716Z
Learning: Applies to tests/integration/test_common_helpers.py : Add integration tests in tests/integration/test_common_helpers.py when modifying helper functions in tools/common.py
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : Always verify the number of calls to `mock_ctx.report_progress` in your assertions to ensure progress tracking is tested.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : When testing tools that transform a list of items, programmatically generate the `expected_result` from the `mock_api_response` instead of writing out large, repetitive expected results.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, do not expose individual pagination parameters; use a single, opaque cursor string and handle it with apply_cursor_to_params.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : When making multiple independent API calls, use asyncio.gather with return_exceptions=True and handle exceptions appropriately.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : Assert that mocked API helper functions (such as `make_blockscout_request`) are called exactly once with the correct `api_path` and `params` in your tests.
blockscout_mcp_server/tools/common.py (15)
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, do not expose individual pagination parameters; use a single, opaque cursor string and handle it with apply_cursor_to_params.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, include the exact notice '**SUPPORTS PAGINATION**: If response includes 'pagination' field, use the provided next_call to get additional pages.' in the docstring.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Use the report_and_log_progress helper from tools/common.py for all progress reporting instead of calling ctx.report_progress directly.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/server.py : Register each new tool in blockscout_mcp_server/server.py by importing the tool function and registering it with the @mcp.tool() decorator.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_*_integration.py : Integration tests for cursor-based pagination must perform a two-step test: (1) call the tool without a cursor and extract the cursor from the response, (2) call the tool again with the cursor and assert that the second page's data is different from the first.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/common.py : Create a request helper function for new APIs in blockscout_mcp_server/tools/common.py.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Truncate large data fields in API responses and flag the truncation, providing guidance on how to retrieve the full data.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Create or modify a tool module file in blockscout_mcp_server/tools/ for each new tool, choosing an existing module or creating a new one as appropriate.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For tools that query Blockscout API, use dynamic chain resolution via get_blockscout_base_url and make_blockscout_request.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For tools that use fixed API endpoints (like BENS), use the appropriate request helper (e.g., make_bens_request).
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Always raise exceptions for error conditions; never return error messages in ToolResponse notes.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Avoid returning ToolResponse[dict] or ToolResponse[Any]; always prefer specific ToolResponse[YourDataModel].
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : All tools MUST return a strongly-typed ToolResponse[YourDataModel] instead of generic ToolResponse[dict].
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Recursively truncate nested data structures in API responses, replacing long strings with a structured object to signal truncation.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : All tools MUST return a standardized ToolResponse[YourDataModel] object using the build_tool_response helper.
blockscout_mcp_server/tools/transaction_tools.py (17)
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, do not expose individual pagination parameters; use a single, opaque cursor string and handle it with apply_cursor_to_params.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, include the exact notice '**SUPPORTS PAGINATION**: If response includes 'pagination' field, use the provided next_call to get additional pages.' in the docstring.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Use the report_and_log_progress helper from tools/common.py for all progress reporting instead of calling ctx.report_progress directly.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Truncate large data fields in API responses and flag the truncation, providing guidance on how to retrieve the full data.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : When making multiple independent API calls, use asyncio.gather with return_exceptions=True and handle exceptions appropriately.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For tools that query Blockscout API, use dynamic chain resolution via get_blockscout_base_url and make_blockscout_request.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For tools that use fixed API endpoints (like BENS), use the appropriate request helper (e.g., make_bens_request).
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/common.py : Create a request helper function for new APIs in blockscout_mcp_server/tools/common.py.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Simplify address objects in API responses to a single address string to save LLM context.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_*_integration.py : Integration tests for cursor-based pagination must perform a two-step test: (1) call the tool without a cursor and extract the cursor from the response, (2) call the tool again with the cursor and assert that the second page's data is different from the first.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Recursively truncate nested data structures in API responses, replacing long strings with a structured object to signal truncation.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Avoid returning ToolResponse[dict] or ToolResponse[Any]; always prefer specific ToolResponse[YourDataModel].
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : All tools MUST return a strongly-typed ToolResponse[YourDataModel] instead of generic ToolResponse[dict].
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : All tools MUST return a standardized ToolResponse[YourDataModel] object using the build_tool_response helper.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/000-role-and-task.mdc:0-0
Timestamp: 2025-07-04T20:18:25.795Z
Learning: Applies to **/*.py : The MCP server must wrap Blockscout APIs and expose blockchain data (balances, tokens, NFTs, contract metadata) via the Model Context Protocol (MCP)
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/server.py : Register each new tool in blockscout_mcp_server/server.py by importing the tool function and registering it with the @mcp.tool() decorator.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Always raise exceptions for error conditions; never return error messages in ToolResponse notes.
tests/tools/test_transaction_tools.py (23)
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : For tools using `make_request_with_periodic_progress`, mock the wrapper itself and assert that it was called with the correct arguments (`request_function`, `request_args`, etc.).
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_*_integration.py : Integration tests for cursor-based pagination must perform a two-step test: (1) call the tool without a cursor and extract the cursor from the response, (2) call the tool again with the cursor and assert that the second page's data is different from the first.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : Ensure all external API calls are properly mocked using `unittest.mock.patch` and `AsyncMock`.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/200-development-testing-workflow.mdc:0-0
Timestamp: 2025-07-04T20:28:28.716Z
Learning: Applies to tests/integration/test_*_integration.py : Add integration tests in tests/integration/test_{tool_module}_integration.py when adding or modifying tool functions that interact with live APIs
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_*_integration.py : Tool-level integration tests targeting high-level MCP tool functions (e.g., get_latest_block, get_tokens_by_address) must be located in files matching tests/integration/test_*_integration.py and should validate data extraction and schema against live API responses.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : When testing tools that transform a list of items, programmatically generate the `expected_result` from the `mock_api_response` instead of writing out large, repetitive expected results.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : Always verify the number of calls to `mock_ctx.report_progress` in your assertions to ensure progress tracking is tested.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_*_integration.py : Integration tests for paginated tools must use a loop with a max_pages_to_check limit to search across pages, and skip the test with a clear message if the target data is not found within the limit.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/200-development-testing-workflow.mdc:0-0
Timestamp: 2025-07-04T20:28:28.716Z
Learning: Applies to tests/integration/test_common_helpers.py : Add integration tests in tests/integration/test_common_helpers.py when modifying helper functions in tools/common.py
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : For tools returning a `ToolResponse` object, do not parse JSON from string results in your test; instead, mock the serialization function (`json.dumps`) if used internally, and make assertions on the structured `ToolResponse` object and its attributes.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/config.py : Add new API endpoint configuration to blockscout_mcp_server/config.py when introducing a new external API endpoint.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For tools that query Blockscout API, use dynamic chain resolution via get_blockscout_base_url and make_blockscout_request.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/000-role-and-task.mdc:0-0
Timestamp: 2025-07-04T20:18:25.795Z
Learning: Applies to **/*.py : The MCP server must wrap Blockscout APIs and expose blockchain data (balances, tokens, NFTs, contract metadata) via the Model Context Protocol (MCP)
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For tools that use fixed API endpoints (like BENS), use the appropriate request helper (e.g., make_bens_request).
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, include the exact notice '**SUPPORTS PAGINATION**: If response includes 'pagination' field, use the provided next_call to get additional pages.' in the docstring.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/common.py : Create a request helper function for new APIs in blockscout_mcp_server/tools/common.py.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_common_helpers.py : Helper-level integration tests targeting low-level helper functions in tools/common.py (e.g., make_blockscout_request, get_blockscout_base_url) must be located in tests/integration/test_common_helpers.py and verify basic network connectivity and response structure.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : When making multiple independent API calls, use asyncio.gather with return_exceptions=True and handle exceptions appropriately.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Avoid returning ToolResponse[dict] or ToolResponse[Any]; always prefer specific ToolResponse[YourDataModel].
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : Assert that mocked API helper functions (such as `make_blockscout_request`) are called exactly once with the correct `api_path` and `params` in your tests.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : Use the `mock_ctx` pytest fixture from `tests/conftest.py` for mocking the MCP Context object in tests; do not create a manual MagicMock for the context within your test functions.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Simplify address objects in API responses to a single address string to save LLM context.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, do not expose individual pagination parameters; use a single, opaque cursor string and handle it with apply_cursor_to_params.
.cursor/rules/110-new-mcp-tool.mdc (20)
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, do not expose individual pagination parameters; use a single, opaque cursor string and handle it with apply_cursor_to_params.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-04T20:16:41.182Z
Learning: Read `.cursor/rules/110-new-mcp-tool.mdc` for instructions on adding a new MCP tool to the server or modifying an existing one before responding to a user request
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, include the exact notice '**SUPPORTS PAGINATION**: If response includes 'pagination' field, use the provided next_call to get additional pages.' in the docstring.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-04T20:16:41.182Z
Learning: Read `.cursor/rules/200-development-testing-workflow.mdc` for instructions related to unit and integration testing applicable when a new helper function or MCP tool function is added or modified
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_*_integration.py : Integration tests for cursor-based pagination must perform a two-step test: (1) call the tool without a cursor and extract the cursor from the response, (2) call the tool again with the cursor and assert that the second page's data is different from the first.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/900-rules-maintenance.mdc:0-0
Timestamp: 2025-07-04T20:35:06.726Z
Learning: Applies to .cursor/AGENTS.md : Update the corresponding guidance in the 'Rule Application Guidelines' section of `.cursor/AGENTS.md` to reflect the changes made to the rule file.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Truncate large data fields in API responses and flag the truncation, providing guidance on how to retrieve the full data.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/900-rules-maintenance.mdc:0-0
Timestamp: 2025-07-04T20:35:06.726Z
Learning: Applies to .cursor/rules/*.mdc : When you create, modify, or delete any `.mdc` file in `.cursor/rules/`, you MUST update `.cursor/AGENTS.md` accordingly.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/140-tool-description.mdc:0-0
Timestamp: 2025-07-04T20:26:50.806Z
Learning: Applies to mcp/tools/**/*.py : The tool description docstring must name the data or system touched and any hard constraints (such as authentication, size, or date limits).
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/140-tool-description.mdc:0-0
Timestamp: 2025-07-04T20:26:50.806Z
Learning: Applies to mcp/tools/**/*.py : If still under the character limit, the tool description docstring may include an ultra-short usage example to clarify intent.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : All tools MUST return a strongly-typed ToolResponse[YourDataModel] instead of generic ToolResponse[dict].
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : All tools MUST return a standardized ToolResponse[YourDataModel] object using the build_tool_response helper.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Avoid returning ToolResponse[dict] or ToolResponse[Any]; always prefer specific ToolResponse[YourDataModel].
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/220-integration-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:31:56.480Z
Learning: Applies to tests/integration/test_*_integration.py : Integration tests for paginated tools must use a loop with a max_pages_to_check limit to search across pages, and skip the test with a clear message if the target data is not found within the limit.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For tools that query Blockscout API, use dynamic chain resolution via get_blockscout_base_url and make_blockscout_request.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For tools that use fixed API endpoints (like BENS), use the appropriate request helper (e.g., make_bens_request).
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Create or modify a tool module file in blockscout_mcp_server/tools/ for each new tool, choosing an existing module or creating a new one as appropriate.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Simplify address objects in API responses to a single address string to save LLM context.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Recursively truncate nested data structures in API responses, replacing long strings with a structured object to signal truncation.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/210-unit-testing-guidelines.mdc:0-0
Timestamp: 2025-07-04T20:30:09.292Z
Learning: Applies to tests/tools/*.py : For tools returning a `ToolResponse` object, do not parse JSON from string results in your test; instead, mock the serialization function (`json.dumps`) if used internally, and make assertions on the structured `ToolResponse` object and its attributes.
AGENTS.md (19)
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to AGENTS.md : Update AGENTS.md documentation to reflect new or modified tool modules, including updates to the project structure and examples sections.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/130-version-management.mdc:0-0
Timestamp: 2025-07-04T20:25:11.277Z
Learning: Applies to blockscout_mcp_server/__init__.py : When updating the version of the MCP server, update the `__version__` variable in `blockscout_mcp_server/__init__.py`.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/130-version-management.mdc:0-0
Timestamp: 2025-07-04T20:25:11.277Z
Learning: Update both `pyproject.toml` and `blockscout_mcp_server/__init__.py` simultaneously to maintain consistency across the codebase.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/140-tool-description.mdc:0-0
Timestamp: 2025-07-04T20:26:50.806Z
Learning: Applies to mcp/tools/**/*.py : The tool description docstring must name the data or system touched and any hard constraints (such as authentication, size, or date limits).
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/140-tool-description.mdc:0-0
Timestamp: 2025-07-04T20:26:50.806Z
Learning: Applies to mcp/tools/**/*.py : The tool description docstring must not include implementation internals such as schemas, parameter lists, versions, or other details.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/900-rules-maintenance.mdc:0-0
Timestamp: 2025-07-04T20:35:06.726Z
Learning: Applies to .cursor/AGENTS.md : Update the corresponding guidance in the 'Rule Application Guidelines' section of `.cursor/AGENTS.md` to reflect the changes made to the rule file.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/130-version-management.mdc:0-0
Timestamp: 2025-07-04T20:25:11.277Z
Learning: Applies to pyproject.toml : When updating the version of the MCP server, update the `version` field in the `[project]` section of `pyproject.toml`.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/000-role-and-task.mdc:0-0
Timestamp: 2025-07-04T20:18:25.795Z
Learning: Applies to **/*.py : The MCP server must wrap Blockscout APIs and expose blockchain data (balances, tokens, NFTs, contract metadata) via the Model Context Protocol (MCP)
Learnt from: CR
PR: blockscout/mcp-server#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-04T20:16:41.182Z
Learning: Read the project technical description in `SPEC.md` to clearly understand how the MCP server communicates with counterparties and important aspects of the server implementation before responding to a user request
Learnt from: CR
PR: blockscout/mcp-server#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-04T20:16:41.182Z
Learning: Read `.cursor/rules/110-new-mcp-tool.mdc` for instructions on adding a new MCP tool to the server or modifying an existing one before responding to a user request
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : All tools MUST return a standardized ToolResponse[YourDataModel] object using the build_tool_response helper.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : All tools MUST return a strongly-typed ToolResponse[YourDataModel] instead of generic ToolResponse[dict].
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Create or modify a tool module file in blockscout_mcp_server/tools/ for each new tool, choosing an existing module or creating a new one as appropriate.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For tools that use fixed API endpoints (like BENS), use the appropriate request helper (e.g., make_bens_request).
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For tools that query Blockscout API, use dynamic chain resolution via get_blockscout_base_url and make_blockscout_request.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/server.py : Register each new tool in blockscout_mcp_server/server.py by importing the tool function and registering it with the @mcp.tool() decorator.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, do not expose individual pagination parameters; use a single, opaque cursor string and handle it with apply_cursor_to_params.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Use the report_and_log_progress helper from tools/common.py for all progress reporting instead of calling ctx.report_progress directly.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Recursively truncate nested data structures in API responses, replacing long strings with a structured object to signal truncation.
SPEC.md (10)
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, include the exact notice '**SUPPORTS PAGINATION**: If response includes 'pagination' field, use the provided next_call to get additional pages.' in the docstring.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For paginated tools, do not expose individual pagination parameters; use a single, opaque cursor string and handle it with apply_cursor_to_params.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/900-rules-maintenance.mdc:0-0
Timestamp: 2025-07-04T20:35:06.726Z
Learning: Applies to .cursor/AGENTS.md : Update the corresponding guidance in the 'Rule Application Guidelines' section of `.cursor/AGENTS.md` to reflect the changes made to the rule file.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Truncate large data fields in API responses and flag the truncation, providing guidance on how to retrieve the full data.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Simplify address objects in API responses to a single address string to save LLM context.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-04T20:16:41.182Z
Learning: Read `.cursor/rules/010-implementation-rules.mdc` for general coding instructions before responding to a user request
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : Recursively truncate nested data structures in API responses, replacing long strings with a structured object to signal truncation.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For tools that query Blockscout API, use dynamic chain resolution via get_blockscout_base_url and make_blockscout_request.
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/000-role-and-task.mdc:0-0
Timestamp: 2025-07-04T20:18:25.795Z
Learning: Applies to **/*.py : The MCP server must wrap Blockscout APIs and expose blockchain data (balances, tokens, NFTs, contract metadata) via the Model Context Protocol (MCP)
Learnt from: CR
PR: blockscout/mcp-server#0
File: .cursor/rules/110-new-mcp-tool.mdc:0-0
Timestamp: 2025-07-04T20:22:01.665Z
Learning: Applies to blockscout_mcp_server/tools/*.py : For tools that use fixed API endpoints (like BENS), use the appropriate request helper (e.g., make_bens_request).
🧬 Code Graph Analysis (8)
tests/tools/test_transaction_tools_helpers.py (1)
blockscout_mcp_server/tools/transaction_tools.py (1)
  • _transform_advanced_filter_item (32-44)
tests/tools/test_common.py (1)
blockscout_mcp_server/tools/common.py (4)
  • create_items_pagination (488-535)
  • decode_cursor (315-324)
  • extract_log_cursor_params (538-544)
  • extract_advanced_filters_cursor_params (547-556)
tests/tools/test_address_logs.py (3)
blockscout_mcp_server/models.py (4)
  • AddressLogItem (255-258)
  • NextCallInfo (12-18)
  • PaginationInfo (21-24)
  • ToolResponse (272-297)
blockscout_mcp_server/tools/address_tools.py (1)
  • get_address_logs (276-381)
tests/conftest.py (1)
  • mock_ctx (8-13)
blockscout_mcp_server/tools/address_tools.py (2)
blockscout_mcp_server/tools/common.py (4)
  • create_items_pagination (488-535)
  • encode_cursor (307-312)
  • extract_log_cursor_params (538-544)
  • build_tool_response (424-465)
blockscout_mcp_server/models.py (4)
  • NftCollectionHolding (228-235)
  • PaginationInfo (21-24)
  • NextCallInfo (12-18)
  • AddressLogItem (255-258)
tests/tools/test_transaction_tools_pagination.py (2)
blockscout_mcp_server/tools/transaction_tools.py (1)
  • get_transactions_by_address (210-320)
tests/conftest.py (1)
  • mock_ctx (8-13)
blockscout_mcp_server/tools/common.py (1)
blockscout_mcp_server/models.py (3)
  • NextCallInfo (12-18)
  • PaginationInfo (21-24)
  • ToolResponse (272-297)
blockscout_mcp_server/tools/transaction_tools.py (2)
blockscout_mcp_server/tools/common.py (7)
  • create_items_pagination (488-535)
  • extract_advanced_filters_cursor_params (547-556)
  • extract_log_cursor_params (538-544)
  • make_request_with_periodic_progress (193-298)
  • make_blockscout_request (99-124)
  • report_and_log_progress (412-421)
  • build_tool_response (424-465)
blockscout_mcp_server/models.py (2)
  • AdvancedFilterItem (165-179)
  • TransactionLogItem (262-268)
tests/tools/test_transaction_tools.py (3)
blockscout_mcp_server/models.py (3)
  • AdvancedFilterItem (165-179)
  • NextCallInfo (12-18)
  • PaginationInfo (21-24)
tests/conftest.py (1)
  • mock_ctx (8-13)
blockscout_mcp_server/tools/transaction_tools.py (2)
  • get_transactions_by_address (210-320)
  • get_token_transfers_by_address (323-435)
🪛 LanguageTool
AGENTS.md

[uncategorized] ~111-~111: Loose punctuation mark.
Context: ... * BLOCKSCOUT_NFT_PAGE_SIZE: Page size for NFT token queries (defaul...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~112-~112: Loose punctuation mark.
Context: ... * BLOCKSCOUT_LOGS_PAGE_SIZE: Page size for address logs queries (def...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~113-~113: Loose punctuation mark.
Context: ... BLOCKSCOUT_ADVANCED_FILTERS_PAGE_SIZE: Page size for advanced filter queries (...

(UNLIKELY_OPENING_PUNCTUATION)

SPEC.md

[misspelling] ~259-~259: This word is normally spelled as one.
Context: ..., the server implements a sophisticated multi-page fetching strategy to handle cases where...

(EN_COMPOUNDS_MULTI_PAGE)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Docker build and docker push
🔇 Additional comments (38)
blockscout_mcp_server/tools/common.py (3)

16-16: LGTM: Import addition aligns with new pagination functionality.

The import of NextCallInfo is correctly added to support the new pagination utilities.


488-536: Excellent pagination utility implementation.

The create_items_pagination function provides a well-designed, reusable approach to pagination with:

  • Clear handling of both normal and forced pagination scenarios
  • Proper edge case management (empty items, cursor generation)
  • Clean separation of concerns using the cursor_extractor pattern
  • Standardized response format using NextCallInfo and PaginationInfo

The logic correctly slices items and generates appropriate pagination metadata. The force_pagination parameter is particularly useful for scenarios where the caller knows more pages exist despite having fewer items than the page size.


538-556: Well-designed cursor extractor functions.

Both extract_log_cursor_params and extract_advanced_filters_cursor_params provide clean, focused implementations for their specific use cases:

  • extract_log_cursor_params: Appropriately extracts block_number and index for log pagination
  • extract_advanced_filters_cursor_params: Comprehensively extracts all relevant indices for advanced filter pagination

The functions return properly structured dictionaries suitable for cursor encoding, maintaining consistency with the pagination pattern.

.env.example (1)

13-21: LGTM: Environment variables properly configured for pagination.

The three new environment variables are well-designed:

  • Clear, descriptive naming that indicates their specific use cases
  • Comprehensive comments explaining which tools use each variable
  • Reasonable default value of 10 that balances API efficiency with response size
  • Consistent with the existing environment variable pattern

These variables provide the necessary configuration flexibility for the new pagination functionality.

tests/tools/test_transaction_tools_helpers.py (1)

157-192: Excellent test implementation following best practices.

This test function demonstrates several strengths:

  • Comprehensive coverage: Tests address transformation, field removal, and preservation of unknown fields
  • Clear structure: Uses proper ARRANGE/ACT/ASSERT pattern with descriptive comments
  • Focused scope: Tests one specific behavior (transformation preserves unknown fields)
  • Thorough assertions: Verifies both expected transformations and field preservation
  • Good test data: Uses realistic input with both standard and custom fields

The test aligns well with the new unit testing guidelines about keeping tests simple and focused.

AGENTS.md (2)

16-16: Good documentation update for common.py.

The updated description appropriately reflects the expanded role of common.py with the new pagination utilities, emphasizing its function as a shared utilities module.


111-113: LGTM: Environment variables properly documented.

The three new pagination-related environment variables are clearly documented with:

  • Descriptive names indicating their specific purposes
  • Consistent formatting with existing variables
  • Appropriate default values mentioned

This maintains the documentation's completeness and helps users understand the configuration options.

.cursor/rules/210-unit-testing-guidelines.mdc (1)

10-40: Excellent addition of focused testing guidelines.

The new "Keep Unit Tests Simple and Focused" section provides valuable guidance that will improve test quality:

  • Clear principles: Emphasizes one test per behavior/scenario
  • Practical benefits: Lists concrete advantages of simple tests (easier maintenance, faster debugging, better failure diagnosis)
  • Actionable examples: Shows clear bad vs. good patterns for splitting complex tests
  • High priority placement: Appropriately positioned at the top to emphasize importance

This addition aligns well with the improved test practices seen throughout the codebase and will help maintain test quality as the project grows.

tests/integration/test_transaction_tools_integration.py (4)

61-61: LGTM! Correctly enforces page size limits.

The test now properly validates that results don't exceed the configured page size limit (10 items), which aligns with the new pagination approach.


245-247: LGTM! Proper pagination validation added.

The test correctly asserts that pagination metadata is present when exactly 10 items are returned, ensuring the pagination mechanism works as expected for full pages.


283-285: LGTM! Consistent pagination validation.

The same pagination validation pattern is correctly applied to token transfers, maintaining consistency across different transaction tools.


370-370: LGTM! Increased search range for better test coverage.

Increasing MAX_PAGES_TO_CHECK from 5 to 20 allows the test to search across more pages for truncated logs, improving the robustness of the pagination test.

tests/tools/test_address_logs.py (4)

6-12: LGTM! Appropriate imports for new pagination functionality.

The added imports for config, NextCallInfo, and PaginationInfo are necessary for the updated pagination testing approach.


107-120: LGTM! Correctly updated to use new pagination helper.

The test properly migrates from mocking encode_cursor to mocking create_items_pagination, reflecting the new pagination implementation. The mock return value correctly provides both sliced items and pagination info.


124-124: LGTM! Updated assertion for new pagination approach.

The assertion correctly validates that create_items_pagination is called once, aligning with the new pagination implementation.


140-170: LGTM! Excellent test for configurable page size.

This new test properly verifies that the get_address_logs function respects custom page size configuration by:

  • Mocking config.logs_page_size to 5
  • Verifying create_items_pagination is called with the correct page size
  • Using appropriate test data (10 items) to validate the slicing behavior

The test follows the established patterns and provides good coverage for the new configuration feature.

tests/tools/test_common.py (3)

335-434: LGTM! Comprehensive test coverage for pagination helper.

These tests provide excellent coverage for the create_items_pagination function, validating:

  • Normal pagination behavior when items exceed page size
  • No pagination when items are below page size
  • Force pagination functionality with various scenarios
  • Proper cursor generation and parameter preservation

The tests are well-structured and cover important edge cases like empty item lists and different pagination modes.


476-498: LGTM! Proper validation of parameter preservation.

This test correctly verifies that base parameters are preserved in pagination info while adding the cursor, ensuring the pagination mechanism maintains all necessary context for subsequent calls.


501-548: LGTM! Thorough testing of cursor extractor functions.

The tests for extract_log_cursor_params and extract_advanced_filters_cursor_params properly validate:

  • Extraction of correct fields from complete items
  • Handling of missing fields (returning None)
  • Proper behavior with empty dictionaries

These tests ensure the cursor extraction functions are robust and handle edge cases appropriately.

SPEC.md (3)

179-180: LGTM! Fixed formatting consistency.

The JSON code block delimiter is now properly closed, maintaining consistent formatting throughout the documentation.


239-268: LGTM! Excellent documentation of pagination strategy.

This section provides a comprehensive and clear explanation of the response slicing and multi-page fetching mechanisms. The documentation accurately describes:

  • The basic slicing mechanism that fetches full pages but returns smaller slices
  • The advanced multi-page fetching strategy for heavily filtered queries
  • The smart pagination logic that handles sparse data scenarios
  • The efficiency balance between network and context optimization

This documentation will be valuable for understanding the sophisticated pagination approach implemented in the codebase.


259-259: Address the static analysis hint about compound word.

The static analysis tool suggests "multipage" instead of "multi-page", but "multi-page" is widely accepted and more readable. No action needed as this is a style preference rather than an error.

tests/tools/test_transaction_tools_3.py (3)

7-13: LGTM! Imports properly organized.

The new imports for config, NextCallInfo, and PaginationInfo are correctly added and follow the established import order.


222-246: Pagination test correctly updated to use new helper.

The test now properly mocks create_items_pagination and constructs the expected return value with curated dictionaries and PaginationInfo, aligning with the new pagination pattern.


446-476: Well-structured test for custom page size configuration.

The test properly mocks the configuration, verifies that create_items_pagination is called with the correct page size parameter, and follows the established testing patterns.

blockscout_mcp_server/tools/address_tools.py (1)

366-375: Address logs pagination correctly uses the unified helper.

The migration to create_items_pagination with extract_log_cursor_params follows the new pagination pattern and properly handles the conversion between dictionaries and AddressLogItem objects.

tests/tools/test_transaction_tools.py (4)

24-93: Excellent refactoring to use smart pagination.

The test correctly verifies that _fetch_filtered_transactions_with_smart_pagination is called with the proper parameters including progress tracking steps (2.0 to 11.0 out of 12.0 total).


249-279: Good test coverage for custom page size configuration.

The test properly mocks the configuration and verifies that create_items_pagination is called with the configured page size.


641-749: Comprehensive test for sparse data multi-page fetching.

This test excellently simulates a realistic scenario where most transactions are filtered out, requiring multiple page fetches. The test data is well-structured with clear documentation of the expected behavior.


751-846: Thorough verification of multi-page progress reporting.

The test meticulously verifies each progress report at the correct steps (0, 1, and 12) with appropriate messages, ensuring the enhanced progress tracking works correctly throughout the multi-page fetching operation.

tests/tools/test_transaction_tools_pagination.py (5)

1-15: Well-documented test module with clear purpose.

The module docstring clearly explains the multi-page fetching strategy being tested, and imports are minimal and appropriate.


16-106: Excellent test for multi-page fetching with mixed transaction types.

The test clearly simulates sparse data requiring multiple page fetches, with detailed mock data showing filtered and valid transactions. The assertions verify correct accumulation, filtering, slicing, and pagination.


107-171: Important test for preventing excessive API calls.

This test ensures the 10-page maximum limit is enforced, preventing potential infinite loops or API abuse. The mock setup and assertions are thorough.


172-233: Good coverage of the optimized single-page scenario.

The test verifies that when sufficient data is available on the first page, no additional API calls are made, demonstrating the efficiency of the implementation.


234-294: Proper handling of API responses without next page.

The test correctly verifies that when the API indicates no more pages are available, the pagination metadata is not included in the response.

blockscout_mcp_server/tools/transaction_tools.py (3)

249-320: Proper integration of smart pagination with accurate progress reporting.

The function correctly uses the new pagination pattern, properly calculates progress steps to account for multiple page fetches, and appropriately uses the force_pagination parameter based on the has_more_pages indicator from the smart pagination helper.


419-435: Clean implementation of the standardized pagination pattern.

The replacement of manual cursor encoding with create_items_pagination simplifies the code and ensures consistency across all paginated tools.


559-559: Correct implementation of pagination with required documentation.

The function properly includes the exact pagination notice in the docstring and correctly uses create_items_pagination with the appropriate cursor extractor.

Also applies to: 636-644

@akolotov akolotov merged commit 29fedf8 into main Jul 8, 2025
7 checks passed
@akolotov akolotov deleted the codex/refactor-nft_tokens_by_address-pagination-logic branch July 8, 2025 04:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement Response Size Reduction for nft_tokens_by_address
1 participant