Skip to main content
Glama

SymKit

Step-by-step symbolic math for AI agents: derive, verify, and certify formulas over SymPy, with full provenance.

License Python MCP Tests

English | 简体中文

What is SymKit?

An MCP server that lets AI agents do exact symbolic math through conversation. Built on SymPy, it combines known formulas into new ones, records every derivation step, and verifies each result symbolically and dimensionally — instead of leaving calculations as uncheckable LLM prose.

LLM alone

With SymKit

❌ "The answer is approximately..."

✅ "The exact expression is ..."

❌ Recalculating from scratch to double-check

✅ Every step is recorded and independently verifiable

❌ "I think the units work out"

✅ Dimensional analysis checks every result

❌ "Where did this formula come from?"

✅ Full provenance: base formulas + derivation steps

Works for physics, engineering, chemistry, biology, economics — any domain where formulas are combined and transformed.

Related MCP server: Symath-MCP

Core capabilities

Capability

What it means

Main tools

Derive

Combine base formulas into new ones

derive, intent_execute, math

Control

Inspect, annotate, and roll back every step

session_*

Verify

Symbolic equivalence + dimensional analysis

session_verify_*, assume

Ship

Export to Python, LaTeX, Markdown, or SymPy script

generate_output

Example — deriving the angular frequency of a simple harmonic oscillator from F = -kx and F = m·a:

1. Load the two base formulas and substitute → m·d²x/dt² = -kx
2. Solve the ODE → x(t) = A·cos(ωt + φ),  ω = √(k/m)
3. Verify by substitution: d²x/dt² = -ω²x  ✓
4. Store the result with its full derivation history

Tools

47 MCP tools across 10 categories. Most work flows through a few high-level tools; power users can drive each step individually.

Category

Count

Highlights

Unified Math

1

math — 33 symbolic operations: calculus, ODEs, matrices, vector analysis, integral transforms, dimensional analysis

Session Management

15

session_start, session_record_step, session_rollback, session_complete

Verification

5

session_verify_step, session_verify_session, session_certify, lean_status

Assumptions

7

assume, unassume, check_assumption_conflicts

Formula Library

8

formula_search, formula_get, formula_add, formula_promote

Symbol Semantics

4

register_symbol, lookup_symbol, check_symbol_conflicts

Output

1

generate_output (markdown_report / latex / python / sympy_script)

Orchestration

3

derive, intent_execute, list_patterns

Meta

2

tool_categories, tool_recommend

Execution

1

python_exec — one-shot Python/sympy snippets in an isolated subprocess

Derivation sessions

A derivation is a chain of immutable, verifiable steps. Expressions are never edited in place — if something goes wrong, session_rollback to the last good state and continue, keeping the whole derivation reproducible. Every step stores its inputs, outputs, notes, assumptions, and SymPy command, persisted as JSON under the data directory.

Formula library

Formulas live in YAML files backed by a persistent SQLite FTS5 index — deterministic, offline, instant. Entries are ranked by tier:

Tier

Source

Boost

seed

Bundled read-only formulas (Reynolds number, Navier–Stokes, …)

+0.10

curated

formula_add, or promoted via formula_promote

+0.15

staging

Session output from session_complete(auto_save=True)

+0.00

formula_search("Navier-Stokes", domain="fluid_dynamics")
formula_get("ns_incompressible", load_into_session=True)
math("simplify", "...", session=True)
session_complete(description="Incompressible NS momentum equation")

Search covers names, aliases (Chinese works: 雷诺数 → Reynolds number), tags, domains, descriptions, and expression text. Session output lands in staging with a deterministic id and is deduplicated; promote keepers with formula_promote, inspect tiers with formula_stats, rebuild after hand-editing YAML with formula_reindex. The index (<data dir>/formulas/index.sqlite3) is a cache — deleting it is always safe. Optional external sources (source="wikidata" | "scipy" | "biomodels") degrade gracefully offline.

Lean 4 kernel certification (optional)

