easydeploy-ai-mcp 0.1.0__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 (27) hide show
  1. easydeploy_ai_mcp-0.1.0/LICENSE +21 -0
  2. easydeploy_ai_mcp-0.1.0/PKG-INFO +288 -0
  3. easydeploy_ai_mcp-0.1.0/README.md +252 -0
  4. easydeploy_ai_mcp-0.1.0/pyproject.toml +64 -0
  5. easydeploy_ai_mcp-0.1.0/setup.cfg +4 -0
  6. easydeploy_ai_mcp-0.1.0/src/easydeploy_ai_mcp/__init__.py +7 -0
  7. easydeploy_ai_mcp-0.1.0/src/easydeploy_ai_mcp/__main__.py +6 -0
  8. easydeploy_ai_mcp-0.1.0/src/easydeploy_ai_mcp/api_client.py +830 -0
  9. easydeploy_ai_mcp-0.1.0/src/easydeploy_ai_mcp/auth.py +127 -0
  10. easydeploy_ai_mcp-0.1.0/src/easydeploy_ai_mcp/cli.py +33 -0
  11. easydeploy_ai_mcp-0.1.0/src/easydeploy_ai_mcp/credentials.py +81 -0
  12. easydeploy_ai_mcp-0.1.0/src/easydeploy_ai_mcp/defaults.py +5 -0
  13. easydeploy_ai_mcp-0.1.0/src/easydeploy_ai_mcp/http_main.py +531 -0
  14. easydeploy_ai_mcp-0.1.0/src/easydeploy_ai_mcp/oauth_as_metadata.py +99 -0
  15. easydeploy_ai_mcp-0.1.0/src/easydeploy_ai_mcp/server.py +978 -0
  16. easydeploy_ai_mcp-0.1.0/src/easydeploy_ai_mcp.egg-info/PKG-INFO +288 -0
  17. easydeploy_ai_mcp-0.1.0/src/easydeploy_ai_mcp.egg-info/SOURCES.txt +25 -0
  18. easydeploy_ai_mcp-0.1.0/src/easydeploy_ai_mcp.egg-info/dependency_links.txt +1 -0
  19. easydeploy_ai_mcp-0.1.0/src/easydeploy_ai_mcp.egg-info/entry_points.txt +3 -0
  20. easydeploy_ai_mcp-0.1.0/src/easydeploy_ai_mcp.egg-info/requires.txt +13 -0
  21. easydeploy_ai_mcp-0.1.0/src/easydeploy_ai_mcp.egg-info/top_level.txt +1 -0
  22. easydeploy_ai_mcp-0.1.0/tests/test_auth.py +521 -0
  23. easydeploy_ai_mcp-0.1.0/tests/test_cognito_jwt_integration.py +112 -0
  24. easydeploy_ai_mcp-0.1.0/tests/test_credentials.py +41 -0
  25. easydeploy_ai_mcp-0.1.0/tests/test_http_main.py +47 -0
  26. easydeploy_ai_mcp-0.1.0/tests/test_oauth_as_metadata.py +47 -0
  27. easydeploy_ai_mcp-0.1.0/tests/test_server_tools.py +509 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 EasyDeploy AI
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,288 @@
1
+ Metadata-Version: 2.4
2
+ Name: easydeploy-ai-mcp
3
+ Version: 0.1.0
4
+ Summary: EasyDeploy AI MCP server — REST API tools for Claude and other MCP clients
5
+ Author: EasyDeploy AI
6
+ License: MIT
7
+ Project-URL: Homepage, https://easydeploy.ai
8
+ Project-URL: Documentation, https://github.com/easydeploy-ai/easydeploy-ai-mcp#readme
9
+ Project-URL: Repository, https://github.com/easydeploy-ai/easydeploy-ai-mcp
10
+ Project-URL: Issues, https://github.com/easydeploy-ai/easydeploy-ai-mcp/issues
11
+ Keywords: mcp,easydeploy,llm,claude,automl
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Requires-Python: >=3.10
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: fastmcp<4,>=3.1.1
25
+ Requires-Dist: httpx<1,>=0.27
26
+ Requires-Dist: python-dotenv>=1.1.0
27
+ Requires-Dist: uvicorn[standard]<1,>=0.30
28
+ Provides-Extra: oauth
29
+ Requires-Dist: pyjwt[crypto]<3,>=2.8; extra == "oauth"
30
+ Provides-Extra: dev
31
+ Requires-Dist: pytest<10,>=8.2; extra == "dev"
32
+ Requires-Dist: pytest-asyncio>=0.24.0; extra == "dev"
33
+ Requires-Dist: pyjwt[crypto]<3,>=2.8; extra == "dev"
34
+ Requires-Dist: certifi>=2024.0.0; extra == "dev"
35
+ Dynamic: license-file
36
+
37
+ # EasyDeploy AI MCP (`easydeploy-ai-mcp`)
38
+
39
+ A [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server that exposes the **[EasyDeploy](https://easydeploy.ai)** public REST API as tools for Claude, Cursor, Claude Code, and other MCP clients.
40
+
41
+ **PyPI package name:** `easydeploy-ai-mcp` · **Import package:** `easydeploy_ai_mcp`
42
+
43
+ ## Contents
44
+
45
+ - [Connect with Claude](#connect-with-claude)
46
+ - [What you get](#what-you-get)
47
+ - [Requirements](#requirements)
48
+ - [Install](#install)
49
+ - [Environment variables](#environment-variables)
50
+ - [Local MCP (stdio)](#local-mcp-stdio)
51
+ - [Remote MCP (HTTP)](#remote-mcp-http)
52
+ - [Documentation](#documentation)
53
+ - [REST API reference](#rest-api-reference)
54
+ - [Releases and API compatibility](#releases-and-api-compatibility)
55
+ - [Development](#development)
56
+ - [Security](#security)
57
+ - [License](#license)
58
+
59
+ ## Connect with Claude
60
+
61
+ ### Option A — Hosted connector (zero setup)
62
+
63
+ The fastest way to use EasyDeploy AI tools in Claude. No installation required.
64
+
65
+ 1. Open **Claude** (web at [claude.ai](https://claude.ai) or Claude Desktop).
66
+ 2. Go to **Settings → Connectors → Add custom connector**.
67
+ 3. Fill in the form:
68
+ - **Name:** `EasyDeploy AI`
69
+ - **URL:** `https://mcp.easydeploy.ai/mcp`
70
+ 4. Complete the OAuth sign-in flow when prompted. Claude will redirect you to EasyDeploy to authenticate with your account.
71
+ 5. Save the connector. EasyDeploy tools will appear in your Claude sessions.
72
+
73
+ > **Note:** The hosted connector uses OAuth — you sign in with your EasyDeploy account; no API key needs to be pasted into Claude.
74
+
75
+ ---
76
+
77
+ ### Option B — Self-hosted (local stdio)
78
+
79
+ Run the MCP server on your own machine using your EasyDeploy API key. Nothing is exposed to the internet.
80
+
81
+ **1. Install**
82
+
83
+ ```bash
84
+ pip install easydeploy-ai-mcp
85
+ ```
86
+
87
+ **2. Add to Claude Desktop config**
88
+
89
+ Edit (or create) the Claude Desktop config file:
90
+
91
+ | OS | Path |
92
+ | ------- | ---- |
93
+ | macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` |
94
+ | Windows | `%APPDATA%\Claude\claude_desktop_config.json` |
95
+
96
+ Merge the following into the root of that JSON (keep any existing keys):
97
+
98
+ ```json
99
+ {
100
+ "mcpServers": {
101
+ "EasyDeploy AI": {
102
+ "command": "easydeploy-ai-mcp-stdio",
103
+ "env": {
104
+ "EDA_API_KEY": "eda_live_YOUR_KEY"
105
+ }
106
+ }
107
+ }
108
+ }
109
+ ```
110
+
111
+ Replace `eda_live_YOUR_KEY` with your key from **Account → API Keys** in the EasyDeploy dashboard. Use the full path to `easydeploy-ai-mcp-stdio` (run `which easydeploy-ai-mcp-stdio` to find it) if Claude cannot locate it on your `PATH`.
112
+
113
+ **3. Restart Claude Desktop**
114
+
115
+ Fully quit and reopen the app. **EasyDeploy AI** will appear in your MCP servers.
116
+
117
+ ---
118
+
119
+ For self-hosting on Docker or a cloud provider, see [Remote MCP (HTTP)](#remote-mcp-http).
120
+
121
+ ## What you get
122
+
123
+ - **24 tools** covering projects, datasets (including upload flow), model versions, training jobs, predictions, and account status.
124
+ - **stdio** transport for local clients, or **HTTP** with Streamable MCP on `/mcp` and **GET /healthz** for load balancers.
125
+ - **Hardening:** HTTPS-only calls to the EasyDeploy API; optional `MCP_SERVICE_TOKEN` for the HTTP MCP surface; response fields trimmed where appropriate for agents.
126
+
127
+ For **production** and **SOC 2–sensitive** setups, prefer self-hosting so your data stays within your own infrastructure. The hosted connector at `https://mcp.easydeploy.ai/mcp` is fine for most users.
128
+
129
+ ## Requirements
130
+
131
+ - Python **3.10+**
132
+ - An EasyDeploy **API key** from the dashboard (**Account → API Keys**). The client uses the production EasyDeploy API host by default.
133
+
134
+ ## Install
135
+
136
+ ### From PyPI (after first release)
137
+
138
+ ```bash
139
+ pip install easydeploy-ai-mcp
140
+ ```
141
+
142
+ ### From source
143
+
144
+ ```bash
145
+ git clone https://github.com/easydeploy-ai/easydeploy-ai-mcp.git
146
+ cd easydeploy-ai-mcp
147
+ pip install -e ".[dev]" # includes pytest
148
+ # or minimal runtime only:
149
+ pip install .
150
+ ```
151
+
152
+ ## Environment variables
153
+
154
+
155
+ | Variable | Required | Description |
156
+ | ---------------------------------- | -------- | ----------------------------------------------------------------------------------------------- |
157
+ | `EDA_API_KEY` | stdio / legacy HTTP | Required for **stdio** and **legacy** HTTP (no OAuth). **Not** used for outbound API calls when `EDA_OAUTH_ENABLED=1` — each MCP request must include `Authorization: Bearer <JWT or eda_live_…>`. |
158
+ | `EDA_API_BASE` | No | Overrides the default production API (`https://api.easydeploy.ai`). Set only when targeting a non-production endpoint. Trailing `/v1` is optional. |
159
+ | `EDA_UI_BASE_URL` | No | Prefix for `ui_url` fields (default `https://easydeploy.ai`). |
160
+ | `MCP_SERVICE_TOKEN` | No | Legacy single-tenant gate. If set, HTTP mode requires `Authorization: Bearer <token>` for `/mcp` (not for `GET /healthz`). Mutually exclusive with `EDA_OAUTH_ENABLED`. |
161
+ | `EDA_OAUTH_ENABLED` | No | Set to `1` to run the HTTP transport as an OAuth 2.0 resource server. Requires `EDA_COGNITO_USER_POOL_ID` and `EDA_COGNITO_CLIENT_ID`. See [Remote MCP (HTTP)](#remote-mcp-http). |
162
+ | `EDA_COGNITO_USER_POOL_ID` | OAuth | Cognito user pool that issues access tokens for the EasyDeploy API. |
163
+ | `EDA_COGNITO_CLIENT_ID` | OAuth | App client ID expected in the access token's `client_id` claim. |
164
+ | `EDA_COGNITO_REGION` | No | AWS region for the user pool (default `us-east-1`). |
165
+ | `EDA_REPORT_MAX_WAIT_SECONDS` | No | `get_model_report` poll budget (default `300`). |
166
+ | `EDA_REPORT_POLL_INTERVAL_SECONDS` | No | Poll interval in seconds (default `10`). |
167
+ | `HOST` / `PORT` | No | HTTP bind (defaults `0.0.0.0` / `8080`). |
168
+ | `EDA_TRUST_FORWARDED_HEADERS` | No | Set to `1` behind ALB/reverse proxy so RFC 9728 `resource` uses `https` (trusts `X-Forwarded-Proto`). |
169
+ | `EDA_MCP_OAUTH_ISSUER` | No | Public MCP base URL (no path) for `authorization_servers` and proxy `/.well-known/oauth-authorization-server` **`issuer`**. Default: request origin. Use if `Host` / `X-Forwarded-Proto` are wrong behind a proxy. |
170
+
171
+
172
+ ## Local MCP (stdio)
173
+
174
+ Use when the client **starts** the server as a subprocess (Claude Desktop, Cursor, etc.).
175
+
176
+ ```bash
177
+ export EDA_API_KEY="eda_live_..."
178
+ easydeploy-ai-mcp-stdio
179
+ ```
180
+
181
+ Or: `python -m easydeploy_ai_mcp`
182
+
183
+ Example config snippet:
184
+
185
+ ```json
186
+ {
187
+ "mcpServers": {
188
+ "easydeploy-ai": {
189
+ "command": "easydeploy-ai-mcp-stdio",
190
+ "env": {
191
+ "EDA_API_KEY": "eda_live_..."
192
+ }
193
+ }
194
+ }
195
+ }
196
+ ```
197
+
198
+ ## Remote MCP (HTTP)
199
+
200
+ Serves **Streamable HTTP** via FastMCP on **`/mcp`** (confirm with your pinned **FastMCP 3.x** version). Health checks: **GET /healthz**.
201
+
202
+ ```bash
203
+ export EDA_API_KEY="eda_live_..."
204
+ easydeploy-ai-mcp-http
205
+ ```
206
+
207
+ Or: `uvicorn easydeploy_ai_mcp.http_main:app --host 0.0.0.0 --port 8080`
208
+
209
+ If you embed `mcp.http_app()` in another ASGI app, pass through **`lifespan`** from the FastMCP HTTP app ([FastMCP ASGI](https://gofastmcp.com/deployment/asgi)); `easydeploy_ai_mcp.http_main` already does this for uvicorn.
210
+
211
+ ### Auth modes
212
+
213
+ Pick exactly one (setting both `EDA_OAUTH_ENABLED` and `MCP_SERVICE_TOKEN` raises at import):
214
+
215
+ - **OAuth 2.0 resource server** (multi-tenant): set `EDA_OAUTH_ENABLED=1` plus
216
+ `EDA_COGNITO_USER_POOL_ID` and `EDA_COGNITO_CLIENT_ID`. Install the optional
217
+ extra: `pip install easydeploy-ai-mcp[oauth]`. The server validates incoming
218
+ Cognito **access** JWTs locally against the Cognito JWKS (issuer, signature,
219
+ `exp`, `token_use=='access'`, `client_id`) and forwards the token to the
220
+ EasyDeploy API. EasyDeploy API keys (prefix `eda_live_`) are accepted in the
221
+ same `Authorization: Bearer` header and forwarded as-is — the API is the
222
+ source of truth for revocation. RFC 9728 metadata is published at
223
+ `/.well-known/oauth-protected-resource`; RFC 8414 proxy metadata includes
224
+ **`registration_endpoint`**, and **`POST /oauth/register`** returns the static
225
+ Cognito MCP **`EDA_COGNITO_CLIENT_ID`** (RFC 7591-style, public client). 401
226
+ responses include `WWW-Authenticate: Bearer …` so MCP clients can discover the
227
+ auth server.
228
+ Note: Cognito access tokens carry `client_id`, **not** `aud`; do not configure
229
+ an audience.
230
+ - **Shared-secret gate** (legacy single-tenant): set `MCP_SERVICE_TOKEN`. All
231
+ outbound API calls use the static `EDA_API_KEY`.
232
+ - **No auth**: development only.
233
+
234
+ **Docker — run locally** (same image you deploy to ECS/Fargate; includes `easydeploy-ai-mcp[oauth]`):
235
+
236
+ ```bash
237
+ # Convenience: build + run (reads .env in the repo root if present)
238
+ ./scripts/run_mcp_docker_local.sh
239
+
240
+ # Explicit env vars (no .env)
241
+ ./scripts/run_mcp_docker_local.sh -e EDA_API_KEY="eda_live_..."
242
+
243
+ # Different host port
244
+ PORT=9000 ./scripts/run_mcp_docker_local.sh
245
+ ```
246
+
247
+ **Host on AWS (Fargate + ALB):** build and push this repo’s **Dockerfile** to a container registry, then deploy behind an HTTPS load balancer. Set the env vars listed above on the task/container.
248
+
249
+ Manual equivalent:
250
+
251
+ ```bash
252
+ docker build -t easydeploy-ai-mcp .
253
+ docker run --rm -p 8080:8080 \
254
+ -e EDA_API_KEY="eda_live_..." \
255
+ easydeploy-ai-mcp
256
+ ```
257
+
258
+ ## Documentation
259
+
260
+ - **[docs/claude-getting-started.md](docs/claude-getting-started.md)** — EasyDeploy + Claude: Connectors or local Desktop config JSON
261
+ - **[docs/claude.md](docs/claude.md)** — Claude Connectors vs Claude Code, transports, headers
262
+
263
+ ## REST API reference
264
+
265
+ This MCP server is a thin client over the **EasyDeploy public REST API**. Endpoint behavior, request bodies, and response shapes are defined by **EasyDeploy** (dashboard, product help, and official API materials at [easydeploy.ai](https://easydeploy.ai)). This repo does not duplicate the full OpenAPI spec; it maps those operations to MCP tools.
266
+
267
+ ## Releases and API compatibility
268
+
269
+ **This repository** is the open-source home of the EasyDeploy MCP server. New releases track the **EasyDeploy public REST API** as documented for customers (dashboard and official API materials). If the API adds or changes endpoints, expect corresponding updates here. Contributors should follow [CONTRIBUTING.md](CONTRIBUTING.md) when changing tools or client behavior.
270
+
271
+ ## Development
272
+
273
+ ```bash
274
+ pip install -e ".[dev]"
275
+ pytest
276
+ ```
277
+
278
+ **Optional — real Cognito JWT against the HTTP app** (live JWKS, no mocks): set `EDA_INTEGRATION_COGNITO_ACCESS_TOKEN` plus the same `EDA_COGNITO_*` vars you use for OAuth mode, then run `pytest tests/test_cognito_jwt_integration.py -v`. See the docstring in that file.
279
+
280
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for pull requests and reporting issues.
281
+
282
+ ## Security
283
+
284
+ See [SECURITY.md](SECURITY.md) for vulnerability reporting and deployment notes.
285
+
286
+ ## License
287
+
288
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,252 @@
1
+ # EasyDeploy AI MCP (`easydeploy-ai-mcp`)
2
+
3
+ A [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server that exposes the **[EasyDeploy](https://easydeploy.ai)** public REST API as tools for Claude, Cursor, Claude Code, and other MCP clients.
4
+
5
+ **PyPI package name:** `easydeploy-ai-mcp` · **Import package:** `easydeploy_ai_mcp`
6
+
7
+ ## Contents
8
+
9
+ - [Connect with Claude](#connect-with-claude)
10
+ - [What you get](#what-you-get)
11
+ - [Requirements](#requirements)
12
+ - [Install](#install)
13
+ - [Environment variables](#environment-variables)
14
+ - [Local MCP (stdio)](#local-mcp-stdio)
15
+ - [Remote MCP (HTTP)](#remote-mcp-http)
16
+ - [Documentation](#documentation)
17
+ - [REST API reference](#rest-api-reference)
18
+ - [Releases and API compatibility](#releases-and-api-compatibility)
19
+ - [Development](#development)
20
+ - [Security](#security)
21
+ - [License](#license)
22
+
23
+ ## Connect with Claude
24
+
25
+ ### Option A — Hosted connector (zero setup)
26
+
27
+ The fastest way to use EasyDeploy AI tools in Claude. No installation required.
28
+
29
+ 1. Open **Claude** (web at [claude.ai](https://claude.ai) or Claude Desktop).
30
+ 2. Go to **Settings → Connectors → Add custom connector**.
31
+ 3. Fill in the form:
32
+ - **Name:** `EasyDeploy AI`
33
+ - **URL:** `https://mcp.easydeploy.ai/mcp`
34
+ 4. Complete the OAuth sign-in flow when prompted. Claude will redirect you to EasyDeploy to authenticate with your account.
35
+ 5. Save the connector. EasyDeploy tools will appear in your Claude sessions.
36
+
37
+ > **Note:** The hosted connector uses OAuth — you sign in with your EasyDeploy account; no API key needs to be pasted into Claude.
38
+
39
+ ---
40
+
41
+ ### Option B — Self-hosted (local stdio)
42
+
43
+ Run the MCP server on your own machine using your EasyDeploy API key. Nothing is exposed to the internet.
44
+
45
+ **1. Install**
46
+
47
+ ```bash
48
+ pip install easydeploy-ai-mcp
49
+ ```
50
+
51
+ **2. Add to Claude Desktop config**
52
+
53
+ Edit (or create) the Claude Desktop config file:
54
+
55
+ | OS | Path |
56
+ | ------- | ---- |
57
+ | macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` |
58
+ | Windows | `%APPDATA%\Claude\claude_desktop_config.json` |
59
+
60
+ Merge the following into the root of that JSON (keep any existing keys):
61
+
62
+ ```json
63
+ {
64
+ "mcpServers": {
65
+ "EasyDeploy AI": {
66
+ "command": "easydeploy-ai-mcp-stdio",
67
+ "env": {
68
+ "EDA_API_KEY": "eda_live_YOUR_KEY"
69
+ }
70
+ }
71
+ }
72
+ }
73
+ ```
74
+
75
+ Replace `eda_live_YOUR_KEY` with your key from **Account → API Keys** in the EasyDeploy dashboard. Use the full path to `easydeploy-ai-mcp-stdio` (run `which easydeploy-ai-mcp-stdio` to find it) if Claude cannot locate it on your `PATH`.
76
+
77
+ **3. Restart Claude Desktop**
78
+
79
+ Fully quit and reopen the app. **EasyDeploy AI** will appear in your MCP servers.
80
+
81
+ ---
82
+
83
+ For self-hosting on Docker or a cloud provider, see [Remote MCP (HTTP)](#remote-mcp-http).
84
+
85
+ ## What you get
86
+
87
+ - **24 tools** covering projects, datasets (including upload flow), model versions, training jobs, predictions, and account status.
88
+ - **stdio** transport for local clients, or **HTTP** with Streamable MCP on `/mcp` and **GET /healthz** for load balancers.
89
+ - **Hardening:** HTTPS-only calls to the EasyDeploy API; optional `MCP_SERVICE_TOKEN` for the HTTP MCP surface; response fields trimmed where appropriate for agents.
90
+
91
+ For **production** and **SOC 2–sensitive** setups, prefer self-hosting so your data stays within your own infrastructure. The hosted connector at `https://mcp.easydeploy.ai/mcp` is fine for most users.
92
+
93
+ ## Requirements
94
+
95
+ - Python **3.10+**
96
+ - An EasyDeploy **API key** from the dashboard (**Account → API Keys**). The client uses the production EasyDeploy API host by default.
97
+
98
+ ## Install
99
+
100
+ ### From PyPI (after first release)
101
+
102
+ ```bash
103
+ pip install easydeploy-ai-mcp
104
+ ```
105
+
106
+ ### From source
107
+
108
+ ```bash
109
+ git clone https://github.com/easydeploy-ai/easydeploy-ai-mcp.git
110
+ cd easydeploy-ai-mcp
111
+ pip install -e ".[dev]" # includes pytest
112
+ # or minimal runtime only:
113
+ pip install .
114
+ ```
115
+
116
+ ## Environment variables
117
+
118
+
119
+ | Variable | Required | Description |
120
+ | ---------------------------------- | -------- | ----------------------------------------------------------------------------------------------- |
121
+ | `EDA_API_KEY` | stdio / legacy HTTP | Required for **stdio** and **legacy** HTTP (no OAuth). **Not** used for outbound API calls when `EDA_OAUTH_ENABLED=1` — each MCP request must include `Authorization: Bearer <JWT or eda_live_…>`. |
122
+ | `EDA_API_BASE` | No | Overrides the default production API (`https://api.easydeploy.ai`). Set only when targeting a non-production endpoint. Trailing `/v1` is optional. |
123
+ | `EDA_UI_BASE_URL` | No | Prefix for `ui_url` fields (default `https://easydeploy.ai`). |
124
+ | `MCP_SERVICE_TOKEN` | No | Legacy single-tenant gate. If set, HTTP mode requires `Authorization: Bearer <token>` for `/mcp` (not for `GET /healthz`). Mutually exclusive with `EDA_OAUTH_ENABLED`. |
125
+ | `EDA_OAUTH_ENABLED` | No | Set to `1` to run the HTTP transport as an OAuth 2.0 resource server. Requires `EDA_COGNITO_USER_POOL_ID` and `EDA_COGNITO_CLIENT_ID`. See [Remote MCP (HTTP)](#remote-mcp-http). |
126
+ | `EDA_COGNITO_USER_POOL_ID` | OAuth | Cognito user pool that issues access tokens for the EasyDeploy API. |
127
+ | `EDA_COGNITO_CLIENT_ID` | OAuth | App client ID expected in the access token's `client_id` claim. |
128
+ | `EDA_COGNITO_REGION` | No | AWS region for the user pool (default `us-east-1`). |
129
+ | `EDA_REPORT_MAX_WAIT_SECONDS` | No | `get_model_report` poll budget (default `300`). |
130
+ | `EDA_REPORT_POLL_INTERVAL_SECONDS` | No | Poll interval in seconds (default `10`). |
131
+ | `HOST` / `PORT` | No | HTTP bind (defaults `0.0.0.0` / `8080`). |
132
+ | `EDA_TRUST_FORWARDED_HEADERS` | No | Set to `1` behind ALB/reverse proxy so RFC 9728 `resource` uses `https` (trusts `X-Forwarded-Proto`). |
133
+ | `EDA_MCP_OAUTH_ISSUER` | No | Public MCP base URL (no path) for `authorization_servers` and proxy `/.well-known/oauth-authorization-server` **`issuer`**. Default: request origin. Use if `Host` / `X-Forwarded-Proto` are wrong behind a proxy. |
134
+
135
+
136
+ ## Local MCP (stdio)
137
+
138
+ Use when the client **starts** the server as a subprocess (Claude Desktop, Cursor, etc.).
139
+
140
+ ```bash
141
+ export EDA_API_KEY="eda_live_..."
142
+ easydeploy-ai-mcp-stdio
143
+ ```
144
+
145
+ Or: `python -m easydeploy_ai_mcp`
146
+
147
+ Example config snippet:
148
+
149
+ ```json
150
+ {
151
+ "mcpServers": {
152
+ "easydeploy-ai": {
153
+ "command": "easydeploy-ai-mcp-stdio",
154
+ "env": {
155
+ "EDA_API_KEY": "eda_live_..."
156
+ }
157
+ }
158
+ }
159
+ }
160
+ ```
161
+
162
+ ## Remote MCP (HTTP)
163
+
164
+ Serves **Streamable HTTP** via FastMCP on **`/mcp`** (confirm with your pinned **FastMCP 3.x** version). Health checks: **GET /healthz**.
165
+
166
+ ```bash
167
+ export EDA_API_KEY="eda_live_..."
168
+ easydeploy-ai-mcp-http
169
+ ```
170
+
171
+ Or: `uvicorn easydeploy_ai_mcp.http_main:app --host 0.0.0.0 --port 8080`
172
+
173
+ If you embed `mcp.http_app()` in another ASGI app, pass through **`lifespan`** from the FastMCP HTTP app ([FastMCP ASGI](https://gofastmcp.com/deployment/asgi)); `easydeploy_ai_mcp.http_main` already does this for uvicorn.
174
+
175
+ ### Auth modes
176
+
177
+ Pick exactly one (setting both `EDA_OAUTH_ENABLED` and `MCP_SERVICE_TOKEN` raises at import):
178
+
179
+ - **OAuth 2.0 resource server** (multi-tenant): set `EDA_OAUTH_ENABLED=1` plus
180
+ `EDA_COGNITO_USER_POOL_ID` and `EDA_COGNITO_CLIENT_ID`. Install the optional
181
+ extra: `pip install easydeploy-ai-mcp[oauth]`. The server validates incoming
182
+ Cognito **access** JWTs locally against the Cognito JWKS (issuer, signature,
183
+ `exp`, `token_use=='access'`, `client_id`) and forwards the token to the
184
+ EasyDeploy API. EasyDeploy API keys (prefix `eda_live_`) are accepted in the
185
+ same `Authorization: Bearer` header and forwarded as-is — the API is the
186
+ source of truth for revocation. RFC 9728 metadata is published at
187
+ `/.well-known/oauth-protected-resource`; RFC 8414 proxy metadata includes
188
+ **`registration_endpoint`**, and **`POST /oauth/register`** returns the static
189
+ Cognito MCP **`EDA_COGNITO_CLIENT_ID`** (RFC 7591-style, public client). 401
190
+ responses include `WWW-Authenticate: Bearer …` so MCP clients can discover the
191
+ auth server.
192
+ Note: Cognito access tokens carry `client_id`, **not** `aud`; do not configure
193
+ an audience.
194
+ - **Shared-secret gate** (legacy single-tenant): set `MCP_SERVICE_TOKEN`. All
195
+ outbound API calls use the static `EDA_API_KEY`.
196
+ - **No auth**: development only.
197
+
198
+ **Docker — run locally** (same image you deploy to ECS/Fargate; includes `easydeploy-ai-mcp[oauth]`):
199
+
200
+ ```bash
201
+ # Convenience: build + run (reads .env in the repo root if present)
202
+ ./scripts/run_mcp_docker_local.sh
203
+
204
+ # Explicit env vars (no .env)
205
+ ./scripts/run_mcp_docker_local.sh -e EDA_API_KEY="eda_live_..."
206
+
207
+ # Different host port
208
+ PORT=9000 ./scripts/run_mcp_docker_local.sh
209
+ ```
210
+
211
+ **Host on AWS (Fargate + ALB):** build and push this repo’s **Dockerfile** to a container registry, then deploy behind an HTTPS load balancer. Set the env vars listed above on the task/container.
212
+
213
+ Manual equivalent:
214
+
215
+ ```bash
216
+ docker build -t easydeploy-ai-mcp .
217
+ docker run --rm -p 8080:8080 \
218
+ -e EDA_API_KEY="eda_live_..." \
219
+ easydeploy-ai-mcp
220
+ ```
221
+
222
+ ## Documentation
223
+
224
+ - **[docs/claude-getting-started.md](docs/claude-getting-started.md)** — EasyDeploy + Claude: Connectors or local Desktop config JSON
225
+ - **[docs/claude.md](docs/claude.md)** — Claude Connectors vs Claude Code, transports, headers
226
+
227
+ ## REST API reference
228
+
229
+ This MCP server is a thin client over the **EasyDeploy public REST API**. Endpoint behavior, request bodies, and response shapes are defined by **EasyDeploy** (dashboard, product help, and official API materials at [easydeploy.ai](https://easydeploy.ai)). This repo does not duplicate the full OpenAPI spec; it maps those operations to MCP tools.
230
+
231
+ ## Releases and API compatibility
232
+
233
+ **This repository** is the open-source home of the EasyDeploy MCP server. New releases track the **EasyDeploy public REST API** as documented for customers (dashboard and official API materials). If the API adds or changes endpoints, expect corresponding updates here. Contributors should follow [CONTRIBUTING.md](CONTRIBUTING.md) when changing tools or client behavior.
234
+
235
+ ## Development
236
+
237
+ ```bash
238
+ pip install -e ".[dev]"
239
+ pytest
240
+ ```
241
+
242
+ **Optional — real Cognito JWT against the HTTP app** (live JWKS, no mocks): set `EDA_INTEGRATION_COGNITO_ACCESS_TOKEN` plus the same `EDA_COGNITO_*` vars you use for OAuth mode, then run `pytest tests/test_cognito_jwt_integration.py -v`. See the docstring in that file.
243
+
244
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for pull requests and reporting issues.
245
+
246
+ ## Security
247
+
248
+ See [SECURITY.md](SECURITY.md) for vulnerability reporting and deployment notes.
249
+
250
+ ## License
251
+
252
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,64 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "easydeploy-ai-mcp"
7
+ version = "0.1.0"
8
+ description = "EasyDeploy AI MCP server — REST API tools for Claude and other MCP clients"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "EasyDeploy AI" }]
13
+ keywords = ["mcp", "easydeploy", "llm", "claude", "automl"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3.10",
20
+ "Programming Language :: Python :: 3.11",
21
+ "Programming Language :: Python :: 3.12",
22
+ "Programming Language :: Python :: 3.13",
23
+ "Programming Language :: Python :: 3.14",
24
+ ]
25
+
26
+ dependencies = [
27
+ "fastmcp>=3.1.1,<4",
28
+ "httpx>=0.27,<1",
29
+ "python-dotenv>=1.1.0",
30
+ "uvicorn[standard]>=0.30,<1",
31
+ ]
32
+
33
+ [project.optional-dependencies]
34
+ oauth = [
35
+ "pyjwt[crypto]>=2.8,<3",
36
+ ]
37
+ dev = [
38
+ "pytest>=8.2,<10",
39
+ "pytest-asyncio>=0.24.0",
40
+ "pyjwt[crypto]>=2.8,<3",
41
+ "certifi>=2024.0.0",
42
+ ]
43
+
44
+ [project.scripts]
45
+ easydeploy-ai-mcp-stdio = "easydeploy_ai_mcp.cli:run_stdio"
46
+ easydeploy-ai-mcp-http = "easydeploy_ai_mcp.cli:run_http"
47
+
48
+ [project.urls]
49
+ Homepage = "https://easydeploy.ai"
50
+ Documentation = "https://github.com/easydeploy-ai/easydeploy-ai-mcp#readme"
51
+ Repository = "https://github.com/easydeploy-ai/easydeploy-ai-mcp"
52
+ Issues = "https://github.com/easydeploy-ai/easydeploy-ai-mcp/issues"
53
+
54
+ [tool.setuptools.packages.find]
55
+ where = ["src"]
56
+
57
+ [tool.pytest.ini_options]
58
+ asyncio_mode = "auto"
59
+ asyncio_default_fixture_loop_scope = "function"
60
+ pythonpath = ["src"]
61
+ testpaths = ["tests"]
62
+ markers = [
63
+ "integration: optional tests that need a real Cognito access JWT and network (see test_cognito_jwt_integration.py)",
64
+ ]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,7 @@
1
+ """EasyDeploy AI MCP server — REST tools for the EasyDeploy public API."""
2
+
3
+ from easydeploy_ai_mcp.server import EDA_MCP_TOOL_NAMES, mcp
4
+
5
+ __all__ = ["mcp", "EDA_MCP_TOOL_NAMES", "__version__"]
6
+
7
+ __version__ = "0.1.0"
@@ -0,0 +1,6 @@
1
+ """python -m easydeploy_ai_mcp → stdio MCP server."""
2
+
3
+ from easydeploy_ai_mcp.cli import run_stdio
4
+
5
+ if __name__ == "__main__":
6
+ run_stdio()