Skip to main content
Glama

Add a unit converter

dsail_add_unit_converter
DestructiveIdempotent

Give a policy check the conversion it needs between two units, with a factor a person supplied.

Use when a rule and its claim values use different units and a person has supplied the conversion factor needed to compare them.

Adds a unit converter to this project so rules mixing the two units resolve instead of answering UNKNOWN. to = from * factor + offset.

The factor is a policy decision with legal weight — an exchange rate fixed by a contract, a density fixed by a spec — and attribution records the person or document it came from, because a figure recalled from training would enter results as though a person had decided it.

This changes results. A check is reproducible from the PAIR (ruleset_hash, unit_library_hash); this edit changes the second half, so an approval recorded against the previous library no longer describes what the ruleset does. The result says so.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
factorYesThe multiplier a person supplied: one `from_unit` equals `factor` `to_unit`. Never a value recalled from training — a rate is a policy decision.
offsetNoAdded after multiplying, for affine conversions such as temperatures. Default 0.
to_unitYesThe unit converted to (`USD`).
from_unitYesThe unit converted from (`EUR`).
attributionNoWho supplied the factor, or the document it comes from. Recorded beside the converter, outside the hashed library.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedOutput schema / oneOf
      Previous value: -[
      -  {
      -    "description": "The unit library after the change, with its new hash and a warning about approvals recorded against the previous one.",
      -    "properties": {
      -      "ok": {
      -        "const": true,
      -        "type": "boolean"
      -      },
      -      "unit_library_hash": {
      -        "type": "string"
      -      },
      -      "versions": {
      -        "description": "Which engine and which wire contract produced this response.",
      -        "properties": {
      -          "engine": {
      -            "example": "dsail-core",
      -            "type": "string"
      -          },
      -          "engine_version": {
      -            "type": "string"
      -          },
      -          "language_version": {
      -            "description": "DSAIL language version.",
      -            "type": "string"
      -          },
      -          "service_version": {
      -            "type": "string"
      -          },
      -          "supported_language_versions": {
      -            "items": {
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "wire_version": {
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "engine",
      -          "engine_version",
      -          "language_version",
      -          "service_version",
      -          "wire_version"
      -        ],
      -        "type": "object"
      -      },
      -      "warning": {
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "ok"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "error": {
      -        "properties": {
      -          "actual": {
      -            "type": "integer"
      -          },
      -          "budget": {
      -            "type": "string"
      -          },
      -          "code": {
      -            "enum": [
      -              "VALIDATION_REJECTED",
      -              "COMPILE_FAILED",
      -              "BUDGET_EXCEEDED",
      -              "RULESET_NOT_FOUND",
      -              "ENGINE_ERROR",
      -              "BAD_REQUEST",
      -              "CREDENTIAL_REQUIRED",
      -              "CREDENTIAL_INVALID",
      -              "CREDENTIAL_SCOPE",
      -              "EVALUATION_LIMIT",
      -              "ENTITLEMENT_EXCEEDED",
      -              "TIER_UNAVAILABLE"
      -            ],
      -            "type": "string"
      -          },
      -          "diagnostics": {
      -            "items": {
      -              "properties": {
      -                "line": {
      -                  "type": [
      -                    "integer",
      -                    "null"
      -                  ]
      -                },
      -                "message": {
      -                  "type": "string"
      -                },
      -                "severity": {
      -                  "enum": [
      -                    "error",
      -                    "warning"
      -                  ],
      -                  "type": "string"
      -                }
      -              },
      -              "required": [
      -                "severity",
      -                "message"
      -              ],
      -              "type": "object"
      -            },
      -            "type": "array"
      -          },
      -          "docs": {
      -            "description": "The docs-site page that resolves this code (markdown). Fetch it before retrying blind.",
      -            "format": "uri",
      -            "type": "string"
      -          },
      -          "failure_count": {
      -            "description": "How many fields failed in total. Equal to the length of `failures` unless a very large rejection was truncated, which the message says.",
      -            "type": "integer"
      -          },
      -          "failures": {
      -            "description": "EVERY failing field, not the first one.",
      -            "items": {
      -              "properties": {
      -                "expected": {
      -                  "type": "string"
      -                },
      -                "field": {
      -                  "type": "string"
      -                },
      -                "received": {
      -                  "type": "string"
      -                }
      -              },
      -              "required": [
      -                "field",
      -                "expected",
      -                "received"
      -              ],
      -              "type": "object"
      -            },
      -            "type": "array"
      -          },
      -          "hint": {
      -            "description": "The grammar guide, carried on compile failures so the next call can succeed without a human.",
      -            "type": "string"
      -          },
      -          "limit": {
      -            "type": "integer"
      -          },
      -          "message": {
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "code",
      -          "message"
      -        ],
      -        "type": "object"
      -      },
      -      "ok": {
      -        "const": false,
      -        "type": "boolean"
      -      },
      -      "versions": {
      -        "description": "Which engine and which wire contract produced this response.",
      -        "properties": {
      -          "engine": {
      -            "example": "dsail-core",
      -            "type": "string"
      -          },
      -          "engine_version": {
      -            "type": "string"
      -          },
      -          "language_version": {
      -            "description": "DSAIL language version.",
      -            "type": "string"
      -          },
      -          "service_version": {
      -            "type": "string"
      -          },
      -          "supported_language_versions": {
      -            "items": {
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "wire_version": {
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "engine",
      -          "engine_version",
      -          "language_version",
      -          "service_version",
      -          "wire_version"
      -        ],
      -        "type": "object"
      -      }
      -    },
      -    "required": [
      -      "ok",
      -      "error",
      -      "versions"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "description": "The unit library after the change, with its new hash and a warning about approvals recorded against the previous one.",
      +    "properties": {
      +      "ok": {
      +        "const": true,
      +        "type": "boolean"
      +      },
      +      "unit_library_hash": {
      +        "type": "string"
      +      },
      +      "versions": {
      +        "description": "Which engine and which wire contract produced this response.",
      +        "properties": {
      +          "engine": {
      +            "example": "dsail-core",
      +            "type": "string"
      +          },
      +          "engine_version": {
      +            "type": "string"
      +          },
      +          "language_version": {
      +            "description": "DSAIL language version.",
      +            "type": "string"
      +          },
      +          "service_version": {
      +            "type": "string"
      +          },
      +          "supported_language_versions": {
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "wire_version": {
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "engine",
      +          "engine_version",
      +          "language_version",
      +          "service_version",
      +          "wire_version"
      +        ],
      +        "type": "object"
      +      },
      +      "warning": {
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "ok"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "error": {
      +        "properties": {
      +          "actual": {
      +            "description": "How much the request used, where that is known. Absent for solver_memory_mb: the solver stops at the limit.",
      +            "type": "integer"
      +          },
      +          "budget": {
      +            "type": "string"
      +          },
      +          "code": {
      +            "enum": [
      +              "VALIDATION_REJECTED",
      +              "COMPILE_FAILED",
      +              "BUDGET_EXCEEDED",
      +              "RULESET_NOT_FOUND",
      +              "ENGINE_ERROR",
      +              "ENGINE_BUSY",
      +              "BAD_REQUEST",
      +              "CREDENTIAL_REQUIRED",
      +              "CREDENTIAL_INVALID",
      +              "CREDENTIAL_SCOPE",
      +              "EVALUATION_LIMIT",
      +              "ENTITLEMENT_EXCEEDED",
      +              "TIER_UNAVAILABLE"
      +            ],
      +            "type": "string"
      +          },
      +          "diagnostics": {
      +            "items": {
      +              "properties": {
      +                "line": {
      +                  "type": [
      +                    "integer",
      +                    "null"
      +                  ]
      +                },
      +                "message": {
      +                  "type": "string"
      +                },
      +                "severity": {
      +                  "enum": [
      +                    "error",
      +                    "warning"
      +                  ],
      +                  "type": "string"
      +                }
      +              },
      +              "required": [
      +                "severity",
      +                "message"
      +              ],
      +              "type": "object"
      +            },
      +            "type": "array"
      +          },
      +          "docs": {
      +            "description": "The docs-site page that resolves this code (markdown). Fetch it before retrying blind.",
      +            "format": "uri",
      +            "type": "string"
      +          },
      +          "failure_count": {
      +            "description": "How many fields failed in total. Equal to the length of `failures` unless a very large rejection was truncated, which the message says.",
      +            "type": "integer"
      +          },
      +          "failures": {
      +            "description": "EVERY failing field, not the first one.",
      +            "items": {
      +              "properties": {
      +                "expected": {
      +                  "type": "string"
      +                },
      +                "field": {
      +                  "type": "string"
      +                },
      +                "received": {
      +                  "type": "string"
      +                }
      +              },
      +              "required": [
      +                "field",
      +                "expected",
      +                "received"
      +              ],
      +              "type": "object"
      +            },
      +            "type": "array"
      +          },
      +          "hint": {
      +            "description": "The grammar guide, carried on compile failures so the next call can succeed without a human.",
      +            "type": "string"
      +          },
      +          "limit": {
      +            "type": "integer"
      +          },
      +          "message": {
      +            "type": "string"
      +          },
      +          "retry_after_ms": {
      +            "description": "ENGINE_BUSY only: when to retry. The REST door also sends it, in seconds, as Retry-After.",
      +            "type": "integer"
      +          }
      +        },
      +        "required": [
      +          "code",
      +          "message"
      +        ],
      +        "type": "object"
      +      },
      +      "ok": {
      +        "const": false,
      +        "type": "boolean"
      +      },
      +      "versions": {
      +        "description": "Which engine and which wire contract produced this response.",
      +        "properties": {
      +          "engine": {
      +            "example": "dsail-core",
      +            "type": "string"
      +          },
      +          "engine_version": {
      +            "type": "string"
      +          },
      +          "language_version": {
      +            "description": "DSAIL language version.",
      +            "type": "string"
      +          },
      +          "service_version": {
      +            "type": "string"
      +          },
      +          "supported_language_versions": {
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "wire_version": {
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "engine",
      +          "engine_version",
      +          "language_version",
      +          "service_version",
      +          "wire_version"
      +        ],
      +        "type": "object"
      +      }
      +    },
      +    "required": [
      +      "ok",
      +      "error",
      +      "versions"
      +    ],
      +    "type": "object"
      +  }
      +]
  2. Changed6 schema fields changed
    • addedInput schema / properties / attribution / description
      Added value: +"Who supplied the factor, or the document it comes from. Recorded beside the converter, outside the hashed library."
    • addedInput schema / properties / factor / description
      Added value: +"The multiplier a person supplied: one `from_unit` equals `factor` `to_unit`. Never a value recalled from training — a rate is a policy decision."
    • addedInput schema / properties / from_unit / description
      Added value: +"The unit converted from (`EUR`)."
    • addedInput schema / properties / offset / description
      Added value: +"Added after multiplying, for affine conversions such as temperatures. Default 0."
    • addedInput schema / properties / to_unit / description
      Added value: +"The unit converted to (`USD`)."
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "description": "The updated unit library. On failure `ok` is false and `error` carries `code`, `message` and `docs`, the URL of the page that resolves it.",
      +  "oneOf": [
      +    {
      +      "description": "The unit library after the change, with its new hash and a warning about approvals recorded against the previous one.",
      +      "properties": {
      +        "ok": {
      +          "const": true,
      +          "type": "boolean"
      +        },
      +        "unit_library_hash": {
      +          "type": "string"
      +        },
      +        "versions": {
      +          "description": "Which engine and which wire contract produced this response.",
      +          "properties": {
      +            "engine": {
      +              "example": "dsail-core",
      +              "type": "string"
      +            },
      +            "engine_version": {
      +              "type": "string"
      +            },
      +            "language_version": {
      +              "description": "DSAIL language version.",
      +              "type": "string"
      +            },
      +            "service_version": {
      +              "type": "string"
      +            },
      +            "supported_language_versions": {
      +              "items": {
      +                "type": "string"
      +              },
      +              "type": "array"
      +            },
      +            "wire_version": {
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "engine",
      +            "engine_version",
      +            "language_version",
      +            "service_version",
      +            "wire_version"
      +          ],
      +          "type": "object"
      +        },
      +        "warning": {
      +          "type": "string"
      +        }
      +      },
      +      "required": [
      +        "ok"
      +      ],
      +      "type": "object"
      +    },
      +    {
      +      "properties": {
      +        "error": {
      +          "properties": {
      +            "actual": {
      +              "type": "integer"
      +            },
      +            "budget": {
      +              "type": "string"
      +            },
      +            "code": {
      +              "enum": [
      +                "VALIDATION_REJECTED",
      +                "COMPILE_FAILED",
      +                "BUDGET_EXCEEDED",
      +                "RULESET_NOT_FOUND",
      +                "ENGINE_ERROR",
      +                "BAD_REQUEST",
      +                "CREDENTIAL_REQUIRED",
      +                "CREDENTIAL_INVALID",
      +                "CREDENTIAL_SCOPE",
      +                "EVALUATION_LIMIT",
      +                "ENTITLEMENT_EXCEEDED",
      +                "TIER_UNAVAILABLE"
      +              ],
      +              "type": "string"
      +            },
      +            "diagnostics": {
      +              "items": {
      +                "properties": {
      +                  "line": {
      +                    "type": [
      +                      "integer",
      +                      "null"
      +                    ]
      +                  },
      +                  "message": {
      +                    "type": "string"
      +                  },
      +                  "severity": {
      +                    "enum": [
      +                      "error",
      +                      "warning"
      +                    ],
      +                    "type": "string"
      +                  }
      +                },
      +                "required": [
      +                  "severity",
      +                  "message"
      +                ],
      +                "type": "object"
      +              },
      +              "type": "array"
      +            },
      +            "docs": {
      +              "description": "The docs-site page that resolves this code (markdown). Fetch it before retrying blind.",
      +              "format": "uri",
      +              "type": "string"
      +            },
      +            "failure_count": {
      +              "description": "How many fields failed in total. Equal to the length of `failures` unless a very large rejection was truncated, which the message says.",
      +              "type": "integer"
      +            },
      +            "failures": {
      +              "description": "EVERY failing field, not the first one.",
      +              "items": {
      +                "properties": {
      +                  "expected": {
      +                    "type": "string"
      +                  },
      +                  "field": {
      +                    "type": "string"
      +                  },
      +                  "received": {
      +                    "type": "string"
      +                  }
      +                },
      +                "required": [
      +                  "field",
      +                  "expected",
      +                  "received"
      +                ],
      +                "type": "object"
      +              },
      +              "type": "array"
      +            },
      +            "hint": {
      +              "description": "The grammar guide, carried on compile failures so the next call can succeed without a human.",
      +              "type": "string"
      +            },
      +            "limit": {
      +              "type": "integer"
      +            },
      +            "message": {
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "code",
      +            "message"
      +          ],
      +          "type": "object"
      +        },
      +        "ok": {
      +          "const": false,
      +          "type": "boolean"
      +        },
      +        "versions": {
      +          "description": "Which engine and which wire contract produced this response.",
      +          "properties": {
      +            "engine": {
      +              "example": "dsail-core",
      +              "type": "string"
      +            },
      +            "engine_version": {
      +              "type": "string"
      +            },
      +            "language_version": {
      +              "description": "DSAIL language version.",
      +              "type": "string"
      +            },
      +            "service_version": {
      +              "type": "string"
      +            },
      +            "supported_language_versions": {
      +              "items": {
      +                "type": "string"
      +              },
      +              "type": "array"
      +            },
      +            "wire_version": {
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "engine",
      +            "engine_version",
      +            "language_version",
      +            "service_version",
      +            "wire_version"
      +          ],
      +          "type": "object"
      +        }
      +      },
      +      "required": [
      +        "ok",
      +        "error",
      +        "versions"
      +      ],
      +      "type": "object"
      +    }
      +  ],
      +  "type": "object"
      +}
  3. First observed

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, the description discloses that this tool changes results, that reproducibility depends on the (ruleset_hash, unit_library_hash) pair, and that a prior approval no longer describes the ruleset after the edit. It also explains the legal/policy weight of the factor and attribution, adding meaningful behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is longer than average, but every sentence earns its place: purpose, usage condition, mechanism, policy semantics, and behavioral consequences. It is front-loaded with the core action and use case, with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the output schema, full parameter coverage, and annotations covering destructiveness and idempotency, the description provides everything an agent needs: when to use it, the conversion formula, the attribution requirement, and the downstream effect on approvals. Nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although schema coverage is 100%, the description adds the crucial formula 'to = from * factor + offset' and explains the semantic significance of attribution as recording the person or document behind a policy decision. This goes well beyond the schema's individual parameter descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: it adds a unit converter so rules using different units resolve instead of answering UNKNOWN. It also gives the conversion formula, making the tool's role unmistakable and distinguishable from read-only siblings like dsail_unit_library.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says to use this tool when a rule and its claim values use different units and a person has supplied the conversion factor. It does not name alternative tools or state when not to use it, but the context is clear enough for an agent to select it appropriately.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.