Prosp MCP Server
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| PROSP_API_KEY | Yes | Your API key | |
| PROSP_TIMEOUT | No | Request timeout in seconds | 30 |
| PROSP_API_BASE | No | API base URL | https://prosp.ai/api/v1 |
| PROSP_LOG_LEVEL | No | DEBUG, INFO, WARNING, ERROR | WARNING |
| PROSP_READ_ONLY | No | Block every write tool | false |
| PROSP_MAX_LEADS_PER_CALL | No | Batch size cap | 200 |
| PROSP_DAILY_MESSAGE_BUDGET | No | Refuse volumes above this | 20 |
| PROSP_DAILY_CONNECTION_BUDGET | No | Refuse volumes above this | 20 |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
| logging | {} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| list_accountsA | List the LinkedIn accounts connected to this Prosp workspace. Returns each account's id, name, connection status, plan tier, and whether it is currently restricted or paused. Call this before anything else in a session. Every other tool needs an account_id, and the daily budget is per account rather than per workspace. |
| get_account_budgetA | Show what daily send budget is left on one account, across all campaigns. This is the number that governs every sending decision. LinkedIn's recommended limits are ACCOUNT-WIDE, not per campaign, so three campaigns set to 20 connection requests each means the account attempts 60 a day. Call this before proposing any volume, and before launching a campaign on an account that already has one running. |
| get_account_healthA | Check one account for the conditions that stop a campaign working. Reports: connection status, whether the session needs refreshing, whether the account is capped or restricted, how many campaigns are active on it, and the combined daily volume those campaigns are configured to send. The last field is the one that matters. An account with three campaigns at 20 each is configured to exceed the ceiling even though each campaign looks reasonable on its own. |
| list_lead_listsB | List the lead lists in this workspace, newest first. Returns each list's id, name, lead count, source type and creation date. |
| get_lead_listA | Get one lead list with its lead count and a breakdown by lead state. The state breakdown is the useful part: Not Contacted, In Campaign, Contacted, Not Accepted, Replied, Duplicate, Blacklist and Failed. A list with a large Not Accepted count relative to Contacted points at the connection note or the list quality, not the sequence. |
| create_lead_listC | Create an empty lead list. Name it after the campaign and the signal type rather than the channel. "q3-saas-founders-job-post-trigger" is answerable in three months; "LinkedIn leads" is not. |
| import_from_postA | Import the people who engaged with a LinkedIn post into a list. This is the highest-intent cold source available. Someone who commented on a post about the exact problem you solve has done something; someone who matches a search filter has not. include_future_reactions keeps the import open, so engagement arriving days later is pulled in without anyone touching it. Leave it on for a post that is still travelling. Importing costs nothing. The capped resource is sending, so import broad and filter at the send step rather than the import step. |
| import_from_searchB | Import leads from a LinkedIn or Sales Navigator search URL. Weaker intent than a post import. Use it when there is no relevant post, and expect to filter harder afterwards. |
| import_leadsB | Import leads from structured data. Each lead needs a linkedin_url. Any other key becomes a custom variable usable in message prompts, so a signal column recorded during research travels with the lead into the copy. Example lead: {"linkedin_url": "...", "first_name": "...", "signal": "hiring a RevOps lead, posted 14 Mar", "signal_url": "...", "tier": "1"} |
| set_lead_stateC | Change one lead's state. Use blacklist for anyone who asked not to be contacted. That is a boundary, not a pause, and it should survive every future campaign. |
| get_leadA | Get one lead: profile fields, state, campaign membership, and custom variables. Custom variables are whatever was imported alongside the lead, so a signal recorded during research shows up here and can be referenced in copy. |
| search_leadsA | Search a list by state or tag. Valid states: not_contacted, in_campaign, contacted, not_accepted, replied, duplicate, blacklist, failed. Searching for state="replied" is the fastest way to find everyone worth a human reply today. Searching not_accepted after 14 days tells you whether the connection note is working. |
| add_tagB | Tag a lead. Tag by signal type and campaign rather than by channel. The question worth being able to answer later is which trigger produced the booked meetings, and that is unanswerable without this field. Tag anyone who books a call, so the sequence stops. A follow-up landing after someone has booked is the most avoidable bad impression in outreach. |
| list_campaignsA | List campaigns, optionally filtered by account or status. Run this before creating anything. The combined daily volume of everything already active on an account is the number that decides how much headroom a new campaign actually has. |
| get_campaignB | Get one campaign: its node sequence, daily limits, source list and status. |
| get_campaign_statsB | Get the figures no CRM holds: requests sent and accepted, messages sent, replies. These are the inputs to the diagnostic chain, which is worked in order and stopped at the first failure: 1 Acceptance below 15% the note, or the list. NOT the sequence. 2 Acceptance fine, replies below 10% the first message. 3 Replies fine, meetings low the ask is mistimed, or the offer is wrong. 4 Meetings fine, nothing closing not an outreach problem. Price or fit. 5 All fine, volume low the daily cap split across campaigns. Report the failing stage and one change. Never more than one change a week: change three and a lift tells you nothing about which one worked. |
| create_campaignA | Create a campaign from a node sequence. Starts paused. NODES. Each node is {"action": ..., "delay_days": ..., "config": {...}} or {"condition": ..., "yes": [...], "no": [...]}. Available actions: connection_request, message, voice_note, inmail, open_profile_message, comment_last_post, reply_comment, like_last_post, visit_profile, wait, add_tag. Available conditions: has_linkedin_url, is_first_level, opened_message, is_open_profile, check_column. THE STANDARD SHAPE: 1 Condition: is_first_level 2 YES branch: message 3 NO branch: connection_request, then message on acceptance 4 Wait 3 days, follow-up on a different angle 5 add_tag TWO RULES THE BUILDER WILL NOT ENFORCE FOR YOU: No wait node after a connection_request. Acceptance auto-detects over two weeks, checking every 24 hours with a random delay. A wait node there does nothing except delay the sequence by days, and it is the most common unnecessary node people add. Four touches maximum. After that the answer is no, and a fifth touch costs more in reputation than it returns in replies. The daily limits default deliberately low. A new account should start at 10 connection requests a day and build to 20 over a fortnight, because a profile with no sending history suddenly running at full rate is the clearest possible pattern. |
| set_campaign_statusA | Start, pause or archive a campaign. Valid: active, paused, archived. Pausing is always safe and never needs justifying. Starting reaches real people, so it needs confirm=true. |
| set_daily_limitsA | Change a campaign's daily limits. Check get_account_budget first. These limits are per campaign but the ceiling they consume is per account, so raising one campaign silently takes headroom from every other campaign on that profile. |
| get_inboxB | Read the unified inbox across every connected account. Leave account_id empty to see everything in one queue rather than logging into each profile in turn. That is what makes a daily reply pass one task for an agency running eight client accounts. |
| get_conversationA | Read one full conversation thread, with the lead's profile and campaign context. Read the whole thread before drafting. A reply that ignores what was already said reads worse than no reply. |
| send_replyA | Send a reply in an existing conversation. Requires confirm=true. BEFORE DRAFTING, classify the reply into exactly one of: INTERESTED wants more, asks about the offer TIMING interested, not now. Capture the date they named. OBJECTION price, fit, incumbent, capacity WRONG_PERSON not their remit. Ask who owns it. NOT_INTERESTED clear no. Thank them, stop, never pitch again. AUTO_REPLY out of office. Reschedule to their return date. ESCALATE anything below 8 confidence Below 8 confidence, escalate to a human rather than guessing. Sarcasm, brevity and politeness all read the same in text, and a misread reply going out under someone's name is theirs to apologise for. Never send to NOT_INTERESTED. A human closes that loop. MATCH THEIR REGISTER. Reply within roughly 20% of their message length. A three-line reply to a six-word message reads as eager; a six-word reply to three paragraphs reads as dismissive. ONE QUESTION ONLY. Two gets you an answer to the easier one. Three gets you nothing, because now it is work. |
| mark_readA | Mark a conversation as read, without replying. Use it for auto-replies and anything already handled elsewhere, so the unread queue stays a real to-do list. |
| get_workspace_statsA | Get figures across every account and campaign, for a date range. Dates are ISO, YYYY-MM-DD. Omit both for the last 30 days. Report percentages beside their absolutes. Up 40% from 5 to 7 is a different sentence from 500 to 700, and a report that only shows the percentage has said almost nothing. |
| diagnose_campaignA | Run the diagnostic chain against one campaign and return the failing stage. Works the chain in order and stops at the first failure, rather than returning five stages of numbers when the first one is broken. The output names one stage, the evidence, and one change. If figures are incomplete it says which stage cannot be assessed, because a diagnosis on partial data points at the wrong stage and that is worse than no diagnosis. |
| signal_attributionA | Report which signal type and campaign produced the booked meetings. This is the single most useful line in any monthly report and the one most likely to be skipped, because it produces one sentence rather than a dashboard. It only works if leads were tagged with their signal type at import. If the output is empty, that is the finding: fix the tagging before next month. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 26 tools
Tools are mostly distinct across accounts, campaigns, leads, inbox, and analytics. The only mild overlap is between account-level operational checks like get_account_budget and get_account_health, and between campaign/workspace reporting tools, but descriptions clarify their separate purposes.
The set follows a strong snake_case verb_noun pattern: list_, get_, set_, create_, import_, search_, add_, send_, mark_, diagnose_. The main deviation is signal_attribution, which is noun-only rather than starting with a verb like get_, but otherwise naming is predictable.
26 tools is heavy for a single MCP server and exceeds the typical 3-15 range. The domain is broad enough that most tools earn their place, but the surface sits at the upper edge of reasonable and includes several reporting/account checks that could potentially be consolidated.
Coverage spans the core outreach lifecycle: account health and budgets, lead lists/imports/tagging, campaign creation/limits/status, inbox replies, and diagnostics with signal attribution. Minor gaps exist around editing an existing campaign's node sequence and explicit lead/list deletion, but these are largely workaround-able.