Edge feature

Claude, let's write a LinkedIn post.

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

The best dashboard isn’t a dashboard.

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.

Vignettes

Three ways people are using it today.

Writing, researching, and synthesizing — each backed by your own Flux data instead of whatever Claude happens to guess.

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.

Setup · 5 minutes

Get Claude talking to your data.

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.

  1. 1

    Generate an API key

    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.

    Flux Settings page, API Keys section with a 'Generate New Key' button and a collapsed Setup guide
    Settings → API Keys
  2. 2

    Add Flux to your MCP client config

    For Claude Code, run this one-liner (replacing YOUR_API_KEY):

    terminal
    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):

    claude_desktop_config.json
    {
      "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):

    .mcp.json
    {
      "mcpServers": {
        "flux": {
          "type": "http",
          "url": "https://flux.elegantatomics.com/mcp",
          "headers": {
            "Authorization": "Bearer YOUR_API_KEY"
          }
        }
      }
    }
  3. 3

    Restart Claude Desktop

    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.

  4. 4

    Try it

    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.

Works with:Claude DesktopClaude CodeCursorZedAny MCP client

Tool reference

Every tool, grouped by job.

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

http
POST https://flux.elegantatomics.com/mcp
Authorization: Bearer flux_xxx
Content-Type: application/json

Envelope

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "<tool_name>",
    "arguments": { /* tool inputs */ }
  }
}

Example: list tracked profiles

bash
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 tools

Query your own post history — KPIs, trends, patterns, and semantic/keyword search.

get_postsfree

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_summaryfree

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_insightsfree

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_trendsfree

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_insightsfree

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_postsfree

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_postsfree

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

2 tools

Score drafts before you publish and generate fresh angles grounded in your top performers.

score_draftfree

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_angles5 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

8 tools

Always-on research streams — external profiles, companies, topics, hiring signals, ad watches — that pull on a schedule into your library.

list_profilesfree

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_streamsfree

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_streamfree

Create 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_feedfree

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_streamfree

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_streamfree

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_streamfree

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_now1–2 credits

Manually 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 tools

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.

list_collectionsfree

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_collectionfree

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_collectionfree

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
  • added — number — new members inserted
  • skipped — number — already members (deduped)
  • member_count — number — total after operation

Errors

  • 404 — Collection not found or not owned by you
remove_from_collectionfree

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_collectionfree

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_segmentsfree

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_segmentfree

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_segmentfree

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_segmentfree

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_segmentfree

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_templatesfree

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_post1 credit

Save 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_alertsfree

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 (HarvestAPI)

12 tools

On-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 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_posts5 credits / page

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_posts5 credits / page

Fetch recent posts from a LinkedIn company page.

linkedin_post_search5 credits

Search LinkedIn posts by keyword. Returns a single page of matching posts.

linkedin_profile_reactions5 credits

Fetch the recent posts a LinkedIn person has reacted to. Useful for inferring interests.

linkedin_profile_comments5 credits

Fetch the recent posts a LinkedIn person has commented on. Useful for inferring interests and conversation partners.

linkedin_post_reactions5 credits

Fetch the people who reacted to a single LinkedIn post (with reaction kind). Engagers are persisted to the post_engagements graph.

linkedin_post_comments5 credits

Fetch the people who commented on a single LinkedIn post (with comment text). Each comment is persisted to post_engagements.

linkedin_people_search5 credits

Search LinkedIn people by company, title, location, or keywords. Returns a single page of profiles.

linkedin_company_search5 credits

Search LinkedIn companies by keywords, industry, or location. Returns a single page of companies.

linkedin_job_search5 credits

Search LinkedIn job postings. Useful for tracking hiring signals at target companies.

linkedin_ad_search10 credits

Search the LinkedIn ad library. Useful for tracking competitor ad creative and messaging.

Constellation (warm outreach)

8 tools

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.

create_campaignfree

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_accountsfree

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_constellationup 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_connectionsfree

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_queuefree

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_brieffree

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_outcomefree

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_statsfree

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

8 tools

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.

get_post_engagers_by_companyfree

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_engagers2 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_breakdownfree

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_engagersfree

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_historyfree

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_brieffree

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_overlapfree

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_pathfree

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

experimental2 tools

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.

traverse_graph_helpfree

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_graphfree

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

3 tools

Visibility into credit balance, tool pricing, and recent usage.

get_credit_balancefree

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_estimatefree

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_historyfree

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

Who it’s for

Three kinds of people get the most out of it.

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.

FAQ

Questions.

One sentence away from your data.

Edge is $10/month. Cancel anytime. Your MCP key is ready the moment you land in Settings.