Social Harvest MCP

Social Harvest MCP

A local Instagram exporter for MCP clients that exports profile metadata, posts, reels, captions, and comments via a manually authenticated browser session.

Category
访问服务器

README

Social Harvest MCP

Local-first Instagram export, inbox search, and messaging automation for MCP-compatible AI agents.

Version Node.js License

Social Harvest connects Claude Code, Codex, OpenCode, and other MCP clients to Instagram through a browser session that you authenticate manually. It can export profiles and media, synchronize a searchable local inbox, send messages and attachments, manage common conversation actions, and monitor inbox changes.

Social Harvest executes locally, and all persistent data stays on your machine. Instagram traffic originates from the local authenticated browser session.

[!IMPORTANT] Social Harvest uses Instagram’s authenticated web experience—not Meta OAuth, the official Instagram APIs, or webhooks. Instagram can change its endpoints and controls without notice. Use this project only with accounts and content you are authorized to access.

Contents

Highlights

Area What Social Harvest provides
Profile export Profile metadata, posts, reels, captions, hashtags, mentions, reported metrics, bounded comments, and optional active stories
Media archive Streaming downloads for profile images, posts, reels, carousels, stories, thumbnails, and DM attachments, with SHA-256 metadata
Local inbox Primary, General, Requests, groups, and spam/hidden system buckets synchronized into SQLite
Search FTS5 full-text message search with thread, folder, sender, and date filters
Messaging Text, local images, video, audio, GIF/sticker search, group-thread targeting, and replies
Conversation actions React or unreact, mark read or unread, and accept or decline message requests
Automation Background jobs, adaptive inbox monitoring, durable events, and optional idempotency keys
Agent safety Bounded reads, explicit side-effect annotations, fail-closed message targeting, and confirmed purge operations

How it works

flowchart LR
    A[MCP client] --> B[Social Harvest MCP]
    C[CLI] --> D[Instagram services]
    B --> D
    D --> E[Shared Playwright session]
    E --> F[Instagram Web]
    D --> G[JSON and NDJSON exports]
    D --> H[SQLite inbox and FTS5]
    D --> I[Content-addressed media]
    H --> J[Durable event queue]

Social Harvest launches Chromium with a persistent profile directory. You complete login and any verification yourself; later CLI and MCP operations reuse that authenticated profile. Concurrent operations share one browser context while receiving isolated pages.

Quick start

Requirements

  • Node.js 20 or newer
  • npm
  • An Instagram account permitted to access the requested content

1. Install

git clone https://github.com/IotA-asce/social-harvest-mcp.git
cd social-harvest-mcp
npm install
npx playwright install chromium

2. Authenticate Instagram

npm run login

A visible browser opens. Log in, complete any verification, return to the terminal, and press Enter. The session is saved under .playwright-profile/instagram/, which is excluded from Git.

Social Harvest never asks for or stores your Instagram password directly.

3. Verify the environment

npm run doctor

The doctor checks the Node.js version, Playwright browser availability, profile directory, and authenticated Instagram session.

4. Start the MCP server

npm run mcp

For client-specific configuration, see Connect an MCP client.

Common workflows

Export a profile and its media

npm run scrape -- --username nasa --max-items 20 --max-comments 50

Media downloading is enabled by default. Normalized assets retain their remote URL and receive local path, MIME type, byte size, and SHA-256 metadata.

Exports use a deterministic run structure:

exports/
└── instagram/
    └── nasa/
        └── 2026-07-28T.../
            ├── manifest.json
            ├── profile.json
            ├── posts.ndjson
            ├── reels.ndjson
            ├── stories.ndjson
            ├── comments.ndjson
            ├── errors.ndjson
            ├── checkpoint.json
            └── media/

Only files containing records are created.

To backfill or resume media for an existing export:

npm run download-media -- --export-dir ./exports/instagram/nasa/2026-07-28T...

To watch the browser and include active stories:

npm run scrape -- \
  --username nasa \
  --max-items 20 \
  --include-stories true \
  --headless false

[!WARNING] Opening an active story creates Instagram’s normal story-view receipt. The story owner may see the authenticated account in their viewer list. Story export is disabled by default.

Synchronize the inbox

npm run sync-inbox -- --folders primary,general,requests,system
npm run inbox-status

Inbox sync stores normalized threads, participants, messages, attachments, reactions, receipts, and pagination state in SQLite. Attachments are stored by content hash so identical files can be reused safely.

The first successful sync of each account and folder is a silent seed: existing history is stored without generating a flood of “new message” events. Later syncs produce deduplicated events for observed changes.

Folder names exposed by the CLI and MCP are normalized as follows:

Folder Meaning
primary Instagram Primary, including the internal main label
general Instagram General
requests Pending message requests
system Current spam and hidden-request buckets

Capture one conversation snapshot

Use instagram_get_messages when an agent needs a portable, bounded snapshot for an exact username. The complete requested history is written locally while the MCP response returns only a small preview.

dm-exports/
└── instagram/
    └── username/
        └── 2026-07-28T.../
            ├── manifest.json
            ├── thread.json
            ├── messages.ndjson
            └── media/

The configured message maximum is 1,000 records per snapshot.

[!NOTE] Opening or fetching a conversation may apply Instagram’s normal read-state behavior.

Send messages and attachments

instagram_send_message targets exactly one username or stable threadId. Thread targeting supports one-to-one conversations and groups.

Supported message parts:

  • text up to 1,000 characters;
  • up to 10 local JPEG, PNG, MP4, MOV, or supported audio files;
  • one GIF/sticker selected with gifQuery and optional gifIndex;
  • an optional replyToMessageId after the conversation has been synchronized.

Text, an attachment batch, and a GIF/sticker are submitted as separate message parts. Local .gif uploads are not accepted by the current Instagram composer; use gifQuery instead.

Example agent request:

Send “The draft is ready” and ./preview.png to the synchronized Instagram
thread 123456. Use clientRequestId "draft-preview-2026-07-28".

[!CAUTION] Messaging, reactions, read-state changes, and request decisions happen immediately. Social Harvest does not provide a draft-confirm step.

Monitor changes

instagram_start_inbox_monitor performs an immediate sync and then polls at a 60-second interval with ±15% jitter. Transient failures use exponential backoff capped at 15 minutes.

Authentication, checkpoint, or challenge failures pause the monitor and release its browser session hold. Monitors never restart automatically after a pause or process restart.

Use:

  • instagram_inbox_monitor_status to inspect the current process-local state;
  • instagram_stop_inbox_monitor to stop polling;
  • instagram_list_inbox_events to read durable local events;
  • instagram_ack_inbox_events to mark events acknowledged locally.

Acknowledgement does not change Instagram state and does not delete the event record.

MCP tools

Core, jobs, and exports

Tool Purpose Side effects
social_capabilities Describe supported platforms, record types, and limits None
instagram_start_export Start a bounded profile export job Reads Instagram; writes local files
social_job_status Read status for any retained background job None
social_export_status Compatibility alias for social_job_status None
social_list_export_files List files in an export directory None
social_read_export Read bounded JSON or NDJSON records None

Inbox sync and search

Tool Purpose Side effects
instagram_start_inbox_sync Synchronize selected inbox folders Reads Instagram; writes local data
instagram_get_messages Capture a bounded exact-username snapshot and index it locally May mark a conversation read; writes local data
instagram_list_conversations List locally synchronized threads with filters None
instagram_get_conversation Read bounded local history, optionally refreshing first Optional Instagram read; optional local writes
instagram_search_messages Search local messages through FTS5 None

Immediate Instagram actions

Tool Purpose Side effects
instagram_send_message Send text, local attachments, GIF/sticker content, or a reply Immediate Instagram write
instagram_set_message_reaction Set or remove the viewer’s emoji reaction Immediate Instagram write
instagram_set_conversation_state Mark a thread read or unread Immediate Instagram write
instagram_handle_message_request Accept or decline a pending request Immediate, potentially destructive Instagram write

Monitoring, events, and retention

Tool Purpose Side effects
instagram_start_inbox_monitor Start process-local adaptive polling Repeated Instagram reads and local writes
instagram_inbox_monitor_status Read monitor state None
instagram_stop_inbox_monitor Stop polling and release the held session Local process state only
instagram_list_inbox_events Read durable local events None
instagram_ack_inbox_events Mark events acknowledged Local database write only
instagram_purge_inbox_data Delete scoped thread/message data and unreferenced media Destructive local write; requires confirm=true

Export and inbox-sync tools return immediately with a job ID. Poll them with social_job_status. Jobs are retained in memory for the lifetime of the MCP server process.

Connect an MCP client

Use the included templates and replace the example project path with an absolute path to your clone.

Client Configuration template
Claude Code examples/claude-code.json
Codex examples/codex.toml
OpenCode examples/opencode.json

A typical agent workflow looks like this:

Use Social Harvest to synchronize my Instagram inbox without downloading media.
Poll the job until it completes, list unread conversations, and summarize the
five most recent messages without sending or changing anything.

Storage and privacy

Social Harvest excludes its default private-data directories from Git:

Path Contents
.playwright-profile/ Authenticated browser state and cookies
exports/ Profile exports and public/session-visible media
dm-exports/ Private bounded conversation snapshots
inbox-data/ SQLite inbox, event queue, mutation audit, and private media

The inbox layout is:

inbox-data/
├── instagram.sqlite
├── instagram.sqlite-wal
├── instagram.sqlite-shm
└── media/
    └── ab/
        └── abcdef...<original-extension>

On POSIX platforms, Social Harvest forces inbox directories to mode 0700 and the database/media files it creates to mode 0600.

[!WARNING] The database, media, exports, and browser profile are plaintext. Filesystem permissions and the security of your device and backups are the only protection in this release.

instagram_purge_inbox_data removes a selected thread or messages before a timestamp and garbage-collects only media no longer referenced by another stored message. Durable event and mutation-audit rows remain in the SQLite database. To erase all local inbox state, stop Social Harvest and remove inbox-data/ yourself.

See SECURITY.md for acceptable-use boundaries and handling guidance.

Operational semantics

Submitted is not delivered

A mutation result with status: "submitted" means Instagram accepted the browser request or composer interaction. It is not a delivery receipt, read receipt, or guarantee that Instagram will retain the message.

Retry safety

Mutation tools accept an optional clientRequestId. Once a request ID completes, retrying it returns the stored result without repeating the browser interaction. Reusing the same ID for a different operation is rejected.

Calls without a request ID are not idempotent and can repeat an action or send duplicate content.

Partial sends

When a call includes text, attachments, and a GIF/sticker, Instagram receives separate parts. A later part can fail after an earlier part was submitted. Social Harvest reports this as direct_send_partial; inspect submitted_parts before retrying.

Fail-closed message mapping

Replies and reactions map a synchronized message ID to one unique rendered text fingerprint. If the message is not rendered, contains no uniquely usable text, or matches multiple visible messages, Social Harvest refuses the action instead of risking interaction with the wrong message. Media-only and duplicate-text messages can therefore require a different target or a later adapter improvement.

Completeness

“Complete” means all records discoverable by the authenticated browser session within the configured bounds. It does not include deleted content, expired stories, inaccessible private content, platform-hidden content, or records Instagram did not load.

Absence is never treated as deletion. Only explicit tombstones or unsend state are stored as deleted messages. Media download failures do not roll back successfully synchronized message metadata.

Limitations

  • Instagram’s private web endpoints, response shapes, numeric folder selectors, and rendered controls can change without notice.
  • Comments and stories are best-effort and bounded.
  • Inbox history is bounded by configured folder, thread, and message pagination limits.
  • Disappearing or unsupported message types may retain metadata without usable content.
  • Story collection creates a normal story-view receipt.
  • Reading conversations can create normal read-state behavior.
  • The project does not solve CAPTCHAs, bypass access controls, rotate proxies, or attempt anti-bot evasion.
  • Eligible professional accounts should prefer an official Instagram API when its permissions and data coverage satisfy the use case.

Development

Run the complete test suite and syntax checks:

npm test
npm run check

Useful diagnostics:

npm run doctor
npm run inbox-status
npm audit

The project uses Node.js ESM, Playwright, the Model Context Protocol TypeScript SDK, Zod, better-sqlite3, SQLite WAL/FTS5, and the built-in Node.js test runner.

License

Released under the MIT License.

推荐服务器

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 模型以安全和受控的方式获取实时的网络信息。

官方
精选