The unified NodeBench MCP gateway keeps one deployable service, but clients should not receive the full internal tool catalog by default. Tool profiles provide small, task-specific catalogs for external builders while preserving the full 114-tool internal surface.
https://nodebench-mcp-unified.onrender.com| Profile | Intended client | Tool count |
|---|---|---|
public-research |
External apps that need public entity research memory | 14 |
gmail-research |
Gmail/job-match integrations | 10 |
documents |
Document and spreadsheet agents | 21 |
memory |
Agent memory clients | 5 |
financial |
Market, macro, crypto, and news lookups | 10 |
knowledge |
Knowledge graph and source registry clients | 11 |
builder |
Builder-facing agents that need research, docs, memory, planning, and search | 55 |
internal-full / full |
Internal NodeBench operators and eval harnesses | 114 |
Counts include the profile-scoped findTools meta-tool. In a profile, findTools only searches the visible tools for that profile.
HTTP MCP clients can request a profile with either a query parameter or header:
https://nodebench-mcp-unified.onrender.com?profile=public-researchx-nodebench-profile: public-researchor:
x-mcp-profile: public-researchIf the server is configured with a profile-scoped token, the token wins over query/header profile requests. For example, a gmail-research token cannot request full.
Hosted production allows anonymous access to the public profiles listed in MCP_PUBLIC_PROFILES:
public-research,gmail-researchThat means external Gmail/job integrations can call the hosted MCP URL with ?profile=gmail-research and no token. Internal, builder, document, memory, and full profiles still require a token when MCP_HTTP_TOKEN or MCP_PROFILE_TOKENS is configured.
The hosted MCP gateway is frictionless for public research, but still account-aware:
- Token calls are attributed to a stable
token:<hash>account key. - Anonymous public calls are attributed to a stable
anon:<profile>:<hash>account key derived from request metadata without storing raw tokens. - Every tool call writes to the MCP ledger with profile, auth mode, client name, request id, estimated cost units, and estimated USD.
- Daily rollups are stored by tier, tool, profile, account, account/tool, and account/profile.
Every JSON-RPC response includes the same accounting metadata:
{
"result": {
"_meta": {
"nodebench": {
"requestId": "uuid",
"profile": "gmail-research",
"authMode": "anonymous",
"accountKey": "anon:gmail-research:...",
"accounting": {
"ledger": "mcpToolCallLedger",
"costModel": "mcp-cost-v1-2026-05",
"costType": "estimated"
}
}
}
}
}The gateway also sends these HTTP headers so apps and agents can log them without parsing the MCP result:
x-nodebench-request-id
x-nodebench-profile
x-nodebench-auth-mode
x-nodebench-account-keyRecommended client headers:
x-nodebench-client: gmail-dashboard
x-nodebench-client-version: 1.0.0
x-nodebench-client-id: stable-install-or-workspace-idx-nodebench-client-id is optional but recommended. It gives anonymous public-profile clients stable usage attribution without requiring a NodeBench login or token. Do not put private email text, resume text, API keys, or other sensitive data in this header. Rotate this value only when you intentionally want a new anonymous accounting bucket.
For operations views, use Convex:
npx convex run --push "domains/mcp/mcpToolLedger:getUsageAndCostSnapshot" "{dateKey:'2026-05-03',limit:20}"For one requester:
npx convex run --push "domains/mcp/mcpToolLedger:getUsageAndCostSnapshot" "{accountKey:'anon:gmail-research:<hash>',limit:20}"Cost values are estimates for product control and abuse detection. Provider invoices remain the source of truth for final billing reconciliation. Anonymous public-profile accounting is intentionally stable per client id so apps can show usage before account linking without sending private user data.
MCP_HTTP_TOKEN=<internal full-access token>
MCP_DEFAULT_PROFILE=full
MCP_PROFILE_TOKENS=<token1>:public-research,<token2>:gmail-research,<token3>:builder
MCP_PUBLIC_PROFILES=public-research,gmail-researchRecommended production setup:
- Keep
MCP_HTTP_TOKENas the internal full-access token. - Keep
public-researchandgmail-researchanonymous for frictionless public-source integrations. - Issue external users profile-scoped tokens through
MCP_PROFILE_TOKENSwhen they need non-public profiles or custom budgets. - Use
MCP_DEFAULT_PROFILE=public-researchonly for a public demo service where full internal access is not needed through the same endpoint.
For stdio clients:
MCP_PROFILE=public-researchor:
MCP_DEFAULT_PROFILE=public-research{
"mcpServers": {
"nodebench-public-research": {
"transport": "http",
"url": "https://nodebench-mcp-unified.onrender.com?profile=public-research"
}
}
}Visible tools:
nodebench.entities.resolve
nodebench.search_public_sources
nodebench.research_company
nodebench.research_person
nodebench.research_role
nodebench.dossiers.get
nodebench.context.pack
nodebench.get_matching_context
nodebench.compile_interview_packet
nodebench.claims.submit_public
nodebench.claims.verify
nodebench.watch_entity
nodebench.link_private_signal_to_public_entity
findTools{
"mcpServers": {
"nodebench-gmail-research": {
"transport": "http",
"url": "https://nodebench-mcp-unified.onrender.com?profile=gmail-research"
}
}
}Visible tools:
nodebench.entities.resolve
nodebench.search_public_sources
nodebench.research_company
nodebench.research_person
nodebench.research_role
nodebench.dossiers.get
nodebench.context.pack
nodebench.get_matching_context
nodebench.compile_interview_packet
findTools$url = "https://nodebench-mcp-unified.onrender.com?profile=public-research"
Invoke-RestMethod "$url" -Method Post -ContentType "application/json" -Body (@{
jsonrpc = "2.0"
id = 1
method = "tools/list"
} | ConvertTo-Json)Expected:
result.profileispublic-researchresult.authModeisanonymouson hosted productionresult.tools.lengthis14- no document, planning, eval, or internal-only tools appear
Blocked-call check:
Invoke-RestMethod "$url" -Method Post -ContentType "application/json" -Body (@{
jsonrpc = "2.0"
id = 2
method = "tools/call"
params = @{
name = "createDocument"
arguments = @{ title = "Should be blocked" }
}
} | ConvertTo-Json -Depth 5)Expected JSON-RPC error message:
Tool not found in profile "public-research": createDocument