BASH-CMS

BASH-CMS

Enables governed LinkedIn company-page publishing from a VS Code extension's MCP server, with read-only tools for account info, post preview, and a draft tool for creating pending posts, plus an optional publish tool that is off by default and requires explicit confirmation.

Category
访问服务器

README

BASH-CMS

Governed publishing from your repo, inside VS Code: browse what's worth sharing, draft LinkedIn company-page posts, run the brand guard, approve with your name on it, and publish — with an idempotency ledger so nothing ever double-posts.

Built by BASH Consulting and used to run its own company page. The pipeline follows one rule end to end: drafts are files, approval is a human decision recorded in the file, and a script does the mechanical work. No post leaves your machine without a person deciding it should.

How it works

Content ──▶ Draft (status: pending) ──▶ Approve (status: approved) ──▶ Publish ──▶ Ledger
   │              a file in                a person, in the             POST /rest/posts    .github/
 .cms/ index      drafts/linkedin/         review panel                 as the org          linkedin-log.json
 or a frontmatter scan
  • Content comes from the .cms/ contract when your repo has one (the zer0-CMS content engine's machine-readable index), and degrades honestly to a frontmatter scan when it doesn't.
  • Drafts are markdown files with type / status / source frontmatter — the same queue format the BASH CI lane publishes from, so the extension and a GitHub Actions workflow can share one queue and one ledger without stepping on each other.
  • The guard is mechanical: LinkedIn's 3,000-character limit, the 140-character "…see more" fold, a banned-phrase list, filler detection, and your own patterns file. Errors block a live post; a human can still be overruled only by a human.
  • The ledger is keyed by canonical URL. Either lane (extension or CI) posts first; the other skips. Byte-compatible with the Python lane's json.dump output, so the file never churns in git.

The four views

View What it shows
Drafts The queue, by status — open the review panel, approve, publish
Content Distributable pages (health-ranked when .cms/ exists), with a posted badge
What to write next Catering lanes: A — distribute what exists · B — write more of what landed · C — say the quiet part · D — refresh what worked
Published The ledger, newest first — jump to the live post

Getting started

  1. Install the extension, open your content repo.
  2. Set bashCms.linkedin.orgUrn and bashCms.site.baseUrl (Settings → BASH-CMS).
  3. Run BASH-CMS: Set LinkedIn Credentials and paste a token with w_organization_social + r_organization_social (from the token generator; requires Community Management API access on your LinkedIn app).
  4. Run BASH-CMS: LinkedIn: Who Am I to confirm the token, scopes, and expiry.
  5. Draft from the Content view, review, approve — and when you're ready to go live, enable bashCms.publish.allow.

Publishing is off by default. Until you enable it, every path — commands, the review panel, MCP — is preview and draft only.

Commands

Command What it does
Set / Clear LinkedIn Credentials Token (and optional client id/secret) into VS Code SecretStorage — never settings, never a file
LinkedIn: Who Am I Token status, granted scopes, days to expiry
New Article Draft / New Text Draft Stage a status: pending draft in the queue
Preview LinkedIn Payload The exact /rest/posts body that would send — no network
Run Brand Guard on Draft Errors, warnings, and the fold preview
Approve Draft pending → approved, recorded in the file
Publish Draft… / Publish All Approved Drafts The live path: guard → ledger → confirm → post → record
Open Review Panel The approval gate, made legible (below)
Generate Catering Worklist Write .cms/distribution/worklists/<date>-catering.md
Open Post on LinkedIn Jump from the ledger to the live post
Configure MCP Server (.vscode/mcp.json) Fallback wiring for older VS Code

The review panel

One panel per draft, opened beside the editor: the commentary with the fold marker where LinkedIn truncates, every guard finding, the exact outgoing JSON, and the ledger state. The Publish button stays disabled until the gates pass — and the extension re-checks every gate on its own side when you click, because a webview is UI, never the gate.

MCP server

The extension registers a bundled MCP server with VS Code (1.101+), so Copilot agent mode — or any MCP client pointed at dist/mcp-server.js — gets six tools:

Tool Safe?
linkedin_whoami · linkedin_list_posts · linkedin_get_post · linkedin_preview read-only
linkedin_draft writes a pending draft for a human
linkedin_publish off by default — needs BASH_CMS_MCP_ALLOW_PUBLISH=1 in the server env and confirm: true per call

The access token is injected into the server process only at start time, from SecretStorage — it never appears in a static definition, a setting, or a log.

Settings

Setting Default Purpose
bashCms.linkedin.orgUrn — The company page (urn:li:organization:…)
bashCms.linkedin.apiVersion 202606 LinkedIn-Version header (YYYYMM)
bashCms.site.baseUrl — Canonical site origin
bashCms.site.permalinkPattern /posts/:year/:month/:day/:slug/ Canonical URL shape (the ledger key)
bashCms.content.globs pages/_posts/**/*.md Where content lives when there's no .cms/
bashCms.content.previewsDir / .fallbackImage assets/images/… Card thumbnail resolution
bashCms.drafts.folder drafts/linkedin The queue
bashCms.ledger.path .github/linkedin-log.json The shared ledger
bashCms.publish.allow false The master gate
bashCms.publish.acceptStatuses pending, approved Set to approved only to require the in-editor approval step
bashCms.guard.bannedPatternsFile — Extra banned patterns ([{name, pattern, flags?}])
bashCms.env.readDotEnv true Read LINKEDIN_* from the workspace .env as a fallback

Boundaries

Four rules this tool is built around, in order of importance:

  1. Every post is approved by whoever's name goes on it. There is no unattended path to the live page.
  2. Each account is authorized by its own owner's consent — a token the owner minted, stored in SecretStorage.
  3. The audience you write for is declared by you — never derived from connections, followers, or anyone's profile data.
  4. Everything read back is your own aggregate numbers. No member-level data enters the catering lanes.

Security notes

  • Tokens live in VS Code SecretStorage (the OS keychain). The workspace .env is a read-only fallback for repos that already use one; the extension never writes secrets to disk.
  • LinkedIn access tokens last 60 days and programmatic refresh is limited to LinkedIn partners — Who Am I tells you the days remaining, and the ledger records the expiry so a CI health-check can warn too.
  • The HTTP client never puts the token in an error message or a log line.

Development

npm install
npm run compile        # type-check + lint + both bundles
npm test               # unit + golden + MCP stdio + integration (downloads VS Code 1.101)
npx @vscode/vsce package   # build the .vsix

The test suite includes golden cross-lane fixtures generated by the Python publishing lane (src/test/fixtures/golden/) — the ledger bytes, payload previews, and catering worklists must match that lane byte-for-byte, because both write the same files in the same repos. Regenerate with python3 src/test/fixtures/golden/generate.py <path-to-bashconsultants>.

License

MIT — © Amr Abdel-Motaleb, BASH Consulting.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选