SooTool

Servidor de cálculo determinista solo con decimales para uso de herramientas LLM

Documentación

SooTool logo

SooTool

MCP de cálculo de precisión para uso de herramientas por LLM.

CI PyPI version Python 3.12+ License: MIT

Servidor MCP que se encarga de los cálculos en lugar del LLM. Realiza con precisión Decimal cálculos de impuestos, nóminas, finanzas, estadística e ingeniería, y devuelve junto con ellos la base del cálculo. Ofrece 276 herramientas básicas en 18 dominios de cálculo + 10 herramientas de políticas administrativas, hasta 500 cálculos paralelos a la vez (core.batch), cálculos encadenados por pasos (core.pipeline) y 4 tipos de transporte (stdio/Streamable HTTP/Unix, SSE en desuso). Python 3.12 o superior.

Por qué es necesario

Los LLM no calculan números, generan números plausibles. Por eso fallan a menudo en los límites de los tramos impositivos progresivos, la dirección del redondeo y las tasas impositivas anuales. A continuación se muestra el resultado de resolver los mismos 20 problemas (medido el 24 de abril de 2026).

Sujeto que resuelveCorrecto (exacto)Aproximado (error ≤ 0,01 %)Incorrecto
SooTool2000
gemini-3-pro-preview1244
claude-opus-4-7938
gpt-5.45312

Los puntos de fallo son similares aunque cambie el modelo: límites de tramos del impuesto sobre la renta, deducción especial por tenencia a largo plazo en el impuesto sobre ganancias de capital, redondeo del IVA y precisión de la impedancia de corriente alterna. La composición de los problemas y los datos originales están en bench/.

SooTool fija estos cálculos con tres mecanismos.

  • Cálculo exclusivo con Decimal. Los números de entrada se reciben como cadena o Decimal. Los errores de coma flotante no se cuelan en el cálculo.
  • Externalización de los valores legales. Las tasas impositivas, deducciones y primas de seguros se guardan en archivos de políticas (YAML) con el artículo legal de referencia y la fecha de entrada en vigor. Si se indica un momento (as_of), se calcula con los valores vigentes en esa fecha.
  • Devolución de la base del cálculo. Toda respuesta incluye un trace con la fórmula, las entradas, los valores intermedios y el resultado, además de un recibo de verificación de reejecución (_meta.integrity).

Estructura

 LLM 에이전트 / CLI / 파이썬 코드
        │
        │  MCP(stdio, HTTP, Unix)        sootool call ...        from sootool.sdk import tax
        ▼                                      ▼                          ▼
 ┌──────────────────────────────────────────────────────────────────────────────┐
 │ 경계 검사   인자 이름·타입·크기 검증, 숫자 문자열 → Decimal, 인증 범위 확인     │
 ├──────────────────────────────────────────────────────────────────────────────┤
 │ 레지스트리   도구 286개를 이름으로 찾아 실행 (core.batch / core.pipeline 포함)   │
 ├───────────────────────────────┬──────────────────────────────────────────────┤
 │ 도메인 도구                     │ 정책 로더                                      │
 │ tax · payroll · finance ·      │ policies/<도메인>/<이름>_<연도>.yaml           │
 │ realestate · stats · ...       │ 해시 검증 → as_of 시점의 시행 버전 선택         │
 └───────────────────────────────┴──────────────────────────────────────────────┘
        │
        ▼
 { 결과 필드, trace(공식·입력·단계·출력), 정책 출처와 근거 조문, _meta.integrity(영수증) }

Los tres puntos de entrada (MCP, CLI, SDK) pasan por el mismo registro. Con la misma entrada, el resultado y el recibo son idénticos sea cual sea la vía utilizada.

Inicio rápido

Instalación

pip install sootool                 # 기호 계산(symbolic.*)까지 쓰려면 pip install "sootool[symbolic]"

Registro en Claude Code

claude mcp add --scope user sootool -- uvx sootool

Para descargar el repositorio y ejecutar el código en desarrollo, regístralo de la siguiente manera.

