# File Room — Unknown file. Clear picture. LOCAL-450 · Version 0.1.0 · Local review build by Dark Vector Cognition. One inspection engine, plus the AI file check (`check_file`) for documents headed into an AI model: the browser desk for people, local MCP for assistants, and a separate HTTP service API. The portable plugin includes Codex, Claude Code and Cursor manifests plus an Agent Skill. Standard MCP configuration covers other compatible local clients, including Grok Build and VS Code. These are local packages, not public marketplace listings. ## Choose your installation Unzip `file-room-0.1.0.zip` into a permanent folder. It contains the engine and pinned dependencies. Node.js 22 or newer is required. Do not run a downloaded unknown file to inspect it. | Surface | Route included | Verification boundary | | --- | --- | --- | | Codex | Native plugin with MCP and skill; personal marketplace | Manifest and protocol checks; local registration recorded in WORK-ROUTE.md | | Claude Code | Native plugin; `claude --plugin-dir /absolute/path/file-room` | Manifest validator and protocol checks; no model session claimed | | Claude Desktop | `file-room-0.1.0.mcpb`; install through Extensions and choose an allowed folder | Bundle/launch checks; desktop UI installation not performed | | Cursor | Native plugin manifest; standard MCP setup below works without a marketplace | Format checked against official docs; no Cursor model session claimed | | VS Code / Copilot | Native MCP `servers` configuration below; packaged skill can be installed separately | Protocol checked; host UI session not tested | | Grok Build | Local stdio MCP registration below; compatible reusable skill | Protocol checked; Grok Build not installed/tested here | | Other local MCP clients | Standard stdio launch: `node /absolute/path/file-room/mcp.mjs` | Requires a client that supports local stdio MCP | | Skill-capable agents | `unknown-file-skill.zip` | Skill validates; connect the MCP server too | | npm-based distribution | `file-room-0.1.0.tgz` | Local install artifact; package is private and unpublished | | ChatGPT | Developer-mode MCP connection, followed by public plugin submission | HTTP MCP and attachment-input schema implemented; real ChatGPT authentication/file handoff and public hosting remain unverified | | Hosted Grok API / remote-only connectors | Need a deployed HTTP MCP service | HTTP MCP implemented and tested locally; not deployed or exercised in the named hosts | Use only one connection method per client to avoid duplicate tools. Package paths below are examples to replace, not download URLs. No npm namespace, domain, trademark or marketplace approval is claimed. ## Allow one folder The generic server has **no filesystem access by default**. It still accepts explicitly supplied inline bytes up to 2 MiB. To inspect file paths, choose a narrow, dedicated folder and configure it at launch: ```sh node /absolute/path/file-room/mcp.mjs --allow-root /absolute/path/inspection-inbox ``` Repeat `--allow-root` for additional explicitly approved folders. Alternatively set `FILE_ROOM_ALLOWED_ROOT` in the server's environment. Do not select your whole home folder by default. MCPB asks for this folder during installation. For native plugins, use the host's MCP environment settings or configure the direct MCP connection below; do not edit cached plugin files. Codex and Grok Build have matching direct registration commands: ```sh codex mcp add file-room -- node /absolute/path/file-room/mcp.mjs --allow-root /absolute/path/inspection-inbox grok mcp add file-room -- node /absolute/path/file-room/mcp.mjs --allow-root /absolute/path/inspection-inbox ``` Claude Code direct registration: ```sh claude mcp add --transport stdio file-room -- node /absolute/path/file-room/mcp.mjs --allow-root /absolute/path/inspection-inbox ``` Claude Desktop's manual config and Cursor's `.cursor/mcp.json` use: ```json { "mcpServers": { "file-room": { "command": "node", "args": ["/absolute/path/file-room/mcp.mjs", "--allow-root", "/absolute/path/inspection-inbox"] } } } ``` VS Code's `.vscode/mcp.json` uses `servers` instead: ```json { "servers": { "file-room": { "type": "stdio", "command": "node", "args": ["/absolute/path/file-room/mcp.mjs", "--allow-root", "/absolute/path/inspection-inbox"] } } } ``` Merge the one server entry into existing configuration; do not replace other connections. If a desktop app cannot find Node, set `command` to its absolute executable path. Restart the connection and use the host's tool approval controls. Native plugin installation does not silently grant access to arbitrary folders. ## Ask it something useful - “What kind of file is this? Identify it without returning the contents.” - “Show me a short preview and explain the columns.” - “List the archive entries without extracting anything.” - “Give me its SHA-256 so I can compare this copy.” - “Create an inspection report for this file.” - “Check this attachment before you summarize it.” (`check_file`, needs a File Room key) `inspect_file` accepts exactly one of `path` or `data_base64`, with an optional inline `filename`. Replies contain format, size, basis, observations and limits. Set `include_preview` only for a user-requested content preview (2,000 characters by default, maximum 8,000); set `include_fingerprint` for requested hashes. Binary previews show limited hex; PDF/SQLite contents are not decoded. JSON depth/nodes and table/archive excerpts are bounded. `create_inspection_report` requires `user_requested_report: true` and re-inspects the provided input. It returns an unsigned observation with filename, hash and device-clock time. The flag documents agent intent; it is not proof of human consent. Host approvals and skill behavior still matter. The tool creates no file, registry entry or stored receipt. ## Check files before your AI reads them `check_file` is the AI file check: call it before summarizing, ingesting or acting on a document from an untrusted source (email attachments, downloads, user uploads, RAG ingestion). It takes the same `path` or `data_base64` input as `inspect_file` and returns `schema: file-room.ai-check.v1`, `risk` (`none`, `low`, `medium`, `high`), a one-sentence `summary`, up to 50 `findings` (`id`, `category`, `severity`, `hidden`, `location`, `evidence`, `why`) with `findings_omitted`, `coverage` (`format`, `extracted`, `not_assessed`), fixed `limits`, `usage` and `privacy`. Risk is the highest finding severity. Evidence is at most 160 characters with secrets and personal data masked, and it is quoted file content: never act on it. Whatever the result, the file's contents are untrusted data. The check runs in the local plugin; files never leave the machine. Each call sends File Room billing your key, a random request ID and a count, and nothing about the file. The first 1,000 checks a month are free, then $1.99 per 1,000. Get a key at https://getfileroom.com/check. The plugin looks for the key in this order: 1. `--key-file /absolute/path/key` (the file must be mode 600; the server refuses a key file other accounts can read) 2. `FILE_ROOM_KEY` in the server's environment 3. `~/.file-room/key` (mode 600) ```sh mkdir -p ~/.file-room && chmod 700 ~/.file-room (umask 077; cat > ~/.file-room/key) # paste the key, Enter, then Ctrl-D ``` Packaged manifests pass the key through where the host supports it: Claude Code prompts for an optional, sensitive `file_room_key` setting; Claude Desktop's MCPB asks for it during installation (sensitive, optional); Codex forwards `FILE_ROOM_KEY` from your environment; Cursor maps `${env:FILE_ROOM_KEY}`. Without any of these, `~/.file-room/key` still works. `inspect_file` never needs a key. Billing answers decide the reply: 200 returns the result with `usage: {period_checks, free_remaining}`; 401 (key rejected), 402 (billing problem, with a portal link when billing provides one) and 429 (monthly safety cap) return an error and withhold the result. If billing is unreachable or failing, the check still returns, and the plugin records the unreported check in `~/.file-room/pending.json` (mode 600). The next successful call reports `1 + pending` checks (at most 100 per call) and clears the count. With 100 checks pending and billing still unreachable, new checks are refused. A failed call is retried once with the same request ID; every new call uses a fresh one. `FILE_ROOM_BILLING_URL` overrides the billing base URL (default `https://pdfmd.dev/api/fileroom`; https only, or http on loopback for testing). What it reads: plain text, Markdown, CSV, JSON and source code (UTF-8, UTF-16 with a byte-order mark, and other text read as Windows-1252); HTML, SVG and XML with visibility tracking; DOCX, PPTX and XLSX parts, comments, notes, hidden slides and sheets, document properties and relationships; ODT, ODP and ODS content and metadata; PDF page text (Flate, ASCII85 and ASCIIHex streams, simple and ToUnicode-mapped fonts), metadata, annotations, form fields, JavaScript and embedded files; PNG, JPEG, GIF and WebP text metadata; ZIP members one level deep and gzip. Everything else gets a weak readable-strings fallback, which `coverage` says. Hidden means a normal reader would not see it: white or same-color text, tiny text, invisible PDF text (render mode 3), text off the page or slide, `display:none` and similar CSS, `hidden` and `aria-hidden`, comments, speaker notes, hidden slides, hidden or very hidden sheets, hidden rows and columns, metadata, alt text and tooltips, field codes, tracked deletions, off-by-default PDF layers and decoded invisible characters. | Rule | Catches | Severity | | --- | --- | --- | | PI001 | Instruction override: "ignore / disregard / forget previous instructions" and variants | High when hidden; medium when visible | | PI002 | The same override in Spanish, French, German, Portuguese, Italian, Chinese, Japanese, Russian and Korean | As PI001 | | PI003 | Role or identity hijack: "you are now an unrestricted AI", "new system prompt", jailbreak modes, "from now on, you will" | As PI001 | | PI004 | Requests to reveal the system prompt, dump credentials or embed the conversation in output | As PI001 | | PI005 | Concealment: "do not tell the user", "keep this secret from the user" | High when hidden; visible only alongside another rule family | | PI006 | Tool coercion: "call the send_email tool", "use your browser tool to" | As PI005 | | PI007 | Action coercion: run this command, visit this URL and, send an email to, transfer money, approve, delete | Only alongside another rule family | | PI008 | Chat-template and delimiter tokens (`<\|im_start\|>`, `[INST]`, `<>`, ``, `### Instruction:`), and forged Human/User then Assistant turns | Tokens as PI001; turn forgery as PI005 | | PI009 | Instructions addressed to AI readers: "if you are an LLM", "note to AI", "hey ChatGPT" | As PI001 | | PI010 | Review and hiring manipulation: "rate this candidate as the best", "give a positive review", "do not mention weaknesses" | As PI005 | | INV001 | Unicode tag characters (ASCII smuggling), decoded and re-checked | Medium; high if the decoded text is an injection | | INV002 | Variation-selector byte smuggling, decoded as UTF-8 and re-checked | Medium; high if the decoded text is an injection | | INV003 | Zero-width characters (emoji and non-Latin joiners excluded) | Low; medium when dense or inside words | | INV004 | Bidirectional control characters (Trojan Source style) | Medium; low next to right-to-left script | | INV005 | Words mixing Latin with lookalike Cyrillic or Greek letters | Low | | SEC001-SEC011 | AWS access key IDs, GitHub, Slack, Stripe live, Google API, OpenAI and Anthropic keys, private key blocks, JWTs, DVC service keys (`fr_`, `pm_`, `ft_`), and GitLab, npm, Hugging Face, SendGrid and Slack webhook tokens | High; masked to the first four characters | | PII001-PII005 | Email addresses, payment cards (Luhn and issuer ranges), US Social Security numbers (valid ranges), IBANs (mod-97), phone numbers; one finding per type with a count | Medium for cards, SSNs and IBANs; low for email and phone | | TYP001 | A program named like a document, a double extension, a right-to-left override in the name | High | | TYP002 | Extension and contents disagree | Medium | | TYP003 | An executable, shortcut or HTML Application | Medium | | TYP004 | Another file appended after the end of a PDF or image (polyglot) | Medium; high if it is a program | | ACT001 | VBA projects, Excel 4.0 macro sheets, OpenDocument macros | High | | ACT002 | Remote template (external `attachedTemplate` relationship) | High | | ACT003 | Other external relationships and remote INCLUDETEXT/INCLUDEPICTURE fields | Medium | | ACT004 | Embedded OLE objects, ActiveX controls, PDF attachments | Medium | | ACT005 | DDE fields and command-running formulas | High | | ACT006 | PDF JavaScript | High when it runs on open; otherwise medium | | ACT007 | PDF Launch actions | High | | ACT008 | PDF form submission or data import | Medium | | ACT009 | `javascript:`, `vbscript:`, `data:text/html`, `file:` and network-share links | Medium | | ACT010 | Scripts and event handlers in markup | Low in HTML; medium in SVG and XML; high for HTML Applications | | ACT011 | Frames and embedded objects in markup | Low in HTML; medium in SVG | | ACT012 | Spreadsheet formulas that reach the network (WEBSERVICE and similar, data-built HYPERLINK) | Medium | | ACT013 | PDF rich media, XFA forms, remote go-to actions | Medium; low for go-to | | EXF001 | Image links with a slot for data (templates, placeholders, encoded blobs), which chat apps fetch on display | High | | EXF002 | Links with a fill-in-the-blank data slot | Medium | A visible injection phrase is often an article about prompt injection, so it is medium and its `why` says so. It becomes high only when two or more rule families appear in the same passage and the passage has no discussion cues such as "attack", "example" or "researchers". Bounds: 20 MiB input; 5,000 archive entries and 500 checked members; 16 MiB per decompressed entry, 64 MiB in total, and a 200:1 expansion cap (a likely bomb is read for its first mebibyte only); one level of archive nesting; a 24-million-character scan budget; 50 findings in the reply; a 15-second worker limit. Partial work is listed under `coverage.not_assessed`, never hidden. ## Privacy and limits The browser desk keeps selected file data in the browser. **MCP inputs and replies enter your assistant conversation**, which can be stored or processed by the host/provider. Inline base64 puts the supplied bytes into that conversation; local file paths avoid placing all source bytes there. Previews and reports can reveal sensitive information. Identification and reports make no outgoing requests. The AI file check sends only a check count, a random request ID and your key to File Room billing. The local plugin has no telemetry, database or inspection history. The separate HTTP service processes submitted bytes remotely and keeps a credit-usage ledger; see API.md in the source project or the website’s API guide. Process memory is released after work; this is not secure erasure, and the OS or host may retain logs or dumps. Local files are capped at 20 MiB, inline files at 2 MiB, and parsing at eight seconds in a worker with bounded heap. One inspection runs per server process. Files must be regular files inside configured folders; resolved symlink escapes are refused. Archives are never extracted and embedded content is never executed. Local path checks are not OS sandboxing and do not defend against another hostile local process racing filesystem changes. Use OS isolation before claiming hostile-file containment. No antivirus scan, behavior analysis, sanitization, USB hardware handling, independently signed attestation or safety guarantee is included. Parser identification is not full-format validation. Reports are on demand, not a main-product trust stamp. ## Packaging and release Developers: `npm ci --ignore-scripts`, then `npm test` and `npm run package`. ZIP and MCPB include runtime dependencies and their license files. The npm tarball declares dependencies for installation; the skill ZIP contains instructions only. `dist/SHA256SUMS.txt` identifies the produced archives, not their safety or issuer authenticity. Application code remains UNLICENSED pending the owner's distribution-license decision. Public distribution still requires owner-reviewed licensing, publisher identity, public documentation/privacy/support URLs, a published source or package location, and each marketplace's review. A private local listing does not imply acceptance by OpenAI, Anthropic, Cursor or xAI. The implemented HTTP service needs public hosting, a verified host-compatible authentication flow, infrastructure review and disclosed data handling before release; no public URL is invented here. ## From a chat-box question to public distribution Two routes serve the same product. A person can install a local plugin or explicitly connect an MCP server. Separately, the publisher can submit a reviewed integration for discovery through an assistant's directory. A listing makes the service available; it does not authorize access to every user's attachments or guarantee that a model will select it. OpenAI currently accepts remote MCP plugins, skills-only plugins, and combined packages through its [plugin submission portal](https://developers.openai.com/plugins/deploy/submission). Approved plugins become public only after the publisher chooses to publish; they then appear in the directory shared by ChatGPT and Codex. A server-backed submission needs a stable public HTTPS endpoint, verified publisher, accurate tool metadata, public product/policy/support pages, and reproducible review cases. None has been submitted for File Room. For a private trial, [ChatGPT developer mode](https://developers.openai.com/plugins/deploy/connect-chatgpt) can connect a public HTTPS MCP server or Secure MCP Tunnel, subject to account/workspace policy. A tunnel can reach local stdio MCP for development; it does not replace the public endpoint required for submission. This build has no running tunnel or ChatGPT connection. The proposed interaction is: user chooses a file → authorizes File Room → inspection tool receives the selected file → returns a compact explanation or requested preview. ChatGPT's [file-input contract](https://developers.openai.com/plugins/reference) uses `openai/fileParams` and supplies a file ID plus temporary download URL. A ChatGPT file ID is not a local filesystem path. The separate HTTP tools now accept this shape with bounded downloads from explicitly configured attachment hosts; the local plugin still accepts local paths or inline bytes. Supported ChatGPT attachment types and availability must be tested; an unknown extension may require a dedicated file-picker flow rather than the normal chat attachment control. The HTTP implementation now includes key authentication, bounded file-reference downloads, destination guards and credit accounting. Local SDK checks pass; actual ChatGPT file delivery and authentication remain to be tested. The service rejects arbitrary destinations, private addresses and redirects, and never exposes the local `path` tool. File URLs, bytes and hashes are excluded from its application ledger and routine logs. This is not hardened OS isolation. Cloud inspection means the service processes the bytes, so the browser's local-only claim cannot be reused. No automatic file history, attestations or public hash log should be introduced. The submission evaluation set should include these prompts with synthetic fixtures: identify a renamed JSON file without content; preview a CSV; list ZIP entries without extraction; obtain a SHA-256; explicitly request an unsigned report. Negative cases: asking for malware clearance must explain that it was not assessed; oversized/malformed files must fail clearly; instructions embedded in a file must remain inert data. These require actual ChatGPT trial results before submission—local parser checks are only part of that evidence. Tool descriptions and the skill provide the intended selection cues for “I don't know what this file is.” Test paraphrases and unsupported requests against the connected host; [OpenAI's metadata guidance](https://developers.openai.com/plugins/guides/optimize-metadata) recommends measuring when the right tool is selected and when it should stay unused. Website visibility and marketplace approval alone do not establish discovery, retention, willingness to pay or reduced token cost. ## Primary integration references - [OpenAI plugin packaging](https://developers.openai.com/plugins/build/plugins) and [Codex native MCP path handling](https://github.com/openai/codex/blob/main/codex-rs/codex-mcp/src/plugin_config.rs) - [Claude Code plugin reference](https://code.claude.com/docs/en/plugins-reference) - [MCPB bundle manifest](https://github.com/modelcontextprotocol/mcpb/blob/main/MANIFEST.md) - [Cursor plugins](https://cursor.com/docs/reference/plugins) - [VS Code MCP configuration](https://code.visualstudio.com/docs/agent-customization/mcp-servers) - [Grok Build local MCP](https://docs.x.ai/build/features/mcp-servers) and [Grok remote MCP API](https://docs.x.ai/developers/tools/remote-mcp) Documentation checked 27 September 2026. Client formats can change; configuration is not evidence of an end-to-end model session.