MCP server

Tools reference

Inputs, results, and behavior for every tool the Homie MCP server exposes.

The Homie MCP server exposes fifteen read-only tools to every token. Tokens with the mcp:write scope also receive four write tools, for nineteen in total. Write tools are not registered at all for a read-only token, so they never appear in its tool list.

  • Organization-scoped tools search the whole network of the organization that owns the token. They work with user MCP tokens and organization API keys.
  • User-scoped tools act on the authenticated user personally: their own connections, prioritized list, target lists, and re-score runs. They need a user MCP token, and organization API keys are rejected.
  • Company tools query Homie's shared company directory.
ToolScopeAccessUse it to
get_icpOrganizationReadRead the Ideal Customer Profile before prospecting.
search_ghost_opportunitiesOrganizationReadLook up prospects the agent has already surfaced, by keyword.
list_ghost_opportunitiesOrganizationReadPage through all surfaced prospects, with filters and sorting.
list_person_networkOrganizationReadSee who a given person knows, warmest first.
search_warm_pathsOrganizationReadFind intro routes to one person or company.
check_warmness_rescoreUserReadWait for AI re-scoring of cold connections and read the refined scores.
search_networkOrganizationReadRun a natural-language search across the network.
search_peopleOrganizationReadFind people by name, email, role, or company.
get_personOrganizationReadFetch one person by id.
list_first_degree_connectionsUserReadPage through your own direct connections.
list_second_degree_connectionsUserReadSee who your contacts could introduce you to.
search_companiesDirectoryReadFind companies by name, industry, or location.
get_companyDirectoryReadFetch one company by id.
list_target_listsUserReadList your target lists.
get_target_listUserReadRead one target list and its companies.
add_prioritized_connectionUserWriteMark a direct connection as a key relationship.
remove_prioritized_connectionUserWriteUndo a prioritization.
create_target_listUserWriteCreate an empty target list.
modify_target_listUserWriteRename a target list, or add or remove a company.

Every tool returns structured content. The result carries a typed structuredContent payload, validated against the tool's declared outputSchema, alongside a JSON text fallback. MCP clients that support structured output get typed results instead of parsing JSON out of a text blob.

Start with get_icp when prospecting. Warmness ranks reachability, not fit, so results ordered by warmness alone put colleagues ahead of prospects.

Already-requested people. Candidate lists (company-mode search_warm_paths, list_person_network) exclude anyone the organization has already requested an intro to, reporting the count as excludedIntroRequested; includeIntroRequested: true brings them back. Lookup tools (person-mode search_warm_paths, search_people, get_person) never filter, but annotate results with introRequested, introStatus, introRequestedBy, and introRequestedAt. Every status counts as already asked, including LOST — the status travels with the annotation so you can judge whether a stale request is worth retrying.

get_icp

Read the organization's Ideal Customer Profile. Takes no arguments.

Returns { configured, icp? }. When configured is false the organization has not set one up; ask the user who they are targeting rather than guessing. Otherwise icp carries name, description, positions, industries, locations, companySize, companyType, additionalContext, skipWarmConnections, isAutoGenerated, sourceWebsite, and updatedAt.

The ICP is stored text, not a scorer: read it and filter the people other tools return against it yourself. Nothing is scored server-side, so there is no added latency or model cost per query.

list_person_network

List the people a given person is connected to, warmest first. This answers "who does Kalle know", "warm paths from Kalle's network", and "who could Kalle introduce us to".

This is the raw-network fallback. Call search_ghost_opportunities first with the person's name and company. Prefer any opportunities it returns, because they are already scored against the ICP.

FieldTypeNotes
namestringPerson's name, fuzzy-matched. Usually what you have. On a tie the best-connected match wins.
linkedinIdstringLinkedIn handle.
personIdstringHomie person id. A user id is also accepted here, since warm paths return fromUserId.
limitnumber1-50, default 20.
offsetnumber0-based offset. Use the previous response's nextOffset.
includeIntroRequestedbooleanDefault false. Set true to include people already asked about, annotated.

