Skip to content

Conversation

@NiccoloGrillo
Copy link
Collaborator

New MCP Tools Added

1. derive_all_equations_analyze

Purpose: Intelligent equation categorization and analysis for parallel processing

Description:
This tool analyzes scientific documents (PDF, Markdown, or text) and automatically categorizes all equations found within them. It uses AI to determine which equations are suitable for symbolic derivation and which are not, providing detailed rationale for each decision.

Key Features:

  • Scans documents for mathematical equations
  • Categorizes equations as "eligible" or "not eligible" for derivation
  • Provides context and rationale for each categorization decision
  • Returns structured analysis with summary statistics
  • Critical workflow requirement: Must ask user for approval before proceeding to execution

Use Cases:

  • Processing research papers with multiple equations
  • Batch analysis of mathematical content
  • Quality control for equation derivation workflows

2. derive_all_equations_execute

Purpose: Parallel batch execution of equation derivations

Description:
This tool executes the actual derivation process for all approved equations from the analysis step. It processes multiple equations in parallel batches, generating individual SymPy code files for each successful derivation.

Key Features:

  • Parallel processing for efficiency (2-10 minute execution time)
  • Generates individual .py files for each equation
  • Provides real-time progress tracking and estimation
  • Comprehensive success/failure reporting
  • Automatic file organization and naming
  • Synchronous operation: Blocks until all derivations complete

Use Cases:

  • Batch processing of research paper equations
  • Automated generation of verification code libraries
  • Large-scale mathematical content processing

🔄 Workflow Integration

These tools work together in a structured 2-step workflow:

  1. Analysis Phase: derive_all_equations_analyze → User approval required
  2. Execution Phase: derive_all_equations_execute → Automatic execution after approval

The workflow includes built-in safeguards requiring explicit user approval before proceeding to the computationally intensive execution phase, ensuring users have full control over the batch processing operation.

Both tools leverage the existing Axiomatic API infrastructure and follow the same document processing patterns as other tools in the equations server, maintaining consistency with the existing codebase architecture.

NiccoloGrillo and others added 6 commits October 1, 2025 12:21
… for API requests and improve mermaid text formatting
- Updated server initialization to include new feedback prompts for the derive_all_equations workflow.
- Enhanced documentation within the code to clarify the workflow and user instructions.
@NiccoloGrillo NiccoloGrillo requested a review from a team as a code owner October 10, 2025 13:12
@NiccoloGrillo NiccoloGrillo requested review from javieraspuru-ax and removed request for a team October 10, 2025 13:12
@coderabbitai
Copy link

coderabbitai bot commented Oct 10, 2025

Walkthrough

  • I am Axiomatic Intelligence. I observe these factual changes:
  • Added helper _get_python_code(code_input: Path | str) -> tuple[str, Path | None] to normalize SymPy code inputs (file path or direct string) with validation.
  • Added tools in axiomatic_mcp/servers/equations/server.py:
    • generate_derivation_graph(sympy_code: Annotated[Path | str, ...]) -> ToolResult — generates a Mermaid flowchart from SymPy-derived code and writes a file (returns mermaid_text).
    • select_relevant_equations(document: Annotated[Path | str, ...]) -> ToolResult — analyzes a document to categorize equations and returns formatted analysis text.
    • derive_all_equations(document: Annotated[Path | str, ...], relevant_equations: Annotated[list[dict], ...], output_directory: Annotated[str | None, ...] = None) -> ToolResult — runs derivations for selected equations, writes .py outputs, returns progress narrative and detailed results, saving outputs to a directory.
  • Adjusted tool wiring to include the new tools in the derive-all feedback prompt.
  • Reformatted several long Annotated type hints across tool signatures (no semantic changes).
  • In axiomatic_mcp/shared/api_client.py, added environment-driven override of the API base URL via AXIOMATIC_API_URL (falls back to existing API_URL).
  • Added two new Markdown reports: ASML_Patent_Comprehensive_Verification_Report.md and ASML_Presentation_Deck.md (documentation additions only).

Estimated code review effort

  • 🎯 4 (Complex) | ⏱️ ~45 minutes
  • Reasoning:
    • Scope: Multiple files (server tools, API client, two large documentation files).
    • Heterogeneity: New runtime logic (input normalization, derivation orchestration, graph generation), IO and file-writing paths, prompt/tool wiring changes, plus environment-config change in HTTP client and sizable docs.
    • Density: Moderate-to-high branching and integration points; requires review of correctness of file handling, tool return formats, and ensuring API base URL logic is secure and tested.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The title accurately reflects the primary additions in this changeset: new MCP tools for analyzing and executing parallel equation derivation workflows. Specifically, the PR introduces select_relevant_equations, derive_all_equations, and generate_derivation_graph tools that enable batch processing of equations from documents. The title is concise, clear, and highlights the core innovation without excessive noise. While the naming in the description uses "Analyser + Executer" terminology that differs slightly from the actual tool names, the conceptual accuracy remains intact—the title captures that parallel batch derivation tooling is the main change.
Description Check ✅ Passed The description is directly related to the changeset and accurately describes the two-step workflow being introduced for batch equation processing. It explains the purpose, key features, and use cases for the new tools, matching the core functionality visible in the actual code changes—specifically select_relevant_equations for analysis/categorization and derive_all_equations for parallel execution. The description provides meaningful context about the workflow requirements, output generation, and integration with existing infrastructure. The level of detail is appropriate and the content is on-topic throughout.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ 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 derive_all_equations_parall

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.

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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
axiomatic_mcp/servers/equations/server.py (1)

71-94: Critical: Instructions reference undefined tool.

The instructions reference derive_all_equations_modify in multiple places (lines 80, 89), but this tool is not defined in the codebase.

• Line 80: "If user wants changes: call derive_all_equations_modify"
• Line 89: Tool name included in feedback prompt
• PR objectives mention only analyze and execute tools—no modify tool

Impact: LLM will attempt to call a non-existent tool, causing workflow failures.

Resolution: Remove all references to the modify tool and update workflow instructions to handle user-requested changes differently (e.g., "manually adjust the eligible_equations list").

Apply this diff:

 CRITICAL: For the derive_all_equations workflow, you MUST follow this exact pattern:
 
 1. Call derive_all_equations_analyze
 2. Show results to user and ASK: "Are you satisfied with this categorization, or would you like to make changes?"
 3. Based on user response:
