eink-mcp
Provides tools for storing and managing files in Vercel Blob storage, including uploading content or files from URLs, retrieving, deleting, and listing files with immutable public URLs and a sync manifest for e-ink devices.
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., "@eink-mcppublish the new app.js bundle to the kindle"
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.
eink-mcp
An MCP server that hosts files for e-ink devices and syncs them down.
Agents put files here with MCP tools. Each file version lands once at an immutable,
content-addressed public URL in a Vercel Blob store, and a small manifest.json maps paths to
those URLs with their sha256. Only the manifest is ever overwritten, so a reader can never see a
manifest that disagrees with the file it names; it can only be up to a minute behind. A device such as a
jailbroken Kindle running eink-ui points its update URL at
that manifest and pulls whatever changed on every start, wake and reload. Nothing has to reach
the device: it is behind NAT and asleep most of the day, so it always pulls.
agent ──MCP──▶ eink-mcp ──put──▶ Vercel Blob (public URLs + manifest.json) ◀──pull── deviceTools
tool | effect |
| the public base URL to set as the device's update URL, the manifest URL, file count |
| every file with size, sha256, URL and last update |
| upload |
| download a URL into the store, for large builds coming out of CI |
| read a file back (text or base64, truncated past 512 KiB) |
| remove a file; devices drop their copy on the next sync |
Paths are relative and map straight onto the device's app directory. On eink-ui devices app.js
is the React bundle and eink-host is the host binary; changing either restarts the host.
Related MCP server: slm-mesh
Run it
Environment:
BLOB_READ_WRITE_TOKEN(required): a Vercel Blob read-write token. This is the only credential; the store is the only state.EINK_PREFIX(defaulteink/): the folder inside the store, one per device or fleet.
npx eink-mcp # from npm, stdio
nix run github:sberan/eink-mcp # from the flake, stdioClaude Code
claude mcp add eink -e BLOB_READ_WRITE_TOKEN=... -- npx eink-mcppg_mcp (Nix runtime)
pg_mcp builds the flake at a pinned commit and runs it over stdio; the Blob token is supplied
as the server's bearer credential through token_env.
SELECT mcp.register_server('eink', auth => 'bearer',
options => '{"token_env":"BLOB_READ_WRITE_TOKEN","env":{"EINK_PREFIX":"kindle/"}}'::jsonb,
runtime => '{"kind":"nix","source":"github:sberan/eink-mcp","revision":"<commit>",
"attribute":"mcp","executable":"bin/eink-mcp"}'::jsonb);
-- then set the bearer token (the Blob token) and wait for mcp.status('eink').runtime = readyManifest
{ "version": 1, "generated": "2026-09-17T01:59:51Z",
"base": "https://<store>.public.blob.vercel-storage.com/kindle/",
"files": { "app.js": { "sha256": "…", "size": 123304, "url": "…", "content_type": "application/javascript", "updated": "…" } } }A device keeps the manifest's ETag and the sha256 of each file it holds, downloads only files whose hash changed, verifies the hash (the CDN can lag a file behind its manifest for up to a minute, in which case the device simply tries again on its next sync), and deletes files that left the manifest.
Develop
npm install && npm run build
BLOB_READ_WRITE_TOKEN=... npm run smoke # end to end against a throwaway prefixAvailable Tools
6 toolsdelete_fileDelete a fileA
Remove a file from the store and the manifest. Devices delete their copy on the next sync.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden. It discloses an important side effect: 'Devices delete their copy on the next sync,' which is crucial for understanding the tool's behavior beyond just removing the file. It also indicates the deletion affects both the store and the manifest, adding completeness. This provides significant behavioral context that is not available elsewhere.
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 two short sentences, achieving high clarity with minimal words. The first sentence states the action, and the second adds an important side-effect. It is front-loaded and efficient, with no superfluous information.
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 low-complexity tool (one param, no output schema), the description is quite complete. It tells the agent what happens to the file and the manifest, and mentions sync behavior. The only minor gap is the lack of explicit path format, but that is not critical for most use cases. Overall, it's sufficient for an agent to call the tool correctly without additional context.
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 schema has one parameter 'path' with no description, and schema coverage is 0%. The tool description says 'Remove a file from the store' but does not explain what 'path' means (e.g., absolute path, relative path, or naming convention). The agent must infer the path semantics. Since there is only one param and the description gives some context, it's acceptable but leaves ambiguity.
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 clearly states the action ('Remove a file from the store and the manifest') with a specific resource ('file'). It distinguishes from siblings like 'put_file' and 'get_file' by focusing on deletion. However, it could be more explicit about the file being referred to (e.g., by path).
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?
The description implies when to use this tool (when a file needs to be removed) but does not provide explicit guidelines for when not to use it or mention alternatives. For instance, it doesn't mention that 'put_file' might be used to overwrite rather than delete, or if there is a separate batch delete. It's adequate but not explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_fileGet a fileA
Read a file back: text for text types, base64 otherwise. Large files are truncated; use the URL from list_files for the whole thing.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries most of the burden and does well by disclosing two key behaviors: text/base64 return format and truncation for large files. It could add error behavior, but for a single-parameter read tool this is solid coverage.
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?
Two sentences, no filler, with the essential encoding behavior and truncation caveat front-loaded. Every clause earns its place.
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 tool with no output schema, the description covers the main behaviors an agent needs: encoding, truncation, and pointer to the alternative. It does not discuss error cases, but the tool's complexity is low and the description is largely complete on its own.
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 schema has 0% description coverage for the path parameter, so the description must compensate, but it adds no detail about path format, relative vs. absolute paths, or file resolution. The meaning of 'path' is inferable from the parameter name, but the description itself contributes nothing to parameter semantics.
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 clearly states the verb 'Read a file back,' identifies the resource, and explains the return encoding (text for text types, base64 otherwise). It also distinguishes itself from siblings by flagging truncation and pointing to list_files for the full file.
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 gives clear context for when to use this tool, including the important large-file limitation and the explicit alternative: 'use the URL from list_files for the whole thing.' It does not enumerate exclusions, but the guidance is actionable and sufficient for a simple read operation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_filesList filesA
Every file in the store with its size, sha256, public URL and last update.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses the output fields and implies a read-only bulk operation, but it does not mention pagination, potential large payloads, or any authentication requirements. For a listing tool this is a moderate gap, but the core behavior is clear.
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 that states the scope ('Every file') and the relevant fields. No fluff or unnecessary detail.
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 listing tool without an output schema, the description adequately conveys the return content and scope. It does not mention ordering or limits, but these are minor for a simple inventory operation. The tool is sufficiently complete for an agent to call it correctly.
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?
There are zero parameters, so the description does not need to explain them. The baseline for 0 params is 4, and the description correctly adds no redundant parameter information.
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 clearly states the verb 'list' and resource 'files', and specifies the exact fields returned (size, sha256, public URL, last update). This distinguishes it from siblings like get_file (single file) and put_file (upload) without ambiguity.
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?
The description implies this is the tool for obtaining a complete inventory of files, but it does not explicitly mention when to use it over get_file for a single file or delete_file for removal. The context is clear, but no explicit alternatives or exclusions are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
put_filePut a fileA
Upload a file by path (relative, as it will appear in the device app directory). Give text as content or binary as content_base64. Devices pick it up on their next sync.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | relative path, e.g. app.js or data/2026-09-16.json | |
| content | No | UTF-8 text content | |
| content_type | No | MIME type; guessed from the extension when omitted | |
| content_base64 | No | binary content, base64 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It discloses two meaningful behaviors: files appear in the device app directory and are delivered on the next sync (asynchronous delivery). It does not mention overwrite behavior, idempotency, failure cases, or any authentication prerequisites, which would strengthen transparency for an upload 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?
Two sentences, zero filler. The primary action and path semantics are front-loaded, and the content-mode and sync-timing details follow in a logical, compact order. Every sentence earns its place.
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 fairly simple upload tool with four well-documented parameters and no output schema, the description is nearly sufficient. It covers path meaning, content encoding choices, and delivery timing. The only gap is what happens on conflict or failure (e.g., whether existing files are overwritten), which would make it fully complete.
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 100%, so the baseline is 3. The description reinforces the schema by saying 'text as content or binary as content_base64' and clarifies that path is relative to the app directory, but it adds little beyond what the schema already documents for each 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 opens with a specific verb and object ('Upload a file') and immediately clarifies the path semantics as 'relative, as it will appear in the device app directory.' This distinguishes it from siblings like get_file, delete_file, and put_file_from_url, which are separate operations or input channels.
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?
The description provides practical context: when you have local text or binary content Encoder, you pass content or content_base64, and the file is picked up on next sync. However, it does not explicitly name alternatives (e.g., put_file_from_url) or state when not to use this tool, leaving some selection inference to the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
put_file_from_urlPut a file from a URLA
Download a URL and store it under path, so large binaries (a host build from CI, for example) never pass through the conversation.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | ||
| path | Yes | ||
| content_type | 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 burden of behavioral disclosure. It honestly describes the write action and adds a helpful side-effect detail (content bypasses the conversation), but it does not disclose overwrite semantics, access requirements, or error behavior. This is modest disclosure rather than full transparency.
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 24-word sentence that leads with the action, states the storage target, and closes with the motivating case. Every phrase contributes to understanding and no redundancy is present.
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 three-parameter tool with no output schema, the description is mostly sufficient: it identifies the source, destination, and intended use case. However, with no annotations and no schema descriptions, the omission of `content_type` and any note about overwriting an existing file leaves some ambiguity for the agent.
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 description must compensate. It clarifies that `url` is the download source and `path` is the storage destination, but it never explains `content_type`, which appears only as an unannotated schema property. This partial compensation leaves one parameter semantically under-specified.
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 opens with a clear verb ('Download') and resource ('a URL') and specifies the outcome ('store it under `path`'), which makes the tool's function unambiguous. It also implicitly distinguishes itself from the sibling `put_file` by explaining that content never passes through the conversation, so an agent can tell them apart.
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?
The phrase 'so large binaries (a host build from CI, for example) never pass through the conversation' gives a concrete scenario and rationale for choosing this tool. It does not explicitly name `put_file` as the alternative or state when not to use it, stopping short of full when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
statusStore statusC
The public base URL devices sync from (set it as update_url on the device), the manifest, and the file count.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It does not state whether this is a read-only operation, whether it requires authentication, what the response format looks like, or whether the file count is computed live or cached. The description is a noun phrase, not a statement of 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?
The description is a single concise sentence that front-loads the key information. It is not verbose, but it could be improved by adding a verb and a clearer statement of purpose.
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 zero-parameter tool with no output schema and no annotations, the description should clarify what the agent can expect. It mentions the three pieces of data returned, but it does not explain the response structure, whether the manifest is a list of files, or how this relates to sibling tools. The description is too thin to fully support correct invocation and interpretation.
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 has zero parameters, so there is no parameter semantics burden. The description adds context about what the tool returns (base URL, manifest, file count), which is useful given the empty schema. Baseline 4 is appropriate for a zero-parameter tool.
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 the tool exposes the public base URL, manifest, and file count, which gives a specific resource and scope. However, it does not use a verb like 'get' or 'retrieve', and it does not clearly distinguish itself from sibling tools like list_files, which could also return file information.
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 is given on when to use this tool versus list_files or other siblings. The description implies it is a status/overview endpoint, but it does not explicitly state when an agent should choose it over alternatives.
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.
6 tool updates
v0.1.0- First observed
delete_file - First observed
get_file - First observed
list_files - First observed
put_file - First observed
put_file_from_url - First observed
status
TDQS
Scored across 6 tools
Each tool targets a distinct operation: status reports server-level info, list_files enumerates metadata, put_file and put_file_from_url are clearly separated by input source, get_file retrieves content, and delete_file removes files. There is no meaningful overlap that would cause an agent to select the wrong tool.
Most tools follow a consistent verb_noun pattern: list_files, put_file, get_file, delete_file, and put_file_from_url extends that pattern naturally. The single outlier is status, which is a noun rather than verb_noun, but it is a conventional command name and not confusing.
Six tools is well-scoped for a file store sync server. Each tool covers a necessary operation without redundancy, and the count is neither too thin nor too heavy for the stated purpose.
The tool surface covers the full file lifecycle: create/update via put_file and put_file_from_url, read via get_file and list_files, delete via delete_file, plus status for device sync configuration. There are no obvious missing operations for the domain.
Maintenance
Related MCP Connectors
Publish files and folders to the web instantly: permanent URLs, immutable versions, claim links.
Publish HTML, files, or a URL to a permanent public URL, then update it — from any MCP agent.
Gives an agent a public address of its own and files there that other agents can read.
Publish, update, read, rename, and share single-URL web pages from any AI agent.
Related MCP Servers
- AlicenseAqualityAmaintenanceSimple and free publishing of content on the web for AI Agents25,766 npmMIT
- AlicenseNot gradedqualityCmaintenanceEnables peer-to-peer communication, discovery, shared state, and file coordination between AI coding agents across machines and sessions.49 npm19Elastic 2.0

A2AL MCP Serverofficial
AlicenseNot gradedqualityAmaintenanceEnables AI agents to publish themselves, discover each other, and establish authenticated encrypted connections without central infrastructure, using a decentralized agent-to-agent networking protocol.1Mozilla Public 2.0
openfuse-mcpofficial
AlicenseNot gradedqualityCmaintenanceEnables AI agents to manage persistent context, send signed messages, sync with peers, and share files through plain-file-based tools.20 npm18MIT