session_certify() re-proves eligible algebraic-equality steps of the current session (simplify / expand / factor / combine in the rational fragment) with the Lean 4 + Mathlib kernel, using ring / field_simp. Results are attached under each step's details.lean; existing verification verdicts are never modified, and unproven only means the automation could not close the goal — not that the step is wrong. A step whose input and output are identical (x = x, 0 = 0) is reported as trivial and excluded from the proven count: the kernel discharges it instantly but validates no algebra. No extra Python packages are required.

Call lean_status() first if you are unsure whether the backend is installed — it is read-only (never runs Lean, never downloads) and reports the resolved toolchain, Mathlib, and workspace paths, where each was resolved from, which layer is missing, and the exact next command. Do not probe the filesystem or run lake --version yourself: a missing directory is not evidence, and Mathlib lives under <data dir>/lean-workspace/.lake/packages/mathlib.

Setup

# One-time: install elan + Lean 4 + prebuilt Mathlib (~1–2 GB download, needs network)
symkit-lean-setup --yes

# Optionally pin a Lean version instead of stable
symkit-lean-setup --yes --toolchain v4.24.0

Configuration knobs:

  • Data directory: the Lean workspace is installed to <data dir>/lean-workspace. Set SYMKIT_DATA_DIR before running the setup (and the server) to relocate it.

  • Toolchain location: lake is discovered from ELAN_HOME/bin, then PATH, then ~/.elan/bin. Point ELAN_HOME at an existing elan install to reuse it — it takes precedence, so a default ~/.elan/bin/lake on PATH cannot shadow it. Certification also checks that the selected lake already owns the Lean version pinned in the workspace; otherwise it reports lean_available: false with a directing reason instead of starting a fresh toolchain download.

  • Proxies: if the download stalls or fails behind a corporate proxy, export HTTP_PROXY / HTTPS_PROXY before running the setup — the elan installer does not read the Windows system proxy settings.

  • Readiness check: re-running session_certify() reports lean_available: true once the toolchain and the .symkit-lean-ready stamp are in place.

Usage notes: session_certify() requires an active session, and steps that divide by a variable need an explicit assertion that the denominator is nonzero. Supply it at certify time with session_certify(assumptions={"x": {"nonzero": True}}) (or assumptions="x nonzero"), or register it beforehand with assume({"x": "nonzero"}). Without a toolchain, everything else in SymKit is unchanged.

Installation

Requirements: Python 3.10+, an MCP-compatible client (Claude Desktop, Claude Code, Cherry Studio, …), and uv or pip.

uv tool install symkit-mcp
symkit-mcp --version

uvx symkit-mcp runs the latest release on the fly without installing.

Option B — pip

pip install symkit-mcp

(pipx install symkit-mcp for an isolated environment.)

Option C — from source

git clone https://github.com/LBurny/symkit-mcp.git
cd symkit-mcp
uv sync --all-extras
uv run symkit-mcp

Data directory

Runtime data lives per-user (via platformdirs): ~/.local/share/symkit/ on Linux, %LOCALAPPDATA%\symkit on Windows, ~/Library/Application Support/symkit on macOS. Set SYMKIT_DATA_DIR to override — e.g. per project via the MCP server env block, to isolate sessions and formula libraries. Seed formulas ship read-only inside the package; user formulas from formula_add go to a writable overlay that overrides seeds by id; session-derived formulas go to <data dir>/formulas/derived/.

Connect your client

Add an mcpServers entry (Claude Desktop: claude_desktop_config.json; Cherry Studio: settings panel).

Installed on PATH (uv tool / pip / pipx):

{ "mcpServers": { "symkit": { "command": "symkit-mcp", "args": [] } } }

Without installing (uvx pulls and caches the latest release):

{ "mcpServers": { "symkit": { "command": "uvx", "args": ["symkit-mcp"] } } }

From a source checkout:

{
  "mcpServers": {
    "symkit": {
      "command": "uv",
      "args": ["run", "--no-sync", "--directory", "<local-path>",
               "python", "-m", "symkit_mcp.server"]
    }
  }
}

