Social Harvest MCP
Provides tools for exporting Instagram profiles, posts, reels, stories, comments, and direct messages, as well as sending direct messages via the Instagram web interface.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Social Harvest MCPExport @nasa profile with 20 posts and 50 comments each."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Social Harvest MCP
Local-first Instagram export, inbox search, and messaging automation for MCP-compatible AI agents.
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.
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
Related MCP server: Instagram Download MCP Server
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 chromium2. Authenticate Instagram
npm run loginA 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 doctorThe doctor checks the Node.js version, Playwright browser availability, profile directory, and authenticated Instagram session.
4. Start the MCP server
npm run mcpFor 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 50Media 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 falseOpening 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-statusInbox 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 |
| Instagram Primary, including the internal |
| Instagram General |
| Pending message requests |
| 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.
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
gifQueryand optionalgifIndex;an optional
replyToMessageIdafter 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".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_statusto inspect the current process-local state;instagram_stop_inbox_monitorto stop polling;instagram_list_inbox_eventsto read durable local events;instagram_ack_inbox_eventsto 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 |
| Describe supported platforms, record types, and limits | None |
| Start a bounded profile export job | Reads Instagram; writes local files |
| Read status for any retained background job | None |
| Compatibility alias for | None |
| List files in an export directory | None |
| Read bounded JSON or NDJSON records | None |
Inbox sync and search
Tool | Purpose | Side effects |
| Synchronize selected inbox folders | Reads Instagram; writes local data |
| Capture a bounded exact-username snapshot and index it locally | May mark a conversation read; writes local data |
| List locally synchronized threads with filters | None |
| Read bounded local history, optionally refreshing first | Optional Instagram read; optional local writes |
| Search local messages through FTS5 | None |
Immediate Instagram actions
Tool | Purpose | Side effects |
| Send text, local attachments, GIF/sticker content, or a reply | Immediate Instagram write |
| Set or remove the viewer’s emoji reaction | Immediate Instagram write |
| Mark a thread read or unread | Immediate Instagram write |
| Accept or decline a pending request | Immediate, potentially destructive Instagram write |
Monitoring, events, and retention
Tool | Purpose | Side effects |
| Start process-local adaptive polling | Repeated Instagram reads and local writes |
| Read monitor state | None |
| Stop polling and release the held session | Local process state only |
| Read durable local events | None |
| Mark events acknowledged | Local database write only |
| Delete scoped thread/message data and unreferenced media | Destructive local write; requires |
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 | |
Codex | |
OpenCode |
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 |
| Authenticated browser state and cookies |
| Profile exports and public/session-visible media |
| Private bounded conversation snapshots |
| 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.
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 checkUseful diagnostics:
npm run doctor
npm run inbox-status
npm auditThe 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.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- FlicenseBqualityFmaintenanceA server that allows fetching Instagram posts using Chrome's existing login session via Model Context Protocol (MCP).Last updated150
- AlicenseAqualityCmaintenanceEnables AI assistants to download Instagram content including posts, videos, reels, stories, highlights, and profile pictures using Instaloader, with optional metadata and caption extraction.Last updated5MIT
- Alicense-qualityCmaintenanceAn MCP server that wraps instagrapi to read, engage, and send DMs from a personal Instagram account, supporting 24 tools for auth, profile, engagement, and messages.Last updatedMIT
- FlicenseBqualityCmaintenanceProvides Instagram analytics, media downloads, and search capabilities through an MCP interface for use with Claude and other MCP clients.Last updated4340
Related MCP Connectors
Browser MCP for logged-in tasks. Uses your Chrome — credentials stay local. Zero-token replay.
Mastodon MCP — public Mastodon data via mastodon.social (no auth required)
Hosted MCP for X/Twitter and Reddit. 12 read-only tools, no API keys, free during beta.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/IotA-asce/social-harvest-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server