记忆

hybrids3

试用

Self-hosted lightweight object storage speaking three interfaces at once — the S3 API (boto3 / AWS-SDK compatible, AWS Sig V4), a plain HTTP API (curl-friendly, Bearer auth), and MCP (Streamable HTTP tools for agents). Buckets/objects with SQLite metadata and flat-file storage on disk; buckets are config-defined (no create/delete API), each with a public/private flag, a private key + public key pair, optional TTL expiry, and a max upload size. Auth is per-bucket keys plus a cross-bucket master key; presigned GET/PUT URLs for handing out single-object access. Use when the user wants to put/get/list/delete files in a self-hosted S3-compatible store, generate presigned upload/download links, drive their own boto3-compatible object storage, or connect an agent to object storage over MCP.

它能做什么

Lightweight object storage that speaks three interfaces from one container: the **S3 API** (boto3 / any AWS SDK, AWS Signature V4), a **plain HTTP API** ( + Bearer token), and **MCP** (Streamable HTTP tool definitions for AI agents). Metadata lives in SQLite, object bytes are flat files on disk.

技能文档

hybrids3

Lightweight object storage that speaks three interfaces from one container: the S3 API (boto3 / any AWS SDK, AWS Signature V4), a plain HTTP API (curl + Bearer token), and MCP (Streamable HTTP tool definitions for AI agents). Metadata lives in SQLite, object bytes are flat files on disk.

Buckets are configuration, not state — they're defined in the server's config.yaml and there is no API to create or delete them. Each bucket carries: a public/private flag, a private key (Bearer token + S3 signing secret), a public_key (the aws_access_key_id identifier), an optional ttl (objects auto-expire after last write), and an optional max_file_size. A single cross-bucket master_key operates on every bucket and is the only credential that can list all buckets.

Object keys support nested paths (reports/2024/jan.pdf). Content type is auto-detected on upload (libmagic sniff + extension fallback). Presigned GET/PUT URLs hand out time-limited single-object access without exposing a key.

For installation, configuration, and container setup, see references/setup.md.

Security & safety

  • Public buckets are world-readable. A bucket with public: true serves GET/HEAD/LIST to anyone who can reach the port — no auth at all. Only store data there that's meant to be openly readable; keep sensitive data in a public: false bucket.
  • Bind loopback, not all interfaces. The container listens on 8080. Publishing it as -p 8080:8080 / compose "8080:8080" makes it reachable from the network by default. Use -p 127.0.0.1:8080:8080 (loopback) unless remote access is intentionally required, and for real deployments put the service on an internal Docker network behind a reverse proxy instead of exposing the port directly — see references/setup.md and Behind a Reverse Proxy.
  • DELETE, presigned PUT, and MCP delete_object are destructive & irreversible. There's no undo, no versioning, no recycle bin — a deleted object (or one overwritten via PUT) is gone. An agent must NEVER call DELETE / delete_object, or generate/use a presigned PUT that overwrites, unless the user explicitly asked for that exact key to be removed or replaced; confirm the specific bucket + key first, never enumerate-then-bulk-delete, and treat bulk cleanup as requiring explicit per-object user confirmation.
  • Bucket keys, master key, and presigned URLs are bearer credentials. Whoever holds a bucket's private key or the master_key (or a live presigned URL) can act as that bucket/master until the credential is rotated or the URL expires — there's no per-caller revocation. Never paste these into shared prompts, logs, or presigned URLs handed to untrusted parties beyond the one object they're meant to grant.
  • This skill is a consumer, not an operator. It talks to an instance the user already runs; it doesn't provision, harden, or expose the server. Don't use this skill to reconfigure config.yaml, change bucket visibility, or alter port bindings on the user's behalf without being explicitly asked.

When To Use

  • Put / get / list / delete files in a self-hosted, S3-compatible object store.
  • Drive existing boto3 / AWS-SDK code against your own endpoint (change endpoint_url + credentials, nothing else).
  • Store artifacts, uploads, reports, backups that services and agents read/write.
  • Generate a presigned PUT URL so a third party can upload one specific key without your bucket key.
  • Generate a presigned GET URL so a third party can download one private object for a limited time.
  • Connect an AI agent to object storage over MCP — structured upload_object / download_object / list_objects / etc. tools.
  • Auto-expiring scratch storage — set a bucket ttl and objects clean themselves up.

