legacy-mcps
Provides tools for interacting with archive.org: searching items with Lucene-style queries, fetching item metadata and file listings by identifier, and uploading local files to items over the S3 gateway (creating items as needed) with metadata headers such as title, mediatype and collection.
Provides tools for managing a SourceForge project's File Release System over SSH/SFTP: uploading local files into release directories (creating directories as needed) with atomic stage-then-rename writes and optional overwrite, and listing files and directories in a release tree.
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., "@legacy-mcpssearch archive.org for NASA images of the Apollo 11 mission"
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.
legacy-mcps
A Model Context Protocol server that gives AI agents tools for managing files and data on two legacy platforms:
Internet Archive — search items, read item metadata, and upload files to items over the archive.org S3 gateway.
SourceForge — upload release files to a project's File Release System (FRS) tree and list what is published, over SSH/SFTP.
The server is credential-aware: read-only tools that need no authentication are always available, and write tools are registered only when the matching credentials are present in the environment.
Install
pip install -e . # runtime dependencies only
pip install -e '.[dev]' # plus pytestRequires Python 3.10 or newer.
Related MCP server: lms-ssh-client-mcp
Run
legacy-mcps # stdio transport (default)
legacy-mcps --transport sse # also: streamable-http
legacy-mcps --describe # print which tools are enabled, then exit--describe is the quickest way to check configuration. It prints the
registration decision as JSON without opening a transport:
{
"server": "legacy-mcps",
"version": "0.1.0",
"internet_archive": {
"read_tools": ["ia_search_items", "ia_get_item_metadata"],
"write_tools": ["ia_upload_file"],
"enabled": true,
"write_enabled": true,
"note": null
},
"sourceforge": {
"tools": ["sf_upload_release_file", "sf_list_release_files"],
"enabled": true,
"note": null
}
}Client configuration
An MCP client launches the server as a subprocess and talks to it over stdio.
For example, in a mcpServers block:
{
"mcpServers": {
"legacy-mcps": {
"command": "legacy-mcps",
"env": {
"IA_ACCESS_KEY": "...",
"IA_SECRET_KEY": "...",
"SF_USERNAME": "your-sourceforge-username",
"SF_SSH_KEY_PATH": "/home/you/.ssh/sourceforge_rsa",
"SF_PROJECT_NAME": "your-project"
}
}
}
}Configuration
Every credential is read from the environment at tool-registration time and at call time. Nothing is stored on disk.
Variable | Used by | Meaning |
| Internet Archive | S3 access key from https://archive.org/account/s3.php |
| Internet Archive | S3 secret key from the same page |
| SourceForge | Your SourceForge account name |
| SourceForge | Path to the private key whose public half is registered with SourceForge |
| SourceForge | The unix name of the project, e.g. |
| SourceForge | SSH host, defaults to |
Which tools appear depends on what is set:
Credentials present | Tools registered |
none |
|
| the above, plus |
|
|
Tools
Internet Archive
Tool | Credentials | Description |
| none | Search archive.org with a Lucene-style query, e.g. |
| none | Fetch an item's metadata and file listing by identifier. |
|
| Upload a local file to an item, creating the item if it does not exist. |
ia_upload_file takes identifier, file_path, an optional remote_name,
optional metadata (which becomes x-archive-meta-* headers — title,
mediatype and collection are the fields the site uses to build the item's
details page), queue_derive and keep_old_version.
Uploads go to the custom S3 endpoint https://s3.us.archive.org. The
x-archive-* headers are injected into the request before SigV4 signing, so
they are covered by the signature the gateway verifies.
SourceForge
Tool | Credentials | Description |
|
| Upload a local file into a release directory such as |
| same | List files and directories in a release directory. An empty |
Uploads land in /home/frs/project/<project>/<remote_dir>/ on
frs.sourceforge.net. Each file is written to a temporary name and then renamed
into place, so a partial transfer is never visible and the mirror sees a single
completed write. overwrite=False (the default) refuses to replace an existing
file; with overwrite=True the swap uses the posix-rename@openssh.com
extension so the published file is replaced atomically.
Unknown SSH host keys are rejected by default, so a network attacker cannot
impersonate SourceForge. On first use, add the host key to your known_hosts
(for example with ssh -o StrictHostKeyChecking=accept-new <user>@frs.sourceforge.net)
or construct the client with allow_unknown_host_key=True.
Response shape
Tools never raise and never tear down the MCP session. Every call returns a JSON object:
{ "ok": true, "remote_path": "/home/frs/project/my-project/releases/1.2.0/app.tar.gz", "size_bytes": 4096, "download_url": "https://sourceforge.net/projects/my-project/files/releases/1.2.0/app.tar.gz/download" }{ "ok": false, "error": "missing_credentials", "message": "Missing required environment variable(s): SF_USERNAME, SF_PROJECT_NAME.", "retryable": false }error is one of a small stable set: missing_credentials, invalid_input,
file_not_found, remote_rejected, not_found, rate_limited, timeout,
connection_error, ambiguous_write, unexpected_error. retryable is true
for rate_limited, timeout and connection_error, so an agent can retry
without guessing.
ambiguous_write is the exception worth knowing about. A timeout or a dropped
connection during an upload does not reveal whether the bytes arrived, so the
file may already be published. The result carries retryable: false and asks
the caller to reconcile the remote state (for example with
sf_list_release_files or ia_get_item_metadata) before retrying.
Project layout
src/legacy_mcps/
├── errors.py # error codes, error payloads, credential helpers
├── server.py # unified entrypoint; credential-aware registration
├── internet_archive/
│ ├── api.py # public metadata + search HTTP endpoints
│ ├── client.py # S3 client: SigV4 signing, x-archive-* headers, upload
│ └── tools.py # MCP tool wrappers
└── sourceforge/
├── client.py # SFTP client: upload, list, path validation
└── tools.py # MCP tool wrappersTests
pip install -e '.[dev]'
pytestThe suite is deliberately built on real protocol code rather than mocks:
Internet Archive tests drive a real
boto3client against a loopback HTTP server standing in for the S3 gateway, then re-derive the SigV4 signature from the recorded request. That checks the property the real gateway enforces — that the injectedx-archive-meta-*headers are part of the signed header set.SourceForge tests run against an in-process SSH/SFTP server (paramiko) rooted in a temporary directory, so the stage-then-rename write path, directory creation, overwrite handling and error mapping are all exercised end to end.
Server tests drive the FastMCP server through the SDK's in-memory transport, including a full
list_tools/call_toolround trip.
License
MIT — see LICENSE.
Available Tools
2 toolsia_get_item_metadataB
Fetch an archive.org item's metadata and file listing by identifier. No credentials required.
| Name | Required | Description | Default |
|---|---|---|---|
| file_limit | No | ||
| identifier | Yes | ||
| include_files | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
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 usefully discloses that no credentials are required and implies a read-only fetch, but says nothing about behavior on an unknown identifier, rate limiting, or the effect of the file_limit cap.
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 short, front-loaded sentences with no filler; the qualification that no credentials are needed earns its place by preempting an authentication question.
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?
An output schema exists, so return values need not be explained. However, for a tool with three parameters and a default truncation limit on file listing, the description leaves the caller without guidance on include_files or the 100-file cap.
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% across three parameters, and the description only explains identifier implicitly through 'by identifier'. The include_files and file_limit parameters—including the default cap of 100 files—are never addressed, so the description 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 (Fetch) and resource (archive.org item metadata and file listing) with the key input (identifier). It implicitly contrasts with the sibling ia_search_items, but never names it, so the differentiation is left to inference.
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 this tool applies (you already have an identifier) versus a search tool, but it never states usage conditions or exclusions explicitly, and does not mention what to do when you only have a query rather than an identifier.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ia_search_itemsB
Search archive.org items. Example query: 'collection:nasa AND mediatype:image'. No credentials required.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | ||
| rows | No | ||
| sort | No | ||
| query | Yes | ||
| fields | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output 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 does disclose that no credentials are required, which is genuinely useful. It says nothing about pagination defaults, result caps, rate limits, or sort behavior, which an agent must guess from the bare schema.
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 short sentences, front-loaded with the purpose, then a concrete query example, then the auth note. Nothing is padded or redundant.
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?
An output schema exists so return values need not be explained, but with 0% schema description coverage the description should compensate for the four undocumented parameters and does not. For a 5-parameter search tool, this is notably incomplete.
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% across 5 parameters, and the description only clarifies the required query via a Solr-style example ('collection:nasa AND mediatype:image'). The page, rows, sort, and fields parameters receive no explanation anywhere.
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 ('Search archive.org items'), which is clearly distinct from the sibling ia_get_item_metadata. However, it never explicitly names the sibling or the boundary between searching and fetching metadata.
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 versus ia_get_item_metadata, nor any conditions, exclusions, or prerequisites beyond the credential note. The example query demonstrates syntax but not tool selection.
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.
2 tool updates
v0.1.0- First observed
ia_get_item_metadata - First observed
ia_search_items
TDQS
Scored across 2 tools
The two tools are clearly distinct: one performs discovery queries, the other retrieves metadata for a known identifier. There is no overlap in purpose or expected arguments.
Both names use the ia_ prefix and snake_case verb_noun structure (search_items, get_item_metadata), which is predictable. Minor inconsistency in noun phrasing (plural 'items' vs. singular 'item_metadata') keeps it from perfect.
Two tools is thin even for a focused read-only archive.org integration; the natural next steps (download/fetch content, browse collections) are absent. Each tool does earn its place, but the surface feels minimal.
Search plus metadata retrieval covers the basic discovery flow, but there is no way to fetch item content/files, list collections, or paginate/refine results beyond the raw query. Agents needing actual archive content hit a dead end.
Maintenance
Related MCP Connectors
Persistent file storage for AI agents via MCP and curl. Upload, download, and version files.
Machine-readable utilities and datasets for AI agents.
Artifact store for AI agents — read, write, and search files by path; share by rendered URL.
Shared long-term memory vault for AI agents with 20 MCP tools.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI agents to connect to and control a Virtual Private Server via SSH. It provides a comprehensive suite of tools for remote file system operations, session management, and shell command execution.105 npm2ISC
- FlicenseAqualityCmaintenanceEnables LLMs to securely SSH into remote servers, execute commands, and manage files via SFTP including listing, reading, writing, deleting, and renaming files.11-
- AlicenseBqualityDmaintenanceEnables AI agents to perform FTP/FTPS/SFTP file operations including upload, download, sync, and directory management with multi-server support.3635 npm7MIT
- AlicenseNot gradedqualityDmaintenanceProvides a browsable, mutable SFTP filesystem for AI agents, supporting file operations like listing, uploading, downloading, moving, and deleting.MIT