MCP Server
Media processing via Transloadit Robots: video encoding (HLS, H.264, VP9), image resizing and watermarks, document conversion, OCR and transcription.
What can you do with MCP Server?
include_builtin:all,latest,exclusively-all,exclusively-latestinclude_content: include parsedstepsin each template item
Install
The installation steps are in the documentation below. Documentation
Documentation
From the project's README on GitHub, refreshed weekly. Links open on GitHub.
Contents
- @transloadit/mcp-server
- Connect by URL (recommended)
- CI and headless agents
- Self-hosted
- Auth model
- Configuration
- Tool surface
- Input files
- Limits
- Waiting for Assemblies
- URL inputs and template behavior
- Local vs hosted file access
- Resume behavior
- Metrics and server card
- MCP vs skills/CLI
- Verify MCP clients
- Docs
- Contributing
@transloadit/mcp-server
Transloadit MCP Server (Streamable HTTP + stdio), built on top of @transloadit/node.
Connect by URL (recommended)
The hosted server lives at:
https://api2.transloadit.com/mcp
Add it to your MCP client by URL. The client discovers API2 as the OAuth authorization server, opens a browser consent page in the Transloadit Console, and keeps a short-lived token plus refresh token for you. No API keys leave your Workspace.
The hosted endpoint asks you to sign in before any tool runs, Robot docs and linting included, because MCP clients only start OAuth when the endpoint challenges them. Robot docs and linting ask for no scopes. To use them without an account, run the server yourself (see Self-hosted).
Claude Code
claude mcp add --transport http transloadit https://api2.transloadit.com/mcp
claude mcp login transloadit
For non-interactive runs (for example claude -p), explicitly allow MCP tools:
claude -p "List templates" \
--allowedTools mcp__transloadit__* \
--output-format json
Claude.ai and Claude Desktop
Settings → Connectors → Add custom connector → enter https://api2.transloadit.com/mcp. Claude
registers itself with API2 and opens the consent page.
ChatGPT
Settings → Apps & Connectors → Advanced → Developer mode → Create, then enter the URL above with
authentication set to OAuth. Files you attach in the chat are handed to
transloadit_create_assembly as attachments; results render in the Assembly result widget.
The plugin manifest for the ChatGPT and Codex catalog (plugin.json, mcp.json and the
.codex-plugin/plugin.json fallback) lives in this package directory. It points at the hosted
server and at the Agent Skills catalog at https://transloadit.com/.well-known/skills/index.json
instead of bundling skill files.
Codex
codex mcp add transloadit --url https://api2.transloadit.com/mcp
Codex opens the consent page right away. To sign in again later, run
codex mcp login transloadit.
Or in ~/.codex/config.toml:
[mcp_servers.transloadit]
url = "https://api2.transloadit.com/mcp"
Cursor
~/.cursor/mcp.json:
{
"mcpServers": {
"transloadit": {
"url": "https://api2.transloadit.com/mcp"
}
}
}
MCP Inspector
npx @modelcontextprotocol/inspector --cli https://api2.transloadit.com/mcp
CI and headless agents
Where no browser is available, mint a bearer token from an Auth Key and pass it as
Authorization: Bearer <token>:
npx -y @transloadit/node auth token --aud mcp
Generate this token in a trusted environment (backend, CI, or local shell), then hand it to the agent runtime. You can mint it via:
- CLI:
npx -y @transloadit/node auth token --aud mcp - API:
POST https://api2.transloadit.com/token(HTTP Basic Auth with key/secret) - Node SDK: instantiate
TransloaditwithauthKey+authSecret, then callclient.mintBearerToken({ aud: 'mcp' })
Interactive CLI sessions can also run npx -y @transloadit/node auth login (device flow) and reuse
the stored credentials.
Bearer tokens satisfy signature auth on API2 requests; signature checks apply to key/secret requests.
Self-hosted
Run the server where your agent runs, set TRANSLOADIT_KEY and TRANSLOADIT_SECRET, and the server
handles API auth automatically.
Install
npm install @transloadit/mcp-server
Stdio
TRANSLOADIT_KEY=MY_AUTH_KEY TRANSLOADIT_SECRET=MY_SECRET_KEY npx -y @transloadit/mcp-server stdio
Auth Keys sign with one HMAC algorithm. Keys created in the Console with "Allow signing Smart CDN
URLs" (the default) require sha256, so add TRANSLOADIT_SIGNATURE_ALGORITHM=sha256, as the
Console's snippet for the key shows. Other keys use the default sha384. A mismatch fails with
mcp_invalid_signature, and its hint names the algorithm the key requires.
HTTP
TRANSLOADIT_KEY=MY_AUTH_KEY TRANSLOADIT_SECRET=MY_SECRET_KEY \
npx -y @transloadit/mcp-server http --host 127.0.0.1 --port 5723
When binding HTTP mode to non-localhost hosts, TRANSLOADIT_MCP_TOKEN (or the hosted-mode
TRANSLOADIT_MCP_RESOURCE_METADATA_URL) is required.
Docker
docker run -i --rm \
-e TRANSLOADIT_KEY=MY_AUTH_KEY \
-e TRANSLOADIT_SECRET=MY_SECRET_KEY \
ghcr.io/transloadit/mcp-server:latest
For HTTP mode via Docker, override the stdio entrypoint, expose the port, and set a transport
token, which binding to 0.0.0.0 requires:
export TRANSLOADIT_MCP_TOKEN="$(openssl rand -hex 32)"
docker run --rm \
-e TRANSLOADIT_KEY=MY_AUTH_KEY \
-e TRANSLOADIT_SECRET=MY_SECRET_KEY \
-e TRANSLOADIT_MCP_TOKEN \
-p 5723:5723 \
--entrypoint transloadit-mcp \
ghcr.io/transloadit/mcp-server:latest \
http --host 0.0.0.0 --port 5723
TRANSLOADIT_MCP_TOKEN explained
TRANSLOADIT_MCP_TOKEN is a self-hosted MCP transport token. It protects your own HTTP MCP endpoint
(npx -y @transloadit/mcp-server http), not API2.
- Set it yourself to any high-entropy secret.
- Send it from your MCP client as
Authorization: Bearer <TRANSLOADIT_MCP_TOKEN>. - It is not minted via
/token. - It is separate from API2 Bearer tokens used for
https://api2.transloadit.com/mcp.
Generate one, then start HTTP mode:
export TRANSLOADIT_MCP_TOKEN="$(openssl rand -hex 32)"
npx -y @transloadit/mcp-server http --host 0.0.0.0 --port 5723
Self-hosted client setup
Most self-hosted users add the server to their MCP client and let the client start it via stdio.
Claude Code
claude mcp add --transport stdio transloadit \
--env TRANSLOADIT_KEY=... \
--env TRANSLOADIT_SECRET=... \
-- npx -y @transloadit/mcp-server stdio
Codex CLI
codex mcp add transloadit \
--env TRANSLOADIT_KEY=... \
--env TRANSLOADIT_SECRET=... \
-- npx -y @transloadit/mcp-server stdio
Allowlist tools in ~/.codex/config.toml:
[mcp_servers.transloadit]
command = "npx"
args = ["-y", "@transloadit/mcp-server", "stdio"]
enabled_tools = ["transloadit_list_templates"]
Gemini CLI
gemini mcp add --scope user transloadit npx -y @transloadit/mcp-server stdio \
--env TRANSLOADIT_KEY=... \
--env TRANSLOADIT_SECRET=...
Allowlist tools in ~/.gemini/settings.json:
{
"mcpServers": {
"transloadit": {
"command": "npx",
"args": ["-y", "@transloadit/mcp-server", "stdio"],
"env": {
"TRANSLOADIT_KEY": "...",
"TRANSLOADIT_SECRET": "..."
},
"includeTools": ["transloadit_list_templates"]
}
}
}
Cursor
~/.cursor/mcp.json:
{
"mcpServers": {
"transloadit": {
"command": "npx",
"args": ["-y", "@transloadit/mcp-server", "stdio"],
"env": {
"TRANSLOADIT_KEY": "...",
"TRANSLOADIT_SECRET": "..."
}
}
}
}
OpenCode
~/.config/opencode/opencode.json:
{
"mcp": {
"transloadit": {
"command": "npx",
"args": ["-y", "@transloadit/mcp-server", "stdio"],
"env": {
"TRANSLOADIT_KEY": "...",
"TRANSLOADIT_SECRET": "..."
}
}
}
}
Auth model
Hosted (https://api2.transloadit.com/mcp)
- Requests without a bearer token get
401withWWW-Authenticate: Bearer resource_metadata="https://api2.transloadit.com/.well-known/oauth-protected-resource/mcp". MCP clients follow that document to API2's authorization server (authorization code + PKCE, Dynamic Client Registration or Client ID Metadata Documents). - This includes a bare
GET /mcp, because some clients (Codex) discover the authorization server from that probe. Directory health checks therefore see401instead of200; the JSON body still carriesname,statusanddocs. Self-hosted and unauthenticated deployments keep answering the bareGETwith200. - Bearer tokens (OAuth or minted with
--aud mcp) are forwarded to API2, which verifies them on every call. A rejected or expired token yields a tool result withisErrorand_meta["mcp/www_authenticate"], so ChatGPT and Claude prompt you to reconnect. - Each tool declares
securitySchemes(top level and in_meta). Because the hosted endpoint challenges every unauthenticated request, all tools declareoauth2there; the Robot docs and linting tools ask for no scopes. - A rejected or expired key/secret on a self-hosted server is reported as
mcp_credentials_rejectedwithout an OAuth challenge, since only an operator can fix it. - Browser requests must come from ChatGPT, Claude, Transloadit or loopback origins; requests without
an
Originheader (CLIs, servers) are not restricted. SetallowedOriginsto change the list. TRANSLOADIT_MCP_UPSTREAM_SECRETis set by Transloadit's own deployment so API2 can tell that a relayedaud=mcptoken arrives from the hosted service; it is not needed for self-hosting. Hosted mode refuses to start without it, because every authenticated call would fail.
Self-hosted
- Stdio and localhost HTTP need no MCP auth by default.
- Non-localhost HTTP requires
TRANSLOADIT_MCP_TOKEN(a static secret you define). - Live Transloadit API calls use:
- incoming Bearer token from MCP request headers, or
TRANSLOADIT_KEY+TRANSLOADIT_SECRET.
Configuration
Environment variables
TRANSLOADIT_KEYTRANSLOADIT_SECRETTRANSLOADIT_SIGNATURE_ALGORITHM(optional,sha1,sha256orsha384, defaultsha384; must match the Auth Key)TRANSLOADIT_MCP_TOKENTRANSLOADIT_MCP_RESOURCE_METADATA_URL(hosted mode: protected-resource metadata URL to advertise in401challenges)TRANSLOADIT_MCP_UPSTREAM_SECRET(hosted mode only, set by Transloadit's deployment; sent to API2 asTransloadit-Mcp-Upstreamnext to forwarded bearer tokens)TRANSLOADIT_MCP_RESULT_DOMAINS(optional, comma-separated origins the result widget may load previews from and link to, either exact such ashttps://tmp-us-east-1.transloadit.netor with a wildcard host; defaulthttps://*.transloadit.com,https://*.transloadit.net,https://*.r2.dev)TRANSLOADIT_MCP_WIDGET_DOMAIN(optional, defaulthttps://transloadit.com; the origin ChatGPT serves the result widget from, sent as_meta["openai/widgetDomain"])TRANSLOADIT_MCP_CONSOLE_URL(optional, defaulthttps://transloadit.com; Console origin for widget deep links)TRANSLOADIT_ENDPOINT(optional, defaulthttps://api2.transloadit.com)TRANSLOADIT_MCP_METRICS_PATH(optional, default/metrics)TRANSLOADIT_MCP_METRICS_USER(optional)TRANSLOADIT_MCP_METRICS_PASSWORD(optional)
CLI flags
npx -y @transloadit/mcp-server http --host 127.0.0.1 --port 5723npx -y @transloadit/mcp-server http --endpoint https://api2.transloadit.comnpx -y @transloadit/mcp-server http --config path/to/config.json
The JSON config accepts the same keys as createTransloaditMcpHttpHandler(), including
allowedOrigins, resourceMetadataUrl, signatureAlgorithm, resultDomains, widgetDomain and
consoleUrl.
Tool surface
| Tool | Account | OAuth scopes | Notes |
|---|---|---|---|
transloadit_lint_assembly_instructions | no | none | read-only |
transloadit_list_robots | no | none | read-only |
transloadit_get_robot_help | no | none | read-only |
transloadit_create_assembly | yes | assemblies:write, templates:read | destructive, open-world (URL imports), widget |
transloadit_get_assembly_status | yes | assemblies:read | read-only |
transloadit_wait_for_assembly | yes | assemblies:read | read-only, result widget |
transloadit_list_templates | yes | templates:read | read-only |
transloadit_get_profile | yes | assemblies:read, templates:read | read-only, _meta["openai/profile"] |
Every tool carries title, readOnlyHint, destructiveHint, idempotentHint and
openWorldHint annotations. transloadit_create_assembly is the only destructive one: export
Robots such as /s3/store can overwrite files at their destination, so hosts should confirm it.
transloadit_lint_assembly_instructions validates complete, merged instructions locally. It does
not fetch the Template named by template_id: resolve the Template and merge any Assembly or
replay overrides before linting. For example, an OCR Step that inherits ocr_provider must
include that provider in the instructions passed to this tool.
securitySchemes depend on how the server runs: hosted (TRANSLOADIT_MCP_RESOURCE_METADATA_URL)
declares oauth2 with the scopes above for every tool; a server holding TRANSLOADIT_KEY and
TRANSLOADIT_SECRET declares noauth everywhere; otherwise the account tools declare oauth2 and
the others noauth. TRANSLOADIT_MCP_TOKEN and TRANSLOADIT_MCP_RESOURCE_METADATA_URL cannot be
combined.
Authenticated tools/list is the reference for outcome shortcuts, descriptions and field schemas.
The synced alphalib Builtin manifest supplies
reviewed version pins and temporary field exclusions. The MCP adapter derives tool names and
titles from those IDs and consumes the catalog schema through @transloadit/zod/v4/builtinTemplates.
An alphalib sync carries approved additions, renames, removals and gate changes without another
MCP registry.
Descriptions, standalone draft-07 fields_schema and content.fields defaults come from API2’s
Template catalog. Defaults merge before validation, preserving JSON types; conservative schema
annotations leave runtime cross-field validation authoritative. A null or absent contract makes
that shortcut unavailable. Generic tools keep their existing behavior.
The manifest’s temporary legacy VP8 webm gate remains until
api2#9960 is deployed and verified.
Social captions are deferred. Transcription language hints do not translate speech.
Catalog reads have a three-second overall deadline without retries. During an authenticated
catalog outage the reviewed names remain discoverable with permissive fields; each call still
fetches and validates the current contract. Malformed or default-sensitive composed schemas also
use permissive discovery, followed by full validation after merging defaults at execution.
Supply fields and the same files/attachments/upload/wait options as transloadit_create_assembly.
For a sandbox file, set expected_uploads, run the returned upload command, then call
transloadit_wait_for_assembly. The SDK already includes the
document extraction registry fix.
transloadit_list_templates supports:
include_builtin:all,latest,exclusively-all,exclusively-latestinclude_content: include parsedstepsin each template item
Builtin items also carry fields_schema unchanged, including conservative-fidelity metadata
and null for older Builtins without a declared schema. Workspace Templates omit that property.
transloadit_get_profile returns { id, name?, nickname? } for the Workspace behind the current
credentials, derived from the Workspace's own Assemblies or Templates.
Result widget
transloadit_create_assembly and transloadit_wait_for_assembly link the MCP Apps resource
ui://transloadit/assembly-result (_meta.ui.resourceUri, also _meta["openai/outputTemplate"]).
Hosts that support MCP Apps render each Step's results with image, video and audio previews,
download links, an "Open in Console" link and a "Save as Template" shortcut. It speaks the MCP Apps
2026-01-26 protocol (ui/initialize with appInfo) and also reads ChatGPT's window.openai.
Its CSP allows https://*.transloadit.com, https://*.transloadit.net and https://*.r2.dev
(result buckets); override the list with TRANSLOADIT_MCP_RESULT_DOMAINS or resultDomains.
ChatGPT asks for the exact hosts a widget uses, so a deployment that knows its result buckets
should list them as origins instead of wildcards. ChatGPT also needs redirect_domains to open
links from the widget: the server sends the result origins plus the Console origin there. ChatGPT
serves the widget from the origin in _meta["openai/widgetDomain"]
(TRANSLOADIT_MCP_WIDGET_DOMAIN). ui.domain stays unset, because Claude derives that value from
the server URL and rejects any other.
Input files
export type InputFile =
| {
kind: 'base64'
field: string
base64: string
filename: string
contentType?: string
}
| {
kind: 'url'
field: string
url: string
filename?: string
contentType?: string
}
Hosts that attach chat files (ChatGPT) pass them under attachments instead, as declared by
_meta["openai/fileParams"]:
type Attachment = {
download_url: string
file_id: string
mime_type?: string
file_name?: string
}
Each attachment becomes a URL input (attachment_1, attachment_2, …) and follows the URL rules
below.
Files that exist only locally or in your sandbox
If the file exists only locally or in your sandbox, call transloadit_create_assembly with
expected_uploads and run the returned upload_instructions; this needs outbound HTTPS from the
sandbox to Transloadit (Claude.ai: Settings → code execution network access must allow it). Hosts
such as Claude.ai do not hand chat attachments to connector tools, and base64 in tool arguments is
impractical for anything but tiny files, so the agent uploads the file itself:
- Call
transloadit_create_assemblywith your instructions andexpected_uploads: 1(one per file, at most 100 per call). The call returns right away, even withwait_for_completion: true, because the Assembly now waits for those uploads. - Each
upload_instructionsentry has the tus endpoint, the tus metadata (assembly_url,fieldname) and a ready-to-runcurlcommand. SetFILEto the file's path and run it in a bash shell; it prints201once the file is uploaded (tus creation-with-upload, one request). - Call
transloadit_wait_for_assemblywith the Assembly URL.
Calling transloadit_create_assembly with assembly_url and expected_uploads (all uploads the
Assembly expects, as at creation) hands out upload_instructions for the uploads an existing
Assembly still waits for.
The commands contain no credentials: the Assembly URL is the only capability, and it lets the holder add files to that one Assembly while it waits for uploads.
Limits
These limits apply to inline JSON/base64 payloads. For larger files, use a public URL or upload from
your own machine with npx -y @transloadit/node upload.
- Hosted default request body limit: 1 MiB
- Hosted
maxBase64Bytes: 512,000 decoded bytes - Self-hosted default request body limit: 10 MiB
Set maxRequestBodyBytes (handler option or JSON config key) to change the body limit; larger
requests get HTTP 413 and are not buffered. Express apps that install their own body parser set
its limit there.
URL inputs that the server downloads (for templates that expect uploads) are capped at 1 GiB in
total per call and 10 minutes per download, redirects included; set maxUrlDownloadBytes and
urlDownloadTimeoutMs to change that. On the hosted
endpoint the caller's token is checked with API2 before anything is downloaded. Downloads count
toward the wait budget below: when they do not finish in time, no Assembly is created and the call
returns mcp_preparation_timeout, so a retry is safe. The download is stopped about a second
later and its file removed.
Waiting for Assemblies
MCP hosts abandon tool calls that run too long (ChatGPT after about a minute) and may retry them,
which would create a second Assembly. transloadit_create_assembly, the Builtin shortcuts and
transloadit_wait_for_assembly therefore wait at most 45 seconds, even with a larger
wait_timeout_ms/timeout_ms. When that budget is spent, the call returns the Assembly with its
current status (a last status read or a slow creation request may take up to 5 seconds more, so
keep the budget that far below the host's limit), running: true and an mcp_assembly_still_running notice; uploads and processing
continue, and transloadit_wait_for_assembly or transloadit_get_assembly_status follow it. Set
maxWaitMs (option or JSON config key) or TRANSLOADIT_MCP_MAX_WAIT_MS to change the budget.
URL inputs and template behavior
For URL inputs, behavior depends on the template/instructions:
- If an
/http/importStep exists, MCP sets/overrides that Step'surl. - If the template expects uploads (
:originalor/upload/handle), MCP downloads then uploads via tus. These downloads require public HTTP(S) URLs; private-network targets are rejected, including redirects to private addresses. - If the template does not take input files, URL inputs are ignored and a warning is returned.
- If
allow_steps_override=falseand only/http/importwould work, URL inputs are rejected.
The Builtin shortcuts for caption-video, convert-to-pdf, encode-video, extract-text,
prepare-image, remove-background, transcribe and video-covers send URLs to API2 as
input_url next to template_id when every file
and attachment of the call is a URL (up to 10, one for caption-video). Transloadit then fetches
the files itself, so the Assembly exists at once and nothing is downloaded by the MCP server or held
up by a large file. API2 names the files after their URLs (or redirects and Content-Disposition),
so inputs given a file name, such as host attachments, keep the download path above, as do calls
that mix URLs with base64 files or sandbox uploads, calls with upload_behavior: 'none', and URLs
that API2 would refuse (whitespace, |, ${…}, over 4096 characters). If API2 refuses
input_url for the request, its error is returned like any other. The eligible Builtins are listed
in the alphalib Builtin manifest.
Local vs hosted file access
- MCP accepts base64 and URL inputs in both self-hosted and hosted deployments. Local filesystem paths are not supported as tool inputs.
- Migration: clients that previously sent
kind: 'path'must switch to base64, a public URL, or a local CLI upload. This also applies to stdio and self-hosted servers. - Use public
urlinputs, smallbase64payloads, or upload locally withnpx -y @transloadit/node upload. - Use
expected_uploadsto keep an Assembly open for out-of-band tus uploads.
Resume behavior
If assembly_url is provided, MCP resumes uploads using Assembly status (tus_uploads +
uploads). This requires stable field names and file metadata (filename + size).
Resubmit the same base64 or public URL input to resume an upload. URL inputs are downloaded and
uploaded even when the original instructions are omitted; resumption does not modify the existing
Assembly's Steps. The file's contents, field name, and filename must remain unchanged.
This resumes tus uploads; URL imports performed by /http/import do not need to be resubmitted.
Assembly IDs must contain 32 hexadecimal characters. Assembly URLs must refer to a Transloadit host
or the explicitly configured API origin, without credentials, query parameters, or fragments.
MCP extracts the ID and resolves the Assembly through its configured API endpoint; it never fetches
the caller-supplied Assembly URL directly. MCP does not follow API response redirects, including an
Assembly's redirect_url. A custom endpoint can use a local origin for development,
but this does not enable private-network URL file downloads.
Metrics and server card
- Prometheus metrics at
GET /metricsby default. - Configure via
TRANSLOADIT_MCP_METRICS_PATHormetricsPath. - Disable via
metricsPath: false. - Optional metrics basic auth via
TRANSLOADIT_MCP_METRICS_USER+TRANSLOADIT_MCP_METRICS_PASSWORDormetricsAuth. - Public discovery at
/.well-known/mcp/server-card.jsondeclarestools: ["dynamic"]; authenticatedtools/listsupplies the complete inventory, schemas, annotations and security schemes. Hosted cards also publish the OAuth resource metadata URL.
MCP vs skills/CLI
- Use MCP for embedded runtime execution (uploads, Assemblies, polling, results).
- Use skills/CLI for human-directed and one-off workflows (setup, scaffolding, local automation).
These are guidelines, not strict rules. Many teams use both.
Verify MCP clients
Run a local smoke test with published MCP server and installed CLIs (Claude Code, Codex CLI,
Gemini CLI). Requires TRANSLOADIT_KEY + TRANSLOADIT_SECRET and active CLI auth.
node scripts/verify-mcp-clients.ts
Set MCP_VERIFY_TIMEOUT_MS to override command timeout.
Docs
- Website docs: https://transloadit.com/docs/sdks/mcp-server/
- API token docs: https://transloadit.com/docs/api/token-post/
Contributing
Prerequisites
- Node.js 22+
- Corepack-enabled Yarn 4
Install dependencies
From repo root:
corepack yarn install
Validate changes
corepack yarn --cwd packages/mcp-server check
Run e2e tests
test:e2e requires valid Transloadit credentials in your environment.
corepack yarn --cwd packages/mcp-server test:e2e
Submit a change
- Add or update tests with behavior changes.
- Keep README and website docs aligned for user-facing behavior.
- Open a PR in
transloadit/node-sdk.
Frequently asked questions
What is MCP Server?
Media processing via Transloadit Robots: video encoding (HLS, H.264, VP9), image resizing and watermarks, document conversion, OCR and transcription.
How do I install MCP Server?
Follow the installation steps in its documentation, shown on this page and in its repository.
Is MCP Server open source?
Yes. Its code is on GitHub under the MIT license.
Who maintains MCP Server?
It is published by transloadit. AI.tn lists it but does not maintain or endorse it.
From the community awesome-mcp-servers lists and the project's GitHub repository. Listing is not an endorsement: review a server's code and permissions before giving it access to your data.