Flux LinkedIn MCP
Flux (fluxgraph.app) is a hosted LinkedIn MCP server for post analytics and research on any public profile or company page. Ask which days, formats, and lengths beat an account's own baseline, with the sample size behind each finding. A free preview covers up to 50 recent posts, and usage limits apply. Paid plans start at $5/month (MCP access is on Edge at $15/month, as of November 2026) and add full post history, weekly refresh, trends, search, and the engagement graph. You share no LinkedIn login or cookie. Flux reads public data through a third-party data provider, is read-only on LinkedIn, and is not affiliated with LinkedIn.
Hosted MCP Server
npx add-mcp 'https://www.fluxgraph.app/mcp'Installs into Claude Code, Codex, Cursor and more
Documentation
The LinkedIn MCP server for post analytics and research.
LinkedIn publishes no official MCP server that we could find. Flux is an independent, hosted one: connect Claude, Claude Code, Cursor, or any MCP client, then ask about any public profile or company page. You never share a LinkedIn login or cookie, and there is nothing to install.
Use Flux to preview linkedin.com/in/janedoe. Which days, hours, formats, and lengths beat this account’s own baseline, and how many posts back each finding?
| Your logged-in session | LinkedIn API with OAuth | Flux (hosted) | |
|---|---|---|---|
| How it reaches LinkedIn | Automates a browser or reuses your cookie | LinkedIn’s API, under your authorization | A third-party provider of public data |
| Whose account is exposed | Yours | Yours, within the permissions you grant | Not yours, because you connect no LinkedIn account |
| Other people’s posts | Whatever your session can see | Very limited | Any public profile or company page |
| Stored history and trends | Usually none | Usually none | Yes, on paid plans |
| Can post or message | Often | Sometimes (posting) | No, read-only on LinkedIn |
| Setup | Local install and upkeep | Your own LinkedIn developer app, usually | Paste one URL |
| Cost | Usually free software | Usually free software | Free 50-post preview, then paid plans |
This table describes common designs, and individual servers vary. As of November 2026, Flux’s price pays for the data pipeline and stored history, not for the protocol.
Flux ships one. Most days you won’t open it. Ask Claudewhat’s working in your last quarter, where engagement broke, who to reach out to next — it queries your post library, embeddings, scoring model, and constellation graph and writes the answer. Your data lives one sentence away from whatever you’re already working on.
Creator
Drafting a post
Claude, help me write a post about LinkedIn's algorithm change. Pull my top 3 posts on algorithm topics so you see my voice, and score the draft before we publish.
BDR
Account research
Map the constellation for Acme Corp. Who are the senior execs, which of my connections is closest to each, and what does their recent posting look like?
Consultant
Writing a proposal
Find my 10 most-engaged posts about SaaS pricing. Summarize the core thesis across them.
Sign in with Flux · no key
Claude — web, desktop app, mobile
Sign in
Add Flux as a custom connector. Connectors sync across claude.ai, the desktop app, and mobile.
- 1
In claude.ai or the Claude desktop app, open Settings → Connectors, click Add custom connector, name it Flux, and paste
https://www.fluxgraph.app/mcp. - 2 Choose Sign in when needed and Register automatically. If Claude preselects No sign-in, change it, or the connector can’t reach your data.
- 3 When Claude shows Connect, sign in with Google or your Flux email and click Approve. No Flux account yet? The same page creates one.
- 4 Enable Flux from the tools menu in a chat. Ask: “ List my tracked LinkedIn profiles.” If Flux’s tools appear and your profiles come back, you’re connected.
Developer tools · MCP key
Claude Code
MCP key
One terminal command adds Flux for every project.
- 1
In Flux, open Settings → MCP → Developer setups and click Generate MCP key. It starts with
flux_and is shown once; the same panel shows this snippet with your key filled in. - 2
Run this, replacing
YOUR_API_KEY:
Why a key: Claude Code picks a random local port for browser sign-in, and Flux’s sign-in server needs an exact one.claude mcp add --transport http --scope user flux \ https://www.fluxgraph.app/mcp \ --header "Authorization: Bearer YOUR_API_KEY" - 3 Ask: “ List my tracked LinkedIn profiles.” If Flux’s tools appear and your profiles come back, you’re connected.
Cursor
MCP key
Add a server entry to ~/.cursor/mcp.json, or.cursor/mcp.json for one project.
- 1
In Flux, open Settings → MCP → Developer setups and click Generate MCP key. It starts with
flux_and is shown once; the same panel shows this snippet with your key filled in. - 2
Add this to
~/.cursor/mcp.json(all projects) or.cursor/mcp.json(one project):{ "mcpServers": { "flux": { "url": "https://www.fluxgraph.app/mcp", "headers": { "Authorization": "Bearer YOUR_API_KEY" } } } } - 3 Ask: “ List my tracked LinkedIn profiles.” If Flux’s tools appear and your profiles come back, you’re connected.
Zed
MCP key
Add a context server to settings.json, or use Settings → AI → MCP Servers.
- 1
In Flux, open Settings → MCP → Developer setups and click Generate MCP key. It starts with
flux_and is shown once; the same panel shows this snippet with your key filled in. - 2
Add this to your Zed
settings.json:{ "context_servers": { "flux": { "url": "https://www.fluxgraph.app/mcp", "headers": { "Authorization": "Bearer YOUR_API_KEY" } } } } - 3 Ask: “ List my tracked LinkedIn profiles.” If Flux’s tools appear and your profiles come back, you’re connected.
Other MCP clients
MCP key
Anything that supports HTTP transport and custom headers.
- 1
In Flux, open Settings → MCP → Developer setups and click Generate MCP key. It starts with
flux_and is shown once; the same panel shows this snippet with your key filled in. - 2
Most clients read this shape:
Calling the server from your own code? See Calling tools directly (HTTP) below.{ "mcpServers": { "flux": { "type": "http", "url": "https://www.fluxgraph.app/mcp", "headers": { "Authorization": "Bearer YOUR_API_KEY" } } } } - 3 Ask: “ List my tracked LinkedIn profiles.” If Flux’s tools appear and your profiles come back, you’re connected.
Calling tools directly (HTTP)
JSON-RPC 2.0 envelope, endpoint, and the errors every tool can return.
Most users will connect Claude or an MCP client like Claude Code and never touch HTTP. If you need to call the server directly, every tool uses the same JSON-RPC envelope — only name and arguments change per call.
Endpoint
POST https://www.fluxgraph.app/mcp
Authorization: Bearer flux_xxx
Content-Type: application/json
Envelope
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "<tool_name>",
"arguments": { /* tool inputs */ }
}
}
Example: list tracked profiles
curl -X POST https://www.fluxgraph.app/mcp \
-H "Authorization: Bearer $FLUX_API_KEY" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"list_profiles","arguments":{}}}'
Common errors (apply to every tool)
401 invalid_api_key— key missing, malformed, or revoked. Get a fresh key at /settings.402 insufficient_credits— balance too low for a paid tool. Call get_cost_estimate first to preview spend.403 forbidden— resource exists but isn't owned by the authenticated user (most often profile_id or collection_id).422 validation_failed— arguments didn't match the tool's input schema.429 rate_limited— too many requests in the burst window. Back off and retry.
Per-tool blocks below only call out errors that are specific to that tool (e.g. insufficient_data, 404 not_found). The five above are universal — assume they can return on any call.
Analytics
Query your own post history — KPIs, trends, patterns, and semantic/keyword search.
7 tools
get_posts free
Return posts with full metrics and text content for a tracked profile. Supports filtering by date range, post type, minimum engagement, and text search. Pass scope to restrict to a collection. Paginated.
Show me every post I published last quarter with more than 50 likes.
Input
| field | type | req | notes |
|---|---|---|---|
| profile_id | string | yes | Tracked profile ID from list_profiles |
| scope | string | no | Optional post_collections.id to filter |
| date_from | string | no | Start date (ISO 8601) |
| date_to | string | no | End date (ISO 8601) |
| post_type | enum | no | text, image, video, document, article, poll |
| min_engagement | number | no | Minimum total engagement |
| search | string | no | Text search across post content |
| sort_by | enum | no | default: published_at |
| sort_dir | enum | no | default: desc |
| page | number | no | default: 1 |
| page_size | number | no | default: 25 (1–50) |
Returns
posts— Array — post objects with id, metrics, text contentmeta— Object — total_count, page, page_size, total_pages, filters_applied
Errors
404— Collection not found (when scope provided)
get_profile_summary free
KPI summary for a tracked profile: total posts, avg engagement (likes/comments/shares/conversation rate), posts per week, engagement trend, top format, and posting goal status.
How am I doing this month vs last month?
Input
| field | type | req | notes |
|---|---|---|---|
| profile_id | string | yes | Tracked profile ID from list_profiles |
Returns
total_posts— numberavg_engagement— numberavg_likes— numberavg_comments— numberavg_shares— numberconversation_rate— number — (comments / likes) * 100posts_per_week— numberdate_range— Object — earliest, latestengagement_trend— Object — direction, change_pct, 30d averagestop_format— Object | nullposting_goal— Object — goal_per_week, posts_this_week, on_tracklinks— Object (optional)
get_posting_insights free
Optimal posting patterns for a profile: best day of week, best hour, format performance breakdown, character-length sweet spot. All metrics relative to the user's own baseline. Pass scope to recompute against a collection.
When should I post this week to maximize comments?
Input
| field | type | req | notes |
|---|---|---|---|
| profile_id | string | yes | Tracked profile ID from list_profiles |
| scope | string | no | Optional post_collections.id to scope analysis |
| date_from | string | no | Start date (ISO 8601) |
| date_to | string | no | End date (ISO 8601) |
Returns
sample_size— number — total posts analyzedoverall_avg_engagement— numberbest_day— Object | nullbest_hour— Object | nullbest_format— Object | nullsweet_spot_length— Object | nullby_day_of_week— Array — sorted by avg_engagementby_hour— Array — sorted by avg_engagementby_format— Arrayby_length— Array — 200-char binsmeta— Object
Errors
403— Profile or scope not found/not owned
get_engagement_trends free
Engagement time series with gap-filled buckets, rolling averages, and trend direction. Each bucket includes avg engagement, likes, comments, shares, and conversation rate.
Plot my engagement over the last 12 weeks and tell me where it broke.
Input
| field | type | req | notes |
|---|---|---|---|
| profile_id | string | yes | Tracked profile ID from list_profiles |
| scope | string | no | Optional post_collections.id |
| granularity | enum | no | default: weekly (daily, weekly, monthly) |
| date_from | string | no | Start date (ISO 8601) |
| date_to | string | no | End date (ISO 8601) |
| rolling_window | number | no | 2–30 buckets; default by granularity |
Returns
series— Array — per-bucket metrics with rolling averagessummary— Object — direction, change_pct, period_comparisonmeta— Object — granularity, rolling_window, sample_size
Errors
403— Profile or scope not found/not owned
get_topic_insights free
Top terms and bigrams across a profile's posts, ranked by post count and engagement vs the user's baseline. Each term carries a sample post URL so you can jump to a representative example. Pass scope to recompute against a collection.
What topics get me the most engagement this quarter?
Input
| field | type | req | notes |
|---|---|---|---|
| profile_id | string | yes | Tracked profile ID from list_profiles |
| n | number | no | default: 15 (1–100 max terms per list) |
| bigrams | boolean | no | default: true |
| scope | string | no | Optional post_collections.id |
| date_from | string | no | Start date (ISO 8601) |
| date_to | string | no | End date (ISO 8601) |
Returns
terms— Array — term, post_count, avg_engagement, vs_baseline, sample_post_urlbigrams— Array | nulltotal_posts— numberoverall_avg_engagement— numberwindow— Object — from, tometa— Object
Errors
403— Profile or scope not found/not owned
search_posts free
Search posts by keyword and/or semantic similarity. Full-text search with stemming for keyword matches, pgvector embeddings for semantic matches. Results ranked by relevance.
Find everything I've written about pricing strategy.
Input
| field | type | req | notes |
|---|---|---|---|
| profile_id | string | yes | Tracked profile ID from list_profiles |
| query | string | yes | Search query |
| scope | string | no | Optional post_collections.id |
| mode | enum | no | default: hybrid (hybrid, keyword, semantic) |
| limit | number | no | default: 20 (1–50) |
Returns
posts— Array — matched posts (with similarity scores in semantic modes)meta— Object — query, mode, result_count, scope
Errors
403— Profile or scope not found/not owned400— Query required, or embedding generation failed
find_similar_posts free
Find posts semantically similar to input text using OpenAI embeddings and pgvector cosine similarity. Scope to a profile or a collection. Returns posts sorted by similarity with engagement metrics.
Have I already written something like this draft?
Input
| field | type | req | notes |
|---|---|---|---|
| text | string | yes | Text to find similar posts for (min 1 char) |
| profile_id | string | no | Optional — scope to this profile's posts |
| collection_id | string | no | Optional — scope to this collection |
| limit | number | no | default: 5 (1–50) |
Returns
posts— Array — sorted by embedding similaritycount— numbercost— number — 0 (free)
Errors
403— Profile or collection not found/not owned400— Failed to generate embedding
Prediction & drafting
Score drafts before you publish and generate fresh angles grounded in your top performers.
2 tools
score_draft free
Predict how a draft post will perform against the user's historical data. OLS regression with detrending, ridge regularization, and recency weighting — same model as the /score page. Returns predicted engagement percentile, projected range, factor breakdown, similar past posts, and improvement suggestions.
Score this draft and tell me what to cut.
Input
| field | type | req | notes |
|---|---|---|---|
| text | string | yes | Draft post text (min 1 char) |
| format | enum | no | text | image | video | document | article | poll (default: text) |
| day_of_week | number | yes | 0–6, 0=Sunday (UTC) |
| hour | number | yes | 0–23 (UTC) |
| profile_id | string | no | Optional — scope model to this profile |
| collection_id | string | no | Optional — scope model to this collection |
Returns
percentile— number — predicted engagement percentile (0–100)stars— string — qualitative bandrange— Object — low/high projected engagementfactors— Array — per-feature contributionsimilar_posts— Array — nearest historical posts with their percentilesuggestions— Array — actionable improvementsmodel— Object — sample size, R², calibration
Errors
insufficient_data— not enough historical posts in scope to train; no charge.
suggest_angles 5 credits
Given a topic, suggest distinct content angles informed by what performs well in the user's scoped data. Pulls top historical posts as context and asks OpenAI to generate 5 concrete angles.
Give me five angles on developer tooling that fit my voice.
Streams
Always-on research streams — external profiles, companies, topics, hiring signals, ad watches — that pull on a schedule into your library.
8 tools
list_profiles free
List all tracked LinkedIn profiles for the authenticated user. Returns profile IDs needed by other tools.
List my tracked LinkedIn profiles.
Returns
profiles— Array — id, display_name, linkedin_url, plan_type, status, posting_goal_per_week, autopilot_active, linksmeta— Object — count
Errors
401— Unauthorized (missing userId)
list_streams free
List all research streams (external profiles, companies, topics, person interests, hiring signals, ad watches, own_profile). Pass type to filter.
Show me every stream I've got running.
Input
| field | type | req | notes |
|---|---|---|---|
| type | enum | no | own_profile, external_profile, company, topic, person_interests, hiring_signals, ad_watch |
| include_inactive | boolean | no | default: false |
Returns
streams— Array — id, type, name, source_url, params, schedule, active, credits_per_run, last/next run, linksmeta— Object — countlinks— Object (optional) — view_all
create_stream free
Create a new research stream — the create call itself is free. Each scheduled run costs credits per page walked — normally one page; see get_cost_estimate for per-type cost. own_profile streams come from subscription checkout, not this tool.
Start a topic stream that watches LinkedIn for posts about RAG.
get_stream_feed free
Return the most recent posts a stream has collected into the library, newest first by published_at.
What did my 'fintech execs' stream pick up this week?
Input
| field | type | req | notes |
|---|---|---|---|
| stream_id | string | yes | Stream ID from list_streams |
| limit | number | no | default: 20 (1–50) |
Returns
stream— Object — id, type, nameposts— Array — recent posts (newest first)meta— Object — count, limitlinks— Object (optional) — view
Errors
404— Stream not found or not owned by you
pause_stream free
Pause a stream so it stops running on its cron schedule. Existing posts remain in the library.
Pause the competitor-ads stream.
Input
| field | type | req | notes |
|---|---|---|---|
| stream_id | string | yes | Stream ID from list_streams |
Returns
stream— Object — id, type, name, active (will be false)
Errors
404— Stream not found or not owned by you
resume_stream free
Resume a paused stream. Queues it to run on the next cron tick.
Resume my hiring-signals stream.
Input
| field | type | req | notes |
|---|---|---|---|
| stream_id | string | yes | Stream ID from list_streams |
Returns
stream— Object — id, type, name, active (will be true), next_run_at
Errors
404— Stream not found or not owned by you
delete_stream free
Delete a stream and its runs. Posts it collected stay in your library so historical data isn't lost. own_profile streams can't be deleted here — cancel the subscription instead.
Drop the stream I set up for Acme Corp.
Input
| field | type | req | notes |
|---|---|---|---|
| stream_id | string | yes | Stream ID from list_streams |
Returns
deleted— boolean — true on successstream_id— string
Errors
404— Stream not found or not owned by you403— own_profile streams cannot be deleted
run_stream_now 1–2 credits
Manually trigger a stream run instead of waiting for its cron tick. Charges per page actually walked (1 credit/page for most types, 2 for person_interests), not per page requested. Useful when you want fresh results before a scheduled run.
Run my hiring-signals stream now.
Collections & Segments
Collections group posts; segments group people. Both can be smart (predicate-driven) or manual, and both can be resolved into concrete IDs for downstream tools.
13 tools
list_collections free
List all post collections for the authenticated user, with member counts.
Input
| field | type | req | notes |
|---|---|---|---|
| type | enum | no | manual, smart, auto_stream |
Returns
collections— Array — id, name, type, config, stream_id, created_at, member_count, linksmeta— Object — countlinks— Object (optional) — view_all
create_collection free
Create a new post collection. Manual or smart (predicate-based).
Make a collection of every post I wrote about hiring.
Input
| field | type | req | notes |
|---|---|---|---|
| name | string | yes | 1–200 chars |
| description | string | no | max 2000 chars |
| type | enum | yes | manual, smart |
| config | object | no | Predicate (required when type=smart) |
Returns
collection— Object — id, name, type, config, stream_id, created_at, member_count: 0, links
Errors
400— config required when type=smart
add_to_collection free
Add one or more posts (by post_id) to a collection. Existing members are silently ignored.
Input
| field | type | req | notes |
|---|---|---|---|
| collection_id | string | yes | Target collection (UUID) |
| post_ids | array | yes | Post UUIDs to add (1–1000 per call) |
Returns
collection_id— stringpinned— number — posts newly pinned to the collectionskipped— number — already members (deduped)member_count— number — total after operationresolved_count— number — total posts the collection now resolves to (rule matches ∪ pinned)
Errors
404— Collection not found or not owned by you
remove_from_collection free
Remove one or more posts (by post_id) from a collection. Missing members are silently ignored.
Input
| field | type | req | notes |
|---|---|---|---|
| collection_id | string | yes | Target collection (UUID) |
| post_ids | array | yes | Post UUIDs to remove (1–1000 per call) |
Returns
collection_id— stringremoved— number — members deletednot_found— number — not membersmember_count— number — total after operation
Errors
404— Collection not found or not owned by you
resolve_collection free
Resolve a post collection into a concrete list of post_ids. Works for both manual and smart collections.
Input
| field | type | req | notes |
|---|---|---|---|
| collection_id | string | yes | Collection (UUID) |
| limit | number | no | default: 1000 (1–5000) |
Returns
collection_id— stringtype— string — manual, smart, or auto_streampost_ids— Arraycount— numberconfig— Object (smart collections only)warnings— Array — predicate-evaluation warningslinks— Object (optional) — view
Errors
404— Collection not found or not owned by you
list_segments free
List all audience segments for the authenticated user, with member counts. Segments are named groups of people (e.g. 'ICP — VPs of Marketing', 'Champions').
Input
| field | type | req | notes |
|---|---|---|---|
| type | enum | no | manual, smart, auto_stream |
Returns
segments— Array — id, name, description, type, config, source_stream_id, created_at, member_count, linksmeta— Object — countlinks— Object (optional) — view_all
create_segment free
Create a new audience segment. Manual or smart (template-based).
Create a segment of everyone who's commented on more than 3 of my posts.
Input
| field | type | req | notes |
|---|---|---|---|
| name | string | no | 1–200 chars; optional if template supplied |
| description | string | no | max 2000 chars |
| type | enum | no | manual, smart, auto_stream; defaults to smart with template |
| template | enum | no | Pre-built template id (pre-fills config) |
| config | object | no | Predicate (required when type=smart) |
| source_stream_id | string | no | Optional source stream UUID |
Returns
segment— Object — id, name, description, type, config, source_stream_id, created_at, member_count: 0, links
Errors
400— name/type required (or pass template); config required when type=smart404— source_stream_id or template id not found
add_to_segment free
Add one or more people (by person_id) to an audience segment.
Input
| field | type | req | notes |
|---|---|---|---|
| segment_id | string | yes | Target segment (UUID) |
| person_ids | array | yes | Person UUIDs to add (1–1000 per call) |
Returns
segment_id— stringadded— number — new members insertedskipped— number — already members (deduped)member_count— number
Errors
404— Segment not found or not owned by you
remove_from_segment free
Remove one or more people (by person_id) from an audience segment.
Input
| field | type | req | notes |
|---|---|---|---|
| segment_id | string | yes | Target segment (UUID) |
| person_ids | array | yes | Person UUIDs to remove (1–1000 per call) |
Returns
segment_id— stringremoved— number — members deletednot_found— number — not membersmember_count— number
Errors
404— Segment not found or not owned by you
resolve_segment free
Resolve an audience segment into a concrete list of person_ids.
Input
| field | type | req | notes |
|---|---|---|---|
| segment_id | string | yes | Segment (UUID) |
| limit | number | no | default: 1000 (1–5000) |
Returns
segment_id— stringtype— string — manual, smart, or auto_streamperson_ids— Arraycount— numberconfig— Object (smart segments only)warnings— Array — predicate-evaluation warningslinks— Object (optional) — view
Errors
404— Segment not found or not owned by you
list_segment_templates free
List available smart-segment templates. Pass a template id to create_segment to spin up a preconfigured segment.
Returns
templates— Array — id, name, default_segment_name, configmeta— Object — count
save_post 1 credit
Save a LinkedIn post to your library by URL. Resolves the post and stores it with source_type='saved'. Optionally adds the post to a manual collection. Failed lookups don't charge.
Save this LinkedIn post and drop it in my 'swipe file' collection.
get_alerts free
Return recent alerts for the authenticated user's streams.
Input
| field | type | req | notes |
|---|---|---|---|
| unread_only | boolean | no | default: true |
| limit | number | no | default: 50 (1–200) |
Returns
alerts— Array — id, stream_id, stream_name, items_new, message, read_at, created_at, linksmeta— Object — count, unread_onlylinks— Object — view_all
Errors
400— Query error
Research (live LinkedIn lookups)
On-demand lookups against live LinkedIn data. Most calls cost 5 credits; results from profile/company post pulls land in your library, and per-post reactions/comments populate the engagement graph so subsequent queries about who-engages-with-what become free.
12 tools
linkedin_profile_info 5 credits
Resolve a LinkedIn person URL into a structured profile — full name, headline, current company/title, location, work history. Upserted into `people` and `linkedin_profiles` so downstream tools can filter on the fields without a re-pull.
Who is this LinkedIn profile?
linkedin_profile_posts 5 credits
Fetch recent posts from a LinkedIn person profile. Results also stored in the post library (source_type='external') and linked to a linkedin_profiles row.
Pull recent posts from this LinkedIn profile.
linkedin_company_posts 5 credits
Fetch recent posts from a LinkedIn company page.
linkedin_post_search 5 credits
Search LinkedIn posts by keyword. Returns a single page of matching posts.
linkedin_profile_reactions 5 credits
Fetch the recent posts a LinkedIn person has reacted to. Useful for inferring interests.
linkedin_profile_comments 5 credits
Fetch the recent posts a LinkedIn person has commented on. Useful for inferring interests and conversation partners.
linkedin_post_reactions 5 credits
Fetch the people who reacted to a single LinkedIn post (with reaction kind). Engagers are persisted to the post_engagements graph.
linkedin_post_comments 5 credits
Fetch the people who commented on a single LinkedIn post (with comment text). Each comment is persisted to post_engagements.
linkedin_people_search 5 credits
Search LinkedIn people by company, title, location, or keywords. Returns a single page of profiles.
linkedin_company_search 5 credits
Search LinkedIn companies by keywords, industry ID, or location. Returns a single page of companies.
linkedin_job_search 5 credits
Search LinkedIn job postings. Useful for tracking hiring signals at target companies.
linkedin_ad_search 10 credits
Search the LinkedIn ad library. Useful for tracking competitor ad creative and messaging.
Constellation (warm outreach)
Map the graph around a target account, score warm paths, prioritize an outreach queue, and log outcomes so acceptance and reply rates build up over time.
8 tools
create_campaign free
Create a Constellation outreach campaign. Groups target accounts, people you care about at those accounts, and warm connections you could approach.
Input
| field | type | req | notes |
|---|---|---|---|
| name | string | yes | 1–200 chars |
| description | string | no | max 2000 chars |
Returns
campaign— Object — id, name, description, status, created_atcredits_used— number — 0monthly_allocation— Object
Errors
400— Database insert failure
add_campaign_accounts free
Add one or more target companies to a campaign. map_constellation is then run per-account.
Input
| field | type | req | notes |
|---|---|---|---|
| campaign_id | string | yes | Target campaign (UUID) |
| accounts | array | yes | 1–500 per call; each: company_name, linkedin_company_id?, employee_count?, tier? |
Returns
campaign_id— string (UUID)added— number — inserted rowsaccounts— Array — id, company_name, linkedin_company_id, tier, status, created_at
Errors
404— Campaign not found or not owned by user400— Database insert failure
map_constellation up to ~175 credits
Map the professional graph around a target company. Finds senior decision-makers, pulls each target's recent posts/reactions/comments to identify engagers, scores every connection, and produces a prioritized outreach queue. Scales with max_targets; actual cost is reported in the response.
Map the constellation for Acme Corp — who are the senior execs and who of mine is closest?
score_connections free
Re-score all constellation entries in a campaign and rewrite queue positions from highest to lowest composite score. Run after new engagers or targets are added.
Input
| field | type | req | notes |
|---|---|---|---|
| campaign_id | string | yes | Campaign to re-score (UUID) |
Returns
campaign_id— string (UUID)rescored— number — entries re-scored and re-ranked
Errors
404— Campaign not found or not owned by user
get_outreach_queue free
Return the prioritized outreach queue for a campaign, sorted by composite score. Each entry includes person details, pool (coworker/engager/mutual), recommended action, and prior log entries.
Who should I reach out to first this week?
Input
| field | type | req | notes |
|---|---|---|---|
| campaign_id | string | no | Full Constellation scoring (mutually exclusive) |
| segment_id | string | no | Engagement-count ranking (mutually exclusive) |
| linkedin_urls | array | no | Ad-hoc URLs, max 200 (mutually exclusive) |
| limit | number | no | default: 50 (1–200) |
| pool | enum | no | coworker, engager, mutual — campaign_id only |
Returns
scope— string — campaign, segment, or linkedin_urlsscoring— string — composite or engagement_countcount— numberqueue— Array — shape varies by scopeunresolved— Array (linkedin_urls mode only)
Errors
400— Must provide exactly one of campaign_id, segment_id, linkedin_urls
get_engagement_brief free
For a Constellation target, return the handful of their recent posts that most closely overlap with the topics you post about yourself — plus suggested talking points. Use before a warm comment or DM.
Brief me before I DM this person.
Input
| field | type | req | notes |
|---|---|---|---|
| target_id | string | no | Constellation targets.id (mutually exclusive) |
| person_id | string | no | people.id (mutually exclusive) |
| linkedin_url | string | no | Profile URL (mutually exclusive) |
Returns
scope— string — target, person, or linkedin_urltarget_id— string (UUID) | nulltarget— Object — full_name, headline, current_title, current_company, linkedin_urlcount— numberposts— Array — post_id, url, published_at, excerpt, engagement, similarity, talking_points
Errors
400— Must provide exactly one of target_id, person_id, linkedin_url404— Target/person not found
log_outcome free
Append an entry to the outreach log: connection requests, acceptances, replies, or no-responses. Feeds get_campaign_stats.
Input
| field | type | req | notes |
|---|---|---|---|
| campaign_id | string | yes | Campaign id (UUID) |
| person_id | string | yes | people.id (UUID) |
| action | enum | yes | sent_request, accepted, replied, no_response |
| note | string | no | max 4000 chars |
Returns
entry— Object — id, campaign_id, person_id, action, note, created_at
Errors
404— Campaign not found or not owned by user400— Insert failure
get_campaign_stats free
Summary stats for a campaign: target count, entry count, outreach volume, and acceptance / reply rates broken down by pool and score tier.
Input
| field | type | req | notes |
|---|---|---|---|
| campaign_id | string | yes | Campaign id (UUID) |
Returns
campaign— Object — id, name, status, created_attotals— Object — accounts, targets, entries, outreach counts by statusacceptance_rate— number | nullreply_rate— number | nullby_pool— Object — per pool: sent, accepted, replied, ratesby_tier— Object — per high/medium/low: sent, accepted, replied, rates
Errors
404— Campaign not found or not owned by user
Engagement graph
Read-only queries against the engagement graph — people who reacted or commented on posts in your library. Mostly free; get_post_set_engagers fetches and enriches on demand. The graph is built up by stream runs and the paid linkedin_post_* tools, then mined by these.
8 tools
get_post_engagers_by_company free
For a post in your library, group its engagers by current company — counts plus optional sample names per company. Filter to a single industry URN to slice tighter.
Which companies showed up in the engagers on my last big post?
Input
| field | type | req | notes |
|---|---|---|---|
| post_url | string | no | Post URL (mutually exclusive with post_id) |
| post_id | string | no | posts.id (mutually exclusive with post_url) |
| industry_urn | string | no | Optional urn:li:fsd_industry:* filter |
| limit | number | no | default: 20 (1–100) |
| top_engagers_per_company | number | no | default: 3 (0–10) |
Returns
post_id— string (UUID)post_url— stringtotal_engagers— numberfiltered_engagers— numbercompanies— Array — company_id, name, industry_hierarchy, engager_count, top_engagers_meta— Object
Errors
404— Post not found in your library or tracked profiles400— Must provide exactly one of post_url or post_id
get_post_set_engagers 2 credits / post + 3 / enrich
Consolidated, deduped people who reacted/commented across a post set — one tracked profile's posts (profile_id) or a post collection (collection_id). Fetches only un-synced posts; enriches only never-seen people up to max_enrich. 2 credits/post + 3/enrich; cached posts free.
Who engaged with the posts in my 'Q2 launch' collection?
get_engagement_industry_breakdown free
Histogram of engagers' industries on a post, with optional depth (1 = top-level, 3 = leaf) and sample companies per bucket. Useful for sanity-checking ICP fit.
Input
| field | type | req | notes |
|---|---|---|---|
| post_url | string | no | Post URL (mutually exclusive) |
| post_id | string | no | posts.id (mutually exclusive) |
| depth | number | no | default: 1 (1–3; 1=top-level, 3=leaf) |
| sample_companies_per_bucket | number | no | default: 3 (0–10) |
Returns
post_id— string (UUID)post_url— stringtotal_engagers— numberdepth— numberindustries— Array — industry, industry_urn, engager_count, sample_companies_meta— Object
Errors
404— Post not found400— Must provide exactly one of post_url or post_id
get_alumni_engagers free
For a target company, list people who engaged with your posts and who are current employees, alumni, or both (configurable). Returns title-at-company, current role, and engagement count.
Who at Acme has engaged with my content?
Input
| field | type | req | notes |
|---|---|---|---|
| company_url | string | no | Company URL (mutually exclusive) |
| company_id | string | no | companies.id (mutually exclusive) |
| relation | enum | no | default: any (coworker, alumni, any) |
| limit | number | no | default: 20 (1–100) |
Returns
company— Object — id, name, linkedin_url, page_type, industry_hierarchyrelation— stringtotal_engagers— numberengagers— Array — person details + title_at_company, is_current_at_company, engagement_count_meta— Object
Errors
404— Company not found
get_engager_position_history free
Career history of a person who has engaged with your posts. Engagement gate: only available for people who actually engaged (not arbitrary LinkedIn profiles).
Input
| field | type | req | notes |
|---|---|---|---|
| person_id | string | no | people.id (mutually exclusive) |
| linkedin_url | string | no | Profile URL (mutually exclusive) |
Returns
person— Object — id, name, linkedin_url, headline, current_company, current_title, locationpositions— Array — title, company_name, company_id, is_current, started_at, ended_at, source_tool_meta— Object
Errors
404— Person not found400— Person has not engaged on your posts (engagement gate)
get_target_warmth_brief free
For an engager, return their engagement summary against your posts: warmth score (0–1.0, v0), reaction/comment counts, first and most recent engagement dates, and the actual posts they touched. Use to qualify a warm DM.
How warm is this person before I reach out?
Input
| field | type | req | notes |
|---|---|---|---|
| person_id | string | no | people.id (mutually exclusive) |
| linkedin_url | string | no | Profile URL (mutually exclusive) |
| days_back | number | no | default: 90 (1–365) |
Returns
target— Object — id, name, headline, linkedin_url, current_company, current_title, locationwarmth_score— number — 0–1.0 (v0)engagement_count— Object — reactions, comments, totalfirst_engagement— string (ISO)most_recent_engagement— string (ISO)posts_engaged— Array — per-post engagement details_meta— Object
Errors
404— Person not found
get_company_engagement_overlap free
Cross-company intel: people who have engaged with both Company A's and Company B's posts in your library. Returns engagement counts per company and totals.
Input
| field | type | req | notes |
|---|---|---|---|
| company_a_id | string | no | Company A id (exactly one of id/url) |
| company_a_url | string | no | Company A URL (exactly one of id/url) |
| company_b_id | string | no | Company B id (exactly one of id/url) |
| company_b_url | string | no | Company B URL (exactly one of id/url) |
| limit | number | no | default: 20 (1–100) |
Returns
company_a— Object — id, name, linkedin_url, page_type, industry_hierarchycompany_b— Object — same shapeoverlap_count— numberengagers_on_a_only— numberengagers_on_b_only— numberengagers— Array — per-person engagement counts to each company_meta— Object
Errors
404— Company A or B not found400— Must provide exactly one of (id/url) for each company
get_outreach_path free
Find warm-intro paths to a target person via coworker/alumni edges in your engagement graph. Configurable max hops (1–3). Returns ranked paths grouped by hop count.
Who's my warmest path to this VP?
Input
| field | type | req | notes |
|---|---|---|---|
| target_person_id | string | no | Target id (mutually exclusive) |
| target_linkedin_url | string | no | Target URL (mutually exclusive) |
| max_hops | number | no | default: 2 (1–3) |
| limit | number | no | default: 10 (1–100 paths) |
Returns
target— Object — id, name, linkedin_url, current_company, current_titlemax_hops— numberpaths— Array — warm_engager + steps + hopspaths_by_hop_count— Object — keyed by hop count_meta— Object
Errors
404— Target person not found
Graph traversal
experimental
Run read-only SQL queries against a sandboxed view of your data. Useful for exploration when the higher-level tools don't fit. v0: validation is regex-based (substring match on caller IDs, keyword filtering); real RLS lands later. Treat as experimental and expect rough edges.
2 tools
traverse_graph_help free
Returns the table schema, FK edges, your caller identifiers (caller_user_ids and tracked_lp_ids that traverse_graph requires you to reference), example queries, and the validation constraints. Call this first.
Show me the graph schema and an example query.
Returns
tables— Object — schema for posts, post_engagements, people, person_positions, companies, linkedin_profiles, tracked_profilesfk_edges— Array[string] — FK relationshipsexamples— Array — 5 canonical SQL examplescaller_user_ids— Array[string] — your user_ids (email-shared)caller_tracked_lp_ids— Array[string] — your tracked LinkedIn profile idsrls_notes— stringconstraints— Object — forbidden_keywords, must_start_with, max_rows, statement_timeout_seconds_meta— Object
traverse_graph free
Execute a single SELECT (or WITH... SELECT) against the graph. Must reference one of your caller_user_ids or tracked_lp_ids — otherwise rejected. INSERT / UPDATE / DELETE / DDL are blocked. Row cap 1000; statement timeout enforced.
Run a custom query: people who engaged with at least 3 of my posts in the last 60 days.
Input
| field | type | req | notes |
|---|---|---|---|
| sql | string | yes | SELECT or WITH; must reference caller_user_id or tracked LP id; min 10 chars |
Returns
rows— Array — result rows from queryrow_count— numbergenerated_sql— string — echoed backelapsed_ms— number_meta— Object_warnings— Array — present if row count capped at 1000
Errors
400— SQL does not start with SELECT or WITH400— SQL contains forbidden keywords (INSERT, UPDATE, DELETE, etc.)400— SQL does not reference caller_user_id or tracked LP id400— Query execution error
Admin & billing
Visibility into credit balance, tool pricing, and recent usage.
3 tools
get_credit_balance free
Return the authenticated user's current credit balance, this period's monthly allocation, and credits used since the period started.
How many credits do I have left?
Returns
balance— numbermonthly_allocation— Object — amount, plan_type, period_start, period_end (or null)used_this_period— number
get_cost_estimate free
Given an MCP tool name, return its credit cost so you can preview an action before running it. Returns { tool_name, cost, balance, sufficient }.
What will map_constellation cost me on Acme?
Input
| field | type | req | notes |
|---|---|---|---|
| tool_name | string | yes | MCP tool name |
| params | object | no | Reserved for future per-call estimation |
Returns
tool_name— stringcost— number — credits (0 if not in registry)balance— numbersufficient— boolean — balance >= costknown_tool— boolean
get_usage_history free
Recent credit_ledger transactions for the authenticated user. Filter by tool, reason, or date range. Paginated.
Input
| field | type | req | notes |
|---|---|---|---|
| tool_name | string | no | Filter to a tool |
| reason | enum | no | monthly_grant, pack_purchase, tool_usage, refund, adjustment |
| date_from | string | no | ISO 8601 start |
| date_to | string | no | ISO 8601 end |
| limit | number | no | default: 50 (1–200) |
Returns
transactions— Array — id, amount, balance_after, reason, tool_name, stream_id, metadata, created_atmeta— Object — count, filters_applied
Errors
400— Query error
Workflow builder
Wires Flux into daily routines. Morning ritual: ask Claude what moved overnight, which drafts are worth finishing, who's worth reaching out to. The dashboard becomes optional.
Agency
Lets clients query their own data without learning a dashboard. Every client gets a key; Claude becomes the universal interface across the book of business.
Operator
Automates repeat analyses. Weekly engagement reviews, quarterly content retros, monthly outreach stand-ups — all scripted as prompts Claude reruns on demand.
One sentence away from your data.
Edge is $15/month. Cancel anytime. Connect Claude the moment you subscribe.