equinix-docs-mcp-server 0.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. equinix_docs_mcp_server-0.3.1/LICENSE +21 -0
  2. equinix_docs_mcp_server-0.3.1/PKG-INFO +342 -0
  3. equinix_docs_mcp_server-0.3.1/README.md +306 -0
  4. equinix_docs_mcp_server-0.3.1/pyproject.toml +81 -0
  5. equinix_docs_mcp_server-0.3.1/setup.cfg +4 -0
  6. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/__init__.py +21 -0
  7. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/api_notices.py +384 -0
  8. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/arazzo_manager.py +1032 -0
  9. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/auth.py +217 -0
  10. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/catalog_discovery.py +224 -0
  11. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/config.py +272 -0
  12. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/data/config/apis.yaml +362 -0
  13. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/data/config/workflows-dcim.yaml +350 -0
  14. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/data/config/workflows.yaml +25 -0
  15. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/data/overlays/accesstoken.yaml +17 -0
  16. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/data/overlays/billing.yaml +43 -0
  17. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/data/overlays/fabric.yaml +43 -0
  18. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/data/overlays/network-edge.yaml +31 -0
  19. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/data/overlays/workvisitsv2.yaml +31 -0
  20. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/data/overlays/workvisitv1.yaml +31 -0
  21. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/docs.py +458 -0
  22. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/lunr_search/search_client.py +251 -0
  23. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/main.py +616 -0
  24. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/openapi_annotations.py +143 -0
  25. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/openapi_overlays/__init__.py +10 -0
  26. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/openapi_overlays/overlay_manager.py +171 -0
  27. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/openrpc.py +694 -0
  28. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/rate_limits.py +183 -0
  29. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/response_formatter.py +216 -0
  30. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/spec_manager.py +864 -0
  31. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/swagger2openapi/converter.py +343 -0
  32. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/tool_ranking.py +104 -0
  33. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/tool_search.py +303 -0
  34. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/workflow_http.py +255 -0
  35. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server.egg-info/PKG-INFO +342 -0
  36. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server.egg-info/SOURCES.txt +56 -0
  37. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server.egg-info/dependency_links.txt +1 -0
  38. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server.egg-info/entry_points.txt +2 -0
  39. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server.egg-info/requires.txt +26 -0
  40. equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server.egg-info/top_level.txt +1 -0
  41. equinix_docs_mcp_server-0.3.1/tests/test_api_notices.py +230 -0
  42. equinix_docs_mcp_server-0.3.1/tests/test_arazzo_fallback.py +173 -0
  43. equinix_docs_mcp_server-0.3.1/tests/test_arazzo_step_normalization.py +103 -0
  44. equinix_docs_mcp_server-0.3.1/tests/test_auth.py +286 -0
  45. equinix_docs_mcp_server-0.3.1/tests/test_catalog_discovery.py +174 -0
  46. equinix_docs_mcp_server-0.3.1/tests/test_config.py +54 -0
  47. equinix_docs_mcp_server-0.3.1/tests/test_docs.py +348 -0
  48. equinix_docs_mcp_server-0.3.1/tests/test_main.py +462 -0
  49. equinix_docs_mcp_server-0.3.1/tests/test_openapi_annotations.py +222 -0
  50. equinix_docs_mcp_server-0.3.1/tests/test_openapi_overlays.py +156 -0
  51. equinix_docs_mcp_server-0.3.1/tests/test_openrpc.py +250 -0
  52. equinix_docs_mcp_server-0.3.1/tests/test_rate_limits.py +183 -0
  53. equinix_docs_mcp_server-0.3.1/tests/test_response_formatter_ne.py +37 -0
  54. equinix_docs_mcp_server-0.3.1/tests/test_spec_manager.py +384 -0
  55. equinix_docs_mcp_server-0.3.1/tests/test_tool_ranking.py +105 -0
  56. equinix_docs_mcp_server-0.3.1/tests/test_tool_search.py +183 -0
  57. equinix_docs_mcp_server-0.3.1/tests/test_workflow_runner.py +695 -0
  58. equinix_docs_mcp_server-0.3.1/version +1 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Marques Johansson
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,342 @@
1
+ Metadata-Version: 2.4
2
+ Name: equinix-docs-mcp-server
3
+ Version: 0.3.1
4
+ Summary: Equinix Docs and API specifications MCP Server (experimental)
5
+ Author: Equinix Labs
6
+ License: MIT
7
+ Requires-Python: >=3.13
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: fastmcp==4.1.6
11
+ Requires-Dist: mcp-types
12
+ Requires-Dist: httpx2>=2.5.0
13
+ Requires-Dist: pydantic>=2.0.0
14
+ Requires-Dist: pyyaml>=6.0.0
15
+ Requires-Dist: click>=8.0.0
16
+ Requires-Dist: aiofiles>=23.0.0
17
+ Requires-Dist: jsonschema>=4.0.0
18
+ Requires-Dist: openapi-spec-validator>=0.7.0
19
+ Requires-Dist: prance>=23.6.21.0
20
+ Requires-Dist: jq>=1.6.0
21
+ Requires-Dist: jmespath>=1.0.1
22
+ Requires-Dist: jinja2>=3.1.0
23
+ Requires-Dist: arazzo-runner>=0.1.4
24
+ Requires-Dist: platformdirs>=4.0.0
25
+ Provides-Extra: dev
26
+ Requires-Dist: exrex>=0.11.0; extra == "dev"
27
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
28
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
29
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
30
+ Requires-Dist: ruff==0.17.4; extra == "dev"
31
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
32
+ Requires-Dist: pre-commit>=3.0.0; extra == "dev"
33
+ Requires-Dist: types-PyYAML>=6.0.0; extra == "dev"
34
+ Requires-Dist: types-aiofiles>=23.0.0; extra == "dev"
35
+ Dynamic: license-file
36
+
37
+ # Equinix Docs and API Specifications MCP Server
38
+
39
+ This project is an experimental Model Context Protocol (MCP) server, for local use and learning, that provides access to Equinix APIs and documentation. This project is not expected to offer high quality (production-ready) results. This is offered for developers learning about MCP, Equinix APIs and documentation, and their potential integration.
40
+
41
+ > [!NOTE]
42
+ > By default the API tool catalog is collapsed behind `search_tools`, `get_tool_schema` and `call_tool`, so large API catalogs no longer overwhelm the model's context window. Use `--tool-catalog full` to list every generated tool directly.
43
+
44
+ ## Features
45
+
46
+ - **API Access**: Fetches and caches Equinix API specifications then exposes operationIds as MCP tools.
47
+ - **Per-family providers**: Each API family (Fabric, Network Edge, Billing, Smart View, …) is served by its own OpenAPI provider; tools are namespaced `<family>_<operationId>` (e.g. `fabric_searchConnections`)
48
+ - **Searchable catalog**: API tools are hidden from `tools/list` and discovered on demand via `search_tools`, following the MCP 2026-07-28 progressive-discovery guidance; `--tool-catalog code-mode` enables FastMCP's experimental sandboxed code execution instead
49
+ - **Tool annotations**: API tools carry MCP behavior hints derived from their HTTP method — `GET` is `readOnlyHint`, `PUT`/`DELETE` are `destructiveHint` + `idempotentHint`, `POST`/`PATCH` are neither read-only nor idempotent — and all are `openWorldHint`; an operation's `x-mcp-annotations` extension (e.g. via an overlay) overrides these
50
+ - **Cache hints**: `tools/list` and related results carry `ttlMs`/`cacheScope` hints per the MCP 2026-07-28 caching utility
51
+ - **API Authentication**: OAuth2 Client Credentials
52
+ - **Configurable Overlays**: Use overlay specifications to normalize API specs before tools are generated from them
53
+ - **Arazzo Workflows (Experimental)**: Define and execute higher-level workflows chaining multiple API operations
54
+ - **Documentation Integration**: Search Equinix documentation via sitemap and Lunr search, fetch full markdown content
55
+ - OpenAI MCP compatible `search` and `fetch` tools for ChatGPT Connectors and deep research
56
+
57
+ ## Supported APIs
58
+
59
+ Any Equinix API specification can be added to the configuration file but operations may need to be filtered and overlays may be needed for this tool to use the spec in the MCP server.
60
+ The bundled `apis.yaml` (at `src/equinix_docs_mcp_server/data/config/apis.yaml`) defines API specifications that have been used during development to test behavior; pass `--config` to use your own.
61
+
62
+ To find catalog APIs not yet configured, run:
63
+
64
+ ```bash
65
+ equinix-docs-mcp-server --discover-apis
66
+ ```
67
+
68
+ This scans [docs.equinix.com/api-catalog](https://docs.equinix.com/api-catalog) for `openapi.yaml` specs and prints ready-to-paste `apis.yaml` entries for anything new (AsyncAPI-only entries such as `emgv1` are reported but skipped). Add `--write` to append them to the configuration file directly — the *Discover New APIs* GitHub workflow does exactly that on a weekly schedule (or on demand via workflow dispatch) and opens a PR with the additions. Operations missing an `operationId` get one synthesized automatically during spec processing.
69
+
70
+ ## Quick Start
71
+
72
+ ### Installation
73
+
74
+ No clone or checkout is required. With [uv](https://docs.astral.sh/uv/getting-started/installation/) installed, run the server directly from GitHub (uv fetches a suitable Python automatically):
75
+
76
+ ```bash
77
+ uvx --system-certs --from git+https://github.com/equinix-labs/equinix-docs-mcp-server equinix-docs-mcp-server
78
+ ```
79
+
80
+ The bundled API/docs configuration ships inside the package, and caches are written to your user cache directory (override with the `EQUINIX_MCP_CACHE_DIR` environment variable). Pass `--config path/to/apis.yaml` to use a custom configuration.
81
+
82
+ Equivalent alternatives: `pipx run --spec git+https://github.com/equinix-labs/equinix-docs-mcp-server equinix-docs-mcp-server`, or `pip install git+https://github.com/equinix-labs/equinix-docs-mcp-server` (Python 3.13+) followed by `equinix-docs-mcp-server`.
83
+
84
+ ### Developer installation
85
+
86
+ To work on this project, clone it and install editable:
87
+
88
+ ```bash
89
+ python3 -m venv .venv
90
+ source .venv/bin/activate # Windows: .venv\Scripts\activate
91
+ pip install -e '.[dev]'
92
+ ```
93
+
94
+ The packaged configuration lives at `src/equinix_docs_mcp_server/data/config/apis.yaml` (with overlays alongside in `data/overlays/`), so with an editable install your edits there take effect directly.
95
+
96
+ ## Adding the MCP Server to Claude Code
97
+
98
+ ```bash
99
+ claude mcp add --env EQUINIX_API_CLIENTID=your_client_id \
100
+ --env EQUINIX_API_CLIENTSECRET=your_client_secret \
101
+ --transport stdio equinix \
102
+ -- uvx --system-certs --from git+https://github.com/equinix-labs/equinix-docs-mcp-server equinix-docs-mcp-server
103
+ ```
104
+
105
+ > [!TIP]
106
+ > The `--env` flags are optional if you already have credentials configured via the [Equinix CLI](https://github.com/equinix/cli) config file (`~/.config/equinix/equinix.yaml`). The server reads `equinix_client_id` and `equinix_client_secret` from that file automatically.
107
+
108
+ Add `--scope project` to share the configuration with the team via a `.mcp.json` file (omit the `--env` flags in that case and export the credentials in your shell instead, so secrets stay out of the committed file). Note the flag ordering: another option (here `--transport stdio`) must sit between the last `--env` and the server name, or the CLI parses the name as another KEY=value pair.
109
+
110
+ For more details, see the [Claude Code MCP documentation](https://code.claude.com/docs/en/mcp).
111
+
112
+ ## Adding the MCP Server to VS Code
113
+
114
+ Add the server with a single command (the JSON is one server object, with the name inline):
115
+
116
+ ```bash
117
+ code --add-mcp '{"name":"equinix","type":"stdio","command":"uvx","args":["--system-certs","--from","git+https://github.com/equinix-labs/equinix-docs-mcp-server","equinix-docs-mcp-server"]}'
118
+ ```
119
+
120
+ Or create a `.vscode/mcp.json` in your workspace to prompt for credentials on first use:
121
+
122
+ ```json
123
+ {
124
+ "servers": {
125
+ "equinix": {
126
+ "type": "stdio",
127
+ "command": "uvx",
128
+ "args": [
129
+ "--system-certs",
130
+ "--from",
131
+ "git+https://github.com/equinix-labs/equinix-docs-mcp-server",
132
+ "equinix-docs-mcp-server"
133
+ ],
134
+ "env": {
135
+ "EQUINIX_API_CLIENTID": "${input:equinix-client-id}",
136
+ "EQUINIX_API_CLIENTSECRET": "${input:equinix-client-secret}"
137
+ }
138
+ }
139
+ },
140
+ "inputs": [
141
+ {
142
+ "type": "promptString",
143
+ "id": "equinix-client-id",
144
+ "description": "Equinix Client ID",
145
+ "password": true
146
+ },
147
+ {
148
+ "type": "promptString",
149
+ "id": "equinix-client-secret",
150
+ "description": "Equinix Client Secret",
151
+ "password": true
152
+ }
153
+ ]
154
+ }
155
+ ```
156
+
157
+ For more details, see the [VS Code MCP Server documentation](https://code.visualstudio.com/docs/agent-customization/mcp-servers).
158
+
159
+ ## Usage
160
+
161
+ ### Configuration
162
+
163
+ Set your Equinix API credentials as environment variables, or configure them once via the [Equinix CLI](https://github.com/equinix/cli) (`~/.config/equinix/equinix.yaml`) — the server reads the same file automatically:
164
+
165
+ ```bash
166
+ # OAuth2 Client Credentials
167
+ export EQUINIX_API_CLIENTID="your_client_id"
168
+ export EQUINIX_API_CLIENTSECRET="your_client_secret"
169
+ ```
170
+
171
+ These are the names the [Equinix Terraform provider](https://github.com/equinix/terraform-provider-equinix) and the Equinix SDKs use. The earlier `EQUINIX_CLIENT_ID` and `EQUINIX_CLIENT_SECRET` still work but are deprecated, and the server logs a warning when it falls back to them.
172
+
173
+ If you have already run `equinix init`, credentials are stored in `~/.config/equinix/equinix.yaml` (keys: `equinix_client_id`, `equinix_client_secret`). No environment variables are needed in that case. Environment variables take priority over that file.
174
+
175
+ #### API Endpoint
176
+
177
+ Requests and token requests go to `https://api.equinix.com`. To use another environment, such as a test environment or a mock server, set `EQUINIX_API_ENDPOINT`, as with the Terraform provider:
178
+
179
+ ```bash
180
+ export EQUINIX_API_ENDPOINT="https://mockapi.example.com"
181
+ ```
182
+
183
+ This replaces the `api.equinix.com` host for every API family and for the token URL (`$EQUINIX_API_ENDPOINT/oauth2/v1/token`). Families served from their own hosts, such as `access.eqix.equinix.com`, keep them. The generated tool catalog and `--export-openrpc` output still document the production URLs.
184
+
185
+ #### API Spec Fetching
186
+
187
+ The server uses cached API specifications by default for faster startup. Use `--update-specs` to force fetching fresh specs from remote sources.
188
+
189
+ ```bash
190
+ equinix-docs-mcp-server --update-specs # --config path/to/custom/config.yaml
191
+ ```
192
+
193
+ #### Rate Limits, Deprecations and Sunsets
194
+
195
+ API requests that get HTTP 429 (or 408) are sent again after the wait the `Retry-After` header asks for, or a short backoff without one. A 502, 503 or 504 is retried only for `GET`, `HEAD`, `OPTIONS`, `PUT` and `DELETE`, since a `POST` or `PATCH` may already have been applied. All waits for one request share a small budget, so a tool call doesn't hold up the agent for long. When the budget runs out, the tool error says whether the request was applied and when to retry.
196
+
197
+ | Variable | Default | Meaning |
198
+ |---|---|---|
199
+ | `EQUINIX_MCP_RETRY_MAX` | `5` | Retries per request; `0` turns retrying off |
200
+ | `EQUINIX_MCP_RETRY_WAIT` | `15` | Seconds all waits for one request may add up to |
201
+
202
+ When an API response carries `Deprecation` or `Sunset` headers, the tool result gets a notice with the dates and any successor `Link`. The notice is given in full once per API family, and in one line on later calls. An error from an endpoint past its sunset says it appears to be retired. Operations marked `deprecated` in their OpenAPI spec say so in their tool description and have a `deprecated` tag.
203
+
204
+ #### Workflow Runs
205
+
206
+ Workflow tools (see [Defining Arazzo Workflows](#defining-arazzo-workflows-experimental)) run in a worker thread, so a long workflow doesn't hold up other tool calls. Their requests behave like the API tools': each gets the server's OAuth token, a 401 fetches a new token and resends once, 429/408 and gateway errors are retried under the same rules and `EQUINIX_MCP_RETRY_*` budget, deprecation notices are added to the result, and each request times out after 30 seconds.
207
+
208
+ A step that fails, by not meeting its `successCriteria` or by its request failing, makes the tool call an error that names the step. A `retry` failure action waits `retryAfter` seconds and reruns the step up to `retryLimit` times. A whole run has a time limit. Once it passes, no further requests are sent and the error names the step the run stopped at. Requests from earlier steps may already have been applied.
209
+
210
+ Only read-only workflows are registered by default: every step, including those in `forEach` loops, must call a `GET`, `HEAD` or `OPTIONS` operation, or a `POST` that the API tools also treat as a read (an operationId starting with a verb such as `search` or `get`, or a path ending in `/search` or `/validate`). A workflow with any other step, or with a step whose operation can't be found in its `sourceDescriptions`, is skipped with a warning in the log. Read-only workflow tools are annotated `readOnlyHint: true`.
211
+
212
+ | Variable | Default | Meaning |
213
+ |---|---|---|
214
+ | `EQUINIX_MCP_WORKFLOW_TIMEOUT` | `60` | Seconds one workflow run may take; `0` turns the limit off |
215
+ | `EQUINIX_MCP_ALLOW_WRITE_WORKFLOWS` | unset | Set to `1` to also register workflows that change resources |
216
+
217
+ ## Server Configuration
218
+
219
+ The server is configured via the packaged `apis.yaml` (or a file passed with `--config`). This file defines:
220
+
221
+ - API endpoints and versions
222
+ - Authentication methods
223
+ - Overlay file locations
224
+ - Documentation settings
225
+
226
+ ### Example API Configuration
227
+
228
+ ```yaml
229
+ apis:
230
+ fabric:
231
+ auth_type: "client_credentials"
232
+ service_name: "fabric"
233
+ # include: [] # regexes of operationIds to expose (all when omitted)
234
+ # exclude: [] # regexes of operationIds to hide
235
+ # enabled: true
236
+ specs:
237
+ - url: "https://docs.equinix.com/api-catalog/fabricv4/openapi.yaml"
238
+ overlay: "overlays/fabric.yaml"
239
+ ```
240
+
241
+ ## Overlay Files
242
+
243
+ Overlay files in the `overlays/` directory normalize API specifications before processing:
244
+
245
+ - Standardize authentication schemes
246
+ - Normalize base paths and servers
247
+ - Add consistent tagging
248
+ - Handle API-specific quirks
249
+
250
+ ## Available MCP Tools
251
+
252
+ The server exposes MCP tools for:
253
+
254
+ 1. **API Operations**: Dynamic tools generated per API family from its OpenAPI specification, named `<family>_<operationId>` (e.g. `fabric_searchConnections`, `network-edge_getMetros`). With the default `--tool-catalog search`, these are hidden from `tools/list` and reached through:
255
+ - `search_tools` - Find API tools by natural-language query. Each match is a short entry: name, title, access (read-only, write or destructive), a one-paragraph summary, required parameters with types, and optional parameter names. Results run about 4-6K characters for 15 matches.
256
+ - `get_tool_schema` - Return one tool's full definition, with every parameter's description and examples. Pass `output_schema: true` to include the response schema, for example to write a `call_api_filtered` query.
257
+ - `call_tool` - Execute a discovered tool by name
258
+ - `call_api_filtered` - Run an API tool and return only what a [JMESPath](https://jmespath.org/specification.html) query selects from its response, rendered as YAML. Use it when a full response would be too large, for example `data[].{code: code, name: name}` on `fabric_getMetros`.
259
+ 2. **Documentation**:
260
+ - `search` - Full-text search documentation using indexed content (OpenAI MCP compatible)
261
+ - `fetch` - Fetch full markdown content of a documentation page by URL (OpenAI MCP compatible)
262
+ - `list_docs` - List and filter documentation
263
+ - `find_docs` - Find documentation by filename/title matching
264
+ 3. **Workflows (Arazzo)**:
265
+ - Tools prefixed with `workflow__` run multi-step workflows defined in [Arazzo](https://spec.openapis.org/arazzo/latest.html) files, for example `workflow__list_ne_metros`.
266
+ - `arazzo_list_workflows` and `arazzo_describe_workflow` list the loaded workflows and describe one.
267
+
268
+ ### Tool Catalog Reference (OpenRPC)
269
+
270
+ The complete tool catalog, including every generated API tool, is published at <https://equinix-labs.github.io/equinix-docs-mcp-server/> as a browsable single-page reference, with the [OpenRPC](https://open-rpc.org/) document it is rendered from at [`openrpc.json`](https://equinix-labs.github.io/equinix-docs-mcp-server/openrpc.json). Each OpenRPC method is one MCP tool: its by-name params are the tool arguments, sent over MCP as `tools/call` with `{"name": "<method>", "arguments": {...}}`.
271
+
272
+ The *OpenRPC Docs* workflow generates and lints the catalog on every pull request and uploads it as the `openrpc-docs` artifact. Pushes to `main`, a weekly run (to pick up upstream API spec changes) and manual runs also deploy it to GitHub Pages. The generated files are not committed.
273
+
274
+ To build the site locally (specs are always refreshed, so the output does not depend on your local cache):
275
+
276
+ ```bash
277
+ equinix-docs-mcp-server --export-openrpc site # writes site/openrpc.json and site/index.html
278
+ npx @redocly/cli lint site/openrpc.json # optional validation
279
+ ```
280
+
281
+ Then open `site/index.html` in a browser. `site/` is git-ignored.
282
+
283
+ ### Defining Arazzo Workflows (Experimental)
284
+
285
+ Workflows are [Arazzo 1.0](https://spec.openapis.org/arazzo/latest.html) documents, run with [arazzo-runner](https://pypi.org/project/arazzo-runner/). List them in the `arazzo` section of `apis.yaml`. Paths resolve relative to the config file's parent directory, and the bundled configuration loads `config/workflows.yaml`:
286
+
287
+ ```yaml
288
+ arazzo:
289
+ specs:
290
+ - config/workflows.yaml
291
+ ```
292
+
293
+ Each workflow becomes a `workflow__<workflowId>` tool. Its parameters come from the workflow's `inputs` schema, and an `inputs_json` parameter accepts the inputs as one JSON or YAML object. The bundled workflow:
294
+
295
+ ```yaml
296
+ arazzo: 1.0.1
297
+ info:
298
+ title: Equinix Workflows to get metros
299
+ version: 2.0.0
300
+ sourceDescriptions:
301
+ - name: ne
302
+ url: https://docs.equinix.com/api-catalog/network-edgev1/openapi.yaml
303
+ type: openapi
304
+ workflows:
305
+ - workflowId: list_ne_metros
306
+ summary: Retrieve Network Edge metros
307
+ steps:
308
+ - stepId: get_metros
309
+ operationId: getMetros
310
+ successCriteria:
311
+ - condition: $statusCode == 200
312
+ outputs:
313
+ metros: $response.body#/data
314
+ outputs:
315
+ metros: $steps.get_metros.outputs.metros
316
+ ```
317
+
318
+ Steps call operations from the `sourceDescriptions` specs, not the server's MCP tools. Values pass between steps with runtime expressions such as `$inputs.<name>` and `$steps.<stepId>.outputs.<name>`. When a workflow declares a `bearerToken` input and the caller doesn't supply one, the server fills it in with its own OAuth token.
319
+
320
+ The server also supports `forEach` on a step, which isn't part of Arazzo 1.0. It runs the step's nested `steps` once per item of a collection, with `$item.<field>` substituted. Only one level of nesting is supported. `data/config/workflows-dcim.yaml` is a larger example that uses it. It isn't loaded by default.
321
+
322
+ ## Development
323
+
324
+ ### Running Tests
325
+
326
+ ```bash
327
+ pip install -e '.[dev]'
328
+ pytest
329
+ ```
330
+
331
+ See [`docs/SPEC_VETTING.md`](docs/SPEC_VETTING.md) for exercising every generated tool against mock responses, [`docs/SEARCH_FETCH_USAGE.md`](docs/SEARCH_FETCH_USAGE.md) for the documentation `search` and `fetch` tools, and [`docs/INTEGRATION_EXAMPLE.md`](docs/INTEGRATION_EXAMPLE.md) for an example of using them together.
332
+
333
+ ## License
334
+
335
+ MIT License. See [LICENSE](LICENSE) for details.
336
+
337
+ ## Links
338
+
339
+ - [Equinix Documentation](https://docs.equinix.com/)
340
+ - [Equinix API Documentation](https://docs.equinix.com/equinix-api)
341
+ - [FastMCP Framework](https://gofastmcp.com/)
342
+ - [Model Context Protocol](https://github.com/modelcontextprotocol)