Skip to content

Add radioactive decay MCP tool - #1416

Closed
tamohannes wants to merge 10 commits into
NVIDIA-NeMo:mainfrom
tamohannes:feat/radioactivedecay-mcp-tool
Closed

tamohannes wants to merge 10 commits into
NVIDIA-NeMo:mainfrom
tamohannes:feat/radioactivedecay-mcp-tool

Conversation

@tamohannes

@tamohannes tamohannes commented May 1, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Add a built-in radioactivedecay MCP tool for nuclide lookup and decay-chain calculations.
  • Document the new built-in tool in the agentic inference tool-calling guide.
  • Add MCP client tests for tool configuration, stdio tool listing, and hidden optional time-unit args.

Test plan

  • python -m py_compile nemo_skills/mcp/servers/radioactivedecay_tool.py
  • python -m pytest tests/test_mcp_clients.py::TestRadioactivedecayTool -q --tb=short
  • python -m pytest tests/test_mcp_clients.py -q --tb=short

Made with Cursor

Summary by CodeRabbit

  • New Features

    • Added a Radioactivedecay tool for querying nuclide properties and computing decay chains over time.
  • Documentation

    • Built-in tools reference updated to include the new Radioactivedecay tool and usage notes.
  • Tests

    • Added tests covering the new tool’s configuration, registration, and runtime behavior.
  • Chores

    • CI workflow refined to conditionally use remote build cache and tighten test marker filtering.

@coderabbitai

coderabbitai Bot commented May 1, 2026 •

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a FastMCP server and stdio-launched client wrapper providing radioactive-decay tools (nuclide-info, decay-chain), updates docs and tests for the new tool, and adjusts CI to conditionally use GHCR caching and exclude live tests.

Changes

Cohort / File(s) Summary
Documentation
docs/agentic_inference/tool_calling.md
Adds RadioactivedecayTool to built-in tools list with source link and note about radioactivedecay dependency.
MCP Server Implementation
nemo_skills/mcp/servers/radioactivedecay_tool.py
New FastMCP server registering nuclide-info and decay-chain handlers, input validation, decay simulation via radioactivedecay, result formatting, main() entrypoint, and RadioactivedecayTool stdio-launched MCP client wrapper.
Tests
tests/test_mcp_clients.py
Adds tests for RadioactivedecayTool validating stdio client selection and server-module arg, configure()/list_tools() behavior, presence and schema of nuclide-info/decay-chain, and ensures proper shutdown.
CI / Workflow
.github/workflows/tests.yml
GHCR login and buildx cache flags gated on GHCR_PAT, installs tools extra during dependency install, and updates pytest to exclude gpu and live tests.

Sequence Diagram

sequenceDiagram
    actor User
    participant Client
    participant MCPStdioClient
    participant Server as radioactivedecay_tool
    participant Library as radioactivedecay

    User->>Client: call decay_chain(nuclide, time, time_unit)
    Client->>MCPStdioClient: send tool request (stdio)
    MCPStdioClient->>Server: invoke tool handler
    Server->>Server: validate inputs (nuclide, time, unit)
    Server->>Library: construct Nuclide & Inventory
    Library-->>Server: Nuclide / Inventory
    Server->>Library: Inventory.decay(time, time_unit)
    Library-->>Server: decayed inventory
    Server->>Server: compute activities, filter, format table
    Server-->>MCPStdioClient: return formatted response
    MCPStdioClient-->>Client: deliver result
    Client-->>User: present decay chain data
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add radioactive decay MCP tool' clearly and directly describes the main change: introducing a new MCP tool for radioactive decay functionality.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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)
tests/test_mcp_clients.py (1)

1018-1034: ⚡ Quick win

Add one runtime tool-call smoke assertion in this test.

This test currently validates discovery/schema only. Adding a simple execute(...) call would catch runtime regressions in the stdio call path with minimal extra cost.

Suggested extension (inside the same test)
         try:
             tools = await tool.list_tools()
             tool_names = {t["name"] for t in tools}
             assert "nuclide-info" in tool_names
             assert "decay-chain" in tool_names

             decay_tool = next(t for t in tools if t["name"] == "decay-chain")
             schema_props = decay_tool["input_schema"]["properties"]
             assert "time_unit" not in schema_props