Windows: if the client reports "command not found", use an absolute path, e.g. "C:/Users/you/AppData/Local/uv/tools/symkit-mcp/Scripts/symkit-mcp.exe".

Architecture

src/
├── symkit/               # Core domain library (no MCP dependency)
│   ├── domain/           # Entities, derivation engine, verifier contracts
│   ├── application/      # Use cases
│   └── infrastructure/   # SymPy engine, Lean checker, persistence, adapters
└── symkit_mcp/           # MCP server layer (FastMCP) + 47 tools
formulas/                 # Seed formula library (source tree)
tests/                    # 1656 tests

Domain-driven design: the core is independent of MCP and SymPy, engines are pluggable via protocols, and formulas/sessions persist as readable YAML/JSON.

Development

uv run pytest          # full test suite
uv run ruff check src/ tests/
uv run mypy src/
uv run symkit-mcp      # dev server

Learn more

Acknowledgments

SymKit builds on nsforge-mcp, which pioneered the neurosymbolic formula-derivation approach, and can be used alongside sympy-mcp, a general-purpose SymPy MCP service.

License

Apache 2.0.

Available Tools

41 tools
assumeB
    Set symbolic assumptions (affecting subsequent math() calculations)

    Assumptions are recorded in MathContext and passed to SymPy, and also written
    to the current session's multi-level assumption engine (session level).

    Args:
        variables: Mapping from variable to properties
                   e.g., {"x": "positive real", "n": "integer"}

    Returns:
        All current assumptions

    Example:
        assume({"x": "positive", "t": "real"})
        # Afterwards, math("simplify", "sqrt(x**2)") returns x instead of Abs(x)
    

Inputs: variables (required). Returns: object

assume_for_stepB
    📋 Set assumptions for the current derivation step only.

    Args:
        *args: Alternating symbol and property strings
               (e.g., "x", "positive", "y", "real")

    Returns:
        Updated step-level assumptions and any conflicts
    

Inputs: args (required). Returns: object

check_assumption_conflictsA
    ⚠️ Detect conflicts across all assumption levels.

    A conflict occurs when a symbol is assigned contradictory properties
    (e.g., both positive and negative).

    Returns:
        Conflict report
    

Inputs: no named parameters. Returns: object

check_symbol_conflictsA
    ⚠️ Check for ambiguous symbols in the current session.

    A conflict occurs when the same symbol name has multiple meanings
    or appears in multiple domains.

    Returns:
        Conflict report with suggested disambiguation
    

Inputs: no named parameters. Returns: object

clear_step_assumptionsA
    🧹 Clear step-level assumptions.

    Useful when moving to a new sub-derivation or branch.

    Returns:
        Operation result
    

Inputs: no named parameters. Returns: object

deriveA
    🚀 High-level derivation entry point — start a derivation from a goal.

    Args:
        goal: Natural-language description of what to derive
        given: Base formulas or expressions to load as starting points
        assumptions: List of assumptions (e.g., ["rho is positive"])
        domain: Math/physics domain (e.g., "fluid_dynamics")
        pattern: Derivation pattern. If None, auto-selected from goal.
        target_expression: Expected final SymPy expression (optional)
        auto_load: If True, load the given formulas into the session
        external_sources: External formula sources to include in recommendations
            (e.g., ["wikidata", "biomodels", "scipy"] or ["all"]).
            Defaults to all sources; network failures are silently ignored.

    Returns:
        Session info + goal + derivation plan + recommended formulas + next steps
    

Inputs: goal (required), given, domain, pattern, +4 more. Returns: object

formula_addA

