skyp claude skill.md
Skyp MCP Skill Guide
You are working with the Skyp MCP server — an email and LinkedIn campaign management platform that lets you create, manage, and analyze outreach campaigns programmatically.
Authentication
All tools require authentication via an API key passed in the MCP client config. If a tool returns an authentication error, the user needs to check their API key in Settings > API Keys on the Skyp dashboard.
Campaign Lifecycle
Campaigns follow a strict lifecycle. Always follow this order:
- Create the campaign (
create_new_campaign) - Add contacts (
add_contact_to_existing_campaign) - Generate a strategy (
generate_campaign_strategy) — this creates the sequence plan with timing and focus for each email - Review the strategy (
get_strategy) — present it to the user before proceeding - Finalize (
finalize_campaign) — this triggers AI message generation for all contacts and cannot be undone
Never finalize a campaign without contacts and a strategy. The campaign must have both before finalization will succeed.
Tool Reference
Campaigns
list_campaigns(skip?, limit?)— List all campaigns with status and metrics. Returns: id, name, description, status, contacts_count, sent/opens/clicks/replies/bounce counts.get_campaign_details(campaign_id)— Full campaign config: touches, max_words, closing_style, tone, timezone, sending_times, sending_days, plus all metrics.create_new_campaign(name, description?, touches?, max_words?, closing_style?, tone?, timezone?)— Create a campaign. Defaults: 3 touches, 80 max words, soft close, America/New_York timezone. Tone is a list of strings like["friendly", "professional"]. Closing style is one of:soft,mix,hard.update_existing_campaign(campaign_id, name?, description?, touches?, max_words?, closing_style?, tone?)— Update campaign config. Only provided fields change. Campaigns in active, evergreen, or completed status are locked — only status changes are allowed. Pause the campaign first to edit config.pause_email_campaign(campaign_id)— Pause an active or evergreen campaign. Halts all sending. The pre-pause status is saved so the campaign can be resumed to the correct state.resume_email_campaign(campaign_id)— Resume a paused campaign. Restores it to its pre-pause status (active or evergreen).finalize_campaign(campaign_id)— Start AI message generation. Campaign must have contacts and a strategy. This is irreversible — always confirm with the user first.get_campaign_messages(campaign_id, skip?, limit?)— Get sent messages with contact info, open/reply status, and full reply details including sentiment and interest level.get_campaign_threads(campaign_id, skip?, limit?)— Get conversation threads grouped by contact. Each thread shows all messages sent and replies received. Useful for reviewing full conversations.
Strategy
generate_campaign_strategy(campaign_id)— Generate an AI-powered sequence strategy. Creates a plan with gap timing (days between emails), focus area, and suggested CTA for each touch. Saves automatically.get_strategy(campaign_id)— Retrieve the saved strategy. Returns touches, total_days, strategy_summary, and per-message details (order, gap, focus, suggested_cta).
Contacts
list_contacts(skip?, limit?)— List all contacts with full details including twitter and timestamps.create_new_contact(email, first_name?, last_name?, title?, company?, location?, linkedin?, context?)— Create a contact. Email is required. Thecontextfield is used for AI email personalization — include relevant details about the contact here.update_existing_contact(contact_id, first_name?, last_name?, email?, title?, company?, location?, linkedin?, context?)— Update contact fields. Only provided fields change.delete_existing_contact(contact_id)— Permanently delete a contact. Cannot be undone.add_contact_to_existing_campaign(campaign_id, email, first_name?, last_name?, title?, company?, context?)— Add a contact to a campaign. Creates the contact if it doesn't exist. If the campaign is already active, this also triggers message generation for the new contact automatically.
Analytics
get_account_analytics()— Account-level metrics over the last 30 days: total_contacts, active_campaigns, emails_sent_30d, delivery_rate, open_rate, click_rate, reply_rate, bounce_rate, positive_replies, negative_replies, neutral_replies. Rates are percentages (0-100).
LinkedIn Campaigns
list_linkedin_campaigns()— List all LinkedIn campaigns with status and lead funnel metrics (pending, invite_sent, message_sent, replied).get_linkedin_campaign_details(campaign_id)— Full campaign config: session, messages, limits, scheduling, and lead funnel breakdown.create_linkedin_campaign(linkedin_session_id, name, followup_message, connection_note?, invites_per_launch?, weekly_invite_limit?, daily_message_limit?, timezone?, sending_hours_start?, sending_hours_end?, sending_days?)— Create a LinkedIn outreach campaign in draft status. Requires a LinkedIn session ID.connection_noteis the optional note with connection requests (max 300 chars).followup_messageis sent after connection is accepted. Defaults: 10 invites/launch, 100/week limit, 9-17 hours, weekdays only.update_linkedin_campaign(campaign_id, name?, connection_note?, followup_message?, invites_per_launch?, weekly_invite_limit?, daily_message_limit?, timezone?, sending_hours_start?, sending_hours_end?, sending_days?)— Update campaign settings. Only allowed when campaign is in draft or paused status.activate_linkedin_campaign(campaign_id)— Activate a campaign to start automated connection requests and followup messages. Requires an active LinkedIn session and at least one lead.pause_linkedin_campaign(campaign_id)— Pause an active campaign. Can be reactivated later.add_linkedin_leads(campaign_id, leads)— Bulk add up to 500 leads. Each lead requireslinkedin_url; optional:first_name,last_name,headline,company. Cannot add to completed campaigns.list_linkedin_leads(campaign_id, status_filter?)— List leads with optional status filter. Valid statuses:pending,invite_sent,message_sent,replied,invite_failed,message_failed,skipped.send_connection_request(linkedin_url, connection_note?)— Send a single LinkedIn connection request immediately. Uses the user's active LinkedIn session directly — no campaign required.connection_noteis an optional message (max 300 chars) included with the request.
Recommended Patterns
Before taking action, discover first
Always call list_campaigns or list_contacts before operating on a specific item. Use the returned IDs for subsequent calls. Never guess or hardcode IDs.
Use context for better personalization
When creating contacts, populate the context field with relevant details (recent achievements, shared connections, mutual interests). This is what the AI uses to personalize emails.
Batch contact additions
When adding multiple contacts to a campaign, call add_contact_to_existing_campaign for each one. There is no bulk endpoint — but each call is fast and will create the contact if it doesn't exist.
Present strategy before finalizing
After generate_campaign_strategy, always retrieve and present the strategy to the user with get_strategy. Let them review the sequence plan (timing, focus areas, CTAs) before calling finalize_campaign. Finalization generates all emails and cannot be reversed.
Interpreting analytics
- delivery_rate: Percentage of emails that didn't bounce. Below 95% may indicate list quality issues.
- open_rate: Percentage of delivered emails opened. Industry average for cold email is 40-60%.
- reply_rate: Percentage of sent emails that got replies. Above 5% is strong for cold outreach.
- Sentiment breakdown: positive/negative/neutral reply counts. Focus follow-up on positive replies.
Pagination
List endpoints support skip and limit parameters (default limit: 50). For large datasets, paginate by incrementing skip. The total field in responses tells you the full count.
Common Workflows
Full campaign setup
1. create_new_campaign(name="Q2 Outreach", description="Target Series A founders", touches=3, tone=["friendly", "concise"])
2. add_contact_to_existing_campaign(campaign_id, email="jane@acme.co", first_name="Jane", ...) // repeat for each contact
3. generate_campaign_strategy(campaign_id)
4. get_strategy(campaign_id) // present to user for review
5. finalize_campaign(campaign_id) // only after user confirms
Morning briefing
1. get_account_analytics() // overview metrics
2. list_campaigns() // find active campaigns
3. get_campaign_threads(campaign_id) // check for new replies on each active campaign
Contact research and outreach
1. list_contacts() // see existing contacts
2. create_new_contact(email, first_name, ..., context="Recently raised Series A, expanding engineering team")
3. add_contact_to_existing_campaign(campaign_id, email) // add to relevant campaign
Editing an evergreen campaign
Evergreen campaigns are config-locked. To make changes, pause first, then resume:
1. pause_email_campaign(campaign_id) // pauses the campaign, saves "evergreen" as previous status
2. update_existing_campaign(campaign_id, max_words=120, tone=["direct"]) // now editable
3. resume_email_campaign(campaign_id) // restores to evergreen status automatically
LinkedIn campaign setup
1. create_linkedin_campaign(linkedin_session_id, name="Q2 LinkedIn Outreach", followup_message="Hi {name}, thanks for connecting! ...", connection_note="Hi, I'd love to connect...")
2. add_linkedin_leads(campaign_id, leads=[{linkedin_url: "https://linkedin.com/in/janedoe", first_name: "Jane", company: "Acme"}])
3. activate_linkedin_campaign(campaign_id) // starts automated connection requests
LinkedIn campaign monitoring
1. list_linkedin_campaigns() // see all campaigns with funnel stats
2. list_linkedin_leads(campaign_id, status_filter="replied") // check who replied
3. list_linkedin_leads(campaign_id, status_filter="invite_failed") // check for failures
LinkedIn Campaign Lifecycle
LinkedIn campaigns follow a different lifecycle than email campaigns:
- Create the campaign (
create_linkedin_campaign) — requires a LinkedIn session ID (set up via the dashboard) - Add leads (
add_linkedin_leads) — bulk add LinkedIn profile URLs - Activate (
activate_linkedin_campaign) — starts the automation:- Connection requests are sent automatically every 2 hours during sending hours (weekdays by default)
- Followup messages are sent at 9:30am and 2:30pm to leads whose connections were accepted
- Monitor (
list_linkedin_leads) — track the funnel: pending → invite_sent → message_sent → replied - Pause/Resume (
pause_linkedin_campaign/activate_linkedin_campaign) — pause and resume as needed
LinkedIn sessions (the li_at cookie) must be configured through the Skyp dashboard — they are not managed via MCP tools for security reasons.
Error Handling
- "Campaign not found or access denied" — The campaign ID is wrong or belongs to a different user/API key.
- "Contact not found or access denied" — Same as above, for contacts.
- "No fields to update" — An update call was made without any fields to change.
- "LinkedIn session not found" — The session ID is wrong or belongs to a different user.
- "LinkedIn session is not active" — The session cookie has expired. The user needs to re-authenticate on the dashboard.
- "Campaign must have at least one lead" — Cannot activate a LinkedIn campaign without leads.
- "Only active or evergreen campaigns can be paused" — The campaign is not in active or evergreen status.
- "Campaign is {status} and can only have its status changed" — Active, evergreen, or completed campaigns are config-locked. Pause the campaign first to make changes.
- "Cannot add leads to a completed campaign" — The campaign has finished and no longer accepts leads.
- Authentication errors — The API key is missing, invalid, or revoked. Direct the user to Settings > API Keys.
Important Constraints
- Campaign IDs and contact IDs are UUIDs. Always use the exact IDs returned by list/create tools.
touchesmust be between 1 and 7.max_wordsmust be between 30 and 150.closing_stylemust be one of:soft,mix,hard.timezonemust be a valid IANA timezone string (e.g.,America/New_York,Europe/London).- Finalization is irreversible. Never call
finalize_campaignwithout explicit user confirmation. - LinkedIn
connection_notemax length is 300 characters (LinkedIn platform limit). - LinkedIn
invites_per_launchmust be between 1 and 25. - LinkedIn
weekly_invite_limitmust be between 1 and 100. - LinkedIn
daily_message_limitmust be between 1 and 150. - LinkedIn
sending_daysis a list of integers: 0=Monday through 6=Sunday. - LinkedIn sessions are managed through the dashboard, not via MCP tools.