Skip to content

Conversation

@aaronsteers
Copy link
Contributor

@aaronsteers aaronsteers commented Nov 12, 2025

feat(mcp): Add mcp_smoke_tests_prompt for validating all tools and resources

Summary

Adds a new MCP prompt called mcp_smoke_tests_prompt to the Connector Builder MCP server that provides comprehensive testing instructions for validating all registered MCP tools, prompts, and resources. This prompt was requested by AJ Steers to enable systematic smoke testing of the MCP server's functionality.

Key changes:

  • New connector_builder_mcp/mcp/smoke_tests.py module with the smoke test prompt implementation
  • Prompt uses the @mcp_prompt decorator for automatic registration in the PROMPTS domain
  • Dynamically discovers all registered tools, resources, and prompts from internal registries
  • Supports read_only parameter (default: True) to filter tools by read-only status
  • Generates structured testing instructions grouped by domain
  • Import added to server.py to trigger decorator registration

Review & Testing Checklist for Human

This is a YELLOW risk PR - the implementation is straightforward but has some areas that need verification:

  • Verify prompt registration: Test that the prompt is actually accessible via MCP protocol (e.g., using Claude Desktop or MCP inspector). The decorator-based registration should work, but needs confirmation.
  • Test filtering logic: Call the prompt with read_only=True and read_only=False to verify the tool filtering works correctly. Check that the annotation key readOnlyHint matches what's actually used in the tool decorators.
  • Review direct registry access: The code directly accesses _REGISTERED_TOOLS, _REGISTERED_RESOURCES, and _REGISTERED_PROMPTS (private variables). Consider if this is the intended API or if there should be a public accessor function.

Test Plan

  1. Start the Connector Builder MCP server
  2. Use an MCP client to list available prompts and verify mcp_smoke_tests_prompt appears
  3. Call the prompt with default parameters and verify it returns comprehensive testing instructions
  4. Call the prompt with read_only=False and verify it includes destructive tools in the output
  5. Follow the generated instructions to manually test a few tools and verify the guidance is accurate

Notes

  • The register_smoke_test_prompt() function exists but is empty (just pass) because registration happens automatically via the @mcp_prompt decorator. This function could be removed or documented better.
  • The import in server.py uses # noqa: F401 to suppress unused import warnings since the import is only needed for decorator side effects.
  • This PR is part of a coordinated effort - a similar prompt was also added to the PyAirbyte MCP server in feat(mcp): Add mcp_smoke_tests_prompt for validating all tools and resources PyAirbyte#859

Requested by: AJ Steers ([email protected]) via GitHub (@aaronsteers)
Devin session: https://app.devin.ai/sessions/1145d85639d849b396b2021ba80433b8

Summary by CodeRabbit

Release Notes

  • New Features
    • Added a new smoke testing feature to validate system tools, resources, and prompts functionality.
    • Introduced a read-only testing mode for safe validation without executing destructive operations.

…sources

- Add new smoke_tests.py module with mcp_smoke_tests_prompt function
- Prompt provides comprehensive testing instructions for all MCP tools, prompts, and resources
- Supports read_only parameter (default: True) to filter tools by read-only status
- Uses @mcp_prompt decorator for automatic registration
- Groups tools by domain and generates detailed testing instructions
- Includes resource and prompt testing in addition to tool testing

Co-Authored-By: AJ Steers <[email protected]>
@devin-ai-integration
Copy link
Contributor

Original prompt from AJ Steers
Received message in Slack channel #ask-devin-ai:

@Devin - In the PyAirbyte MCP server and also in the Connector Builder MCP server, let's add a prompt-based smoke test of all tools. I think we can call this something like `mcp_smoke_tests_prompt` . The prompt will be something like 'run all of your tools and check all of your mcp resource assets to confirm that they all are working properly'. The tool will take a single arg which is 'read_only', defaulting to True.
Thread URL: https://airbytehq-team.slack.com/archives/C08BHPUMEPJ/p1762905441804149

@devin-ai-integration
Copy link
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 12, 2025

Warning

Rate limit exceeded

@devin-ai-integration[bot] has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 4 minutes and 11 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 1c595ad and a8a3ca7.

