{
  "access": "public",
  "type": "reference",
  "format": "markdown",
  "title": "Tool Naming",
  "chunked": true,
  "url": "https://library.datagrout.ai/tool-naming",
  "summary": "**How DataGrout resolves tool names across different clients and calling conventions**",
  "content_markdown": "# Tool Naming and Compatibility\n\n**How DataGrout resolves tool names across different clients and calling conventions**\n\nDataGrout tools use a structured canonical format, but many AI clients (Claude, ChatGPT, n8n, LangChain, Cursor, etc.) restrict function names to `^[a-zA-Z0-9_-]{1,64}$` — no `@` or `/` allowed. DataGrout handles this automatically, so you can call tools using whichever format your client supports.\n\n---\n\n## Canonical format\n\nEvery tool has a canonical name:\n\n```\nintegration@version/toolsuite.tool@version\n```\n\nExamples:\n- `data-grout@1/discovery.discover@1`\n- `salesforce@1/get_leads@1`\n- `quickbooks@1/find_recent_invoices@1`\n- `data-grout@1/warden.ensemble@1`\n\nRules:\n- Lowercase, kebab-case for multi-word integrations\n- Dots separate tool suites from tool names (`prism.refract`, `warden.canary`)\n- Versions are integers after `@` (currently `@1` for all tools)\n\nIf your client supports arbitrary function names, you can use canonical names directly.\n\n---\n\n## OpenAI-compatible format\n\nFor clients that restrict function names to letters, numbers, underscores, and hyphens, DataGrout generates a flat name by stripping versions, replacing `/` and `.` with underscores, and compressing common integration prefixes to shorter aliases when possible:\n\n| Canonical | OpenAI-compatible |\n|-----------|-------------------|\n| `salesforce@1/get_leads@1` | `sf_get_leads` |\n| `data-grout@1/prism.refract@1` | `dg_prism_refract` |\n| `data-grout@1/discovery.discover@1` | `dg_discovery_discover` |\n| `data-grout@1/warden.ensemble@1` | `dg_warden_ensemble` |\n| `quickbooks@1/find_recent_invoices@1` | `qb_find_recent_invoices` |\n\nWhen you call `tools/list`, each tool descriptor includes both names:\n\n```json\n{\n  \"name\": \"data-grout@1/warden.ensemble@1\",\n  \"openai_name\": \"dg_warden_ensemble\",\n  \"description\": \"Runs the full Warden ensemble...\",\n  \"inputSchema\": { ... }\n}\n```\n\n### Automatic client detection\n\nDataGrout detects clients that need OpenAI-compatible names and transforms `tools/list` responses automatically. Known clients include:\n\n- Claude Desktop, Claude AI\n- ChatGPT, OpenAI API clients\n- n8n workflow automation\n- LangChain, LlamaIndex\n- Cursor, Continue, Cline, Windsurf\n- mcp-remote transport library\n\nWhen detected, `tools/list` returns `openai_name` as the primary `name` field and preserves the original in `canonical_name`.\n\n### Forcing OpenAI mode\n\nIf auto-detection doesn't work for your client, you can force it:\n\n- Set the header `x-openai-mode: true` on your connection\n\n---\n\n## Calling tools with flat names\n\nWhen you make a `tools/call` with a flat name (no `/`), DataGrout resolves it back to canonical form through a multi-step fallback chain:\n\n1. **Descriptor match** — scans the server's tool list for a matching `openai_name` or `cursor_name`\n2. **Prefix-based reversal** — splits the flat name on known integration prefixes and aliases (`sf`, `qb`, `dg`, plus the full integration names) and reconstructs the canonical form\n3. **Passthrough** — if no match is found, the name is used as-is\n\nThis means you can call tools using any of these equivalent forms:\n\n```json\n// Canonical\n{ \"method\": \"tools/call\", \"params\": { \"name\": \"data-grout@1/warden.canary@1\", \"arguments\": { ... } } }\n\n// OpenAI-compatible\n{ \"method\": \"tools/call\", \"params\": { \"name\": \"dg_warden_canary\", \"arguments\": { ... } } }\n```\n\nBoth resolve to the same tool.\n\n---\n\n## Version handling\n\nVersions are flexible on input:\n\n| Input | Resolved |\n|-------|----------|\n| `salesforce/get_leads` | `salesforce@1/get_leads@1` |\n| `salesforce@1/get_leads@1` | `salesforce@1/get_leads@1` |\n| `salesforce@v1/get_leads@v1` | `salesforce@1/get_leads@1` |\n| `salesforce@latest/get_leads@latest` | `salesforce@1/get_leads@1` |\n\nIf you omit versions, `@1` is assumed. The `@v1` prefix form and `@latest` tag are also accepted and normalized. Canonical names are case-insensitive — `Salesforce@1/GET_LEADS@1` resolves identically.\n\n---\n\n## Transport encoding\n\nSome transports cannot carry `@` or `/` in tool names. DataGrout accepts two encoding schemes:\n\n| Encoding | Example | Resolves to |\n|----------|---------|-------------|\n| Tilde as slash | `salesforce@1~get_leads@1` | `salesforce@1/get_leads@1` |\n| Percent-encoding | `salesforce%401%2Fget_leads%401` | `salesforce@1/get_leads@1` |\n\nThese are decoded before normalization, so they work seamlessly with all resolution paths.\n\n---\n\n## Collision handling\n\nWhen multiple tools produce the same OpenAI-compatible name (e.g., two integrations with tools that differ only by version), DataGrout appends a numeric suffix to disambiguate:\n\n```\nsf_create_lead    → salesforce@1/create_lead@1\nsf_create_lead_2  → salesforce@2/create_lead@1\n```\n\nThe dedup suffix is stripped during resolution, so calling `salesforce_create_lead_2` correctly resolves to the second variant.\n\n---\n\n## Summary\n\n| Format | Example | When to use |\n|--------|---------|-------------|\n| Canonical | `data-grout@1/prism.refract@1` | Native MCP clients, Conduit SDK |\n| OpenAI-compatible | `data-grout_prism_refract` | Claude, ChatGPT, n8n, LangChain, etc. |\n| No version | `salesforce/get_leads` | Quick calls where version isn't important |\n| Transport-encoded | `salesforce%401~get_leads%401` | Restrictive transports |\n\nAll formats resolve to the same canonical tool and produce identical results. Use whichever your client supports.\n\n---\n\n## Related\n\n- [Tools Reference](tools-reference) — Full list of DataGrout core tools\n- [Authentication](authentication) — How to connect your client\n- [Conduit SDK](conduit-sdk) — Drop-in SDK for Python, TypeScript, and Rust\n"
}