Tools reference
Inputs, results, and behavior for every tool the Homie MCP server exposes.
The Homie MCP server exposes fifteen lookup tools to every token: thirteen are read-only, while search_warm_paths and list_person_network can automatically queue background warmness updates for user tokens. Tokens with the mcp:write scope also receive six explicit write tools, for twenty-one in total. Those six tools are not registered for a token with only mcp:read.
- 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.
- Directory company tools query Homie's shared company directory. They read existing company records.
| Tool | Scope | Access | Use it to |
|---|---|---|---|
get_icp | Organization | Read | Read the Ideal Customer Profile before prospecting. |
search_sales_opportunities | Organization | Read | Look up prospects the agent has already surfaced, by keyword. |
list_sales_opportunities | Organization | Read | Page through all surfaced prospects, with filters and sorting. |
list_person_network | Organization | Read | See who a given person knows, warmest first. |
search_warm_paths | Organization | Read | Find intro routes to one person or company. |
check_warmness_rescore | User | Read | Read the current status of an existing AI warmness run. |
search_network | Organization | Read | Run a natural-language search across the network. |
search_people | Organization | Read | Find people by name, email, role, or company. |
get_person | Organization | Read | Fetch one person by id. |
list_first_degree_connections | User | Read | Page through your own direct connections. |
list_second_degree_connections | User | Read | See who your contacts could introduce you to. |
search_companies | Directory | Read | Find companies by name, industry, or location. |
get_company | Directory | Read | Fetch one company by id. |
list_target_lists | User | Read | List your target lists. |
get_target_list | User | Read | Read one target list and its companies. |
add_prioritized_connection | User | Write | Mark a direct connection as a key relationship. |
remove_prioritized_connection | User | Write | Undo a prioritization. |
create_target_list | User | Write | Create an empty target list. |
rename_target_list | User | Write | Rename one target list. |
add_company_to_target_list | User | Write | Add one company to a target list. |
remove_company_from_target_list | User | Write | Remove one company from a target list. |
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".
Use this directly to explore a person's network. search_sales_opportunities matches prospects, not connectors, and is only relevant when looking for existing sales recommendations.
| Field | Type | Notes |
|---|---|---|
name | string | Person's name, fuzzy-matched. Usually what you have. On a tie the best-connected match wins. |
linkedinId | string | LinkedIn handle. |
personId | string | Homie person id. A user id is also accepted here, since warm paths return fromUserId. |
limit | number | 1-50, default 20. |
offset | number | 0-based offset. Use the previous response's nextOffset. |
includeIntroRequested | boolean | Default 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.
| Value | Meaning |
|---|---|
synced | The person is a Homie user and their own connections were imported. The list is their network. |
derived | Their 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. |
none | Homie 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_sales_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".
Background warmness updates
With a user token, this lookup can automatically queue AI re-scoring for up to ten low-score connections. The background worker persists updated warmness scores and breakdowns; the lookup returns current evidence without waiting. This also works with mcp:read alone. Low or missing warmness is unverified relationship evidence, not proof of a warm introduction.
search_warm_paths
Find warm intro paths from anyone in the organization to a target person OR to anyone at a target company.
| Field | Type | Notes |
|---|---|---|
prospectPersonId | string | Homie person id. Pass exactly one target: this, prospectLinkedinId, prospectName, or prospectCompany. |
prospectLinkedinId | string | LinkedIn handle. |
prospectName | string | Fuzzy name match. Add prospectCompany alongside it to disambiguate; it then narrows the person rather than switching modes. |
prospectCompany | string | Company name. On its own, returns paths to anyone working there. Each path's target field identifies the specific employee. |
prospectRoles | string[] | 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. |
maxHops | number | 1-3. Keep only routes with at most this many relationship edges. 3 also opts in to three-hop third_degree routes. |
includePossiblePaths | boolean | Default false. Set true to include complete routes with weak or unscored hops. These are possible routes, not warm intros. |
limit | number | 1-50, default 20. Maximum paths requested; the response size budget may return fewer. Always continue with nextOffset. |
offset | number | 0-based offset for pagination. Use the previous response's nextOffset to fetch the next page. |
includeIntroRequested | boolean | Company mode only. Default false. Set true to include employees the org already asked for an intro to. |
scope | string | organization (default) searches from everyone here; me restricts to the authenticated user and requires a user-scoped token. |
fromUserIds | string[] | Search only from these org members. Accepts user ids or person ids. Mutually exclusive with a non-default scope. |
connectionTypes | string[] | 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
outcome | Meaning |
|---|---|
found | At least one genuinely warm route, with warmness above 0, was returned. |
no_paths | The 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_found | No such person or company is in the organization's network. prospect and company are both null. |
incomplete | A 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.
Scoping the search
By default this searches from every member of the organization, which answers "can we reach them". Narrowing the source answers the everyday variants:
| Question | Arguments |
|---|---|
| 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 advocates | connectionTypes: ["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 anadvocate_second_degreepath, the accepted advocate the org member can ask first. In that path type,connectoris 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 whenmaxHopsis3.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 hasfrom,to,warmness, andsignals.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 orderedhopsto 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".
Background warmness updates
With a user token, this lookup can automatically queue AI re-scoring for up to ten low-score connections. The background worker persists updated warmness scores and breakdowns; the lookup returns current evidence without waiting. This also works with mcp:read alone. Low or missing warmness is unverified relationship evidence, not proof of a warm introduction.
check_warmness_rescore
Read the current status and persisted results of an AI warmness run queued by search_warm_paths or list_person_network. This status check returns immediately without waiting, queuing work or changing scores. User-scoped: organization API keys have no re-score runs, so they always get status: "none".
| Field | Type | Notes |
|---|---|---|
runId | string | Optional. A specific re-score run. Omit it to use your latest one. |
Answer the initial lookup with its current results. Call this tool only when the user later asks for an update; do not poll. Without runId, it only considers runs started in the last 15 minutes.
Returns { status, completed, failed, total, results }.
status | Meaning |
|---|---|
completed | The run finished and results are final. |
running | Scoring continues in the background; current results may be partial. |
failed | The run errored. |
none | There 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.
| Field | Type | Notes |
|---|---|---|
limit | number | 1-50, default 20. |
offset | number | 0-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.
| Field | Type | Notes |
|---|---|---|
limit | number | 1-50, default 20. |
offset | number | 0-based offset for pagination. Use the previous response's nextOffset. |
viaConnectorId | string | Only 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.
| Field | Type | Notes |
|---|---|---|
personId | string | Homie person id, as returned by list_first_degree_connections, search_people, or get_person. Pass one of these two fields. |
connectionId | string | Connection id, as an alternative. Useful for an id taken from a ghost opportunity's bestPath.connectionId. |
Prioritizing has four effects:
- The person moves to the top of your priority list.
- A strong priority signal enters that connection's warmness score, which is recalculated immediately.
- If the person also has a Homie account, they are promoted to an accepted advocate, so they appear as an available connector.
- Homie queues one LinkedIn sync of that person's network on your Homie extension. It uses your saved search filters, the same ones your automatic sync uses. It is skipped if a sync through them is already queued or running, or if their network was searched in the last 7 days. The sync needs the extension online and takes a few minutes. New warm paths through the person appear later in
search_warm_paths.
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.
| Field | Type | Notes |
|---|---|---|
personId | string | Homie person id. Pass one of these two fields. |
connectionId | string | Connection 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).
| Field | Type | Notes |
|---|---|---|
id | string | Required. 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_sales_opportunities
List the organization's stored sales recommendations — prospects Homie 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.
| Field | Type | Notes |
|---|---|---|
status | string | visible, saved, accepted, intro_requested, or dismissed. Default: the active set. |
sort | string | newest (default), oldest, or relevancy. |
search | string | Substring match on prospect name, company, or position. |
limit | number | 1-50, default 20. |
offset | number | 0-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_sales_opportunities
Search the sales prospects Homie has already recommended, by keyword. Use it for questions like "any opportunities at fintechs?" or "opportunities matching Acme", when the user wants existing sales recommendations. 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.
| Field | Type | Notes |
|---|---|---|
query | string | Required. Substring matched against prospect name, company, and position. |
status | string | visible, saved, accepted, intro_requested, or dismissed. Default: the active set. |
sort | string | relevancy (default, highest overallScore first), newest, or oldest. |
limit | number | 1-50, default 20. |
offset | number | 0-based offset for pagination. Use the previous response's nextOffset. |
Returns the same payload as list_sales_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".
When query describes what the wanted companies do or run (for example "companies that run their own cloud or bare-metal infrastructure"), people whose current company's own description says so come first, followed by looser fits that match the other criteria only. The text note after the result says how many of each are on the page and lists any requirement Homie could not apply.
The response includes totalCount and returnedCount. Results come warmest-first, one page per call. A person's warmness is their best introduction route's strength; a route through a connector is as warm as its weaker hop. When the response has nextOffset, call again with the same arguments and offset set to it to get the next matches; no nextOffset means there are no further matches in the network.
Responses are compact: instead of raw warmness factor breakdowns, each connector in connectionSources carries readable connectorToProspectSignals (how the connector knows the person) and networkOwnerToConnectorSignals (how you or your teammate know the connector), and image URLs are omitted. When fewer than limit people on a page have an introduction route, the search reads further into the network to fill it. A page may still hold fewer results than limit to stay within the response size budget; always continue with nextOffset. A short text note after the result says in plain words whether more people match and how to fetch them.
The person, company, industry and position exclusions are applied while a page is chosen, so excluded people never use up a page. Connector exclusions remove routes after the page is chosen, so that page can hold fewer people.
| Field | Type | Notes |
|---|---|---|
query | string | Natural-language criteria. Optional when any structured criterion below is given. |
titles | string[] | Optional. Job titles to match; widened with similar titles unless similarTitles is false. |
industries | string[] | Optional. Current-company industries (LinkedIn names); widened with related ones unless similarIndustries is false. |
locations | string[] | Optional. Where the person is based: countries, states, regions or cities. |
companyLocations | string[] | Optional. Where the current company is headquartered. |
companySizes | string[] | Optional. Employee bands such as 201-500 or 10001+. |
similarTitles | boolean | Optional. Widen titles with similar ones. Default: on at strictness 1; true widens at any strictness, false keeps the given titles only. |
similarIndustries | boolean | Optional. Widen industries with related ones. Default true. |
networks | ("user" | "advocate" | "organization")[] | Default: all three. |
strictness | 1-3 | 1=relaxed (default), 2=normal, 3=strict. |
asUserId | string | Org 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. |
limit | number | 1-50, default 20. |
offset | number | Optional. The previous response's nextOffset. |
excludePersonIds | string[] | Optional. Person ids never to return, e.g. everyone already shown in this conversation. |
excludeCompanies | string[] | Optional. Leave out people currently at these companies (case-insensitive name match). |
excludeIndustries | string[] | Optional. Leave out people whose current company is in these industries, e.g. an ICP's exclusions. |
excludePositions | string[] | Optional. Title keywords to leave out, on word boundaries, e.g. account executive. |
directContacts | "include" | "exclude" | "only" | Optional. People you already know directly: include (default), exclude so every result needs an introduction, or only those people. |
excludeConnectorPersonIds | string[] | Optional. No route may pass through these connectors; people reachable only through them are left out. |
excludeConnectorNames | string[] | Optional. No route may pass through a connector with this name (substring). |
excludeConnectorCompanies | string[] | Optional. No route may pass through a connector currently at these companies. |
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.
get_path_details
The numbers behind one introduction route from a search_network result: each hop's stored warmness score, readable signals and the full factor breakdown (mutual connections, time worked or studied together, emails, meetings, reactions and each factor's score). Fetch it for the routes you want to explain, not for every result.
| Field | Type | Notes |
|---|---|---|
targetPersonId | string | Required. The result's person id. |
route | object | Required. The result's chosen connectionSources entry: type, plus advocatePersonId and teamMemberId when present. |
asUserId | string | The asUserId passed to search_network, if any. |
Returns found and hops[], each with from, to, warmness, signals and breakdown. found: false (with a message) means the route can't be verified for your organization, for example when the route's owner isn't a member or no longer holds the first hop.
search_people
Substring search across people in the network (1st-degree direct connections + 2nd-degree by default).
| Field | Type | Notes |
|---|---|---|
query | string | Required. Matches name, email, position, company. |
limit | number | 1-50, default 20. |
includeSecondDegree | boolean | Default 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.
| Field | Type | Notes |
|---|---|---|
query | string | Required. |
page | number | 1-based, default 1. |
limit | number | 1-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.
| Field | Type | Notes |
|---|---|---|
id | string | Required. 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 one of the target-list write tools.
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.
| Field | Type | Notes |
|---|---|---|
targetListId | string | Target-list id from list_target_lists. |
limit | number | 1-50, default 20. |
offset | number | 0-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.
| Field | Type | Notes |
|---|---|---|
name | string | Required. 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 add_company_to_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.
rename_target_list
Rename one of your own target lists. Requires mcp:write; other users' lists and organization API keys are rejected. It does not create a list or change membership.
| Field | Type | Notes |
|---|---|---|
targetListId | string | Required. List id from list_target_lists. |
name | string | Required. New list name, trimmed, 1–255 characters. |
Returns { action: "rename", changed, targetList }. Repeating the existing name returns changed:false.
add_company_to_target_list
Add one company to one of your own target lists. Requires mcp:write; other users' lists and organization API keys are rejected. Resolve the list with list_target_lists and the company with search_companies before the requested write. It does not create a company or create, rename or empty a list.
| Field | Type | Notes |
|---|---|---|
targetListId | string | Required. List id from list_target_lists. |
companyId | string | Required. The id or companyId returned by search_companies. |
Returns { action: "add_company", changed, targetList }. An existing membership returns changed:false.
add_companies_to_target_list
Add up to 20 companies to one of your own target lists and start LinkedIn discovery of warm paths to them. Requires mcp:write; other users' lists and organization API keys are rejected. Use it when you agree to it, typically after search_warm_paths found no warm path to a company.
| Field | Type | Notes |
|---|---|---|
targetListId | string | An existing list id from list_target_lists. Pass this or newListName. |
newListName | string | Creates a list with this name; an existing list with exactly this name is reused. |
companies | array | 1–20 entries, each { name } (the company name as you said it), { companyId } (the id or companyId from search_companies) or { linkedinUrl } (a LinkedIn company URL, for a company Homie does not have yet). |
discover | boolean | Start discovery for the companies. Defaults to true. |
Returns { createdList, targetList, companies: [{ input, status, companyId, company, candidates }], discovery }. Each company's status is added, already_in_list, not_found or ambiguous. A name is added only when one company clearly matches: the exact name with a verified LinkedIn ID and by far the most known employees. Otherwise it returns ambiguous with up to five candidates and adds nothing for that entry; choose one and pass its companyId. discovery.status is queued, nothing_to_sync, not_requested, unavailable or failed, with counts of companies queued, already searched for this list, and waiting for a verified LinkedIn company ID.
Discovery runs one LinkedIn people search for the added companies through your Homie extension: first with your saved filters, then once with only the company filter if nobody was found. It needs the extension online and takes minutes; new paths then appear in search_warm_paths. Companies already searched for the list are not searched again.
remove_company_from_target_list
Remove one company's membership from one of your own target lists. Requires mcp:write; other users' lists and organization API keys are rejected. Resolve the list and company before the requested write, using get_target_list when current membership is needed. It does not delete the company or list or remove other members.
| Field | Type | Notes |
|---|---|---|
targetListId | string | Required. List id from list_target_lists. |
companyId | string | Required. The id or companyId returned by search_companies. |
Returns { action: "remove_company", changed, targetList }. An absent membership returns changed:false.
Resources
Every tool hands back ids. Rather than re-running a search to turn an id back into a record, read it directly:
| URI | Returns |
|---|---|
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://icp | Same { configured, icp? } payload as get_icp. |
homie://ghost-opportunity/{id} | One opportunity, same shape as an entry from list_sales_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.