📒 Files selected for processing (1)
  • connector_builder_mcp/mcp/smoke_tests.py (1 hunks)
📝 Walkthrough

Walkthrough

This PR introduces a new MCP smoke test prompt module that generates comprehensive testing documentation. The module provides a function to dynamically build smoke test instructions by aggregating registered tools, resources, and prompts—filtered by tool access level when requested—and organizing them by domain. An import is added to the server module.

Changes

Cohort / File(s) Change Summary
New MCP smoke test prompt module
connector_builder_mcp/mcp/smoke_tests.py
Adds mcp_smoke_tests_prompt() function that generates a comprehensive multi-section smoke test document, filtering registered tools by read-only hint, grouping tools/resources by domain, listing available prompts, and including detailed testing instructions. Includes placeholder register_smoke_test_prompt() function.
Server import
connector_builder_mcp/server.py
Imports mcp_smoke_tests_prompt from the new smoke tests module; suppressed unused import warning.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Review the smoke test prompt generation logic, including tool/resource filtering and domain-based grouping behavior
  • Verify the prompt structure and instruction content align with testing requirements
  • Confirm register_smoke_test_prompt() placeholder meets immediate needs or requires implementation

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • dbgold17
  • pedroslopez
  • pnilan
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch devin/1762905945-add-mcp-smoke-test-prompt

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

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

👋 Welcome to the Airbyte Connector Builder MCP!

Thank you for your contribution! Here are some helpful tips and reminders for your convenience.

Testing This Branch via MCP

To test the changes in this specific branch with an MCP client like Claude Desktop, use the following configuration:

{
  "mcpServers": {
    "connector-builder-mcp-dev": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/airbytehq/connector-builder-mcp.git@devin/1762905945-add-mcp-smoke-test-prompt", "connector-builder-mcp"]
    }
  }
}

Testing This Branch via CLI

You can test this version of the MCP Server using the following CLI snippet:

# Run the CLI from this branch:
uvx 'git+https://github.com/airbytehq/connector-builder-mcp.git@devin/1762905945-add-mcp-smoke-test-prompt#egg=airbyte-connector-builder-mcp' --help

PR Slash Commands

Airbyte Maintainers can execute the following slash commands on your PR:

  • /autofix - Fixes most formatting and linting issues
  • /build-connector - Builds the default connector on-demand using the AI builder
  • /build-connector prompt="<your prompt>" - Builds a connector on-demand using the AI builder
  • /poe <command> - Runs any poe command in the uv virtual environment

AI Builder Evaluations

AI builder evaluations run automatically under the following conditions:

  • When a PR is marked as "ready for review"
  • When a PR is reopened

A set of standardized evaluations also run on a schedule (Mon/Wed/Fri at midnight UTC) and can be manually triggered via workflow dispatch.

Helpful Resources

If you have any questions, feel free to ask in the PR comments or join our Slack community.

📝 Edit this welcome message.

@github-actions github-actions bot added the enhancement New feature or request label Nov 12, 2025
from connector_builder_mcp.mcp.prompts import register_mcp_prompts
from connector_builder_mcp.mcp.secrets_config import register_secrets_tools
from connector_builder_mcp.mcp.server_info import register_server_info_resources
from connector_builder_mcp.mcp.smoke_tests import mcp_smoke_tests_prompt # noqa: F401
@github-actions
Copy link

github-actions bot commented Nov 12, 2025

PyTest Results (Fast)

0 tests  ±0   0 ✅ ±0   0s ⏱️ ±0s
0 suites ±0   0 💤 ±0 
0 files   ±0   0 ❌ ±0 

Results for commit a8a3ca7. ± Comparison against base commit 0750ae6.

♻️ This comment has been updated with latest results.

@github-actions
Copy link

github-actions bot commented Nov 12, 2025

PyTest Results (Full)

0 tests  ±0   0 ✅ ±0   0s ⏱️ ±0s
0 suites ±0   0 💤 ±0 
0 files   ±0   0 ❌ ±0 

Results for commit a8a3ca7. ± Comparison against base commit 0750ae6.

♻️ This comment has been updated with latest results.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
connector_builder_mcp/mcp/smoke_tests.py (1)

60-61: The prompt includes itself in the listing (expected behavior).