+
+            out = await tool.execute("decay-chain", {"nuclide": "Co-60", "time": 1.0})
+            assert isinstance(out, str)
+            assert "Decay of" in out
         finally:
             await tool.shutdown()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_mcp_clients.py` around lines 1018 - 1034, The test only checks
discovery/schema; add a runtime smoke invocation to catch stdio regressions by
calling RadioactivedecayTool.execute for the discovered "decay-chain" tool and
asserting the response is truthy/has expected shape. Locate the
test_radioactivedecay_stdio_list_tools test, after you select decay_tool (next(t
for t in tools if t["name"] == "decay-chain")), call tool.execute with a minimal
valid input payload for the decay-chain tool (e.g., a simple nuclide and time
spec) and assert the result is non-empty or contains an expected key (like a
decay chain entry), then proceed to the existing finally block to await
tool.shutdown().
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@nemo_skills/mcp/servers/radioactivedecay_tool.py`:
- Around line 58-67: The loop that formats the half-life (using nuc.half_life()
and nuc.half_life(unit)) only emits a line when a converted value is >= 1.0, so
nuclides with half-life < 1 s produce no output; update the logic in the
half-life block to ensure a value is always appended — after the for loop over
units (["y","d","h","m","s"]) detect if no line was appended and then append a
fallback line (e.g., use the raw seconds value half_life_s or the seconds
conversion hl when <1) such as "Half-life: {half_life_s:.6g} s" so sub-second
half-lives are shown; make the change around the code that references
half_life_s, nuc.half_life(), and the existing for-loop.

---

Nitpick comments:
In `@tests/test_mcp_clients.py`:
- Around line 1018-1034: The test only checks discovery/schema; add a runtime
smoke invocation to catch stdio regressions by calling
RadioactivedecayTool.execute for the discovered "decay-chain" tool and asserting
the response is truthy/has expected shape. Locate the
test_radioactivedecay_stdio_list_tools test, after you select decay_tool (next(t
for t in tools if t["name"] == "decay-chain")), call tool.execute with a minimal
valid input payload for the decay-chain tool (e.g., a simple nuclide and time
spec) and assert the result is non-empty or contains an expected key (like a
decay chain entry), then proceed to the existing finally block to await
tool.shutdown().
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 58d9a4f0-29ef-4ce3-bb2e-f64bd6c27d22

📥 Commits

Reviewing files that changed from the base of the PR and between 7dcb0a6 and 4328237.

📒 Files selected for processing (3)
  • docs/agentic_inference/tool_calling.md
  • nemo_skills/mcp/servers/radioactivedecay_tool.py
  • tests/test_mcp_clients.py

@gwarmstrong gwarmstrong left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Hi @tamohannes , Thank you for the contributions! I would encourage you to please switch to a tool path that avoids the MCP protocol (we have found it to cause real latency and stability issues during RL) in favor of a direct tool approach. The changes should be fairly minimal--please see the DirectPythonTool for an example.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/tests.yml:
- Line 27: The step-level conditional using "if: ${{ secrets.GHCR_PAT != '' }}"
is invalid; move the secret into the job-level environment and change the
conditional to check env instead. Define GHCR_PAT under the job's env (e.g.,
env: GHCR_PAT: ${{ secrets.GHCR_PAT }}) and update the step conditional to "if:
${{ env.GHCR_PAT != '' }}", ensuring the step no longer references the secrets
context directly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 866ec0e0-0f22-41e2-a641-10facb91e30c

📥 Commits

Reviewing files that changed from the base of the PR and between 4328237 and dc09ff6.

📒 Files selected for processing (1)
  • .github/workflows/tests.yml

Comment thread .github/workflows/tests.yml Resolved
Signed-off-by: tamohannes <hovhannes.tamoyan@gmail.com>
@tamohannes
tamohannes force-pushed the feat/radioactivedecay-mcp-tool branch from 6aab2a9 to 38238f6 Compare May 1, 2026 19:03
Signed-off-by: tamohannes <hovhannes.tamoyan@gmail.com>
@tamohannes

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
.github/workflows/tests.yml (1)

26-32: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Fix the GHCR login gate before merging.

secrets is still referenced in the step-level if, which GitHub Actions rejects during workflow validation. The build step’s env block does not help here because step conditions cannot read it.

Suggested fix
 jobs:
   unit-tests:
     runs-on: ubuntu-latest
+    env:
+      GHCR_PAT: ${{ secrets.GHCR_PAT }}
     steps:
@@
     - name: Login to GHCR
-      if: ${{ secrets.GHCR_PAT != '' }}
+      if: ${{ env.GHCR_PAT != '' }}
       uses: docker/login-action@v3
       with:
         registry: ghcr.io
         username: ${{ github.actor }}
-        password: ${{ secrets.GHCR_PAT }}
+        password: ${{ env.GHCR_PAT }}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/tests.yml around lines 26 - 32, The step "Login to GHCR"
is using a step-level if that references secrets.GHCR_PAT (secrets cannot be
evaluated in step-level conditionals and fails workflow validation); remove the
step-level if that uses secrets.GHCR_PAT and instead place the conditional at
the job level (or gate the entire job) so the login step using
docker/login-action@v3 only runs when the secret exists; ensure the step itself
no longer references secrets in its if and continues to use username: ${{
github.actor }} and password: ${{ secrets.GHCR_PAT }} inside the with: block.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@nemo_skills/mcp/servers/radioactivedecay_tool.py`:
- Around line 96-97: The current validation only checks time < 0 and allows
NaN/inf to reach inv.decay; update the validation around the variable time (the
same block that currently does "if time < 0: return ...") to first reject
non-finite values (use math.isfinite or equivalent) and return a clear error
(e.g., "Time must be a finite non-negative number") before proceeding to call
inv.decay(...), so inv.decay never receives NaN or infinite inputs.

---

Duplicate comments:
In @.github/workflows/tests.yml:
- Around line 26-32: The step "Login to GHCR" is using a step-level if that
references secrets.GHCR_PAT (secrets cannot be evaluated in step-level
conditionals and fails workflow validation); remove the step-level if that uses
secrets.GHCR_PAT and instead place the conditional at the job level (or gate the
entire job) so the login step using docker/login-action@v3 only runs when the
secret exists; ensure the step itself no longer references secrets in its if and
continues to use username: ${{ github.actor }} and password: ${{
secrets.GHCR_PAT }} inside the with: block.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 2fd5aea4-a2a9-4049-a681-1c4e9bc4f108

📥 Commits

Reviewing files that changed from the base of the PR and between 6aab2a9 and 38238f6.

📒 Files selected for processing (4)
  • .github/workflows/tests.yml
  • docs/agentic_inference/tool_calling.md
  • nemo_skills/mcp/servers/radioactivedecay_tool.py
  • tests/test_mcp_clients.py
✅ Files skipped from review due to trivial changes (1)
  • docs/agentic_inference/tool_calling.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/test_mcp_clients.py

Signed-off-by: tamohannes <hovhannes.tamoyan@gmail.com>
@tamohannes

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Signed-off-by: tamohannes <hovhannes.tamoyan@gmail.com>
@tamohannes

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Signed-off-by: tamohannes <hovhannes.tamoyan@gmail.com>
@tamohannes

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Signed-off-by: tamohannes <hovhannes.tamoyan@gmail.com>
@tamohannes

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Signed-off-by: tamohannes <hovhannes.tamoyan@gmail.com>
@tamohannes

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Signed-off-by: tamohannes <hovhannes.tamoyan@gmail.com>
@tamohannes

Copy link
Copy Markdown
Collaborator Author

Updated this PR to use the direct \ path instead of launching a stdio MCP server. The PR diff is now limited to the tool implementation, docs reference, and focused tests; workflow/pyproject changes were removed. @coderabbitai review

@coderabbitai

coderabbitai Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@tamohannes Thanks for the update! I'll kick off a fresh review of the revised PR now, focusing on the tool implementation, docs reference, and tests.

[review]

@tamohannes

Copy link
Copy Markdown
Collaborator Author

Updated this PR to use the direct Tool path instead of launching a stdio MCP server. The PR diff is now limited to the tool implementation, docs reference, and focused tests; workflow/pyproject changes were removed. @coderabbitai review

@coderabbitai

coderabbitai Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@tamohannes Thanks for the update! I'll kick off a fresh review of the revised PR now, focusing on the direct Tool path implementation, docs reference, and tests.

[review]

Signed-off-by: tamohannes <hovhannes.tamoyan@gmail.com>
@tamohannes

Copy link
Copy Markdown
Collaborator Author

Updated to the direct Tool implementation path (no stdio MCP server/client). The final diff is scoped to the tool file, docs reference, and focused tests only. @coderabbitai review

@coderabbitai

coderabbitai Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@tamohannes Thanks for the update! I'll kick off a fresh review of the revised PR now, focusing on the direct Tool implementation, docs reference, and tests — with no stdio MCP server/client in scope.

[review]

…cay-mcp-tool

Signed-off-by: tamohannes <hovhannes.tamoyan@gmail.com>
@tamohannes

Copy link
Copy Markdown
Collaborator Author

Closing in favor of #1423, reopened from an internal NVIDIA-NeMo/Skills branch so CI can access repository secrets.

@tamohannes tamohannes closed this May 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants