Merge pull request #315 from coreyhaines31/chore/sync-main-pre-v2.0.1
chore: sync development with vendor PRs landed on main
This commit is contained in:
@@ -8,7 +8,7 @@ Reference for using AI image generators, video generators, and code-based video
|
||||
|
||||
| Need | Tool Category | Best Fit |
|
||||
|------|---------------|----------|
|
||||
| Static ad images (banners, social) | Image generation | Nano Banana Pro, Flux, Ideogram |
|
||||
| Static ad images (banners, social) | Image generation | ChatGPT Images 2.0, Nano Banana Pro, Flux, Ideogram |
|
||||
| Ad images with text overlays | Image generation (text-capable) | Ideogram, Nano Banana Pro |
|
||||
| Short video ads (6-30 sec) | Video generation | Veo, Kling, Runway, Sora, Seedance |
|
||||
| Video ads with voiceover | Video gen + voice | Veo/Sora (native), or Runway + ElevenLabs |
|
||||
|
||||
+26
-1
@@ -26,6 +26,7 @@ Quick reference for AI agents to discover tool capabilities and integration meth
|
||||
| ahrefs | SEO | ✓ | - | [✓](clis/ahrefs.js) | - | [ahrefs.md](integrations/ahrefs.md) |
|
||||
| dataforseo | SEO | ✓ | - | [✓](clis/dataforseo.js) | ✓ | [dataforseo.md](integrations/dataforseo.md) |
|
||||
| keywords-everywhere | SEO | ✓ | - | [✓](clis/keywords-everywhere.js) | - | [keywords-everywhere.md](integrations/keywords-everywhere.md) |
|
||||
| rankparse | SEO | ✓ | ✓ | [✓](clis/rankparse.js) | - | [rankparse.md](integrations/rankparse.md) |
|
||||
| clearbit | Data Enrichment | ✓ | - | [✓](clis/clearbit.js) | ✓ | [clearbit.md](integrations/clearbit.md) |
|
||||
| apollo | Data Enrichment | ✓ | - | [✓](clis/apollo.js) | - | [apollo.md](integrations/apollo.md) |
|
||||
| zoominfo | Data Enrichment | ✓ | ✓ | [✓](clis/zoominfo.js) | - | [zoominfo.md](integrations/zoominfo.md) |
|
||||
@@ -73,6 +74,7 @@ Quick reference for AI agents to discover tool capabilities and integration meth
|
||||
| introw | Partner Ecosystem | - | ✓ | - | - | [introw.md](integrations/introw.md) |
|
||||
| pendo | Product Analytics | ✓ | - | [✓](clis/pendo.js) | - | [pendo.md](integrations/pendo.md) |
|
||||
| similarweb | Competitive Intelligence | ✓ | - | [✓](clis/similarweb.js) | - | [similarweb.md](integrations/similarweb.md) |
|
||||
| exa | AI Search | ✓ | ✓ | [✓](clis/exa.js) | ✓ | [exa.md](integrations/exa.md) |
|
||||
| firehose | Competitive Intelligence | ✓ | - | - | - | [firehose.md](integrations/firehose.md) |
|
||||
| sparktoro | Audience Research | - | - | - | - | [sparktoro.md](integrations/sparktoro.md) |
|
||||
| rb2b | Visitor Identification | ✓ | - | - | - | [rb2b.md](integrations/rb2b.md) |
|
||||
@@ -94,6 +96,7 @@ Quick reference for AI agents to discover tool capabilities and integration meth
|
||||
| contentful | Headless CMS | ✓ | - | ✓ | ✓ | [contentful.md](integrations/contentful.md) |
|
||||
| strapi | Headless CMS | ✓ | - | ✓ | ✓ | [strapi.md](integrations/strapi.md) |
|
||||
| composio | Integration Layer | ✓ | ✓ | ✓ | ✓ | [composio.md](integrations/composio.md) |
|
||||
| cogny | Integration Layer | - | ✓ | - | - | [cogny.md](integrations/cogny.md) |
|
||||
|
||||
---
|
||||
|
||||
@@ -126,8 +129,9 @@ Search engine optimization tools for keyword research, rank tracking, and site a
|
||||
| **ahrefs** | Backlink analysis, content research | Best for links |
|
||||
| **dataforseo** | SERP tracking, backlinks, on-page audits | Comprehensive API |
|
||||
| **keywords-everywhere** | Quick keyword research, traffic estimates | Credit-based |
|
||||
| **rankparse** | Cheap, agent-friendly backlinks + domain data | Credit-based, MCP available |
|
||||
|
||||
**Agent recommendation**: Google Search Console is essential (free). Add Semrush or Ahrefs for competitive research. DataForSEO for programmatic SERP data. Keywords Everywhere for quick keyword lookups.
|
||||
**Agent recommendation**: Google Search Console is essential (free). Add Semrush or Ahrefs for competitive research. DataForSEO for programmatic SERP data. Keywords Everywhere for quick keyword lookups. RankParse for agent workflows where per-call cost matters — backlinks, domain authority, and tech stack at a fraction of enterprise pricing.
|
||||
|
||||
### CRM
|
||||
|
||||
@@ -387,6 +391,16 @@ AI-powered content generation and optimization platforms.
|
||||
|
||||
**Agent recommendation**: AirOps for building AI content workflows that generate SEO-optimized content at scale.
|
||||
|
||||
### AI Search
|
||||
|
||||
AI-powered web search APIs built for LLMs and agents. Return structured results with on-demand text, highlights, and summaries.
|
||||
|
||||
| Tool | Best For | Notes |
|
||||
|------|----------|-------|
|
||||
| **exa** | Neural/semantic web search, content research, competitor discovery | Search + findSimilar + Contents; MCP and SDKs available |
|
||||
|
||||
**Agent recommendation**: Exa for neural search over the open web — content research, competitor/similar-page discovery, link prospecting, news monitoring, and audience research. Pairs well with seo-audit, content-strategy, and competitor-profiling skills.
|
||||
|
||||
### Partner Ecosystem
|
||||
|
||||
Partner data sharing, co-sell, and ecosystem management.
|
||||
@@ -468,6 +482,7 @@ These tools have Model Context Protocol servers available, enabling direct agent
|
||||
- **outreach** - Sales engagement sequences
|
||||
- **crossbeam** - Partner ecosystem data
|
||||
- **introw** - Partner relationship management
|
||||
- **exa** - AI-powered web search for LLMs and agents
|
||||
|
||||
To use MCP tools, ensure the appropriate MCP server is configured in your environment.
|
||||
|
||||
@@ -481,6 +496,16 @@ To use MCP tools, ensure the appropriate MCP server is configured in your enviro
|
||||
|
||||
Use Composio when you need MCP access to OAuth-heavy tools. Prefer native MCP servers (GA4, Stripe, Mailchimp, etc.) when available — they have deeper coverage.
|
||||
|
||||
### Cogny Integration
|
||||
|
||||
[Cogny](integrations/cogny.md) is a hosted MCP gateway focused on marketing channels — one federated MCP URL with managed OAuth across every channel you've connected. Narrower than Composio (marketing-only) and useful when you want SEO, paid social, and privacy-friendly analytics behind a single MCP login.
|
||||
|
||||
- **Setup**: connect channels at [cogny.com](https://cogny.com), then in Claude.ai go to Settings → Connectors → Add custom connector and paste `https://app.cogny.com/mcp`
|
||||
- **Channels**: Search Console, Bing Webmaster, Semrush, LinkedIn Ads, Reddit Ads, TikTok Ads, Plausible, Fathom
|
||||
- **Pricing**: Solo plan starts at $9/mo (7-day trial)
|
||||
|
||||
Use Cogny when you only need marketing channels and want to avoid running your own OAuth proxy. Prefer native APIs when you need deep, custom control of a single tool.
|
||||
|
||||
---
|
||||
|
||||
## Quick Start by Use Case
|
||||
|
||||
@@ -50,6 +50,7 @@ Every CLI reads credentials from environment variables:
|
||||
| `dataforseo` | `DATAFORSEO_LOGIN`, `DATAFORSEO_PASSWORD` |
|
||||
| `demio` | `DEMIO_API_KEY`, `DEMIO_API_SECRET` |
|
||||
| `dub` | `DUB_API_KEY` |
|
||||
| `exa` | `EXA_API_KEY` |
|
||||
| `g2` | `G2_API_TOKEN` |
|
||||
| `ga4` | `GA4_ACCESS_TOKEN` |
|
||||
| `google-ads` | `GOOGLE_ADS_TOKEN`, `GOOGLE_ADS_DEVELOPER_TOKEN`, `GOOGLE_ADS_CUSTOMER_ID` |
|
||||
@@ -148,6 +149,7 @@ DOMAINS=$(rewardful affiliates list | jq -r '.data[].email')
|
||||
| `dataforseo.js` | SEO | [DataForSEO](https://dataforseo.com) |
|
||||
| `demio.js` | Webinar | [Demio](https://demio.com) |
|
||||
| `dub.js` | Links | [Dub.co](https://dub.co) |
|
||||
| `exa.js` | AI Search | [Exa](https://exa.ai) |
|
||||
| `g2.js` | Reviews | [G2](https://g2.com) |
|
||||
| `ga4.js` | Analytics | [Google Analytics 4](https://analytics.google.com) |
|
||||
| `google-ads.js` | Ads | [Google Ads](https://ads.google.com) |
|
||||
|
||||
Executable
+147
@@ -0,0 +1,147 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const API_KEY = process.env.EXA_API_KEY
|
||||
const BASE_URL = 'https://api.exa.ai'
|
||||
|
||||
if (!API_KEY) {
|
||||
console.error(JSON.stringify({ error: 'EXA_API_KEY environment variable required' }))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
async function api(method, path, body) {
|
||||
if (args['dry-run']) {
|
||||
return { _dry_run: true, method, url: `${BASE_URL}${path}`, headers: { 'x-api-key': '***', 'Content-Type': 'application/json', 'x-exa-integration': 'marketingskills' }, body: body || undefined }
|
||||
}
|
||||
const res = await fetch(`${BASE_URL}${path}`, {
|
||||
method,
|
||||
headers: {
|
||||
'x-api-key': API_KEY,
|
||||
'Content-Type': 'application/json',
|
||||
'x-exa-integration': 'marketingskills',
|
||||
},
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
})
|
||||
const text = await res.text()
|
||||
try {
|
||||
return JSON.parse(text)
|
||||
} catch {
|
||||
return { status: res.status, body: text }
|
||||
}
|
||||
}
|
||||
|
||||
function parseArgs(args) {
|
||||
const result = { _: [] }
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const arg = args[i]
|
||||
if (arg.startsWith('--')) {
|
||||
const key = arg.slice(2)
|
||||
const next = args[i + 1]
|
||||
if (next && !next.startsWith('--')) {
|
||||
result[key] = next
|
||||
i++
|
||||
} else {
|
||||
result[key] = true
|
||||
}
|
||||
} else {
|
||||
result._.push(arg)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
function buildContents(args) {
|
||||
const contents = {}
|
||||
if (args.text) {
|
||||
contents.text = args['max-chars']
|
||||
? { maxCharacters: Number(args['max-chars']) }
|
||||
: true
|
||||
}
|
||||
if (args.highlights) {
|
||||
contents.highlights = args['highlight-query']
|
||||
? { query: args['highlight-query'] }
|
||||
: true
|
||||
}
|
||||
if (args.summary) {
|
||||
contents.summary = args['summary-query']
|
||||
? { query: args['summary-query'] }
|
||||
: {}
|
||||
}
|
||||
return Object.keys(contents).length ? contents : null
|
||||
}
|
||||
|
||||
const args = parseArgs(process.argv.slice(2))
|
||||
const [cmd, ...rest] = args._
|
||||
|
||||
async function main() {
|
||||
let result
|
||||
|
||||
switch (cmd) {
|
||||
case 'search': {
|
||||
const query = args.query || rest.join(' ')
|
||||
if (!query) { result = { error: '--query required' }; break }
|
||||
const body = { query }
|
||||
if (args.type) body.type = args.type
|
||||
if (args.num) body.numResults = Number(args.num)
|
||||
if (args.category) body.category = args.category
|
||||
if (args['include-domains']) body.includeDomains = args['include-domains'].split(',').map(s => s.trim())
|
||||
if (args['exclude-domains']) body.excludeDomains = args['exclude-domains'].split(',').map(s => s.trim())
|
||||
if (args['include-text']) body.includeText = args['include-text'].split(',').map(s => s.trim())
|
||||
if (args['exclude-text']) body.excludeText = args['exclude-text'].split(',').map(s => s.trim())
|
||||
if (args['start-published']) body.startPublishedDate = args['start-published']
|
||||
if (args['end-published']) body.endPublishedDate = args['end-published']
|
||||
if (args['start-crawl']) body.startCrawlDate = args['start-crawl']
|
||||
if (args['end-crawl']) body.endCrawlDate = args['end-crawl']
|
||||
if (args['user-location']) body.userLocation = args['user-location']
|
||||
const contents = buildContents(args)
|
||||
if (contents) body.contents = contents
|
||||
result = await api('POST', '/search', body)
|
||||
break
|
||||
}
|
||||
|
||||
case 'find-similar': {
|
||||
const url = args.url
|
||||
if (!url) { result = { error: '--url required' }; break }
|
||||
const body = { url }
|
||||
if (args.num) body.numResults = Number(args.num)
|
||||
if (args['include-domains']) body.includeDomains = args['include-domains'].split(',').map(s => s.trim())
|
||||
if (args['exclude-domains']) body.excludeDomains = args['exclude-domains'].split(',').map(s => s.trim())
|
||||
if (args['start-published']) body.startPublishedDate = args['start-published']
|
||||
if (args['end-published']) body.endPublishedDate = args['end-published']
|
||||
if (args['start-crawl']) body.startCrawlDate = args['start-crawl']
|
||||
if (args['end-crawl']) body.endCrawlDate = args['end-crawl']
|
||||
const contents = buildContents(args)
|
||||
if (contents) body.contents = contents
|
||||
result = await api('POST', '/findSimilar', body)
|
||||
break
|
||||
}
|
||||
|
||||
case 'contents': {
|
||||
const urls = args.urls?.split(',').map(s => s.trim())
|
||||
if (!urls || !urls.length) { result = { error: '--urls required (comma-separated)' }; break }
|
||||
const body = { urls }
|
||||
const contents = buildContents(args)
|
||||
if (contents) Object.assign(body, contents)
|
||||
else body.text = true
|
||||
result = await api('POST', '/contents', body)
|
||||
break
|
||||
}
|
||||
|
||||
default:
|
||||
result = {
|
||||
error: 'Unknown command',
|
||||
usage: {
|
||||
search: 'search --query <q> [--type neural|fast|auto|deep-lite|deep|deep-reasoning|instant] [--num <n>] [--category company|research paper|news|personal site|financial report|people] [--include-domains <d1,d2>] [--exclude-domains <d1,d2>] [--include-text <phrases>] [--exclude-text <phrases>] [--start-published <ISO>] [--end-published <ISO>] [--user-location <CC>] [--text] [--highlights] [--summary] [--max-chars <n>] [--highlight-query <q>] [--summary-query <q>]',
|
||||
'find-similar': 'find-similar --url <url> [--num <n>] [--include-domains <d1,d2>] [--exclude-domains <d1,d2>] [--start-published <ISO>] [--end-published <ISO>] [--text] [--highlights] [--summary]',
|
||||
contents: 'contents --urls <url1,url2> [--text] [--highlights] [--summary] [--max-chars <n>] [--highlight-query <q>] [--summary-query <q>]',
|
||||
options: '--dry-run (preview request without sending)',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(JSON.stringify(result, null, 2))
|
||||
}
|
||||
|
||||
main().catch(err => {
|
||||
console.error(JSON.stringify({ error: err.message }))
|
||||
process.exit(1)
|
||||
})
|
||||
Executable
+196
@@ -0,0 +1,196 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const API_KEY = process.env.RANKPARSE_API_KEY
|
||||
const BASE_URL = 'https://api.rankparse.com/v1'
|
||||
|
||||
if (!API_KEY) {
|
||||
console.error(JSON.stringify({ error: 'RANKPARSE_API_KEY environment variable required' }))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
async function api(method, path, body) {
|
||||
if (args['dry-run']) {
|
||||
return { _dry_run: true, method, url: `${BASE_URL}${path}`, headers: { 'X-API-Key': '***', 'Content-Type': 'application/json' }, body }
|
||||
}
|
||||
const init = {
|
||||
method,
|
||||
headers: {
|
||||
'X-API-Key': API_KEY,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}
|
||||
if (body) init.body = JSON.stringify(body)
|
||||
const res = await fetch(`${BASE_URL}${path}`, init)
|
||||
const text = await res.text()
|
||||
try {
|
||||
return JSON.parse(text)
|
||||
} catch {
|
||||
return { status: res.status, body: text }
|
||||
}
|
||||
}
|
||||
|
||||
function parseArgs(args) {
|
||||
const result = { _: [] }
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const arg = args[i]
|
||||
if (arg.startsWith('--')) {
|
||||
const key = arg.slice(2)
|
||||
const next = args[i + 1]
|
||||
if (next && !next.startsWith('--')) {
|
||||
result[key] = next
|
||||
i++
|
||||
} else {
|
||||
result[key] = true
|
||||
}
|
||||
} else {
|
||||
result._.push(arg)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const args = parseArgs(process.argv.slice(2))
|
||||
const [cmd, sub, ...rest] = args._
|
||||
|
||||
function requireDomain() {
|
||||
if (!args.domain) return { error: '--domain required' }
|
||||
return null
|
||||
}
|
||||
|
||||
function requireUrl() {
|
||||
if (!args.url) return { error: '--url required' }
|
||||
return null
|
||||
}
|
||||
|
||||
async function main() {
|
||||
let result
|
||||
|
||||
switch (cmd) {
|
||||
case 'domain-authority':
|
||||
case 'domain-rank':
|
||||
case 'tech-stack':
|
||||
case 'site-health':
|
||||
case 'similar-domains':
|
||||
case 'link-audit':
|
||||
case 'site-explorer':
|
||||
case 'crawl-history': {
|
||||
const err = requireDomain(); if (err) { result = err; break }
|
||||
result = await api('GET', `/${cmd}?domain=${encodeURIComponent(args.domain)}`)
|
||||
break
|
||||
}
|
||||
|
||||
case 'backlinks': {
|
||||
const err = requireDomain(); if (err) { result = err; break }
|
||||
const params = new URLSearchParams({ domain: args.domain })
|
||||
if (args.limit) params.set('limit', args.limit)
|
||||
if (args.sort) params.set('sort', args.sort)
|
||||
if (args['from-domain']) params.set('from_domain', args['from-domain'])
|
||||
if (args['link-type']) params.set('link_type', args['link-type'])
|
||||
if (args.score) params.set('score', 'true')
|
||||
result = await api('GET', `/backlinks?${params}`)
|
||||
break
|
||||
}
|
||||
|
||||
case 'referring-domains':
|
||||
case 'outbound-links':
|
||||
case 'anchor-text':
|
||||
case 'top-pages':
|
||||
case 'sitemap': {
|
||||
const err = requireDomain(); if (err) { result = err; break }
|
||||
const params = new URLSearchParams({ domain: args.domain })
|
||||
if (args.limit) params.set('limit', args.limit)
|
||||
result = await api('GET', `/${cmd}?${params}`)
|
||||
break
|
||||
}
|
||||
|
||||
case 'domain-overlap': {
|
||||
if (!args.domains) { result = { error: '--domains required (comma-separated, 2-5 domains)' }; break }
|
||||
const params = new URLSearchParams({ domains: args.domains })
|
||||
if (args.limit) params.set('limit', args.limit)
|
||||
result = await api('GET', `/domain-overlap?${params}`)
|
||||
break
|
||||
}
|
||||
|
||||
case 'link-intersect': {
|
||||
if (!args['domain-a'] || !args['domain-b']) { result = { error: '--domain-a and --domain-b required' }; break }
|
||||
const params = new URLSearchParams({ domain_a: args['domain-a'], domain_b: args['domain-b'] })
|
||||
if (args.limit) params.set('limit', args.limit)
|
||||
result = await api('GET', `/link-intersect?${params}`)
|
||||
break
|
||||
}
|
||||
|
||||
case 'competitor-gap': {
|
||||
const err = requireDomain(); if (err) { result = err; break }
|
||||
if (!args.vs) { result = { error: '--vs required (competitor domain)' }; break }
|
||||
const params = new URLSearchParams({ domain: args.domain, vs: args.vs })
|
||||
if (args.limit) params.set('limit', args.limit)
|
||||
result = await api('GET', `/competitor-gap?${params}`)
|
||||
break
|
||||
}
|
||||
|
||||
case 'page-seo': {
|
||||
const err = requireUrl(); if (err) { result = err; break }
|
||||
result = await api('GET', `/page-seo?url=${encodeURIComponent(args.url)}`)
|
||||
break
|
||||
}
|
||||
|
||||
case 'page-performance': {
|
||||
const err = requireUrl(); if (err) { result = err; break }
|
||||
const params = new URLSearchParams({ url: args.url })
|
||||
if (args.strategy) params.set('strategy', args.strategy)
|
||||
result = await api('GET', `/page-performance?${params}`)
|
||||
break
|
||||
}
|
||||
|
||||
case 'batch': {
|
||||
if (!args.domains) { result = { error: '--domains required (comma-separated)' }; break }
|
||||
const domains = args.domains.split(',').map(d => d.trim()).filter(Boolean)
|
||||
result = await api('POST', '/batch', { domains })
|
||||
break
|
||||
}
|
||||
|
||||
case 'me':
|
||||
result = await api('GET', '/me')
|
||||
break
|
||||
|
||||
case 'credits':
|
||||
result = await api('GET', '/credits')
|
||||
break
|
||||
|
||||
default:
|
||||
result = {
|
||||
error: 'Unknown command',
|
||||
usage: {
|
||||
'domain-authority': 'domain-authority --domain <domain>',
|
||||
'domain-rank': 'domain-rank --domain <domain>',
|
||||
'backlinks': 'backlinks --domain <domain> [--limit <n>] [--sort importance|recent] [--from-domain <d>] [--link-type <t>] [--score]',
|
||||
'referring-domains': 'referring-domains --domain <domain> [--limit <n>]',
|
||||
'outbound-links': 'outbound-links --domain <domain> [--limit <n>]',
|
||||
'anchor-text': 'anchor-text --domain <domain> [--limit <n>]',
|
||||
'top-pages': 'top-pages --domain <domain> [--limit <n>]',
|
||||
'domain-overlap': 'domain-overlap --domains <d1,d2,...> [--limit <n>]',
|
||||
'link-intersect': 'link-intersect --domain-a <d> --domain-b <d> [--limit <n>]',
|
||||
'competitor-gap': 'competitor-gap --domain <d> --vs <competitor> [--limit <n>]',
|
||||
'similar-domains': 'similar-domains --domain <domain>',
|
||||
'tech-stack': 'tech-stack --domain <domain>',
|
||||
'site-health': 'site-health --domain <domain>',
|
||||
'sitemap': 'sitemap --domain <domain> [--limit <n>]',
|
||||
'crawl-history': 'crawl-history --domain <domain>',
|
||||
'page-seo': 'page-seo --url <url>',
|
||||
'page-performance': 'page-performance --url <url> [--strategy mobile|desktop]',
|
||||
'link-audit': 'link-audit --domain <domain>',
|
||||
'site-explorer': 'site-explorer --domain <domain>',
|
||||
'batch': 'batch --domains <d1,d2,...>',
|
||||
'me': 'me (account info + credit balance)',
|
||||
'credits': 'credits (credit balance)',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(JSON.stringify(result, null, 2))
|
||||
}
|
||||
|
||||
main().catch(err => {
|
||||
console.error(JSON.stringify({ error: err.message }))
|
||||
process.exit(1)
|
||||
})
|
||||
@@ -0,0 +1,153 @@
|
||||
# Cogny
|
||||
|
||||
Hosted MCP gateway that bundles several marketing tools behind one URL with managed OAuth. Useful when you want AI agents to talk to multiple marketing channels without standing up your own OAuth proxy.
|
||||
|
||||
## Capabilities
|
||||
|
||||
| Integration | Available | Notes |
|
||||
|-------------|-----------|-------|
|
||||
| API | - | Access is via MCP, not a public REST API |
|
||||
| MCP | ✓ | One federated MCP URL, OAuth-managed per channel |
|
||||
| CLI | - | Connect tools via the Cogny dashboard |
|
||||
| SDK | - | Use any MCP-capable client (Claude.ai, Claude API, Claude CLI, ChatGPT, etc.) |
|
||||
|
||||
## How it works
|
||||
|
||||
```
|
||||
┌──────────────────┐ ┌──────────────────────┐ ┌───────────────────┐
|
||||
│ Claude.ai / │──────│ app.cogny.com/mcp │──────│ Channel API │
|
||||
│ Claude CLI / │ │ (federated MCP │ │ (LinkedIn, GSC, │
|
||||
│ ChatGPT, etc. │ │ endpoint) │ │ TikTok, …) │
|
||||
└──────────────────┘ └──────────────────────┘ └───────────────────┘
|
||||
│
|
||||
│ Federates per-channel
|
||||
│ mcp.cogny.com endpoints
|
||||
▼ with managed OAuth
|
||||
```
|
||||
|
||||
`https://app.cogny.com/mcp` is a single federated endpoint that fans out to the per-channel `mcp.cogny.com` MCP servers — you connect once and every channel you've authorized in the dashboard becomes available.
|
||||
|
||||
## When to Use Cogny vs. Native or Composio
|
||||
|
||||
Cogny is one of several integration paths. Pick based on what you need:
|
||||
|
||||
| Scenario | Suggested |
|
||||
|----------|-----------|
|
||||
| Tool has a native MCP server you can self-host | Native MCP |
|
||||
| You want a single bill / single login across many channels | Cogny or Composio |
|
||||
| You need 500+ tools (CRM, productivity, dev tools, etc.) | [Composio](composio.md) |
|
||||
| You only need the marketing channels Cogny ships | Cogny |
|
||||
| You need deep, custom control over a single tool | Native API + CLI |
|
||||
|
||||
Cogny is narrower than Composio — it focuses on marketing channels — but the trade-off is fewer moving parts when you only need those channels.
|
||||
|
||||
## Setup
|
||||
|
||||
### 1. Connect your channels
|
||||
|
||||
1. Sign up at [cogny.com](https://cogny.com) and create a workspace.
|
||||
2. In the dashboard, connect the channels you want (OAuth flow per tool).
|
||||
|
||||
### 2. Add Cogny as a custom connector
|
||||
|
||||
In Claude.ai:
|
||||
|
||||
1. Go to **Settings → Connectors → Add custom connector**.
|
||||
2. Enter name **Cogny** and paste your MCP URL:
|
||||
|
||||
```
|
||||
https://app.cogny.com/mcp
|
||||
```
|
||||
|
||||
3. Complete the OAuth handshake when prompted.
|
||||
|
||||
The same `https://app.cogny.com/mcp` URL works in any MCP-capable client (Claude API, Claude CLI, ChatGPT custom connectors, etc.) — Cogny handles auth and routes each tool call to the right underlying channel.
|
||||
|
||||
## Channels Available via Cogny
|
||||
|
||||
Coverage changes over time — check the Cogny dashboard for the current list.
|
||||
|
||||
### SEO
|
||||
|
||||
| Channel | Typical use |
|
||||
|---------|-------------|
|
||||
| Search Console | Search analytics, URL inspection, sitemap submission |
|
||||
| Bing Webmaster | Coverage, query stats, URL submission quota |
|
||||
| Semrush | Keyword research, competitor checks (subject to Semrush plan) |
|
||||
|
||||
### Paid Social
|
||||
|
||||
| Channel | Typical use |
|
||||
|---------|-------------|
|
||||
| LinkedIn Ads | Campaign reporting, audience overlap, creative checks |
|
||||
| Reddit Ads | Campaign reporting, audience and conversion lookups |
|
||||
| TikTok Ads | Campaign reporting, ad group / creative health |
|
||||
|
||||
### Analytics
|
||||
|
||||
| Channel | Typical use |
|
||||
|---------|-------------|
|
||||
| Plausible | Privacy-friendly site analytics, goal reporting |
|
||||
| Fathom | Privacy-friendly site analytics |
|
||||
|
||||
## Common Agent Operations
|
||||
|
||||
Once `https://app.cogny.com/mcp` is wired up, the agent picks tools by name across every channel you've connected.
|
||||
|
||||
### Search Console — pages losing clicks
|
||||
|
||||
```
|
||||
> "Pull Search Console clicks for the last 28 days vs the previous 28 days,
|
||||
group by page, and list pages where clicks dropped more than 30%."
|
||||
```
|
||||
|
||||
### LinkedIn Ads — campaign hygiene
|
||||
|
||||
```
|
||||
> "List my active LinkedIn campaigns, their CTR and CPL for the last 14 days,
|
||||
and flag anything with CTR below 0.4%."
|
||||
```
|
||||
|
||||
### Reddit Ads — audience overlap
|
||||
|
||||
```
|
||||
> "For my Reddit Ads campaigns this month, summarize spend, conversions, and
|
||||
the subreddits driving the most clicks."
|
||||
```
|
||||
|
||||
### TikTok Ads — creative fatigue
|
||||
|
||||
```
|
||||
> "Find TikTok ad groups where CTR has dropped 25%+ over the last 7 days
|
||||
compared to the prior 7 days."
|
||||
```
|
||||
|
||||
### Plausible — funnel sanity check
|
||||
|
||||
```
|
||||
> "From Plausible, show top 10 pages by pageviews and the conversion rate
|
||||
for the 'Signup' goal over the last 30 days."
|
||||
```
|
||||
|
||||
## Limitations
|
||||
|
||||
- **Marketing-only scope** — Cogny ships marketing channels; for CRM, productivity, or dev tools use [Composio](composio.md) or the relevant native integration.
|
||||
- **Hosted dependency** — if `app.cogny.com` is down, the connected channels are unavailable through this path.
|
||||
- **Coverage depth varies** — read-heavy and reporting tools generally have more depth than write/mutation tools.
|
||||
- **OAuth tokens** — managed by Cogny; you don't control token refresh or storage directly.
|
||||
|
||||
## Pricing
|
||||
|
||||
Cogny's Solo plan starts at **$9/month** and includes a 7-day free trial. Higher tiers are available for teams. Check [cogny.com/pricing](https://cogny.com/pricing) for current plans and limits.
|
||||
|
||||
## See Also
|
||||
|
||||
- [Composio](composio.md) — broader integration layer (500+ tools, OAuth-heavy CRMs and productivity apps)
|
||||
- [Google Search Console](google-search-console.md) — native API guide if you'd rather call GSC directly
|
||||
- [LinkedIn Ads](linkedin-ads.md), [TikTok Ads](tiktok-ads.md) — native API guides
|
||||
|
||||
## Relevant Skills
|
||||
|
||||
- seo-audit (Search Console, Bing Webmaster, Semrush via Cogny)
|
||||
- paid-ads (LinkedIn, Reddit, TikTok via Cogny)
|
||||
- analytics-tracking (Plausible, Fathom via Cogny)
|
||||
@@ -0,0 +1,145 @@
|
||||
# Exa
|
||||
|
||||
AI-powered web search API built for LLMs and agents. Returns high-quality search results with neural and keyword matching, plus on-demand content retrieval (full text, highlights, and summaries) in a single request.
|
||||
|
||||
## Capabilities
|
||||
|
||||
| Integration | Available | Notes |
|
||||
|-------------|-----------|-------|
|
||||
| API | ✓ | Search, Find Similar, Contents |
|
||||
| MCP | ✓ | Official MCP server available |
|
||||
| CLI | ✓ | [exa.js](../clis/exa.js) |
|
||||
| SDK | ✓ | `exa-py` (Python), `exa-js` (TypeScript) |
|
||||
|
||||
## Authentication
|
||||
|
||||
- **Type**: API Key
|
||||
- **Header**: `x-api-key: {key}`
|
||||
- **Get key**: https://dashboard.exa.ai
|
||||
|
||||
## Endpoints
|
||||
|
||||
Base URL: `https://api.exa.ai`
|
||||
|
||||
| Endpoint | Purpose |
|
||||
|----------|---------|
|
||||
| `POST /search` | Search the web with neural, keyword-like, or auto-routed modes |
|
||||
| `POST /findSimilar` | Find pages similar to a given URL |
|
||||
| `POST /contents` | Fetch text, highlights, or summaries for one or more URLs |
|
||||
|
||||
## Common Agent Operations
|
||||
|
||||
### Web Search with Content
|
||||
|
||||
```bash
|
||||
POST https://api.exa.ai/search
|
||||
{
|
||||
"query": "best B2B SaaS onboarding flows",
|
||||
"type": "auto",
|
||||
"numResults": 10,
|
||||
"contents": {
|
||||
"text": { "maxCharacters": 1000 },
|
||||
"highlights": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Competitor Content Discovery
|
||||
|
||||
```bash
|
||||
POST https://api.exa.ai/search
|
||||
{
|
||||
"query": "landing page teardowns",
|
||||
"includeDomains": ["goodui.org", "growth.design", "marketingexamples.com"],
|
||||
"startPublishedDate": "2024-01-01T00:00:00Z",
|
||||
"contents": { "highlights": true }
|
||||
}
|
||||
```
|
||||
|
||||
### Find Similar Pages
|
||||
|
||||
```bash
|
||||
POST https://api.exa.ai/findSimilar
|
||||
{
|
||||
"url": "https://stripe.com/pricing",
|
||||
"numResults": 20,
|
||||
"contents": { "summary": { "query": "What pricing model and price points does this page use?" } }
|
||||
}
|
||||
```
|
||||
|
||||
### Category-Filtered Search
|
||||
|
||||
```bash
|
||||
POST https://api.exa.ai/search
|
||||
{
|
||||
"query": "DTC beauty brand raising Series A",
|
||||
"category": "news",
|
||||
"numResults": 25,
|
||||
"startPublishedDate": "2024-06-01T00:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
### Fetch Contents for Known URLs
|
||||
|
||||
```bash
|
||||
POST https://api.exa.ai/contents
|
||||
{
|
||||
"urls": ["https://example.com/post-1", "https://example.com/post-2"],
|
||||
"text": true,
|
||||
"summary": { "query": "Summarize this article's key argument in one paragraph." }
|
||||
}
|
||||
```
|
||||
|
||||
## Key Parameters
|
||||
|
||||
### Search Types
|
||||
- `auto` - Automatically routes between neural and keyword matching (default)
|
||||
- `neural` - Embedding-based semantic search; best for concept/idea queries
|
||||
- `fast` - Lower-latency neural search
|
||||
- `instant` - Returns cached results near-instantly
|
||||
- `deep-lite`, `deep`, `deep-reasoning` - Agentic search variants that plan multiple queries and synthesize
|
||||
|
||||
### Categories
|
||||
`company`, `research paper`, `news`, `personal site`, `financial report`, `people`
|
||||
|
||||
### Filtering
|
||||
- `includeDomains` / `excludeDomains` - Restrict to or exclude specific domains (up to 1200)
|
||||
- `includeText` / `excludeText` - Require or forbid phrases in result pages
|
||||
- `startPublishedDate` / `endPublishedDate` - ISO 8601 publication date range
|
||||
- `startCrawlDate` / `endCrawlDate` - ISO 8601 crawl date range
|
||||
- `userLocation` - Two-letter country code (e.g., `US`)
|
||||
|
||||
### Contents (Mix and Match)
|
||||
All three can be requested in the same call:
|
||||
- `text: true` or `{ maxCharacters, includeHtmlTags, verbosity }` - Full or truncated page text
|
||||
- `highlights: true` or `{ query, maxCharacters }` - LLM-selected relevant snippets
|
||||
- `summary: { query, schema }` - LLM-generated summary, optionally conforming to a JSON schema
|
||||
|
||||
## When to Use
|
||||
|
||||
- **Content research** - Find high-quality long-form content on niche topics by meaning, not just keywords
|
||||
- **Competitor discovery** - Find companies similar to one you've identified via `findSimilar`
|
||||
- **SEO content gap analysis** - Search for topics your competitors rank for and pull highlights for quick review
|
||||
- **Customer research** - Find forum threads, blog posts, and reviews about your product or category
|
||||
- **Audience research** - Discover blogs, newsletters, and communities where your ICP publishes or comments
|
||||
- **News monitoring** - Track mentions of your brand, competitors, or category with date-filtered news search
|
||||
- **Link prospecting** - Find authoritative pages covering topics you write about, for outreach
|
||||
- **Lead research** - Use the `company` and `people` categories to discover accounts or individuals matching criteria
|
||||
|
||||
## Rate Limits
|
||||
|
||||
- Varies by plan; see https://exa.ai/pricing
|
||||
- Most production plans support hundreds of concurrent requests
|
||||
- Content retrieval (text/highlights/summary) is billed separately from the base search
|
||||
|
||||
## Relevant Skills
|
||||
|
||||
- seo-audit
|
||||
- ai-seo
|
||||
- content-strategy
|
||||
- competitor-profiling
|
||||
- competitor-alternatives
|
||||
- customer-research
|
||||
- cold-email
|
||||
- lead-magnets
|
||||
- marketing-ideas
|
||||
@@ -0,0 +1,257 @@
|
||||
# RankParse
|
||||
|
||||
Agent-friendly SEO data API for backlinks, domain authority, tech stack, and on-page metadata. Designed as a low-cost alternative to enterprise SEO suites.
|
||||
|
||||
## Capabilities
|
||||
|
||||
| Integration | Available | Notes |
|
||||
|-------------|-----------|-------|
|
||||
| API | ✓ | REST API at `api.rankparse.com` |
|
||||
| MCP | ✓ | Hosted MCP server for agent use |
|
||||
| CLI | [✓](../clis/rankparse.js) | Node CLI wrapper |
|
||||
| SDK | - | API-only (SDKs in progress) |
|
||||
|
||||
## Authentication
|
||||
|
||||
- **Type**: API Key
|
||||
- **Header**: `X-API-Key: rp_...`
|
||||
- **Get key**: Sign up at https://rankparse.com and create a key in the dashboard
|
||||
- **Billing**: Credit-based (one-time credit packs, no subscription). Each endpoint deducts a fixed number of credits per call.
|
||||
|
||||
## Common Agent Operations
|
||||
|
||||
### Domain authority
|
||||
|
||||
```bash
|
||||
GET https://api.rankparse.com/v1/domain-authority?domain=example.com
|
||||
|
||||
X-API-Key: rp_...
|
||||
```
|
||||
|
||||
Returns authority score, registered date, registrar, and popularity rank.
|
||||
|
||||
### Backlinks
|
||||
|
||||
```bash
|
||||
GET https://api.rankparse.com/v1/backlinks?domain=example.com&limit=100
|
||||
|
||||
X-API-Key: rp_...
|
||||
```
|
||||
|
||||
Optional params: `sort=importance|recent`, `from_domain=`, `link_type=`, `score=true`.
|
||||
|
||||
### Referring domains
|
||||
|
||||
```bash
|
||||
GET https://api.rankparse.com/v1/referring-domains?domain=example.com&limit=100
|
||||
|
||||
X-API-Key: rp_...
|
||||
```
|
||||
|
||||
### Outbound links
|
||||
|
||||
```bash
|
||||
GET https://api.rankparse.com/v1/outbound-links?domain=example.com&limit=100
|
||||
|
||||
X-API-Key: rp_...
|
||||
```
|
||||
|
||||
### Anchor text profile
|
||||
|
||||
```bash
|
||||
GET https://api.rankparse.com/v1/anchor-text?domain=example.com&limit=100
|
||||
|
||||
X-API-Key: rp_...
|
||||
```
|
||||
|
||||
### Top pages
|
||||
|
||||
```bash
|
||||
GET https://api.rankparse.com/v1/top-pages?domain=example.com&limit=50
|
||||
|
||||
X-API-Key: rp_...
|
||||
```
|
||||
|
||||
### Domain overlap
|
||||
|
||||
```bash
|
||||
GET https://api.rankparse.com/v1/domain-overlap?domains=a.com,b.com,c.com
|
||||
|
||||
X-API-Key: rp_...
|
||||
```
|
||||
|
||||
Compare 2–5 domains.
|
||||
|
||||
### Link intersect
|
||||
|
||||
```bash
|
||||
GET https://api.rankparse.com/v1/link-intersect?domain_a=a.com&domain_b=b.com
|
||||
|
||||
X-API-Key: rp_...
|
||||
```
|
||||
|
||||
Domains that link to both targets.
|
||||
|
||||
### Competitor gap
|
||||
|
||||
```bash
|
||||
GET https://api.rankparse.com/v1/competitor-gap?domain=mysite.com&vs=competitor.com
|
||||
|
||||
X-API-Key: rp_...
|
||||
```
|
||||
|
||||
### Similar domains
|
||||
|
||||
```bash
|
||||
GET https://api.rankparse.com/v1/similar-domains?domain=example.com
|
||||
|
||||
X-API-Key: rp_...
|
||||
```
|
||||
|
||||
### Tech stack
|
||||
|
||||
```bash
|
||||
GET https://api.rankparse.com/v1/tech-stack?domain=example.com
|
||||
|
||||
X-API-Key: rp_...
|
||||
```
|
||||
|
||||
### Page SEO
|
||||
|
||||
```bash
|
||||
GET https://api.rankparse.com/v1/page-seo?url=https://example.com/page
|
||||
|
||||
X-API-Key: rp_...
|
||||
```
|
||||
|
||||
Returns title, meta description, OG tags, canonical, and structured metadata for a single URL.
|
||||
|
||||
### Page performance
|
||||
|
||||
```bash
|
||||
GET https://api.rankparse.com/v1/page-performance?url=https://example.com/page&strategy=mobile
|
||||
|
||||
X-API-Key: rp_...
|
||||
```
|
||||
|
||||
Core Web Vitals via Google PageSpeed Insights. Daily quotas apply.
|
||||
|
||||
### Site health
|
||||
|
||||
```bash
|
||||
GET https://api.rankparse.com/v1/site-health?domain=example.com
|
||||
|
||||
X-API-Key: rp_...
|
||||
```
|
||||
|
||||
### Sitemap
|
||||
|
||||
```bash
|
||||
GET https://api.rankparse.com/v1/sitemap?domain=example.com&limit=100
|
||||
|
||||
X-API-Key: rp_...
|
||||
```
|
||||
|
||||
### Crawl history
|
||||
|
||||
```bash
|
||||
GET https://api.rankparse.com/v1/crawl-history?domain=example.com
|
||||
|
||||
X-API-Key: rp_...
|
||||
```
|
||||
|
||||
Wayback Machine snapshots for the domain.
|
||||
|
||||
### Link audit
|
||||
|
||||
```bash
|
||||
GET https://api.rankparse.com/v1/link-audit?domain=example.com
|
||||
|
||||
X-API-Key: rp_...
|
||||
```
|
||||
|
||||
Combined health score, risk flags, anchor profile, and top backlinks.
|
||||
|
||||
### Site explorer
|
||||
|
||||
```bash
|
||||
GET https://api.rankparse.com/v1/site-explorer?domain=example.com
|
||||
|
||||
X-API-Key: rp_...
|
||||
```
|
||||
|
||||
All-in-one snapshot of a domain.
|
||||
|
||||
### Batch lookup
|
||||
|
||||
```bash
|
||||
POST https://api.rankparse.com/v1/batch
|
||||
Content-Type: application/json
|
||||
X-API-Key: rp_...
|
||||
|
||||
{ "domains": ["a.com", "b.com", "c.com"] }
|
||||
```
|
||||
|
||||
Bulk domain summaries in one call.
|
||||
|
||||
## Free Tools (Unauthenticated)
|
||||
|
||||
Public, IP-rate-limited endpoints for quick lookups without an API key:
|
||||
|
||||
- `GET /v1/tools/backlinks?domain=`
|
||||
- `GET /v1/tools/domain-authority?domain=`
|
||||
- `GET /v1/tools/tech-stack?domain=`
|
||||
- `GET /v1/tools/similar-websites?domain=`
|
||||
- `GET /v1/tools/domain-age?domain=`
|
||||
- `GET /v1/tools/meta-tag-analyzer?url=`
|
||||
- `GET /v1/tools/link-intersect?domain_a=&domain_b=`
|
||||
- `GET /v1/tools/page-speed?url=`
|
||||
|
||||
## Key Response Fields
|
||||
|
||||
### Domain Metrics
|
||||
- `authority` - Domain authority score
|
||||
- `popularity_rank` - Tranco popularity rank
|
||||
- `registered_at` - Domain registration date
|
||||
- `registrar` - Registrar name
|
||||
|
||||
### Backlink Fields
|
||||
- `from_url` - Source URL
|
||||
- `to_url` - Target URL
|
||||
- `anchor` - Anchor text
|
||||
- `link_type` - dofollow / nofollow / ugc / sponsored
|
||||
- `first_seen` - First discovery date
|
||||
|
||||
## When to Use
|
||||
|
||||
- Backlink discovery and analysis
|
||||
- Competitor link research and gap analysis
|
||||
- Domain authority lookups at scale
|
||||
- Tech stack detection
|
||||
- On-page SEO audits
|
||||
- Sitemap and crawl history discovery
|
||||
- Agent-driven SEO workflows where per-call cost matters
|
||||
|
||||
## Pricing Model
|
||||
|
||||
- Pay-as-you-go credit packs (no subscription)
|
||||
- Most domain endpoints: 1–2 credits per call
|
||||
- Aggregated endpoints (overlap, intersect, similar, gap): 5 credits
|
||||
- Link audit: 8 credits
|
||||
- Site explorer: 10 credits
|
||||
- Batch: 1 credit per domain
|
||||
- Free tier available for unauthenticated endpoints
|
||||
|
||||
## MCP Server
|
||||
|
||||
RankParse ships a hosted MCP server exposing all endpoints as tools — connect from Claude, Cursor, or any MCP-compatible agent. See https://rankparse.com for connection details.
|
||||
|
||||
## Relevant Skills
|
||||
|
||||
- seo-audit
|
||||
- content-strategy
|
||||
- competitors
|
||||
- competitor-profiling
|
||||
- ai-seo
|
||||
- site-architecture
|
||||
- schema
|
||||
Reference in New Issue
Block a user