Returns { person, connections, totalCount, returnedCount, limit, offset, nextOffset, hasMore, excludedIntroRequested, coverage }. Each connection carries position, currentCompany, city, country, warmness, and warmnessSignals, which is what you need to qualify them against the ICP.

Check coverage before describing the result

coverage says how complete the network is, which is a different question from how big it is. Most people in the graph are derived or none, so an empty list is usually not evidence that someone has no connections.

ValueMeaning
syncedThe person is a Homie user and their own connections were imported. The list is their network.
derivedTheir connections are known indirectly, through the people around them. This is the slice of their network Homie has observed, not all of it. Say so rather than implying completeness.
noneHomie has no outbound edges for them. An empty connections means "not mapped", never "they know nobody".

The subject must be in the organization's network: either an org member, or someone an org member is directly connected to. Anyone else returns a scope error rather than turning this into a directory lookup over every person in Homie.

Do not reach for alternatives that look similar. Enumerating list_ghost_opportunities and filtering for a connector is slow and misses anyone the agent has not surfaced. search_network's asUserId only accepts org members who hold a Homie account, so it cannot express "as this person in our network".

Cold connections are re-scored

When the top of the list includes people with warmness below 25, Homie queues the subject's edges to them for background AI re-scoring. Up to ten people are queued per call. This needs a user MCP token, because the run is tracked against the requesting user. Call check_warmness_rescore next, and answer with its refined scores rather than the cold ones.

search_warm_paths

Find warm intro paths from anyone in the organization to a target person OR to anyone at a target company.

FieldTypeNotes
prospectPersonIdstringHomie person id. Pass exactly one target: this, prospectLinkedinId, prospectName, or prospectCompany.
prospectLinkedinIdstringLinkedIn handle.
prospectNamestringFuzzy name match. Add prospectCompany alongside it to disambiguate; it then narrows the person rather than switching modes.
prospectCompanystringCompany name. On its own, returns paths to anyone working there. Each path's target field identifies the specific employee.
prospectRolesstring[]Company-only filter: 1–20 literal role phrases, OR-ed against current profile titles before finding paths. For example ["head of security", "security", "ciso"]. Titles are not independent verification of seniority.
maxHopsnumber1-3. Keep only routes with at most this many relationship edges. 3 also opts in to three-hop third_degree routes.
includePossiblePathsbooleanDefault false. Set true to include complete routes with weak or unscored hops. These are possible routes, not warm intros.
limitnumber1-50, default 20. Maximum paths requested; the response size budget may return fewer. Always continue with nextOffset.
offsetnumber0-based offset for pagination. Use the previous response's nextOffset to fetch the next page.
includeIntroRequestedbooleanCompany mode only. Default false. Set true to include employees the org already asked for an intro to.
scopestringorganization (default) searches from everyone here; me restricts to the authenticated user and requires a user-scoped token.
fromUserIdsstring[]Search only from these org members. Accepts user ids or person ids. Mutually exclusive with a non-default scope.
connectionTypesstring[]Keep only these path types: direct, second_degree, third_degree, advocate, advocate_second_degree.

Returns { outcome, message, fallbackConnections, prospect, company, paths[], totalCount, returnedCount, limit, offset, nextOffset, hasMore, excludedIntroRequested, coverage }. For person mode company is null; for company mode prospect is null and each path entry has a target field with the employee being reached.

Compact connector responses

Both the structured result and JSON text fallback contain the same compact page, limited to 12,000 UTF-8 bytes per payload. Raw scoring-factor breakdowns and image URLs are omitted. Person identities, positions, companies, ordered hops, scores, signal labels and intro-request annotations remain available. An unscored hop stays null; it is not evidence of a warm relationship.

limit is an upper bound, not a guaranteed page length. If the page is shortened, returnedCount reflects the paths actually included, hasMore is true, and nextOffset points to the first undisplayed path. Keep the same filters and pass that value as offset; do not add limit yourself. totalCount and graph coverage retain their original meaning. Use get_person for additional profile details instead of requesting larger path pages.

Read outcome before calling anything a warm intro

outcomeMeaning
foundAt least one genuinely warm route, with warmness above 0, was returned.
no_pathsThe target exists but no route is warm. paths may still hold cold routes whose connector-to-target hop scores 0. Those are reachable in name only.
target_not_foundNo such person or company is in the organization's network. prospect and company are both null.
incompleteA bounded scan hit its cap, so a warm route may have been missed. This takes precedence over no_paths.

A list of paths alone is not proof of a warm route, so gate on outcome === "found" or on a path's own warmness. On no_paths and target_not_found the result carries a human-readable message. When the organization has any warm contacts, it also carries fallbackConnections: the organization's warmest reachable people, warmest first. Relay the message and offer those people as the closest existing contacts. Never present them as a path to the requested target, and never report an empty result as "they know no one".

coverage reports capped, candidatePeople, candidatePeopleCap, secondDegreeEdgesCapped, and thirdDegreeEdgesCapped. capped is true when the employee candidate cap or a second- or third-degree edge cap was reached. Check it before implying the list is complete.

By default this searches from every member of the organization, which answers "can we reach them". Narrowing the source answers the everyday variants:

QuestionArguments
Can anyone here reach them?(default)
Can I reach them?scope: "me"
Who in my first-degree network bridges to them?scope: "me", connectionTypes: ["second_degree"]
Do I already know them?scope: "me", connectionTypes: ["direct"]
Can a specific colleague reach them?fromUserIds: ["<user or person id>"]
Only routes through advocatesconnectionTypes: ["advocate", "advocate_second_degree"]

scope: "me" needs a user-scoped MCP token; an organization API key has no personal network and gets a scope error telling it to use fromUserIds instead. fromUserIds accepts either id kind because warm paths return fromUserId while every other tool returns person ids. People in the network who have no Homie account cannot be a source at all — use list_person_network for them.

excludedIntroRequested counts employees withheld in company mode because an intro was already requested. It is always 0 in person mode, which annotates the prospect with introRequested instead of filtering: you named one person, so answering "no paths" because an intro is already in flight would hide more than it helps.

Each path includes:

  • fromUserId / fromUserName: the org member whose perspective enables the path.
  • connector: the intermediary person.
  • viaAdvocate: for an advocate_second_degree path, the accepted advocate the org member can ask first. In that path type, connector is the advocate's connection to the target.
  • connectionType: one of:
    • direct: the org member knows the target.
    • second_degree: the org member knows someone who knows the target.
    • third_degree: a three-hop route, returned only when maxHops is 3.
    • advocate: an advocate of the org member knows the target.
    • advocate_second_degree: an advocate of the org member knows someone who knows the target.
  • hops: the route as an ordered list of edges. Each hop has from, to, warmness, and signals.
  • warmness: overall score for ranking (0-100).
  • userToConnectorWarmness + userToConnectorSignals: score and human-readable signal labels for the source-side relationship. For a route via an advocate, use the ordered hops to identify each relationship precisely.
  • connectorToProspectWarmness + connectorToProspectSignals: score and labels for the connector to target hop (set for non-direct paths).

The *Signals arrays and each hop's signals contain human-readable evidence (e.g. "Working together at Acme", "3 mutual connections", "Both reacted to each other's posts"). Raw *Breakdown objects remain optional in the output schema for compatibility, but compact MCP responses omit them. REST responses and native Homie cards are unaffected.

Results are ranked in this order: direct, advocate, 2nd-degree, advocate 2nd-degree, 3rd-degree. Within each tier, warmer paths appear first. When the target is found but has no paths, the matched prospect or company is still returned, with outcome: "no_paths".

Cold connections are re-scored

When the result surfaces cold connections from the authenticated user's own network, Homie queues them for background AI re-scoring. This needs a user MCP token. The message then tells you scoring is running. Call check_warmness_rescore and answer with the refined scores.

