Skip to main content
Glama
zouwei

mcp-instagram

by zouwei
README.md
# mcp-instagram

Instagram 发布 MCP server —— 走**官方 Graph API**,同时支持 stdio 与 streamable-http 两种传输。

为飞雁(feiyan)而写,但不依赖飞雁:任何 MCP 客户端都能用。AGPL-3.0-only。

## 为什么自己写

Meta 没有官方 Instagram MCP(唯一的官方连接器是 Meta Ads,只管广告投放)。社区实现有几个,但全是 Graph API 的薄封装、star 个位到二十几、维护弱。既然是薄封装,与其依赖一个随时会停更的仓库,不如自己维护一份。

## 先决条件

这三件是 Meta 的硬门槛,不是本项目能绕开的:

1. **专业账号**(Business / Creator)。个人号在 API 层面被结构性排除。
2. **Meta 应用 + Advanced Access**:`instagram_business_content_publish` 权限要过 App Review 与企业验证,每次提交 2–4 周。
3. **长期访问令牌**(60 天)与 `IG_USER_ID`。短期令牌可以用 `exchangeForLongLived()` 换一次;之后本服务会在剩余 7 天内自动续期。

## 平台硬限制(工具描述里也写了一遍)

| 项 | 限制 |
|---|---|
| 图片格式 | **仅 JPEG** |
| 图片大小 | ≤ 8 MB |
| 图片尺寸 | 宽 320–1440 px |
| 宽高比 | 4:5 ~ 1.91:1 |
| 轮播 | 2–10 张;**所有图按第一张的比例裁剪**,顺序即展示顺序 |
| caption | ≤ 2200 字符,≤ 30 个话题标签,**不渲染 Markdown** |
| 发布配额 | 100 条 / 24 小时滚动窗口(轮播算 1 条) |

**媒体必须是 https 公网地址** —— Instagram 由服务端主动拉取,本地路径和内网地址它都取不到。把图片放到公网(对象存储 / CDN / 图床)再把 URL 交给本服务。

## 配置

| 环境变量 | 必填 | 说明 |
|---|---|---|
| `IG_USER_ID` | ✅ | 专业账号的 user id(不是用户名) |
| `IG_ACCESS_TOKEN` | ✅ | 长期访问令牌 |
| `IG_APP_SECRET` | | 仅「短期换长期」时需要;续期用不到 |
| `IG_API_BASE` | | 默认 `https://graph.instagram.com`(测试可指向本地假服务器) |
| `IG_DATA_DIR` | | 令牌缓存目录。容器里挂卷,续期结果才能跨重启保留 |
| `AUTH_TOKEN` | | **http 模式的 Bearer 令牌**。不设 = 不鉴权 |
| `MCP_TRANSPORT` / `MCP_PORT` / `MCP_HOST` | | `http` 启用 streamable-http,默认端口 18080 |

## 运行

```bash
# stdio(默认):客户端拉起本进程,一进程一账号
IG_USER_ID=... IG_ACCESS_TOKEN=... npx @feiyan/mcp-instagram

# streamable-http:常驻服务 / 容器
IG_USER_ID=... IG_ACCESS_TOKEN=... AUTH_TOKEN=$(openssl rand -hex 24) \
  npx @feiyan/mcp-instagram --http --port 18080
# 端点 http://<host>:18080/mcp,健康检查 http://<host>:18080/healthz(不鉴权)
```

Claude Desktop 之类的客户端配置:

```json
{
  "mcpServers": {
    "instagram": {
      "command": "npx",
      "args": ["-y", "@feiyan/mcp-instagram"],
      "env": { "IG_USER_ID": "...", "IG_ACCESS_TOKEN": "..." }
    }
  }
}
```

## 工具

| 工具 | 说明 |
|---|---|
| `publish_post(caption, image_urls[], alt_texts?)` | 1 张 → 单图帖,2–10 张 → 轮播。唯一的发布入口 |
| `get_publishing_limit()` | 24 小时配额用了多少、还剩多少 |
| `check_token()` | 令牌剩余有效天数 |
| `refresh_token()` | 立即续期(通常不必手动调,快过期会自动续) |

失败一律以 `isError: true` 返回,并把 Graph API 的错误码翻成可执行的话(例如 `190` → 「重新走一次授权」,`10` → 「缺 `instagram_business_content_publish`,去 App Review 申请 Advanced Access」)。

## 开发

```bash
pnpm install
pnpm build      # stdio 子进程用例测的是 dist/index.js,跑测试前先 build
pnpm test
pnpm check      # tsc --noEmit
pnpm lint
```

测试不打真实网络:起一个**真的 node:http 假 Graph API** 当夹具(mock fetch 只能证明「我以为的请求」是对的),并用真的 MCP 客户端 SDK 连 stdio 与 streamable-http 各跑一遍。

TDQS

A4.2/5.0

Scored across 4 tools

Disambiguation5/5

每个工具功能边界清晰:publish_post 负责发布内容,get_publishing_limit 查询配额,check_token 检查令牌有效期,refresh_token 刷新令牌。不存在职责重叠,易于选择。

Naming Consistency5/5

所有工具均采用一致的 verb_noun 命名模式(publish_post, get_publishing_limit, check_token, refresh_token),动词明确,风格统一。

Tool Count5/5

4 个工具精准覆盖 Instagram 发布与令牌管理的核心需求,数量精简,没有冗余工具。

Completeness4/5

覆盖了发布、配额查询、令牌查看与刷新等关键操作,但缺少如获取账号信息、删除帖子等扩展功能,不过对于当前定位已足够完整。

Maintenance

ActivitySlowing
ResponsivenessNo issues