Your next connection
starts with your AI.

Connect Peers, join your community, and share what you are working on. Start here if you want to meet people.

Your AI's introduction inbox: an introduction both people approved, a recommendation from Peers, and someone who asked for more context.

1. Add Peers to your assistant.

Use this server URL when your assistant asks for a custom remote MCP connection:

https://api.linkpeers.com/mcp

Claude

Add a custom connector in your connector settings, enter the Peers URL above, and complete the authorization flow. Your plan or workspace settings may affect availability. Claude’s current connection guide.

ChatGPT

Create a custom MCP app using the Peers URL and complete authorization. Access depends on your plan, developer-mode availability, and workspace permissions. OpenAI’s current setup guide.

Gemini, Grok, and other assistants

You need a client that supports remote MCP over Streamable HTTP and OAuth authorization. Availability in an API or developer tool does not necessarily mean the same connection is available in its consumer chat app. Check the client’s current instructions before connecting. These Peers connections have not been verified in this release.

Grok’s custom-connector guidance. If your assistant does not offer the required connection, use a supported remote-MCP client.

2. Join your community.

Give your assistant your community’s Peers invitation or space name and ask to join. If you do not have one yet, ask it to suggest relevant listed spaces. Available people depend on the communities you join.

3. Tell it what matters now.

Start with your own goal and experience. Here is an example you can adapt:

I’m expanding into Europe and can help with enterprise AI adoption. Help me describe what I need and can offer in this community, then explore people worth meeting.

Choose how introductions happen. Automatic introductions are the default. Ask your assistant to switch to approve-first if you want to review each one. Shared profile content is visible to members and their assistants within joined communities. Contact disclosure follows the introduction’s consent settings.

Understand sharing and control

Overview

A space is any group you want to make introductions within, an event, a community, a cohort, a network. People join and share what they need and offer. Peers looks for complementarity, scores candidate pairs, and auto-introduces your best matches directly: you're always in control (switch to approve-first or opt out anytime).

Connection reference

Both paths reach the same Peers. Start with your assistant; drop to the API only if you're building something custom.

Through your AI assistant

Recommended
  • 1Add https://api.linkpeers.com/mcp to a compatible remote-MCP client. See the assistant guidance above.
  • 2Authorize once: your assistant runs the OAuth flow. No keys to paste.
  • 3For members: join a community, share what you need, and explore possible introductions. Organizers can create a space and preview matching. Done.
Transport Streamable HTTP · Auth OAuth 2.0 (PKCE)

Call the REST API

For builders
  • 1POST /v1/keys/request: get a one-time code by email.
  • 2POST /v1/keys/exchange: trade it for an mm_sk_ key.
  • 3Call /v1 with an Authorization: Bearer header. Done.
Base https://api.linkpeers.com · read-only keys are GET-only
✳

You don't have to write code. Connect through your assistant and ask in plain language, it calls the tools for you. The tool and endpoint reference below is there when you need the detail.

The flow

However you connect, the lifecycle of a space is the same:

Step 1

Create a space

Ask your assistant to create a space and pick a slug. You become its organizer.

Step 2

Bring people in

Share the join link so people add themselves through their own assistant, or bring in an existing list. On Free an imported list adds people quietly, and they fill in their own profile; on Pro it sends each person one invitation from you, and nobody is matched until they accept. Importing is optional.

Step 3

Matching runs

Matching runs automatically, hourly, and whenever someone joins or updates their profile. You can also trigger a run on demand. Peers scores complementarity and stages the best pairs.

Step 4

Auto-intros go out

By default, Peers emails the introduction itself. Switch to approve-first or opt out at any time.

Try it free in 3 calls

You do not need a plan, real members, or real email addresses to see what Peers would do. Ask your assistant for these three, in order:

Call 1

create_space({ name: "Trial", slug: "my-trial", sandbox: true })

A private throwaway space. It can never send email to anyone, is never billed, is never auto-matched, and nobody else can join it — so join links, QR codes and the share kit do not apply. A sandbox never becomes a live space, so give it a preview slug and keep the real name for the real room.

Call 2

import_attendees({ slug: "my-trial", sample: true })

Loads Peers' roster of fictional people, all on @example.com addresses that cannot reach a real inbox. Their profiles take about a minute to be read. Or upload your own list instead — import_attendees({ slug, records: [...] }), up to 50 people (your full list if you organize a Pro space), any columns; everything beyond email, name and linkedin is read as free text, so a paragraph per person works better than a title alone. Use a real list only if you are allowed to share those people's details, and pass attestPermission: true when it has real email addresses. This is the sandbox: the records become profiles straight away and nobody is emailed. On a live Pro space the same call invites each person instead.