check_warmness_rescore

Wait for the background AI re-scoring that search_warm_paths or list_person_network just queued for cold connections, then return the refined scores. User-scoped: organization API keys have no re-score runs, so they always get status: "none".

FieldTypeNotes
runIdstringOptional. A specific re-score run. Omit it to use your latest one.

Call it right after a tool says scoring is running. It blocks until the run finishes, checking every few seconds for up to about 35 seconds. Without runId, it only considers runs started in the last 15 minutes. You can then answer once with the improved scores instead of asking the user to try again.

Returns { status, completed, failed, total, results }.

statusMeaning
completedThe run finished and results are final.
runningThe wait timed out before the run finished. Call again to get the rest.
failedThe run errored.
noneThere is no recent re-score to report.

completed and total count re-scored pairs. Each entry in results has name, previousScore (the formula score before re-scoring), newScore (the AI-refined score, now saved on the connection), and a short summary. It lists up to 20 successfully re-scored people, highest newScore first.

list_first_degree_connections

List the authenticated user's own first-degree LinkedIn connections. Unlike the search tools, this one is scoped to the token's user personally — organization API keys are rejected.

FieldTypeNotes
limitnumber1-50, default 20.
offsetnumber0-based offset for pagination. Use the previous response's nextOffset to fetch the next page.

Returns { connections, totalCount, returnedCount, limit, offset, nextOffset, hasMore }. Each connection has person fields only: id, name, linkedinId, position, currentCompany. Ordered by name. Connections whose warmness hasn't been computed yet are included — warmness is enrichment, not a membership filter.

list_second_degree_connections

People connected to one of your own first-degree contacts, but whom you don't know directly. Each entry names the bridging connector, so you can see who could introduce you. User-scoped: organization API keys are rejected.

FieldTypeNotes
limitnumber1-50, default 20.
offsetnumber0-based offset for pagination. Use the previous response's nextOffset.
viaConnectorIdstringOnly list people reachable through this first-degree contact (a person id).

Returns { connections, totalCount, returnedCount, limit, offset, nextOffset, hasMore, scannedBridges, capped }, ordered warmest first. Each connection carries viaConnector (the bridging contact) and warmness for the connector→person edge.

Coverage is bounded. Second-degree networks can be very large, so results cover a bounded number of warm edges per connector. Without viaConnectorId, the bridge set is bounded too. totalCount counts people within that window, scannedBridges says how many contacts were considered, and capped: true means a bridge or per-connector edge cap was reached. This signal applies with or without viaConnectorId.

add_prioritized_connection

Add one of your own first-degree connections to your prioritized list, meaning the people you consider key relationships. This tool writes. User-scoped: organization API keys are rejected.

FieldTypeNotes
personIdstringHomie person id, as returned by list_first_degree_connections, search_people, or get_person. Pass one of these two fields.
connectionIdstringConnection id, as an alternative. Useful for an id taken from a ghost opportunity's bestPath.connectionId.

Prioritizing has three effects:

  1. The person moves to the top of your priority list.
  2. A strong priority signal enters that connection's warmness score, which is recalculated immediately.
  3. If the person also has a Homie account, they are promoted to an accepted advocate, so they appear as an available connector.

Returns { id, connectionId, priority, alreadyPrioritized, person, warmness }. alreadyPrioritized is true when the person was already on the list. A retry after the person reaches the top is a no-op: it does not increment priority or rerun side effects. warmness is the score after the initial recalc, or the stored score on a no-op; it is omitted if scoring failed, which does not undo the write.

Only your own first-degree connections can be prioritized. Passing a second-degree person, or someone else's connection, returns a validation error.

remove_prioritized_connection

Remove one of your first-degree connections from your prioritized list. This tool writes. User-scoped: organization API keys are rejected.

FieldTypeNotes
personIdstringHomie person id. Pass one of these two fields.
connectionIdstringConnection id, as an alternative, exactly as for the add tool.