Add or update a formula in the local library.

    This lets you (and the LLM) extend the local formula collection manually.
    Formulas are persisted as YAML files under ``formulas/library/<category>/``.

    Args:
        id: Unique identifier for the formula (e.g., "custom_drag_force").
           Used as the file name and lookup key.
        name: Human-readable formula name.
        sympy_str: SymPy-compatible expression, e.g. "F_d == 1/2 * rho * v**2 * C_d * A".
        latex: LaTeX representation, e.g. "F_d = \frac{1}{2} \rho v^2 C_d A".
        variables: Mapping of symbol names to metadata, e.g.
                   {"rho": {"description": "density", "unit": "kg/m^3"}}.
        domain: Optional domain tag (e.g., "fluid_dynamics").
        category: Optional category folder name (e.g., "fluid_dynamics").
        description: Optional longer description of the formula.
        aliases: Optional list of alternative names.
        tags: Optional list of tags.
        references: Optional list of references / URLs.
        library_path: Optional custom library directory. Defaults to ``formulas/library``.

    Returns:
        {
            "success": true,
            "formula_id": "custom_drag_force",
            "file_path": "formulas/library/fluid_dynamics/custom_drag_force.yaml",
            "message": "Formula added to local library."
        }

    Example:
        formula_add(
            id="custom_drag_force",
            name="Drag force",
            sympy_str="F_d == 1/2 * rho * v**2 * C_d * A",
            latex="F_d = \frac{1}{2} \rho v^2 C_d A",
            domain="fluid_dynamics",
            category="fluid_dynamics",
            description="Drag force on a body in a fluid.",
            variables={
                "F_d": {"description": "drag force", "unit": "N"},
                "rho": {"description": "density", "unit": "kg/m^3"},
                "v": {"description": "velocity", "unit": "m/s"},
                "C_d": {"description": "drag coefficient"},
                "A": {"description": "reference area", "unit": "m^2"}
            },
            aliases=["drag force", "fluid drag"],
            tags=["drag", "force"],
        )
    

Inputs: id (required), name (required), latex (required), sympy_str (required), +8 more. Returns: object

formula_categoriesA

List available formula categories.

    Get the categories currently present in the local formula library.

    Args:
        source: Data source
               - "local": Local YAML library (default)
               - "all": Local + legacy sources
               - "wikidata", "biomodels", "scipy": Legacy source only

    Returns:
        {
            "success": true,
            "categories": {
                "local": ["fluid_dynamics", "mechanics", "thermodynamics"],
                "wikidata": [...]
            }
        }
    

Inputs: source. Returns: object

formula_getA

Get detailed formula information from the local library.

    Args:
        formula_id: Formula identifier (e.g., "reynolds_number")
        source: Data source
               - "local": Local YAML library (default, recommended)
               - "wikidata", "biomodels", "scipy": Legacy sources
        load_into_session: If True, load the formula into the current derivation session.
                          Requires an active session started with session_start().

    Returns:
        {
            "success": true,
            "formula": {
                "id": "reynolds_number",
                "name": "Reynolds number",
                "latex": "Re = \frac{\rho v L}{\mu}",
                "sympy_str": "rho * v * L / mu",
                "variables": {...},
                "source": "local"
            },
            "session_loaded": true
        }

    Example:
        # Get a local formula
        formula_get("reynolds_number")

        # Get and immediately load into a derivation session
        formula_get("reynolds_number", load_into_session=True)
    

Inputs: formula_id (required), source, load_into_session. Returns: object

generate_derivation_reportB
    Generate a complete derivation report in Markdown.

    Args:
        problem: Problem description
        given: Given parameters {"symbol": "value with unit"}
        steps: Derivation steps
        results: Final results {"symbol": "expression"}
        verification: Optional verification status

    Returns:
        Markdown report
    

Inputs: given (required), steps (required), problem (required), results (required), +1 more. Returns: object

generate_latex_derivationA
    Generate LaTeX documentation for a derivation.

    Args:
        title: Derivation title
        steps: List of {"description": str, "latex": str}
        final_result: Final result in LaTeX

    Returns:
        LaTeX document string
    

Inputs: steps (required), title (required), final_result (required). Returns: object

