MCP, MCP server
Substack Mcp
A Model Context Protocol (MCP) Server for Substack enabling LLM clients to interact with Substack's API for automations like creating posts, managing drafts, and more.
Compatibility: Not stated.
Grade C
One Medium finding. Read the findings before installing.
Not a guarantee. A hygiene check of the source at the commit shown, not a security audit.
Rescanned at commit c148a3b17699, unchanged since the check below.
SECRETS_PATH_CREDENTIAL
Why this grade
- SECRETS_PATH_CREDENTIAL Medium
Mentions a credential store path (~/.ssh, id_rsa, .npmrc, .aws/credentials, credentials.json, .netrc).
ops/publish-npm.sh, line 14
# Create .npmrc file with auth token
Any High, or two or more Medium findings, give D. One Medium gives C. Low findings or a security Note give B. Each code names a finding behind the letter.
Grades are a hygiene check of the source at the commit shown, on the date checked, not a security audit or a guarantee. The free directory grades are automated. Before release, a PlugVet engineer reviews every paid report and any grade we hold back, including all F grades, against the source code and the evidence we quote.
What was checked
Plain notes from the hygiene checks.
Permissions
Concern
can delete files.
PERMISSION_DELETE_FILES
src/api/substack/image.spec.js, line 63
await fs.rm(dir, {recursive: true, force: true});
src/tools/upload_image.spec.js, line 71
after(async () => fs.rm(dir, {recursive: true, force: true}));
Install and update
Pass
No install-time script found, and dependencies are pinned or absent.
Network
Concern
can reach a host that is not written as a fixed address. can reach not-mocked.example.com. The description does not name that host.
NETWORK_NO_FIXED_HOST NETWORK_UNNAMED_HOST
src/api/substack/SubstackApi.js, line 135
response = await fetch(url, {
src/tools/update_draft.spec.js, line 28
http.get(SOURCE, () => new HttpResponse(body, {status: 200, headers: {'Content-Type': type}}));
src/tools/update_draft.spec.js, line 273
http.get(SOURCE, () => new HttpResponse('nope', {status: 500, headers: {'Content-Type': 'text/plain'}}))
Show more
src/tools/upload_image.spec.js, line 31
return http.get(SOURCE, () => new HttpResponse(body, {status: 200, headers: {'Content-Type': type}}));
src/tools/upload_image.spec.js, line 188
http.get(REDIRECTOR, () => new HttpResponse(null, {status: 302, headers: {Location: INTERNAL}}))
docs/superpowers/plans/2026-08-06-test-suite.md, line 304
const res = await axios.post(DRAFTS_URL, {draft_title: 'Hello'}, {
docs/superpowers/plans/2026-08-06-test-suite.md, line 316
await assert.rejects(() => axios.get('https://not-mocked.example.com/leak'));
docs/superpowers/plans/2026-08-06-test-suite.md, line 322
const err = await axios.post(DRAFTS_URL, {}).catch((e) => e);
docs/superpowers/plans/2026-08-06-test-suite.md, line 1456
await axios.get('https://substack.com/api/v1/whoami');
Secrets
Concern
reads a credential or environment file.
SECRETS_ENV_READ SECRETS_PATH_CREDENTIAL
ops/publish-npm.sh, line 14
# Create .npmrc file with auth token
ops/publish-npm.sh, line 15
echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ~/.npmrc
src/index.spec.js, line 44
...env,
Show more
src/tools/add_tag_to_post.js, line 43
auth_token: process.env.SUBSTACK_SESSION_TOKEN,
src/tools/comment_on_post.js, line 36
auth_token: process.env.SUBSTACK_SESSION_TOKEN,
src/tools/create_draft_post.js, line 94
auth_token: process.env.SUBSTACK_SESSION_TOKEN,
src/tools/delete_draft.js, line 31
auth_token: process.env.SUBSTACK_SESSION_TOKEN,
src/tools/export_subscribers.js, line 119
auth_token: process.env.SUBSTACK_SESSION_TOKEN,
src/tools/get_analytics.js, line 215
auth_token: process.env.SUBSTACK_SESSION_TOKEN,
src/tools/get_comment_thread.js, line 37
auth_token: process.env.SUBSTACK_SESSION_TOKEN,
src/tools/get_draft.js, line 36
auth_token: process.env.SUBSTACK_SESSION_TOKEN,
.dockerignore, line 8
.vscode
.gitignore, line 10
/npm-debug.log*
docs/superpowers/plans/2026-08-06-test-suite.md, line 117
.vscode
docs/superpowers/specs/2026-08-06-test-suite-design.md, line 250
.vscode
Agent instructions
Pass
No instruction to ignore earlier instructions or to hide a step.
Obfuscation
Pass
No encoded or minified payload found.
Licence
Pass
A licence file is present (LICENSE).
Maintainer activity
Pass
The latest commit is within the last 365 days.
Note
Hygiene check of commit c148a3b17699. can delete files. can reach a host that is not written as a fixed address. can reach not-mocked.example.com. The description does not name that host. reads a credential or environment file.
Date and source
Date checked:
github.com
Commit graded: c148a3b176997077d2796530ae98660ef2f96d5a
This link goes to the original host. PlugVet does not host or check what you download from there, and installing it is your own decision and risk.