Apodyx is a verified CRM SaaS registry queryable by AI agents via MCP (Model Context Protocol). The MVP validates one hypothesis: will AI agents query a third-party verified registry when making software recommendations? There is no frontend. There is no vendor-facing UI. The entire product is the MCP server and the data behind it.
Unprompted agent queries appearing in agent_query_logs within 14 days of MCP server publication.
- Database: Supabase (PostgreSQL)
- API: Vercel serverless functions (Node.js)
- MCP Server: npm package (Node.js, MCP SDK)
- Seeding: Node.js script consuming Scout CSV output
- No frontend. No auth. No RLS.
SUPABASE_URL= SUPABASE_ANON_KEY= SUPABASE_SERVICE_ROLE_KEY=
Store in .env locally. Add to Vercel environment variables for deployed functions.
apodyx/
├── ARCHITECTURE.md
├── .env.example
├── .gitignore
├── package.json
├── api/
│ ├── search.js # GET /api/search
│ ├── product.js # GET /api/product/:id
│ ├── verify.js # GET /api/verify/:id
│ └── log-query.js # POST /api/log-query (internal, called by MCP server)
├── mcp/
│ ├── index.js # MCP server entry point
│ ├── tools/
│ │ ├── search.js # search_crm_software tool
│ │ ├── details.js # get_software_details tool
│ │ ├── compare.js # compare_software tool
│ │ └── report.js # report_issue tool
│ └── package.json # separate npm package for MCP server
├── scripts/
│ ├── seed.js # bulk import Scout CSV to Supabase
│ ├── verify.js # run automated checks on all products
│ └── schema.sql # full Supabase schema
└── lib/
├── supabase.js # Supabase client singleton
└── scorer.js # trust score calculation logic
| column | type | notes |
|---|---|---|
| id | uuid | primary key, gen_random_uuid() |
| name | text | required |
| url | text | required |
| description | text | |
| crm_subcategory | text[] | array: general, real estate, nonprofit, financial services, construction, healthcare, sales-focused, marketing-focused |
| pricing_model | text | free, freemium, paid |
| price_min | numeric | lowest paid tier per month |
| price_max | numeric | highest published tier, null if enterprise-only |
| free_tier | boolean | |
| target_company_size | text[] | array: 1-10, 11-50, 51-200, 201-1000, enterprise |
| primary_use_cases | text[] | array: sales pipeline, marketing automation, customer support, field sales, inside sales, account management |
| api_available | boolean | |
| mobile_app | boolean | |
| data_residency | text | US-only, EU available, global, unknown |
| contract_terms | text | monthly, annual-only, both |
| implementation_complexity | text | self-serve, guided, requires partner |
| deployment_model | text | cloud-only, on-premise available, hybrid |
| g2_rating | numeric | from public G2 listing, null if not listed |
| us_based | boolean | default true |
| claimed | boolean | default false |
| created_at | timestamptz | default now() |
| column | type | notes |
|---|---|---|
| id | uuid | primary key |
| product_id | uuid | fk to products |
| integration_name | text | |
| verified | boolean | default false |
| column | type | notes |
|---|---|---|
| id | uuid | primary key |
| product_id | uuid | fk to products |
| cert_type | text | SOC2, GDPR, HIPAA, ISO27001 |
| claimed | boolean | default true |
| verified | boolean | default false |
| verified_date | date |
| column | type | notes |
|---|---|---|
| id | uuid | primary key |
| product_id | uuid | fk to products |
| check_type | text | ssl, security_headers, uptime, domain_age, pricing_accessible, us_signal |
| result | text | pass, fail, warn |
| score | numeric | points contributed to trust score |
| checked_at | timestamptz | default now() |
| column | type | notes |
|---|---|---|
| id | uuid | primary key |
| product_id | uuid | fk to products |
| trust_score | numeric | 0-100 |
| report_json | jsonb | full breakdown of all checks |
| generated_at | timestamptz | default now() |
| column | type | notes |
|---|---|---|
| id | uuid | primary key |
| query_params | jsonb | full params passed by agent |
| results_returned | jsonb | array of product ids returned |
| result_count | int | |
| session_id | text | optional, if agent passes one |
| created_at | timestamptz | default now() |
| column | type | notes |
|---|---|---|
| id | uuid | primary key |
| product_id | uuid | fk to products |
| issue_type | text | wrong_pricing, wrong_compliance, discontinued, other |
| description | text | |
| submitted_at | timestamptz | default now() |
Primary agent-facing endpoint. Returns ranked array of products sorted by trust score.
Query params (all optional, flexible matching):
- category: crm subcategory string or array
- price_max: numeric, filters price_min <= price_max
- price_min: numeric
- compliance: comma-separated cert types (soc2, gdpr, hipaa, iso27001)
- integration: integration name string, partial match
- free_tier: boolean
- target_size: company size string
- use_case: use case tag string
- api: boolean
- mobile: boolean
- deployment: cloud-only, on-premise available, hybrid
- contract: monthly, annual-only, both
- complexity: self-serve, guided, requires partner
- limit: default 10, max 25
Response shape:
[
{
"id": "uuid",
"name": "string",
"url": "string",
"description": "string",
"trust_score": 85,
"pricing_model": "freemium",
"price_min": 15,
"price_max": 99,
"free_tier": true,
"crm_subcategory": ["general", "sales-focused"],
"target_company_size": ["11-50", "51-200"],
"primary_use_cases": ["sales pipeline", "inside sales"],
"compliance": ["SOC2", "GDPR"],
"top_integrations": ["Slack", "Gmail", "Zapier"],
"api_available": true,
"mobile_app": true,
"g2_rating": 4.4
}
]Every call to this endpoint must also call POST /api/log-query with the params and results.
Full profile for a single product. Returns all fields including full integration list, all compliance claims, and latest verification report.
Latest verification report for a product. Returns trust score and full check breakdown.
Called by MCP server after every search. Not exposed publicly.
Body:
{
"query_params": {},
"results_returned": [],
"result_count": 0,
"session_id": "optional"
}Package name: apodyx-mcp Published to: npm, Anthropic MCP directory, Smithery, PulseMCP
Description: Search the Apodyx verified CRM registry. Returns structured, verified data on CRM software products matching the specified criteria. All results include trust scores based on automated security and verification checks.
Input schema:
- price_max (number, optional): maximum monthly price per user
- price_min (number, optional): minimum monthly price
- compliance (array of strings, optional): required certifications e.g. ["SOC2", "HIPAA"]
- integrations (array of strings, optional): required integrations e.g. ["Slack", "Salesforce"]
- free_tier (boolean, optional): whether a free tier is required
- target_size (string, optional): company size the product targets
- use_case (string, optional): primary use case
- limit (number, optional): number of results, default 5
Description: Get full verified profile for a specific CRM product by name or ID. Returns complete structured data including all integrations, compliance claims, pricing details, and trust score breakdown.
Input schema:
- product (string, required): product name or Apodyx product ID
Description: Compare 2-3 CRM products side by side on specified attributes. Returns structured comparison table.
Input schema:
- products (array of strings, required): 2-3 product names or IDs
- attributes (array of strings, optional): specific fields to compare, defaults to price, compliance, integrations, trust_score, target_size
Description: Report an inaccuracy in a product's Apodyx listing. Use when you encounter data that contradicts the registry.
Input schema:
- product (string, required): product name or ID
- issue_type (string, required): wrong_pricing, wrong_compliance, discontinued, other
- description (string, required): description of the inaccuracy
100 points total:
- SSL grade A: 20pts
- Security headers present (HSTS, CSP, X-Frame-Options): 20pts
- Site responding (uptime): 20pts
- Domain age over 2 years: 15pts
- Pricing publicly accessible (not JS-gated): 15pts
- US incorporation signal present: 10pts
Run by scripts/verify.js on all products after seed import and weekly thereafter.
- SSL check: fetch SSL Labs API or ssl-checker npm package
- Security headers: fetch product URL, check response headers
- Uptime: simple HTTP GET, expect 200
- Domain age: WHOIS lookup via whois npm package
- Pricing accessibility: fetch /pricing URL, check if content renders without JS
- US signal: check WHOIS registrant country or about page for US address
scripts/seed.js accepts Scout CSV with the following column headers: name, url, description, crm_subcategory, pricing_model, price_min, price_max, free_tier, target_company_size, primary_use_cases, integrations (pipe-separated), compliance (pipe-separated), api_available, mobile_app, data_residency, contract_terms, implementation_complexity, deployment_model, g2_rating
After import, automatically triggers scripts/verify.js on all imported products.
On completion:
- npm publish from mcp/ directory
- Submit to Anthropic MCP directory: https://docs.anthropic.com/mcp
- Submit to Smithery: https://smithery.ai
- Submit to PulseMCP: https://pulsemcp.com
No dashboard. Query agent_query_logs directly in Supabase:
-- Check for any agent queries
select created_at, query_params, result_count
from agent_query_logs
order by created_at desc
limit 20;
-- Check query volume by day
select date_trunc('day', created_at) as day, count(*)
from agent_query_logs
group by day
order by day desc;