Nullprint
NPM · NULLPRINT-MCP · 2 COMPONENTS
Create, launch, check and drive Nullprint multi-profile browser profiles from any MCP agent.
Available components
Last scanned (12 hours ago)
Scores higher than 35% of npm servers
Category Browser Automation
How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →
Supply Chain Security50
- Malware scan not yet available for this package.Unverified
- No known CVEs affecting this package version or its production dependencies.Pass
- No install/post-install scripts declared.Pass
- No production dependencies, so there is no dependency health to assess. View diagnostics → Pass
Provenance & Transparency45
- Source repository is publicly reachable at the declared URL. View diagnostics → Pass
- Provenance check failed: no build-provenance attestation is published. See how to fix → View diagnostics → Fail
- Clear OSI-approved license (MIT).Pass
- Actively maintained (last published 0 days ago).Pass
- Disclosure check failed: no security disclosure policy was found in the source repository. See how to fix → Fail
Schema Quality & AI Usability71
- AI-judged instruction clarity (excellent).Pass
- Context-footprint check failed: tool/resource definitions use about 3521 tokens (~185/item across 19 items; 19 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management33
- Stability observed for 10 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage100
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 100% of tool parameters carry a description.Pass
Tool Safety75
- No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
- 0 of 2 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation; "profile_delete" implies "delete" and declares no destructiveHint at all, which the MCP spec reads as destructive by default. See how to fix → Fail
- An AI judge read all 20 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 23 Oct 26 −15
- Malware scan: pass → unverified ▼ security
- Schema quality: 2980 → 3521 ▼ functional
- Package version: 0.1.2 → 0.1.5 functional
- 22 Oct 26 +5
- Stability: unverified → 0.30 ▲ functional
- 13 Oct 26 +29
- Injection markers: unverified → pass ▲ security
- First check of Judged manipulation: pass security
- Stability: Stability not yet verified: not enough scan history yet (needs a 30-day window). security
- Tool coverage: unverified → 100 ▲ functional
- MCP protocol: unverified → pass ▲ functional
- First check of Schema quality: fail functional
- First check of Schema quality: excellent functional
- First check of Schema quality: fail functional
- First check of Destructive annotations: 0 functional
- First check of Tool coverage: 100 functional
- 12 Oct 26 39
First indexed and scored.
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 23 Oct 2026 · Analysed npm/nullprint-mcp@0.1.5
Provenance No attestation
The registry publishes no build provenance for this version, so there is nothing to verify.
| Result | No attestation |
|---|---|
| Ecosystem | npm |
Background: How many MCP packages publish verified provenance →
Dependencies 0 packages
| Packages resolved | 0 |
|---|---|
| Tree resolution | Complete |
Background: SBOMs and build attestations, explained →
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
profile_checkup ~224
Run the consistency checkup on an identity — is its fingerprint coherent? Every trait has one correct value given the identity's OS, browser core, and exit IP, so each item gets a verdict rather than just being displayed. Run it after changing an identity's proxy, and before trusting an identity with anything that matters. Returns {name, engine, live, summary, checks}. `summary` is "pass", "warn", or "fail" — the worst verdict among the checks. Each entry in `checks` has an id, a label, a verdict ("pass"/"warn"/"fail"/"skip"), and a detail string explaining it. "skip" means the check needs live=true, or does not apply.
| Name | Type | Req | Description |
|---|---|---|---|
| live | boolean | – | false (default) derives everything from the stored record — fast, no side effects. true additionally STARTS THE BROWSER to measure the real TLS/JA3 fingerprint and User-Agent; takes tens of seconds a… |
| name | string | yes | identity name, exactly as profiles_list reports it |
No output schema declared.
No examples provided.
profile_create ~376
Create a new identity. Its fingerprint is generated and frozen on the spot. You do not choose the fingerprint — the point of the product is that every identity gets one self-consistent, frozen set of traits that stays byte-identical across restarts. Do not create identities speculatively: they count against the installation's quota. Returns {name, os, created}. Fails with a readable message if the name is taken (409), if the quota is reached or the installation is unauthorized (403), or if an argument is rejected (422).
| Name | Type | Req | Description |
|---|---|---|---|
| engine | string | – | which browser core backs the identity. Leave unset to use this installation's default; an unknown value is rejected with the list of accepted ones. |
| force_dark | boolean | – | personal display preference, OFF by default. true inverts web pages that have no dark theme of their own (Google Ads and the like) to dark; sites may notice the changed colors, so use it only on iden… |
| group | string | – | local ledger: which account, email, or purpose this identity is bound to |
| name | string | yes | the new identity's name. Must be unique — creating a name that already exists fails rather than overwriting it. |
| note | string | – | local ledger note, free text |
| proxy | string | – | exit proxy URL, e.g. "http://user:pass@host:port" or "socks5://host:port" — any vendor. Omit for a direct connection. Test it with proxy_check first. |
| tags | array | – | local ledger tags |
| urls | array | – | startup tabs — pages opened automatically when the identity starts |
No output schema declared.
No examples provided.
profile_delete ~222
Move an identity to the recycle bin. Recoverable — this is not erasure. The identity's browser storage, cookies and logged-in sessions go to the recycle bin intact and profile_restore brings them back unchanged. It stops counting against the installation's quota while it sits there, and it no longer appears in profiles_list. A running identity is refused (409) rather than killed under itself — stop it with profile_stop first, then delete. Deleting a name that is already in the recycle bin replaces the older copy, so the older one is lost. There is deliberately NO tool here for permanent deletion. Emptying the recycle bin destroys logged-in accounts with no way back, so it is a manual action in the desktop app only — a person does it, looking at what they are about to lose. Do not look for a way around this; tell the human instead. Fails with a readable message if the identity does not exist (404), or if it is still running (409).
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | yes | identity name, exactly as profiles_list reports it |
No output schema declared.
No examples provided.
profile_restore ~120
Bring an identity back from the recycle bin, exactly as it was. Its frozen fingerprint, proxy binding, cookies and login state all come back — restoring is not re-creating, so nothing is regenerated and no logged-in account is lost. Returns {name, engine, created}. Fails with a readable message if nothing by that name is in the recycle bin (404), or if a live identity has taken the name since (409) — rename or delete that one first, then restore.
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | yes | the trashed identity's name |
No output schema declared.
No examples provided.
profile_settings ~166
Change a display setting of an existing identity. Only the settings you pass are changed; everything else in its launch settings stays as it is. force_dark: true = force dark web pages (inverts sites that have no dark theme; the identity's color scheme then reads as dark too). false = off, pages render exactly as the sites intend (the default). Sites may notice forced dark colors — reserve it for identities the user manages for themselves. Chrome-engine identities only. Takes effect the next time the identity starts. Returns {name, launch} with the launch settings now stored.
| Name | Type | Req | Description |
|---|---|---|---|
| force_dark | boolean | – | true = force dark web pages; false = off (default). Chrome-engine identities only. |
| name | string | yes | identity name, exactly as profiles_list reports it |
No output schema declared.
No examples provided.
profile_start ~347
Open a browser session for an identity and return the endpoint to drive it. The identity keeps its frozen fingerprint, its exit proxy, and its logged-in cookies — starting it does not re-randomize anything. Starting an identity that already has a session open is a no-op that returns the existing one. Returns the session record: name, opened_at, idle_seconds, url (the page it is on), plus cdp_endpoint — a ws:// DevTools address you can attach your own automation to. It is only published for Chrome-core identities that have external debugging turned on in the app (off by default; Edit -> Advanced -> External debugging, needs a second verification, then reopen the identity). Otherwise it is null, cdp_unavailable gives the daemon's reason code (external_debug_off, external_debug_not_granted, not_supported_for_engine, starting) and cdp_note says what to do — the session commands work either way. Prefer the daemon's own commands over attaching to cdp_endpoint. A session driven from outside bypasses Nullprint's consistency guards, so an outside tool can set a viewport, locale, timezone, or header that contradicts the identity's frozen fingerprint and make it detectable. Attach at your own risk, and change nothing the identity did not already claim. Fails with a readable message if the identity does not exist (404), if too many sessions are already warm (429), or if the daemon is not running.
| Name | Type | Req | Description |
|---|---|---|---|
| headless | boolean | – | run without a visible window. Default false (headed), which is what sites expect and what you want for anything login-shaped. |
| name | string | yes | identity name, exactly as profiles_list reports it |
No output schema declared.
No examples provided.
profile_stop ~209
Stop an identity's browser, however it was started. Cookies and login state live in the identity's own storage and survive the stop; whatever was typed into an open form does not. Stop identities you are done with — a running identity holds a warm browser and keeps its login state exposed. Two things can be running for one identity and this closes either: the warm session profile_start opens (the daemon drives it), and a window the desktop app launched on its own. The session is closed first; if there is none, the identity-level stop is used instead, which also terminates a launched window and is a no-op on an identity that is already idle. Returns {name, stopped, closed}: `stopped` is false when the identity was already idle, and `closed` lists what was actually shut down. Fails with a readable message if the identity does not exist, or if the daemon is not running.
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | yes | identity name, exactly as profiles_list reports it |
No output schema declared.
No examples provided.
profiles_list ~103
List every identity in this installation, with its live status. Each entry carries: name, os, engine (which browser core backs it), created, proxy (the exit server only — never credentials), status ("running" when a browser is open for it, otherwise "idle"), and meta (the local ledger: group, tags, note, last_launched). Call this first to find the exact name to pass to profile_start / profile_stop; names are case-sensitive.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
proxy_check ~171
Test a proxy URL and report where it actually comes out. No identity needed. Use it before binding a proxy to an identity with profile_create: a dead or slow exit found here costs nothing, the same exit found halfway through a signup costs the account. Returns {ok: true, exit_ip, country, latency_ms} when the proxy works, or {ok: false, error} when it does not. A dead proxy is an ANSWER, not a failure — check the `ok` field rather than assuming success. `country` can be null even on a working proxy if the exit IP cannot be geolocated.
| Name | Type | Req | Description |
|---|---|---|---|
| url | string | yes | the proxy URL to test, e.g. "http://user:pass@host:port" or "socks5://host:port" |
No output schema declared.
No examples provided.
session_click_selector ~150
Click an element on the session's current page, located by a CSS selector. Requires a session opened with profile_start first. `selector` is a CSS selector (e.g. "button#submit", "a.nav-link") — not an XPath, not a role/name pair (use session_snapshot to find one). Returns {ok: true}. Fails with a readable message if the session is not open (409 — call profile_start first), the identity does not exist (404), or the selector never matches / the click times out (502).
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | yes | identity name, exactly as profiles_list reports it |
| selector | string | yes | CSS selector for the element to click |
No output schema declared.
No examples provided.
session_dialog ~231
Answer the JavaScript dialog (alert, confirm, prompt, beforeunload) open on the session's page. Dialogs are left open, as in a normal browser: while one is open the page is blocked and the other session_* tools fail with 409 "a JavaScript <type> is open on the page (<message>)". Call this to answer it, then retry. A beforeunload that your own session_goto (or click) causes is accepted automatically and never shows up here. Returns {ok, action, type, message} for the dialog that was answered. Fails with a readable message if no dialog is open (409), the session is not open (409 — call profile_start first) or the identity does not exist (404).
| Name | Type | Req | Description |
|---|---|---|---|
| action | string | yes | "accept" (OK / Leave) or "dismiss" (Cancel / Stay) |
| name | string | yes | identity name, exactly as profiles_list reports it |
| prompt_text | string | – | for a prompt() dialog, the text to enter before accepting; omit it to accept the prompt's default value |
No output schema declared.
No examples provided.
session_eval ~194
Evaluate a JavaScript expression on the session's current page. Requires a session opened with profile_start first. A page-JS error is data to read, not a tool failure: the daemon returns {"ok": false, "error", "error_type"} instead of raising when the expression throws. Returns the {ok, result} envelope: {"ok": true, "result": <value>} on success. `result` is whatever the expression evaluates to as JSON — string, number, boolean, object, array, or null — not necessarily a string; do not assume its type. Fails with a readable message if the session is not open (409 — call profile_start first) or the identity does not exist (404).
| Name | Type | Req | Description |
|---|---|---|---|
| expr | string | yes | the JavaScript expression to evaluate in the page, e.g. "document.title" |
| name | string | yes | identity name, exactly as profiles_list reports it |
No output schema declared.
No examples provided.
session_fill_selector ~166
Fill a text field on the session's current page, located by a CSS selector. Uses Playwright's fill(), which drives React/Vue-controlled inputs correctly (setting the DOM value directly does not). Requires a session opened with profile_start first. `selector` is a CSS selector, not an XPath. Returns {ok: true}. Fails with a readable message if the session is not open (409 — call profile_start first), the identity does not exist (404), or the selector never matches / the fill times out (502).
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | yes | identity name, exactly as profiles_list reports it |
| selector | string | yes | CSS selector for the input to fill |
| text | string | yes | the text to put in the field, replacing whatever was there |
No output schema declared.
No examples provided.
session_goto ~121
Navigate a session's current page to a URL. Open the identity's session with profile_start first — this drives an already-open session, it does not open one itself. Returns {url}: the page's URL after navigation. Fails with a readable message if the session is not open (409 — call profile_start first) or the identity does not exist (404).
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | yes | identity name, exactly as profiles_list reports it |
| url | string | yes | the URL to navigate to, e.g. "https://example.com/login" |
No output schema declared.
No examples provided.
session_press ~120
Press a keyboard key on the session's current page (whatever is focused). Requires a session opened with profile_start first. Use Playwright key names, e.g. "Enter", "Tab", "Escape", "Control+A". Returns {ok: true}. Fails with a readable message if the session is not open (409 — call profile_start first) or the identity does not exist (404).
| Name | Type | Req | Description |
|---|---|---|---|
| key | string | yes | the key (or chord) to press |
| name | string | yes | identity name, exactly as profiles_list reports it |
No output schema declared.
No examples provided.
session_snapshot ~124
Take an accessibility-tree snapshot of the session's current page. This is the primary way to see what is on a page before acting on it — read it to find the roles/names/selectors to pass to session_click_selector or session_fill_selector. Requires a session opened with profile_start first. Returns {snapshot}: the page's accessibility tree as text. Fails with a readable message if the session is not open (409 — call profile_start first) or the identity does not exist (404).
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | yes | identity name, exactly as profiles_list reports it |
No output schema declared.
No examples provided.
session_switch_tab ~143
Bring one of the session's open tabs to the front and make it the active one. Requires a session opened with profile_start first. Get `index` from session_tabs — indices are only valid as of that snapshot, a tab opened or closed since shifts them. Returns {index, url} for the now-active tab. Fails with a readable message if the session is not open (409 — call profile_start first), the identity does not exist (404), or the index is out of range (422).
| Name | Type | Req | Description |
|---|---|---|---|
| index | integer | yes | the tab's index, from session_tabs |
| name | string | yes | identity name, exactly as profiles_list reports it |
No output schema declared.
No examples provided.
session_tabs ~120
List the session's open tabs, with the currently active one marked. Requires a session opened with profile_start first. Use this to find the index to pass to session_switch_tab. Returns {tabs, active}: `tabs` is a list of {index, url}, `active` is the index of the tab currently in front. Fails with a readable message if the session is not open (409 — call profile_start first) or the identity does not exist (404).
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | yes | identity name, exactly as profiles_list reports it |
No output schema declared.
No examples provided.
trash_list ~106
List the identities in the recycle bin — what is still recoverable. Read-only. Deleted identities do not appear in profiles_list, so without this you could only restore a name you already knew. Pair it with profile_restore. Each entry carries name, engine, os, created, and deleted_at. Newest deletion first. An empty list means the recycle bin is empty. Nothing here is gone yet — everything listed still has its cookies and login state and comes back intact via profile_restore.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
How do I install the Nullprint MCP server?
Nullprint runs locally as an npm package, launched with npx -y nullprint-mcp. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
npm · nullprint-mcp
claude mcp add nullprintai-nullprint-mcp -- npx -y nullprint-mcp
What is the Nullprint MCP server?
Nullprint is an MCP server listed in the public MCP registry as io.github.nullprintai/nullprint-mcp. Create, launch, check and drive Nullprint multi-profile browser profiles from any MCP agent. This page covers its npm package (nullprint-mcp).
Is the Nullprint MCP server safe to use?
Nullprint scores 58 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 23 October 2026. It declares no install or post-install scripts. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the Nullprint MCP server expose?
Nullprint exposes 19 tools: profiles_list, profile_start, profile_stop, profile_create, profile_settings, and 14 more. Their descriptions and schemas cost roughly 3,413 tokens of context every time the server is loaded.
Is the Nullprint MCP server still maintained?
Nullprint is still listed as active in the MCP registry. We last reached this channel on 23 October 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.
What licence is the Nullprint MCP server under?
Nullprint declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.