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.
- equinix_docs_mcp_server-0.3.1/LICENSE +21 -0
- equinix_docs_mcp_server-0.3.1/PKG-INFO +342 -0
- equinix_docs_mcp_server-0.3.1/README.md +306 -0
- equinix_docs_mcp_server-0.3.1/pyproject.toml +81 -0
- equinix_docs_mcp_server-0.3.1/setup.cfg +4 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/__init__.py +21 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/api_notices.py +384 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/arazzo_manager.py +1032 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/auth.py +217 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/catalog_discovery.py +224 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/config.py +272 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/data/config/apis.yaml +362 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/data/config/workflows-dcim.yaml +350 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/data/config/workflows.yaml +25 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/data/overlays/accesstoken.yaml +17 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/data/overlays/billing.yaml +43 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/data/overlays/fabric.yaml +43 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/data/overlays/network-edge.yaml +31 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/data/overlays/workvisitsv2.yaml +31 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/data/overlays/workvisitv1.yaml +31 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/docs.py +458 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/lunr_search/search_client.py +251 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/main.py +616 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/openapi_annotations.py +143 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/openapi_overlays/__init__.py +10 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/openapi_overlays/overlay_manager.py +171 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/openrpc.py +694 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/rate_limits.py +183 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/response_formatter.py +216 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/spec_manager.py +864 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/swagger2openapi/converter.py +343 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/tool_ranking.py +104 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/tool_search.py +303 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server/workflow_http.py +255 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server.egg-info/PKG-INFO +342 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server.egg-info/SOURCES.txt +56 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server.egg-info/dependency_links.txt +1 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server.egg-info/entry_points.txt +2 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server.egg-info/requires.txt +26 -0
- equinix_docs_mcp_server-0.3.1/src/equinix_docs_mcp_server.egg-info/top_level.txt +1 -0
- equinix_docs_mcp_server-0.3.1/tests/test_api_notices.py +230 -0
- equinix_docs_mcp_server-0.3.1/tests/test_arazzo_fallback.py +173 -0
- equinix_docs_mcp_server-0.3.1/tests/test_arazzo_step_normalization.py +103 -0
- equinix_docs_mcp_server-0.3.1/tests/test_auth.py +286 -0
- equinix_docs_mcp_server-0.3.1/tests/test_catalog_discovery.py +174 -0
- equinix_docs_mcp_server-0.3.1/tests/test_config.py +54 -0
- equinix_docs_mcp_server-0.3.1/tests/test_docs.py +348 -0
- equinix_docs_mcp_server-0.3.1/tests/test_main.py +462 -0
- equinix_docs_mcp_server-0.3.1/tests/test_openapi_annotations.py +222 -0
- equinix_docs_mcp_server-0.3.1/tests/test_openapi_overlays.py +156 -0
- equinix_docs_mcp_server-0.3.1/tests/test_openrpc.py +250 -0
- equinix_docs_mcp_server-0.3.1/tests/test_rate_limits.py +183 -0
- equinix_docs_mcp_server-0.3.1/tests/test_response_formatter_ne.py +37 -0
- equinix_docs_mcp_server-0.3.1/tests/test_spec_manager.py +384 -0
- equinix_docs_mcp_server-0.3.1/tests/test_tool_ranking.py +105 -0
- equinix_docs_mcp_server-0.3.1/tests/test_tool_search.py +183 -0
- equinix_docs_mcp_server-0.3.1/tests/test_workflow_runner.py +695 -0
- 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)
|