Removing withdraws the priority signal from that connection's warmness score, which is recalculated immediately. It does not revoke advocate status that was granted when the person was prioritized.

Returns { connectionId, removed, person, warmness }. removed is false when the person was not on your list, in which case nothing changes and warmness is the stored score. Only call it when the user explicitly asks to unprioritize someone.

get_person

Fetch one person by their Homie person id (as returned by search_people, search_warm_paths, or list_first_degree_connections).

FieldTypeNotes
idstringRequired. Homie person id.

Returns { found, person? }. person includes profile fields, current company, network size, a degree field ("first" or "second"), and — on first-degree connections — the org's warmness, warmnessBreakdown, and human-readable warmnessSignals. found is false when the person isn't in the organization's network (1st or 2nd degree), so the tool never reveals that someone exists outside your graph.

list_ghost_opportunities

List the organization's ghost opportunities — prospects the agent discovered, each with an ICP evaluation, buying-intent signals, key insights, and the best warm intro path. Org-scoped: works with both user MCP tokens and organization API keys.

FieldTypeNotes
statusstringvisible, saved, accepted, intro_requested, or dismissed. Default: the active set.
sortstringnewest (default), oldest, or relevancy.
searchstringSubstring match on prospect name, company, or position.
limitnumber1-50, default 20.
offsetnumber0-based offset for pagination. Use the previous response's nextOffset.

Returns { opportunities, totalCount, returnedCount, limit, offset, nextOffset, hasMore }. Prospects working at your own company are excluded. A path whose connector is one of your own org members is not surfaced as bestPath (it would just echo back what the org already knows); when every path for an opportunity is internal, the opportunity is still returned with bestPath omitted.

search_ghost_opportunities

Search the ghost opportunities the agent has already discovered, by keyword. Use it for questions like "any opportunities at fintechs?" or "opportunities matching Acme", and before list_person_network when someone asks who a person could introduce. Org-scoped: works with both user MCP tokens and organization API keys.

It does not scan the network or create new opportunities. For open-ended prospecting use search_network, and for a route to one specific person or company use search_warm_paths.

FieldTypeNotes
querystringRequired. Substring matched against prospect name, company, and position.
statusstringvisible, saved, accepted, intro_requested, or dismissed. Default: the active set.
sortstringrelevancy (default, highest overallScore first), newest, or oldest.
limitnumber1-50, default 20.
offsetnumber0-based offset for pagination. Use the previous response's nextOffset.

Returns the same payload as list_ghost_opportunities, with the same exclusions. The only differences are that query is required and results sort by relevancy by default.

search_network

Natural-language search across the organization's combined network. Best for queries like "VPs of Eng at Series C startups in NYC".

The response includes totalCount and returnedCount.

FieldTypeNotes
querystringRequired.
networks("user" | "advocate" | "organization")[]Default: all three.
strictness1-31=relaxed (default), 2=normal, 3=strict.
asUserIdstringOrg member to use as perspective for user/advocate networks. Accepts their user id or their person id. Defaults to the authenticated MCP user when available, otherwise the oldest admin. People in the network without a Homie account cannot be a perspective; use list_person_network for them.
limitnumber1-50, default 20.

The search uses the same semantic engine as the Homie app's own search page and falls back to a simpler keyword search when that is unavailable or returns nothing. The response carries a fallback object explaining any downgrade, so read it rather than assuming which search ran.

search_people

Substring search across people in the network (1st-degree direct connections + 2nd-degree by default).

FieldTypeNotes
querystringRequired. Matches name, email, position, company.
limitnumber1-50, default 20.
includeSecondDegreebooleanDefault true.

Returns { results: [...] }. Each result includes a degree field ("first" or "second"), a warmness score, and a warmnessBreakdown object with the factors behind the score.

search_companies

Search Homie's company directory by name, industry, or HQ location. This is a directory lookup, not a warm-path search.

FieldTypeNotes
querystringRequired.
pagenumber1-based, default 1.
limitnumber1-50, default 20.