generate_python_functionA
    Generate a Python function from VERIFIED derivation steps.

    ═══════════════════════════════════════════════════════════════════════
    ⚠️ PREREQUISITE: All expressions must be verified with SymPy-MCP first!
    ═══════════════════════════════════════════════════════════════════════

    Correct workflow:
    1. Use SymPy-MCP to derive and verify each expression
    2. Use print_latex_expression() to show results to user
    3. User confirms the derivation is correct
    4. Call this tool with the verified expressions

    The generated code assembles the provided expressions into a Python
    function; it does not perform new symbolic calculations. The expressions
    must already be verified before calling this tool.

    Args:
        name: Function name (e.g., "calculate_seatbelt_tension")
        description: Function docstring description
        parameters: List of {"name": str, "type": str, "description": str}
        steps: List of {"description": str, "expression": str, "result_var": str}
        return_vars: Variables to return

    Returns:
        dict with keys ``success``, ``code`` (the generated Python function),
        ``function_name``, ``parameters``, and ``returns``.

    Example:
        generate_python_function(
            name="calculate_tension",
            description="Calculate seatbelt tension from collision",
            parameters=[
                {"name": "M1", "type": "float", "description": "Vehicle 1 mass (kg)"},
                {"name": "M2", "type": "float", "description": "Vehicle 2 mass (kg)"},
                {"name": "v", "type": "float", "description": "Initial velocity (m/s)"},
                {"name": "m", "type": "float", "description": "Person mass (kg)"},
                {"name": "k", "type": "float", "description": "Seatbelt constant (N/m)"},
            ],
            steps=[
                {"description": "Final velocity after collision",
                 "expression": "M1 * v / (M1 + M2)",
                 "result_var": "v_f"},
                {"description": "Velocity change",
                 "expression": "v - v_f",
                 "result_var": "delta_v"},
                {"description": "Maximum tension",
                 "expression": "delta_v * sqrt(m * k)",
                 "result_var": "T_max"},
            ],
            return_vars=["v_f", "delta_v", "T_max"]
        )
    

Inputs: name (required), steps (required), parameters (required), description (required), +1 more. Returns: object

generate_sympy_scriptA
    Generate a standalone SymPy script for a computation.

    This generates a complete, runnable Python script that can be
    executed independently to reproduce the derivation.

    Args:
        expressions: List of {"name": str, "expr": str, "description": str}
        operations: List of operations to perform
            {"op": "simplify|solve|diff|integrate", "input": str, ...}

    Returns:
        Complete Python script

    Example:
        generate_sympy_script(
            expressions=[
                {"name": "momentum", "expr": "m1*v1 + m2*v2", "description": "Total momentum"},
            ],
            operations=[
                {"op": "solve", "input": "momentum = (m1+m2)*v_f", "for": "v_f"},
            ]
        )
    

Inputs: operations (required), expressions (required). Returns: object

intent_executeA
    🎯 Natural-language intent router — map a request to the right tool chain.

    Understands common math/derivation intents and returns the recommended
    tool(s) to call. The agent can then execute the recommended tool(s) directly.

    Args:
        intent: Natural language request
                (e.g., "derive NS equations", "simplify this", "verify derivative", "solve for x")
        expression: Optional expression to operate on
        variable: Optional variable for differentiation/solving
        session: Whether to use session-based derivation (default True)

    Returns:
        intent_type, recommended tool chain, and examples

    Example:
        intent_execute("derive the temperature corrected elimination rate",
                       expression="C0 * exp(-k*t)")
    

Inputs: intent (required), session, variable, expression. Returns: object

list_assumptionsA
    📐 List assumptions at a specific level or merged across all levels.

    Args:
        level: "global", "domain", "session", "step", or None for merged

    Returns:
        Assumptions at the requested level
    

Inputs: level. Returns: object

list_domain_symbolsB
    📋 List default symbols for a given domain.

    Args:
        domain: Domain name

    Returns:
        List of symbols with meanings and units
    

Inputs: domain. Returns: object

list_patternsA
    📋 List all available derivation patterns.

    Returns:
        Descriptions, typical steps, and suggested operations for each pattern.
    

