← The evidence ledger
Evidence row 48128
Observed , by baseline/1.
- Kind
- listing
- About
- source_record mcp_registry:io.github.pvliesdonk/paperless-mcp
- Recorded
- Previous row
- None: the first of its kind about this subject
- Body SHA-256
- bbd0364cee44d1aa447bfedc67dde578bdd64f0efedffa0af378c163e8e24f95
- Leaf
- 0x74e089dbdbc079f199ecbc4dcdad0750c06bb1a4579a5c93723cd522b8b94212
What was observed
{
"endpoints": [
[
"web",
"https://pvliesdonk.github.io/paperless-mcp/"
]
],
"name": "Paperless MCP",
"owner_address": null,
"raw": {
"_meta": {
"io.modelcontextprotocol.registry/official": {
"isLatest": true,
"publishedAt": "2026-09-21T18:08:55.928958Z",
"status": "active",
"statusChangedAt": "2026-09-21T18:08:55.928958Z",
"updatedAt": "2026-09-21T18:08:55.928958Z"
}
},
"server": {
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
"description": "Paperless-NGX over MCP: search, read, upload and tag documents; manage correspondents and types.",
"name": "io.github.pvliesdonk/paperless-mcp",
"packages": [
{
"environmentVariables": [
{
"default": "file:///data/state",
"description": "Persistent-state backend URL shared by every pvl-core subsystem that needs state. `memory://` is in-process and lost on restart; `file:///path` persists on one server; `redis://`, `dynamodb://` and `mongodb://` each need their matching extra. When unset, defaults to `file:///data/state` (the volume family Docker images mount), or to `memory://` (with a warning) on a host where that directory is not usable.",
"name": "PAPERLESS_MCP_KV_STORE_URL"
},
{
"description": "Comma-separated explicit tool names this instance exposes; every other tool is hidden from listings and cannot be invoked. Names matching no registered tool are inert. Mutually exclusive with `tools_deny`. Takes effect through `apply_tool_visibility`.",
"name": "PAPERLESS_MCP_TOOLS_ALLOW"
},
{
"description": "Comma-separated explicit tool names hidden from this instance (absent from listings, cannot be invoked). Names matching no registered tool are inert. Mutually exclusive with `tools_allow`. Takes effect through `apply_tool_visibility`.",
"name": "PAPERLESS_MCP_TOOLS_DENY"
},
{
"description": "Rename this server instance; defaults to the project name.",
"name": "PAPERLESS_MCP_SERVER_NAME"
},
{
"description": "Concise routing context that distinguishes this deployment's material or responsibility.",
"name": "PAPERLESS_MCP_INSTANCE_DESCRIPTION"
},
{
"description": "Deployment-specific behavioral policy added to the generated MCP instructions.",
"name": "PAPERLESS_MCP_INSTRUCTIONS_EXTRA"
},
{
"description": "Legacy: replaces all generated MCP instructions (deprecated; use _INSTANCE_DESCRIPTION for routing and _INSTRUCTIONS_EXTRA for policy).",
"name": "PAPERLESS_MCP_INSTRUCTIONS"
},
{
"choices": [
"DEBUG",
"INFO",
"WARNING",
"ERROR",
"CRITICAL"
],
"default": "INFO",
"description": "Log level for every logger in the process, FastMCP's included (DEBUG / INFO / WARNING / ERROR / CRITICAL). The -v CLI flag overrides to DEBUG. The unprefixed FASTMCP_LOG_LEVEL still works for one major version and logs a deprecation warning.",
"name": "PAPERLESS_MCP_LOG_LEVEL"
},
{
"choices": [
"rich",
"json"
],
"description": "Log rendering. rich is one colour event key=value line per record, for a terminal; json is one JSON object per record, for a collector. Unset picks rich when stderr is a terminal and json everywhere else, so a container or journald gets JSON with no configuration.",
"name": "PAPERLESS_MCP_LOG_FORMAT"
},
{
"description": "Base URL of the Paperless-NGX REST API, without a trailing slash. The server refuses to start without it.",
"name": "PAPERLESS_MCP_PAPERLESS_URL"
},
{
"description": "Paperless service-account token used for outbound API requests. The server refuses to start without it.",
"isSecret": true,
"name": "PAPERLESS_MCP_API_TOKEN"
},
{
"default": "30.0",
"description": "Per-request HTTP timeout in seconds.",
"format": "number",
"name": "PAPERLESS_MCP_HTTP_TIMEOUT_SECONDS"
},
{
"default": "2",
"description": "Retries for idempotent requests after network errors or 5xx responses.",
"format": "number",
"name": "PAPERLESS_MCP_HTTP_RETRIES"
},
{
"default": "25",
"description": "Default page size for list tools, from 1 through 100.",
"format": "number",
"name": "PAPERLESS_MCP_DEFAULT_PAGE_SIZE"
},
{
"description": "Public Paperless UI URL for user-visible links; defaults to PAPERLESS_URL.",
"name": "PAPERLESS_MCP_PAPERLESS_PUBLIC_URL"
},
{
"default": "3600.0",
"description": "Link lifetime in seconds when the caller requests no explicit TTL.",
"format": "number",
"name": "PAPERLESS_MCP_TRANSFER_TTL_DEFAULT_S"
},
{
"default": "86400.0",
"description": "Ceiling in seconds a caller-requested link TTL is clamped to.",
"format": "number",
"name": "PAPERLESS_MCP_TRANSFER_TTL_MAX_S"
},
{
"default": "60.0",
"description": "Post-success grace window in seconds: a served token's TTL shrinks to this so a stalled transfer can retry within it.",
"format": "number",
"name": "PAPERLESS_MCP_TRANSFER_GRACE_TTL_S"
},
{
"default": "60.0",
"description": "Crashed-handler reclaim window in seconds for an in-flight reservation.",
"format": "number",
"name": "PAPERLESS_MCP_TRANSFER_LEASE_S"
},
{
"default": "104857600",
"description": "Maximum size in bytes of a single upload.",
"format": "number",
"name": "PAPERLESS_MCP_TRANSFER_MAX_UPLOAD_BYTES"
}
],
"identifier": "pvliesdonk-paperless-mcp",
"registryType": "pypi",
"runtimeHint": "uvx",
"transport": {
"type": "stdio"
},
"version": "3.0.0"
},
{
"environmentVariables": [
{
"default": "3",
"description": "Seconds SIGTERM may spend draining in-flight requests before the HTTP server exits. Keep it at or below the termination grace period the orchestrator allows. `0` drops in-flight requests immediately.",
"format": "number",
"name": "PAPERLESS_MCP_SHUTDOWN_GRACE_S"
},
{
"description": "Public base URL of the deployed server, for example `https://mcp.example.com`. Required for OIDC. Also the fallback source of the MCP Apps domain when `app_domain` is unset.",
"name": "PAPERLESS_MCP_BASE_URL",
"placeholder": "https://mcp.example.com"
},
{
"description": "Single shared bearer token; enables bearer auth unless `bearer_tokens_file` is set, which takes precedence.",
"isSecret": true,
"name": "PAPERLESS_MCP_BEARER_TOKEN",
"placeholder": "<secret>"
},
{
"description": "OIDC discovery document URL, for example `https://auth.example.com/.well-known/openid-configuration`.",
"name": "PAPERLESS_MCP_OIDC_CONFIG_URL",
"placeholder": "https://auth.example.com/.well-known/openid-configuration"
},
{
"description": "OIDC client identifier registered with the provider.",
"name": "PAPERLESS_MCP_OIDC_CLIENT_ID",
"placeholder": "mcp-client"
},
{
"description": "OIDC client secret registered with the provider.",
"isSecret": true,
"name": "PAPERLESS_MCP_OIDC_CLIENT_SECRET",
"placeholder": "your-client-secret"
},
{
"description": "Expected `aud` claim; tokens issued for another audience are rejected.",
"name": "PAPERLESS_MCP_OIDC_AUDIENCE",
"placeholder": "mcp-api"
},
{
"default": "openid",
"description": "Scopes a caller must present, space- or comma-separated. Defaults to `openid` in oidc-proxy mode.",
"name": "PAPERLESS_MCP_OIDC_REQUIRED_SCOPES"
},
{
"default": "openid offline_access",
"description": "Scopes advertised to MCP clients in protected-resource metadata, space- or comma-separated. Overrides the default `openid offline_access`; `oidc_required_scopes` is always added on top. Set this when the registered client is not permitted `offline_access`, or to have clients request extra claim scopes (such as `groups`) without also requiring them in every token.",
"name": "PAPERLESS_MCP_OIDC_ADVERTISED_SCOPES"
},
{
"default": "derived",
"description": "Signing key for issued tokens; used in oidc-proxy mode only. When unset, the key is derived deterministically from `oidc_client_secret`, so tokens survive a restart. Rotating that secret then invalidates every issued token. Set this explicitly to decouple token validity from secret rotation. Generate with `openssl rand -hex 32`.",
"isSecret": true,
"name": "PAPERLESS_MCP_OIDC_JWT_SIGNING_KEY"
},
{
"default": "false",
"description": "Validate the access token instead of the id token.",
"format": "boolean",
"name": "PAPERLESS_MCP_OIDC_VERIFY_ACCESS_TOKEN"
},
{
"default": "file:///data/state",
"description": "Persistent-state backend URL shared by every pvl-core subsystem that needs state. `memory://` is in-process and lost on restart; `file:///path` persists on one server; `redis://`, `dynamodb://` and `mongodb://` each need their matching extra. When unset, defaults to `file:///data/state` (the volume family Docker images mount), or to `memory://` (with a warning) on a host where that directory is not usable.",
"name": "PAPERLESS_MCP_KV_STORE_URL"
},
{
"description": "MCP Apps iframe domain, used for CSP sandboxing. Overrides the host derived from `base_url`.",
"name": "PAPERLESS_MCP_APP_DOMAIN"
},
{
"description": "Comma-separated explicit tool names this instance exposes; every other tool is hidden from listings and cannot be invoked. Names matching no registered tool are inert. Mutually exclusive with `tools_deny`. Takes effect through `apply_tool_visibility`.",
"name": "PAPERLESS_MCP_TOOLS_ALLOW"
},
{
"description": "Comma-separated explicit tool names hidden from this instance (absent from listings, cannot be invoked). Names matching no registered tool are inert. Mutually exclusive with `tools_allow`. Takes effect through `apply_tool_visibility`.",
"name": "PAPERLESS_MCP_TOOLS_DENY"
},
{
"description": "Explicit auth-mode override, accepting `remote` or `oidc-proxy` (case- and whitespace-insensitive). When unset the mode is auto-detected from which auth variables are set; the override exists because having all four OIDC variables set is ambiguous between those two modes. Other values are ignored with a warning.",
"name": "PAPERLESS_MCP_AUTH_MODE"
},
{
"description": "Path to a TOML file mapping bearer tokens to subjects; overrides the single-token `bearer_token` mode.",
"format": "filepath",
"name": "PAPERLESS_MCP_BEARER_TOKENS_FILE",
"placeholder": "/etc/paperless-mcp/tokens.toml"
},
{
"default": "bearer-anon",
"description": "Subject assigned to the single-token bearer mode; ignored when `bearer_tokens_file` is set, since mapped mode carries per-token subjects.",
"name": "PAPERLESS_MCP_BEARER_DEFAULT_SUBJECT"
},
{
"description": "Rename this server instance; defaults to the project name.",
"name": "PAPERLESS_MCP_SERVER_NAME"
},
{
"description": "Concise routing context that distinguishes this deployment's material or responsibility.",
"name": "PAPERLESS_MCP_INSTANCE_DESCRIPTION"
},
{
"description": "Deployment-specific behavioral policy added to the generated MCP instructions.",
"name": "PAPERLESS_MCP_INSTRUCTIONS_EXTRA"
},
{
"description": "Legacy: replaces all generated MCP instructions (deprecated; use _INSTANCE_DESCRIPTION for routing and _INSTRUCTIONS_EXTRA for policy).",
"name": "PAPERLESS_MCP_INSTRUCTIONS"
},
{
"default": "/mcp",
"description": "Mount path for the MCP endpoint; the health routes derive their prefix from it.",
"name": "PAPERLESS_MCP_HTTP_PATH"
},
{
"choices": [
"status",
"standard",
"full"
],
"default": "standard",
"description": "How much the unauthenticated /health and /health/ready bodies say: status, standard (adds name, version and per-check verdicts), or full (adds redacted reasons; trusted networks only).",
"name": "PAPERLESS_MCP_HEALTH_DETAIL"
},
{
"default": "1000",
"description": "Run the server process as this UID; the container entrypoint reassigns ownership of writable paths to match.",
"format": "number",
"name": "PUID"
},
{
"default": "1000",
"description": "Run the server process as this GID; pair with PUID to match the owner of a mounted volume.",
"format": "number",
"name": "PGID"
},
{
"choices": [
"DEBUG",
"INFO",
"WARNING",
"ERROR",
"CRITICAL"
],
"default": "INFO",
"description": "Log level for every logger in the process, FastMCP's included (DEBUG / INFO / WARNING / ERROR / CRITICAL). The -v CLI flag overrides to DEBUG. The unprefixed FASTMCP_LOG_LEVEL still works for one major version and logs a deprecation warning.",
"name": "PAPERLESS_MCP_LOG_LEVEL"
},
{
"choices": [
"rich",
"json"
],
"description": "Log rendering. rich is one colour event key=value line per record, for a terminal; json is one JSON object per record, for a collector. Unset picks rich when stderr is a terminal and json everywhere else, so a container or journald gets JSON with no configuration.",
"name": "PAPERLESS_MCP_LOG_FORMAT"
},
{
"description": "Base URL of the Paperless-NGX REST API, without a trailing slash. The server refuses to start without it.",
"name": "PAPERLESS_MCP_PAPERLESS_URL"
},
{
"description": "Paperless service-account token used for outbound API requests. The server refuses to start without it.",
"isSecret": true,
"name": "PAPERLESS_MCP_API_TOKEN"
},
{
"default": "30.0",
"description": "Per-request HTTP timeout in seconds.",
"format": "number",
"name": "PAPERLESS_MCP_HTTP_TIMEOUT_SECONDS"
},
{
"default": "2",
"description": "Retries for idempotent requests after network errors or 5xx responses.",
"format": "number",
"name": "PAPERLESS_MCP_HTTP_RETRIES"
},
{
"default": "25",
"description": "Default page size for list tools, from 1 through 100.",
"format": "number",
"name": "PAPERLESS_MCP_DEFAULT_PAGE_SIZE"
},
{
"description": "Public Paperless UI URL for user-visible links; defaults to PAPERLESS_URL.",
"name": "PAPERLESS_MCP_PAPERLESS_PUBLIC_URL"
},
{
"default": "3600.0",
"description": "Link lifetime in seconds when the caller requests no explicit TTL.",
"format": "number",
"name": "PAPERLESS_MCP_TRANSFER_TTL_DEFAULT_S"
},
{
"default": "86400.0",
"description": "Ceiling in seconds a caller-requested link TTL is clamped to.",
"format": "number",
"name": "PAPERLESS_MCP_TRANSFER_TTL_MAX_S"
},
{
"default": "60.0",
"description": "Post-success grace window in seconds: a served token's TTL shrinks to this so a stalled transfer can retry within it.",
"format": "number",
"name": "PAPERLESS_MCP_TRANSFER_GRACE_TTL_S"
},
{
"default": "60.0",
"description": "Crashed-handler reclaim window in seconds for an in-flight reservation.",
"format": "number",
"name": "PAPERLESS_MCP_TRANSFER_LEASE_S"
},
{
"default": "104857600",
"description": "Maximum size in bytes of a single upload.",
"format": "number",
"name": "PAPERLESS_MCP_TRANSFER_MAX_UPLOAD_BYTES"
}
],
"identifier": "ghcr.io/pvliesdonk/paperless-mcp:v3.0.0",
"packageArguments": [
{
"default": "8000",
"description": "Port for the HTTP transport",
"name": "--port",
"type": "named"
}
],
"registryType": "oci",
"transport": {
"type": "streamable-http",
"url": "http://localhost:{--port}/mcp"
}
}
],
"repository": {
"source": "github",
"url": "https://github.com/pvliesdonk/paperless-mcp"
},
"title": "Paperless MCP",
"version": "3.0.0",
"websiteUrl": "https://pvliesdonk.github.io/paperless-mcp/"
}
},
"source": "mcp_registry",
"summary": "Paperless-NGX over MCP: search, read, upload and tag documents; manage correspondents and types."
}What the leaf hashes
{"body":"bbd0364cee44d1aa447bfedc67dde578bdd64f0efedffa0af378c163e8e24f95","id":48128,"kind":"listing","method":"baseline/1","observed_us":1793025411385918,"prev":null,"subject":"mcp_registry:io.github.pvliesdonk/paperless-mcp","subject_kind":"source_record"}Proof
Fold these into the leaf in order, hashing each sorted pair with keccak256, to reach the root of (296695 rows).
- 0x74e08281d197beb09e71b41fc8ded569a8786195664cbd128a9fbac10274272b
- 0x6859d0ab466db4aec311abe20d2b8b7ace5d67dcd7c82ecff9b94a0d1ced1d41
- 0xa3e1c482e8ac0ba4b69270100361bc5359f97de49f819948375915f51680d5b5
- 0xc936f0e3b137d35063a2095ae0994a6cc7380761a15d5e99eaba49be265a0e15
- 0x214a41e687acdae92a0fc88e26f095d3937ec426d930062b31c254819968c2d1
- 0x1901748d5792e72ce0d56cb0d212a160717f01406ab8408a1761b553fce9285c
- 0x875c66b057e56eaa888d39f5743c0015abedbe10432f399e67b9f6acbedb13f0
- 0x5d9ecfd959448624fcc7bb660082fd2521f479ffbb5b3177d7e47189c1381fae
- 0xfa0bf377c193bc06578e3240f9e9d08e5282e2836746fc9d37a4b125f582cc28
- 0x9ee05f244b24b5c2218a463b4ab58eba1018e880e4d46ed9425dabadbdd4bc8c
- 0xff8296d2db87846f2b3d9a7a4926ee8ea17587a9a2960c155a4f0e1d36206dd8
- 0x43ccc5fffcdb82bff6ecf4ac7157c905b45d2f0362e7f7fbe908de1250b9533c
- 0xdef3cab0b4070d8ad7f4f91288da4881d19789f131b1b353621df79df04a0617
- 0xc4fe2177880ea1b0e82b6fe4c270090fd0fbe5af3a42a8cbf6a6ba2fa35625f6
- 0x15039087bf60ae9b06b756ec3cbc299760e59923a438bbd91e34d105186db0ed
- 0x2b6e23e3624a1b66e1d2298cfbce99a93ce6b13d24a58112a71802d79c5f7a76
- 0xd21942ae3214eff88e08ab04884fd4b11958b51af9a0741b7668e2d07a2c56c9
- 0x9a9024edb5069d88a324facb310a5ce8e495214bbaa968f077bede437390194f
- 0x9b9ce5b74b9bab5121612ef6b64920a8d453cbf311096a423eef9702747e868a
- Day root
- 0xf43e8dcc3d451a4788b26be904c55e8c4c0fa75c9666796c51db38d37e2c0df8
- Chained
- 0x702d5ac508f08b0d1accf36af25822d8e5660367494edd17a642fb61e158a57a
- Published
- On Arc Testnet, block 69251483: 0x495162f8936e19f0039918feebe6c307f327cd6bf8c37219620b1970041fa9ae