Switch MCP transport from stdio to Streamable HTTP

Mount POST /mcp on the main Express app (stateless Streamable HTTP).
Keep optional MCP-only HTTP process via npm run mcp. Update docs.
This commit is contained in:
2026-08-07 08:51:59 +02:00
parent f7f1481a39
commit 3032f2ea85
6 changed files with 152 additions and 58 deletions

View File

@@ -11,7 +11,7 @@ Official Webshare HTTP API documentation: [https://webshare.cz/apidoc/](https://
| **Stream** | `GET /stream/:ident` | Fresh Webshare `file_link` + HTTP 302 to CDN |
| **Fake qBittorrent** | `/api/v2/*` | Download client API; streams the HTTPS file to disk |
| **Debug** | `GET /resolve/:ident` | JSON with the resolved CDN URL |
| **MCP server** | stdio (`npm run mcp`) | Tools for AI agents: search, resolve links, login check |
| **MCP server** | `POST /mcp` (Streamable HTTP) | Tools for AI agents: search, resolve links, login check |
Webshare download links expire after roughly ten minutes, so the torrent never embeds a CDN URL—only a path on this service that resolves a fresh link at fetch time.
@@ -26,7 +26,8 @@ src/
torrent.js # bencode + fake torrent + info-hash
qbt.js # qBittorrent Web API façade + download queue
mcp-server.js # MCP tool registration (shared)
mcp.js # MCP stdio entrypoint for agents
mcp-http.js # Streamable HTTP transport mount for Express
mcp.js # Optional MCP-only HTTP process
__tests__/
compose.yaml
Dockerfile
@@ -49,6 +50,8 @@ Environment variables (required unless noted):
| `SONARR_API_KEY` | _(empty)_ | Optional; enables periodic missing-episode search |
| `SONARR_SEARCH_INTERVAL_HOURS` | `2` | Interval for that search |
| `DOWNLOAD_HOST_PATH` | `./data/webshare` | Host path mounted at `DOWNLOAD_PATH` in Compose |
| `MCP_ENABLED` | `true` | Set to `0`/`false` to disable the MCP HTTP endpoint |
| `MCP_PATH` | `/mcp` | HTTP path for the Streamable HTTP MCP endpoint |
Copy `.env.example` and fill in credentials. Do not commit a filled `.env`.
@@ -82,7 +85,21 @@ Sonarr hands `.torrent` files to the fake qBittorrent API. This service extracts
## MCP (AI agents)
Exposes Webshare to MCP-compatible clients over **stdio** (stdout is protocol-only; logs go to stderr).
Exposes Webshare to MCP-compatible clients over **Streamable HTTP** (not stdio).
With `npm start` (or Compose), MCP is available on the same process/port:
```
POST http://<host>:3001/mcp
```
Optional MCP-only process (no Torznab/qBittorrent):
```bash
export WEBSHARE_USERNAME=...
export WEBSHARE_PASSWORD=...
npm run mcp # listens on PORT, serves POST /mcp
```
### Tools
@@ -92,43 +109,22 @@ Exposes Webshare to MCP-compatible clients over **stdio** (stdout is protocol-on
| `webshare_get_link` | Resolve a temporary CDN URL for a file `ident` |
| `webshare_login_check` | Verify credentials against the Webshare API |
### Run
```bash
export WEBSHARE_USERNAME=...
export WEBSHARE_PASSWORD=...
npm run mcp
# or: npx webshare-mcp (after npm link / global install)
```
### Client configuration example
**Claude Desktop / similar** (`mcpServers`):
```json
{
"mcpServers": {
"webshare": {
"command": "node",
"args": ["/absolute/path/to/webshare-api/src/mcp.js"],
"env": {
"WEBSHARE_USERNAME": "your-username",
"WEBSHARE_PASSWORD": "your-password"
}
}
}
}
```
**Grok / OpenCode-style** (TOML):
**HTTP / Streamable HTTP** (preferred):
```toml
[mcp_servers.webshare]
command = "node"
args = ["/absolute/path/to/webshare-api/src/mcp.js"]
url = "http://127.0.0.1:3001/mcp"
```
Pass `WEBSHARE_USERNAME` and `WEBSHARE_PASSWORD` via the client env settings or a process manager—not in the repo.
```bash
grok mcp add --transport http webshare http://127.0.0.1:3001/mcp
```
Credentials stay on the server process (`WEBSHARE_*` env); clients only need the URL.
The transport is **stateless** Streamable HTTP (POST only).
## Tests