scan-mcp
This server provides an MCP interface for discovering scanners, starting/configuring scan jobs, and inspecting/cancelling jobs and their artifacts.
Discover connected scanner devices and their SANE options.
Start scan jobs with optional device auto-selection and defaults.
Configure scans by resolution, color mode, source, duplex, page size, custom size, output format, temp dir, and document break policy.
Optionally detect and crop carrier-sheet pages while preserving raw pages.
Check job status, list recent jobs, and cancel running jobs.
Retrieve job manifests and event logs.
Supports discovery and scanning from Epson scanners via the SANE epson2 backend, enabling scan jobs with device options, ADF/duplex, page-size settings, and multipage TIFF assembly.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@scan-mcpScan all pages in the ADF and combine into one PDF"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Minimal MCP server for scanner capture (ADF/duplex/page-size), batching, and multipage assembly.
Features
Small, typed MCP server exposing tools for device discovery and scan jobs
zod-validated inputs; the JSON Schemas in
schemas/document the contract and are contract-testedSmart device selection (prefers ADF/duplex, avoids camera backends), robust defaults
Local-first transports: stdio by default to keep everything on-device, optional HTTP for your own network deployments
Note: This package targets Node 22 and Linux SANE backends (scanimage).
Related MCP server: fsext-mcp-server-java
Quick Start (local stdio, default)
Add a server entry to your MCP client configuration:
{
"mcpServers": {
"scan": {
"command": "npx",
"args": [
"-y",
"scan-mcp"
],
"env": {
"INBOX_DIR": "~/Documents/scanned_documents/inbox"
}
}
}
}This invocation runs over stdio for a privacy-first, single-machine setup.
Call
start_scan_jobwithout adevice_idto auto-select a scanner and begin scanning.Artifacts are written under
INBOX_DIRper job:job-*/page_*.tiff,doc_*.tiff,manifest.json,events.jsonl. Whencrop_carrier_sheetsis set and a carrier sheet is detected, apage_*.cropped.tiffderivative is also written per affected page.
Streamable HTTP transport
Prefer to attach the scanner to another machine on your network? scan-mcp also supports the
streamable HTTP transport:
scan-mcp --httpDefault port is
3001; setMCP_HTTP_PORTto override (for exampleMCP_HTTP_PORT=3333 scan-mcp --http).Binds
127.0.0.1by default. SetMCP_HTTP_HOSTto expose it on other interfaces (for exampleMCP_HTTP_HOST=::for all, or a LAN address); the server has no authentication, so only do that on a trusted network.HTTP responses use server-sent events (SSE) for streaming tool output; clients such as Claude Desktop and Windsurf support this transport.
There is currently no authentication; widen the bind address only on a trusted internal network.
Install
Run with npx:
npx scan-mcp(recommended)The CLI runs a quick preflight check for Node 22+ and required scanner/image tools and prints installation hints if anything is missing.
See recommended server config above
Use
npx scan-mcp --httpto launch the streamable HTTP transport when running on another machine.CLI help:
scan-mcp --helpFrom source (for development):
npm installnpm run build
For Cline setup, and other automated agentic installation, see llms-install.md
System Requirements
Linux with SANE utilities:
scanimageTIFF tools:
tiffcp(multipage assembly) and ImageMagickconvert(carrier-sheet detection and cropping); preflight requires both
Environment Variables
SCAN_MOCK(default:false): mock SANE calls and generate fake TIFFs for testing.INBOX_DIR(default:scanned_documents/inbox): base directory for job runs and artifacts.SCANIMAGE_BIN(default:scanimage): override the binary path.TIFFCP_BIN/IM_CONVERT_BIN(defaults:tiffcp/convert): multipage assembly and image analysis tools.SCAN_EXCLUDE_BACKENDS(CSV): backends to exclude (e.g.,v4l).SCAN_PREFER_BACKENDS(CSV): preferred backends (e.g.,epjitsu,epson2).PERSIST_LAST_USED_DEVICE(default:true): persist and lightly prefer last used device.LOG_LEVEL(default:info): pino log level.MCP_HTTP_PORT(default:3001): TCP port for the HTTP transport.MCP_HTTP_HOST(default:127.0.0.1): bind address for the HTTP transport.
API
Tools
list_devices
Discover connected scanners with backend details.
Inputs: none.
get_device_options
Get SANE options for a specific device.
Inputs:
device_id(string): Target device identifier.
start_scan_job
Begin a scanning job; omitting
device_idtriggers auto-selection and default options.Inputs (all optional unless noted):
device_id(string)resolution_dpi(integer, 50–1200)color_mode(Color|Gray|Lineart): color_mode defaults to Lineart (document-first); at >= 600dpi it defaults to Color, since high-dpi capture usually means artwork/photos where 1-bit destroys information. Pass color_mode explicitly to override either default; high dpi is the only signal used.source(Flatbed|ADF|ADF Duplex)duplex(boolean)page_size(Letter|A4|Legal|Custom)custom_size_mm{width,height}doc_break_policy{type(page_count|none),page_count}: split the batch into documents ofpage_countpagesoutput_format(string, defaulttiff)tmp_dir(string)crop_carrier_sheets(boolean, defaultfalse): detect carrier-sheet leading-edge band and write cropped page derivatives; raw pages are kept
get_job_status
Inspect job state and artifact counts.
Inputs:
job_id(string)
cancel_job
Request job cancellation; best effort during scan loops.
Inputs:
job_id(string)
list_jobs
List recent jobs from the inbox directory.
Inputs (optional):
limit(integer, max 100)state(running|completed|cancelled|error|unknown)
get_manifest
Fetch a job's
manifest.json.Inputs:
job_id(string)
get_events
Retrieve a job's
events.jsonllog.Inputs:
job_id(string)
See JSON Schemas in schemas/ for input shapes. Runtime validation is zod (src/server/register.ts); the schemas document the contract and tests assert against them.
How Selection and Defaults Work
Defaults aim for 300dpi, reasonable color mode, and ADF/duplex when available. Full details on scoring and fallbacks live in docs:
Selection and defaults:
docs/SELECTION.md
Project Layout
src/mcp.ts— MCP server entry and tool registrationsrc/services/*— hardware interface and job orchestrationschemas/— JSON Schemas documenting the tool contracts (used by tests)docs/— architecture, conventions, and deep dives
Development
npm run dev(stdio MCP server),npm run dev:http(HTTP transport)make verifyruns lint, typecheck, and testsConventions:
docs/CONVENTIONS.mdand architecture indocs/BLUEPRINT.md
Roadmap
Tracking ideas and future improvements are documented in docs/ROADMAP.md.
Available Tools
8 toolscancel_jobC
Cancel a running scan job
| Name | Required | Description | Default |
|---|---|---|---|
| job_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It does not disclose that cancellation is likely irreversible, what happens to partial scan results, whether permissions are required, or whether the job stops immediately or gracefully — critical context for a destructive operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single short sentence with the action front-loaded and zero filler; it is appropriately sized but borders on under-specification rather than being padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with no annotations and no output schema, an agent needs to know the effect of cancelling and what a successful call returns. The description supplies neither, leaving significant gaps for an irreversible operation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With one parameter at 0% schema description coverage, the description must compensate but says nothing about job_id — no format, no hint that it is likely obtained from list_jobs or start_scan_job. The schema only declares it as a bare string.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb 'cancel' plus resource 'scan job' makes the operation unambiguous, and it is clearly the inverse of the sibling start_scan_job. It stops short of explicitly naming a sibling or clarifying scope (e.g., can queued jobs be cancelled or only running ones).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to call this versus letting a job finish, and no mention of prerequisites. The qualifier 'running' implies only active jobs qualify, but this is left to inference rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_device_optionsB
Get SANE options for a specific device (sources, resolutions, modes)
| Name | Required | Description | Default |
|---|---|---|---|
| device_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It implies a read-only retrieval and enumerates option categories, but does not state whether the device must exist, what happens on invalid device_id, whether any permissions are required, or what the return shape looks like.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence with a compact parenthetical that adds useful examples. There is no wasted text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter tool with no output schema, the description explains the broad purpose and return categories but does not explain how to obtain device_id or what the option data will look like. It is enough to attempt a call if device_id is already known, but not fully self-contained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the single device_id parameter is undocumented in the schema. The description adds only 'for a specific device', not the expected format, example values, or that it should come from list_devices, leaving a meaningful gap for the only parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Get SANE options for a specific device', and clarifies the kind of options with examples '(sources, resolutions, modes)'. This clearly separates it from sibling list_devices, though it does not explicitly name that sibling or state the relationship.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It implies that the tool is used when device options are needed, but gives no explicit when-to-use guidance, prerequisites, or alternatives. An agent must infer that device_id likely comes from list_devices and that this is a pre-scan inspection step.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_eventsB
Fetch job events JSONL by job_id
| Name | Required | Description | Default |
|---|---|---|---|
| job_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it does disclose the return format (JSONL) — useful information not present in the schema. However, it says nothing about event ordering, completeness, pagination/streaming behavior, or whether output is bounded, which matters for a log-fetching tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single six-word sentence with the resource and scoping key front-loaded and no filler. Its terseness is efficient rather than padded, though 'JSONL' is left unelaborated.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no annotations, no output schema, and an undocumented parameter, the description is too thin: it does not explain what an 'event' contains, whether results are truncated or ordered, or how job_id is obtained. An agent can attempt the call but cannot predict the response.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, but the single parameter is self-explanatory by name and type. The description restates that job_id selects the job whose events are returned but adds no format details or guidance on where to obtain a job_id (e.g., from list_jobs or start_scan_job).
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (fetch) and resource (job events, JSONL) scoped to a job_id, so an agent can tell it apart from list_jobs or get_manifest. It stops short of explicitly contrasting itself with the closest sibling, get_job_status, which also keys off a job.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit when-to-use or when-not-to-use guidance, and no mention of the alternative get_job_status for job introspection. The only signal is the implied requirement of a job_id, leaving the agent to infer the workflow.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_job_statusC
Get status and artifact counts for a job
| Name | Required | Description | Default |
|---|---|---|---|
| job_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, yet it only says what fields are returned. It does not disclose that this is a non-mutating read, how it behaves for an unknown or expired job_id, or whether status reflects completed/cancelled states.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no wasted words. It is efficient, though the brevity is partly the source of the missing guidance rather than deliberate tightness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter read with no output schema, the description does convey the key return contents (status and artifact counts). It still leaves the parameter's provenance and the read-only nature unexplained, which is a real but modest gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and the single required parameter job_id is undocumented in the schema. The description never mentions job_id, so it fails to compensate by explaining its format or that it likely comes from start_scan_job or list_jobs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (get) and resource (job status) plus what is returned (artifact counts), so the agent knows this is a single-job status read rather than a list. It does not explicitly contrast with siblings like list_jobs or get_manifest, so the differentiation is inferred rather than stated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this versus list_jobs, get_manifest, or get_events, and no mention of polling, terminal states, or prerequisites such as where job_id comes from. Usage is only implied by the tool name.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_manifestC
Fetch a job manifest JSON by job_id
| Name | Required | Description | Default |
|---|---|---|---|
| job_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden, yet it says nothing about error behavior for an unknown job_id, whether the manifest is cached or generated on demand, or what happens while a job is still running. It only weakly implies a read-only fetch.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single short sentence that front-loads the verb and resource with no wasted words. It is arguably too terse rather than too long.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no annotations, no output schema, and no parameter documentation, the description should explain what a 'manifest' contains and how it relates to other job outputs. As written it leaves the agent without enough context for a correctly-formed call in edge cases.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and the single parameter job_id is documented only insofar as the description repeats 'by job_id'. No format, provenance, or source of valid IDs is given beyond what the schema's string type already conveys.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Fetch) and resource (job manifest JSON) keyed by job_id, so the operation is unambiguous. However, it does nothing to distinguish itself from siblings like get_job_status, list_jobs, or get_events, which all operate on the same job domain.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no indication of when to use this instead of get_job_status or get_events, nor whether the manifest is available before, during, or after a scan job completes. The agent must guess the routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_devicesA
List connected scanner devices with basic capabilities
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations at all, so the description carries the full disclosure burden. It does add real signal with 'connected' (only currently-attached devices) and 'basic capabilities' (output is a summary, not full detail), but it says nothing about permissions, ordering, or emptiness behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One short sentence, front-loaded with the verb and resource, with no filler. It is arguably too terse rather than padded, but nothing wastes space.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a parameterless read tool with no output schema, the description should clarify what a 'device' record contains or that detailed capabilities require a follow-up call. 'Basic capabilities' gestures at this but does not close the gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4 and there is nothing for the description to compensate for.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb plus resource: 'List connected scanner devices' with a stated scope 'basic capabilities'. It is distinguishable from siblings like get_device_options or start_scan_job, though it never names those siblings to sharpen the contrast.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied — an agent can infer this is the discovery step before get_device_options or start_scan_job, but the description states no when-to-use condition and explicitly excludes nothing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_jobsC
List recent scan jobs from the inbox directory
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| state | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It implies a read operation and discloses the inbox directory as the source, but it does not state ordering, pagination/truncation behavior, what "recent" means, or whether access permissions are required. For a listing tool with no annotation coverage, this leaves material behavioral questions unanswered.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single front-loaded sentence with no wasted words. However, its brevity comes at the cost of under-specification rather than earned conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no annotations, no output schema, and two undocumented parameters, the description should explain filtering, ordering, and what a job listing contains. It gives only a source directory and a vague recency claim, leaving the agent without enough context to invoke the tool confidently.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and the description does not mention either parameter. The limit cap of 100 and the state enum (running/completed/cancelled/error/unknown) are left entirely to the schema, with no explanation of their meaning or effect. The description fails to compensate for the complete lack of parameter documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description provides a clear verb and resource ("List recent scan jobs") plus a scope ("from the inbox directory"). It implicitly distinguishes itself from siblings like start_scan_job, get_job_status, and cancel_job, though it does not explicitly name alternatives. The word "recent" is vague but the core purpose is understandable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this tool versus siblings such as get_job_status or get_manifest, nor any exclusions or prerequisites. The phrase "recent" hints at a time-based context, but it is not defined or actionable. An agent must infer the use case entirely.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
start_scan_jobC
Start a scan job; auto-selects device and fills defaults when omitted
| Name | Required | Description | Default |
|---|---|---|---|
| duplex | No | ||
| source | No | ||
| tmp_dir | No | ||
| device_id | No | ||
| page_size | No | ||
| color_mode | No | color_mode defaults to Lineart (document-first); at >= 600dpi it defaults to Color, since high-dpi capture usually means artwork/photos where 1-bit destroys information. Pass color_mode explicitly to override either default; high dpi is the only signal used. | |
| output_format | No | ||
| custom_size_mm | No | ||
| resolution_dpi | No | ||
| doc_break_policy | No | ||
| crop_carrier_sheets | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are present, so the description carries the full burden. It does disclose one real trait — that device_id is auto-selected and other fields are defaulted when omitted — but says nothing about whether the call blocks or returns immediately, where output lands (tmp_dir), error behavior, or what identifier is returned for later polling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded clause with zero filler; the behavioral hint about auto-selection follows immediately. It is efficient, though the brevity arguably reflects under-specification rather than disciplined trimming.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 11-parameter job-creation tool with nested objects, no annotations, and no output schema, one sentence is far too thin. An agent cannot tell from the description how to drive the duplex/source interaction, what the defaults actually are, or how to follow up on the returned job.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 9% across 11 parameters, including two nested objects (doc_break_policy, custom_size_mm) and overlapping concepts like duplex vs. source="ADF Duplex". The description mentions omitted parameters in general and device selection, but adds no meaning about duplex, page_size, resolution_dpi, or doc-break behavior, so it does not compensate for the coverage gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Start a scan job") that is clearly distinct from siblings such as get_job_status, cancel_job, and list_jobs. It stops short of explicitly contrasting with alternatives, but the purpose is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implies the call is safe to make with no arguments because device selection and defaults are automatic. It never states prerequisites (e.g., use get_device_options first to override defaults) or when a different tool (get_job_status, cancel_job) is the right next step.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
8 tool updates
v0.3.0- First observed
cancel_job - First observed
get_device_options - First observed
get_events - First observed
get_job_status - First observed
get_manifest - First observed
list_devices - First observed
list_jobs - First observed
start_scan_job
TDQS
Scored across 8 tools
Each tool maps to a distinct resource or action: device listing, device options, job start/cancel, job listing/status, manifest, and events. The job-read tools are adjacent but clearly differentiated by their outputs.
All names use consistent snake_case with clear verb_object patterns such as list_devices, get_job_status, start_scan_job, and cancel_job. There is no mixed casing or vague verb usage.
Eight tools is well-scoped for scanner discovery, job control, and job inspection. Each tool covers a separate operation with no obvious filler.
The surface covers device discovery/options and the core job lifecycle plus manifest/events inspection. However, there is no tool to retrieve or download scanned artifacts, and no explicit option-setting operation, which can leave end-to-end scanning workflows at a dead end.
Maintenance
Related MCP Connectors
Scans remote MCP servers for protocol, security, and TLS issues; exposes scan tools via MCP.
PDF tools + QR over MCP: merge, split, rotate, text, metadata, malicious-content scan.
MCP server for the PDFGate API. Generate PDFs, manage documents and handle e-signatures.
Document processing over MCP: merge, split and compress PDFs, run OCR, extract document text.
Related MCP Servers
- AlicenseAqualityDmaintenanceAn MCP server that enables users to print markdown tasklists, Notion tasks with QR codes, and arbitrary images directly to ESC/POS thermal printers over USB. It includes specialized tools for task processing, automated card generation, and printer diagnostics.720 PyPI1MIT
- AlicenseNot gradedqualityCmaintenanceA full-featured secure MCP server for local file system operations, with built-in image processing, OCR and media tools.Apache 2.0
- AlicenseAqualityCmaintenanceEnables scanning documents via network (eSCL) or USB (WIA/SANE) scanners, returning inline images, OCR text, or saved PDFs for Claude to read.21MIT
- AlicenseNot gradedqualityDmaintenanceA local MCP server that drives PDFium and pypdf to perform comprehensive PDF operations including inspection, assembly, page editing, watermarking, rendering, extraction, form filling, encryption, compression, attachments, bookmarks, and metadata management.MIT