{"id":"2b5f1ee8-f37e-427a-8fe3-1b0dad64c908","shortId":"us3nK7","kind":"skill","title":"find-seo-agency","tagline":"Use whenever the user wants to find, shortlist, vet, or enrich US SEO agencies — technical SEO, on-page/off-page, link-building, content-led SEO, local SEO, ecommerce SEO, B2B SEO, and SEO audits. Triggers on \"find me an SEO agency in Texas\", \"shortlist three technical SEO consul","description":"# find-seo-agency\n\nDrive the **ServiceGraph API** (`https://api.servicegraph.co`) to find,\nshortlist, and enrich US SEO agencies. The catalog has thousands of US\nfirms tagged with `service_provided:seo` under\n`industry:marketing_agency`.\n\n**Always pin both `industry:marketing_agency` and\n`service_provided:seo`.** SEO sub-flavors (technical, local,\nlink-building, on-page, ecommerce, B2B, etc.) are not separate tags\n— the catalog has one `seo` tag — so sub-flavor specialization is\ninferred via keyword search across firm text.\n\nAny HTTP client works (curl, fetch, requests). Examples below use curl.\n\n## Sibling skills — defer when scope is broader\n\nIf the user wants a **multi-service** marketing engagement (SEO plus\nPPC plus content plus social, or a \"full-service digital agency\"),\ndefer to `find-marketing-agency` — that skill covers the same\ncatalog with a broader filter and won't over-constrain on SEO.\n\nIf the user wants strictly web/app development (build a site, ship\na feature), defer to `find-web-developer` / `find-software-developer`.\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\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\nfirm viewed per calendar month*, not per call. Re-paging the same\nquery is free. Two different filters that overlap charge once for\nthe overlap. Re-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. Confirm `seo` is present in\nthe `service_provided` taxonomy returned by `/tags`. The parser\nsilently accepts unknown tags and returns zero results, so verifying\nthe tag name once per session prevents silent failures.\n\nField kinds you'll use most:\n- **categorical**: `industry` (always `marketing_agency`), `state`, `pricing_model`, `company_size_signal`, `geography_served` — op `:`\n- **tag_set_with_evidence**: `service_provided` (always include `seo`, optionally with `@high` evidence) — op `:` with optional `@evidence`\n- **numeric**: `rating`, `review_count_total`, `founded_year` — ops `= >= <= > <`\n- **presence**: `has:phone`, `has:clutch`, `has:rating`, `has:linkedin_company`, …\n- **keyword**: free-text substring across firm name / brand / title / meta / legal_name. 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\n   an operator becomes a free-text substring across name / brand /\n   title / meta / legal_name. Multiple barewords AND.\n\n**SEO-flavored examples** (validate yours with `/v1/check`):\n\n```\nindustry:marketing_agency service_provided:seo\nindustry:marketing_agency service_provided:seo@high state:TX\nindustry:marketing_agency service_provided:seo technical\nindustry:marketing_agency service_provided:seo local\nindustry:marketing_agency service_provided:seo ecommerce\nindustry:marketing_agency service_provided:seo b2b saas\nindustry:marketing_agency service_provided:seo@high rating>=4 review_count_total>=20 has:clutch\nindustry:marketing_agency service_provided:seo \"core web vitals\"\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**Sub-flavor → keyword mapping** (since the catalog has one `seo` tag):\n\n| User asks for | Add as keyword |\n|---|---|\n| Technical SEO | `technical` |\n| Local SEO | `local` |\n| Link-building | `link-building` or `links` |\n| On-page SEO | `on-page` or `onpage` |\n| Off-page SEO | `off-page` or `offpage` |\n| Ecommerce SEO | `ecommerce` |\n| B2B SEO | `b2b` |\n| Shopify SEO | `shopify` |\n| Core Web Vitals / page speed | `core web vitals` (note: multi-word splits into separate ANDed barewords) |\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 (`searchpilot.com`, not\n`www.searchpilot.com/about`). Anyone with an apex list can compute\nfirm_ids locally and call `/v1/get/:id` directly — no `/search`\nneeded for BYO enrichment.\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 \"searchpilot.com\" | tr 'A-Z' 'a-z' \\\n  | openssl dgst -sha256 -hex | awk '{print substr($2,1,12)}'\n```\n\n## Recipes\n\n### A. SEO agency in a state (the baseline)\n\nUser: *\"Find me an SEO agency in Texas.\"*\n\n```\nGET /v1/explore?filter=industry:marketing_agency+service_provided:seo+state:TX\n# → pool size + breakdowns\n\nGET /v1/search?filter=industry:marketing_agency+service_provided:seo+state:TX&limit=10\n# → 10 brief cards; user picks 3\n\nGET /v1/get/<firm_id>     # ×3\n# → urls, phones, emails for outreach\n```\n\n### B. Technical SEO for a SaaS company\n\nUser: *\"Three technical SEO consultancies for a B2B SaaS company.\"*\n\n`technical` and `b2b` and `saas` go in as barewords; SEO sub-flavor\nisn't a structured tag.\n\n```\nGET /v1/search?filter=industry:marketing_agency+service_provided:seo@high+technical+b2b+saas&limit=10\n```\n\n### C. Link-building + on-page for ecommerce\n\nUser: *\"Help with link-building and on-page SEO for our ecommerce store.\"*\n\n```\nGET /v1/search?filter=industry:marketing_agency+service_provided:seo+link-building+on-page+ecommerce\n```\n\nIf the breakdown is sparse, drop one of the barewords (start with\n`on-page`) — agencies that do SEO at all usually do both.\n\n### D. Local SEO for a multi-location business\n\nUser: *\"Local SEO agency to help our chain of fitness studios in NJ.\"*\n\n```\nGET /v1/search?filter=industry:marketing_agency+service_provided:seo+local+state:NJ&limit=10\n```\n\nThe catalog tags one `state` per firm (HQ); the local-SEO firm doesn't\nhave to be in NJ to serve NJ clients. If results are too narrow,\ndrop `state:NJ` and use `geography_served:national_US,multi_state_regional`.\n\n### E. Indirect intent — \"organic traffic flat\"\n\nUser: *\"Our organic traffic has been flat for 6 months — we need an\nSEO partner.\"*\n\nThat's an SEO procurement ask. Translate:\n\n```\nGET /v1/explore?filter=industry:marketing_agency+service_provided:seo\n# → confirm the pool exists\n\nGET /v1/search?filter=industry:marketing_agency+service_provided:seo&limit=10&order_by=relevance\n```\n\nIf the user gave a vertical or location elsewhere in the conversation,\nadd it. Otherwise present the top-10 by relevance and ask for\nconstraints.\n\n### F. Quality threshold + third-party signals\n\nUser: *\"Three SEO agencies with at least 4-star ratings, 20+ reviews,\nand a Clutch profile.\"*\n\n```\nGET /v1/search?filter=industry:marketing_agency+service_provided:seo@high+rating>=4+review_count_total>=20+has:clutch&limit=10\n```\n\n### G. BYO apex list — enrich domains the user already has\n\nUser pastes 8–20 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\n   charged) if not.\n3. Aggregate, present, flag the not-found ones to the user.\n\nUseful for confirming whether a list of \"SEO firm\" domains is actually\nin the catalog and pulling contact info in one pass. Note that not\nevery firm with `seo` in their domain is tagged `service_provided:seo`\nin the catalog — a 404 here doesn't mean the firm doesn't exist, just\nthat we don't have it.\n\n## Gotchas\n\n- **Always pin both `industry:marketing_agency` AND `service_provided:seo`.** Without the industry pin, `service_provided:seo` would match SEO services from IT firms or design shops too. Without the service pin, you'd return all marketing agencies regardless of SEO specialty.\n- **SEO sub-flavors (technical/local/link-building/on-page) are NOT separate tags.** Use barewords (`technical`, `local`, `link-building`, etc.) for sub-flavor — these become keyword substring matches in firm text.\n- **Defer to `find-marketing-agency` for multi-service scope.** If the user wants SEO plus paid plus content plus social as one engagement, that's a full-service marketing ask, not strictly SEO.\n- **Defer to `find-web-developer` for \"fix our site speed / Core Web Vitals\" if they want it BUILT.** SEO agencies advise on CWV; they generally don't refactor your front-end. If the user wants development work, that's web-dev, not SEO.\n- **`looks_not_pro_services` 404 is not a bug.** A `firm_id` may exist in `/search` but 404 on `/get` if it's been flagged. Skip and continue; not charged.\n- **`/v1/explore` k=20 suppression.** When fewer than 20 firms match, the response is `{\"count\": \"<20\", \"suppressed\": true, \"breakdowns\": {}}`. Drilling further makes the count smaller. Broaden or escalate to `/v1/search`.\n- **Briefs from `/search` do NOT include `apex`, `url`, `phone_primary`, `email_primary`, `legal_name`, or address.** If the user asks for contact info, you must `/get/:id`. Do not pretend to have it from the brief.\n- **Catalog is US-only B2B.** Refuse non-US asks (\"an SEO agency in Berlin\"), individual freelancers (\"a freelance SEO writer\"), and DIY/do-the-work asks (\"how do I rank for X\").\n- **\"SEM\" / \"PPC\" / \"paid search\" / \"Google Ads\" are NOT SEO.** Defer those to `find-marketing-agency`. SEM-vs-SEO is a frequent terminology mix-up.\n- **Multi-word phrases must be split into separate barewords.** `core web vitals` parses as three AND'd keywords.\n- **Quota is per-user-per-month, deduped on first view.** Re-views are free; re-pagination is free.\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: *\"Three technical SEO consultancies for a B2B SaaS company,\nideally with at least a 4-star rating and a Clutch listing.\"*\n\n```\n# 1. Discover fields (once per session)\nGET /v1/tags?include_values=1\n# Confirms 'seo' is a valid service_provided tag, 'rating' is numeric,\n# 'has:clutch' is a presence flag.\n\n# 2. Validate the filter and scope the pool (free, no auth)\nGET /v1/check?filter=industry:marketing_agency+service_provided:seo@high+technical+b2b+saas+rating>=4+has:clutch\n# → {\"valid\": true, \"normalized\": \"...\"}\n\nGET /v1/explore?filter=industry:marketing_agency+service_provided:seo@high+technical+b2b+saas+rating>=4+has:clutch\n# → {\"count\": 22, \"breakdowns\": {...}}\n\n# 3. Search briefs\nGET /v1/search?filter=...&limit=10\n# Header: Authorization: Bearer $SERVICEGRAPH_TOKEN\n# → 10 brief cards.\n\n# 4. Present briefs to user, get their pick of 3.\n\n# 5. Pull full bundles for the 3 picks\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","seo","agency","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-seo-agency","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-seo-agency","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 (18,136 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.737Z","embedding":null,"createdAt":"2026-05-06T12:58:11.527Z","updatedAt":"2026-05-18T18:56:03.737Z","lastSeenAt":"2026-05-18T18:56:03.737Z","tsv":"'-10':1986 '/.env.local':1022 '/about':1607 '/check':291,760,947 '/explore':292,762,948 '/get':250,589,767,1241,2317,2382 '/off-page':24 '/search':249,587,765,1239,1624,2313,2359 '/stats':251 '/tags':290,661,759,946 '/v1/auth/request-otp''':1097 '/v1/auth/verify-otp?format=env''':1174 '/v1/check':362,498,1412,1490,2518,2689 '/v1/explore':368,511,1682,1942,2328,2582,2709 '/v1/get':385,553,1620,1715,2063,2763 '/v1/research':576 '/v1/search':374,532,1696,1758,1797,1859,1955,2017,2356,2732 '/v1/search?filter=...''':1001,1033 '/v1/stats':397 '/v1/tags':356,482,2656 '/v1/tags?include_values=1':643 '0':895 '1':332,333,859,1081,1315,1662,2053,2649,2659 '10':1707,1708,1771,1871,1964,2035,2735,2741 '12':1586,1597,1642,1663,2536 '2':905,1106,1334,1661,2061,2677 '2.1':257 '20':1469,2010,2031,2049,2330,2335,2342 '200':535 '22':2726 '3':966,1190,1225,1350,1713,1716,2074,2728,2753,2760,2764 '4':1058,1376,1465,2007,2027,2642,2702,2722,2744 '400':2504,2519,2528 '401':1243,2543 '404':2069,2127,2302,2315,2551 '429':2565,2576 '4xx':1143 '5':1236,2754 '50':556 '6':1927 '8':2048 'a-z':1648,1651 'accept':665 'across':133,743,1395 'actual':2097 'ad':2429 'add':1517,1980 'address':569,2372 'advis':2273 'agenc':4,18,47,58,71,87,93,177,183,693,1415,1421,1430,1437,1444,1451,1459,1474,1667,1678,1686,1700,1762,1801,1827,1848,1863,1946,1959,2003,2021,2150,2182,2221,2272,2406,2439,2693,2713 'agent':233,423,1085,1110 'aggreg':2075 'allow':1365 'alreadi':625,851,2044 'also':1157 'alway':88,691,709,835,2145 'and':1576 'andexpr':1272,1274,1275 'anon':350 'anonym':288,306,764,944 'anyon':1608 'apex':1598,1611,1635,2038,2363 'apex.lower':1594,1638 'api':62,932 'api.servicegraph.co':63,642,1000,1032,1096,1173 'api.servicegraph.co/v1/auth/request-otp''':1095 'api.servicegraph.co/v1/auth/verify-otp?format=env''':1172 'api.servicegraph.co/v1/search?filter=...''':999,1031 'api.servicegraph.co/v1/tags?include_values=1':641 'appear':801 'append':1127 'application/json':1102,1179 'ask':836,957,962,1515,1939,1990,2248,2376,2403,2417 'atom':1285,1286 'audit':40,267 'auth':229,247,440,444,468,476,758,810,913,951,964,971,2594,2687 'author':826,995,1027,2737 'avail':865,898 'awk':1658 'b':1323,1329,1722 'b2b':36,111,1455,1555,1557,1736,1741,1768,2398,2634,2699,2719 'backend':341 'bareword':751,1293,1307,1377,1403,1577,1747,1821,2197,2460 'baselin':1672 'bash':879,986,1080,1643 'bearer':534,555,770,996,1028,2738 'becom':755,1389,2209 'berlin':2408 'bind':1317 'bite':1314 'bodi':1037 'brand':746,1397 'breakdown':520,1694,1814,2345,2727 'brief':540,1709,2357,2392,2730,2742,2746 'broaden':2352 'broader':153,192 'budget':2621,2785 'bug':2306 'build':27,106,209,1528,1531,1775,1786,1807,2202 'built':2270 'bundl':562,2065,2757 'busi':1844 'byo':1627,2037 'c':1324,1331,1772 'ca':1342,1367,1373 'cach':644 'calendar':596 'call':230,321,486,509,571,600,639,914,952,972,1619 'candid':525 'canon':1499 'captur':1034,1066,1192,1205,1209 'card':542,1710,2743 'carri':2596 'catalog':73,118,189,394,1509,1873,2068,2100,2125,2393,2557 'categor':689 'chain':1852 'char':1589,2539 'charg':590,614,2071,2327,2561 'check':359,873 'claud':1187 'claude-c':1186 'cli':1188 'client':138,1895 'clutch':732,1471,2014,2033,2647,2672,2704,2724 'code':878,894,1109,1115,1147,1183,1184,2497,2500 'comma':1335,1361 'command':1053 'comment':1159 'compani':697,737,1728,1738,2636 'complet':442,1217 'comput':1614,2054 'confirm':650,906,1191,1950,2088,2660 'consent':1214 'constrain':199 'constraint':1992 'construct':636 'consul':54 'consult':1733,2631 'contact':546,2103,2378 'content':29,168,1100,1177,2235 'content-l':28 'content-typ':1099,1176 'context':285,781,793 'continu':2325,2564 'contract':1580,2059 'convers':649,804,985,1979 'core':1478,1561,1566,2263,2461 'cost':477 'count':519,723,1467,2029,2341,2350,2725 'cover':186 'credenti':263,789 'curl':140,146,310,358,364,370,380,392,403,993,1025,1091,1137,1168 'cwv':2275 'd':1103,1180,1836,2178,2468 'data':345 'dedup':2477 'def':1632 'defer':149,178,215,581,2216,2252,2433 'deriv':2542 'design':2170 'detect':405,845,860,1065 'dev':2295 'develop':208,220,224,2257,2289 'dgst':1655 'differ':610 'digit':176 'direct':816,1070,1622 'discov':490,2650 'discoveri':320 'dispatch':276,807,967,1223 'diy/do-the-work':2416 'doesn':1012,1148,1885,2129,2134 'domain':1602,2041,2050,2095,2117 'dotenv':822 'doubt':1483 'drill':2346 'drive':59 'drop':1817,1901 'dsl':1261 'e':1913 'echo':1050,1202,1644 'ecommerc':34,110,1448,1552,1554,1780,1794,1811 'either':1019 'els':379,391,402 'elsewher':1976 'email':565,1084,1090,1104,1105,1181,1182,1719,2367,2767 'empti':2522 'encod':1640 'end':2284,2623,2625,2770 'end-to-end':2622 'endpoint':339,349 'engag':163,2240 'enrich':15,68,1628,2040 'enter':282,983 'env':784,892,1118 'env.local':273,785,856,887,925,1004,1072,1129,1189,1201,1232 'environ':821,924,992 'error':1154,2491,2493,2496,2507 'escal':2354 'etc':112,2203 'even':847,1164 'ever':281 'everi':297,488,809,970,2111 'evid':706,715,719 'exampl':143,1408,2626 'exchang':1107 'exhaust':2579 'exist':1953,2136,2311 'exit':877,893,1138 'expand':1057 'expir':1250 'explor':365 'explore/search':508 'export':988 'f':1134,1993 'failur':682 'fall':458 'featur':214 'fetch':141,621 'fewer':2333 'field':492,683,2575,2651 'file':790,823,1041,1152 'filter':193,360,499,504,512,533,611,638,754,1260,1269,1287,1487,1491,1683,1697,1759,1798,1860,1943,1956,2018,2505,2513,2520,2523,2680,2690,2710,2733 'find':2,11,43,56,65,181,218,222,1674,2219,2255,2437 'find-marketing-ag':180,2218,2436 'find-seo-ag':1,55 'find-software-develop':221 'find-web-develop':217,2254 'firm':78,134,366,372,383,537,541,558,574,593,623,744,1578,1581,1591,1615,1633,1878,1884,2055,2094,2112,2133,2168,2214,2308,2336,2530,2532,2554 'first':485,912,1492,2479 'fit':1854 'fix':2259,2511 'flag':1135,2077,2322,2559,2676 'flat':1918,1925 'flavor':101,126,1407,1504,1751,2190,2207 'flow':445,464,815,1060,1219,1259 'follow':1385 'form':1501 'format':1117 'found':725,918,2081,2553 'four':472,1311 'four-tier':471 'free':484,501,514,539,560,608,630,740,1392,1495,2485,2490,2685 'free-text':739,1391 'freelanc':2410,2412 'frequent':2446 'front':2283 'front-end':2282 'fss':1092,1169 'full':174,561,2064,2245,2756 'full-servic':173,2244 'funnel':474 'futur':1234 'g':2036 'gave':1971 'general':2277 'geographi':700,1906 'get':355,361,367,373,382,384,396,481,497,510,531,552,640,1681,1695,1714,1757,1796,1858,1941,1954,2016,2062,2616,2655,2688,2708,2731,2749,2762 'github':1266 'github-search-styl':1265 'go':1744 'goe':973 'googl':2428 'gotcha':2144 'grep':883,888,1197 'h':994,1026,1098,1175 'handl':262,1590 'har':234,261,419,447 'harness-specif':418 'hashlib':1631 'hashlib.sha256':1637 'header':827,2572,2604,2736 'help':1782,1850 'hex':1588,1657,2538 'hex-char':1587 'hexdigest':1596,1641 'high':714,1306,1425,1463,1766,2025,2697,2717 'hit':1489 'honor':2568 'host':260 'hq':1879 'http':137 'id':386,554,1579,1582,1592,1616,1621,1634,2056,2309,2383,2531,2533 'ideal':2637 'ident':1290,1299,1303,1308,1381 'ignor':1163 'implicit':1213,1280 'import':1630 'includ':710,2362,2509,2657 'indirect':1914 'individu':2409 'industri':85,91,690,1413,1419,1428,1435,1442,1449,1457,1472,1684,1698,1760,1799,1861,1944,1957,2019,2148,2157,2691,2711 'infer':129 'info':547,2104,2379 'initi':448 'insid':1007,1359 'inspect':876 'intent':1915 'invalid':2529 'ip':516 'ip-throttl':515 'isn':1752 'jq':1044,1131 'jq-process':1043 'json':2495 'k':2329 'keep':774 'keyword':131,738,757,1310,1378,1505,1519,2210,2469 'kind':494,684 'know':2782 'land':1167 'later':958 'leak':1014 'least':2006,2640 'led':30 'left':2787 'legal':491,567,749,1400,2369 'limit':1706,1770,1870,1963,2034,2567,2734 'line':1160 'link':26,105,1527,1530,1533,1774,1785,1806,2201 'link-build':25,104,1526,1529,1773,1784,1805,2200 'linkedin':736 'list':353,1336,1362,1612,2039,2091,2648 'liter':797,980,1358 'll':686 'llm':284,780,834,1079 'load':240,378,390,401,434 'local':32,103,1441,1523,1525,1617,1837,1846,1867,1882,2057,2199 'local-seo':1881 'locat':1843,1975 'look':2298 'low':1304,2617 'lowercas':2537 'make':1136,2348 'map':334,1506 'market':86,92,162,182,692,1414,1420,1429,1436,1443,1450,1458,1473,1685,1699,1761,1800,1862,1945,1958,2020,2149,2181,2220,2247,2438,2692,2712 'match':426,1345,2163,2212,2337 'matter':586 'may':2310 'mcp':225,238,253,293,298,330,346,376,388,399,410,431,454 'mcp.servicegraph.co':241 'mean':2131 'medium':1305 'messag':2498 'meta':748,1399 'mid':1246 'mid-sess':1245 'mirror':1155 'missing/expired':2546 'mix':2449 'mix-up':2448 'mode':2584 'model':696,773 'month':538,559,597,628,1928,2476,2577,2590,2609,2778 'much':2784 'multi':160,1571,1842,1910,2224,2452 'multi-loc':1841 'multi-servic':159,2223 'multi-word':1570,2451 'multipl':1402 'must':2381,2455,2534 'mvp':580 'n':880,1645 'name':416,493,568,676,745,750,1185,1396,1401,2370 'narrow':1900 'nation':1908 'need':450,1132,1625,1930 'negat':1351,1357 'never':782,800,982 'new':1068 'nj':1857,1869,1891,1894,1903 'non':901,1140,2401 'non-us':2400 'non-zero':900,1139 'none':483,500,513 'normal':1500,2707 'not-found':2079 'note':1569,2108 'notexpr':1276,1278,1282,1284 'number':1300,1309,1383 'numer':720,2670 'ny':1343,1368,1375 'oauth':256,301 'off-pag':1543,1547 'offpag':1551 'ok':926 'on-pag':21,107,1534,1538,1776,1788,1808,1824 'one':120,1262,1339,1511,1818,1875,2082,2106,2239,2525 'onpag':1542 'op':702,716,727,1291,1294 'openssl':1654 'oper':495,1388 'option':712,718 'order':1965 'orexpr':1270,1271 'organ':1916,1921 'otherwis':1982 'otp':381,393,404,463,1059,1203,1258,2550 'outreach':1721,2769 'over-constrain':197 'overlap':613,618 'page':23,109,603,1536,1540,1545,1549,1564,1778,1790,1810,1826 'pagin':2488 'paid':577,2233,2426 'param':1120 'paramet':1264 'paren':1333 'parent':1017 'pars':1325,1488,2464,2506 'parser':663 'parti':1998 'partner':1933 'pass':2107 'past':2047 'path':318,352 'pattern':325,425 'pattern-match':424 'payload':2508 'per':591,595,599,678,840,1877,2473,2475,2653 'per-user-per-month':2472 'persist':1230 'phone':564,730,1718,2365,2766 'phrase':2454 'pick':1712,2751,2761 'pin':89,2146,2158,2176 'pkce':258 'plain':309,1125 'plus':165,167,169,2232,2234,2236 'pollut':1150 'pool':526,1692,1952,2684 'posit':2510 'post':575,1094,1171 'ppc':166,2425 'predic':1288,1289,1340 'prefer':227,242,296,435 'prefix':421 'presenc':728,2675 'present':457,653,1983,2076,2745 'pretend':2386 'prevent':680 'price':695 'primari':2366,2368 'print':1659 'pro':2300 'proceed':1221 'process':1045 'procur':1938 'profil':2015 'prompt':1086,1111 'provid':82,96,657,708,1417,1423,1432,1439,1446,1453,1461,1476,1688,1702,1764,1803,1865,1948,1961,2023,2121,2153,2160,2666,2695,2715 'public':337 'pull':626,2102,2755 'python':1629 'q':1198 'qs':884,889 'qualiti':1994 'queri':606,1119,1263 'quota':343,529,583,2470,2578,2603,2776 'quota-spend':528 'rank':550,2421 'rate':721,734,1464,2009,2026,2566,2644,2668,2701,2721 'ratelimit':2599 're':602,620,956,1255,2482,2487,2515,2541,2548 're-ask':955 're-der':2540 're-fetch':619 're-pag':601 're-pagin':2486 're-run':1254,2547 're-valid':2514 're-view':2481 'read':783,867 'recip':1664 'recommend':351 'refactor':2280 'refus':2399 'regardless':2183 'region':1912 'regist':1601 'reject':1370 'relev':1967,1988 'remain':2608,2777 'remaining-month':2607 'report':2773 'request':142,811,933,1052 'requir':300,768,2521,2527 'resolut':857 'respons':646,1036,2339,2595 'rest':313,324,338,348,462,2587 'result':671,1897 'retri':2570,2573 'retry-aft':2569 'return':659,669,1121,1242,1497,1636,2179,2494 'reveal':1194 'review':722,1466,2011,2028 'revok':1253 'ritual':634 'round':830 'round-trip':829 'rstrip':1595,1639 'rule':584,858,1312 'run':870,1256,2549 'saa':1456,1727,1737,1743,1769,2635,2700,2720 'safe':1161 'sandbox':268 'say':939 'scope':151,518,2226,2682 'search':132,371,1267,1379,2427,2729 'searchpilot.com':1603,1646 'secur':772 'see':408,2058 'sem':2424,2441 'sem-vs-seo':2440 'seo':3,17,20,31,33,35,37,39,46,53,57,70,83,97,98,121,164,201,651,711,1406,1418,1424,1433,1440,1447,1454,1462,1477,1512,1521,1524,1537,1546,1553,1556,1559,1666,1677,1689,1703,1724,1732,1748,1765,1791,1804,1830,1838,1847,1866,1883,1932,1937,1949,1962,2002,2024,2093,2114,2122,2154,2161,2164,2185,2187,2231,2251,2271,2297,2405,2413,2432,2443,2630,2661,2696,2716 'seo-flavor':1405 'separ':115,1575,2194,2459 'serv':701,1893,1907 'server':226,239,254,303,432 'servic':81,95,161,175,656,707,1416,1422,1431,1438,1445,1452,1460,1475,1687,1701,1763,1802,1864,1947,1960,2022,2120,2152,2159,2165,2175,2225,2246,2301,2665,2694,2714 'servicegraph':61,237,413,430,453,881,885,890,920,931,997,1029,1122,1199,2739 'session':489,632,679,841,916,935,1235,1247,2654,2772 'session-start':631 'set':704,1020,1023 'sha256':1593,1656 'shell':275,806,854,872,969,976,991,1018 'ship':212 'shop':2171 'shopifi':1558,1560 'shortlist':12,50,66,551,573 'sibl':147 'signal':699,1999 'silent':664,681 'simpler':317 'sinc':1507 'site':211,2261 'size':523,698,1693 'skill':148,185 'skill-find-seo-agency' 'skip':582,950,2323,2562 'smaller':2351 'social':170,566,2237 'softwar':223 'somewher':899 'sourc':1005 'source-nostrband' 'spars':1816 'special':127 'specialti':2186 'specif':420 'speed':1565,2262 'spend':506,530 'split':1573,2457 'stabl':1585 'star':2008,2643 'start':633,1822 'stat':395 'state':694,1341,1366,1372,1374,1426,1670,1690,1704,1868,1876,1902,1911 'status':2499 'stay':941 'step':1224 'store':1795 'strict':206,2250 'structur':1755 'studio':1855 'style':1268 'sub':100,125,1503,1750,2189,2206 'sub-flavor':99,124,1502,1749,2188,2205 'subshel':1009 'substr':428,742,1394,1660,2211 'success':1208 'suppress':2331,2343 'surfac':1074,2605 'switch':2580 'tag':79,116,122,354,667,675,703,1513,1756,1874,2119,2195,2667 'tagatevid':1301,1302 'taxonomi':658 'technic':19,52,102,1434,1520,1522,1723,1731,1739,1767,2198,2629,2698,2718 'technical/local/link-building/on-page':2191 'tell':2591 'terminolog':2447 'texa':49,1680 'text':135,741,1126,1393,2215 'third':1997 'third-parti':1996 'thousand':75 'three':51,1349,1730,2001,2466,2628 'threshold':1995 'throttl':517 'tier':248,289,307,441,469,473,475,945 'tighter':1318 'titl':747,1398 'tmp':1040 'token':279,771,776,795,814,846,863,882,886,891,896,904,921,981,998,1030,1056,1063,1069,1123,1200,1204,1227,1249,2545,2740 'tool':244,299,331,347,411,437,455 'top':1985 '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':724,1468,2030 'tr':1647 'traffic':1917,1922 'translat':1940 'trigger':41,1082 'trip':831 'true':2344,2706 'two':609 'tx':1344,1427,1691,1705 'type':1101,1178 'unauthor':1244,2544 'uniqu':536,557,592 'unknown':666 'unless':959 'url':314,544,563,1717,2364,2765 'us':16,69,77,1909,2396,2402 'us-on':2395 'use':5,145,255,322,478,521,548,687,805,843,928,1332,1371,1905,2086,2196 'user':8,156,204,819,838,909,938,961,1088,1113,1211,1514,1673,1711,1729,1781,1845,1919,1970,2000,2043,2046,2085,2229,2287,2375,2474,2593,2613,2627,2748,2781 'usual':1833 'valid':502,1409,2516,2664,2678,2705 'valu':280,496,798,869,1076,1196,1296,1297,1298,2610,2658 'valueorlist':1292,1295 'vari':422 'verifi':673 'vertic':1973 'vet':13 'via':130,968 'view':594,2480,2483 'vital':1480,1563,1568,2265,2463 'vs':2442 'want':9,157,205,2230,2268,2288 'web':219,1479,1562,1567,2256,2264,2294,2462 'web-dev':2293 'web/app':207 'whenev':6 'whether':861,1485,2089 'whitespac':1279 'within':1338 'without':828,866,1073,1193,2155,2173 'won':195 'word':1572,2453 'work':139,965,2290 'would':2162 'wrapper':977 'writer':2414 'wrong':1146 'www.searchpilot.com':1606 'www.searchpilot.com/about':1605 'x':1093,1170,1353,1356,2423,2598,2602,2775 'x-quota':2601 'x-quota-remaining-month':2774 'x-ratelimit':2597 'year':726 'yes':357,363,369 'z':1650,1653 'zero':670,902,1141","prices":[{"id":"1ec436bc-a067-460b-b07b-3f74e165745c","listingId":"2b5f1ee8-f37e-427a-8fe3-1b0dad64c908","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.527Z"}],"sources":[{"listingId":"2b5f1ee8-f37e-427a-8fe3-1b0dad64c908","source":"github","sourceId":"nostrband/ServiceGraph/find-seo-agency","sourceUrl":"https://github.com/nostrband/ServiceGraph/tree/main/skills/find-seo-agency","isPrimary":false,"firstSeenAt":"2026-05-06T12:58:11.527Z","lastSeenAt":"2026-05-18T18:56:03.737Z"}],"details":{"listingId":"2b5f1ee8-f37e-427a-8fe3-1b0dad64c908","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"nostrband","slug":"find-seo-agency","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":"87975f2efca9a520eabf2da9200b498cd4f06a1c","skill_md_path":"skills/find-seo-agency/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/nostrband/ServiceGraph/tree/main/skills/find-seo-agency"},"layout":"multi","source":"github","category":"ServiceGraph","frontmatter":{"name":"find-seo-agency","license":"MIT","description":"Use whenever the user wants to find, shortlist, vet, or enrich US SEO agencies — technical SEO, on-page/off-page, link-building, content-led SEO, local SEO, ecommerce SEO, B2B SEO, and SEO audits. Triggers on \"find me an SEO agency in Texas\", \"shortlist three technical SEO consultancies for SaaS\", \"link-building and on-page for our ecommerce store\", or \"pull contact info for these 8 SEO firm domains\", even when described indirectly (organic traffic flat, improve Google rankings, search visibility). Drives the ServiceGraph API (api.servicegraph.co) — a 100k+ US firm catalog filterable by industry, services, location, size, ratings, third-party listings. Defer to find-marketing-agency when scope spans multiple marketing services beyond SEO. Skip SEM/PPC/paid-search asks, web-dev asks (use find-web-developer), \"how do I rank\" DIY questions, SEO tool recommendations (Ahrefs, Semrush), in-house SEO hires, non-US firms, individual freelancers."},"skills_sh_url":"https://skills.sh/nostrband/ServiceGraph/find-seo-agency"},"updatedAt":"2026-05-18T18:56:03.737Z"}}