Swarm MCP
OfficialProvides integration with Ethereum Swarm's decentralized storage network, enabling tools for uploading and downloading text data, files, and folders, managing postage stamps for storage, and updating/reading Swarm feeds.
Swarm MCP Server
A Model Context Protocol (MCP) server implementation that uses Ethereum Swarm's Bee API for storing and retrieving data.
Overview
This server implements the Model Context Protocol (MCP), a standard protocol for connecting AI systems with external tools and data sources. The Swarm MCP server provides tools to upload and download text data, storing this data on the Swarm decentralized storage network using the Bee API.
Related MCP server: Onesource MCP
Features
Upload text data to Swarm.
Download text data from Swarm.
Upload files and folders to Swarm.
Download files and folders from Swarm.
Update data on a Swarm feed.
Read latest data from a Swarm feed.
Create postage stamp batches for storage.
Get a postage stamp batch.
List postage stamp batches.
Extend storage and duration of a postage stamp batch.
Track the progress of deferred (background) uploads.
Run long-running operations as MCP tasks.
Expose every tool as an MCP prompt.
Configuration Options
Option | Type | Required | Description |
| string | optional (unless using your own node) | The URL of the Bee API endpoint. If omitted, the default Swarm Gateway will be used: |
| string | optional (cannot update feed without it) | The private key of the Swarm Feed to use. If not provided, Swarm Feed functionality will be disabled. |
| boolean | optional | Whether to automatically assign a postage stamp if none is provided. Default value is: true. Set to false to disable automatic stamp assignment. |
| number | optional | Size threshold in megabytes for deferred uploads. Files larger than this size will be uploaded asynchronously. Default value is: 5 (MB). |
| number | optional | Time to live of a task in milliseconds. Default value is: 1200000 (20 minutes). If the task TTL specified by the MCP client is larger than this value, that one will be used. |
| number | optional (web mode only) | Port the HTTP server listens on. Default value is: 3000. |
| string | optional (web mode only) | Host interface the HTTP server binds to. Default value is: |
Bee Node vs. Swarm Gateway
The server detects at runtime whether BEE_API_URL points at the public Swarm Gateway or at a full Bee node, and adapts
what it exposes:
Own Bee node (e.g.
http://localhost:1633): all tools are available, and tools that support it can be executed as MCP tasks.Swarm Gateway (the default when
BEE_API_URLis omitted): the postage-stamp tools (create_postage_stamp,get_postage_stamp,list_postage_stamps,extend_postage_stamp) andquery_upload_progressare omitted fromtools/list, because the gateway does not expose those endpoints. Task execution is also disabled, so every call runs synchronously.
MCP Tools
The server provides the following MCP tools:
create_postage_stamp
Buy postage stamp batch based on size in megabytes and duration.
Parameters:
size: Storage capacity, e.g. 1GB, 1MB, 1KB.duration: Duration for which the data should be stored. Time to live of the postage stamp batch, e.g. 1d - 1 day, 1w - 1 week, 1month - 1 month.label: (Optional) Sets label for the postage stamp batch.
Sample prompt:
Create new stamp with 4 days, 10 megabytes.get_postage_stamp
Get a specific postage stamp batch based on batch id.
Parameters:
postageBatchId: The id of the postage stamp batch which is requested.
Sample prompt:
Give me the details for batch 3b3881ac37f936a4023a4562c69f1f138df8c1c24994f7b047514fbcbe9388fa.list_postage_stamps
List the available postage stamp batches.
Parameters:
leastUsed: (Optional) A boolean value that tells if postage stamp batches are sorted so least used comes first.limit: (Optional) Limit is the maximum number of returned postage stamp batches.minUsage: (Optional) Only list postage stamp batches with at least this usage percentage.maxUsage: (Optional) Only list postage stamp batches with at most this usage percentage.
Sample prompt:
List my stamps.extend_postage_stamp
Increase the duration (relative to current duration) or size (in megabytes) of a postage stamp batch.
Parameters:
postageBatchId: The id of the postage stamp batch for which extend is performed.size: (Optional) Storage capacity, e.g. 1GB, 1MB, 1KB.duration: (Optional) Duration for which the data should be stored. Time to live of the postage stamp batch, e.g. 1d - 1 day, 1w - 1 week, 1month - 1 month.
Sample prompt:
Extend 3b3881ac37f936a4023a4562c69f1f138df8c1c24994f7b047514fbcbe9388fa by 5 days.upload_data
Upload text data to Swarm.
Parameters:
data: Arbitrary string to upload.redundancyLevel: (Optional) Redundancy level for fault tolerance: 0 - none, 1 - medium, 2 - strong, 3 - insane, 4 - paranoid (higher values provide better fault tolerance but increase storage overhead). Optional, value is 0 if not requested.postageBatchId: (Optional) The postage stamp batch ID which will be used to perform the upload, if it is provided.
Sample prompt:
Upload data to Swarm: Hello World!.download_data
Downloads immutable data from a Swarm content address hash.
Parameters:
reference: Swarm reference hash.
Sample prompt:
Download data from Swarm: 76d133e2798d2b15db55b6c3de01303acd86e43998eab372e25c5a2115bf3f0b.update_feed
Update the feed of a given topic with new data.
Parameters:
data: Arbitrary string to upload.memoryTopic: If provided, uploads the latest data to a feed with this topic. It is the label of the memory that can be used later to retrieve the data instead of its content hash. If not a hex string, it will be hashed to create a feed topic.postageBatchId: (Optional) The postage stamp batch ID which will be used to perform the upload, if it is provided.
Sample prompt:
Update the Swarm feed of Topic1 with: Message1 using postage batch id 3b3881ac37f936a4023a4562c69f1f138df8c1c24994f7b047514fbcbe9388fa.read_feed
Retrieve the latest data from the feed of a given topic.
Parameters:
memoryTopic: Feed topic.owner: (Optional) When accessing external memory or feed, ethereum address of the owner must be set..
Sample prompt:
Read the Swarm feed of Topic1.upload_file
Upload a file to Swarm. Small files upload synchronously and return the reference. Large files (over the deferred-upload threshold) upload in the background: the response immediately includes the final reference (computed locally) and a tag ID for query_upload_progress; the content becomes retrievable at the reference once the upload completes. When redundancyLevel > 0, only the tag ID is returned immediately.
Parameters:
data: File content or file path.redundancyLevel: (Optional) Redundancy level for fault tolerance (higher values provide better fault tolerance but increase storage overhead). 0 - none, 1 - medium, 2 - strong, 3 - insane, 4 - paranoid.postageBatchId: (Optional) The postage stamp batch ID which will be used to perform the upload, if it is provided.
Sample prompt:
Upload to Swarm the file: uploads/file.txt.upload_folder
Upload a folder to Swarm.
Parameters:
folderPath: Path to the folder to upload.redundancyLevel: (Optional) Redundancy level for fault tolerance (higher values provide better fault tolerance but increase storage overhead). 0 - none, 1 - medium, 2 - strong, 3 - insane, 4 - paranoid.postageBatchId: (Optional) The postage stamp batch ID which will be used to perform the upload, if it is provided.
Sample prompt:
Upload to Swarm folder: /home/conversational-agent-client/uploads.download_files
Download a file or folder from a Swarm reference and save it to disk. Handles both single files and folder manifests. The
reference must be a manifest — for raw text data uploaded with upload_data, use download_data instead.
Parameters:
reference: Swarm reference hash.filePath: (Optional) Destination folder (not a filename) to save the downloaded content into. Files from the manifest are written inside this folder under their original names. Absolute paths are recommended; relative paths resolve against the server's working directory. If omitted, files are saved into the server's current working directory. Only available instdiomode.
Sample prompt:
Download from Swarm the file with reference ba35af06601ddf5ac3d71ee33da0db7537215a914fd6a5414b5597bb3d618bdb to folder downloads.query_upload_progress
Query upload progress for a specific upload session identified with the returned Tag ID. Also returns the final Swarm
reference of the upload, which is how you obtain the reference of a deferred upload_folder (a folder's reference
cannot be computed up front) once processedPercentage reaches 100.
Parameters:
tagId: Tag ID returned by theupload_fileandupload_foldertools to track upload progress.
Sample prompt:
Query Swarm for upload tag with id: 1.MCP Tasks (long-running operations)
The server declares the tasks capability, so a client can ask for a slow operation to be executed as a task and poll
for its result instead of holding the tool call open.
Task execution is opt-in per call: the client includes task parameters (ttl, pollInterval) in the tools/call
request. If it does not, the tool runs synchronously as usual.
The following tools accept task execution (taskSupport: "optional"):
upload_fileupload_folderdownload_filescreate_postage_stampextend_postage_stamp
All other tools are declared taskSupport: "forbidden" and always run synchronously. Task execution also requires a real
Bee node — see Bee Node vs. Swarm Gateway.
Supported task requests: tasks/get, tasks/result, and tasks/list (paginated with a cursor, 50 tasks per page).
Task lifetime is governed by TASK_TTL_MS (default 20 minutes); the effective TTL is the larger of that value and the
one the client requested. The default poll interval is 5 seconds. Tasks are held in an in-memory store, so they do not
survive a server restart.
MCP Prompts
The server also declares the prompts capability and exposes one prompt per tool, named <tool_name>_prompt (e.g.
upload_data_prompt, download_files_prompt). Each prompt takes the same arguments as the corresponding tool and
returns a natural-language instruction — useful for clients that surface prompts as slash commands or templates. The
prompt list is generated from the tool schemas, so it always stays in sync with the tools above.
Setup
Prerequisites
Node.js 18+ installed
npm
A running Bee node or access to a public Bee gateway
A valid postage batch ID (for production use)
Installation
Clone this repository
Install dependencies:
npm ciConfiguration
You need to create a .env file with the content from .env.example. Update the environment variables with the desired values.
Tests, Linting and Formatting
npm test # run the Jest test suite
npm run lint # ESLint
npm run format # Prettier, writes in placePublishing
This server is also published to the Model Context Protocol registry as io.github.Solar-Punk-Ltd/swarm-mcp, with the
npm package @solarpunkltd/swarm-mcp (stdio transport). The registry metadata lives in server.json. For the release
and publishing process, see the MCP registry publishing guide.
Running the Server Locally
You can run the server locally in two different modes: stdio or web.
Stdio (Default)
This is the standard mode for direct integration with MCP clients that manage their own subprocesses.
Development (with hot-reloading):
npm run devDevelopment (without building):
npm run serveProduction: First, build the project:
npm run buildThen, run the server:
npm start
# or
npm run start:stdioWeb Server (HTTP)
This runs the server as a web service on port 3000, with endpoints for HTTP.
Development (without building):
npm run serve:webProduction: First, build the project:
npm run buildThen, run the server:
npm run start:webDocker
This project includes a Dockerfile to run the Swarm MCP server as a containerized service with HTTP transport.
Dockerfile: Builds a single image for the server, which runs on port 3000.
Building the Docker Image
To build the Docker image, run the following command from the project root:
docker build -t swarm-mcp .Running the Docker Container
To run the server, use the docker run command. The container exposes port 3000 for HTTP.
docker run --name swarm-mcp -p 3000:3000 swarm-mcpConfiguration with Environment Variables
To configure the server, pass environment variables to the container using the -e flag. This is necessary to connect to your own Bee node or use features like Swarm Feeds.
docker run -p 3000:3000 \
-e BEE_API_URL="http://localhost:1633" \
-e BEE_FEED_PK="your_private_key_here" \
-e AUTO_ASSIGN_STAMP="true" \
-e DEFERRED_UPLOAD_SIZE_THRESHOLD_MB="5" \
swarm-mcpTesting with cURL
The HTTP transport is session-based, so tools/list cannot be sent on its own: every session starts with an
initialize request, and the server returns the session id in the Mcp-Session-Id response header. Subsequent requests
must echo that id back.
First, initialize and read the session id from the response headers (-i):
curl -i -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-06-18",
"capabilities": {},
"clientInfo": { "name": "curl", "version": "1.0.0" }
}
}'Then list the tools, passing the id from the Mcp-Session-Id header above:
curl -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Mcp-Session-Id: <session-id-from-the-initialize-response>" \
-d '{
"jsonrpc": "2.0",
"method": "tools/list",
"id": 2
}'A successful response contains the list of the server's tools. Send DELETE /mcp with the same header to end the
session.
Note: text/event-stream in the accept header is required, and responses arrive as a server-sent event frame
(event: message followed by a data: line holding the JSON-RPC payload) rather than as a bare JSON body. Requests with
no session id are rejected with 400, and requests naming an unknown or ended session with 404.
Using with MCP Clients
The server supports two connection methods:
1. Web Connection (Docker)
When running the server in Docker, it operates as a web service with HTTP endpoint. To connect your MCP client, you must use: http://localhost:3000/mcp.
In your client's settings, add a new remote/custom connector and provide the appropriate URL.
Note on supported features: Functionalities that require direct access to the local file system are not available in web mode, and are only supported when running the server in stdio mode:
upload_folderis rejected outright — it always reads from the local file system.upload_fileis rejected when thedatavalue resolves to an existing local file. The server decides this itself by checking the path; there is no flag to set. Passing raw file content asdataworks in both modes.download_filesis rejected whenfilePathis supplied. WithoutfilePaththe call succeeds, but the files are written into the working directory of the server process, not the client machine.
2. Stdio Connection (Local)
For local development or with clients that manage their own server subprocesses, you can run the server directly in stdio mode.
For detailed instructions on how to configure your MCP client for stdio, please refer to the Swarm MCP Client Setup guide.
To run the server in this mode, see the commands under the Stdio (Default) section above.
Available Tools
7 toolsdownload_dataDownload dataA
Download raw text data from a Swarm reference and return it as a string. Use this tool ONLY when the user explicitly asks for the text content, string content, or raw data behind a reference, or when the reference is known to have been uploaded via upload_data. If the user mentions "file", "files", "folder", or asks to "download" without specifying that they want the raw text content, use download_files instead. When in doubt about the reference type, prefer download_files — it handles both single files and folder manifests and can be saved to disk.
| Name | Required | Description | Default |
|---|---|---|---|
| reference | Yes | Swarm reference hash. |
Output Schema
| Name | Required | Description |
|---|---|---|
| textData | Yes | The downloaded data for the given reference. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are present, so the description carries the behavioral burden. It clearly states the operation returns a string and is limited to raw text, and the usage guidance prevents misuse. It does not go into edge-case behavior, but for a simple read-like tool this is sufficient.
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?
Every sentence contributes: purpose, when-to-use, when-not-to-use, and the fallback alternative are all packed into a compact description. The critical routing information is front-loaded.
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 one-parameter tool with an output schema and full parameter coverage, the description is complete: it defines what is returned, exactly when to call it, and which sibling to choose instead. Nothing needed for correct selection and invocation is missing.
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 single parameter has full schema description coverage ('Swarm reference hash'), so the schema already documents it. The description adds context about upload_data-origin references but does not materially enhance the parameter semantics beyond the baseline.
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 names a specific verb ('Download'), a resource ('raw text data from a Swarm reference'), and the result type ('string'), making the tool's purpose explicit. It also implicitly differentiates from download_files by restricting scope to raw text content.
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 exact conditions for use ('ONLY when the user explicitly asks for text content, string content, or raw data') and explicit exclusions for file/folder requests that route to download_files. It even provides a tie-breaker rule ('When in doubt... prefer download_files'), which is unusually complete guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
download_filesDownload filesA
Download a file or folder from a Swarm reference. Handles both single files and folder manifests, saves them to disk (in stdio mode) or returns the file list. Use this tool whenever the user asks to "download" from a reference and mentions "file", "files", "folder", or does not specify the data type. Prefer this tool over download_data unless the user explicitly asks for the raw text/string content behind a reference. This is the safe default for downloads when the reference type is unknown.
| Name | Required | Description | Default |
|---|---|---|---|
| filePath | No | Optional destination FOLDER (not a filename) to save the downloaded content into (only available in stdio mode). Files from the manifest are written inside this folder using their original names. Absolute paths are recommended; relative paths resolve against the server's current working directory. If omitted, files are saved into the server's current working directory. | |
| reference | Yes | Swarm reference hash |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral disclosure burden. It does disclose mode-dependent behavior ('saves them to disk (in stdio mode) or returns the file list') and that it handles folder manifests. It does not mention overwrite behavior, permissions, or error cases, but the core surprising behavior is covered.
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?
Three sentences, front-loaded with the core purpose, then usage guidance, then the sibling routing rule. Every sentence contributes actionable information with no filler.
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 two parameters, no output schema, and no annotations, the description covers the main usage scenario, mode-dependent behavior, and alternatives. It does not specify what the returned file list looks like or what happens on failure, but enough information is present for an agent to decide to call it and pass the required reference parameter.
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 adds context by explaining that files from a manifest are written into the destination folder, and it clarifies the stdio-mode dependency, but it largely restates what the schema already documents. It does not materially improve on the parameter descriptions.
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 ('Download a file or folder from a Swarm reference'), and further specifies that it handles both single files and folder manifests. It also distinguishes itself from download_data by naming the alternative and explaining when to prefer it.
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?
Explicit usage conditions are given: use this tool when the user asks to download and mentions 'file', 'files', 'folder', or does not specify a data type. It also gives a clear exclusion rule: prefer download_data only when raw text/string content is explicitly requested. This is strong routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_feedRead feedB
Retrieve the latest data from the feed of a given topic.
| Name | Required | Description | Default |
|---|---|---|---|
| owner | No | when accessing external memory or feed, ethereum address of the owner must be set | |
| memoryTopic | Yes | Feed topic. |
Output Schema
| Name | Required | Description |
|---|---|---|
| textData | Yes | The downloaded data for the given topic. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must carry the burden of behavioral disclosure. It only says 'Retrieve,' which hints at a read-only operation, but it does not explicitly say whether it has side effects, requires ownership or authentication, or any constraints like rate limits. The description is not misleading, but is far from transparent.
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 one sentence, free of filler, and front-loads the verb and object. Every word contributes to the core message, making it easy to parse quickly.
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?
Given the tool's low complexity, 100% parameter schema coverage, and presence of an output schema, the description is nearly sufficient for an agent to invoke the tool and interpret results. The main gap is the lack of guidance about the optional owner parameter for external/feed memory access, but that is already captured in the schema, so this is a minor shortfall.
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 memoryTopic and owner are already documented with concrete meaning. The description adds 'given a topic,' which aligns with memoryTopic but does not explain the owner field or when it is required. Baseline of 3 is appropriate because the schema does most of the work.
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 action ('Retrieve') and resource ('the latest data from the feed'), so the tool's core function is clear. It does not differentiate from siblings like download_data or download_files, but the feed-specific wording makes it reasonably distinct.
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 the tool—when you want a topic's feed data—but gives no explicit guidance about when not to use it, prerequisites, or alternatives such as update_feed or download_data. With six siblings present, this lack of routing guidance leaves the agent to infer the right choice.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_feedUpdate feedA
Update a mutable, topic-indexed Swarm feed with new data. Requires a memoryTopic supplied by the user. Use this tool ONLY when the user explicitly mentions a feed, topic, or memory name. If the user asks to upload data without mentioning a feed/topic/memory, use upload_data instead — do NOT prompt the user for a topic to route them here. postageBatchId is optional — do not ask the user for it unless they explicitly bring it up.
| Name | Required | Description | Default |
|---|---|---|---|
| data | Yes | The literal string content to write to the feed, taken verbatim from the user's message. Pass the exact text the user provided (typically the text after phrases like "with:", "update with:", "set to:", or similar), even if the value looks like a short identifier, a placeholder name (e.g. 'Message1', 'foo'), or otherwise seems like a variable — it is the content itself. Do not ask the user to clarify or expand the content; do not substitute your own text. | |
| memoryTopic | Yes | Required. Must be supplied by the user. If missing, ask the user — never invent, hash, or derive from the data. The feed topic. Pass exactly whatever the user names it as a plain string (e.g. 'notes', 'Topic1', 'game-state') -- the server hashes non-hex strings into a topic automatically. Do NOT derive it from the data. Only ask the user if they gave no topic at all. | |
| postageBatchId | No | The id of the batch which will be used to perform the upload. |
Output Schema
| Name | Required | Description |
|---|---|---|
| topic | Yes | The topic. |
| feedUrl | Yes | The feed URL. |
| message | No | Update feed response message. |
| reference | Yes | Swarm reference hash for feed update. |
| topicString | No | The topic string. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full responsibility. It does disclose that the tool writes new data to a mutable feed and that `memoryTopic` must be user-supplied, and it sets expectations about not asking for `postageBatchId`. However, it does not describe side effects like overwriting existing content, behavior if the feed/topic does not exist, or error handling. The word 'update' implies mutation, but the consequences are not fully transparent.
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 well-structured and front-loaded, opening with the core action and then presenting usage rules and optional-parameter policy. Each sentence provides useful guidance, though there is minor repetition around 'the user' and the phrasing could be tightened slightly.
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 update tool with a fully covered schema and an output schema, the description supplies the essential routing rules, required topic source, and optional-parameter etiquette. It does not cover edge cases like missing feed creation or failure behavior, but those are not critical for an agent to call the tool correctly in the intended scenarios.
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 schema already provides rich parameter details, including verbatim data handling and server-side hashing of topics. The description adds reinforcement that `memoryTopic` must come from the user and `postageBatchId` is optional, but it does not add semantic meaning beyond what the schema 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?
The description states a specific action ('Update a mutable, topic-indexed Swarm feed with new data') that clearly distinguishes this tool from siblings like `read_feed` (read vs. update) and `upload_data` (no topic context). It identifies the verb, the resource, and the operational scope in one sentence.
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 explicitly says when to use the tool ('ONLY when the user explicitly mentions a feed, topic, or memory name'), names the alternative (`upload_data`) for the opposite case, and warns against prompting the user to route here. It also gives clear guidance on the optional `postageBatchId` parameter, telling the agent not to ask unless the user brings it up.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
upload_dataUpload dataA
Upload arbitrary text data to Swarm as an immutable, content-addressed blob. Returns a Swarm reference hash that permanently identifies the uploaded bytes. Use this tool whenever the user asks to "upload data", "upload text", "store data", or similar, without mentioning a feed, topic, or memory. This is NOT a feed operation — if the user wants mutable, topic-indexed storage (i.e. mentions a feed, topic, or memory name), use update_feed instead. Only data is required. redundancyLevel and postageBatchId are optional — use their defaults and do NOT ask the user for them unless the user explicitly brings them up.
| Name | Required | Description | Default |
|---|---|---|---|
| data | Yes | The literal string content to upload, taken verbatim from the user's message. Pass the exact text the user provided (typically the text after phrases like "upload data:", "upload:", "store:", or similar), even if the value looks like a short identifier, a placeholder name (e.g. 'Text1', 'Message1', 'foo'), or otherwise seems like a variable — it is the content itself. Do not ask the user to clarify or expand the content; do not substitute your own text. | |
| postageBatchId | No | Optional. The id of the batch which will be used to perform the upload. Do not ask the user for this value; only set it if the user explicitly provides a batch id. | |
| redundancyLevel | No | Optional redundancy level for fault tolerance (higher values provide better fault tolerance but increase storage overhead): 0 - none, 1 - medium, 2 - strong, 3 - insane, 4 - paranoid. Default is 0. Do not ask the user for this value; only set it if the user explicitly requests a redundancy level. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | Yes | URL to access uploaded data. |
| message | No | Upload response message. |
| reference | Yes | Swarm reference hash for uploaded data. |
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 explains that uploaded data is immutable and content-addressed, and that the returned hash permanently identifies the bytes. This adds useful context about side effects, though it could have mentioned whether the operation requires authentication or has rate limits, but the description does not contradict anything.
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 concise, uses bullet-like structure in a natural way, and front-loads the core action. Every sentence earns its place: it states purpose, gives usage triggers, routes away from sibling tools, and clarifies parameter handling. No fluff or redundancy.
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 three parameters, an output schema, and no nested objects, the description covers all necessary aspects: what it does, when to use it, how handles parameters, and what it returns. It even addresses edge cases like placeholder values. The existence of an output schema reduces the need to describe return details, but the description still mentions the return hash.
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?
Although the schema descriptions cover 100% of parameters, the description adds critical semantic detail beyond the schema. It emphasizes that the `data` parameter should be taken verbatim from the user's message and includes guidance to avoid substituting or clarifying content. This is significant added value because the schema might not convey that the string is literal content, not a variable reference. The description also reiterates that optional parameters should use defaults and not be asked 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?
The description clearly states the tool's purpose: uploading arbitrary text data as an immutable content-addressed blob and returning a Swarm reference hash. It uses a specific verb ('upload') and resource ('text data'), and distinguishes itself from feed operations by explicitly mentioning that it is not a feed operation.
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 explicit when-to-use guidance: it tells the agent to use this tool for phrases like 'upload data', 'upload text', 'store data' without mentioning feed, topic, or memory. It also names the alternative tool `update_feed` and specifies when NOT to use this one, making the routing decision unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
upload_fileUpload fileA
Upload a SINGLE file to Swarm. To upload a local file, pass its filesystem path as data — the server reads the file itself (stdio mode only). Alternatively, pass the raw text content directly as data. This tool handles one file only — if the path refers to a directory, or the user mentions "folder", "directory", "the contents of", or otherwise asks to upload more than one file, use upload_folder instead and pass the path as its folderPath. Never ask the user for the file content when a path is given, and never pass a Swarm reference — references are the OUTPUT of this tool, not an input. Small files upload synchronously and return a reference. Large files (over the server's deferred-upload threshold) upload in the background and immediately return the final reference (computed locally) plus a tagId for query_upload_progress; the content becomes retrievable at the reference once the upload completes. With redundancyLevel > 0 only the tagId is returned immediately. Optional options (ignore if they are not requested): redundancyLevel: redundancy level for fault tolerance. Optional, value is 0 if not requested. postageBatchId: The postage stamp batch ID which will be used to perform the upload, if it is provided.
| Name | Required | Description | Default |
|---|---|---|---|
| data | Yes | File content or file path. | |
| postageBatchId | No | The id of the batch which will be used to perform the upload. | |
| redundancyLevel | No | redundancy level for fault tolerance (higher values provide better fault tolerance but increase storage overhead) 0 - none, 1 - medium, 2 - strong, 3 - insane, 4 - paranoid |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and does so thoroughly. It discloses that local paths only work in stdio mode, that the server reads the file itself, that large files upload asynchronously, and that with redundancyLevel > 0 only the tagId is returned immediately. It also states that references are the tool's output, not an input.
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 long but every sentence earns its place: core usage modes, routing to upload_folder, behavioral notes on sync/async uploads, and optional parameters all serve the agent's decision-making. The most critical constraints are front-loaded, and the optional parameters are logically grouped at the end.
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 and no output schema, the description is remarkably complete. It explains return behavior (reference, tagId, query_upload_progress), deferred uploads, redundancy behavior, and the alternative tool. An agent has enough information to select and invoke this tool correctly in a wide range of contexts.
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?
Although schema coverage is 100%, the description adds substantial meaning beyond the schema: it explains how to pass a filesystem path versus raw text for `data`, notes stdio-only limitation, and details the optional semantics of redundancyLevel and postageBatchId. This goes far beyond the bare schema descriptions.
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 defines the tool as uploading a SINGLE file to Swarm, with specific content modes (filesystem path or raw text). It explicitly differentiates from upload_folder by stating that this tool is for one file only, and clarifies that Swarm references are outputs, not inputs.
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 gives explicit when-to-use and when-not-to-use guidance: if the user mentions "folder", "directory", "the contents of", or requests more than one file, the agent should use upload_folder instead. It also instructs the agent never to ask for file content when a path is given and never to pass a Swarm reference as input.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
upload_folderUpload folderA
Upload a folder (directory). Use this tool whenever the user mentions "folder", "directory", "the contents of", or asks to upload a path that refers to a directory rather than one file — including phrasings like "upload to Swarm folder ", where is the folder to upload, not a destination. Prefer this tool over upload_file when it is unclear whether a given path is a file or a directory: upload_file cannot upload a directory. folderPath is REQUIRED — pass the folder path from the user's message verbatim. Small folders upload synchronously and return the manifest reference. Large folders (over the server's deferred-upload threshold) upload in the background and return only a tagId; unlike upload_file, a folder's reference cannot be computed up front, so retrieve it by polling query_upload_progress with that tagId until processedPercentage is 100. Optional options (ignore if they are not requested): redundancyLevel: redundancy level for fault tolerance. Optional, value is 0 if not requested. postageBatchId: The postage stamp batch ID which will be used to perform the upload, if it is provided.
| Name | Required | Description | Default |
|---|---|---|---|
| folderPath | Yes | Required. Path to the local folder to upload, taken verbatim from the user's message. Do not ask the user to confirm or re-enter the path when one was already given. | |
| postageBatchId | No | The id of the batch which will be used to perform the upload. | |
| redundancyLevel | No | redundancy level for fault tolerance (higher values provide better fault tolerance but increase storage overhead) 0 - none, 1 - medium, 2 - strong, 3 - insane, 4 - paranoid |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden, and it does so well. It discloses both synchronous behavior (small folders return a `reference`) and asynchronous behavior (large folders return a `tagId` and require polling `query_upload_progress` until processedPercentage is 100). This gives the agent the operational knowledge needed to handle either path correctly.
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 longer than average, but every sentence serves a purpose: trigger phrases, sibling differentiation, sync/async behavior, polling, and parameter usage. Some minor redundancy exists (e.g., 'Optional options' and 'ignore if they are not requested'), but the overall structure is front-loaded with purpose and usage before deferring to parameter details.
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?
Given that there is no output schema and no annotations, the description covers everything an agent needs to call the tool correctly: required path, sync/async return semantics, how to retrieve the eventual reference, and how to treat optional parameters. It also handles nuanced user phrasings that might otherwise route the agent to `upload_file`.
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 already covers 100% of parameters, so the baseline is 3. The description adds meaningful operational semantics beyond the schema: `folderPath` must be passed verbatim, optional parameters should be ignored unless requested, redundancyLevel defaults to 0, and postageBatchId is only used if provided. This lifts the score above baseline.
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 tool's function: 'Upload a folder (directory)' and goes beyond by explicitly naming the sibling tool `upload_file` as the alternative when the path is a file. It even lists phrasing triggers like 'folder', 'directory', and 'the contents of', making the distinction unmistakable.
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 explicit when-to-use guidance: 'Use this tool whenever the user mentions "folder", "directory", ...' and says to prefer it over `upload_file` when the path type is unclear. It also instructs not to ask for confirmation or re-entering the path, and to ignore optional parameters if not requested.
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.
7 tool updates
v0.9.5- First observed
download_data - First observed
download_files - First observed
read_feed - First observed
update_feed - First observed
upload_data - First observed
upload_file - First observed
upload_folder
TDQS
Scored across 7 tools
The upload family is mostly well-separated, but `upload_file` accepts raw text content in addition to paths, making it overlap with `upload_data` for text uploads. The download pair is better distinguished by explicit routing rules, though it still relies on subtle user phrasing.
All tools follow a readable `verb_noun` snake_case pattern (`upload_folder`, `read_feed`, etc.). Minor inconsistency: `upload_file` is singular while `download_files` is plural, and `upload_data`/`upload_file` are semantically close despite different nouns.
Seven tools is a reasonable scope for a storage-plus-feed MCP server. Each tool has a clear responsibility in the workflow, even if `upload_data` partially overlaps with `upload_file`.
The set covers upload/download and feed read/update, but both upload tools reference `query_upload_progress` for deferred uploads, and that tool is absent from the server. Large uploads therefore dead-end with only a tagId, which is a significant functional gap.
Maintenance
Related MCP Connectors
Self-hosted MCP server: 26 deterministic dev, security, and EVM tools.
MCP tools for TON Sites, TON DNS and TON Storage.
MCP server for Boson Protocol — on-chain agentic commerce for physical & digital goods.
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
Related MCP Servers
- AlicenseCqualityFmaintenance🪐 MCP IPFS Server This server empowers language models 🤖 and other MCP clients to manage storacha.network spaces, upload/download data, manage delegations, and perform various other tasks by seamlessly wrapping w3 commands.3515 npm21MIT
- AlicenseAqualityBmaintenanceMCP server with 43 tools for blockchain data — token lookups, wallet balances, live chain queries across 10+ networks, and full API documentation search.27696 npmApache 2.0
- AlicenseAqualityBmaintenanceMCP server exposing the Swarmwage agent hire protocol as tools for any MCP-compatible AI agent (Claude Desktop, Claude Code, Cursor, Cline, etc.)113MIT
- AlicenseAqualityDmaintenanceMCP server for Shelby Protocol that enables AI agents to read, write, and manage files on decentralized storage (Aptos) through tools like upload, download, list, delete, and account info.51MIT