Since the @mcp_prompt decorator registers this function at import time, _REGISTERED_PROMPTS will include mcp_smoke_tests_prompt itself when this code executes. This means the generated smoke test instructions will include testing the smoke test prompt, creating a minor circular reference. This is likely acceptable as it provides complete coverage, but be aware of this self-referential behavior.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0750ae6 and 1c595ad.

📒 Files selected for processing (2)
  • connector_builder_mcp/mcp/smoke_tests.py (1 hunks)
  • connector_builder_mcp/server.py (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-10-11T02:19:05.231Z
Learnt from: aaronsteers
Repo: airbytehq/connector-builder-mcp PR: 136
File: connector_builder_agents/src/evals/evaluators.py:233-245
Timestamp: 2025-10-11T02:19:05.231Z
Learning: In the connector-builder-mcp repository Python files, all imports must be placed at the module level (top of the file), never inside functions or methods. This is a recurring issue that should be flagged during code reviews.

Applied to files:

  • connector_builder_mcp/server.py
📚 Learning: 2025-11-08T06:53:26.977Z
Learnt from: aaronsteers
Repo: airbytehq/connector-builder-mcp PR: 176
File: connector_builder_mcp/_manifest_history_utils.py:38-49
Timestamp: 2025-11-08T06:53:26.977Z
Learning: In the connector-builder-mcp repository, all imports must be at the module level (top of the file). Inline imports inside functions or methods are not allowed unless explicit permission is granted. This rule must never be violated.

Applied to files:

  • connector_builder_mcp/server.py
🧬 Code graph analysis (2)
connector_builder_mcp/mcp/smoke_tests.py (1)
connector_builder_mcp/mcp/_mcp_utils.py (2)
  • ToolDomain (49-80)
  • mcp_prompt (152-182)
connector_builder_mcp/server.py (1)
connector_builder_mcp/mcp/smoke_tests.py (1)
  • mcp_smoke_tests_prompt (23-137)
⏰ 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). (3)
  • GitHub Check: Pytest (Fast)
  • GitHub Check: Pytest (All, Python 3.11, Ubuntu)
  • GitHub Check: Pytest (All, Python 3.10, Ubuntu)
🔇 Additional comments (4)
connector_builder_mcp/mcp/smoke_tests.py (3)

23-137: Well-structured smoke test prompt generation.

The function correctly:

  • Filters tools based on the read_only parameter
  • Groups tools, resources, and prompts by domain for organized output
  • Generates comprehensive, actionable testing instructions
  • Returns properly formatted prompt content

The string-building approach using list concatenation and join is efficient and readable.


9-15: No action required—private registry access is acceptable for internal package use.

Direct access to _REGISTERED_TOOLS, _REGISTERED_RESOURCES, and _REGISTERED_PROMPTS is appropriate here. These are internal implementation details of the mcp package with no public accessors defined elsewhere in the codebase. The access is limited to internal package files (_mcp_utils.py and smoke_tests.py) and follows the established deferred registration pattern. Adding public wrapper functions would only introduce unnecessary boilerplate without improving encapsulation in this context.


37-42: The original review comment is incorrect—tools are properly annotated with readOnlyHint.

The filtering logic is sound and working as intended. Tools are explicitly decorated with read_only=True (e.g., manifest_checks.py, checklist.py, guidance.py), which correctly maps to the readOnlyHint annotation key through the mcp_tool decorator. When read_only=True, the filter returns tools marked as read-only; when read_only=False, it includes all tools. The annotation convention is established and followed.

Likely an incorrect or invalid review comment.

connector_builder_mcp/server.py (1)

24-24: Side-effect import pattern is correctly implemented.

The @mcp_prompt decorator registers the smoke test prompt in _REGISTERED_PROMPTS at module load time, and register_mcp_prompts() later consumes the registry. The noqa: F401 suppression is justified because the import triggers necessary decorator registration, not a true unused import. Verification confirms the flow works correctly.

Comment on lines 140 to 142
def register_smoke_test_prompt(app: FastMCP) -> None:
"""Register the smoke test prompt with the FastMCP app."""
pass
Copy link
Contributor

@coderabbitai coderabbitai bot Nov 12, 2025

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Remove unused registration function.

