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 sessionLinkedIn API with OAuthFlux (hosted)
How it reaches LinkedInAutomates a browser or reuses your cookieLinkedIn’s API, under your authorizationA third-party provider of public data
Whose account is exposedYoursYours, within the permissions you grantNot yours, because you connect no LinkedIn account
Other people’s postsWhatever your session can seeVery limitedAny public profile or company page
Stored history and trendsUsually noneUsually noneYes, on paid plans
Can post or messageOftenSometimes (posting)No, read-only on LinkedIn
SetupLocal install and upkeepYour own LinkedIn developer app, usuallyPaste one URL
CostUsually free softwareUsually free softwareFree 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. 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. 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. 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. 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. 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. 2 Run this, replacing YOUR_API_KEY:
    claude mcp add --transport http --scope user flux \
      https://www.fluxgraph.app/mcp \
      --header "Authorization: Bearer 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.
  3. 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. 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. 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. 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. 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. 2 Add this to your Zed settings.json:
    {
      "context_servers": {
        "flux": {
          "url": "https://www.fluxgraph.app/mcp",
          "headers": {
            "Authorization": "Bearer YOUR_API_KEY"
          }
        }
      }
    }
    
  3. 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. 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. 2 Most clients read this shape:
    {
      "mcpServers": {
        "flux": {
          "type": "http",
          "url": "https://www.fluxgraph.app/mcp",
          "headers": {
            "Authorization": "Bearer YOUR_API_KEY"
          }
        }
      }
    }
    
    Calling the server from your own code? See Calling tools directly (HTTP) below.
  3. 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

fieldtypereqnotes
profile_idstringyesTracked profile ID from list_profiles
scopestringnoOptional post_collections.id to filter
date_fromstringnoStart date (ISO 8601)
date_tostringnoEnd date (ISO 8601)
post_typeenumnotext, image, video, document, article, poll
min_engagementnumbernoMinimum total engagement
searchstringnoText search across post content
sort_byenumnodefault: published_at
sort_direnumnodefault: desc
pagenumbernodefault: 1
page_sizenumbernodefault: 25 (1–50)

Returns

  • posts — Array — post objects with id, metrics, text content
  • meta — 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

fieldtypereqnotes
profile_idstringyesTracked profile ID from list_profiles

Returns

  • total_posts — number
  • avg_engagement — number
  • avg_likes — number
  • avg_comments — number
  • avg_shares — number
  • conversation_rate — number — (comments / likes) * 100
  • posts_per_week — number
  • date_range — Object — earliest, latest
  • engagement_trend — Object — direction, change_pct, 30d averages
  • top_format — Object | null
  • posting_goal — Object — goal_per_week, posts_this_week, on_track
  • links — 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

fieldtypereqnotes
profile_idstringyesTracked profile ID from list_profiles
scopestringnoOptional post_collections.id to scope analysis
date_fromstringnoStart date (ISO 8601)
date_tostringnoEnd date (ISO 8601)

Returns

  • sample_size — number — total posts analyzed
  • overall_avg_engagement — number
  • best_day — Object | null
  • best_hour — Object | null
  • best_format — Object | null
  • sweet_spot_length — Object | null
  • by_day_of_week — Array — sorted by avg_engagement
  • by_hour — Array — sorted by avg_engagement
  • by_format — Array
  • by_length — Array — 200-char bins
  • meta — 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

fieldtypereqnotes
profile_idstringyesTracked profile ID from list_profiles
scopestringnoOptional post_collections.id
granularityenumnodefault: weekly (daily, weekly, monthly)
date_fromstringnoStart date (ISO 8601)
date_tostringnoEnd date (ISO 8601)
rolling_windownumberno2–30 buckets; default by granularity

Returns

  • series — Array — per-bucket metrics with rolling averages
  • summary — Object — direction, change_pct, period_comparison
  • meta — 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

fieldtypereqnotes
profile_idstringyesTracked profile ID from list_profiles
nnumbernodefault: 15 (1–100 max terms per list)
bigramsbooleannodefault: true
scopestringnoOptional post_collections.id
date_fromstringnoStart date (ISO 8601)
date_tostringnoEnd date (ISO 8601)

Returns

  • terms — Array — term, post_count, avg_engagement, vs_baseline, sample_post_url
  • bigrams — Array | null
  • total_posts — number
  • overall_avg_engagement — number
  • window — Object — from, to
  • meta — 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

