claygent-verifier

claygent-verifier

MCP server that verifies Claygent-generated claims from a Clay export CSV by re-checking each claim against its source URL, outputting verification verdicts.

Category
访问服务器

README

Claygent Verification Agent

Takes a Clay export CSV and re-checks every Claygent-generated claim against its row's own source URL before that data reaches a live outreach sequence. Ships two interfaces (CLI, MCP server) over one shared verification engine.

Why this exists

Clay's built-in AI research agent, Claygent, hallucinates: it fabricates dates, misattributes facts, and sometimes ignores its own "return JSON only" instruction and returns a narrative sentence instead. I hit this directly building a news/fundraising signal monitor for a client's Clay workflow - Claygent occasionally broke every downstream field extraction on a row by not returning valid JSON, and there was no way to tell a real hallucination from a correct extraction without manually re-checking the source article. Clay has no systematic fix for this; their own support response is "try a different integration."

This tool is that manual re-check, automated: take Claygent's claim, fetch the same source URL a human would click to verify it, and ask an independent model whether the page actually supports the claim. It's built to fail loudly, not quietly - a row with nothing usefully extracted, a source that can't be fetched, or a page that doesn't address the claim all produce their own distinct, reportable outcome (NO_CLAIM_DATA, FETCH_FAILED, UNVERIFIABLE) instead of being silently skipped or forced into a MATCH.