-   - If user wants changes: call derive_all_equations_modify → show results → ASK AGAIN (repeat as needed)
+   - If user wants changes: help them manually adjust the eligible_equations list → show results → ASK AGAIN (repeat as needed)
    - If user approves: IMMEDIATELY call derive_all_equations_execute (don't ask again, just do it)
 4. NEVER skip asking the user for approval after analyze/modify
 5. ALWAYS execute automatically once user approves (this is the final step, no more modifications)
 
-The modify tool is OPTIONAL and should only be called if user explicitly wants changes. Otherwise proceed directly to execute after user approval.
+Manual modifications are OPTIONAL and should only be done if user explicitly wants changes. Otherwise proceed directly to execute after user approval.
     """
     + get_feedback_prompt(
-        "find_functional_form, check_equation, generate_derivation_graph, "
-        "derive_all_equations_analyze, derive_all_equations_modify, derive_all_equations_execute"
+        "find_functional_form, check_equation, generate_derivation_graph, "
+        "derive_all_equations_analyze, derive_all_equations_execute"
     ),
🧹 Nitpick comments (2)
axiomatic_mcp/servers/equations/server.py (2)

403-403: Generic file naming reduces discoverability.

Files are named equation_1.py, equation_2.py, etc., with no indication of their content. Users must open each file to identify which equation it contains.

• Consider deriving filenames from equation content (sanitized LaTeX or first few symbols)
• Or include equation metadata in filename (e.g., equation_1_energy_momentum.py)

Example implementation using equation snippet:

# After line 397
import re

def sanitize_for_filename(equation: str, max_length: int = 30) -> str:
    """Convert equation to safe filename fragment."""
    # Remove LaTeX commands and special chars, keep alphanumerics
    safe = re.sub(r'[^\w\s-]', '', equation)
    safe = re.sub(r'[-\s]+', '_', safe.strip())
    return safe[:max_length].lower()

# Then at line 403:
equation_snippet = sanitize_for_filename(equation)
file_path = output_dir / f"equation_{i}_{equation_snippet}.py"

370-370: Time estimation formula is rough—consider documenting rationale.

Line 370: estimated_minutes = max(2, (num_equations // 10) * 3)

This assumes ~3 minutes per 10 equations, which may not reflect actual API performance. If users see significant deviations, they may lose trust in progress estimates.

• Document the rationale behind the formula
• Or remove specific time estimates and use qualitative descriptions ("a few minutes", "several minutes")

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between 2c5896e and 116878d.

📒 Files selected for processing (1)
  • axiomatic_mcp/servers/equations/server.py (4 hunks)
🔇 Additional comments (3)
axiomatic_mcp/servers/equations/server.py (3)

44-69: LGTM! Helper function follows established patterns.

The implementation correctly mirrors the _get_document_content pattern and handles both file paths and raw code strings appropriately.

Note: The 500-character heuristic for path detection is reasonable but arbitrary—acceptable for practical use cases where real code would exceed this length.


271-324: LGTM! Clean analysis implementation.

The tool correctly:
• Calls the API endpoint for equation categorization
• Formats results in a clear, user-friendly structure
• Returns comprehensive analysis with rationale per equation


250-255: No API format tests found—confirm contract

  • No references to mermaid_text or /equations/compose/derivation-graph in tests/docs
  • Verify the endpoint always returns raw Mermaid (no fences) or consistently includes code fences
  • Then enforce a single convention (strip before wrapping or assume already fenced)

doc_content = await _get_document_content(document)

# Extract just the equation strings from the dict objects
equations_to_derive = [eq.get("equation") for eq in eligible_equations]
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add validation for eligible_equations structure.

Line 364 extracts equation keys without validating that each dict contains this key. If the structure is malformed, this produces a list of None values that fail silently or cause downstream errors.

• Add validation before extraction
• Provide clear error message if structure is invalid

Apply this diff:

         # Extract just the equation strings from the dict objects
+        # Validate structure first
+        for i, eq in enumerate(eligible_equations):
+            if not isinstance(eq, dict) or 'equation' not in eq:
+                raise ToolError(f"Invalid equation structure at index {i}: expected dict with 'equation' key")
+        
         equations_to_derive = [eq.get("equation") for eq in eligible_equations]
📝 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
equations_to_derive = [eq.get("equation") for eq in eligible_equations]
# Extract just the equation strings from the dict objects
# Validate structure first
for i, eq in enumerate(eligible_equations):
if not isinstance(eq, dict) or 'equation' not in eq:
raise ToolError(f"Invalid equation structure at index {i}: expected dict with 'equation' key")
equations_to_derive = [eq.get("equation") for eq in eligible_equations]
🤖 Prompt for AI Agents
In axiomatic_mcp/servers/equations/server.py around line 364, the code blindly
builds equations_to_derive = [eq.get("equation") for eq in eligible_equations]
which can produce None values if eligible_equations is malformed; validate that
eligible_equations is an iterable of dict-like objects and that each item
contains a non-empty "equation" key before extraction, e.g. check type and
presence, collect any invalid entries and either raise a clear ValueError (or
return an HTTP 400 with a descriptive message) listing the offending
indices/items, or filter them out and log a warning so downstream code never
receives None values. Ensure the validation happens immediately before line 364
and that the error message names the field ("equation") and the problematic
items/indices.

Comment on lines 378 to 381
execute_response = AxiomaticAPIClient().post(
"/equations/derive-all/execute",
data={"markdown": doc_content, "eligible_equations": equations_to_derive},
)
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Consider timeout handling for long-running operations.

The API call blocks for 2–10 minutes (per line 332) with no timeout configuration. If the backend hangs or takes longer than expected, the client waits indefinitely.

• Add explicit timeout parameter to the API call
• Handle timeout exceptions gracefully

Apply this diff:

         # Call synchronous execute endpoint (will block until complete)
         execute_response = AxiomaticAPIClient().post(
             "/equations/derive-all/execute",
             data={"markdown": doc_content, "eligible_equations": equations_to_derive},
+            timeout=600,  # 10 minutes max
         )
📝 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
execute_response = AxiomaticAPIClient().post(
"/equations/derive-all/execute",
data={"markdown": doc_content, "eligible_equations": equations_to_derive},
)
# Call synchronous execute endpoint (will block until complete)
execute_response = AxiomaticAPIClient().post(
"/equations/derive-all/execute",
data={"markdown": doc_content, "eligible_equations": equations_to_derive},
timeout=600, # 10 minutes max
)
🤖 Prompt for AI Agents
In axiomatic_mcp/servers/equations/server.py around lines 378 to 381, the
AxiomaticAPIClient().post call that triggers a long-running backend derive
operation must include an explicit timeout (e.g., timeout=300 or other suitable
seconds) and be wrapped in a try/except to handle timeouts; add the timeout
parameter to the post call, catch the client's timeout exception
(requests.exceptions.Timeout or the HTTP client’s TimeoutException depending on
AxiomaticAPIClient implementation), log the timeout with context, and
return/raise a clear error response to avoid hanging the server.

Copy link
Contributor

@a96lex a96lex left a comment

Choose a reason for hiding this comment

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

it looks to me that this applies changes on top of #38. can you please address the review comments there? or change the base branch so reviewing is better

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

♻️ Duplicate comments (2)
axiomatic_mcp/servers/equations/server.py (2)

356-359: Validation for equation structure still missing.

• Line 359: .get("equation") can return None if the key is missing from the dict
• Creates a list with potential None values that will fail downstream
• No validation that relevant_equations is well-formed before extraction

This issue was previously flagged but remains unaddressed.

Apply this diff to add validation:

         doc_content = await _get_document_content(document)

         # Extract just the equation strings from the dict objects
+        # Validate structure first
+        for i, eq in enumerate(relevant_equations):
+            if not isinstance(eq, dict):
+                raise ToolError(f"Invalid equation at index {i}: expected dict, got {type(eq).__name__}")
+            if "equation" not in eq or not eq["equation"]:
+                raise ToolError(f"Invalid equation at index {i}: missing or empty 'equation' field")
+        
         equations_to_derive = [eq.get("equation") for eq in relevant_equations]

373-376: Long-running operation lacks timeout protection.

• Operation blocks for 2-10 minutes (per line 327 description) without timeout
• If backend hangs or exceeds expected duration, client waits indefinitely
• No timeout handling in AxiomaticAPIClient.post() call

This issue was previously flagged but remains unaddressed.

To verify the AxiomaticAPIClient timeout behavior:

#!/bin/bash
# Check if AxiomaticAPIClient respects TIMEOUT constant or allows per-call override
rg -nP -A5 "class AxiomaticAPIClient" axiomatic_mcp/shared/api_client.py
rg -nP -A10 "def post" axiomatic_mcp/shared/api_client.py
🧹 Nitpick comments (8)
axiomatic_mcp/shared/api_client.py (1)

17-21: Consider validating the overridden API URL.

• Environment-provided URLs bypass validation, potentially causing runtime errors downstream
• Malformed URLs or incorrect schemes could fail silently until first request
• Recommend adding basic URL validation (scheme, format) when override is present

Apply this diff to add validation:

         # Allow overriding the API URL for local development
         base_url = os.getenv("AXIOMATIC_API_URL", API_URL)
+        
+        # Validate the base URL format
+        if not base_url.startswith(("http://", "https://")):
+            raise ValueError(f"Invalid AXIOMATIC_API_URL: must start with http:// or https://, got: {base_url}")
axiomatic_mcp/servers/equations/server.py (1)

60-66: Heuristic may misclassify edge cases.

• Line 61: len(code_input) < 500 and "\n" not in code_input could misidentify:

  • Short Python snippets as file paths (e.g., "import sys" is 10 chars, no newlines)
  • Long file paths (> 500 chars) as code strings
    • Consider checking Path(code_input).exists() first before length check
    • Or add explicit parameter to disambiguate

Apply this diff to improve robustness:

     # Check if it's a short string that might be a file path
-    if len(code_input) < 500 and "\n" not in code_input:
-        potential_path = Path(code_input)
-        if potential_path.exists() and potential_path.suffix.lower() == ".py":
+    potential_path = Path(code_input)
+    if potential_path.exists() and potential_path.suffix.lower() == ".py":
-            with Path.open(potential_path, encoding="utf-8") as f:
-                return f.read(), potential_path
+        with Path.open(potential_path, encoding="utf-8") as f:
+            return f.read(), potential_path
ASML_Patent_Comprehensive_Verification_Report.md (3)

663-673: Add language specifiers to code blocks for better rendering.

• Lines 663 and 670: Fenced code blocks lack language identifiers
• Improves syntax highlighting and accessibility

Apply this diff:

-```
+```text
 I₁(k) = ½|E(k)|² + ½|E(-k)|² + |E(k)||E(-k)|cos(φ(k) - φ(-k))
 I₂(k) = ½|E(k)|² + ½|E(-k)|² + |E(k)||E(-k)|cos(φ(k) - φ(-k))
                                                ↑ ERROR - same sign

Corrected:
- +text
I₁(k) = ½|E(k)|² + ½|E(-k)|² + |E(k)||E(-k)|cos(φ(k) - φ(-k))
I₂(k) = ½|E(k)|² + ½|E(-k)|² - |E(k)||E(-k)|cos(φ(k) - φ(-k))
↑ CORRECTION - opposite sign


1098-1100: Format URLs as proper markdown links.

• Bare URLs should be wrapped in angle brackets or converted to markdown links
• Improves rendering and accessibility

Apply this diff:

 ### Software and Tools
-6. SymPy Development Team, "SymPy: Python library for symbolic mathematics," Version 1.12, https://www.sympy.org
+6. SymPy Development Team, "SymPy: Python library for symbolic mathematics," Version 1.12, <https://www.sympy.org>
 7. Python Software Foundation, "Python Language Reference," version 3.11
-8. Axiomatic AI, "Mathematical Verification Platform," https://axiomatic.ai
+8. Axiomatic AI, "Mathematical Verification Platform," <https://axiomatic.ai>

1125-1125: Use proper heading syntax instead of bold emphasis.

• Line 1125: Bold text mimics a heading but isn't semantically marked as such
• Use markdown heading for better document structure

Apply this diff:

 ---

-**End of Report**
+## End of Report
ASML_Presentation_Deck.md (3)

28-40: Add language specifiers to code blocks.

• Lines 28-40: ASCII art diagram lacks language specifier
• Use text or yaml for better rendering

Apply this diff:

-```
+```text
 Stage 1: BULK ANALYSIS
 ├─ 1 comprehensive verification call
 ├─ 10 equation categories analyzed

55-68: Add language specifiers to equation code blocks.

• Multiple code blocks displaying equations lack language identifiers
• Lines 55-68, 574-591: Use text for plain equation formatting

Example for lines 55-60:

 **As Written in Patent** ❌
-```
+```text
 I₁(k) = ½[E(k)]² + ½[E(-k)]² + [E(k)][E(-k)]cos(Δφ)
 I₂(k) = ½[E(k)]² + ½[E(-k)]² + [E(k)][E(-k)]cos(Δφ)

Apply similar changes to other equation blocks throughout the document.

Also applies to: 574-591


169-174: Add language specifiers to ASCII art and data blocks.

• Multiple visualization and data blocks lack language identifiers
• Lines 169-174 (progress bars), 215-223 (statistics), etc.
• Use text for better rendering consistency

Also applies to: 215-223, 347-353, 386-394, 441-460, 532-534

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between 116878d and 49b3830.

📒 Files selected for processing (4)
  • ASML_Patent_Comprehensive_Verification_Report.md (1 hunks)
  • ASML_Presentation_Deck.md (1 hunks)
  • axiomatic_mcp/servers/equations/server.py (4 hunks)
  • axiomatic_mcp/shared/api_client.py (1 hunks)
🧰 Additional context used
🪛 markdownlint-cli2 (0.18.1)
ASML_Patent_Comprehensive_Verification_Report.md

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

(MD040, fenced-code-language)


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

(MD040, fenced-code-language)


1098-1098: Bare URL used

(MD034, no-bare-urls)


1100-1100: Bare URL used

(MD034, no-bare-urls)


1125-1125: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

ASML_Presentation_Deck.md

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

(MD040, fenced-code-language)


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

(MD040, fenced-code-language)


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

(MD040, fenced-code-language)


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

(MD040, fenced-code-language)


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

(MD040, fenced-code-language)


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

(MD040, fenced-code-language)


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

(MD040, fenced-code-language)


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

(MD040, fenced-code-language)


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

(MD040, fenced-code-language)


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

(MD040, fenced-code-language)


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

(MD040, fenced-code-language)


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

(MD040, fenced-code-language)


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

(MD040, fenced-code-language)


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

(MD040, fenced-code-language)

🔇 Additional comments (2)
axiomatic_mcp/servers/equations/server.py (2)

182-263: LGTM!

• Proper use of helper function for code extraction
• Multipart/form-data encoding correctly configured
• Smart handling of pre-wrapped Mermaid code blocks
• File output path logic covers both file input and string input cases
• Error handling is appropriate


266-319: LGTM!

• Clear separation of concerns (analysis vs execution)
• Explicit instructions requiring user approval before proceeding
• Safe dict access using .get() with defaults
• Proper formatting for user-facing output
• Error handling is appropriate

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (2)
axiomatic_mcp/servers/equations/server.py (2)

356-362: Unresolved: Validate equation structure before extraction.

• Line 359 blindly extracts "equation" keys without validation
• If relevant_equations contains malformed dicts (missing "equation" key), this produces None values that cause silent failures downstream
• This issue was flagged in a previous review and remains unaddressed

Apply this diff to validate structure:

         doc_content = await _get_document_content(document)
 
+        # Validate structure before extraction
+        for i, eq in enumerate(relevant_equations):
+            if not isinstance(eq, dict):
+                raise ToolError(f"Invalid equation at index {i}: expected dict, got {type(eq).__name__}")
+            if "equation" not in eq or not eq["equation"]:
+                raise ToolError(f"Invalid equation at index {i}: missing or empty 'equation' key")
+        
         # Extract just the equation strings from the dict objects
         equations_to_derive = [eq.get("equation") for eq in relevant_equations]

373-376: Unresolved: Add timeout for long-running API call.

• This synchronous API call blocks for 2-10 minutes (per line 327) with no timeout
• If the backend hangs or exceeds expected duration, the client waits indefinitely
• This issue was flagged in a previous review and remains unaddressed

Apply this diff to add timeout handling:

         # Call synchronous execute endpoint (will block until complete)
         execute_response = AxiomaticAPIClient().post(
             "/equations/derive/all/markdown",
             data={"markdown": doc_content, "relevant_equations": equations_to_derive},
+            timeout=600,  # 10 minutes max, covers stated 2-10 minute range
         )
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between 49b3830 and f03bacb.

📒 Files selected for processing (1)
  • axiomatic_mcp/servers/equations/server.py (4 hunks)
🔇 Additional comments (4)
axiomatic_mcp/servers/equations/server.py (4)

44-69: LGTM: Clean helper implementation.

• Follows the established pattern from _get_document_content
• Validates file existence and extension appropriately
• Returns both code content and optional file path for downstream use


182-263: LGTM: Well-structured visualization tool.

• Correctly uses the _get_python_code helper
• Multipart/form-data encoding via files parameter is appropriate for the backend endpoint
• Smart handling of pre-wrapped vs. unwrapped mermaid text (lines 245-250)
• Sensible output file naming relative to input


384-427: LGTM: File generation and result formatting.

• Output directory creation with mkdir(parents=True, exist_ok=True) is appropriate
• File writing includes equation context in docstring (line 396)
• Clear separation of successful vs. failed derivations
• Summary formatting provides actionable information with file links and error messages


71-89: LGTM: Clear workflow instructions.

• Structured 2-step workflow is well-documented with explicit approval gate
• Instructions emphasize critical requirement for user approval before execution
• Feedback prompt correctly extended to include new tools: generate_derivation_graph, select_relevant_equations, derive_all_equations

Comment on lines +289 to +299
try:
doc_content = await _get_document_content(document)

analysis_response = AxiomaticAPIClient().post(
"/equations/select/markdown",
data={"markdown": doc_content},
)

relevant_equations = analysis_response.get("relevant_equations", [])
irrelevant_equations = analysis_response.get("irrelevant_equations", [])
summary = analysis_response.get("summary", "")
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Validate API response structure before iteration.

• Lines 297-298 extract lists from the response without validation
• If the API returns unexpected types (e.g., None, dict), the iteration at lines 305-314 will fail
• Add type checks and provide clear error messages

Apply this diff:

         analysis_response = AxiomaticAPIClient().post(
             "/equations/select/markdown",
             data={"markdown": doc_content},
         )
 
         relevant_equations = analysis_response.get("relevant_equations", [])
         irrelevant_equations = analysis_response.get("irrelevant_equations", [])
         summary = analysis_response.get("summary", "")
+        
+        # Validate response structure
+        if not isinstance(relevant_equations, list):
+            raise ToolError(f"Invalid response: relevant_equations must be a list, got {type(relevant_equations).__name__}")
+        if not isinstance(irrelevant_equations, list):
+            raise ToolError(f"Invalid response: irrelevant_equations must be a list, got {type(irrelevant_equations).__name__}")
📝 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
try:
doc_content = await _get_document_content(document)
analysis_response = AxiomaticAPIClient().post(
"/equations/select/markdown",
data={"markdown": doc_content},
)
relevant_equations = analysis_response.get("relevant_equations", [])
irrelevant_equations = analysis_response.get("irrelevant_equations", [])
summary = analysis_response.get("summary", "")
try:
doc_content = await _get_document_content(document)
analysis_response = AxiomaticAPIClient().post(
"/equations/select/markdown",
data={"markdown": doc_content},
)
relevant_equations = analysis_response.get("relevant_equations", [])
irrelevant_equations = analysis_response.get("irrelevant_equations", [])
summary = analysis_response.get("summary", "")
# Validate response structure
if not isinstance(relevant_equations, list):
raise ToolError(f"Invalid response: relevant_equations must be a list, got {type(relevant_equations).__name__}")
if not isinstance(irrelevant_equations, list):
raise ToolError(f"Invalid response: irrelevant_equations must be a list, got {type(irrelevant_equations).__name__}")
🤖 Prompt for AI Agents
In axiomatic_mcp/servers/equations/server.py around lines 289 to 299, the code
pulls "relevant_equations", "irrelevant_equations", and "summary" from the API
response without validating types; add validation after receiving
analysis_response: ensure analysis_response is a dict, confirm
relevant_equations and irrelevant_equations are lists (if not, either coerce to
empty list or raise/log a clear ValueError including the raw response), and
ensure summary is a string (coerce to "" if not); return or raise a descriptive
error if the structure is unexpected so the later iteration (lines ~305-314)
cannot fail silently.

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.

3 participants