content-hub
Creates and updates Bilibili column drafts through the creation API; actual publication requires final zone selection in the edit page.
Publishes and updates articles on CSDN via browser automation, and retrieves the account's article list.
Publishes articles to Juejin, updates already-published articles in place, and fetches the account's article list.
Publishes articles to Zhihu through browser UI injection and automatically captures the article ID; supports in-place updates.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
Harbor
English · 简体中文
Self-hosted publishing hub for people who write in Chinese and publish everywhere. Write once, ship to fifteen platforms, and keep every published copy in sync — with AI drafting, a compliance gate, and a human in the loop when a platform fights back.

What it does
Fifteen platforms, one publish action | Zhihu, Juejin, CSDN, Bilibili, Cnblogs, Toutiao, OSChina, SegmentFault, 51CTO, MetaWeblog blogs, WeChat Official Accounts, GitHub Pages, Dev.to, Telegraph, Xiaohongshu. Each adapter declares what it can actually do — publish, draft, update, tags, cover, Q&A — and the UI greys out the rest. |
Update in place | Edit once; every already-published copy is updated rather than duplicated. |
AI drafting with a compliance gate | Seven provider routes with failover, plus a four-stage gate before anything ships: safety scan → AIGC disclosure → dual-model review → human confirmation. |
Pauses instead of guessing | CAPTCHA, risk control, expired session: the task stops, tells you, and resumes where it left off. |
Session persistence | Log in once per platform. Cookies live in a local profile plus an atomic snapshot, so a wiped profile does not force a re-scan. |
MCP server, 32 tools | Drive the whole pipeline from Claude Code, Cursor or any MCP client. stdio by default; remote SSE requires a bearer token. |
Everything local | SQLite with FTS5 full-text search, local media store with content-addressed dedupe, no vendor account, no telemetry. |
Related MCP server: Hashnode MCP Server v2.0
Screens
Publish center | Task center |
|
|
Settings | Mobile |
|
|

Fifteen adapters, each declaring what it can actually do. Greyed-out actions are not supported by that platform, not missing features.
Quick start
Requires Python 3.10+, uv, Node 20+ and pnpm.
git clone https://github.com/badhope/harbor.git
cd harbor
# Terminal 1 — backend
cd backed
uv sync
uv run uvicorn app.factory:create_app --factory --host 127.0.0.1 --port 8000 --reload
# Terminal 2 — frontend
cd web
pnpm install
pnpm dev # http://127.0.0.1:5173Open http://127.0.0.1:5173. The Vite dev server proxies /api to port 8000.
Desktop shell (experimental)
cd web
pnpm install
pnpm run tauri devTauri launches the Python backend as a sidecar. Packaging is not verified across platforms — see Known limits.
Connect a platform
Two connection styles, decided per platform:
Browser login — for platforms without a usable API. Open Settings → Platform accounts, click Log in on the platform, and complete the scan or password step in the window that opens. The session is stored in a local profile and reused.
uv run --project backed python -m backed.cli --headed login --platform zhihuProtocol credentials — for platforms with a stable API. Fill in
platforms.<name> in config.json; no browser needed. See
PLATFORM_CONNECTION.md for the field list per platform.
uv run --project backed python -m backed.cli publish --id <article-id> --platforms zhihu,juejinConfiguration
Edit backed/config.json, or use environment variables:
Variable | Purpose | Default |
| REST authentication token | Auto-generated on loopback; required in production/Docker |
| Signing / JWT key | Required in production; no public default |
| Client networks exempt from the API token | Loopback only |
| Reverse proxies whose | Empty |
| Allowed cross-origin origins | Same-origin |
| Accepted | Loopback |
| Persistent root for DB, media, profiles, config | Repo-local |
| Reuse a system browser ( | Bundled Chromium |
| Public base URL for hosted media | Empty (media stored, not rewritten) |
| Demo mode: no browser, no external API calls | Off |
Deployment
Docker Compose runs the backend behind nginx, with the token injected server-side:
export SECRET_KEY=$(openssl rand -hex 32)
export HARBOR_API_TOKEN=$(openssl rand -hex 32)
docker compose -f deploy/docker-compose.yml --profile web up -d --buildThe backend is not exposed to the host; nginx terminates and injects the token. Data
lives in the hub_data volume.
Testing
bash scripts/check_all.sh # all gates; Linux/macOS
pwsh -File scripts/check_all.ps1 # all gates; Windows
cd backed && uv run pytest -q # backend only
pnpm --dir web test # frontend onlycheck_all runs eight gates: compileall, ruff, version consistency, secret scan,
pytest, eslint, vitest, vite build.
Architecture
Vue 3 SPA ──REST/SSE──► FastAPI ──► Publishing hub
(Tauri shell) (uvicorn) ├── 15 platform adapters
├── task engine + scheduler
├── SQLite (WAL + FTS5)
└── MCP bridge (stdio/SSE)Details in docs/architecture/ARCHITECTURE.md.
Known limits
Read this before trusting any claim above.
Browser fetch and screenshot are enabled but network-restricted. The target host is pinned to its validated public IP inside Chromium and every sub-resource is checked. Private, loopback and link-local targets are rejected.
Real publishing is not regression-tested against live platform DOM. Adapters pass a static contract probe; only Juejin has a captured DOM sample. Verify with a draft before relying on any platform.
Docker and Tauri builds are unverified on this machine. Docker daemon unavailable; Tauri fails with a local linker error. The compose file and sidecar script exist but have not produced a tested artifact here.
No auto-update, no signed release manifest, no cross-platform installer.
Documentation
Branch model, DoD, gates, five-remote sync | |
SemVer policy and release checklist | |
Shipped, next, backlog, out of scope | |
Per-platform credentials and CLI | |
Module boundaries and data flow | |
Dated evidence for manual checks | |
Historical defect audits and fixes | |
How to send a change | |
Reporting vulnerabilities |
License
MIT — see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Run your company blog for SEO and AI search from your AI assistant.
Publish to self-hosted WordPress from AI agents: markdown, images, SEO, and Notion sync.
Read, write, translate and sync WordPress and Webflow blog articles from Claude.
Draft, edit, organise, schedule and publish a Writavo Site's content from any AI assistant.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI assistants to manage WordPress sites through natural conversation, supporting post creation, content updates, site queries, and draft-to-publish workflows via the WordPress REST API.9MIT
- FlicenseNot gradedqualityCmaintenanceEnables AI assistants to publish, update, and manage Hashnode blog articles, with support for tags, cover images, and publication management.-
- AlicenseAqualityBmaintenanceEnables AI tools to research, write, and publish finished blog posts to Ghost and WordPress in the user's voice, supporting multiple author personas and destinations through natural language.142MIT
- AlicenseAqualityCmaintenanceEnables AI models to manage, curate, draft, publish, and administer self-hosted Ghost CMS blogs and newsletters.3422 npmMIT



