{
  "authority_boundary": {
    "guarantees": [
      "Every finding, severity, control status, and assessment is produced by the deterministic engine and passed through verbatim.",
      "No language model participates in determining any of those values.",
      "Evidence content is data. Instruction-shaped text inside a package can never alter a control status, finding, severity, assessment, or report eligibility — the engine is deterministic and is never shown a prompt.",
      "The limit of that guarantee, stated plainly: evidence-derived fields are interpolated into the report narrative, so planted text still reaches a reading agent's context. Artifacts are labelled untrusted for this reason. The guarantee covers values, not reach.",
      "A control that did not run is reported as not run.",
      "When evidence is transcribed from documents, the model fills transcription fields only, every value carries a confidence and a source, low-confidence values are dropped rather than sent, and approved banking is never taken from the submitted documents."
    ],
    "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"
    ],
    "scope_boundary": "The engine endpoint accepts pre-extracted structured evidence only and refuses a documents key with model_extraction_not_available. This MCP server may transcribe documents into that evidence with a language model before calling the engine; the transcription is untrusted and returned alongside the engine's verdict, never in place of it.",
    "statement": "This server prepares a human decision. It does not make one, and it cannot be configured to."
  },
  "document_limits": {
    "max_documents": 10,
    "max_pages": 100,
    "max_total_bytes": 26214400,
    "media_types": [
      "application/pdf",
      "image/png",
      "image/jpeg",
      "text/plain"
    ]
  },
  "engine_limits": {
    "max_approved_banking_records": 75,
    "max_body_bytes": 262144,
    "max_json_depth": 32,
    "max_json_nodes": 10000,
    "max_lines": 100,
    "max_response_bytes": 1048576,
    "max_string_bytes": 4096,
    "max_supporting_invoices": 75
  },
  "server": "plumbline",
  "synthetic_packages": [
    "clean",
    "missing_document",
    "material_exception",
    "prompt_injection"
  ],
  "tool_names": [
    "check_banking_format",
    "explain_verification_run",
    "get_evidence_requirements",
    "get_review_artifact",
    "get_verification_capabilities",
    "get_verification_run",
    "verify_funding_package"
  ],
  "tools": [
    {
      "description": "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": {
        "account_number": "…",
        "bank_name": "Example Bank",
        "routing_number": "123456780"
      },
      "input_schema": {
        "$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"
      },
      "name": "check_banking_format",
      "title": "Check banking identifiers for well-formedness"
    },
    {
      "description": "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": {
        "audience": "analyst",
        "run_id": "run_…"
      },
      "input_schema": {
        "$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"
      },
      "name": "explain_verification_run",
      "title": "Explain a run in plain language"
    },
    {
      "description": "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": {},
      "input_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {},
        "type": "object"
      },
      "name": "get_evidence_requirements",
      "title": "Get evidence requirements"
    },
    {
      "description": "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": {
        "run_id": "run_…"
      },
      "input_schema": {
        "$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"
      },
      "name": "get_review_artifact",
      "title": "Get the review artifact for a run"
    },
    {
      "description": "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": {},
      "input_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {},
        "type": "object"
      },
      "name": "get_verification_capabilities",
      "title": "Get verification capabilities"
    },
    {
      "description": "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": {
        "run_id": "run_…"
      },
      "input_schema": {
        "$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"
      },
      "name": "get_verification_run",
      "title": "Get the control trace for a run"
    },
    {
      "description": "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": {
        "package_id": "clean"
      },
      "input_schema": {
        "$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"
      },
      "name": "verify_funding_package",
      "title": "Verify a funding package"
    }
  ],
  "transport": {
    "http": "POST /mcp (stateless Streamable HTTP; OAuth sign-in with Google through Clerk, bearer token on every request)",
    "stdio": "node src/server.js"
  },
  "version": "0.1.0"
}