The register_smoke_test_prompt() function is never called and serves no purpose since registration happens via the @mcp_prompt decorator. This is dead code that should be removed to avoid confusion.

Apply this diff to remove the unused function:

-def register_smoke_test_prompt(app: FastMCP) -> None:
-    """Register the smoke test prompt with the FastMCP app."""
-    pass
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def register_smoke_test_prompt(app: FastMCP) -> None:
"""Register the smoke test prompt with the FastMCP app."""
pass
🤖 Prompt for AI Agents
In connector_builder_mcp/mcp/smoke_tests.py around lines 140 to 142, remove the
unused dead function register_smoke_test_prompt(app: FastMCP) which is never
called because registration is handled by the @mcp_prompt decorator; delete the
entire function definition and its docstring so only the decorator-based
registration remains, and run tests/lint to confirm no references remain.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Code rabbit, that's not exactly correct but thanks for flagging.

Devin,

this function should call the register_prompts helper with the applicable domain as input.

Copy link
Contributor

Choose a reason for hiding this comment

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for register_prompts function definition
echo "=== Searching for register_prompts function ==="
rg -n "def register_prompts" -A 5

echo -e "\n=== Searching for register_prompts usage ==="
rg -n "register_prompts\(" -B 2 -A 2

echo -e "\n=== Searching for similar register_ functions in mcp directory ==="
fd -e py . connector_builder_mcp/mcp/ --exec rg -n "def register_" {} \;

echo -e "\n=== Checking _mcp_utils module for helper functions ==="
fd -e py . connector_builder_mcp/mcp/ -x basename {} | grep -E "(_mcp|utils)" | head -5
rg -n "def register" connector_builder_mcp/mcp/_mcp_utils.py -A 3

Length of output: 1933


🏁 Script executed:

#!/bin/bash
# Check the implementation of register_mcp_prompts
echo "=== register_mcp_prompts implementation ==="
rg -n "def register_mcp_prompts" connector_builder_mcp/mcp/_mcp_utils.py -A 20

echo -e "\n=== Check how other domains use these registration functions ==="
rg -n "register_mcp_prompts\(" -B 1 -A 1
rg -n "register_mcp_tools\(" -B 1 -A 1 | head -20

Length of output: 2567


@aaronsteers, thank you for the clarification! You're absolutely right. The function should call the register_mcp_prompts helper. Here's the corrected implementation:

Step 1: Add register_mcp_prompts to the imports

from connector_builder_mcp.mcp._mcp_utils import (
    _REGISTERED_PROMPTS,
    _REGISTERED_RESOURCES,
    _REGISTERED_TOOLS,
    ToolDomain,
    mcp_prompt,
    register_mcp_prompts,  # Add this import
)

Step 2: Implement the function body

def register_smoke_test_prompt(app: FastMCP) -> None:
    """Register the smoke test prompt with the FastMCP app."""
    register_mcp_prompts(app, domain=ToolDomain.PROMPTS)

This follows the same pattern used in prompts.py and other domain registration functions throughout the codebase.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for the feedback! I've updated the register_smoke_test_prompt() function to call register_mcp_prompts(app, domain=ToolDomain.PROMPTS), following the same pattern used in connector_builder_mcp/mcp/prompts.py.

Implementation details

The function now delegates to the existing register_mcp_prompts helper from _mcp_utils.py, which filters and registers all prompts in the PROMPTS domain. Since the smoke test prompt is already decorated with @mcp_prompt(domain=ToolDomain.PROMPTS), it will be included when this helper is called.

The current server.py already calls register_mcp_prompts(app, domain=ToolDomain.PROMPTS) on line 53, which registers all prompts including the smoke test. This function provides an explicit registration path that follows the established pattern in the codebase.

Pushing the update now.

Copy link
Contributor

Choose a reason for hiding this comment

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

Skipped: comment is from another GitHub bot.

…rompts helper

- Add register_mcp_prompts import from _mcp_utils
- Update register_smoke_test_prompt() to call register_mcp_prompts(app, domain=ToolDomain.PROMPTS)
- Follows the same pattern as register_prompts() in prompts.py

Addresses feedback from @aaronsteers

Co-Authored-By: AJ Steers <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants