Hyperlink MCP
README.md
# Hyperlink MCP
One MCP server, many platforms. Hyperlink MCP gives an LLM agent a single connection through which it can **read, post, comment, and engage** on forums, comment sections, and social media **as the user** — for marketing, SEO research, and community engagement.
Instead of wiring one MCP server per platform into every client, you connect Hyperlink once and add platforms as adapters.
## Status
| Platform | Adapter | Auth | Capabilities |
|---|---|---|---|
| Substack | ✅ opt-in (`SUBSTACK_ENABLE`) | session cookie | full substack-mcp surface (drafts, Notes, feed, comments, restack, tags, settings, stats) |
| Reddit | ✅ opt-in (`REDDIT_ENABLE`) | OAuth | whoami, feed, search, thread, submit, comment, vote |
| Hacker News | ✅ always on | none (public API) | feed, thread, search, user profile (read-only) |
| X (Twitter) | 🔜 planned | session cookie | read + post + reply |
| Threads | 🔜 planned | session cookie | read + post + reply |
| LinkedIn | 🔜 planned | session cookie | read + post + reply |
| LIHKG | 🔜 planned | session cookie | read + post + reply |
| Discourse forums | 🔜 planned | API key | read + post + reply |
| Medium | 🔜 planned | session cookie | read + comment + clap |
| Quora | 🔜 planned | session cookie | read + answer + comment |
| Dev.to | 🔜 planned | API key | read + post + comment |
| Product Hunt | 🔜 planned | OAuth | read + comment + upvote |
| YouTube comments | 🔜 planned | OAuth | read + comment |
(See `src/platforms/_template/` to add one.)
## Quick start
```bash
nvm use
npm install # also runs tsc via prepare
npx playwright install chromium # needed for Substack Notes
npm run smoke # build + list platforms/tools + live HN
```
Register with an MCP client (e.g. Claude Code):
```bash
claude mcp add hyperlink -- node /path/to/hyperlink-mcp/dist/src/index.js
```
Or in a JSON MCP config (enable platforms via `env`):
```json
{
"mcpServers": {
"hyperlink": {
"command": "node",
"args": ["/path/to/hyperlink-mcp/dist/src/index.js"],
"env": {
"REDDIT_ENABLE": "true",
"REDDIT_CLIENT_ID": "...",
"REDDIT_CLIENT_SECRET": "...",
"REDDIT_REFRESH_TOKEN": "...",
"SUBSTACK_ENABLE": "true",
"SUBSTACK_PUBLICATION_URL": "https://yourname.substack.com",
"SUBSTACK_SESSION_TOKEN": "...",
"SUBSTACK_USER_ID": "..."
}
}
}
}
```
## Platform setup
A platform is enabled only when its `*_ENABLE` flag is truthy (`true` / `1` / `yes`) **and** every required parameter below is set. `list_platforms` shows what is missing.
### Substack
Session-cookie auth. Log in to Substack in your browser, then copy the `substack.sid` cookie value and your numeric user id.
| Parameter | Required | Description |
|---|---|---|
| `SUBSTACK_ENABLE` | ✅ | Set to `true` to enable the adapter |
| `SUBSTACK_PUBLICATION_URL` | ✅ | Your publication URL, e.g. `https://yourname.substack.com` |
| `SUBSTACK_SESSION_TOKEN` | ✅ | `substack.sid` session cookie value |
| `SUBSTACK_USER_ID` | ✅ | Numeric Substack user id |
| `SUBSTACK_USE_CHROME` | optional | Set to `1` to prefer installed Chrome over bundled Chromium for Notes |
Notes create/reply drive a real browser (Cloudflare-protected endpoints) — install Playwright Chromium once:
```bash
npx playwright install chromium
```
### Reddit
OAuth with a permanent refresh token. Create an app at <https://www.reddit.com/prefs/apps> (type **script** or **web app**), then run the OAuth code flow once with `duration=permanent` to obtain a refresh token.
| Parameter | Required | Description |
|---|---|---|
| `REDDIT_ENABLE` | ✅ | Set to `true` to enable the adapter |
| `REDDIT_CLIENT_ID` | ✅ | App client id from reddit.com/prefs/apps |
| `REDDIT_CLIENT_SECRET` | ✅ | App client secret |
| `REDDIT_REFRESH_TOKEN` | ✅ | Permanent OAuth refresh token |
| `REDDIT_USER_AGENT` | optional | Custom user agent, e.g. `hyperlink-mcp/0.1.0 (by /u/yourusername)` |
### Hacker News
No setup — public Firebase/Algolia APIs, read-only, always on.
| Parameter | Required | Description |
|---|---|---|
| — | — | No configuration needed |
## How it works
```
src/
index.ts MCP server bootstrap (stdio transport)
core/registry.ts collects adapters, namespaces tools, gates on enableEnv + requiredEnv
platforms/
index.ts the adapter list — register new platforms here
_template/ copy me: documented adapter skeleton
hackernews/ reference adapter (public API, no auth)
reddit/ OAuth adapter (adapter.ts + api.ts)
substack/ full port of substack-mcp (adapter.ts + api/ + tools/ + utils/)
dist/ tsc output — MCP clients point here
```
- Every adapter exposes tools namespaced by platform: `hackernews_search`, `reddit_comment`, …
- Optional `enableEnv` (e.g. `REDDIT_ENABLE`) must be truthy (`true` / `1` / `yes`); then every `requiredEnv` credential must be set. Until then the platform is **disabled but visible** — `list_platforms` lists what is missing.
- Adapters aim for a shared verb set (`whoami`, `get_feed`, `search`, `get_thread`, `create_post`, `comment`, `react`) plus platform-specific extras, so agent skills transfer between platforms.
## Adding a platform
1. Copy `src/platforms/_template/` to `src/platforms/<platform>/`.
2. Fill in `id`, `name`, optional `enableEnv`, `requiredEnv`, and implement the tool handlers (`adapter.ts` + `api.ts` as needed).
3. Register the adapter in `src/platforms/index.ts`.
4. `npm run build` then `npm run smoke` / `npm run test:registry`.
Auth guidance lives in the template. For cookie-auth platforms behind bot detection (Cloudflare etc.), the proven pattern is playwright-extra + stealth with in-page `fetch()` calls — see `src/platforms/substack/tools/create_note.ts` and `utils/notesBrowser.ts`.
## Configuration
All credentials come from environment variables, one prefix per platform (see `.env.example`). No credentials are ever written to disk by this server.
## A note on responsible use
This server acts **as the authenticated user, on their own accounts, at their direction**. Use it for genuine engagement and research. Platform terms of service still apply — spam and inauthentic behaviour will get accounts banned regardless of tooling.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing