tubekit

io.github.santiriera626由 GitHub 账号 santiriera626 发布v0.3.0更新于 Oct 24, 2026

Compliance-aware MCP server for YouTube publishing, analytics and creator insights.

概览

AI 生成的概览

带合规校验的 MCP 服务器,让助手代你在自己的 YouTube 频道上传、管理视频并查看分析数据,并记录配额与审计日志。

可以做什么
  • 用本地合规规则库校验视频元数据,在发布前拦截问题
  • 上传视频、设置缩略图,修改标题、描述、标签或隐私状态
  • 读取视频状态、列出上传视频与播放列表,并创建、更新、排序或移除播放列表条目
  • 获取频道、多频道组合与单视频的分析报告,含收入估算与 YPP 进度
  • 汇总、列出并读取评论串,并在本地记录评论已读状态
  • 检查 OAuth 授权是否有效,并为大文件申请一次性上传地址
适用场景
适合让助手实际运营一个 YouTube 频道:发布视频、整理播放列表、处理评论或汇报数据,同时希望有合规拦截、配额核算和审计记录,而不是直接暴露原始 API。
运行要求
以 stdio 在本地运行(PyPI 包,用 uvx 或 uv tool install 启动)。需要启用 YouTube Data API v3(报告还需 Analytics API)的 Google Cloud 项目、Desktop 类型 OAuth 客户端 JSON(TUBEKIT_OAUTH_CLIENT_SECRETS_PATH)、Fernet 主密钥(TUBEKIT_MASTER_KEY_PATH)、SQLite 状态文件(TUBEKIT_STATE_DB_PATH),以及每个频道一次交互式 OAuth 授权。
安装前请注意
助手会真实改动线上频道:上传、元数据修改、播放列表写入和缩略图更换都会生效,创建播放列表和添加条目不具备幂等性。上传会消耗大量 API 配额。OAuth 刷新令牌以主密钥加密存储,状态数据库与密钥同时丢失需重新授权所有频道。使用 HTTP 传输且未设置 ingest 目录时,令牌几乎等同于可读取服务器文件系统。

安装

在 SourceWeft 中

  1. 打开 控制台中的 tubekit,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。

其他 MCP 客户端

参照 仓库 中的启动说明。

README

tubekit-mcp

Compliance-aware Model Context Protocol server for YouTube publishing, analytics, and creator insights — every action gated, metered, and audited before it touches a channel.

[CI] [License: FSL-1.1-MIT] [Python 3.11+] [Type-checked: mypy strict] [Lint: ruff]

tubekit-mcp is an MCP server: you connect it to an MCP client (Claude Desktop, Claude Code, …) and the assistant can then publish and manage videos on a YouTube channel on your behalf, with compliance checks, quota accounting, idempotent uploads and a tamper-evident audit log on every state-changing call. Licensed under FSL-1.1-MIT — run and self-host it freely, commercially or not; each release becomes plain MIT two years after publication.

Architecture

A single tool call (e.g. upload_video) flows through a compliance gate, a quota / idempotency ledger, an OAuth refresh, the YouTube API, and a tamper-evident audit row — with the pure core kept free of protocol concerns, a boundary enforced in CI by an AST fitness test (tests/unit/services/test_no_fastmcp_imports.py).

mermaid
flowchart LR    client["MCP client<br/>(Claude Desktop / Code)"]    subgraph edge["Protocol edge"]      transport["Transport<br/>stdio · HTTP + Bearer"]      tool["Tool wrapper"]    end    subgraph core["Pure core — no protocol imports (CI-enforced)"]      compliance{"Compliance<br/>gate"}      ledger["Quota +<br/>idempotency<br/>ledger"]      oauth["OAuth refresh<br/>(Fernet at rest)"]    end    upstream["YouTube<br/>Data / Analytics API"]    audit[("Tamper-evident<br/>hash-chained<br/>audit log")]
    client --> transport --> tool --> compliance    compliance -->|pass| ledger --> oauth --> upstream    compliance -->|fail| suggestion["Suggestion →<br/>agent retries"]    tool -. audited .-> audit    ledger -. audited .-> audit    oauth -. audited .-> audit