get_company

Fetch one company from Homie's directory. This is a directory lookup, not a warm-path search; use search_warm_paths with prospectCompany to reach people there.

FieldTypeNotes
idstringRequired. Either the Homie id or the LinkedIn companyId, as returned by search_companies, get_target_list, or a person's company.

Returns { found, company? }. The company carries id, companyId, name, industry, headquartersLocation, minSize, maxSize, and logoUrl when available. Unknown ids return found: false rather than an error.

list_target_lists

List your own target lists, most recently updated first. User-scoped: organization API keys are rejected.

Takes no arguments. Returns { targetLists }; each summary contains id, name, companyCount, unmatchedCompanyCount, createdAt, and updatedAt. Use the list's id as targetListId with get_target_list or modify_target_list.

companyCount counts companies linked to Homie's company directory. unmatchedCompanyCount counts imported company names that have not yet matched a directory record.

get_target_list

Read one of your own target lists and page through its matched companies. User-scoped: organization API keys are rejected.

FieldTypeNotes
targetListIdstringTarget-list id from list_target_lists.
limitnumber1-50, default 20.
offsetnumber0-based company offset. Use the previous response's nextOffset.

Returns { found, targetList? }. The target list includes its summary fields plus companies, totalCount, returnedCount, limit, offset, nextOffset, and hasMore. Each company carries its Homie id, LinkedIn companyId, name, industry, and headquarters when available. Lists that do not belong to the authenticated user return found:false.

create_target_list

Create a new, empty target list that you own. This tool writes. User-scoped: organization API keys are rejected.

FieldTypeNotes
namestringRequired. 255 characters maximum, trimmed.

If you already own a list with exactly this name, no duplicate is created and that list is returned instead, so a retry is safe. Follow up with modify_target_list to add companies. Only call it when the user asks for a new list, or asks to add companies to a list that list_target_lists shows does not exist.

Returns { created, targetList }. created is false when the existing list was returned.

modify_target_list

Rename one of your own target lists, add a company, or remove a company. This tool writes and only the list's owner can use it. Organization API keys are rejected.

FieldTypeNotes
targetListIdstringTarget-list id from list_target_lists.
actionstringrename, add_company, or remove_company.
namestringRequired only for rename; 255 characters maximum.
companyIdstringRequired for add/remove. Accepts either the id or companyId returned by search_companies.

Resolve the list first with list_target_lists. For company changes, use search_companies to resolve the company and get_target_list when you need to inspect current membership. Only call the write after the user explicitly asks for the change.

Returns { action, changed, targetList }. changed:false means the requested end state was already true: the list already had that name or company, or the company was already absent. This makes repeat calls safe.

Resources

Every tool hands back ids. Rather than re-running a search to turn an id back into a record, read it directly:

URIReturns
homie://person/{id}Same payload as get_person.
homie://company/{id}Same payload as get_company. Accepts the Homie company id or the LinkedIn companyId.
homie://icpSame { configured, icp? } payload as get_icp.
homie://ghost-opportunity/{id}One opportunity, same shape as an entry from list_ghost_opportunities.

All four return application/json. Person and opportunity resources outside your organization's reach return a found:false payload rather than erroring, so they do not confirm the existence of records you cannot access. Company lookup uses the shared company directory.

These are addressable lookups rather than enumerable collections, so the templates don't support listing. Enumerate with the paginated tools instead.

Prompts

warm-intro-brief

The workflow the server exists for. Give it a prospect (LinkedIn handle, full name, or company) and it drives search_warm_paths + get_person, then briefs you on:

  • who to ask — the connector and the org member who owns that relationship,
  • why the path works — quoting the warmness signal labels verbatim rather than paraphrasing them,
  • how to ask — a short message grounded in the actual shared context,
  • alternatives — the next-best path, when it's a genuinely different route.

It instructs the model never to invent a connector, signal, or score, and to say so plainly when no path exists.

On this page