fieldtypereqnotes
profile_idstringyesTracked profile ID from list_profiles
querystringyesSearch query
scopestringnoOptional post_collections.id
modeenumnodefault: hybrid (hybrid, keyword, semantic)
limitnumbernodefault: 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 owned
  • 400 — 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

fieldtypereqnotes
textstringyesText to find similar posts for (min 1 char)
profile_idstringnoOptional — scope to this profile's posts
collection_idstringnoOptional — scope to this collection
limitnumbernodefault: 5 (1–50)

Returns

  • posts — Array — sorted by embedding similarity
  • count — number
  • cost — number — 0 (free)

Errors

  • 403 — Profile or collection not found/not owned
  • 400 — 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

fieldtypereqnotes
textstringyesDraft post text (min 1 char)
formatenumnotext | image | video | document | article | poll (default: text)
day_of_weeknumberyes0–6, 0=Sunday (UTC)
hournumberyes0–23 (UTC)
profile_idstringnoOptional — scope model to this profile
collection_idstringnoOptional — scope model to this collection

Returns

  • percentile — number — predicted engagement percentile (0–100)
  • stars — string — qualitative band
  • range — Object — low/high projected engagement
  • factors — Array — per-feature contribution
  • similar_posts — Array — nearest historical posts with their percentile
  • suggestions — Array — actionable improvements
  • model — 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, links
  • meta — 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

fieldtypereqnotes
typeenumnoown_profile, external_profile, company, topic, person_interests, hiring_signals, ad_watch
include_inactivebooleannodefault: false

Returns

  • streams — Array — id, type, name, source_url, params, schedule, active, credits_per_run, last/next run, links
  • meta — Object — count
  • links — 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

fieldtypereqnotes
stream_idstringyesStream ID from list_streams
limitnumbernodefault: 20 (1–50)

Returns

  • stream — Object — id, type, name
  • posts — Array — recent posts (newest first)
  • meta — Object — count, limit
  • links — 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

fieldtypereqnotes
stream_idstringyesStream 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

fieldtypereqnotes
stream_idstringyesStream 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

fieldtypereqnotes
stream_idstringyesStream ID from list_streams

Returns

  • deleted — boolean — true on success
  • stream_id — string

Errors

  • 404 — Stream not found or not owned by you
  • 403 — 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

fieldtypereqnotes
typeenumnomanual, smart, auto_stream

Returns

  • collections — Array — id, name, type, config, stream_id, created_at, member_count, links
  • meta — Object — count
  • links — 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

fieldtypereqnotes
namestringyes1–200 chars
descriptionstringnomax 2000 chars
typeenumyesmanual, smart
configobjectnoPredicate (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

fieldtypereqnotes
collection_idstringyesTarget collection (UUID)
post_idsarrayyesPost UUIDs to add (1–1000 per call)

Returns

  • collection_id — string
  • pinned — number — posts newly pinned to the collection
  • skipped — number — already members (deduped)
  • member_count — number — total after operation
  • resolved_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

fieldtypereqnotes
collection_idstringyesTarget collection (UUID)
post_idsarrayyesPost UUIDs to remove (1–1000 per call)

Returns

  • collection_id — string
  • removed — number — members deleted
  • not_found — number — not members
  • member_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

fieldtypereqnotes
collection_idstringyesCollection (UUID)
limitnumbernodefault: 1000 (1–5000)

Returns

  • collection_id — string
  • type — string — manual, smart, or auto_stream
  • post_ids — Array
  • count — number
  • config — Object (smart collections only)
  • warnings — Array — predicate-evaluation warnings
  • links — 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

fieldtypereqnotes
typeenumnomanual, smart, auto_stream

Returns

  • segments — Array — id, name, description, type, config, source_stream_id, created_at, member_count, links
  • meta — Object — count
  • links — 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

fieldtypereqnotes
namestringno1–200 chars; optional if template supplied
descriptionstringnomax 2000 chars
typeenumnomanual, smart, auto_stream; defaults to smart with template
templateenumnoPre-built template id (pre-fills config)
configobjectnoPredicate (required when type=smart)
source_stream_idstringnoOptional 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=smart
  • 404 — 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

fieldtypereqnotes
segment_idstringyesTarget segment (UUID)
person_idsarrayyesPerson UUIDs to add (1–1000 per call)

Returns

  • segment_id — string
  • added — number — new members inserted
  • skipped — 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

fieldtypereqnotes
segment_idstringyesTarget segment (UUID)
person_idsarrayyesPerson UUIDs to remove (1–1000 per call)

Returns

  • segment_id — string
  • removed — number — members deleted
  • not_found — number — not members
  • member_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

fieldtypereqnotes
segment_idstringyesSegment (UUID)
limitnumbernodefault: 1000 (1–5000)

Returns

  • segment_id — string
  • type — string — manual, smart, or auto_stream
  • person_ids — Array
  • count — number
  • config — Object (smart segments only)
  • warnings — Array — predicate-evaluation warnings
  • links — 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, config
  • meta — 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

fieldtypereqnotes
unread_onlybooleannodefault: true
limitnumbernodefault: 50 (1–200)

Returns

  • alerts — Array — id, stream_id, stream_name, items_new, message, read_at, created_at, links
  • meta — Object — count, unread_only
  • links — 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

fieldtypereqnotes
namestringyes1–200 chars
descriptionstringnomax 2000 chars

Returns

  • campaign — Object — id, name, description, status, created_at
  • credits_used — number — 0
  • monthly_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

fieldtypereqnotes
campaign_idstringyesTarget campaign (UUID)
accountsarrayyes1–500 per call; each: company_name, linkedin_company_id?, employee_count?, tier?

Returns

  • campaign_id — string (UUID)
  • added — number — inserted rows
  • accounts — Array — id, company_name, linkedin_company_id, tier, status, created_at

Errors

  • 404 — Campaign not found or not owned by user
  • 400 — 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

fieldtypereqnotes
campaign_idstringyesCampaign 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

fieldtypereqnotes
campaign_idstringnoFull Constellation scoring (mutually exclusive)
segment_idstringnoEngagement-count ranking (mutually exclusive)
linkedin_urlsarraynoAd-hoc URLs, max 200 (mutually exclusive)
limitnumbernodefault: 50 (1–200)
poolenumnocoworker, engager, mutual — campaign_id only

Returns

  • scope — string — campaign, segment, or linkedin_urls
  • scoring — string — composite or engagement_count
  • count — number
  • queue — Array — shape varies by scope
  • unresolved — 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

fieldtypereqnotes
target_idstringnoConstellation targets.id (mutually exclusive)
person_idstringnopeople.id (mutually exclusive)
linkedin_urlstringnoProfile URL (mutually exclusive)

Returns

  • scope — string — target, person, or linkedin_url
  • target_id — string (UUID) | null
  • target — Object — full_name, headline, current_title, current_company, linkedin_url
  • count — number
  • posts — Array — post_id, url, published_at, excerpt, engagement, similarity, talking_points

Errors

  • 400 — Must provide exactly one of target_id, person_id, linkedin_url
  • 404 — 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

fieldtypereqnotes
campaign_idstringyesCampaign id (UUID)
person_idstringyespeople.id (UUID)
actionenumyessent_request, accepted, replied, no_response
notestringnomax 4000 chars

Returns

  • entry — Object — id, campaign_id, person_id, action, note, created_at

Errors

  • 404 — Campaign not found or not owned by user
  • 400 — 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

fieldtypereqnotes
campaign_idstringyesCampaign id (UUID)

Returns

  • campaign — Object — id, name, status, created_at
  • totals — Object — accounts, targets, entries, outreach counts by status
  • acceptance_rate — number | null
  • reply_rate — number | null
  • by_pool — Object — per pool: sent, accepted, replied, rates
  • by_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

fieldtypereqnotes
post_urlstringnoPost URL (mutually exclusive with post_id)
post_idstringnoposts.id (mutually exclusive with post_url)
industry_urnstringnoOptional urn:li:fsd_industry:* filter
limitnumbernodefault: 20 (1–100)
top_engagers_per_companynumbernodefault: 3 (0–10)

Returns

  • post_id — string (UUID)
  • post_url — string
  • total_engagers — number
  • filtered_engagers — number
  • companies — Array — company_id, name, industry_hierarchy, engager_count, top_engagers
  • _meta — Object

Errors

  • 404 — Post not found in your library or tracked profiles
  • 400 — 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

fieldtypereqnotes
post_urlstringnoPost URL (mutually exclusive)
post_idstringnoposts.id (mutually exclusive)
depthnumbernodefault: 1 (1–3; 1=top-level, 3=leaf)
sample_companies_per_bucketnumbernodefault: 3 (0–10)

Returns

  • post_id — string (UUID)
  • post_url — string
  • total_engagers — number
  • depth — number
  • industries — Array — industry, industry_urn, engager_count, sample_companies
  • _meta — Object

Errors

  • 404 — Post not found
  • 400 — 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

fieldtypereqnotes
company_urlstringnoCompany URL (mutually exclusive)
company_idstringnocompanies.id (mutually exclusive)
relationenumnodefault: any (coworker, alumni, any)
limitnumbernodefault: 20 (1–100)

Returns

  • company — Object — id, name, linkedin_url, page_type, industry_hierarchy
  • relation — string
  • total_engagers — number
  • engagers — 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

fieldtypereqnotes
person_idstringnopeople.id (mutually exclusive)
linkedin_urlstringnoProfile URL (mutually exclusive)

Returns

  • person — Object — id, name, linkedin_url, headline, current_company, current_title, location
  • positions — Array — title, company_name, company_id, is_current, started_at, ended_at, source_tool
  • _meta — Object

Errors

  • 404 — Person not found
  • 400 — 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

fieldtypereqnotes
person_idstringnopeople.id (mutually exclusive)
linkedin_urlstringnoProfile URL (mutually exclusive)
days_backnumbernodefault: 90 (1–365)

Returns

  • target — Object — id, name, headline, linkedin_url, current_company, current_title, location
  • warmth_score — number — 0–1.0 (v0)
  • engagement_count — Object — reactions, comments, total
  • first_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

fieldtypereqnotes
company_a_idstringnoCompany A id (exactly one of id/url)
company_a_urlstringnoCompany A URL (exactly one of id/url)
company_b_idstringnoCompany B id (exactly one of id/url)
company_b_urlstringnoCompany B URL (exactly one of id/url)
limitnumbernodefault: 20 (1–100)

Returns

  • company_a — Object — id, name, linkedin_url, page_type, industry_hierarchy
  • company_b — Object — same shape
  • overlap_count — number
  • engagers_on_a_only — number
  • engagers_on_b_only — number
  • engagers — Array — per-person engagement counts to each company
  • _meta — Object

Errors

  • 404 — Company A or B not found
  • 400 — 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

fieldtypereqnotes
target_person_idstringnoTarget id (mutually exclusive)
target_linkedin_urlstringnoTarget URL (mutually exclusive)
max_hopsnumbernodefault: 2 (1–3)
limitnumbernodefault: 10 (1–100 paths)

Returns

  • target — Object — id, name, linkedin_url, current_company, current_title
  • max_hops — number
  • paths — Array — warm_engager + steps + hops
  • paths_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_profiles
  • fk_edges — Array[string] — FK relationships
  • examples — Array — 5 canonical SQL examples
  • caller_user_ids — Array[string] — your user_ids (email-shared)
  • caller_tracked_lp_ids — Array[string] — your tracked LinkedIn profile ids
  • rls_notes — string
  • constraints — 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

fieldtypereqnotes
sqlstringyesSELECT or WITH; must reference caller_user_id or tracked LP id; min 10 chars

Returns

  • rows — Array — result rows from query
  • row_count — number
  • generated_sql — string — echoed back
  • elapsed_ms — number
  • _meta — Object
  • _warnings — Array — present if row count capped at 1000

Errors

  • 400 — SQL does not start with SELECT or WITH
  • 400 — SQL contains forbidden keywords (INSERT, UPDATE, DELETE, etc.)
  • 400 — SQL does not reference caller_user_id or tracked LP id
  • 400 — 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 — number
  • monthly_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

fieldtypereqnotes
tool_namestringyesMCP tool name
paramsobjectnoReserved for future per-call estimation

Returns

  • tool_name — string
  • cost — number — credits (0 if not in registry)
  • balance — number
  • sufficient — boolean — balance >= cost
  • known_tool — boolean

get_usage_history free

Recent credit_ledger transactions for the authenticated user. Filter by tool, reason, or date range. Paginated.

Input

fieldtypereqnotes
tool_namestringnoFilter to a tool
reasonenumnomonthly_grant, pack_purchase, tool_usage, refund, adjustment
date_fromstringnoISO 8601 start
date_tostringnoISO 8601 end
limitnumbernodefault: 50 (1–200)

Returns

  • transactions — Array — id, amount, balance_after, reason, tool_name, stream_id, metadata, created_at
  • meta — 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.