git clone https://github.com/JinHo-von-Choi/SooTool.git
cd SooTool && uv sync
claude mcp add --scope user sootool -- uv run --directory "$PWD" python -m sootool

Primer cálculo

En un cliente MCP, si preguntas «¿cuál es el impuesto sobre la renta de 2026 para una base imponible de 50 millones de wones?», el agente llamará a tax.kr_income. También puedes ejecutar la misma herramienta directamente desde la terminal.

sootool call tax.kr_income --arg taxable_income=50000000 --arg year=2026 --format raw
{
  "tax": "6240000",
  "effective_rate": "0.12480000",
  "marginal_rate": "0.15",
  "breakdown": [ ... 구간별 과세표준과 세액 ... ],
  "policy_effective_date": "2026-01-01",
  "policy_citations": [{"law": "소득세법", "article": "제55조제1항", "url": "https://www.law.go.kr/법령/소득세법/제55조"}]
}

Cómo leer la respuesta

finance.npv(rate="0.08", cashflows=["-1000","300","400","500","200"], rounding="HALF_EVEN", decimals=2) es una respuesta real.

{
  "npv": "164.64",
  "trace": {
    "tool": "finance.npv",
    "formula": "NPV = sum(CF_t / (1+r)^t, t=0..n)",
    "inputs": {"rate": "0.08", "cashflows": ["-1000", "300", "400", "500", "200"], "rounding": "HALF_EVEN", "decimals": 2},
    "steps": [{"label": "npv_raw", "value": "164.63539696786661172171511042618089308126395968697"}],
    "output": "164.64"
  },
  "_meta": {
    "integrity": {
      "tool": "finance.npv",
      "input_hash": "00da5199...",
      "result_hash": "d7a0ecfe...",
      "tool_version": "1.0.0",
      "sootool_version": "0.2.0"
    },
    "engine": "decimal"
  }
}
CampoSignificado
Campos de resultado como npvResultado del cálculo. Todos los números son cadenas.
trace.stepsCálculo intermedio, incluido el valor antes del redondeo. Sirve para que una persona pueda comprobar el resultado.
policy_*Solo aparece en las herramientas de políticas. Fecha de entrada en vigor, estado, artículo legal de referencia y hash del archivo de políticas aplicado.
_meta.integrityRecibo. Es el hash de la entrada y del resultado, por lo que se puede volver a ejecutar el mismo cálculo con sootool receipt verify para comparar.
_meta.engineMotor de cálculo. decimal (exacto), mpmath (con dígitos especificados), float64 (aproximado), composite, none.
_meta.hintsSugerencia de herramientas que podrían usarse a continuación. No afecta al valor del resultado.

Funciones principales

El redondeo lo elige quien llama

Las herramientas financieras y contables donde la práctica de redondeo varía según el contexto (IVA, flujo de caja, depreciación, cambio de divisa, etc.) aceptan rounding (HALF_EVEN, HALF_UP, DOWN, UP, FLOOR, CEIL) y decimals. El cálculo inverso del IVA usa truncamiento a la unidad (DOWN), la contabilidad general usa HALF_EVEN: cada uso tiene su propia regla. Cuando la ley fija el tratamiento de los decimales (por ejemplo, el impuesto local se trunca por debajo de 10 wones), se sigue esa regla y se indica en la descripción de la herramienta.

Cálculo de políticas con fecha indicada

Las leyes fiscales y las primas de seguros cambian incluso a mitad de año. Las herramientas de políticas aceptan, además de year, as_of (AAAA-MM-DD) y include_proposed.

policies/payroll/kr_4insurance_2026.yaml             2026-01-01 ~ 2026-06-30
policies/payroll/kr_4insurance_2026@2026-07-01.yaml  2026-07-01 ~ 2026-10-31  ◀── as_of="2026-08-15"
policies/payroll/kr_4insurance_2026@2026-11-01.yaml  2026-11-01 ~ 2026-12-31

as_of가 속한 버전으로 계산하고, 응답에 그 버전의 시행일과 근거 조문을 싣는다.