Inputs: no named parameters. Returns: object

lookup_symbolB
    🔍 Look up the semantic meaning of a symbol.

    Args:
        name: Symbol name
        domain: Optional domain to prefer

    Returns:
        Symbol meaning and all known definitions
    

Inputs: name (required), domain. Returns: object

mathA
    Run mathematical operations (unified Mathematica-style tool)

    ═══════════════════════════════════════════════════════════════════════
    SymKit's core tool — supports ~25 mathematical operations.
    One tool handles derivation, calculation, solving, and transformation.
    ═══════════════════════════════════════════════════════════════════════

    **Supported operations (operation):**

    | Category | Operation | Description |
    |------|------|------|
    | Parse | `parse` | Parse expression and extract symbols |
    | Simplify | `simplify` | General simplification |
    | | `expand` | Expand polynomial |
    | | `factor` | Factorization |
    | | `collect` | Collect like terms (requires variable) |
    | | `cancel` | Cancel rational function |
    | | `apart` | Partial fraction expansion (requires variable) |
    | | `together` | Combine over common denominator |
    | | `trigsimp` | Trigonometric simplification |
    | | `powsimp` | Power simplification |
    | | `radsimp` | Radical simplification |
    | | `combsimp` | Combinatorial simplification |
    | Solve | `solve` | Solve for variable (requires variable) |
    | Substitute | `substitute` | Substitute variables (requires substitution dict) |
    | Calculus | `diff` | Differentiate (requires variable; order optional) |
    | | `integrate` | Integrate (variable, lower/upper optional) |
    | | `limit` | Limit (variable, point, direction) |
    | | `series` | Series expansion (variable, point, order) |
    | ODE | `dsolve` | Solve ODE (variable=function name, with_respect_to=independent variable) |
    | Vector | `gradient` | Gradient (variable="x,y,z" comma-separated coordinates) |
    | | `divergence` | Divergence |
    | | `curl` | Curl |
    | | `laplacian` | Laplacian |
    | Matrix | `det` | Determinant |
    | | `inv` | Inverse matrix |
    | | `eigenvals` | Eigenvalues |
    | | `eigenvects` | Eigenvectors |
    | Transform | `laplace` | Laplace transform (variable=time, with_respect_to=s) |
    | | `ilaplace` | Inverse Laplace transform (variable=s, with_respect_to=t) |
    | | `fourier` | Fourier transform |
    | | `ifourier` | Inverse Fourier transform |

    Args:
        operation: Operation name (see table above)
        expression: Mathematical expression (SymPy or LaTeX format)
        variable: Differentiation/integration/solving variable (for vector operations can be comma-separated like "x,y,z")
        with_respect_to: Second variable (independent variable for ODE, target variable for transforms)
        substitution: Substitution mapping {"var": "replacement", ...}
        point: Limit point / series expansion point (default "0")
        direction: Limit direction "+-", "+", "-"
        order: Differentiation order / number of series terms (default 1)
        lower: Definite integral lower bound
        upper: Definite integral upper bound
        assumptions: Symbolic assumptions ["x is positive", "t is real"]
        method: Simplification method "auto", "trig", "radical", "expand_then_simplify"
        session: True=record to derivation session, False=stateless computation
        description: Description of this step (used when recording to session)
        notes: Human insight (used when recording to session)

    Returns:
        Result dict containing expression, latex, operation

    Examples:
        # Stateless quick calculation
        math("diff", "x**3", variable="x")
        → {"expression": "3*x**2", "latex": "3 x^{2}"}

        # Substitute
        math("substitute", "m*a", substitution={"m": "2", "a": "9.8"})
        → {"expression": "19.6", ...}

        # Laplace transform
        math("laplace", "exp(-k*t)", variable="t", with_respect_to="s")
        → {"expression": "1/(k + s)", ...}

        # Vector calculus
        math("gradient", "x**2 + y**2 + z**2", variable="x,y,z")
        → gradient in vector form

        # Solve ODE
        math("dsolve", "diff(y,t) - k*y", variable="y", with_respect_to="t")
    

Inputs: operation (required), expression (required), lower, notes, +11 more. Returns: object

register_symbolA
    🏷️ Register the semantic meaning of a symbol in the current session.

    Args:
        name: Symbol name (e.g., "R", "hbar", "k")
        meaning: Human-readable meaning (e.g., "Universal gas constant")
        domain: Domain this meaning belongs to
        unit: Default physical unit
        assumptions: Common assumptions (e.g., ["positive"])
        aliases: Alternative names for this symbol

    Returns:
        Registration result
    

Inputs: name (required), meaning (required), unit, domain, +2 more. Returns: object

session_abortA
    Suspend the current derivation (session is saved to disk)

    Returns:
        Operation result
    

Inputs: no named parameters. Returns: object

session_add_noteB
    Add a human knowledge note to the derivation (non-computational step)

    Args:
        note: Note content
        note_type: "assumption", "limitation", "observation",
                   "correction", "interpretation", "application", "reference"
        related_variables: Related variables

    Returns:
        Record result
    

Inputs: note (required), note_type, related_variables. Returns: object

session_completeC
    Complete the derivation and auto-save

    Args:
        description: Formula description (physical/mathematical meaning)
        application_context: Usage context (when to use this formula)
        assumptions: Derivation assumptions
        limitations: Usage limitations
        references: References
        tags: Tags
        auto_save: Whether to auto-save (default True)
        require_target_match: If True, the derivation will only be saved as
            completed when the current expression matches the goal target.
            Default is False for backward compatibility, but a warning is
            still returned if the target is not reached.

    Returns:
        Complete derivation record
    

Inputs: tags, auto_save, references, assumptions, +4 more. Returns: object

session_explainA
    🗣️ Explain the current derivation in natural language.

    Generates a human-readable summary of the derivation so far, including:
    - The overall goal (session name/description)
    - What formulas were loaded
    - What operations were performed and why
    - Key assumptions and limitations recorded
    - The current result

    Args:
        level: Detail level — "short", "medium" (default), or "detailed"
        focus: Optional aspect to focus on ("assumptions", "steps", "result")

    Returns:
        Natural-language summary and structured metadata
    

Inputs: focus, level. Returns: object

session_get_stepsA

Return all recorded steps in the current session.

    Returns:
        List of steps with metadata.
    

Inputs: no named parameters. Returns: object

session_listA

List all saved derivation sessions.

Inputs: no named parameters. Returns: object

session_load_formulaA

Load a formula into the current session.

    Correct workflow for derivation from an external source:
        1. formula_search("<concept>", domain="<domain>")
        2. formula_get(result["id"], source=result["source"], load_into_session=True)
        3. math(..., session=True) to derive or transform
        4. session_complete(...) to finalize and save

    Args:
        expression: Formula or expression string (e.g. "rho * v * L / mu" or
                   a LaTeX string). For formulas loaded via formula_get, you can
                   pass formula["sympy_str"] or formula["latex"].
        formula_id: Optional custom formula ID.
        source: Source label (e.g. "user_input", "scipy", "wikidata").

    Returns:
        Load result with formula_id, expression and LaTeX.
    

Inputs: expression (required), source, formula_id. Returns: object

session_record_stepA

Manually record a derivation step (e.g. a result computed outside the tool).

    The ``expression`` argument is parsed through the unified parser, which
    supports SymPy strings, natural equations (``A = B``), Leibniz derivative
    notation (``dX/dY``), Greek/Unicode math, and LaTeX.

    Args:
        expression: Result expression string (SymPy or LaTeX).
        description: Human-readable step description.
        operation: Ignored. Manual steps are always recorded as OperationType.CUSTOM
            to prevent a user-supplied operation label (e.g. "simplify") from being
            falsely reported as automatically verified.
        notes: Human insight / observation.
        assumptions: Step-specific assumptions.
        limitations: Step-specific limitations.

    Returns:
        Recorded step details.
    

