diff --git a/docs/content/docs/getting-started/_index.md b/docs/content/docs/getting-started/_index.md index a46b166..3c6e276 100644 --- a/docs/content/docs/getting-started/_index.md +++ b/docs/content/docs/getting-started/_index.md @@ -11,9 +11,9 @@ Install and use OCP libraries for API tool discovery and context management. ## Installation & Quick Start -{{< tabs items="Python,JavaScript,VS Code" >}} +{{< tabs >}} -{{< tab >}} +{{< tab name="Python" >}} **Prerequisites:** Python 3.8+ ```bash @@ -51,7 +51,7 @@ result = agent.call_tool("findPetsByStatus", {"status": "available"})) ``` {{< /tab >}} -{{< tab >}} +{{< tab name="JavaScript" >}} **Prerequisites:** Node.js 16+ ```bash @@ -89,7 +89,7 @@ const result = await agent.callTool('findPetsByStatus', {status: 'available'}); ``` {{< /tab >}} -{{< tab >}} +{{< tab name="VS Code" >}} **Prerequisites:** VS Code ```bash diff --git a/docs/content/docs/tool-discovery/_index.md b/docs/content/docs/tool-discovery/_index.md index e2239ae..74c6e65 100644 --- a/docs/content/docs/tool-discovery/_index.md +++ b/docs/content/docs/tool-discovery/_index.md @@ -31,42 +31,116 @@ agent.call_tool("createPaymentIntent", {"amount": 2000}) - **Automatic Caching**: Specs cached locally for 7 days with configurable expiration - **Built-in Validation**: Parameters validated against OpenAPI schemas automatically -## Tool Naming Rules - -OCP generates predictable camelCase tool names from OpenAPI specifications with automatic normalization: - -**1. Use `operationId` (when present) with camelCase normalization:** -```yaml -# OpenAPI spec -paths: - /repos/{owner}/{repo}/issues: - get: - operationId: "listRepositoryIssues" # → Tool name: "listRepositoryIssues" - /meta: - get: - operationId: "meta/root" # → Tool name: "metaRoot" - /admin/apps: - put: - operationId: "admin_apps_approve" # → Tool name: "adminAppsApprove" - /accounts: - get: - operationId: "FetchAccount" # → Tool name: "fetchAccount" -``` - -**2. Generate from HTTP method + path (when `operationId` missing) with camelCase normalization:** -```yaml -# OpenAPI spec # Generated tool name -GET /items # → "getItems" -POST /items # → "postItems" -GET /items/{id} # → "getItemsId" -DELETE /repos/{owner}/{repo} # → "deleteReposOwnerRepo" -``` - -**Normalization Rules:** -- Special characters (`/`, `_`, `-`, `.`) are removed and surrounding words capitalized -- PascalCase is converted to camelCase (e.g., `FetchAccount` → `fetchAccount`) -- Numbers and version prefixes are preserved (e.g., `v2010/Accounts` → `v2010Accounts`) -- Multiple consecutive separators are collapsed (e.g., `api//users` → `apiUsers`) +## Tool Naming + +OCP generates consistent, predictable tool names from path structure regardless of how individual vendors wrote their specs. + +The basic pattern is **verb + resource chain** in camelCase: + +``` +GET /repos/{owner}/{repo}/issues → listRepoIssues +POST /repos/{owner}/{repo}/issues → createRepoIssue +GET /repos/{owner}/{repo}/issues/{id} → getRepoIssue +DELETE /repos/{owner}/{repo}/issues/{id} → deleteRepoIssue +``` + +The verb comes from the HTTP method (`GET` on a collection → `list`, `GET` on an item → `get`, `POST` → `create`, etc.). Path parameters are dropped. Intermediate container segments — segments that exist only to scope a sub-resource — are skipped. The remaining resource words are singularized (except the final word of a `list` call) and assembled into camelCase. + +### API Schema Phenomena + +Real-world API schemas present a number of structural patterns that a naive path-to-name mapping can't handle correctly. Here's what OCP addresses and why. + +**Path structure noise** + +Path parameters and file extensions carry no resource semantics and are stripped before name generation. API-specific path prefixes (version strings, account identifiers) can be configured per API and are stripped too: + +``` +GET /rest/api/3/issue/{issueId}/remotelink/{linkId} → getIssueRemotelink + (prefix /rest/api/3 configured for Jira) +GET /v1/balance/history → listBalanceHistory + (prefix /v1 configured for Stripe) +``` + +**Container segments** + +Some path segments exist purely to scope a sub-resource — they don't name the thing being acted on. OCP detects and skips these: + +``` +GET /repos/{owner}/{repo}/issues → listRepoIssues + ↑ container ↑ resource +``` + +Without this, you'd get `listRepoRepoIssues` or similar noise. + +**Dot-notation paths** + +Slack-style APIs use dots instead of slashes to express hierarchy. OCP treats the dot as a segment boundary: + +``` +GET /bots.info → getBotInfo +POST /chat.postMessage → createChatMessage +GET /dnd.endDnd → endDnd +``` + +The action word after the dot becomes the verb when it's a recognized action (e.g. `post`, `end`), and the resource word follows from the remainder. + +**Terminal action verbs** + +Some paths end in an action word rather than a resource noun. The terminal segment drives the verb, overriding the HTTP method: + +``` +POST /disputes/{id}/close → closeDispute (not createDispute) +PUT /issues/{id}/lock → lockIssue (not updateIssue) +``` + +**Collection vs. singleton** + +`GET` on a resource-final path usually means a collection (`list`), but some terminal words are semantically singular by nature — they refer to one object, not a set. OCP recognises these and uses `get` instead: + +``` +GET /users → listUsers (collection) +GET /bots.info → getBotInfo (singleton: info) +GET /repos/{id}/actions/cache/usage → getActionCacheUsage (singleton: usage) +``` + +Singleton terminals: `info`, `count`, `default`, `usage`, `public-key`. + +**Compound resource names** + +Resources are often expressed as hyphenated, snake\_case, or camelCase compounds. Inflection and deduplication operate on the tail word only — leaving the prefix intact: + +``` +GET /repos/{id}/direct-children → listRepoDirectChildren + (children, not childrens) +GET /team.billableInfo → getTeamBillableInfo + (info is uncountable → no plural) +``` + +**Adjacent prefix repetition** + +A common REST convention is for a sub-resource to prefix itself with its parent's name (`workflow` → `workflowSchemes`, `source` → `source_transactions`). This produces stutter in the assembled name, so OCP collapses it: + +``` +GET /workflow/{id}/workflowSchemes → listWorkflowSchemes +GET /sources/{source}/source_transactions → listSourceTransactions +``` + +Non-adjacent repetition is left intact — stripping it would lose structural context: + +``` +DELETE /issues/{id}/sub-issues/{sub_id} → deleteIssueSubIssue (unchanged) +``` + +**Inflection irregularities** + +Standard pluralization rules break on irregular forms, Latin/Greek words, uncountable nouns, and opaque compound strings. OCP uses a purpose-built inflector that handles these correctly: + +``` +children → children (irregular, not childrens) +analysis → analyses (Greek -sis → -ses) +datum → datums (geographic datum, not data) +info → info (uncountable) +``` ## Handling Tool Conflicts diff --git a/docs/go.mod b/docs/go.mod index 01e43c0..3191a27 100644 --- a/docs/go.mod +++ b/docs/go.mod @@ -2,4 +2,4 @@ module github.com/opencontextprotocol/specification go 1.24.1 -require github.com/imfing/hextra v0.11.1 // indirect +require github.com/imfing/hextra v0.12.1 // indirect diff --git a/docs/go.sum b/docs/go.sum index e1907e0..846341f 100644 --- a/docs/go.sum +++ b/docs/go.sum @@ -2,3 +2,5 @@ github.com/imfing/hextra v0.9.5 h1:lG6wnklT9PNLepq69Gj3GZyHRUkBWwv6bkPVL9yAcIQ= github.com/imfing/hextra v0.9.5/go.mod h1:cEfel3lU/bSx7lTE/+uuR4GJaphyOyiwNR3PTqFTXpI= github.com/imfing/hextra v0.11.1 h1:8pTc4ReYbzGTHAnyiebmlT3ijFfIXiGu1r7tM/UGjFI= github.com/imfing/hextra v0.11.1/go.mod h1:cEfel3lU/bSx7lTE/+uuR4GJaphyOyiwNR3PTqFTXpI= +github.com/imfing/hextra v0.12.1 h1:3t1n0bmJbDzSTVfht93UDcfF1BXMRjeFojA071ri2l8= +github.com/imfing/hextra v0.12.1/go.mod h1:vi+yhpq8YPp/aghvJlNKVnJKcPJ/VyAEcfC1BSV9ARo= diff --git a/docs/layouts/_partials/sidebar.html b/docs/layouts/_partials/sidebar.html index 0173f4a..2b6fb4a 100644 --- a/docs/layouts/_partials/sidebar.html +++ b/docs/layouts/_partials/sidebar.html @@ -21,10 +21,12 @@ {{- end -}}