Call 3

dry_run_matching({ slug: "my-trial" })

The real engine with sending switched off: every pair it would introduce, every pair it declined and why, and the actual email each pair would have received. The response carries a reportUrl you can open in a browser. Edit the space's matchPolicy with update_space and run it again to see exactly what your change did.

Calling a tool: payload and response

Normally your assistant does this for you. If you are driving MCP directly, every call is JSON-RPC over POST /mcp with your API key in the Authorization header. Tool arguments are the parameters listed for each tool below.

# Request
POST /mcp
Authorization: Bearer mm_sk_...
Accept: application/json, text/event-stream

{
  "jsonrpc": "2.0", "id": 1, "method": "tools/call",
  "params": {
    "name": "dry_run_matching",
    "arguments": { "slug": "founders-2026", "refresh": true }
  }
}

Every tool replies in the same envelope: a content array whose first entry is text. Most tools return prose written for an assistant to relay. A few return JSON inside that text so it can be reasoned over rather than read aloud, and dry_run_matching is one of them.

# Response envelope (all tools)
{
  "jsonrpc": "2.0", "id": 1,
  "result": { "content": [ { "type": "text", "text": "..." } ] }
}

# The text of a finished dry_run_matching, parsed
{
  "status": "ready",
  "policyVersion": 3,
  "counts": { "candidates": 45, "judged": 12, "accepted": 3, "rejected": 9 },
  "accepted": [
    { "a": "Rhiannon Beck", "b": "Noor Haddad", "score": 0.88,
      "aGains": "...", "bGains": "...", "nextStep": "...", "risk": "low" }
  ],
  "declined": [
    { "a": "Noor Haddad", "b": "Gustav Lindqvist", "why": "not_useful",
      "explanation": "Judge found no useful exchange: a judge/policy decision", "note": "..." }
  ],
  "changedSinceLastRun": { "added": [], "removed": [], "policyChanged": true }
}

A first call returns {"status":"started"} instead: matching is asynchronous, so wait ten to thirty seconds and call again to read the finished report. Other statuses you may get back are rate_limited, in_flight, and a plan or member-floor refusal, each with a message explaining what to do about it. Two declined categories are not policy rejections and say so in their explanation: lost_to_cap (approved, but over the space's pace) and not_judged (outranked by stronger candidates).

Mutating tools are marked Mut. Read-only API keys are rejected on those. Errors come back as a JSON-RPC error with a message written to be shown to the user.

Organizer tools

For the person who runs the space. MUT marks a tool that changes data (blocked for read-only access).

Question-generation cost: if you do not provide questions, Peers generates them once when the space is created. Owner-authored questions skip that call and stay unchanged when goals change. Switching back to generated questions requires an explicit regenerateIntakeQuestions: true, which queues one generation call.

create_spaceMutCreate a space; optionally provide judge policy and 1–8 custom text questions. Policy guides matching but cannot override member exclusions, consent, privacy, evidence, or mutual value. Pass sandbox: true for a private throwaway space that can never email anyone: it is free to dry-run on any plan and is how you preview matching before inviting real people.name, slug, type?, description?, matchingGoals?, matchPolicy?, intakeQuestions?, sandbox?, listed?
import_attendeesMutThree forms, one per call. csv: a plain email/name list. records: an enriched list (title, company, looking_for, offers, linkedin); needs attestPermission: true on a real space, and on a sandbox when it has real email addresses. sample: true: loads Peers' fictional roster into a sandbox space so a dry run has something to judge; refused on a real space. Free: csv adds people quietly with no email, and they add their own needs and offers; records is Pro. Sandbox: records and sample become profiles right away (up to 50, or your full list if you organize a Pro space), and nothing is ever emailed. Pro: csv and records create invitations, not members: each person gets one email from you and is matched only if they accept; what you provided is shown to them to edit or remove. A Pro call without confirmSend: true sends nothing and returns a preview; previewTo: "self" emails you a test copy; message adds a short plain-text note (links are removed).slug, csv?, records?, sample?, attestPermission?, message?, confirmSend?, previewTo?
list_participantsList participants with name, email, role, and memory count. Emails of members who joined by themselves show on Premium; people you imported or invited always show. On Pro, also invitation counts by status and the pending and declined addresses.slug
remove_memberMutRemove one member (by email or personId). They stop being matched, their pending introductions and requests are cancelled, and they can't rejoin by themselves. Completed introductions are not undone and they are not emailed. Can't remove an organizer or yourself. Given the address of a pending invitation, it cancels the invitation.slug, member, reason
get_space_statsAggregate stats plus active policy/version, questions, their source, and generation status. Also the invitation funnel (sent, accepted, declined, pending, expired), every invitation limit in force with where it comes from, and whether member emails are shown (rosterContactDetails).slug
update_spaceMutUpdate goals, judge policy, questions, consent, or intro pace. Goal edits regenerate only generated questions; custom questions are preserved. Use the explicit flag to switch back to generation.slug, matchingGoals?, matchPolicy?, intakeQuestions?, regenerateIntakeQuestions?, consentDefault?, freeIntroLimit?
run_matchingMutTrigger a match run on demand. Matching also runs automatically, hourly, and on new members / profile updates.slug
set_space_boostsMutTurn the anonymized Asks Board on/off for your space, or take a specific boost down. Disabling hides the space's boosts everywhere.slug, enabled?, removeBoostId?
dry_run_matchingMutRun the real engine with delivery suppressed. Returns the pairs it would introduce, the pairs it declined with a category, and the email each pair would receive. Nothing is created and nobody is emailed. Every response — including refusals — carries reportUrl, the browser page for this space's dry runs. Re-runs automatically when the match policy version moves; pass refresh after a roster change. Status no_candidates means the run judged nothing (usually profiles were still being read): wait about a minute and call again rather than editing the policy. Free on a sandbox space, Pro on a real one; 10 runs per space per rolling 24 hours.slug, refresh?
manage_emailGet a one-time browser link to connect the organizer's own SMTP account, so broadcasts send from their address. Credentials are never entered in chat.slug
broadcast_to_spaceMutSend one message to every member through the organizer's verified SMTP. Rate-limited to one per space per 24 hours. Opted-out and departed members are skipped.slug, subject, message, ctaUrl?
setup_payoutsMutStart Stripe Connect onboarding so a paid space can pay out. Returns a hosted Stripe link; identity and bank details never touch Peers.country?
get_payout_statusWhether charges and payouts are enabled, what Stripe still requires, and whether the account is ready for paid spaces.(none)
configure_paid_spaceMutSet admission price, currency, capacity, refund policy, and intro pace for a paid space. status is draft, active, or paused.slug, status, memberCapacity, price, currency, refundPolicy, defaultIntrosPerWeek?, defaultIntrosPerMonth?

Participant tools

For everyone in a space: including the organizer, who is also a participant. A member never needs the website: their assistant can join, build a profile, browse the room, ask for an introduction and accept one, entirely through these tools.

whoamiReturn the signed-in person's identity, scope, and permission.
list_my_spacesList all spaces the person has joined.
get_spacePublic summary of a space by slug.slug
join_spaceMutJoin a public space. An invite-only space admits only people with an open invitation to it. A membership-only space admits only people who hold its membership; anyone else is told so, with a link to the membership page. Returns the space's intake questions and offer options for you to read out — the member picks or rewords, never the assistant. If you were invited with a code, pass referralCode: the person who invited you gets connected to you with a warm intro (and those intros don't count against anyone's weekly/monthly caps).slug, copyFromSlug?, referralCode?
talk_to_matchmakerMutSend a message to the space matchmaker and get the reply: the default way to build your profile; it extracts needs/offers automatically.slug, message
submit_intakeMutSubmit intake tags (instant) and free-text answers (queued for extraction). Answers only work for spaces that have intake questions defined, otherwise the call redirects you to talk_to_matchmaker; tags always work.slug, tags?, answers?
list_my_memoriesList the caller's active memories in a space.slug
remove_memoryMutCorrect one of your own memories (replacement queued for extraction), or delete it by omitting text.memoryId, text?
browse_unmatchedFree discovery: who in the room you have not been paired with yet, shown anonymously — what they want, what they bring, no names or contact details. Everyone shown also lands in your inbox as a recommendation; triage from there.slug?, limit?
inbox_listYour single inbox: intros delivered to you, requests from others, recommendations worth meeting, check-ins, and platform messages, newest first. Start every session here — it is the only read that tells you what is waiting.cursor?, type?, space?, since?, limit?
inbox_requestMutAsk to be introduced to someone; asking back is how you accept — a specific reason of at least 20 characters is required and is shown to them.itemId, reason
inbox_respondMutAccept or decline a delivered introduction. Contact details are only exchanged once both sides accept.itemId, accept
inbox_dismissMutPass on any inbox item — nothing is sent to anyone. The optional reason is never shown to another member and is the most useful signal for improving matching.itemId, reason?
inbox_searchSearch your whole reach — every room you're in at once — for members whose stated needs, offers or background answer a question, in your own words. Results also land in your inbox.query, type?, space?, limit?
get_member_profileRead everything one member has said, by the opaque memberId from a browse_unmatched entry or an inbox item — still anonymous, no name or contact details.memberId
why_no_introsExplain, honestly and specifically, why you have not received introductions in a space, with one suggested next step.slug
find_matchesMutPaid deep search for a current need. With explicit confirmation, saves that need as matchable and expiring, judges a bounded shortlist, and returns strong opportunities without sending introductions — they also land in your inbox as recommendations. New people are preferred; past connections require new evidence and a new reason.slug, need, confirmMatchable, expiresInDays?, maxResults?, includePastConnections?
set_preferencesMutUpdate your consent mode, discovery breadth, and intro pace — call with only slug to read current settings back without changing anything. matchStrictness: exploratory (widest, allows specific low-risk inferred matches), balanced (default), or selective (strongest explicit value only). accountIntrosPerWeek caps total introductions across every space; introsPerWeek/introsPerMonth set the pace for this space only. maxRequestsFromOthers caps how many people per week may ask to be introduced to you. referralIntros: whether people who join with your invite code get auto-connected to you (default on; these don't count toward your caps either way). Optionally add LinkedIn/phone shared only after mutual consent.slug, consentMode?, introCap?, introsPerWeek?, accountIntrosPerWeek?, maxRequestsFromOthers?, introsPerMonth?, matchStrictness?, referralIntros?, outreachOptOut?, linkedinUrl?, phone?, sharePhone?
block_personMutNever be matched with a specific person in this space ("don't match me with X"). Resolves by display name.slug, name
unblock_personMutUndo a previous block: allow this person to be matched with you again.slug, name
check_join_statusWhere a join stands for a paid space: pending, processing, paid, failed, expired, refunded, disputed, or revoked, with the amount and paid-at time once settled.slug
profile_suggestionsFacts Peers has inferred about you in a space but not yet stored, each with a suggested confirming question. Nothing is matched on until you confirm it.slug
recommend_spacesDiscover other listed spaces whose members fit your needs and offers, ranked by fit.limit?
get_share_kitGet everything to invite others: a personal referral link, the space's value angles, and your referral count.slug
create_share_assetMutMake a personal card to post yourself: "I'm in" (what you want and bring) or "Looking for" (one need), with your referral QR. Two photo options, feed and story, PNG or GIF.slug, type, lookingFor, bringing, need
get_social_runbookYour Social Runbook: for each space, post ideas, gaps to recruit for, cards and asks worth publishing, and (for organizers) the room's diagnosis with next actions. Plus the brand guide and a daily check-in routine. Drafts only; you approve what goes out.slug, days
preview_boostMutTurn one of your asks into an anonymized, shareable post: drafts it but publishes nothing. Strips your name, employer, and contact details, generalizes the ask so it can't single you out, then returns a LinkedIn post, an X post, and (by default) a line for the public Asks Board, with a boostId to approve. Opt-in; sensitive topics need sensitiveAck.slug, sourceMemoryId?, sensitiveAck?, mode?
publish_boostMutPublish a boost draft you already reviewed, by its boostId: this only flips that exact draft live; it never accepts new text, so nothing you haven't seen can go out.boostId
list_my_boostsList your Ask Boost drafts and published posts (id, status, the anonymized text).slug?
unpublish_boostMutTake one of your boosts down from the Asks Board.boostId
give_feedbackMutRecord feedback about the experience or a specific intro.slug, introId?, useful?, met?, rating?, note?…
leave_spaceMutStop participating in a space: pending intros are cancelled and your profile stops being matched. Your data is kept unless you also delete it.slug
delete_my_dataMutErase your data, one space or everywhere. Immediate soft-delete, then a permanent purge after 30 days.scope (space|all), slug?
revoke_my_agent_accessMutRevoke all agent (MCP) access tokens you've granted.

REST API, authentication

Every request carries an API key in the Authorization header. Create one by requesting a one-time code by email, then exchanging it. Read-only keys are rejected on any write (non-GET) request. Paths are versioned under /v1.

# 1. Request a one-time code
POST /v1/keys/request
{ "email": "you@example.com" }

# 2. Exchange the emailed code for a key
POST /v1/keys/exchange
{ "email": "you@example.com", "code": "1234", "name": "my-app" }
→ { "apiKey": "mm_sk_…", "keyPrefix": "mm_sk_…", "permissionLevel": "read_write" }

# 3. Use it on every request
Authorization: Bearer mm_sk_…

Spaces

matchPolicy accepts objective, mustHave[], prefer[], avoid[], and organizerReview[]. Matching configuration is private to the organizer.

POST/v1/spacesCreate a space; optional matchPolicy and intakeQuestions. Returns joinUrl and configuration state. A taken slug returns 409 with up to three free suggestions.
GET/v1/spaces/:slugPublic space summary. No auth. 404 for private spaces.
GET/v1/spaces/:slug/configRead policy/version and questionnaire state (organizer only).
PATCH/v1/spaces/:slugUpdate goals, policy, or questions; use regenerateIntakeQuestions: true for one generation job (organizer only).
POST/v1/spaces/:slug/joinSelf-join a public space.
GET/v1/spaces/:spaceId/participantsRoster (organizer only): name, email, role, how they joined, memory count. Emails of members who joined by themselves show on Premium; people you imported or invited always show.
GET/v1/spaces/:spaceId/invitationsInvitation counts by status, with the pending and declined addresses (organizer only).
DEL/v1/spaces/:slug/members/:emailRemove a member, or cancel their pending invitation (organizer only). Optional reason. Returns { status }: removed, already_removed, invitation_cancelled or not_member.

Chat & profile

POST/v1/spaces/:slug/chatMessage the space matchmaker. Body: { message }. Returns { reply, done }.
GET/v1/spaces/:slug/me/memoriesList your own active memories in a space.
DEL/v1/memories/:idSoft-delete one of your own memories.

Import

Import a CSV directly, or presign an S3 upload for larger files. On a live Pro space every route here invites people rather than adding them.

POST/v1/spaces/:slug/membersAdd people from another system. Body: exactly one of { members: [{ email, name? }] } or { records: [...], attestPermission: true } (Pro), plus optional message and dryRun (returns the preview, sends nothing). Free adds members quietly with no email; Pro sends each person one invitation. Safe to retry: a repeated address comes back already_invited or already_member and is never emailed twice. 402 records on Free, 423 invitations paused, 429 rate limited.
POST/v1/spaces/:spaceId/importUpload a CSV (multipart file, ≤10MB). Enqueues an import job.
POST/v1/spaces/:spaceId/import/recordsImport enriched records as JSON (Pro; ≤500/call — free and unattested on a sandbox space). Body: { records[], attestPermission }.
POST/v1/spaces/:spaceId/import/presignGet a presigned S3 PUT URL. Body: { filename }.
POST/v1/spaces/:spaceId/import/completeMark a presigned upload complete and enqueue import. Body: { storageKey }.
GET/v1/spaces/:spaceId/import/:batchIdImport batch status, row counts, and errors.

From Eventbrite, Luma or a form (Zapier): trigger on a new registration, then Webhooks by Zapier POST to https://api.linkpeers.com/v1/spaces/<slug>/members with header Authorization: Bearer <your API key> and body {"members":[{"email":"{{email}}","name":"{{name}}"}]}. Test once with "dryRun": true. On Pro each registrant gets one invitation from you; on Free they are added quietly, so put your join link in your own confirmation email.

Introductions

Consent and feedback are token-authenticated links delivered by email: no API key needed. They render a confirmation page and are idempotent.

GET/i/:introId/:side/:actionAccept or decline an intro from an email link. side a|b, action accept|decline, signed ?t=.
GET/f/:introId/:side/:verdictThumbs up/down on a delivered intro. verdict up|down, signed ?t=.

Keys & sign-in

POST/v1/keys/requestEmail a one-time code to create an API key.
POST/v1/keys/exchangeExchange the code for a new mm_sk_ key.
POST/v1/auth/magic-linkRequest a magic sign-in link by email.
POST/v1/auth/verifyVerify a magic-link token and start a session.
GET/v1/auth/meThe currently signed-in person.
◆

MCP clients don't use API keys. The /mcp endpoint authenticates over OAuth 2.0 (PKCE), which your assistant negotiates automatically. API keys are only for direct REST calls.