Schema-agnostic by design (and why there's no single "claim column")

There's no fixed Clay export format to conform to, and there's no single "claim column" to point this tool at - a real Clay CSV export never carries the raw Claygent response with data in it; that column always exports blank. The only columns with real values are the ones manually selected from Claygent's side panel (click the response cell, pick which JSON keys become their own table columns). So this tool takes a list of pre-extracted claim columns, whatever names and however many your export happens to have, and treats a row where every one of those columns is blank as the real-world signature of a failed extraction (NO_CLAIM_DATA) - not a JSON parse error, since there's never any raw JSON in the export to parse in the first place. app/csv_mapper.py never hardcodes a specific client's schema.

Architecture

app/
  schema.py            : shared dataclasses passed between every stage
  csv_mapper.py         : deterministic - CSV parsing + configurable multi-column claim mapping
  claim_parser.py        : deterministic - drops blank claim columns, flags NO_CLAIM_DATA if all blank
  fetcher.py              : deterministic - fetch source URL -> page text, with failure taxonomy
  verifiers.py             : ClaimVerifier interface + ClaudeClaimVerifier (the one LLM call)
  model_capabilities.py     : per-model thinking/effort quirks (copied from the sibling
                              ai-personalization-engine project, kept in sync manually)
  engine.py                  : batch orchestration + cost estimation, depends only on
                                the ClaimVerifier interface, never a vendor SDK directly
  cli.py                      : thin CLI, single CSV in, verified CSV out
  mcp_server.py                 : thin MCP tool, same engine.run_batch() call as the CLI
tests/
  test_csv_mapper.py    : multi-column mapping, arbitrary/missing headers
  test_claim_parser.py   : blank-column filtering incl. the all-blank NO_CLAIM_DATA case
  test_fetcher.py          : fetch failure taxonomy (dead link, timeout, paywall, JS shell)
  test_engine.py             : full orchestration against a FakeClaimVerifier double
  fixtures/                    : synthetic CSVs modeled on real Clay export column shapes,
                                  including a blank raw-response column for realism

engine.py never imports anthropic or requests directly - only the ClaimVerifier interface and the deterministic modules above it. The CLI and MCP server both call engine.run_batch() and nothing else, so they can't drift out of sync with each other; adding a third interface (e.g. a future Sheets add-on) means writing a thin wrapper, not new verification logic.

Cost-aware by design

--estimate-only gives a rough pre-flight cost estimate, based on a character-count heuristic, before any API calls are made:

python -m app.cli export.csv --claim-columns funding_series,is_confirmed --source-column Link --estimate-only
# 3 rows, estimated cost for model claude-sonnet-5: ~$0.0071

Every real run also reports actual token usage and dollar cost per batch, same credit-conscious pattern as the other tools in this portfolio.

Running it

python -m venv .venv
.venv/Scripts/activate        # .venv/bin/activate on macOS/Linux
pip install -r requirements.txt

export ANTHROPIC_API_KEY=sk-ant-...   # required for real runs, not for tests

# CLI
python -m app.cli export.csv --claim-columns funding_series,is_confirmed --source-column Link --out verified.csv

# MCP server (wire into a client's .mcp.json, or run standalone)
python -m app.mcp_server

Example .mcp.json entry for Claude Code / Cursor:

{"mcpServers": {"claygent-verifier": {"command": "python", "args": ["-m", "app.mcp_server"]}}}

Input CSV needs, at minimum, one or more pre-extracted claim columns and a source-URL column - any names, any count, pointed to explicitly. The raw Claygent-response column, if your export even has one, is expected to be blank and is simply ignored:

company_name,claygent_extraction,funding_series,is_confirmed,source_url
Acme Robotics,,Series B,CONFIRMED,https://example.com/news/acme-series-b

Output CSV is the same rows plus verification_verdict, verification_detail, verification_confidence_note, and verification_checked_fields columns.

Tests

pip install pytest requests-mock
python -m pytest tests/ -v

33 unit tests, no Anthropic API key, no real network calls (requests_mock intercepts the transport layer for fetcher/engine tests, and raises on any URL that wasn't explicitly registered - so a test can't silently succeed by hitting the real internet). They verify multi-column claim mapping, blank- column filtering (including the all-blank NO_CLAIM_DATA case), the fetch failure taxonomy, and the full engine orchestration against a FakeClaimVerifier double. They do not verify actual LLM judgment quality - whether ClaudeClaimVerifier correctly distinguishes MATCH from MISMATCH on real page text needs a real API key and human review on real claims, which is a manual smoke-testing step, not something covered by the automated suite.

Manual smoke test not yet run in this environment: no ANTHROPIC_API_KEY was available when this was built, so ClaudeClaimVerifier, the CLI's non---estimate-only path, and the MCP tool's real verification call are untested against the live API. Run the CLI once against a real CSV with a real key to close this gap - see "Known limitations" below.

Test data

tests/fixtures/ contains only synthetic data: invented company names, invented URLs, modeled on the real column shapes seen in an actual client Clay export but with no real client data. No Employers/ client CSVs were used in the test suite or in this README, by deliberate choice - see the project's build plan for the reasoning.

Known limitations

  • No raw-JSON-blob path. This tool assumes claim data always arrives as N pre-extracted columns, since that's what a real Clay export produces. If some future Clay export config somehow does carry a real JSON blob with data in it, this tool won't parse it - you'd need to select the fields into their own columns first, the same way you already do for a normal Clay export.
  • Manual smoke test against the live Claude API hasn't been run yet in this build environment - see "Tests" above. This is the single biggest gap before treating this as demo-ready.
  • Cost estimates are heuristics. The pre-flight estimate uses a ~4-characters-per-token approximation, not the API's real tokenizer.
  • Model pricing table is a static, manually-maintained reference (MODEL_PRICING_PER_MILLION in app/engine.py). Verify at anthropic.com/pricing before relying on it for real budgeting.
  • Paywall/JS-rendered detection is heuristic, not exhaustive: it flags pages with very little extracted article text and, for paywalls, a known marker phrase. A paywall or JS site that doesn't match either signal will likely just extract as thin real text and get judged UNVERIFIABLE by the LLM stage instead of being caught earlier - a reasonable fallback, but not the same as a purpose-built paywall detector.
  • One retry on timeout, one vendor implemented. fetcher.py retries a timeout once before giving up; ClaimVerifier has one working implementation (Claude). The interface is vendor-agnostic, but no second implementation has been written.
  • No non-technical interface yet. This ships CLI + MCP only. A Sheets/Clay-native interface for GTM operators who aren't in a terminal is planned as later work, not built here.
  • No case-study writeup yet. A demo writeup for job-hunting/Portfolio/case-studies/ is planned as later work, once the live-API smoke test above has actually been run and its real output can be shown.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选