Si no se indica as_of, se usa la versión definitiva de ese año con la fecha de entrada en vigor más tardía. Las enmiendas aún no aprobadas por la Asamblea Nacional (status: proposed) solo se usan cuando include_proposed=true. El procedimiento para modificar los archivos de políticas sin redistribuir el servidor está en docs/policy_management.md.

Varios elementos a la vez: batch y pipeline

core.batch     독립 계산 N건을 병렬로             core.pipeline   앞 단계 결과를 다음 단계 입력으로
                                                 
 ┌ s1: finance.npv(rate=0.05) ┐                  annual = core.mul(3000000, 12)
 ├ s2: finance.npv(rate=0.08) ┼─▶ id 순서로 결과       │  ${annual.result.result}
 └ s3: finance.npv(rate=0.10) ┘                       ▼
                                                  tax = tax.kr_income(annual, 2026)
 최대 500건, 항목당 10초, 전체 60초              최대 50단계, 깊이 10, 단계당 2초, 전체 30초

core.batch registra por separado el éxito, el error y el tiempo de espera de cada elemento y devuelve los resultados en el orden de entrada. core.pipeline marca los pasos posteriores como skipped si un paso anterior falla, e incluye core.pipeline_resume (conservado 10 minutos) para reanudar desde el punto de fallo.

{
  "name": "core.pipeline",
  "arguments": {
    "steps": [
      {"id": "annual", "tool": "core.mul",      "args": {"operands": ["3000000", "12"]}},
      {"id": "tax",    "tool": "tax.kr_income", "args": {"taxable_income": "${annual.result.result}", "year": 2026}}
    ]
  }
}

En la práctica se usa así.

TareaVolumenCombinación
Cierre de nómina500 empleadoscore.batch + payroll.kr_salary
Sensibilidad de inversión9 tasas de descuento × 5 escenarios de flujo de cajacore.batch + finance.npv, finance.irr
Separación del IVA en extractos de transaccionesCientos de casoscore.batch + accounting.vat_extract
Del salario bruto al neto recibido4 pasoscore.pipeline

Cálculo inverso, comparación y explicación

  • core.solve_for: encuentra el valor de entrada que produce el resultado objetivo. Ejemplo: el salario bruto mensual que da un neto recibido de 3 millones de wones.
  • core.compare: presenta en una tabla los valores y diferencias de cada escenario frente al caso base.
  • core.explain: explica el proceso de cálculo y las políticas aplicadas en frases en coreano o inglés. No cambia las cifras.

Verificación de reejecución con recibo

sootool receipt verify --tool finance.fv \
  --arguments '{"present_value":"1000","rate":"0.05","periods":10}' \
  --receipt receipt.json

Vuelve a ejecutar la misma herramienta y compara el nombre de la herramienta, el hash de entrada, el hash de resultado, la versión de la herramienta y el hash de políticas. Si se especifica un archivo de clave privada ed25519 en SOOTOOL_RECEIPT_KEY_FILE, el recibo lleva firma.

Catálogo de herramientas (276 básicas + 10 admin, 18 dominios de cálculo + herramientas operativas)

NamespaceN.ºHerramientas representativas
core11add, sub, mul, div, calc (fórmula), batch, pipeline, pipeline_resume, solve_for, compare, explain
accounting12vat_extract, vat_add, balance, 3 de depreciación, 2 de dupont, ratios, income_statement, cashflow_operating, break_even
finance18pv, fv, npv, irr, roi, cagr, payback_period, loan_schedule, bond_ytm, bond_duration, black_scholes, 2 de var, sharpe, sortino
tax17kr_income, kr_comprehensive_income_tax, kr_withholding_simple, capital_gains_kr, kr_gift, kr_inheritance, kr_corporate, kr_eitc, 3 de impuesto local adicional
tax_us4federal_income, capital_gains, state_tax, fica
payroll15kr_salary, kr_gross_from_net, kr_severance_pay, kr_year_end_tax_settlement, kr_overtime_pay, kr_minimum_wage_check, 4 de deducciones
realestate10kr_acquisition_tax, kr_transfer_tax, kr_property_tax, kr_comprehensive, kr_ltv, kr_dti, kr_dsr, kr_subscription_score
stats14descriptive, 3 de prueba t, anova_oneway, regression_linear, ci_mean, bootstrap_ci, pruebas no paramétricas
probability30pdf, cdf y ppf de las distribuciones normal, binomial, Poisson, gamma, beta, exponencial, lognormal, chi-cuadrado y F; bayes, nCr, nPr
datetime14cálculo de días hábiles, day_count, age, diff, tz_convert, conversión de calendario lunar, 24 términos solares, año fiscal, período impositivo del impuesto sobre la renta
math102 de integración numérica, 2 de diferenciación numérica, 2 de interpolación, polynomial_roots, polynomial_horner, fft, ifft
geometry157 de área y volumen, 3 de vectores, 4 de matrices, haversine
engineering56circuitos eléctricos y de CA, fluidos, transferencia de calor, mecánica de materiales, control, fiabilidad, conversión de prefijos SI
units8convert, fx_convert, fx_triangulate, temperature, conversión de energía, presión, tamaño de datos y tiempo
medical12bmi, bsa, egfr, dose_weight_based, pregnancy_weeks, cha2ds2_vasc, has_bled, framingham_cvd_10y, 4 de QTc
science11half_life, ideal_gas, molar_mass, stoichiometry, nernst, snell_law, thin_lens, bragg y otros
crypto10gcd, lcm, egcd, modinv, modpow, crt, is_prime, euler_totient, carmichael_lambda, hash
pm5critical_path, pert, evm, earned_schedule, monte_carlo_schedule
symbolic2solve, diff (si sootool[symbolic] está instalado)
sootool2+10skill_guide, verify_receipt, 10 de gestión de políticas (4 de escritura solo en modo administrador)

La versión, el grado de precisión y la descripción de cada herramienta están en docs/tool_catalog.md. Este archivo se genera automáticamente desde el registro.

Ejecución del servidor

sootool                                                    # stdio (MCP 클라이언트 기본)
sootool --transport http --http-port 10535                 # Streamable HTTP
sootool --transport unix --socket /tmp/sootool.sock        # Unix 소켓
sootool --transport stdio,http --socket /tmp/sootool.sock  # 여러 전송 동시 기동
TransporteUsoNotas
stdioClientes locales como Claude Code, Claude Desktop, etc.Valor predeterminado
httpAcceso remoto (Streamable HTTP)Sin estado, por lo que puede colocarse detrás de un balanceador de carga. Puerto predeterminado 10535
unixOtros procesos del mismo hostEl acceso se controla con los permisos del archivo de socket (0600 por defecto)
sse-legacyCompatibilidad con clientes MCP 2024-11En desuso. Solo se activa con --enable-sse-legacy. Puerto predeterminado 10536

Las reglas de seguridad para el transporte de red son las siguientes.

  • El enlace predeterminado es 127.0.0.1. Para abrirlo al exterior con --host 0.0.0.0 se necesita --auth-token (o SOOTOOL_AUTH_TOKEN) para arrancar.
  • Las 4 herramientas de escritura que modifican políticas solo se exponen en stdio y sockets Unix. Para usarlas por red se necesitan todos los elementos de --admin --remote-admin --admin-token <토큰>, y solo las solicitudes autenticadas con el token de administrador pueden realizar escrituras.

Perfiles de exposición

sootool --profile full   # 기본값. 도구 286개를 모두 노출
sootool --profile lean   # sootool.search, describe, call, skill_guide 4개만 노출

lean no carga todas las definiciones de herramientas en el contexto. El agente busca herramientas con sootool.search, comprueba los argumentos con sootool.describe y luego ejecuta con sootool.call. El resultado y el recibo son idénticos a los de una llamada directa. sootool.call solo ejecuta herramientas de solo lectura.

Línea de comandos

Si se da un subcomando, se ejecuta la herramienta directamente sin levantar el servidor.