Inputs: expression (required), description (required), notes, operation, +2 more. Returns: object

session_resumeC
    Resume a suspended derivation session

    Args:
        session_id: Session ID

    Returns:
        Session status
    

Inputs: session_id (required). Returns: object

session_rollbackA
    Roll back to the specified step

    Keep steps up to and including the specified step, and delete steps after it.
    After rolling back, you can continue the derivation from that step (taking a different path).

    Args:
        to_step: Step number to roll back to (1-based); 0 = clear all

    Returns:
        Rollback result
    

Inputs: to_step (required). Returns: object

session_set_goalA

Set a natural-language derivation goal for the current session.

    Args:
        goal: Natural-language goal text.
        target_expression: Optional explicit target expression (e.g.
            "v = sqrt(2*G*M/R)").  When provided, it overrides the
            automatically-extracted target expression.

    Returns:
        Parsed goal and session status.
    

Inputs: goal (required), target_expression. Returns: object

session_showA
    Show the current derivation state and formula

    ⚠️ Must be called after each derivation operation to show the user the result!

    Args:
        show_steps: Whether to show all step history

    Returns:
        Current formula LaTeX and derivation state
    

Inputs: show_steps. Returns: object

session_startC
    Start a new derivation session

    Args:
        name: Derivation name
        description: Derivation description
        domain: Math/physics domain tag
        pattern: Derivation pattern
        goal: Natural-language goal (optional)
        author: Author

    Returns:
        Session information
    

Inputs: name (required), goal, author, domain, +2 more. Returns: object

session_statusA

Get the current session status.

Inputs: no named parameters. Returns: object

session_suggest_formulasA

Suggest formulas that may help reach the current session goal.

    Args:
        top_k: Maximum number of suggestions.

    Returns:
        List of recommended formulas with rationale.
    

Inputs: top_k. Returns: object

session_verify_sessionA

Verify the entire derivation chain in the current session.

    Returns:
        Summary with total, verified, failed and inconclusive counts.
    

Inputs: no named parameters. Returns: object

session_verify_stepA

Re-verify a single step in the current session.

    Args:
        step_number: 1-based step number. Defaults to -1 (last step).

    Returns:
        Verification result.
    

Inputs: step_number. Returns: object

show_assumptionsB
    Show all symbolic assumptions in the current scope

    Returns:
        Assumptions in the current MathContext
    

Inputs: no named parameters. Returns: object

tool_categoriesB
    🧰 List SymKit tools organized by category.

    Returns:
        Categorized tool index with descriptions and examples.
    

Inputs: no named parameters. Returns: object

tool_recommendA
    💡 Recommend the best tool(s) for a given task.

    Args:
        task: Brief description of what you want to do
        domain: Optional domain context

    Returns:
        Recommended tool with rationale and example
    

Inputs: task (required), domain. Returns: object

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.4/5.0

    Scored across 41 tools

    Disambiguation3/5

    Many tools within categories like session management (16 tools) and assumptions (6 tools) have similar purposes, such as `session_add_note` vs `session_record_step` or `session_show` vs `session_status`. While descriptions help, the high number of closely related tools could cause misselection.

    Naming Consistency4/5

    All tools use snake_case consistently, but the verb-object order varies (e.g., `formula_add` vs `session_start`). Some tools are single words like `math` or `derive`. Overall, the pattern is mostly predictable with minor deviations.

    Tool Count3/5

    41 tools is high for a single server. The large number of session (16) and assumption (6) tools suggests the scope could be trimmed. However, the domain of symbolic mathematics derivation is complex, so the count is borderline acceptable.

    Completeness4/5

    The tool set covers the full derivation lifecycle: setup, formula management, symbolic operations, assumptions, verification, reporting, and code generation. Minor gaps exist (e.g., no explicit session import/export), but overall it is well-rounded for the domain.

    Maintenance

    ActivitySlowing
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers