# Plumbline MCP tools

<!-- Generated by scripts/docs.mjs from the registered server. Do not edit. Version 0.1.0. -->

7 tools. This server prepares a human decision. It does not make one, and it cannot be configured to.

| Tool | Title |
| --- | --- |
| `check_banking_format` | Check banking identifiers for well-formedness |
| `explain_verification_run` | Explain a run in plain language |
| `get_evidence_requirements` | Get evidence requirements |
| `get_review_artifact` | Get the review artifact for a run |
| `get_verification_capabilities` | Get verification capabilities |
| `get_verification_run` | Get the control trace for a run |
| `verify_funding_package` | Verify a funding package |

## check_banking_format

Answer whether banking identifiers are well formed, without a verification run. Supply any of routing_number, account_number (the full number), account_last4, iban, swift and bank_name, as the caller has them; at least one identifier is required. Returns the same checks verify_funding_package reports beside the engine's verdict: the ABA checksum and Federal Reserve prefix on a routing number, the NACHA length on an account number, mod-97 on an IBAN, the ISO 9362 shape and country on a BIC, and the two cross-field comparisons. String arithmetic only: no credential, no penny test, no network call, no engine call and no model call. It is a precheck, not an IVP-001 control — it produces no finding and changes no status, severity or assessment — and a field that is absent reads not_checked rather than valid. A full account number is masked to its last four digits in the answer and is never stored whole. Whether the identifiers are the supplier's approved ones is a different question, answered by verify_funding_package.

Example arguments:

```json
{"routing_number":"123456780","account_number":"…","bank_name":"Example Bank"}
```

Input schema:

```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "additionalProperties": false,
  "properties": {
    "account_last4": {
      "description": "The last four digits, when the full number is not to hand.",
      "type": "string"
    },
    "account_number": {
      "description": "The full account number. Masked to its last four digits in the answer, and never stored whole: the usage record keeps the last four digits and a salted digest.",
      "type": "string"
    },
    "bank_name": {
      "description": "Recorded with the call for context. No check reads it, so it does not admit a call on its own.",
      "type": "string"
    },
    "iban": {
      "description": "IBAN. Stored masked to its country and last four characters, because it embeds the account number.",
      "type": "string"
    },
    "routing_number": {
      "description": "US ABA routing number, nine digits.",
      "type": "string"
    },
    "swift": {
      "description": "SWIFT/BIC, 8 or 11 characters.",
      "type": "string"
    }
  },
  "type": "object"
}
```

## explain_verification_run

A non-authoritative, plain-language narrative of a run's control trace for an analyst or an executive. Presentation only: a code-written status table heads every explanation, carrying each control's status and verdict verbatim from the engine and, for a control that skips items before checking them, one MCP-lane count of the matched invoices it examined, labelled as such in the table. The narrative is checked against the trace's own vocabulary, and submitter-supplied text is never shown to the model. The trace from get_verification_run remains the record.

Example arguments:

```json
{"run_id":"run_…","audience":"analyst"}
```

Input schema:

```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "additionalProperties": false,
  "properties": {
    "audience": {
      "description": "analyst (default): control by control. executive: outcome and reason, short.",
      "type": "string"
    },
    "run_id": {
      "description": "A run_id returned by verify_funding_package.",
      "type": "string"
    }
  },
  "required": [
    "run_id"
  ],
  "type": "object"
}
```

## get_evidence_requirements

The structured evidence a funding package must carry, the cardinality limits enforced by the endpoint, which controls become unreachable when an input is missing, and what the endpoint refuses outright.

Example arguments:

```json
{}
```

Input schema:

```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "properties": {},
  "type": "object"
}
```

## get_review_artifact

The artifact the engine produced: a Funding Upload Review Summary, an Incomplete Documentation Notice, or a withheld-report refusal with its deficiencies. Never synthesizes an artifact the engine declined to issue, and the report markdown is byte-identical to the engine's. Where the report lists a performed control that the engine's own metrics show examined no matched invoice, mcp_items_checked_notice says so in one sentence beside the report, with mcp_items_checked_authority naming it a lane annotation. Neither key changes a status, finding, severity or assessment.

Example arguments:

```json
{"run_id":"run_…"}
```

Input schema:

```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "additionalProperties": false,
  "properties": {
    "run_id": {
      "description": "A run_id returned by verify_funding_package.",
      "type": "string"
    }
  },
  "required": [
    "run_id"
  ],
  "type": "object"
}
```

## get_verification_capabilities

What this Plumbline instance can and cannot do right now, read from the live health endpoint. Capabilities are release gates, so a capability reported as unavailable is genuinely unavailable. Also returns the authority boundary and the synthetic package catalog.

Example arguments:

```json
{}
```

Input schema:

```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "properties": {},
  "type": "object"
}
```

## get_verification_run

The full IVP-001 control trace: every control in mandatory order with its execution status (performed, not_performed, not_reached), the reason it did not run where applicable, coverage, and findings. A control that did not run is reported as one. Beside the trace, mcp_items_checked names the performed controls whose own engine metrics show they examined none of the matched invoices. That block is authored by this server, not by IVP-001: it carries its authority string, it is not the engine's verification_coverage, and it changes no status, finding, severity or assessment. A control absent from it is not thereby claimed to have examined everything.

Example arguments:

```json
{"run_id":"run_…"}
```

Input schema:

```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "additionalProperties": false,
  "properties": {
    "run_id": {
      "description": "A run_id returned by verify_funding_package.",
      "type": "string"
    }
  },
  "required": [
    "run_id"
  ],
  "type": "object"
}
```

## verify_funding_package

Run IVP-001 against a funding package. Supply exactly one of: package_id for a synthetic demo package; evidence for a structured funding_request_evidence_v1 object; or documents (PDF, PNG, JPEG, text) and/or raw_text, which a language model transcribes into evidence first. Executes the real deterministic engine. Returns a run_id plus the engine's own verdict, and for documents the extracted evidence labelled untrusted with a confidence and source per field, and documents_not_transcribed, every submitted document the engine never saw: no evidence value and no record came from it. Beside the engine's verdict, format_checks reports whether each banking identifier in the evidence — routing_number, account_last4, iban, swift — is well formed, keyed by invoice filename and by approved-banking supplier name. Those checks are a precheck this server runs on strings, not an IVP-001 control: they produce no finding and change no status, severity or assessment. A field that is absent reads not_checked rather than valid, a record built on one of the synthetic catalog's deliberately fake identifiers is left unchecked, and on the documents path the invoices a model transcribed are left unchecked too. mcp_items_checked is the other block this server authors rather than reads: it names the performed controls whose own engine metrics show they examined none of the matched invoices, carries its authority string, and likewise produces no finding and changes no status, severity or assessment. A control absent from it is not thereby claimed to have examined everything. This tool does not decide anything and cannot approve funding.

Example arguments:

```json
{"package_id":"clean"}
```

Input schema:

```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "additionalProperties": false,
  "properties": {
    "approved_banking": {
      "description": "The funder's approved banking on file, with documents only. Never taken from the documents themselves.",
      "items": {
        "additionalProperties": {},
        "type": "object"
      },
      "type": "array"
    },
    "documents": {
      "description": "Up to 10 documents, 25 MB and 100 pages in total. Kept with the usage record while the server captures content, for its retention period: 30 days on the hosted server; nothing over stdio, which keeps no usage record at all.",
      "items": {
        "additionalProperties": false,
        "properties": {
          "data": {
            "description": "Base64 file bytes.",
            "type": "string"
          },
          "media_type": {
            "description": "application/pdf, image/png, image/jpeg, or text/plain.",
            "type": "string"
          },
          "name": {
            "description": "Distinct name; extracted values cite it.",
            "maxLength": 200,
            "minLength": 1,
            "type": "string"
          },
          "role": {
            "description": "Declared role. A declared supporting_invoice that yields nothing is recorded unreadable.",
            "type": "string"
          }
        },
        "required": [
          "name",
          "media_type",
          "data"
        ],
        "type": "object"
      },
      "type": "array"
    },
    "evidence": {
      "additionalProperties": {},
      "description": "A funding_request_evidence_v1 object. Must not contain a documents key; pass documents in the documents argument instead.",
      "type": "object"
    },
    "package_id": {
      "description": "One of the synthetic packages: clean, missing_document, material_exception, prompt_injection",
      "type": "string"
    },
    "raw_text": {
      "description": "Pasted document text, transcribed the same way as documents.",
      "maxLength": 200000,
      "type": "string"
    }
  },
  "type": "object"
}
```

## Never exposed

- approve or decline funding
- release, schedule, or transmit a payment
- issue a waiver or exception approval
- create or alter banking instructions
- override a finding, a severity, or a control status
- declare a package free of fraud
- record a human disposition or attestation

## Limits

Engine endpoint:

- `max_body_bytes`: 262144
- `max_response_bytes`: 1048576
- `max_string_bytes`: 4096
- `max_json_depth`: 32
- `max_json_nodes`: 10000
- `max_lines`: 100
- `max_supporting_invoices`: 75
- `max_approved_banking_records`: 75

Documents submitted for extraction:

- `max_documents`: 10
- `max_total_bytes`: 26214400
- `max_pages`: 100
- `media_types`: application/pdf, image/png, image/jpeg, text/plain

Extraction concurrency (defaults; `get_verification_capabilities` reports the running values under `extraction.concurrency`):

- `max_in_flight`: 4
- `queue_wait_s`: 20
- `over_limit`: A submission past max_in_flight waits up to queue_wait_s for a slot, then is refused with extraction_busy and retry_after_s.

Typed refusal when the queue wait runs out: `extraction_busy`, with `retry_after_s` counted from the oldest in-flight extraction.
