Edge feature
Flux ships an MCP server. Point Claude Desktop, Cursor, or any MCP-compatible client at it and query your post history, prospect research, and constellation maps in natural language — or co-write your next post with Claude using your own data as context.
Why MCP matters
Vignettes
Writing, researching, and synthesizing — each backed by your own Flux data instead of whatever Claude happens to guess.
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.
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?
Writing a proposal
Find my 10 most-engaged posts about SaaS pricing. Summarize the core thesis across them.
Setup · 5 minutes
Flux exposes a single HTTP MCP endpoint at https://flux.elegantatomics.com/mcp. Auth is a bearer token — one API key per user, generated from Settings.
Log in at flux.elegantatomics.com/login, open Settings → API Keys, and click Generate. The key is shown once — copy it into your client config immediately. Keys start with flux_. You can revoke and regenerate at any time.

For Claude Code, run this one-liner (replacing YOUR_API_KEY):
claude mcp add --transport http --scope user flux \ https://flux.elegantatomics.com/mcp \ --header "Authorization: Bearer YOUR_API_KEY"
For Claude Desktop, edit the config at ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"flux": {
"type": "http",
"url": "https://flux.elegantatomics.com/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}For Cursor, Zed, or any other client that reads .mcp.json, drop the same block at the root of your project (or in the client’s MCP config directory):
{
"mcpServers": {
"flux": {
"type": "http",
"url": "https://flux.elegantatomics.com/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}Fully quit and relaunch — Claude picks up new MCP servers on boot. In the chat composer you should see a tools indicator showing flux is connected.
Ask Claude: “List my tracked LinkedIn profiles.” It’ll call list_profiles and show you what’s wired up. From there, anything on the tool reference below is fair game.
Tool reference
Free tools show free; paid tools call out their credit cost. Each tool card has input fields, return keys, and any tool-specific errors. The JSON-RPC envelope and common error codes live in the first section below.
Calling tools directly (HTTP)
JSON-RPC 2.0
Most users will configure an MCP client (Claude Desktop, 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://flux.elegantatomics.com/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://flux.elegantatomics.com/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
7 toolsQuery your own post history — KPIs, trends, patterns, and semantic/keyword search.
get_postsfreeReturn 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_appliedErrors
404 — Collection not found (when scope provided)get_profile_summaryfreeKPI 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_insightsfreeOptimal 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 — ObjectErrors
403 — Profile or scope not found/not ownedget_engagement_trendsfreeEngagement 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_sizeErrors
403 — Profile or scope not found/not ownedget_topic_insightsfreeTop 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 — ObjectErrors
403 — Profile or scope not found/not ownedsearch_postsfreeSearch 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, scopeErrors
403 — Profile or scope not found/not owned400 — Query required, or embedding generation failedfind_similar_postsfreeFind 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 embeddingPrediction & drafting
2 toolsScore drafts before you publish and generate fresh angles grounded in your top performers.
score_draftfreePredict 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², calibrationErrors
insufficient_data — not enough historical posts in scope to train; no charge.suggest_angles5 creditsGiven 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
8 toolsAlways-on research streams — external profiles, companies, topics, hiring signals, ad watches — that pull on a schedule into your library.
list_profilesfreeList 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 — countErrors
401 — Unauthorized (missing userId)list_streamsfreeList 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_allcreate_streamfreeCreate a new research stream — the create call itself is free. Each scheduled run costs credits per STREAM_RUN_COSTS; 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_feedfreeReturn 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) — viewErrors
404 — Stream not found or not owned by youpause_streamfreePause 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 youresume_streamfreeResume 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_atErrors
404 — Stream not found or not owned by youdelete_streamfreeDelete 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 — stringErrors
404 — Stream not found or not owned by you403 — own_profile streams cannot be deletedrun_stream_now1–2 creditsManually trigger a stream run instead of waiting for its cron tick. Charges per STREAM_RUN_COSTS (1 credit/run for most types, 2 for person_interests). Useful when you want fresh results before a scheduled run.
Run my hiring-signals stream now.
Collections & Segments
13 toolsCollections group posts; segments group people. Both can be smart (predicate-driven) or manual, and both can be resolved into concrete IDs for downstream tools.
list_collectionsfreeList 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_allcreate_collectionfreeCreate 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, linksErrors
400 — config required when type=smartadd_to_collectionfreeAdd 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 — stringadded — number — new members insertedskipped — number — already members (deduped)member_count — number — total after operationErrors
404 — Collection not found or not owned by youremove_from_collectionfreeRemove 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 operationErrors
404 — Collection not found or not owned by youresolve_collectionfreeResolve 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) — viewErrors
404 — Collection not found or not owned by youlist_segmentsfreeList 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_allcreate_segmentfreeCreate 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, linksErrors
400 — name/type required (or pass template); config required when type=smart404 — source_stream_id or template id not foundadd_to_segmentfreeAdd 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 — numberErrors
404 — Segment not found or not owned by youremove_from_segmentfreeRemove 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 — numberErrors
404 — Segment not found or not owned by youresolve_segmentfreeResolve 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) — viewErrors
404 — Segment not found or not owned by youlist_segment_templatesfreeList 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 — countsave_post1 creditSave a LinkedIn post to your library by URL. Resolves the post via HarvestAPI 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_alertsfreeReturn 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_allErrors
400 — Query errorResearch (HarvestAPI)
12 toolsOn-demand lookups against LinkedIn data via HarvestAPI. 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.
linkedin_profile_info5 creditsResolve 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_posts5 credits / pageFetch 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_posts5 credits / pageFetch recent posts from a LinkedIn company page.
linkedin_post_search5 creditsSearch LinkedIn posts by keyword. Returns a single page of matching posts.
linkedin_profile_reactions5 creditsFetch the recent posts a LinkedIn person has reacted to. Useful for inferring interests.
linkedin_profile_comments5 creditsFetch the recent posts a LinkedIn person has commented on. Useful for inferring interests and conversation partners.
linkedin_post_reactions5 creditsFetch the people who reacted to a single LinkedIn post (with reaction kind). Engagers are persisted to the post_engagements graph.
linkedin_post_comments5 creditsFetch the people who commented on a single LinkedIn post (with comment text). Each comment is persisted to post_engagements.
linkedin_people_search5 creditsSearch LinkedIn people by company, title, location, or keywords. Returns a single page of profiles.
linkedin_company_search5 creditsSearch LinkedIn companies by keywords, industry, or location. Returns a single page of companies.
linkedin_job_search5 creditsSearch LinkedIn job postings. Useful for tracking hiring signals at target companies.
linkedin_ad_search10 creditsSearch the LinkedIn ad library. Useful for tracking competitor ad creative and messaging.
Constellation (warm outreach)
8 toolsMap 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.
create_campaignfreeCreate 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 — ObjectErrors
400 — Database insert failureadd_campaign_accountsfreeAdd 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_atErrors
404 — Campaign not found or not owned by user400 — Database insert failuremap_constellationup to ~175 creditsMap 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_connectionsfreeRe-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-rankedErrors
404 — Campaign not found or not owned by userget_outreach_queuefreeReturn 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_urlsget_engagement_brieffreeFor 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_pointsErrors
400 — Must provide exactly one of target_id, person_id, linkedin_url404 — Target/person not foundlog_outcomefreeAppend 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_atErrors
404 — Campaign not found or not owned by user400 — Insert failureget_campaign_statsfreeSummary 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, ratesErrors
404 — Campaign not found or not owned by userEngagement graph
8 toolsRead-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.
get_post_engagers_by_companyfreeFor 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 — ObjectErrors
404 — Post not found in your library or tracked profiles400 — Must provide exactly one of post_url or post_idget_post_set_engagers2 credits / post + 3 / enrichConsolidated, 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_breakdownfreeHistogram 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 — ObjectErrors
404 — Post not found400 — Must provide exactly one of post_url or post_idget_alumni_engagersfreeFor 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 — ObjectErrors
404 — Company not foundget_engager_position_historyfreeCareer 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 — ObjectErrors
404 — Person not found400 — Person has not engaged on your posts (engagement gate)get_target_warmth_brieffreeFor 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 — ObjectErrors
404 — Person not foundget_company_engagement_overlapfreeCross-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 — ObjectErrors
404 — Company A or B not found400 — Must provide exactly one of (id/url) for each companyget_outreach_pathfreeFind 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 — ObjectErrors
404 — Target person not foundGraph traversal
experimental2 toolsRun 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.
traverse_graph_helpfreeReturns 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 — Objecttraverse_graphfreeExecute 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 1000Errors
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 errorAdmin & billing
3 toolsVisibility into credit balance, tool pricing, and recent usage.
get_credit_balancefreeReturn 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 — numberget_cost_estimatefreeGiven 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 — booleanget_usage_historyfreeRecent 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_appliedErrors
400 — Query errorWho it’s for
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.
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.
Automates repeat analyses. Weekly engagement reviews, quarterly content retros, monthly outreach stand-ups — all scripted as prompts Claude reruns on demand.
FAQ
Edge is $10/month. Cancel anytime. Your MCP key is ready the moment you land in Settings.