{"id":"032c6a36-a414-43b1-95d0-5bec3b661080","shortId":"3RLvxF","kind":"skill","title":"find-service-providers","tagline":"Use whenever the user wants to find, shortlist, vet, enrich, or research US professional-services firms — law, marketing, consulting, accounting, IT services, architecture, engineering, HR, PR, design, and similar B2B service providers. Triggers on requests like \"find me a PPC ag","description":"# find-service-providers\n\nDrive the **ServiceGraph API** (`https://api.servicegraph.co`) to find,\nshortlist, and enrich US professional-services firms. The catalog has\n100k+ B2B service firms classified across 22 industries with multi-tag\nservice taxonomies, location, size, and third-party rating signals.\n\nAny HTTP client works (curl, fetch, requests). Examples below use curl\nfor clarity.\n\n## MCP server (preferred for authed calls)\n\nIf your agent harness has the **ServiceGraph MCP server** loaded\n(`https://mcp.servicegraph.co`), prefer its tools for the **authed**\ntier (`/search`, `/get`, `/stats`). The MCP server uses OAuth 2.1 +\nPKCE — the host harness handles credentials in its own audited\nsandbox, so there's no `.env.local`, no shell dispatch, and no token\nvalue ever enters the LLM context.\n\nFor the **anonymous** tier (`/tags`, `/check`, `/explore`), MCP is\n**not** preferred — every MCP tool requires OAuth (the server has no\nanonymous tier), so plain curl against the REST URL is the simpler\npath for discovery calls. Use the REST patterns below for those.\n\nThe MCP tools 1:1-map to the public REST endpoints — same backend,\nsame quota, same data:\n\n| MCP tool | REST endpoint | Anon? | Recommended path |\n|---|---|---|---|\n| `list_tags` | `GET /v1/tags` | yes | curl |\n| `check_filter` | `GET /v1/check` | yes | curl |\n| `explore_firms` | `GET /v1/explore` | yes | curl |\n| `search_firms` | `GET /v1/search` | no | MCP if loaded, else curl + OTP |\n| `get_firm` | `GET /v1/get/:id` | no | MCP if loaded, else curl + OTP |\n| `catalog_stats` | `GET /v1/stats` | no | MCP if loaded, else curl + OTP |\n\n**Detection**: if you see any MCP tools with `servicegraph` in the\nname (the harness-specific prefix varies — agents pattern-match the\nsubstring), the ServiceGraph MCP server is loaded. Prefer those\ntools for the authed tier; complete any auth flow the harness\ninitiates if needed. If no `servicegraph` MCP tools are present,\nfall through to the REST + OTP flow below for the authed tier.\n\n## The four-tier funnel\n\nThe API is a deliberate cost funnel. Cheaper tiers are free or nearly\nfree; expensive tiers reveal more. **Always work down the funnel — don't\nskip tiers.**\n\n| Tier | Auth | Cost | Use it for |\n|---|---|---|---|\n| `GET /v1/tags` | none | free | **First call of every session.** Discover legal field names, kinds, operators, values. |\n| `GET /v1/check?filter=...` | none | free | Validate a filter before spending an explore/search call. |\n| `GET /v1/explore?filter=...` | none | free, IP-throttled | Scope: count + breakdowns. Use to size the candidate pool before quota-spending. |\n| `GET /v1/search?filter=...` | bearer | 200 unique firms / month free | Brief firm cards. **No url, no contact info.** Use for ranking / shortlisting. |\n| `GET /v1/get/:id` | bearer | 50 unique firms / month free | Full bundle: url, phone, email, social, legal name, address. **Only call for shortlisted firms.** |\n| `POST /v1/research` | paid | not in MVP | Deferred — skip. |\n\n**Quota rule that matters**: `/search` and `/get` charge per *unique firm\nviewed per calendar month*, not per call. Re-paging the same query is\nfree. Two different filters that overlap charge once for the overlap.\nRe-fetching a firm you already pulled this month is free.\n\n## Session-start ritual\n\nBefore constructing any filter, call:\n\n```\nGET https://api.servicegraph.co/v1/tags?include_values=1\n```\n\nCache the response for the conversation. It returns every filterable\nfield with its `kind`, allowed `operators`, and (for categorical /\ntag-set fields) the legal value list. **Never invent industry or\nservice values from memory** — the parser silently accepts unknown\nvalues for categorical fields and returns zero results.\n\nYou'll get five field kinds:\n\n- **categorical** (e.g. `industry`, `state`, `pricing_model`) — single value, op `:` only.\n- **tag_set_with_evidence** (e.g. `service_provided`) — Map<tag, evidence∈{low,medium,high}>. Op `:` with optional `@evidence`.\n- **numeric** (e.g. `rating`, `review_count_total`, `founded_year`) — ops `= >= <= > <`.\n- **presence** (`has:phone`, `has:clutch`, `has:rating`, …) — boolean populated-ness check on a column or third-party listing.\n- **keyword** — free-text substring across firm name / brand / title / meta description / legal name. Any bareword in the filter becomes a keyword.\n\n## Auth\n\n`/tags`, `/check`, and `/explore` are anonymous. `/search` and `/get`\nrequire a bearer token.\n\n**Security model — keep the token out of the LLM context.**\n\n- **Never** read `.env`, `.env.local`, or any other credential file\n  into your context. The token's literal value should never appear\n  in the conversation.\n- Use shell dispatch for every authed request so the token flows\n  directly from the user's environment / dotenv file into the\n  `Authorization` header without round-tripping through the LLM.\n- **Always ask the user once per session** before using a detected\n  token, even if it's already in their shell or `.env.local`.\n\n**Resolution rule**:\n\n1. **Detect** whether a token is available — without reading its\n   value. Run a shell check that only inspects exit codes:\n\n   ```bash\n   ( [ -n \"${SERVICEGRAPH_TOKEN:-}\" ] \\\n     || grep -qs '^SERVICEGRAPH_TOKEN=' .env.local \\\n     || grep -qs '^SERVICEGRAPH_TOKEN=' .env )\n   ```\n\n   Exit code `0` = token is available somewhere; non-zero = no token.\n\n2. **Confirm with the user** before the first authed call this session:\n\n   > \"I found a `SERVICEGRAPH_TOKEN` in your environment / `.env.local`.\n   > OK to use it for ServiceGraph API requests this session?\"\n\n   If the user says no, stay on the anonymous tiers (`/tags`, `/check`,\n   `/explore`) and skip authed calls. Don't re-ask later unless the\n   user asks for authed work.\n\n3. **Dispatch via shell** — every authed call goes through a shell\n   wrapper so the literal token never enters the conversation:\n\n   ```bash\n   # If exported in the shell environment:\n   curl -H \"Authorization: Bearer $SERVICEGRAPH_TOKEN\" \\\n        'https://api.servicegraph.co/v1/search?filter=...'\n\n   # If in .env.local — source it inside a subshell so it doesn't\n   # leak into the parent shell either:\n   ( set -a; . ./.env.local; set +a;\n     curl -H \"Authorization: Bearer $SERVICEGRAPH_TOKEN\" \\\n          'https://api.servicegraph.co/v1/search?filter=...' )\n   ```\n\n   Capture the response body to a tmp file or jq-process it, but do\n   NOT echo the request command with the token expanded.\n\n4. **OTP flow** if no token is detected — capture the new token\n   directly into `.env.local` without surfacing its value to the LLM:\n\n   ```bash\n   # 1. trigger the email — agent prompts the user for $EMAIL\n   curl -fsS -X POST 'https://api.servicegraph.co/v1/auth/request-otp' \\\n     -H 'Content-Type: application/json' \\\n     -d \"{\\\"email\\\":\\\"$EMAIL\\\"}\"\n\n   # 2. exchange the code — agent prompts the user for $CODE.\n   #    The ?format=env query param returns SERVICEGRAPH_TOKEN=<token>\n   #    as plain text appended to .env.local — no jq needed. The -f\n   #    flag makes curl exit non-zero on 4xx so a wrong code doesn't\n   #    pollute the file (the error mirror is also a `# comment` line,\n   #    safe to ignore even if it lands).\n   curl -fsS -X POST 'https://api.servicegraph.co/v1/auth/verify-otp?format=env' \\\n     -H 'Content-Type: application/json' \\\n     -d \"{\\\"email\\\":\\\"$EMAIL\\\",\\\"code\\\":\\\"$CODE\\\",\\\"name\\\":\\\"claude-cli\\\"}\" \\\n     >> .env.local\n\n   # 3. confirm capture without revealing the value\n   grep -q '^SERVICEGRAPH_TOKEN=' .env.local && echo \"OTP token captured.\"\n   ```\n\n   After a successful capture, the user has implicitly consented\n   (they just completed the flow), so proceed to dispatch (step 3).\n   The token is now persistent in `.env.local` for future sessions.\n\n5. If a `/search` or `/get` returns `401 unauthorized` mid-session,\n   the token expired or was revoked — re-run the OTP flow.\n\n## Filter DSL\n\nOne query parameter, GitHub-search-style.\n\n```\nfilter   := orExpr\norExpr   := andExpr (\"OR\" andExpr)*\nandExpr  := notExpr ((\"AND\")? notExpr)*    # whitespace = implicit AND\nnotExpr  := (\"NOT\" | \"-\") notExpr | atom\natom     := \"(\" filter \")\" | predicate\npredicate:= IDENT op valueOrList | bareword\nop       := \":\" | \"=\" | \">=\" | \"<=\" | \">\" | \"<\"\nvalueOrList := value (\",\" value)*\nvalue    := IDENT | NUMBER | tagAtEvidence\ntagAtEvidence := IDENT \"@\" (\"low\"|\"medium\"|\"high\")\nbareword := IDENT | NUMBER          # → keyword:<bareword>\n```\n\n**Four rules that bite:**\n\n1. **AND binds tighter than OR.** `a OR b c` parses as `a OR (b AND c)`.\n   Use parens.\n2. **Comma list = OR within one predicate.** `state:CA,NY,TX` matches\n   any of the three.\n3. **Negation is `-x` or `NOT x`.** Negative literals inside a comma\n   list are **not** allowed: `state:CA,-NY` is rejected. Use\n   `state:CA -state:NY`.\n4. **Bareword = keyword search.** Any IDENT or NUMBER not followed by an\n   operator becomes a free-text substring across name / brand / title /\n   meta / legal_name. Multiple barewords AND.\n\n**Examples** (validate yours with `/v1/check`):\n\n```\nindustry:marketing_agency service_provided:seo\ndental industry:marketing_agency\nindustry:legal state:CA,NY -company_size_signal:solo\nindustry:management_consulting (service_provided:strategy-consulting@high OR service_provided:operations-consulting@high)\nstate:CA has:phone has:email\nrating>=4 review_count_total>=20 has:clutch\nindustry:it_services NOT (service_provided:web-development OR service_provided:hosting)\n```\n\nWhen in doubt about whether a filter parses, hit `/v1/check?filter=...`\nfirst — it's free and returns the canonical normalized form.\n\n## firm_id contract\n\n`firm_id` is a stable 12-hex-char handle:\n\n```\nfirm_id = sha256(apex.lower().rstrip(\".\")).hexdigest()[:12]\n```\n\n`apex` is the registered domain (`mckinsey.com`, not\n`www.mckinsey.com/about`). Anyone with an apex list can compute firm_ids\nlocally and call `/v1/get/:id` directly — no `/search` needed for BYO\nenrichment.\n\n```python\nimport hashlib\ndef firm_id(apex):\n    return hashlib.sha256(apex.lower().rstrip(\".\").encode()).hexdigest()[:12]\n```\n\n```bash\necho -n \"mckinsey.com\" | tr 'A-Z' 'a-z' \\\n  | openssl dgst -sha256 -hex | awk '{print substr($2,1,12)}'\n```\n\n## Recipes\n\n### A. Shortlist by industry + state\n\n```\nGET /v1/explore?filter=industry:legal+state:CA+-company_size_signal:solo\n# → see pool size + breakdowns\n\nGET /v1/search?filter=industry:legal+state:CA+-company_size_signal:solo&limit=20\n# → 20 brief cards; pick top 3 with user\n\nGET /v1/get/<firm_id>     # for each of the 3 picks\n# → urls, phones, emails for outreach\n```\n\n### B. Multi-tag service intersection\n\nUser: *\"Marketing agency that does both branding and SEO at high evidence.\"*\n\n```\nGET /v1/explore?filter=industry:marketing_agency+service_provided:branding@high+service_provided:seo@high\n\nGET /v1/search?filter=industry:marketing_agency+service_provided:branding@high+service_provided:seo@high&limit=10\n```\n\n### C. Quality threshold\n\nUser: *\"Consultancies with at least 4★ and 20+ reviews and a Clutch listing.\"*\n\n```\nGET /v1/search?filter=industry:management_consulting+rating>=4+review_count_total>=20+has:clutch&limit=10\n```\n\n### D. Indirect intent — user describes a need without naming the category\n\nUser: *\"I need someone to handle our open enrollment communications for 200 employees.\"*\n\nThat's HR consulting + benefits comms. Translate, then verify with\n`/v1/check`:\n\n```\nGET /v1/check?filter=industry:hr_recruiting_staffing+service_provided:benefits-administration\n\nGET /v1/explore?filter=industry:hr_recruiting_staffing+service_provided:benefits-administration\n```\n\nIf the breakdown is too narrow, broaden — drop the service tag, add\nadjacent industries (`marketing_agency` for the comms angle), or fall\nback to keyword: `benefits enrollment industry:marketing_agency,hr_recruiting_staffing`.\n\n### E. Keyword + structured filter\n\nUser: *\"HIPAA-savvy IT consultancies in Texas.\"*\n\n```\nGET /v1/search?filter=hipaa+industry:it_services+state:TX&limit=10\n```\n\n`hipaa` is a bareword keyword → substring match in firm text.\n\n### F. BYO apex list — enrich domains the user already has\n\nUser pastes 12 domains. For each:\n\n1. Compute `firm_id` locally (see contract above).\n2. `GET /v1/get/<firm_id>` — full bundle if in catalog, 404 (not charged)\n   if not.\n3. Aggregate, present, flag the not-found ones to the user.\n\n`/get` only charges on first view per calendar month per user, so re-runs\nare free.\n\n## Gotchas\n\n- **`looks_not_pro_services` 404 is not a bug.** A `firm_id` may exist\n  in `/search` but 404 on `/get` if it's been flagged (residual SaaS /\n  B2C leakage). Skip and continue; not charged.\n- **`/v1/explore` k=20 suppression.** When fewer than 20 firms match,\n  the response is `{\"count\": \"<20\", \"suppressed\": true,\n  \"breakdowns\": {}}`. Drilling further makes the count smaller, not\n  bigger. Broaden the filter or escalate to `/v1/search` if the user\n  wants the actual firms.\n- **Briefs from `/search` do NOT include `apex`, `url`, `phone_primary`,\n  `email_primary`, `legal_name`, or address.** If the user asks for\n  contact info, you must `/get/:id`. Do not pretend to have it from\n  the brief.\n- **Catalog is US-only B2B pro-services.** Refuse non-US asks rather\n  than returning misleading partial matches. Refuse consumer-facing\n  legal/financial requests (e.g. *\"I need a divorce lawyer for\n  personal matters\"*) — the catalog is built for B2B procurement.\n- **Always use `/v1/tags` for legal field values.** Inventing\n  `industry:law` instead of `industry:legal` returns zero results\n  silently — the parser doesn't validate categorical values.\n- **Multi-word phrases must be split into separate barewords.**\n  `family law` parses as two AND'd keywords (`family` AND `law`),\n  not one phrase.\n- **Quota is per-user-per-month, deduped on first view.** Don't refuse\n  to look up a firm \"to save quota\" if the user already viewed it this\n  month — re-views are free.\n- **Re-pagination is free.** Pulling page 2 of the same `/search` query\n  doesn't re-charge for firms returned on page 1.\n\n## Errors\n\nAll errors return JSON: `{\"error\": {\"code\": \"...\", \"message\": \"...\"}}`.\n\n| Status | Code | What to do |\n|---|---|---|\n| 400 | `filter_parse_error` | Payload includes `position`. Fix the filter, re-validate with `/v1/check`. |\n| 400 | `filter_required` | Empty filter where one is required. |\n| 400 | `invalid_firm_id` | firm_id must be 12 lowercase hex chars. Re-derive. |\n| 401 | `unauthorized` | Token missing/expired. Re-run OTP. |\n| 404 | `not_found` | Firm not in catalog or flagged. Not charged. Skip and continue. |\n| 429 | `rate_limited` | Honor `Retry-After` header / `retry_after` field. |\n| 429 | `monthly_quota_exhausted` | Switch to `/v1/explore`-only mode for the rest of the month. Tell the user. |\n\nAuthed responses carry `X-RateLimit-*` and `X-Quota-*` headers. Surface\nthe remaining-month value to the user when it gets low so they can\nbudget.\n\n## End-to-end example\n\nUser: *\"Find me three top management-consulting firms in California\nfocused on strategy, with strong third-party ratings.\"*\n\n```\n# 1. Discover fields (once per session)\nGET /v1/tags?include_values=1\n# Confirms 'management_consulting' is a valid industry value, that\n# 'strategy-consulting' is in the service_provided taxonomy, and that\n# rating + review_count_total are numeric.\n\n# 2. Validate the filter and scope the pool (free, no auth)\nGET /v1/check?filter=industry:management_consulting+state:CA+service_provided:strategy-consulting@high+rating>=4+review_count_total>=20\n# → {\"valid\": true, \"normalized\": \"...\"}\n\nGET /v1/explore?filter=industry:management_consulting+state:CA+service_provided:strategy-consulting@high+rating>=4+review_count_total>=20\n# → {\"count\": 47, \"breakdowns\": {...}}\n\n# 3. Search briefs (charges new firms against monthly /search quota)\nGET /v1/search?filter=...&limit=10\n# Header: Authorization: Bearer $SERVICEGRAPH_TOKEN\n# → 10 brief cards with industry, service tags, size, state, etc.\n\n# 4. Present briefs to user, get their pick of 3.\n\n# 5. Pull full bundles for the 3 (charges 3 against monthly /get quota)\nGET /v1/get/<firm_id>     # ×3\n# → urls, phones, emails for outreach\n```\n\nEnd of session: report `X-Quota-Remaining-Month` so the user knows how\nmuch budget is left.","tags":["find","service","providers","servicegraph","nostrband","agent-skills","ai-agents","b2b-data","claude-code-marketplace","claude-code-plugins","claude-code-skills","claude-plugins"],"capabilities":["skill","source-nostrband","skill-find-service-providers","topic-agent-skills","topic-ai-agents","topic-b2b-data","topic-claude-code-marketplace","topic-claude-code-plugins","topic-claude-code-skills","topic-claude-plugins","topic-claude-skills","topic-mcp-server","topic-openapi","topic-professional-services","topic-vendor-discovery"],"categories":["ServiceGraph"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/nostrband/ServiceGraph/find-service-providers","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add nostrband/ServiceGraph","source_repo":"https://github.com/nostrband/ServiceGraph","install_from":"skills.sh"}},"qualityScore":"0.530","qualityRationale":"deterministic score 0.53 from registry signals: · indexed on github topic:agent-skills · 160 github stars · SKILL.md body (16,205 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T18:56:03.848Z","embedding":null,"createdAt":"2026-05-06T12:58:11.625Z","updatedAt":"2026-05-18T18:56:03.848Z","lastSeenAt":"2026-05-18T18:56:03.848Z","tsv":"'/.env.local':946 '/about':1446 '/check':170,684,871 '/explore':171,686,872 '/get':129,495,691,1165,1812,1849,1929,2391 '/search':128,493,689,1163,1463,1845,1906,2077,2348 '/stats':130 '/tags':169,683,870 '/v1/auth/request-otp''':1021 '/v1/auth/verify-otp?format=env''':1098 '/v1/check':241,404,1333,1405,1672,1674,2117,2295 '/v1/explore':247,417,1510,1577,1686,1864,2181,2318 '/v1/get':264,459,1459,1546,1789,2394 '/v1/research':482 '/v1/search':253,438,1525,1591,1623,1743,1896,2351 '/v1/search?filter=...''':925,957 '/v1/stats':276 '/v1/tags':235,388,1984,2253 '/v1/tags?include_values=1':549 '0':819 '1':211,212,783,1005,1239,1501,1779,2089,2246,2256 '10':1605,1637,1752,2354,2360 '100k':69 '12':1425,1436,1481,1502,1775,2135 '2':829,1030,1258,1500,1787,2073,2283 '2.1':136 '20':1380,1536,1537,1616,1633,1866,1871,1878,2313,2336 '200':441,1660 '22':75 '3':890,1114,1149,1274,1542,1551,1800,2340,2379,2386,2388,2395 '4':982,1300,1376,1614,1629,2309,2332,2370 '400':2103,2118,2127 '401':1167,2142 '404':1795,1834,1847,2150 '429':2164,2175 '47':2338 '4xx':1067 '5':1160,2380 '50':462 'a-z':1487,1490 'accept':588 'account':25 'across':74,665,1319 'actual':1902 'add':1708 'address':475,1919 'adjac':1709 'administr':1684,1696 'ag':46 'agenc':1336,1343,1566,1581,1595,1712,1726 'agent':112,302,1009,1034 'aggreg':1801 'allow':564,1289 'alreadi':531,775,1771,2056 'also':1081 'alway':372,759,1982 'andexpr':1196,1198,1199 'angl':1716 'anon':229 'anonym':167,185,688,868 'anyon':1447 'apex':1437,1450,1474,1765,1910 'apex.lower':1433,1477 'api':54,355,856 'api.servicegraph.co':55,548,924,956,1020,1097 'api.servicegraph.co/v1/auth/request-otp''':1019 'api.servicegraph.co/v1/auth/verify-otp?format=env''':1096 'api.servicegraph.co/v1/search?filter=...''':923,955 'api.servicegraph.co/v1/tags?include_values=1':547 'appear':725 'append':1051 'application/json':1026,1103 'architectur':28 'ask':760,881,886,1923,1953 'atom':1209,1210 'audit':146 'auth':108,126,319,323,347,382,682,734,837,875,888,895,2193,2293 'author':750,919,951,2356 'avail':789,822 'awk':1497 'b':1247,1253,1558 'b2b':35,70,1945,1980 'b2c':1857 'back':1719 'backend':220 'bareword':675,1217,1231,1301,1327,1756,2016 'bash':803,910,1004,1482 'bearer':440,461,694,920,952,2357 'becom':679,1313 'benefit':1666,1683,1695,1722 'benefits-administr':1682,1694 'bigger':1889 'bind':1241 'bite':1238 'bodi':961 'boolean':647 'brand':668,1321,1570,1584,1598 'breakdown':426,1523,1699,1881,2339 'brief':446,1538,1904,1939,2342,2361,2372 'broaden':1703,1890 'budget':2220,2416 'bug':1838 'built':1978 'bundl':468,1791,2383 'byo':1466,1764 'c':1248,1255,1606 'ca':1266,1291,1297,1347,1370,1515,1530,2301,2324 'cach':550 'calendar':502,1819 'california':2236 'call':109,200,392,415,477,506,545,838,876,896,1458 'candid':431 'canon':1414 'captur':958,990,1116,1129,1133 'card':448,1539,2362 'carri':2195 'catalog':67,273,1794,1940,1976,2156 'categor':568,592,604,2005 'categori':1648 'char':1428,2138 'charg':496,520,1797,1814,1863,2083,2160,2343,2387 'cheaper':361 'check':238,651,797 'clariti':103 'classifi':73 'claud':1111 'claude-c':1110 'cli':1112 'client':93 'clutch':644,1382,1620,1635 'code':802,818,1033,1039,1071,1107,1108,2096,2099 'column':654 'comm':1667,1715 'comma':1259,1285 'command':977 'comment':1083 'communic':1658 'compani':1349,1516,1531 'complet':321,1141 'comput':1453,1780 'confirm':830,1115,2257 'consent':1138 'construct':542 'consult':24,1355,1360,1367,1610,1627,1665,1739,2233,2259,2268,2299,2306,2322,2329 'consum':1962 'consumer-fac':1961 'contact':452,1925 'content':1024,1101 'content-typ':1023,1100 'context':164,705,717 'continu':1861,2163 'contract':1419,1785 'convers':555,728,909 'cost':359,383 'count':425,635,1378,1631,1877,1886,2279,2311,2334,2337 'credenti':142,713 'curl':95,101,189,237,243,249,259,271,282,917,949,1015,1061,1092 'd':1027,1104,1638,2023 'data':224 'dedup':2038 'def':1471 'defer':487 'deliber':358 'dental':1340 'deriv':2141 'describ':1642 'descript':671 'design':32 'detect':284,769,784,989 'develop':1391 'dgst':1494 'differ':516 'direct':740,994,1461 'discov':396,2247 'discoveri':199 'dispatch':155,731,891,1147 'divorc':1970 'doesn':936,1072,2002,2079 'domain':1441,1768,1776 'dotenv':746 'doubt':1398 'drill':1882 'drive':51 'drop':1704 'dsl':1185 'e':1730 'e.g':605,618,632,1966 'echo':974,1126,1483 'either':943 'els':258,270,281 'email':471,1008,1014,1028,1029,1105,1106,1374,1555,1914,2398 'employe':1661 'empti':2121 'encod':1479 'end':2222,2224,2401 'end-to-end':2221 'endpoint':218,228 'engin':29 'enrich':14,60,1467,1767 'enrol':1657,1723 'enter':161,907 'env':708,816,1042 'env.local':152,709,780,811,849,928,996,1053,1113,1125,1156 'environ':745,848,916 'error':1078,2090,2092,2095,2106 'escal':1894 'etc':2369 'even':771,1088 'ever':160 'everi':176,394,558,733,894 'evid':617,623,630,1575 'exampl':98,1329,2225 'exchang':1031 'exhaust':2178 'exist':1843 'exit':801,817,1062 'expand':981 'expens':368 'expir':1174 'explor':244 'explore/search':414 'export':912 'f':1058,1763 'face':1963 'fall':337,1718 'famili':2017,2025 'fetch':96,527 'fewer':1869 'field':398,560,572,593,602,1987,2174,2248 'file':714,747,965,1076 'filter':239,405,410,418,439,517,544,559,678,1184,1193,1211,1402,1406,1511,1526,1578,1592,1624,1675,1687,1733,1744,1892,2104,2112,2119,2122,2286,2296,2319,2352 'find':2,11,42,48,57,2227 'find-service-provid':1,47 'firm':21,65,72,245,251,262,443,447,464,480,499,529,666,1417,1420,1430,1454,1472,1761,1781,1840,1872,1903,2049,2085,2129,2131,2153,2234,2345 'first':391,836,1407,1816,2040 'five':601 'fix':2110 'flag':1059,1803,1854,2158 'flow':324,343,739,984,1143,1183 'focus':2237 'follow':1309 'form':1416 'format':1041 'found':637,842,1807,2152 'four':351,1235 'four-tier':350 'free':364,367,390,407,420,445,466,514,536,662,1316,1410,1828,2065,2070,2291 'free-text':661,1315 'fss':1016,1093 'full':467,1790,2382 'funnel':353,360,376 'futur':1158 'get':234,240,246,252,261,263,275,387,403,416,437,458,546,600,1509,1524,1545,1576,1590,1622,1673,1685,1742,1788,2215,2252,2294,2317,2350,2375,2393 'github':1190 'github-search-styl':1189 'goe':897 'gotcha':1829 'grep':807,812,1121 'h':918,950,1022,1099 'handl':141,1429,1654 'har':113,140,298,326 'harness-specif':297 'hashlib':1470 'hashlib.sha256':1476 'header':751,2171,2203,2355 'hex':1427,1496,2137 'hex-char':1426 'hexdigest':1435,1480 'high':626,1230,1361,1368,1574,1585,1589,1599,1603,2307,2330 'hipaa':1736,1745,1753 'hipaa-savvi':1735 'hit':1404 'honor':2167 'host':139,1395 'hr':30,1664,1677,1689,1727 'http':92 'id':265,460,1418,1421,1431,1455,1460,1473,1782,1841,1930,2130,2132 'ident':1214,1223,1227,1232,1305 'ignor':1087 'implicit':1137,1204 'import':1469 'includ':1909,2108,2254 'indirect':1639 'industri':76,579,606,1334,1341,1344,1353,1383,1507,1512,1527,1579,1593,1625,1676,1688,1710,1724,1746,1990,1994,2263,2297,2320,2364 'info':453,1926 'initi':327 'insid':931,1283 'inspect':800 'instead':1992 'intent':1640 'intersect':1563 'invalid':2128 'invent':578,1989 'ip':422 'ip-throttl':421 'jq':968,1055 'jq-process':967 'json':2094 'k':1865 'keep':698 'keyword':660,681,1234,1302,1721,1731,1757,2024 'kind':400,563,603 'know':2413 'land':1091 'later':882 'law':22,1991,2018,2027 'lawyer':1971 'leak':938 'leakag':1858 'least':1613 'left':2418 'legal':397,473,574,672,1324,1345,1513,1528,1916,1986,1995 'legal/financial':1964 'like':41 'limit':1535,1604,1636,1751,2166,2353 'line':1084 'list':232,576,659,1260,1286,1451,1621,1766 'liter':721,904,1282 'll':599 'llm':163,704,758,1003 'load':119,257,269,280,313 'local':1456,1783 'locat':83 'look':1830,2046 'low':624,1228,2216 'lowercas':2136 'make':1060,1884 'manag':1354,1626,2232,2258,2298,2321 'management-consult':2231 'map':213,621 'market':23,1335,1342,1565,1580,1594,1711,1725 'match':305,1269,1759,1873,1959 'matter':492,1974 'may':1842 'mckinsey.com':1442,1485 'mcp':104,117,132,172,177,209,225,255,267,278,289,310,333 'mcp.servicegraph.co':120 'medium':625,1229 'memori':584 'messag':2097 'meta':670,1323 'mid':1170 'mid-sess':1169 'mirror':1079 'mislead':1957 'missing/expired':2145 'mode':2183 'model':609,697 'month':444,465,503,534,1820,2037,2060,2176,2189,2208,2347,2390,2409 'much':2415 'multi':79,1560,2008 'multi-tag':78,1559 'multi-word':2007 'multipl':1326 'must':1928,2011,2133 'mvp':486 'n':804,1484 'name':295,399,474,667,673,1109,1320,1325,1646,1917 'narrow':1702 'near':366 'need':329,1056,1464,1644,1651,1968 'negat':1275,1281 'ness':650 'never':577,706,724,906 'new':992,2344 'non':825,1064,1951 'non-us':1950 'non-zero':824,1063 'none':389,406,419 'normal':1415,2316 'not-found':1805 'notexpr':1200,1202,1206,1208 'number':1224,1233,1307 'numer':631,2282 'ny':1267,1292,1299,1348 'oauth':135,180 'ok':850 'one':1186,1263,1808,2029,2124 'op':612,627,639,1215,1218 'open':1656 'openssl':1493 'oper':401,565,1312,1366 'operations-consult':1365 'option':629 'orexpr':1194,1195 'otp':260,272,283,342,983,1127,1182,2149 'outreach':1557,2400 'overlap':519,524 'page':509,2072,2088 'pagin':2068 'paid':483 'param':1044 'paramet':1188 'paren':1257 'parent':941 'pars':1249,1403,2019,2105 'parser':586,2001 'parti':88,658,2244 'partial':1958 'past':1774 'path':197,231 'pattern':204,304 'pattern-match':303 'payload':2107 'per':497,501,505,764,1818,1821,2034,2036,2250 'per-user-per-month':2033 'persist':1154 'person':1973 'phone':470,642,1372,1554,1912,2397 'phrase':2010,2030 'pick':1540,1552,2377 'pkce':137 'plain':188,1049 'pollut':1074 'pool':432,1521,2290 'popul':649 'populated-':648 'posit':2109 'post':481,1018,1095 'ppc':45 'pr':31 'predic':1212,1213,1264 'prefer':106,121,175,314 'prefix':300 'presenc':640 'present':336,1802,2371 'pretend':1933 'price':608 'primari':1913,1915 'print':1498 'pro':1832,1947 'pro-servic':1946 'proceed':1145 'process':969 'procur':1981 'profession':19,63 'professional-servic':18,62 'prompt':1010,1035 'provid':4,37,50,620,1338,1357,1364,1388,1394,1583,1587,1597,1601,1681,1693,2273,2303,2326 'public':216 'pull':532,2071,2381 'python':1468 'q':1122 'qs':808,813 'qualiti':1607 'queri':512,1043,1187,2078 'quota':222,435,489,2031,2052,2177,2202,2349,2392,2407 'quota-spend':434 'rank':456 'rate':89,633,646,1375,1628,2165,2245,2277,2308,2331 'ratelimit':2198 'rather':1954 're':508,526,880,1179,1825,2062,2067,2082,2114,2140,2147 're-ask':879 're-charg':2081 're-der':2139 're-fetch':525 're-pag':507 're-pagin':2066 're-run':1178,1824,2146 're-valid':2113 're-view':2061 'read':707,791 'recip':1503 'recommend':230 'recruit':1678,1690,1728 'refus':1949,1960,2044 'regist':1440 'reject':1294 'remain':2207,2408 'remaining-month':2206 'report':2404 'request':40,97,735,857,976,1965 'requir':179,692,2120,2126 'research':16 'residu':1855 'resolut':781 'respons':552,960,1875,2194 'rest':192,203,217,227,341,2186 'result':597,1998 'retri':2169,2172 'retry-aft':2168 'return':557,595,1045,1166,1412,1475,1956,1996,2086,2093 'reveal':370,1118 'review':634,1377,1617,1630,2278,2310,2333 'revok':1177 'ritual':540 'round':754 'round-trip':753 'rstrip':1434,1478 'rule':490,782,1236 'run':794,1180,1826,2148 'saa':1856 'safe':1085 'sandbox':147 'save':2051 'savvi':1737 'say':863 'scope':424,2288 'search':250,1191,1303,2341 'secur':696 'see':287,1520,1784 'seo':1339,1572,1588,1602 'separ':2015 'server':105,118,133,182,311 'servic':3,20,27,36,49,64,71,81,581,619,1337,1356,1363,1385,1387,1393,1562,1582,1586,1596,1600,1680,1692,1706,1748,1833,1948,2272,2302,2325,2365 'servicegraph':53,116,292,309,332,805,809,814,844,855,921,953,1046,1123,2358 'session':395,538,765,840,859,1159,1171,2251,2403 'session-start':537 'set':571,615,944,947 'sha256':1432,1495 'shell':154,730,778,796,893,900,915,942 'shortlist':12,58,457,479,1505 'signal':90,1351,1518,1533 'silent':587,1999 'similar':34 'simpler':196 'singl':610 'size':84,429,1350,1517,1522,1532,2367 'skill' 'skill-find-service-providers' 'skip':379,488,874,1859,2161 'smaller':1887 'social':472 'solo':1352,1519,1534 'someon':1652 'somewher':823 'sourc':929 'source-nostrband' 'specif':299 'spend':412,436 'split':2013 'stabl':1424 'staf':1679,1691,1729 'start':539 'stat':274 'state':607,1265,1290,1296,1298,1346,1369,1508,1514,1529,1749,2300,2323,2368 'status':2098 'stay':865 'step':1148 'strategi':1359,2239,2267,2305,2328 'strategy-consult':1358,2266,2304,2327 'strong':2241 'structur':1732 'style':1192 'subshel':933 'substr':307,664,1318,1499,1758 'success':1132 'suppress':1867,1879 'surfac':998,2204 'switch':2179 'tag':80,233,570,614,622,1561,1707,2366 'tag-set':569 'tagatevid':1225,1226 'taxonomi':82,2274 'tell':2190 'texa':1741 'text':663,1050,1317,1762 'third':87,657,2243 'third-parti':86,656,2242 'three':1273,2229 'threshold':1608 'throttl':423 'tier':127,168,186,320,348,352,362,369,380,381,869 'tighter':1242 'titl':669,1322 'tmp':964 'token':158,695,700,719,738,770,787,806,810,815,820,828,845,905,922,954,980,987,993,1047,1124,1128,1151,1173,2144,2359 'tool':123,178,210,226,290,316,334 'top':1541,2230 'topic-agent-skills' 'topic-ai-agents' 'topic-b2b-data' 'topic-claude-code-marketplace' 'topic-claude-code-plugins' 'topic-claude-code-skills' 'topic-claude-plugins' 'topic-claude-skills' 'topic-mcp-server' 'topic-openapi' 'topic-professional-services' 'topic-vendor-discovery' 'total':636,1379,1632,2280,2312,2335 'tr':1486 'translat':1668 'trigger':38,1006 'trip':755 'true':1880,2315 'two':515,2021 'tx':1268,1750 'type':1025,1102 'unauthor':1168,2143 'uniqu':442,463,498 'unknown':589 'unless':883 'url':193,450,469,1553,1911,2396 'us':17,61,1943,1952 'us-on':1942 'use':5,100,134,201,384,427,454,729,767,852,1256,1295,1983 'user':8,743,762,833,862,885,1012,1037,1135,1544,1564,1609,1641,1649,1734,1770,1773,1811,1822,1899,1922,2035,2055,2192,2212,2226,2374,2412 'valid':408,1330,2004,2115,2262,2284,2314 'valu':159,402,575,582,590,611,722,793,1000,1120,1220,1221,1222,1988,2006,2209,2255,2264 'valueorlist':1216,1219 'vari':301 'verifi':1670 'vet':13 'via':892 'view':500,1817,2041,2057,2063 'want':9,1900 'web':1390 'web-develop':1389 'whenev':6 'whether':785,1400 'whitespac':1203 'within':1262 'without':752,790,997,1117,1645 'word':2009 'work':94,373,889 'wrapper':901 'wrong':1070 'www.mckinsey.com':1445 'www.mckinsey.com/about':1444 'x':1017,1094,1277,1280,2197,2201,2406 'x-quota':2200 'x-quota-remaining-month':2405 'x-ratelimit':2196 'year':638 'yes':236,242,248 'z':1489,1492 'zero':596,826,1065,1997","prices":[{"id":"fb07edb8-57b1-4306-92ad-ba012983db5e","listingId":"032c6a36-a414-43b1-95d0-5bec3b661080","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"nostrband","category":"ServiceGraph","install_from":"skills.sh"},"createdAt":"2026-05-06T12:58:11.625Z"}],"sources":[{"listingId":"032c6a36-a414-43b1-95d0-5bec3b661080","source":"github","sourceId":"nostrband/ServiceGraph/find-service-providers","sourceUrl":"https://github.com/nostrband/ServiceGraph/tree/main/skills/find-service-providers","isPrimary":false,"firstSeenAt":"2026-05-06T12:58:11.625Z","lastSeenAt":"2026-05-18T18:56:03.848Z"}],"details":{"listingId":"032c6a36-a414-43b1-95d0-5bec3b661080","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"nostrband","slug":"find-service-providers","github":{"repo":"nostrband/ServiceGraph","stars":160,"topics":["agent-skills","ai-agents","b2b-data","claude-code-marketplace","claude-code-plugins","claude-code-skills","claude-plugins","claude-skills","mcp-server","openapi","professional-services","vendor-discovery"],"license":"mit","html_url":"https://github.com/nostrband/ServiceGraph","pushed_at":"2026-05-07T12:11:52Z","description":"AI Agent skills for a structured catalog of 100k+ US professional-services firms","skill_md_sha":"2c0aeb73aec10e608e802efaac91b401f3e6f7f2","skill_md_path":"skills/find-service-providers/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/nostrband/ServiceGraph/tree/main/skills/find-service-providers"},"layout":"multi","source":"github","category":"ServiceGraph","frontmatter":{"name":"find-service-providers","license":"MIT","description":"Use whenever the user wants to find, shortlist, vet, enrich, or research US professional-services firms — law, marketing, consulting, accounting, IT services, architecture, engineering, HR, PR, design, and similar B2B service providers. Triggers on requests like \"find me a PPC agency in California\", \"shortlist three boutique IP law firms\", \"build a longlist of 50 mid-size IT consultancies\", or \"here are 12 agency domains — pull contact info and confirm which are US-based\", even when the need is described indirectly without naming a category. Drives the ServiceGraph API (api.servicegraph.co) — a 100k+ US firm catalog with filters for industry, services, location, size, ratings, and third-party listings. Skip when the user is asking for personal/consumer services for themselves (an individual's own legal, tax, or medical needs), non-US firms, individual freelancers, retail/ecommerce/SaaS-product companies, recruiting-an-employee tasks, or general web research that doesn't need a structured firm directory."},"skills_sh_url":"https://skills.sh/nostrband/ServiceGraph/find-service-providers"},"updatedAt":"2026-05-18T18:56:03.848Z"}}