|
1 | 1 |
|
| 2 | +# ============================================================================= |
| 3 | +# Core configuration |
| 4 | +# ============================================================================= |
| 5 | +# USPTO_API_KEY is the only REQUIRED value. Get one (free) from |
| 6 | +# https://data.uspto.gov/myodp/ . On Windows the setup script stores it with |
| 7 | +# DPAPI encryption instead of a plaintext .env; see API_KEY_GUIDE.md. |
| 8 | +# USPTO_API_KEY= |
| 9 | + |
| 10 | +# Document extraction reads the PDF's native text layer with pypdf first. |
| 11 | +# Scanned pages need an OCR backend; either of the two below is sufficient, |
| 12 | +# and neither is required for text-layer PDFs. |
| 13 | +# - Mistral OCR (hosted, metered): |
| 14 | +# MISTRAL_API_KEY= |
| 15 | +# MISTRAL_OCR_MODEL=mistral-ocr-latest # pin a dated slug for determinism |
| 16 | +# - Docling (self-hosted, e.g. docling-serve): base URL of the instance |
| 17 | +# DOCLING_SERVE_URL=https://your-docling-host.example.com |
| 18 | + |
| 19 | +# Transport. "stdio" (Claude Desktop) or "http" (Docker / claude.ai). |
| 20 | +# HTTP mode additionally requires INTERNAL_AUTH_SECRET. |
| 21 | +# FASTMCP_TRANSPORT=stdio |
| 22 | +# FASTMCP_HOST=127.0.0.1 |
| 23 | +# FASTMCP_PORT=8000 |
| 24 | +# INTERNAL_AUTH_SECRET= # openssl rand -hex 32; must match PFW's |
| 25 | + |
| 26 | +# Download proxy. See README "Environment variables" for the full list. |
| 27 | +# FPD_PROXY_PORT=8081 |
| 28 | +# CENTRALIZED_PROXY_URL= # full base URL of the PFW centralized proxy |
| 29 | + |
2 | 30 | # ============================================================================= |
3 | 31 | # OAuth sign-in (dual IdP: Google + Entra ID) — HTTP mode only |
4 | 32 | # ============================================================================= |
5 | 33 | # "none" (default) keeps today's behavior. "oauth" turns the HTTP surface into |
6 | 34 | # an OAuth 2.1 authorization server: users sign in with Google/Microsoft and |
7 | 35 | # must have an active row in the mcp_users table (see |
8 | | -# scripts/manage_mcp_users.py and the FPD_manage_users tool). In the suite |
9 | | -# deployment FPD points FPD_AUTH_DB_PATH at the shared paid-tier file |
10 | | -# hosted by PFW (shared bind mount, same host only). |
| 36 | +# scripts/manage_mcp_users.py and the FPD_manage_users tool). In a suite |
| 37 | +# deployment FPD points FPD_AUTH_DB_PATH at the shared user database |
| 38 | +# hosted alongside PFW (shared bind mount, same host only). |
11 | 39 | # FPD_AUTH_MODE=oauth |
12 | 40 | # FPD_AUTH_BASE_URL=https://your-public-hostname.example.com |
13 | 41 | # FPD_AUTH_JWT_SECRET= # openssl rand -hex 32 — rotating logs everyone out |
|
26 | 54 | # # this only to whichever internal caller |
27 | 55 | # # actually needs to manage users; most |
28 | 56 | # # deployments should leave it unset. |
| 57 | +# FPD_AUTH_ALLOWED_REDIRECT_HOSTS= # comma-separated EXTRA hosts allowed to |
| 58 | +# # dynamically register a redirect_uri. claude.ai, |
| 59 | +# # claude.com, anthropic.com, chatgpt.com, openai.com, |
| 60 | +# # localhost and 127.0.0.1 are always allowed |
| 61 | +# # (subdomains included). Clients already registered |
| 62 | +# # are unaffected. |
| 63 | +# FPD_AUTH_OPEN_REGISTRATION=false # true restores fully open Dynamic Client |
| 64 | +# # Registration. Leave false: an arbitrary redirect_uri |
| 65 | +# # is the first half of an identity-takeover chain. |
29 | 66 | # FPD_AUTH_REGISTER_URL= # optional "Request access" link |
30 | 67 | # FPD_AUTH_ACCESS_TTL=3600 |
31 | 68 | # FPD_AUTH_REFRESH_TTL=2592000 |
|
56 | 93 | # tool disappears. When enabled + FPD_AUTH_MODE=oauth it is additionally |
57 | 94 | # gated behind the fpd:admin scope. |
58 | 95 | # FPD_ENABLE_USER_MANAGEMENT=false |
| 96 | + |
| 97 | +# Registration gate for the 10 MCP prompt templates. Default off: no prompts |
| 98 | +# are registered (absent from prompts/list on stdio and HTTP alike) unless |
| 99 | +# this is "true". When enabled, all 10 prompt templates register as before. |
| 100 | +# FPD_ENABLE_PROMPTS=false |
| 101 | + |
| 102 | +# ============================================================================= |
| 103 | +# Response-size guard (shared/response_bounds.py) |
| 104 | +# ============================================================================= |
| 105 | +# claude.ai replaces an OVERSIZED tool result with a client-side truncation |
| 106 | +# error the server never sees: the model gets no data and no way to recover. |
| 107 | +# The cap applies to the serialized payload, so these budgets are CHARACTER |
| 108 | +# budgets (len(json.dumps(...))), never token estimates. Shared, identically |
| 109 | +# named, across the FPD/PTAB/PFW MCPs. |
| 110 | +# |
| 111 | +# Structured responses (searches, petition details) are slimmed then |
| 112 | +# truncated to fit, always with a `_bounds` marker carrying recovery |
| 113 | +# guidance. Document content (the OCR tool) gets the higher content budget |
| 114 | +# and a `_window` cursor instead — nothing is lost, it is paged via |
| 115 | +# char_offset/max_chars. |
| 116 | +# USPTO_MAX_RESPONSE_CHARS=40000 |
| 117 | +# USPTO_MAX_CONTENT_CHARS=120000 |
| 118 | +# USPTO_RESPONSE_BOUNDS_ENABLED=true # false disables the guard entirely |
| 119 | + |
| 120 | +# Per-document page cap for the Mistral OCR tier (was a hard-coded 50). |
| 121 | +# Same variable name in the PFW and PTAB MCPs. A capped extraction is always |
| 122 | +# marked (truncated / truncation_note / _bounds). |
| 123 | +# MISTRAL_OCR_MAX_PAGES=50 |
| 124 | + |
| 125 | +# Daily (UTC) ceiling on metered Mistral OCR usage. UNSET NOW MEANS THE |
| 126 | +# BUILT-IN DEFAULT of 5.00, not unlimited: leaving the only bound on a metered |
| 127 | +# third-party API switched off by default was M-21. Set 0 to opt out |
| 128 | +# explicitly. The user-facing message when the ceiling is hit is neutral; the |
| 129 | +# accounting detail stays in the server log. |
| 130 | +# MISTRAL_OCR_DAILY_BUDGET_USD=5.00 |
| 131 | + |
| 132 | +# ============================================================================= |
| 133 | +# Timeouts (F-R2: these existed but were documented only in main.py's |
| 134 | +# docstring and CLAUDE.md, not anywhere an operator tuning a deployment looks) |
| 135 | +# ============================================================================= |
| 136 | +# USPTO_TIMEOUT=30.0 # per USPTO API request |
| 137 | +# USPTO_DOWNLOAD_TIMEOUT=60.0 # PDF download, extraction AND proxy stream |
| 138 | +# DOCLING_TIMEOUT=300.0 # docling-serve extraction (tier 3) |
| 139 | +# DOCLING_MAX_PAGES=25 # tier-3 page gate; a document whose page count |
| 140 | +# # cannot be determined is refused, not admitted |
| 141 | +# FPD_TOOL_DEADLINE_SECONDS=150 # overall budget for one content-extraction |
| 142 | +# # tool call, so a slow tier returns an envelope |
| 143 | +# # instead of a client-side transport timeout |
| 144 | +# FPD_MAX_MCP_BODY_BYTES=4194304 # request body cap on the /mcp surface |
| 145 | +# FPD_MAX_PDF_BYTES=26214400 # per-document extraction byte cap (25 MB) |
| 146 | + |
| 147 | +# Error-detail mode. Unset means "production": error envelopes carry a |
| 148 | +# generic message for 401/403/429/5xx and never a `context` block. F-E8: this |
| 149 | +# variable appeared nowhere in .env.example, the Dockerfile or deploy/, so |
| 150 | +# the detailed branch was unreachable for developers too — a debug mode |
| 151 | +# nobody could turn on without reading the source. Values that enable detail: |
| 152 | +# development, dev, test. |
| 153 | +# ENVIRONMENT=production |
| 154 | + |
| 155 | +# ============================================================================= |
| 156 | +# Reverse-proxy trust (M-1) |
| 157 | +# ============================================================================= |
| 158 | +# The download-proxy IP allowlist and every rate limiter key on the caller's |
| 159 | +# address. Behind an API gateway or reverse proxy the raw ASGI peer is ONE |
| 160 | +# value for the whole internet, so the allowlist admits everyone the proxy |
| 161 | +# admits and the limiters throttle all callers as a single client. Declare |
| 162 | +# the proxy's own address (IP or CIDR, comma-separated) and X-Forwarded-For |
| 163 | +# is honored FROM THAT PEER ONLY. Leave unset for a direct deployment: the |
| 164 | +# header is then never consulted, which is the historical behavior. |
| 165 | +# FPD_TRUSTED_PROXY_IPS=172.18.0.0/16 |
0 commit comments