mcp-openapi-proxy 0.3.2__tar.gz → 0.3.4__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.
- {mcp_openapi_proxy-0.3.2 → mcp_openapi_proxy-0.3.4}/PKG-INFO +61 -6
- {mcp_openapi_proxy-0.3.2 → mcp_openapi_proxy-0.3.4}/README.md +59 -4
- {mcp_openapi_proxy-0.3.2 → mcp_openapi_proxy-0.3.4}/mcp_openapi_proxy/server_lowlevel.py +13 -8
- {mcp_openapi_proxy-0.3.2 → mcp_openapi_proxy-0.3.4}/mcp_openapi_proxy.egg-info/PKG-INFO +61 -6
- {mcp_openapi_proxy-0.3.2 → mcp_openapi_proxy-0.3.4}/mcp_openapi_proxy.egg-info/requires.txt +1 -1
- {mcp_openapi_proxy-0.3.2 → mcp_openapi_proxy-0.3.4}/pyproject.toml +5 -2
- {mcp_openapi_proxy-0.3.2 → mcp_openapi_proxy-0.3.4}/LICENSE +0 -0
- {mcp_openapi_proxy-0.3.2 → mcp_openapi_proxy-0.3.4}/mcp_openapi_proxy/__init__.py +0 -0
- {mcp_openapi_proxy-0.3.2 → mcp_openapi_proxy-0.3.4}/mcp_openapi_proxy/handlers.py +0 -0
- {mcp_openapi_proxy-0.3.2 → mcp_openapi_proxy-0.3.4}/mcp_openapi_proxy/logging_setup.py +0 -0
- {mcp_openapi_proxy-0.3.2 → mcp_openapi_proxy-0.3.4}/mcp_openapi_proxy/openapi.py +0 -0
- {mcp_openapi_proxy-0.3.2 → mcp_openapi_proxy-0.3.4}/mcp_openapi_proxy/server_fastmcp.py +0 -0
- {mcp_openapi_proxy-0.3.2 → mcp_openapi_proxy-0.3.4}/mcp_openapi_proxy/types.py +0 -0
- {mcp_openapi_proxy-0.3.2 → mcp_openapi_proxy-0.3.4}/mcp_openapi_proxy/utils.py +0 -0
- {mcp_openapi_proxy-0.3.2 → mcp_openapi_proxy-0.3.4}/mcp_openapi_proxy.egg-info/SOURCES.txt +0 -0
- {mcp_openapi_proxy-0.3.2 → mcp_openapi_proxy-0.3.4}/mcp_openapi_proxy.egg-info/dependency_links.txt +0 -0
- {mcp_openapi_proxy-0.3.2 → mcp_openapi_proxy-0.3.4}/mcp_openapi_proxy.egg-info/entry_points.txt +0 -0
- {mcp_openapi_proxy-0.3.2 → mcp_openapi_proxy-0.3.4}/mcp_openapi_proxy.egg-info/top_level.txt +0 -0
- {mcp_openapi_proxy-0.3.2 → mcp_openapi_proxy-0.3.4}/setup.cfg +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mcp-openapi-proxy
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.4
|
|
4
4
|
Summary: MCP server for exposing OpenAPI specifications as MCP tools.
|
|
5
5
|
Author-email: Matthew Hand <11550632+matthewhand@users.noreply.github.com>
|
|
6
6
|
Requires-Python: >=3.10
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
8
|
License-File: LICENSE
|
|
9
|
-
Requires-Dist: mcp[cli]
|
|
9
|
+
Requires-Dist: mcp[cli]<2,>=1.2.0
|
|
10
10
|
Requires-Dist: python-dotenv>=1.0.1
|
|
11
11
|
Requires-Dist: requests>=2.25.0
|
|
12
12
|
Requires-Dist: fastapi>=0.100.0
|
|
@@ -170,13 +170,14 @@ The example configurations below were exercised against the live APIs, and the p
|
|
|
170
170
|
| flyio | 34–35 | apps + machine health | `API_KEY` |
|
|
171
171
|
| slack | 7 (exact dot-path whitelist until #27 fix) | `auth.test` + `postMessage` | `API_KEY` |
|
|
172
172
|
| netbox | 9 (whitelist `/ipam/ip-addresses`) | IPAM write + read | `API_KEY` + `API_AUTH_TYPE=Token` |
|
|
173
|
+
| homeassistant | 21 | `get_config` (200) + `call_service` (light.turn_on, 200) | `SERVER_URL_OVERRIDE` + `API_KEY` (`${HA_TOKEN}`, sent as Bearer) |
|
|
173
174
|
|
|
174
175
|
### Client matrix
|
|
175
176
|
|
|
176
177
|
| Agent CLI | Model used (live test) | MCP attach mechanism | Tool calls | Prompts/Resources surfaced to model? |
|
|
177
178
|
|---|---|---|---|---|
|
|
178
179
|
| **opencode** | (CLI default) | `~/.config/opencode/opencode.json` `mcp` | ✅ native | **prompts: ✅ (slash) · resources: ✅** — most complete ‖ |
|
|
179
|
-
| Codex | `gpt-5-codex` (OpenAI API) | `codex exec -c mcp_servers.*` | ✅ native | prompts: ❌ (
|
|
180
|
+
| Codex | `gpt-5-codex` (OpenAI API) | `codex exec -c mcp_servers.*` | ✅ native | prompts: ❌ low-level · ✅ fastmcp (via `call_function`→`get_prompt`) · resources: ✅ (`read_mcp_resource`) ‖ |
|
|
180
181
|
| Kilocode | `kilo-auto/free` | global `settings/mcp_settings.json` | ✅ native | prompts: ❌ (no prompt mechanism) · resources: ✅ (`access_mcp_resource`) ‖ |
|
|
181
182
|
| Qwen | `agent` group via local LiteLLM gateway | project `.qwen/settings.json` | ✅ native (live invoke auth-blocked) | prompts: ✅ (slash `/summarize_spec`) · resources: ❌ (no client support) ‖ |
|
|
182
183
|
| Gemini | Google OAuth free tier (CLI default model) | project `.gemini/settings.json` `mcpServers` | ✅ native | prompts: interactive slash only · resources: interactive `@` only (neither reaches the model headless) ‖ |
|
|
@@ -188,11 +189,17 @@ The example configurations below were exercised against the live APIs, and the p
|
|
|
188
189
|
> resources. **mcp-openapi-proxy serves all three, advertised by default since 0.3.0.**
|
|
189
190
|
> Whether they reach the model is up to the *client*, and that varies:
|
|
190
191
|
>
|
|
191
|
-
> - **‖ re-verified 2026-06-
|
|
192
|
-
> (validating the default-on advertising), driving each **real client binary
|
|
192
|
+
> - **‖ re-verified 2026-06-15 against the published 0.3.3 release** with **no** flags set
|
|
193
|
+
> (validating the default-on advertising), driving each **real client binary**, in
|
|
194
|
+
> **both** server modes (low-level and FastMCP simple). Per-client results were the
|
|
195
|
+
> same across modes except where noted.
|
|
193
196
|
> - **Tools** work on every client tested. **Prompts→model**: opencode & Qwen (slash
|
|
194
197
|
> commands); Gemini interactive-only. **Resources→model**: opencode, Codex, Kilocode.
|
|
195
|
-
> **opencode is the only client that surfaces all three
|
|
198
|
+
> **opencode is the only client that surfaces all three** in any mode.
|
|
199
|
+
> - **FastMCP simple mode exception:** a client with no native prompt surface can still
|
|
200
|
+
> reach prompts through the static `call_function`→`get_prompt` indirection. Observed
|
|
201
|
+
> with **Codex** (prompts ❌ in low-level, ✅ in FastMCP simple mode). Vibe stays
|
|
202
|
+
> tools-only regardless of mode.
|
|
196
203
|
> - **‡ unknown** — Letta can't be exercised without standing up a Letta server + model;
|
|
197
204
|
> left untested rather than guessed.
|
|
198
205
|
> - Every cell on the proxy side was confirmed via a raw stdio handshake (`initialize`
|
|
@@ -935,6 +942,54 @@ Tips: set `IGNORE_SSL_TOOLS=true` only if your host serves a self-signed/mismatc
|
|
|
935
942
|
|
|
936
943
|
</details>
|
|
937
944
|
|
|
945
|
+
<details>
|
|
946
|
+
<summary><b>Home Assistant Example</b> — control your smart home; <code>call_service</code> needs the >= 0.3.3 path-param body fix</summary>
|
|
947
|
+
|
|
948
|
+
Exposes a generic slice of the [Home Assistant REST API](https://developers.home-assistant.io/docs/api/rest/)
|
|
949
|
+
(21 operations) — read state (`get_config`, `list_states`, `get_state`, `list_services`,
|
|
950
|
+
`get_history`/`get_history_now`, `get_logbook`, `list_calendars`, `get_calendar_events`,
|
|
951
|
+
`get_camera_image`, `get_error_log`, `list_components`, `list_events`, `get_api_status`) and
|
|
952
|
+
act (`call_service`, `set_state`, `delete_state`, `fire_event`, `render_template`,
|
|
953
|
+
`check_config`, `handle_intent`). HA ships no official OpenAPI spec, so this is hand-rolled
|
|
954
|
+
from the official docs.
|
|
955
|
+
|
|
956
|
+
#### 1. Verify the OpenAPI specification
|
|
957
|
+
|
|
958
|
+
```bash
|
|
959
|
+
curl https://raw.githubusercontent.com/matthewhand/mcp-openapi-proxy/refs/heads/main/examples/homeassistant.openapi.json
|
|
960
|
+
```
|
|
961
|
+
|
|
962
|
+
#### 2. Configure mcp-openapi-proxy for Home Assistant
|
|
963
|
+
|
|
964
|
+
```json
|
|
965
|
+
{
|
|
966
|
+
"mcpServers": {
|
|
967
|
+
"homeassistant": {
|
|
968
|
+
"command": "uvx",
|
|
969
|
+
"args": ["mcp-openapi-proxy"],
|
|
970
|
+
"env": {
|
|
971
|
+
"OPENAPI_SPEC_URL": "https://raw.githubusercontent.com/matthewhand/mcp-openapi-proxy/refs/heads/main/examples/homeassistant.openapi.json",
|
|
972
|
+
"SERVER_URL_OVERRIDE": "http://homeassistant.local:8123",
|
|
973
|
+
"API_KEY": "${HA_TOKEN}"
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
```
|
|
979
|
+
|
|
980
|
+
Key configuration points:
|
|
981
|
+
- `SERVER_URL_OVERRIDE` — your instance base URL, e.g. `http://homeassistant.local:8123` or `http://<ha-host>:8123`.
|
|
982
|
+
- `HA_TOKEN` — a Home Assistant **long-lived access token** (Profile → Long-Lived Access Tokens), passed via `API_KEY`; the proxy sends it as `Authorization: Bearer <token>` (its default scheme), so no `EXTRA_HEADERS` needed. Never commit the token; keep it in your environment.
|
|
983
|
+
- `call_service` requires **mcp-openapi-proxy >= 0.3.3**: earlier versions leaked the `{domain}`/`{service}` path params into the JSON body, which Home Assistant rejects with HTTP 400.
|
|
984
|
+
|
|
985
|
+
#### 3. Testing
|
|
986
|
+
|
|
987
|
+
`get_config` should return your HA configuration (200). `call_service` for `light/turn_on`
|
|
988
|
+
with body `{"entity_id": "light.kitchen"}` should return 200 — the path params land in the URL
|
|
989
|
+
(`/api/services/light/turn_on`), not the body.
|
|
990
|
+
|
|
991
|
+
</details>
|
|
992
|
+
|
|
938
993
|
## Troubleshooting
|
|
939
994
|
|
|
940
995
|
### JSON-RPC Testing
|
|
@@ -148,13 +148,14 @@ The example configurations below were exercised against the live APIs, and the p
|
|
|
148
148
|
| flyio | 34–35 | apps + machine health | `API_KEY` |
|
|
149
149
|
| slack | 7 (exact dot-path whitelist until #27 fix) | `auth.test` + `postMessage` | `API_KEY` |
|
|
150
150
|
| netbox | 9 (whitelist `/ipam/ip-addresses`) | IPAM write + read | `API_KEY` + `API_AUTH_TYPE=Token` |
|
|
151
|
+
| homeassistant | 21 | `get_config` (200) + `call_service` (light.turn_on, 200) | `SERVER_URL_OVERRIDE` + `API_KEY` (`${HA_TOKEN}`, sent as Bearer) |
|
|
151
152
|
|
|
152
153
|
### Client matrix
|
|
153
154
|
|
|
154
155
|
| Agent CLI | Model used (live test) | MCP attach mechanism | Tool calls | Prompts/Resources surfaced to model? |
|
|
155
156
|
|---|---|---|---|---|
|
|
156
157
|
| **opencode** | (CLI default) | `~/.config/opencode/opencode.json` `mcp` | ✅ native | **prompts: ✅ (slash) · resources: ✅** — most complete ‖ |
|
|
157
|
-
| Codex | `gpt-5-codex` (OpenAI API) | `codex exec -c mcp_servers.*` | ✅ native | prompts: ❌ (
|
|
158
|
+
| Codex | `gpt-5-codex` (OpenAI API) | `codex exec -c mcp_servers.*` | ✅ native | prompts: ❌ low-level · ✅ fastmcp (via `call_function`→`get_prompt`) · resources: ✅ (`read_mcp_resource`) ‖ |
|
|
158
159
|
| Kilocode | `kilo-auto/free` | global `settings/mcp_settings.json` | ✅ native | prompts: ❌ (no prompt mechanism) · resources: ✅ (`access_mcp_resource`) ‖ |
|
|
159
160
|
| Qwen | `agent` group via local LiteLLM gateway | project `.qwen/settings.json` | ✅ native (live invoke auth-blocked) | prompts: ✅ (slash `/summarize_spec`) · resources: ❌ (no client support) ‖ |
|
|
160
161
|
| Gemini | Google OAuth free tier (CLI default model) | project `.gemini/settings.json` `mcpServers` | ✅ native | prompts: interactive slash only · resources: interactive `@` only (neither reaches the model headless) ‖ |
|
|
@@ -166,11 +167,17 @@ The example configurations below were exercised against the live APIs, and the p
|
|
|
166
167
|
> resources. **mcp-openapi-proxy serves all three, advertised by default since 0.3.0.**
|
|
167
168
|
> Whether they reach the model is up to the *client*, and that varies:
|
|
168
169
|
>
|
|
169
|
-
> - **‖ re-verified 2026-06-
|
|
170
|
-
> (validating the default-on advertising), driving each **real client binary
|
|
170
|
+
> - **‖ re-verified 2026-06-15 against the published 0.3.3 release** with **no** flags set
|
|
171
|
+
> (validating the default-on advertising), driving each **real client binary**, in
|
|
172
|
+
> **both** server modes (low-level and FastMCP simple). Per-client results were the
|
|
173
|
+
> same across modes except where noted.
|
|
171
174
|
> - **Tools** work on every client tested. **Prompts→model**: opencode & Qwen (slash
|
|
172
175
|
> commands); Gemini interactive-only. **Resources→model**: opencode, Codex, Kilocode.
|
|
173
|
-
> **opencode is the only client that surfaces all three
|
|
176
|
+
> **opencode is the only client that surfaces all three** in any mode.
|
|
177
|
+
> - **FastMCP simple mode exception:** a client with no native prompt surface can still
|
|
178
|
+
> reach prompts through the static `call_function`→`get_prompt` indirection. Observed
|
|
179
|
+
> with **Codex** (prompts ❌ in low-level, ✅ in FastMCP simple mode). Vibe stays
|
|
180
|
+
> tools-only regardless of mode.
|
|
174
181
|
> - **‡ unknown** — Letta can't be exercised without standing up a Letta server + model;
|
|
175
182
|
> left untested rather than guessed.
|
|
176
183
|
> - Every cell on the proxy side was confirmed via a raw stdio handshake (`initialize`
|
|
@@ -913,6 +920,54 @@ Tips: set `IGNORE_SSL_TOOLS=true` only if your host serves a self-signed/mismatc
|
|
|
913
920
|
|
|
914
921
|
</details>
|
|
915
922
|
|
|
923
|
+
<details>
|
|
924
|
+
<summary><b>Home Assistant Example</b> — control your smart home; <code>call_service</code> needs the >= 0.3.3 path-param body fix</summary>
|
|
925
|
+
|
|
926
|
+
Exposes a generic slice of the [Home Assistant REST API](https://developers.home-assistant.io/docs/api/rest/)
|
|
927
|
+
(21 operations) — read state (`get_config`, `list_states`, `get_state`, `list_services`,
|
|
928
|
+
`get_history`/`get_history_now`, `get_logbook`, `list_calendars`, `get_calendar_events`,
|
|
929
|
+
`get_camera_image`, `get_error_log`, `list_components`, `list_events`, `get_api_status`) and
|
|
930
|
+
act (`call_service`, `set_state`, `delete_state`, `fire_event`, `render_template`,
|
|
931
|
+
`check_config`, `handle_intent`). HA ships no official OpenAPI spec, so this is hand-rolled
|
|
932
|
+
from the official docs.
|
|
933
|
+
|
|
934
|
+
#### 1. Verify the OpenAPI specification
|
|
935
|
+
|
|
936
|
+
```bash
|
|
937
|
+
curl https://raw.githubusercontent.com/matthewhand/mcp-openapi-proxy/refs/heads/main/examples/homeassistant.openapi.json
|
|
938
|
+
```
|
|
939
|
+
|
|
940
|
+
#### 2. Configure mcp-openapi-proxy for Home Assistant
|
|
941
|
+
|
|
942
|
+
```json
|
|
943
|
+
{
|
|
944
|
+
"mcpServers": {
|
|
945
|
+
"homeassistant": {
|
|
946
|
+
"command": "uvx",
|
|
947
|
+
"args": ["mcp-openapi-proxy"],
|
|
948
|
+
"env": {
|
|
949
|
+
"OPENAPI_SPEC_URL": "https://raw.githubusercontent.com/matthewhand/mcp-openapi-proxy/refs/heads/main/examples/homeassistant.openapi.json",
|
|
950
|
+
"SERVER_URL_OVERRIDE": "http://homeassistant.local:8123",
|
|
951
|
+
"API_KEY": "${HA_TOKEN}"
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
```
|
|
957
|
+
|
|
958
|
+
Key configuration points:
|
|
959
|
+
- `SERVER_URL_OVERRIDE` — your instance base URL, e.g. `http://homeassistant.local:8123` or `http://<ha-host>:8123`.
|
|
960
|
+
- `HA_TOKEN` — a Home Assistant **long-lived access token** (Profile → Long-Lived Access Tokens), passed via `API_KEY`; the proxy sends it as `Authorization: Bearer <token>` (its default scheme), so no `EXTRA_HEADERS` needed. Never commit the token; keep it in your environment.
|
|
961
|
+
- `call_service` requires **mcp-openapi-proxy >= 0.3.3**: earlier versions leaked the `{domain}`/`{service}` path params into the JSON body, which Home Assistant rejects with HTTP 400.
|
|
962
|
+
|
|
963
|
+
#### 3. Testing
|
|
964
|
+
|
|
965
|
+
`get_config` should return your HA configuration (200). `call_service` for `light/turn_on`
|
|
966
|
+
with body `{"entity_id": "light.kitchen"}` should return 200 — the path params land in the URL
|
|
967
|
+
(`/api/services/light/turn_on`), not the body.
|
|
968
|
+
|
|
969
|
+
</details>
|
|
970
|
+
|
|
916
971
|
## Troubleshooting
|
|
917
972
|
|
|
918
973
|
### JSON-RPC Testing
|
|
@@ -249,14 +249,19 @@ async def dispatcher_handler(request: types.CallToolRequest) -> types.CallToolRe
|
|
|
249
249
|
try:
|
|
250
250
|
path = path.format(**parameters)
|
|
251
251
|
logger.debug(f"Substituted path using format(): {path}")
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
252
|
+
# Path placeholders are now substituted into the URL, so drop them from
|
|
253
|
+
# `parameters` for ALL methods. Previously this ran only for GET, so on
|
|
254
|
+
# POST/PUT/PATCH/DELETE the path params leaked into request_body and
|
|
255
|
+
# strict APIs rejected the unexpected fields -- e.g. Home Assistant
|
|
256
|
+
# POST /api/services/{domain}/{service} returned HTTP 400 because the
|
|
257
|
+
# body carried domain/service.
|
|
258
|
+
placeholder_keys = [
|
|
259
|
+
seg.strip("{}")
|
|
260
|
+
for seg in operation_details["original_path"].split("/")
|
|
261
|
+
if seg.startswith("{") and seg.endswith("}")
|
|
262
|
+
]
|
|
263
|
+
for key in placeholder_keys:
|
|
264
|
+
parameters.pop(key, None)
|
|
260
265
|
except KeyError as e:
|
|
261
266
|
logger.error(f"Missing parameter for substitution: {e}")
|
|
262
267
|
return types.CallToolResult(
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mcp-openapi-proxy
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.4
|
|
4
4
|
Summary: MCP server for exposing OpenAPI specifications as MCP tools.
|
|
5
5
|
Author-email: Matthew Hand <11550632+matthewhand@users.noreply.github.com>
|
|
6
6
|
Requires-Python: >=3.10
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
8
|
License-File: LICENSE
|
|
9
|
-
Requires-Dist: mcp[cli]
|
|
9
|
+
Requires-Dist: mcp[cli]<2,>=1.2.0
|
|
10
10
|
Requires-Dist: python-dotenv>=1.0.1
|
|
11
11
|
Requires-Dist: requests>=2.25.0
|
|
12
12
|
Requires-Dist: fastapi>=0.100.0
|
|
@@ -170,13 +170,14 @@ The example configurations below were exercised against the live APIs, and the p
|
|
|
170
170
|
| flyio | 34–35 | apps + machine health | `API_KEY` |
|
|
171
171
|
| slack | 7 (exact dot-path whitelist until #27 fix) | `auth.test` + `postMessage` | `API_KEY` |
|
|
172
172
|
| netbox | 9 (whitelist `/ipam/ip-addresses`) | IPAM write + read | `API_KEY` + `API_AUTH_TYPE=Token` |
|
|
173
|
+
| homeassistant | 21 | `get_config` (200) + `call_service` (light.turn_on, 200) | `SERVER_URL_OVERRIDE` + `API_KEY` (`${HA_TOKEN}`, sent as Bearer) |
|
|
173
174
|
|
|
174
175
|
### Client matrix
|
|
175
176
|
|
|
176
177
|
| Agent CLI | Model used (live test) | MCP attach mechanism | Tool calls | Prompts/Resources surfaced to model? |
|
|
177
178
|
|---|---|---|---|---|
|
|
178
179
|
| **opencode** | (CLI default) | `~/.config/opencode/opencode.json` `mcp` | ✅ native | **prompts: ✅ (slash) · resources: ✅** — most complete ‖ |
|
|
179
|
-
| Codex | `gpt-5-codex` (OpenAI API) | `codex exec -c mcp_servers.*` | ✅ native | prompts: ❌ (
|
|
180
|
+
| Codex | `gpt-5-codex` (OpenAI API) | `codex exec -c mcp_servers.*` | ✅ native | prompts: ❌ low-level · ✅ fastmcp (via `call_function`→`get_prompt`) · resources: ✅ (`read_mcp_resource`) ‖ |
|
|
180
181
|
| Kilocode | `kilo-auto/free` | global `settings/mcp_settings.json` | ✅ native | prompts: ❌ (no prompt mechanism) · resources: ✅ (`access_mcp_resource`) ‖ |
|
|
181
182
|
| Qwen | `agent` group via local LiteLLM gateway | project `.qwen/settings.json` | ✅ native (live invoke auth-blocked) | prompts: ✅ (slash `/summarize_spec`) · resources: ❌ (no client support) ‖ |
|
|
182
183
|
| Gemini | Google OAuth free tier (CLI default model) | project `.gemini/settings.json` `mcpServers` | ✅ native | prompts: interactive slash only · resources: interactive `@` only (neither reaches the model headless) ‖ |
|
|
@@ -188,11 +189,17 @@ The example configurations below were exercised against the live APIs, and the p
|
|
|
188
189
|
> resources. **mcp-openapi-proxy serves all three, advertised by default since 0.3.0.**
|
|
189
190
|
> Whether they reach the model is up to the *client*, and that varies:
|
|
190
191
|
>
|
|
191
|
-
> - **‖ re-verified 2026-06-
|
|
192
|
-
> (validating the default-on advertising), driving each **real client binary
|
|
192
|
+
> - **‖ re-verified 2026-06-15 against the published 0.3.3 release** with **no** flags set
|
|
193
|
+
> (validating the default-on advertising), driving each **real client binary**, in
|
|
194
|
+
> **both** server modes (low-level and FastMCP simple). Per-client results were the
|
|
195
|
+
> same across modes except where noted.
|
|
193
196
|
> - **Tools** work on every client tested. **Prompts→model**: opencode & Qwen (slash
|
|
194
197
|
> commands); Gemini interactive-only. **Resources→model**: opencode, Codex, Kilocode.
|
|
195
|
-
> **opencode is the only client that surfaces all three
|
|
198
|
+
> **opencode is the only client that surfaces all three** in any mode.
|
|
199
|
+
> - **FastMCP simple mode exception:** a client with no native prompt surface can still
|
|
200
|
+
> reach prompts through the static `call_function`→`get_prompt` indirection. Observed
|
|
201
|
+
> with **Codex** (prompts ❌ in low-level, ✅ in FastMCP simple mode). Vibe stays
|
|
202
|
+
> tools-only regardless of mode.
|
|
196
203
|
> - **‡ unknown** — Letta can't be exercised without standing up a Letta server + model;
|
|
197
204
|
> left untested rather than guessed.
|
|
198
205
|
> - Every cell on the proxy side was confirmed via a raw stdio handshake (`initialize`
|
|
@@ -935,6 +942,54 @@ Tips: set `IGNORE_SSL_TOOLS=true` only if your host serves a self-signed/mismatc
|
|
|
935
942
|
|
|
936
943
|
</details>
|
|
937
944
|
|
|
945
|
+
<details>
|
|
946
|
+
<summary><b>Home Assistant Example</b> — control your smart home; <code>call_service</code> needs the >= 0.3.3 path-param body fix</summary>
|
|
947
|
+
|
|
948
|
+
Exposes a generic slice of the [Home Assistant REST API](https://developers.home-assistant.io/docs/api/rest/)
|
|
949
|
+
(21 operations) — read state (`get_config`, `list_states`, `get_state`, `list_services`,
|
|
950
|
+
`get_history`/`get_history_now`, `get_logbook`, `list_calendars`, `get_calendar_events`,
|
|
951
|
+
`get_camera_image`, `get_error_log`, `list_components`, `list_events`, `get_api_status`) and
|
|
952
|
+
act (`call_service`, `set_state`, `delete_state`, `fire_event`, `render_template`,
|
|
953
|
+
`check_config`, `handle_intent`). HA ships no official OpenAPI spec, so this is hand-rolled
|
|
954
|
+
from the official docs.
|
|
955
|
+
|
|
956
|
+
#### 1. Verify the OpenAPI specification
|
|
957
|
+
|
|
958
|
+
```bash
|
|
959
|
+
curl https://raw.githubusercontent.com/matthewhand/mcp-openapi-proxy/refs/heads/main/examples/homeassistant.openapi.json
|
|
960
|
+
```
|
|
961
|
+
|
|
962
|
+
#### 2. Configure mcp-openapi-proxy for Home Assistant
|
|
963
|
+
|
|
964
|
+
```json
|
|
965
|
+
{
|
|
966
|
+
"mcpServers": {
|
|
967
|
+
"homeassistant": {
|
|
968
|
+
"command": "uvx",
|
|
969
|
+
"args": ["mcp-openapi-proxy"],
|
|
970
|
+
"env": {
|
|
971
|
+
"OPENAPI_SPEC_URL": "https://raw.githubusercontent.com/matthewhand/mcp-openapi-proxy/refs/heads/main/examples/homeassistant.openapi.json",
|
|
972
|
+
"SERVER_URL_OVERRIDE": "http://homeassistant.local:8123",
|
|
973
|
+
"API_KEY": "${HA_TOKEN}"
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
```
|
|
979
|
+
|
|
980
|
+
Key configuration points:
|
|
981
|
+
- `SERVER_URL_OVERRIDE` — your instance base URL, e.g. `http://homeassistant.local:8123` or `http://<ha-host>:8123`.
|
|
982
|
+
- `HA_TOKEN` — a Home Assistant **long-lived access token** (Profile → Long-Lived Access Tokens), passed via `API_KEY`; the proxy sends it as `Authorization: Bearer <token>` (its default scheme), so no `EXTRA_HEADERS` needed. Never commit the token; keep it in your environment.
|
|
983
|
+
- `call_service` requires **mcp-openapi-proxy >= 0.3.3**: earlier versions leaked the `{domain}`/`{service}` path params into the JSON body, which Home Assistant rejects with HTTP 400.
|
|
984
|
+
|
|
985
|
+
#### 3. Testing
|
|
986
|
+
|
|
987
|
+
`get_config` should return your HA configuration (200). `call_service` for `light/turn_on`
|
|
988
|
+
with body `{"entity_id": "light.kitchen"}` should return 200 — the path params land in the URL
|
|
989
|
+
(`/api/services/light/turn_on`), not the body.
|
|
990
|
+
|
|
991
|
+
</details>
|
|
992
|
+
|
|
938
993
|
## Troubleshooting
|
|
939
994
|
|
|
940
995
|
### JSON-RPC Testing
|
|
@@ -5,14 +5,17 @@ build-backend = "setuptools.build_meta"
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "mcp-openapi-proxy"
|
|
7
7
|
requires-python = ">=3.10"
|
|
8
|
-
version = "0.3.
|
|
8
|
+
version = "0.3.4"
|
|
9
9
|
description = "MCP server for exposing OpenAPI specifications as MCP tools."
|
|
10
10
|
readme = "README.md"
|
|
11
11
|
authors = [
|
|
12
12
|
{ name = "Matthew Hand", email = "11550632+matthewhand@users.noreply.github.com" }
|
|
13
13
|
]
|
|
14
14
|
dependencies = [
|
|
15
|
-
|
|
15
|
+
# mcp 2.x is a breaking rewrite (FastMCP renamed to MCPServer, Resource.uri type
|
|
16
|
+
# change, etc.) that crashes both server modes at import. Pin to 1.x; see
|
|
17
|
+
# tests/unit/test_mcp_version_pin.py before relaxing this bound.
|
|
18
|
+
"mcp[cli]>=1.2.0,<2",
|
|
16
19
|
"python-dotenv>=1.0.1",
|
|
17
20
|
"requests>=2.25.0",
|
|
18
21
|
"fastapi>=0.100.0", # For OpenAPI parsing utils if used later, and data validation
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mcp_openapi_proxy-0.3.2 → mcp_openapi_proxy-0.3.4}/mcp_openapi_proxy.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{mcp_openapi_proxy-0.3.2 → mcp_openapi_proxy-0.3.4}/mcp_openapi_proxy.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{mcp_openapi_proxy-0.3.2 → mcp_openapi_proxy-0.3.4}/mcp_openapi_proxy.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|