Why this exists. Agents are starting to operate real YouTube channels — and a channel is an asset you can lose. One bad call can publish a video that violates policy, burn the day's API quota (an upload costs 1600 of the default 10,000 daily units), or double-publish on a retry. Generic YouTube wrappers hand the agent the raw API; tubekit wraps every call in the guardrails an unattended operator needs: a compliance gate before anything goes live, quota accounted before it is spent, idempotent retries, OAuth tokens encrypted at rest (fingerprint-only logging), and a tamper-evident audit chain of everything the agent did. Full design rationale in ADR 0001.

Usage

Prerequisites

Before an assistant can act on a channel you need, once per channel:

  1. A Google Cloud project with the YouTube Data API v3 (and YouTube Analytics API if you use get_analytics) enabled.
  2. An OAuth client of type Desktop app, downloaded as client_secret.json.
  3. The channel whose Google account will grant the consent.

The OAuth grant is interactive and only happens here — tubekit stores the resulting refresh token Fernet-encrypted and never prints it. Never used Google Cloud Console? docs/runbooks/gcp-setup.md walks the whole thing from zero (project, APIs, consent screen, client type, and the two Google policies — token expiry in testing, private-locked uploads for unaudited projects — that surprise people later). The consent flows themselves are in docs/runbooks/oauth-bootstrap.md.

Install

From PyPI:

bash
uv tool install tubekit-mcp   # installs the tubekit / tubekit-mcp-* commands

Use uv tool install, not uvx, for a real setup: the one-time steps below need the tubekit CLI to still be there afterwards. uvx tubekit-mcp runs the stdio server from a throwaway environment, which is what an MCP client's config points at once the setup is done.

The server will not start yet, and that is deliberate — it refuses to run without a master key rather than inventing one, since that key is what encrypts your OAuth tokens at rest. One-time setup below is the two commands that fix it.

Or from source, for development:

bash
git clone https://github.com/santiriera626/tubekit-mcp.git tubekit-mcp && cd tubekit-mcpuv sync --all-extras        # installs the tubekit / tubekit-mcp-* entry pointsmake db-upgrade             # builds the state schema (wraps `tubekit db upgrade`;                            #   `tubekit db current` prints the applied revision)

(uv itself installs with curl -LsSf https://astral.sh/uv/install.sh | sh.)

Try it in 60 seconds — no Google account needed

The compliance engine is pure-local, so you can watch the gate and its self-correction Suggestions work before touching Google Cloud:

bash
cat > video.json <<'EOF'{  "title": "Test Upload — Compliance Gate Demo",  "description": "Demo description for the compliance gate.",  "tags": ["demo", "test"],  "ai_disclosure": false,  "made_for_kids": null,  "category_id": "10"}EOFuv run tubekit compliance test video.json
text
Compliance: PASSED  (8 rules evaluated)  WARNING AI_DISCLOSURE_MISSING: AI disclosure flag is false; confirm this is the      channel owner's intended policy for AI-generated content.      suggestion: action=set field=metadata.ai_disclosure value=True  WARNING KIDS_FLAG_NOT_SET: made_for_kids is unset; set it explicitly to true or      false (this rule does not classify by content).      suggestion: action=set field=metadata.made_for_kids value=False

An error-severity violation — say a 126-character title — fails the gate with exit 1 and a machine-applicable fix (suggestion: action=truncate field=metadata.title value=100). That is the same Suggestion an agent receives from a rejected upload_video and applies before retrying (ADR D8). tubekit compliance list prints the rule catalog; tubekit compliance manifest exports it for external auditors.

Install with an AI agent

Rather not type the commands above yourself? Paste the block below into Claude Code (or any coding agent with shell access) and it will clone, install and register the server for you. It stops at the boundary above: no Google account, client_secret.json or OAuth consent is involved.

text
Install tubekit-mcp and register it as an MCP server. Stop and report if any step fails.
1. Clone the repo and enter it (install uv first if missing:   curl -LsSf https://astral.sh/uv/install.sh | sh):   git clone https://github.com/santiriera626/tubekit-mcp.git tubekit-mcp && cd tubekit-mcp
2. Install dependencies, apply the database migrations and create the Fernet   master key (the server refuses to start without one):   uv sync --all-extras   make db-upgrade   uv run tubekit auth init-master-key   (Idempotent: an existing key is reported and left untouched.)
3. Run the zero-credential compliance smoke check to confirm the install works:   cat > video.json <<'EOF'   {     "title": "Test Upload — Compliance Gate Demo",     "description": "Demo description for the compliance gate.",     "tags": ["demo", "test"],     "ai_disclosure": false,     "made_for_kids": null,     "category_id": "10"   }   EOF   uv run tubekit compliance test video.json   Expect "Compliance: PASSED (8 rules evaluated)" and exit code 0.
4. Register the server with Claude Code over stdio, using absolute paths:   claude mcp add tubekit \     -e TUBEKIT_STATE_DB_PATH="$(pwd)/state.db" \     -e TUBEKIT_MASTER_KEY_PATH="$HOME/.config/tubekit/master.key" \     -- "$(pwd)/.venv/bin/tubekit-mcp-stdio"
Do not run `tubekit auth setup-channel` or open any Google consent screen —OAuth channel bootstrap is a separate, human-in-the-loop step documented indocs/runbooks/oauth-bootstrap.md. Stop after step 4 and tell me to run thatmyself.

Restart your MCP client after registration; it can now call tubekit.health() and list the full tool catalog. Every tool that takes a channel argument — validate_compliance included — needs a configured channel, which means completing One-time setup — including the OAuth consent in docs/runbooks/oauth-bootstrap.md — yourself. The compliance gate itself is testable without any channel via step 3's tubekit compliance test.

One-time setup

bash
# 1. Create the Fernet master key used to encrypt stored tokens (mode 0600).#    Skip if the agent install above already created it.tubekit auth init-master-key
# 2. Bootstrap a channel — opens a browser for the OAuth consent.#    The alias is positional; --channel-id, --gcp-project, --client-secrets#    and --scopes are all required (see docs/runbooks/oauth-bootstrap.md).tubekit auth setup-channel mychannel \  --channel-id UCxxxxxxxxxxxxxxxxxxxxxx \  --gcp-project my-gcp-project \  --client-secrets ./client_secret.json \  --scopes youtube.upload,youtube.readonly
#    …or, on a headless box (no browser), append --device-code:tubekit auth setup-channel mychannel \  --channel-id UCxxxxxxxxxxxxxxxxxxxxxx \  --gcp-project my-gcp-project \  --client-secrets ./client_secret.json \  --scopes youtube.upload,youtube.readonly \  --device-code
# 3. Define the channel registry — setup-channel persists only the encrypted#    token; the registry is a TOML you write yourself. The table name is the#    alias. Full field reference: docs/runbooks/vps-deploy.md §5.mkdir -p ~/.config/tubekit/channelscat > ~/.config/tubekit/channels/mychannel.toml <<'EOF'[mychannel]channel_id     = "UCxxxxxxxxxxxxxxxxxxxxxx"gcp_project_id = "my-gcp-project"oauth_scopes   = [  "https://www.googleapis.com/auth/youtube.upload",  "https://www.googleapis.com/auth/youtube.readonly",]EOF
# 4. Verify — `show` prints one channel's status (token fingerprint only),#    `list` prints every configured aliastubekit channels show mychannel --channels-dir ~/.config/tubekit/channelstubekit channels list --channels-dir ~/.config/tubekit/channels

Connect to an MCP client (stdio)

Most clients launch the server over stdio. Add this to the client's MCP config (for Claude Desktop: claude_desktop_config.json):

json
{  "mcpServers": {    "tubekit": {      "command": "tubekit-mcp-stdio",      "env": {        "TUBEKIT_STATE_DB_PATH": "/absolute/path/to/state.db",        "TUBEKIT_MASTER_KEY_PATH": "/absolute/path/to/master.key"      }    }  }}

Restart the client. The assistant now sees the tools below plus a tubekit.health() probe. Ask it, e.g., "upload ./intro.mp4 to mychannel" and it will call upload_video, which gates on compliance, charges quota, refreshes OAuth and writes an audit row — all transparently.

Available tools

ToolWhat it doesOAuth scopeQuota
validate_compliance(channel, metadata, thumbnail_present=False)Run the rule registry against metadata; returns a ComplianceReport. Pure-local, no YouTube call.—0
upload_video(channel, video_path, metadata, idempotency_key, privacy_status="private", notify_subscribers=False)Upload a video after an internal compliance gate. Idempotent via idempotency_key.youtube.upload1600
set_thumbnail(channel, video_id, thumbnail_path)Set a thumbnail on an existing video.youtube50
update_metadata(channel, video_id, patch)Partially update title/description/tags/privacy. Compliance-gated on the post-patch metadata.youtube50
get_video_status(channel, video_id)Read processing/privacy status of a video.youtube.readonly1
get_analytics(channel, metrics, start_date, end_date, dimensions=None)Channel-level metrics over a window. Uses the separate Analytics quota bucket.yt-analytics.readonly1 (Analytics)
get_portfolio_report(channels=None, period="28d", start_date=None, end_date=None)One row per channel: period totals + vs-prior deltas (views, revenue), YPP progress for non-monetized channels. Per-channel failures are isolated.yt-analytics.readonly + youtube.readonly (+yt-analytics-monetary.readonly for revenue)3/channel (Analytics)
get_channel_report(channel, period="28d", start_date=None, end_date=None, granularity="auto")Single-channel health report: totals, trend series, top videos, traffic sources, Shorts/long-form split, revenue or YPP progress, lifetime snapshot.yt-analytics.readonly + youtube.readonly (+monetary for revenue)7 (Analytics)
get_video_report(channel, video_id, period="lifetime", start_date=None, end_date=None, granularity="auto")Per-video deep dive: retention proxy, traffic sources, revenue when monetized; window starts at publication by default.yt-analytics.readonly + youtube.readonly (+monetary for revenue)5 (Analytics)
list_my_videos(channel, page_size=50, page_token=None)Paginated list of channel uploads.youtube.readonly1
get_comments_digest(channels=None, force_sync=False)Portfolio-wide comment counts (unread/unanswered/held/spam, per video).youtube.force-ssl4/channel
list_comments(channel, video_id=None, only="unread", search=None, order="time", page_size=20, page=1)Compact comment listing from the local mirror.youtube.force-ssl1
get_comment_thread(channel, comment_id)One thread in full: untruncated text + all replies.youtube.force-ssl2
mark_comments_reviewed(channel, ids=None, video_id=None, all_unread=False, state="read")Local triage state; never mutates YouTube.—0
check_oauth(channel)Zero-quota OAuth liveness pre-flight: refresh the stored grant against Google's token endpoint and report oauth_ok + expiry. Run before a quota-spending tool.—0
request_ingest_upload(channel, filename, size_bytes, sha256)Issue a one-time brokered upload URL so a remote client can PUT a multi-GB video the server then ingests — no ssh. See media ingest.—0
list_playlists(channel, page_size=50, page_token=None)The channel's own playlists: id, title, privacy, item count.youtube.readonly1
list_playlist_items(channel, playlist_id, page_size=50, page_token=None)One playlist's videos in order. Returns each playlist_item_id — the handle remove/reorder need.youtube.readonly1
create_playlist(channel, title, description="", privacy_status="private")Create a playlist. Defaults to private; going public is an explicit act. Not idempotent.youtube50
update_playlist(channel, playlist_id, title=None, description=None, privacy_status=None)Patch title/description/privacy. Omitted fields are read and merged, never blanked.youtube50
add_to_playlist(channel, playlist_id, video_id, position=None)Add a video (append, or insert at position). Not idempotent — YouTube allows duplicates.youtube50
reorder_playlist_item(channel, playlist_id, playlist_item_id, video_id, position)Move an entry to position (0 = first).youtube50
remove_from_playlist(channel, playlist_item_id)Remove one entry. The video itself is untouched.youtube50

Playlist writes take a playlist_item_id, never a bare video id: the same video may appear in a list more than once, so YouTube cannot disambiguate from the video alone. Get the ids from one list_playlist_items call (1 unit) and reuse them — the services deliberately do not resolve them for you, because that would be a quota charge the caller never asked for.

Playlists are not run through the compliance registry: it scores video metadata (thumbnail, category, tags, synthetic-media declaration), none of which a playlist has, and its TITLE_TOO_LONG would apply the video ceiling (100) to a resource whose real ceiling is 150. What is enforced instead is what Google documents for the playlist resource: a non-empty title, a valid privacyStatus, ≤150 characters of title, ≤5000 of description, and no <, > or U+2028 in either. Those limits live in the YouTube Help page, not in the Data API reference — which documents none, and is why they were missed at first.

Comments tools need the channel grant to carry youtube.force-ssl (moderation-status filtering is owner-only). Verify with check_oauth; if missing, re-consent once: tubekit auth setup-channel --scopes …,https://www.googleapis.com/auth/youtube.force-ssl.

Revenue figures across the report tools are estimated ad + YouTube Premium revenue only (memberships, Super Chat and Shopping are not exposed by the channel-level APIs), lag ~2 days (period.revenue_complete_until), and are finalized around the 10th of the following month. Thumbnail impressions/CTR are not available in the targeted Analytics API. get_analytics remains the raw escape hatch for any ad-hoc query.

Every tool returns a ToolResult envelope (ok + data, or a structured ToolError whose code is one of the documented error codes). On a compliance failure the error carries a Suggestion the assistant can apply and retry — the self-correction loop described in ADR D8.

HTTP transport (multi-user)

For remote / multi-tenant use, run the HTTP transport instead. It requires a per-client Bearer API token scoped to specific channels and tools, with an optional per-token rate limit:

bash
# Issue a token (the plain value is printed exactly once — store it now)tubekit auth issue --name claude-prod --channels mychannel --tools "*" \  --rate-limit-per-min 30
# Serve over HTTPtubekit-mcp-http --host 0.0.0.0 --port 8080

Clients send Authorization: Bearer <token>. Requests that are unauthenticated, out-of-scope, or rate-limited get JSON-RPC errors (-32001..-32006). GET /healthz returns the liveness payload; the per-channel detail (aliases, OAuth expiry) is added only for a valid Bearer and narrowed to that token's channels. Manage tokens with tubekit auth list | show | revoke | rotate.

To run this centrally on a VPS (one server, many projects connecting over HTTPS), follow docs/runbooks/vps-deploy.md — a self-contained, step-by-step deployment guide (systemd + Traefik + per-project tokens) written for an infra team.

Media ingest (remote upload_video)

upload_video(video_path) reads the file from the server's filesystem — a client-local path can never resolve on a remote deployment. There are two ways to get the media onto the server.

Brokered upload (recommended, no ssh). The agent orchestrates the whole transfer over HTTP via the MCP. Call request_ingest_upload, then PUT the bytes to the one-time URL it returns (same Bearer token), then upload_video with the returned server-side path:

bash
# 1. request_ingest_upload(channel, filename="video.mp4", size_bytes, sha256)#    → { upload_url, curl, video_path: "/ingest/video.mp4" }# 2. transfer the bytes (the returned curl recipe):curl -fSs -T video.mp4 -H "Authorization: Bearer $TUBEKIT_TOKEN" "<upload_url>"# 3. upload_video(channel="...", video_path="/ingest/video.mp4", ...)

The server streams the body to a staging .part, verifies size_bytes + sha256, and atomically publishes before upload_video reads it. The URL is a single-use, channel-bound capability with a TTL; an interrupted transfer resumes via HEAD + Content-Range. Design rationale: ADR 0002. Requires TUBEKIT_INGEST_UPLOAD_URL_BASE to be set (otherwise the tool returns precondition_failed).

rsync convention (fallback, requires ssh). Transfer out-of-band, then call the tool with the server-side path:

bash
rsync -av --chmod=F644 video.mp4 <server>:/opt/tubekit-ingest/# upload_video(channel="...", video_path="/ingest/video.mp4", ...)

Set TUBEKIT_INGEST_DIR to the in-server ingest path (e.g. /ingest): when a video_path is unreadable the tool returns validation_error with a suggestion pointing the calling agent at this convention. See the media-ingest section of the VPS runbook for the volume mount and retention policy.

Environment variables

All settings use the TUBEKIT_ prefix (see .env.example):

VariableDefaultPurpose
TUBEKIT_STATE_DB_PATHstate.dbSQLite file holding audit + state tables
TUBEKIT_MASTER_KEY_PATH~/.config/tubekit/master.keyFernet key that encrypts stored OAuth tokens
TUBEKIT_OAUTH_CLIENT_SECRETS_PATHunsetPath to client_secret.json (Google Cloud confidential client). Required at runtime — google-auth cannot refresh access tokens without it, so every channel tool fails if unset
TUBEKIT_TOKEN_BACKENDsqlite_fernetToken store backend (sqlite_fernet | in_memory)
TUBEKIT_AUDIT_RETENTION_DAYS365Audit retention window
TUBEKIT_OTLP_ENDPOINTunsetOTLP collector endpoint; unset → no-op telemetry
TUBEKIT_INGEST_DIRunsetServer-side media ingest dir. Advertised in upload_video path errors, and — for HTTP callers only — the boundary their video_path/thumbnail_path must resolve inside. Unset means no such boundary: an HTTP token is then equivalent to read access to the server's filesystem
TUBEKIT_INGEST_UPLOAD_URL_BASEunsetPublic origin for brokered uploads; unset disables request_ingest_upload
TUBEKIT_INGEST_UPLOAD_TTL_SECONDS3600One-time brokered-upload token lifetime
TUBEKIT_INGEST_MAX_BYTES21474836480Max size of a single brokered upload (20 GiB)
TUBEKIT_INGEST_MAX_PENDING32Cap on concurrent pending upload tokens (disk-exhaustion guard)
TUBEKIT_INGEST_PURGE_AFTER_UPLOADtrueDelete the source file from the ingest dir once the upload/thumbnail is confirmed
TUBEKIT_HTTP_KEEPALIVE_TIMEOUT5uvicorn keep-alive (s); raise for long SSE sessions, align with the proxy idle timeout
TUBEKIT_HTTP_LIMIT_CONCURRENCYunsetuvicorn max concurrent connections
TUBEKIT_HTTP_GRACEFUL_SHUTDOWN_TIMEOUTunsetuvicorn graceful-shutdown timeout (s)
TUBEKIT_HTTP_MAX_JSONRPC_BODY4194304Max bytes the auth gate buffers for one JSON-RPC POST before authenticating (pre-auth DoS guard); oversized → 413
TUBEKIT_HTTP_FORWARDED_ALLOW_IPSunsetReverse-proxy IPs/CIDRs whose X-Forwarded-* uvicorn may trust. Unset → uvicorn trusts only 127.0.0.1, so behind a proxy every audit row is stamped with the proxy's IP and the request scheme stays http. Use the proxy's own pinned address, not the bridge subnet — every container on a shared network resolves inside that CIDR and could forge the header. Never * (rejected at load): it would let any caller choose the audited IP
TUBEKIT_HTTP_SSE_RESUMABLEfalseEnable MCP streamable-HTTP resumability (in-memory event store) so a dropped SSE session resumes via Last-Event-ID
TUBEKIT_HTTP_SSE_RETRY_INTERVAL_MS2000SSE reconnect hint (ms) advertised to clients; only used when resumable
TUBEKIT_SQLITE_BUSY_TIMEOUT_MS5000SQLite writer lock wait before SQLITE_BUSY
TUBEKIT_LOG_LEVEL / TUBEKIT_LOG_FORMATINFO / jsonLogging

A lost state.db / master.key pair means re-bootstrapping every channel. Back them up together — see docs/runbooks/state-db-backup.md.

Hosted version

Gatecast is the hosted tier of tubekit — same engine, run and kept alive for you. It is pre-launch; the waiting list is the whole thing so far. Self-hosting with this repo is and stays fully supported.

Development

bash
uv sync --all-extrasmake lint    # ruffmake type    # mypy --strictmake test    # pytest unit suitemake cov     # coverage report

make demo-stack-up brings up the Jaeger/Prometheus/Grafana observability stack with five provisioned dashboards (docker-compose.demo.yml, docs/grafana/).

Repository layout

docs/adr/        Architecture Decision Records (source of truth for design)docs/grafana/    Provisioned Grafana dashboards + demo observability configdocs/runbooks/   Operational procedures (master key rotation, audit verify, …)docs/ROADMAP.md  Shipped, planned and under-exploration worksrc/tubekit/     Library code (Alembic migrations ship in src/tubekit/migrations/)tests/           Unit + integration suites

Contributing & security

License

FSL-1.1-MIT © 2026 sriera

The Functional Source License in plain words: read it, run it, modify it, self-host it for your own channels — commercially or not. The one thing it forbids is offering tubekit itself to others as a competing product or service. Each release additionally becomes plain MIT two years after its publication, automatically and irrevocably.

来源:README.md,提交 6d29e6a

工具

0
SourceWeft 尚未在沙箱中启动过该软件包,因此其工具未知。

版本历史

1
  1. v0.3.0最新Sep 16, 2026

评分

已满足适用检查项的 40%

该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。

  • 近 30 天内可连通25 分

    请保持端点能够响应 MCP 握手;SourceWeft 每 30 天探测一次。

  • 已声明认证方式10 分

    请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。

  • 已列出工具15 分

    请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。

  • 描述必需15 分
  • 图标10 分
  • 文档15 分
  • 许可证10 分

    请在仓库或注册中心条目中声明许可证。