sootool call core.add --arg 'operands=["1.5","2.5"]'
sootool call finance.npv --arg-json '{"rate":"0.1","cashflows":["-100","50","60","70"]}'
sootool call payroll.kr_gross_from_net --arg net_monthly=3000000 --arg year=2026 --format raw
sootool tools list --search 양도세        # 줄임말과 일상 표현으로 검색
sootool tools describe tax.kr_income     # 인자와 정책 인자 확인
sootool batch -f items.json              # -f - 는 표준입력
sootool policy show --arg domain=tax --arg name=kr_income --arg year=2026
sootool skill-guide --section triggers
sootool version
ElementoContenido
ArgumentosRepite --arg 이름=값 o pásalos de una vez con --arg-json. Los argumentos de cadena se usan tal cual; los enteros, booleanos, listas y objetos se leen como JSON.
Formato de salida--format pretty (predeterminado), json (completo), raw (sin trace ni _meta), trace
Destino de salidaEl resultado va a la salida estándar y los errores a la salida de error, en JSON.
Código de salida0 éxito, 1 error de herramienta, 2 error de entrada, 3 requiere modo administrador (SOOTOOL_ADMIN_MODE=1), 70 error interno

Uso como biblioteca de Python

Se llaman las mismas herramientas como funciones sin servidor MCP. El resultado, el recibo y el procesamiento de as_of son iguales que en MCP, y los tipos de resultado están declarados, por lo que el verificador de tipos comprueba los campos.

from sootool.sdk import tax

out = tax.kr_income(taxable_income=50_000_000, year=2026)
out["tax"]                                # "6240000"
out["_meta"]["integrity"]["input_hash"]   # 재실행 검증용 영수증

Para configuraciones donde el agente ejecuta Python en un sandbox, consulta docs/sdk.md.

Indicar al agente las reglas de uso

Aunque se registren las herramientas, el agente a veces calcula mentalmente. Añade la regla «los cálculos numéricos los hace SooTool» con una de las siguientes opciones.

  • Haz que llame a sootool.skill_guide al inicio de la sesión. Devuelve una tabla de disparadores que indica cuándo usar cada herramienta, ejemplos, patrones prohibidos y un manual (section: triggers, examples, anti_patterns, playbooks, all / lang: ko, en).
  • Reglas para pegar en el archivo de configuración del cliente: Claude Code, Cursor, AGENTS.md

Documentación

DocumentoContenido
Guía de usuarioResumen de herramientas por dominio, argumentos comunes y reglas de respuesta
Catálogo de herramientasVersión, grado de precisión y descripción de las 286 herramientas
Gestión de políticasEstructura de los archivos de políticas, selección de fecha, procedimientos de actualización y reversión, registro de auditoría
SDKUso de la biblioteca de Python y configuración del sandbox
Paquetes de políticas externosCreación, verificación e instalación de paquetes de políticas firmados
Contrato de estabilidadAlcance de la compatibilidad garantizada y procedimiento de retirada
Libro de recetasEjemplos de llamadas por escenario: fiscalidad, finanzas e ingeniería eléctrica
Registro de decisiones de arquitecturaDecisiones de diseño y su justificación (ADR)
Procedimiento de publicaciónDesde el aumento de versión hasta la publicación en PyPI

Desarrollo

uv sync --extra symbolic
make test        # pytest와 커버리지
make lint        # ruff
make typecheck   # mypy
uv run python scripts/mcp_smoke_test.py   # stdio 연결 점검 (http, sse, unix 스크립트도 있다)

Para añadir una herramienta nueva, crea una función en src/sootool/modules/<도메인>/, añade @REGISTRY.tool(namespace, name, description, version) y cárgala desde el dominio __init__.py: quedará registrada. Si cambias la descripción o los tipos de una herramienta, regenera los documentos con scripts/gen_tool_catalog.py y scripts/gen_sdk_stubs.py. Si modificas un archivo de políticas, actualiza el hash con scripts/policy_stamp.py.

Licencia

MIT. Consulta LICENSE.