When NOT To Use

  • Creating or deleting buckets at runtime — buckets live in config.yaml; add/remove them there and restart. PUT /{bucket} is an S3-compat no-op.
  • Multipart / chunked uploads (S3's multipart protocol) — not implemented. Upload the whole object in one request.
  • Object versioning, ACLs beyond bucket-level public/private, replication, or encryption at rest — none are supported.
  • Downloading objects over 50 MB via MCP — the MCP download_object tool caps at 50 MB. Use the S3 or plain HTTP GET for large objects.
  • CORS from a browser — no CORS headers are emitted; add them at the reverse-proxy layer.
  • Provisioning, configuring, or hardening the server itself — this skill is a consumer. It talks to an instance the user already runs and trusts.

Setup

The container should already be running. Point the skill at it:

export HYBRIDS3_URL=http://localhost:8080

Verify: curl $HYBRIDS3_URL/health returns {"status":"ok"}.

Keys are per-bucket and come from the operator's config.yaml. Export the ones you'll use rather than pasting them inline:

export HYBRIDS3_KEY=          # Bearer token / aws_secret_access_key
export HYBRIDS3_PUBLIC_KEY=    # aws_access_key_id (defaults to bucket name)
# For cross-bucket / list-all-buckets operations, use the master credentials instead:
export HYBRIDS3_MASTER_KEY=
export HYBRIDS3_MASTER_PUBLIC_KEY=   # defaults to "master"

If the server runs behind a reverse proxy at a subpath, HYBRIDS3_URL includes it (e.g. http://host/storage) and every route — health included — lives under that prefix.

For install / config.yaml shape / bucket + key definitions / ports / reverse proxy, see references/setup.md.

Three Access Modes

One service, three front doors on the same port (8080). Pick per client:

ModeEndpointAuthReach for it when…
S3 APIroot (/), signed requestsAWS Sig V4 (public_key = access key id, key = secret)You already have boto3 / AWS-SDK code, or want SDK ergonomics (pagination, presign helpers, retries).
Plain HTTP/{bucket}/{key} etc.Authorization: Bearer Shell scripts, curl, quick one-offs. No SDK, no signing — just a Bearer header (and public-bucket reads need none).
MCPPOST /mcp/per-connection + per-tool auth_keyAn AI agent should manipulate storage through typed tool calls instead of raw HTTP.

They share one SQLite metadata store and one flat-file tree — an object written over S3 is readable over plain HTTP and MCP, and vice versa.

S3 API

S3 clients authenticate with AWS Signature V4. The bucket's public_key is the aws_access_key_id (travels in the request in plaintext, in the Credential= field); the bucket's private key is the aws_secret_access_key (used only to compute the HMAC locally — never transmitted). region_name is required by SDKs but the value is arbitrary — use us-east-1.

Authorization: AWS4-HMAC-SHA256 Credential=uploads-id/20240101/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-date, Signature=

boto3

import boto3
from botocore.config import Config

# per-bucket client — access limited to the "uploads" bucket
s3 = boto3.client(
    "s3",
    endpoint_url="http://localhost:8080",     # HYBRIDS3_URL
    aws_access_key_id="uploads-id",           # bucket public_key
    aws_secret_access_key="uploads-secret",   # bucket key (private)
    region_name="us-east-1",                  # arbitrary but required
    config=Config(signature_version="s3v4"),
)

s3.put_object(Bucket="uploads", Key="file.txt", Body=b"hello")
s3.get_object(Bucket="uploads", Key="file.txt")["Body"].read()
s3.head_object(Bucket="uploads", Key="file.txt")
s3.list_objects_v2(Bucket="uploads", Prefix="images/")
s3.delete_object(Bucket="uploads", Key="file.txt")
s3.list_buckets()                             # bucket key → only "uploads"

# presigned URLs (see MCP / HTTP presign for the same semantics)
get_url = s3.generate_presigned_url(
    "get_object", Params={"Bucket": "permanent", "Key": "doc.pdf"}, ExpiresIn=3600,
)
put_url = s3.generate_presigned_url(
    "put_object", Params={"Bucket": "uploads", "Key": "inbox/report.pdf"}, ExpiresIn=600,
)

For cross-bucket access or list_buckets() returning all buckets, build a second client with the master credentials (aws_access_key_id=master_public_key, aws_secret_access_key=master_key). Don't embed the master key in client-facing code — per-bucket keys scope access to one bucket.

Destructive & irreversible. delete_object deletes the object with no undo — no versioning, no recycle bin. An agent must NEVER call it unless the user explicitly asked for that exact key to be deleted; confirm the specific bucket + key first, scope it to the current task, and never enumerate-then-bulk-delete. On a shared instance where multiple callers use the same bucket, this can destroy another caller's data — treat bulk deletes as admin-only and requiring explicit confirmation.

aws-cli

aws --endpoint-url "$HYBRIDS3_URL" \
    --region us-east-1 \
    s3api put-object --bucket uploads --key file.txt --body ./file.txt
# credentials via env: AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY=

Supported S3 operations: put_object, get_object, head_object, delete_object, list_objects_v2 (honours Prefix), list_buckets, generate_presigned_url (GET + PUT). Not supported: multipart upload, versioning, ACLs, bucket create/delete (boto3's implicit create_bucket maps to a no-op).

Plain HTTP API

Bearer auth: pass the bucket's private key (or the master_key) as Authorization: Bearer . Public-bucket reads (GET/HEAD/LIST) need no auth; all writes and private-bucket reads require a key.

Requests carrying an AWS Sig V4 Authorization header get S3-style XML back; everything else gets JSON. Every response includes X-Request-Id (log correlation) and X-Content-Type-Options: nosniff. Errors carry "error" + "request_id" fields.

Objects

MethodPathAuthDescription
PUT/{bucket}/{key}writeUpload object. Returns ETag (MD5 of content). Content type auto-detected; override with a Content-Type header.
GET/{bucket}/{key}readDownload object. Returns ETag, Last-Modified, Content-Length.
HEAD/{bucket}/{key}readObject metadata, no body.
DELETE/{bucket}/{key}writeDelete object — always 204, even if absent.
GET/{bucket}readList objects. Query: prefix, max-keys.
POST/presign/{bucket}/{key}writeGenerate a presigned URL. Query: method (GET default / PUT), expires (seconds, 1–604800, default 3600).

Destructive & irreversible. DELETE removes the object with no undo. An agent must NEVER call it unless the user explicitly asked for that exact key to be deleted; confirm the specific bucket + key first, scope it to the current task, and never enumerate-then-bulk-delete. On a shared bucket used by other callers, this can destroy their data — treat it as admin-only.

# upload
curl -X PUT "$HYBRIDS3_URL/uploads/file.txt" \
  -H "Authorization: Bearer $HYBRIDS3_KEY" \
  --data-binary @file.txt

# upload a nested key (parent dirs created automatically)
curl -X PUT "$HYBRIDS3_URL/uploads/reports/2024/january.pdf" \
  -H "Authorization: Bearer $HYBRIDS3_KEY" \
  --data-binary @january.pdf

# download from a public bucket — no auth needed
curl "$HYBRIDS3_URL/uploads/file.txt"

# download from a private bucket
curl "$HYBRIDS3_URL/permanent/doc.pdf" \
  -H "Authorization: Bearer $HYBRIDS3_KEY"

# list objects with a prefix
curl "$HYBRIDS3_URL/uploads?prefix=images/&max-keys=50" \
  -H "Authorization: Bearer $HYBRIDS3_KEY"

# delete
curl -X DELETE "$HYBRIDS3_URL/uploads/file.txt" \
  -H "Authorization: Bearer $HYBRIDS3_KEY"

Buckets

MethodPathAuthDescription
GET/healthnone{"status":"ok"} liveness check.
GET/master or bucket keyList buckets — master key lists all, bucket key lists only its own.
HEAD/{bucket}read200 if bucket exists in config, else 404.
PUT/{bucket}writeS3-compat no-op: 200 if bucket exists in config, 404 if not. Creates nothing.
# list all buckets — needs the master key
curl "$HYBRIDS3_URL/" -H "Authorization: Bearer $HYBRIDS3_MASTER_KEY"

# a bucket key lists only its own bucket
curl "$HYBRIDS3_URL/" -H "Authorization: Bearer $HYBRIDS3_KEY"

Presigned URLs (HTTP)

POST /presign/{bucket}/{key} requires the bucket key or master key. The result grants exactly one verb on exactly one key. A GET URL can't be used to PUT (the method is baked into the signature).

# presigned GET on a PRIVATE bucket → signed, expiring URL
curl -X POST "$HYBRIDS3_URL/presign/permanent/doc.pdf?expires=3600" \
  -H "Authorization: Bearer $HYBRIDS3_KEY"
# → {"url":"http://.../permanent/doc.pdf?X-Amz-Algorithm=...&X-Amz-Signature=...","method":"GET","expires":3600}

# presigned GET on a PUBLIC bucket → plain URL, no signature, no expiry (reads are open anyway)
curl -X POST "$HYBRIDS3_URL/presign/uploads/photo.jpg" \
  -H "Authorization: Bearer $HYBRIDS3_KEY"
# → {"url":"http://.../uploads/photo.jpg","method":"GET","expires":null}

# presigned PUT → ALWAYS signed, even for public buckets (anonymous writes are never allowed)
curl -X POST "$HYBRIDS3_URL/presign/uploads/inbox/report.pdf?method=PUT&expires=600" \
  -H "Authorization: Bearer $HYBRIDS3_KEY"

# recipient uploads using only the URL — no Authorization header
curl -X PUT "" --data-binary @report.pdf

The bucket's max_file_size is enforced server-side during the upload regardless of how it was authenticated (oversized → 413). Expired or tampered presigned URLs → 403.

MCP Endpoint

An MCP server runs at POST /mcp/ over the Streamable HTTP transport. Client config:

{
  "mcpServers": {
    "hybrids3": { "type": "streamable-http", "url": "http://localhost:8080/mcp/" }
  }
}

Wire it into Claude Code:

claude mcp add --transport http hybrids3 "$HYBRIDS3_URL/mcp/"
# with endpoint-level auth:
claude mcp add --transport http hybrids3 "$HYBRIDS3_URL/mcp/" \
  --header "Authorization: Bearer $HYBRIDS3_MASTER_KEY"

Auth (two layers)

Endpoint-level (optional) — a token that authenticates the connection before any tool runs. Master key = full access; a bucket key = limited to that bucket. Send it as Authorization: Bearer , or (for clients that can't set headers) as ?auth= on the URL. A token that matches nothing → 401; no token → passes through, and per-tool auth applies.

Per-tool — every tool that touches a bucket takes an auth_key argument (the bucket's private key or the master key), checked independently of the connection token. Public-bucket reads (download_object, list_objects, object_info) accept an empty auth_key; all writes and all private-bucket ops require it.

Tools

ToolArgsAuthNotes
upload_objectbucket, key, content, auth_key, content_type="", encoding="utf-8"bucket/master keyencoding="base64" for binary. Returns size, etag, content_type.
download_objectbucket, key, auth_key="", encoding="utf-8"key on private onlybase64 for binary; UTF-8 that won't decode auto-falls back to base64. Objects > 50 MB rejected — use HTTP.
delete_objectbucket, key, auth_keybucket/master keyIdempotent.
list_objectsbucket, auth_key="", prefix="", max_keys=100key on private onlymax_keys clamped to 1–1000.
list_bucketsauth_keymaster or bucket keyMaster lists all; bucket key lists only its own.
object_infobucket, key, auth_key=""key on private onlyMetadata only (size, content_type, etag, uploaded_at, expires_at).
presign_urlbucket, key, auth_key, method="GET", expires=3600, base_url="", host=""bucket/master keymethod GET/PUT. Same public-GET-plain / everything-else-signed logic as the HTTP endpoint. expires clamped 1–604800. Set base_url to the externally-reachable URL so the link is usable.

delete_object is destructive & irreversible. It deletes the object with no undo. An agent must NEVER call it unless the user explicitly asked for that exact key to be deleted; confirm the specific bucket + key first, never enumerate-then-bulk-delete. On a shared bucket used by other callers, this can destroy their data — treat it as admin-only.

All tools return structuredContent with a plain-text fallback. Internal error details are masked.

Raw JSON-RPC

For debugging or non-MCP callers, POST JSON-RPC directly. The transport requires the Accept header below.

# tools/list
curl -s "$HYBRIDS3_URL/mcp/" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

# tools/call — upload
curl -s "$HYBRIDS3_URL/mcp/" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc":"2.0","id":2,"method":"tools/call",
    "params":{
      "name":"upload_object",
      "arguments":{"bucket":"uploads","key":"note.txt","content":"hello","auth_key":"'"$HYBRIDS3_KEY"'"}
    }
  }'

Authentication (all modes)

CredentialConfig fieldRoleKeep secret?
Bucket private keykeyBearer token (HTTP/MCP) and aws_secret_access_key (S3). Signs/verifies — never transmitted.Yes
Bucket public keypublic_keyaws_access_key_id (S3) + Credential= in presigned URLs. Identifies, grants nothing. Defaults to bucket name.No
Master keymaster_keyCross-bucket god key. Works on every bucket + only credential that lists all buckets.Yes
Master public keymaster_public_keyaws_access_key_id paired with the master key (S3). Defaults to "master".No

Bucket visibility:

GET / HEAD / LISTPUTDELETE / presign
public: trueno authbucket key, master key, or valid presigned PUTbucket key or master key
public: falsebucket key, master key, or valid presigned GETbucket key, master key, or valid presigned PUTbucket key or master key

Unauthorized or non-existent bucket access always returns 404 — callers can't tell "doesn't exist" from "no access". All key comparisons are constant-time.

Typical Workflows

Upload + fetch over plain HTTP

export HYBRIDS3_URL=http://localhost:8080
export HYBRIDS3_KEY=

curl -X PUT "$HYBRIDS3_URL/uploads/report.pdf" \
  -H "Authorization: Bearer $HYBRIDS3_KEY" --data-binary @report.pdf
curl -sO "$HYBRIDS3_URL/uploads/report.pdf"     # public bucket → no auth on read

Or via the helper (see scripts/hybrids3.sh):

HYBRIDS3_URL=http://localhost:8080 HYBRIDS3_KEY= \
  scripts/hybrids3.sh put uploads report.pdf ./report.pdf
scripts/hybrids3.sh list uploads reports/
scripts/hybrids3.sh get uploads report.pdf ./out.pdf
scripts/hybrids3.sh delete uploads report.pdf
scripts/hybrids3.sh buckets                     # needs HYBRIDS3_KEY=

Hand someone a presigned upload URL

# you generate it (needs a key); they upload with no credentials
curl -X POST "$HYBRIDS3_URL/presign/uploads/inbox/theirs.zip?method=PUT&expires=600" \
  -H "Authorization: Bearer $HYBRIDS3_KEY" | jq -r .url
# → hand the URL over; recipient: curl -X PUT "" --data-binary @theirs.zip

Drop-in boto3 against your own endpoint

Point any existing boto3 code at HYBRIDS3_URL, set the bucket's public_key/key as the credential pair, region_name="us-east-1", signature_version="s3v4". See S3 API.

Agent-driven storage over MCP

Add the server (claude mcp add --transport http hybrids3 "$HYBRIDS3_URL/mcp/"), then call list_buckets to discover buckets, upload_object / download_object / list_objects to move data. Pass the bucket key as auth_key; use the master key only when you need cross-bucket reach.

Auto-expiring scratch storage

If a bucket has a ttl set (server config), objects delete themselves that long after their last write — overwriting resets the clock. Nothing to do client-side; just write to the bucket.

相关技能

把自然语言描述转为结构化 JSON,并由 mcp-diagram-generator MCP 服务生成 Draw.io、Mermaid 或 Excalidraw 图表文件。

作者 nssa.io1.0k 次安装47 星标

通过托管 OAuth 代理访问 YouTube Data API v3,搜索与管理视频、播放列表、频道、订阅和评论。

作者 byungkyu880 次安装145 星标

在本地磁盘以分类纯 Markdown 文件保存需要长期留存的事实,与智能体内置记忆并存。

作者 Iván555 次安装18 星标

以 AI 机器人身份加入视频会议,提供语音、虚拟形象与屏幕共享四种模式。

作者 johnpatternai21 次安装8 星标

通过一个命令行工具完成多链加密货币交易、钱包管理与 AI 市场分析。

作者 lowesyang162 次安装109 星标

通过托管 OAuth 访问 Microsoft Graph Excel 接口,读写 OneDrive 中的工作簿、工作表、区域、表格与图表。

作者 byungkyu800 次安装42 星标

psyb0t 的更多技能

浏览全部技能

对接用户自部署的 mt5-httpapi MetaTrader 5 网关,每次涉及真实资金的写操作都必须逐笔确认后再执行。

作者 psyb0t107 次安装4 星标

面向反爬检测栈 QA 与授权测试场景的 Docker 浏览器自动化工具。

作者 psyb0t137 次安装2 星标

自托管、OpenAI 兼容的语音服务,一个容器搞定转写、翻译与合成。

作者 psyb0t13 次安装

在固定白名单的 SSH 沙箱里跑 ffmpeg、sox、ImageMagick 处理音视频和图片。

作者 psyb0t71 次安装

通过 SSH 调用 Qwen3-TTS 生成语音,支持预设音色、声音克隆与声音设计。

作者 psyb0t55 次安装

一个端点统一管控多个 IMAP/SMTP 邮箱,跨账号并行完成读取、检索、发送、标记与删除。

作者 psyb0t15 次安装