Skip to content

feat(mcp): human titles + tool annotations on all 51 tools - #450

Merged
ralyodio merged 1 commit into
masterfrom
feat/mcp-tool-annotations
Nov 11, 2026
Merged

ralyodio merged 1 commit into
masterfrom
feat/mcp-tool-annotations

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Adds a human title and explicit annotations (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) to every one of the 51 CrawlProof MCP tools, for the Claude Connectors Directory.

  • lib/mcp/annotations.ts: one TOOL_HINTS entry per tool. withToolHints(server) runs first in the /api/mcp initializer and merges title + annotations into each registerTool config, so the SDK (1.32.2) tools/list mapper emits them. A tool without an entry throws at startup.
  • Names, input schemas, behaviour unchanged. The existing tools/list wrapper (resultType/ttlMs/cacheScope) still spreads the SDK result, so the new fields pass through.
  • Destructive: post_to_socials, promote_url, send_message, autoblog_post, autoblog_guest_post, start_audit (credits), affiliate_payout (money), deletes, overwrites (update_webhook, payout address, affiliate webhook), token/secret rotation.

Tests (local, bun-installed worktree):

  • vitest run tests/mcp-annotations.test.ts: 3 pass; lists through the real SDK Client over InMemoryTransport, 51/51 with title + 4 hints
  • vitest run: 259 files / 3086 tests pass
  • tsc --noEmit: clean

🤖 Generated with Claude Code

Claude's Connectors Directory requires a title and readOnlyHint /
destructiveHint / openWorldHint on every tool. lib/mcp/annotations.ts
holds one entry per tool (plus idempotentHint) and withToolHints()
merges it into every registerTool config before the modules register,
so the SDK's own tools/list mapper emits title + annotations. A tool
with no entry throws at startup. Names, schemas and behaviour are
unchanged; the tools/list cache-field wrapper still spreads the SDK
result.

Posting, sending outreach, publishing articles, spending credits or
money, deletes and overwrites are destructive; reads are readOnly;
anything reaching a third-party site, network, mailbox, AI engine or
webhook receiver is openWorld.

Test: tests/mcp-annotations.test.ts lists tools through the real SDK
client and asserts all 51 carry a title + all four hints.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

ThreatCrush Security Scan

50 finding(s)

HIGH/CRITICAL: 2 | MEDIUM: 30 | LOW: 18

Severity Rule Location
HIGH tls-verification-disabled lib/onion.ts:50
HIGH secret-generic-credential lib/sp/platforms/facebook.ts:32
MEDIUM js-unescaped-html-sink app/(app)/dashboard/admin/email-broadcast/EmailBroadcastForm.tsx:125
MEDIUM js-unescaped-html-sink app/(app)/dashboard/projects/[id]/autoblog/articles/[articleId]/page.tsx:214
MEDIUM js-unescaped-html-sink app/(marketing)/blog/[slug]/page.tsx:74
MEDIUM js-unescaped-html-sink app/(marketing)/blog/[slug]/page.tsx:102
MEDIUM js-unescaped-html-sink app/(marketing)/recent/page.tsx:177
MEDIUM js-unescaped-html-sink app/(marketing)/recent/page.tsx:181
MEDIUM js-unescaped-html-sink app/c/[project]/[slug]/page.tsx:76
MEDIUM js-unescaped-html-sink app/c/[project]/page.tsx:58
MEDIUM js-unescaped-html-sink app/careers.js/route.ts:228
MEDIUM js-unescaped-html-sink app/careers.js/route.ts:285
MEDIUM js-unescaped-html-sink app/layout.tsx:139
MEDIUM js-open-redirect app/login/form.tsx:40
MEDIUM js-unescaped-html-sink app/r/[token]/page.tsx:164
MEDIUM js-open-redirect app/signup/form.tsx:65
MEDIUM js-unescaped-html-sink app/surveys/[slug]/invite/page.tsx:68
MEDIUM js-unescaped-html-sink components/json-ld.tsx:8
MEDIUM js-unescaped-html-sink components/pit-footer.tsx:17
MEDIUM js-unescaped-html-sink components/report/markdown-view.tsx:16
MEDIUM js-unescaped-html-sink lib/careers/page-templates.ts:198
MEDIUM js-dynamic-code-execution lib/crawl-limits.ts:67
MEDIUM redos-nested-quantifier lib/emailMarkdown.ts:41
MEDIUM redos-nested-quantifier lib/emailMarkdown.ts:324
MEDIUM redos-nested-quantifier lib/lx/articleGen.ts:100
MEDIUM redos-nested-quantifier lib/tracker/agent-gate.ts:61
MEDIUM sh-predictable-temp-path ops/selfhost/server/setup-supabase.sh:218
MEDIUM sql-template-interpolation scripts/detect-slot-themes.ts:31
MEDIUM sql-template-interpolation scripts/purge-constructed-keywords.ts:163
MEDIUM sql-template-interpolation scripts/purge-offniche-keywords.ts:124
MEDIUM js-dynamic-code-execution scripts/test-crawl-limits.mjs:14
MEDIUM js-dynamic-code-execution scripts/test-crawl-limits.mjs:24
LOW secret-generic-credential app/(marketing)/docs/autoblog-webhook/page.tsx:156
LOW secret-generic-credential lib/sealed/migrate.ts:38
LOW secret-generic-credential lib/sp/platforms/linkedin.ts:25
LOW secret-generic-api-key tests/ads-generator-agent.test.ts:160
LOW secret-generic-api-key tests/ads-generator-agent.test.ts:187
LOW js-dynamic-code-execution tests/careers-page-templates.test.ts:21
LOW js-dynamic-code-execution tests/careers-widget-script.test.ts:19
LOW js-dynamic-code-execution tests/careers-widget-script.test.ts:69
LOW js-dynamic-code-execution tests/contract/ad-visitor-id.test.ts:51
LOW js-dynamic-code-execution tests/contract/ad-visitor-id.test.ts:52
LOW js-dynamic-code-execution tests/contract/ads-click-cooldown-redis.test.ts:20
LOW js-dynamic-code-execution tests/contract/ads-click-cooldown-redis.test.ts:24
LOW js-dynamic-code-execution tests/contract/ads-click-cooldown-redis.test.ts:25
LOW js-dynamic-code-execution tests/contract/ads-click-cooldown-redis.test.ts:26
LOW js-dynamic-code-execution tests/contract/ads-click-cooldown-redis.test.ts:31
LOW js-dynamic-code-execution tests/contract/ads-click-cooldown-redis.test.ts:35
LOW secret-generic-credential tests/contract/posthog-integration.test.ts:13
LOW secret-generic-credential tests/lead-campaign.test.ts:16

Snippets are redacted; ThreatCrush never prints matched credential material.

@ralyodio
ralyodio merged commit bfe25f7 into master Nov 11, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant