ultralytics-mcp 0.1.6 → 0.1.7
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.
- package/README.md +92 -10
- package/TOOLS.md +2 -0
- package/dist/tools/downloads.js +32 -4
- package/dist/tools/index.js +18 -18
- package/package.json +9 -3
package/README.md
CHANGED
|
@@ -19,8 +19,6 @@ dataset uploads.
|
|
|
19
19
|
- [Get API Key](#get-api-key)
|
|
20
20
|
- [Environment Variables](#environment-variables)
|
|
21
21
|
- [Installation](#installation)
|
|
22
|
-
- [Claude Code](#claude-code)
|
|
23
|
-
- [Codex](#codex)
|
|
24
22
|
- [Verify Setup](#verify-setup)
|
|
25
23
|
- [What You Can Do](#what-you-can-do)
|
|
26
24
|
- [Tools](#tools)
|
|
@@ -61,7 +59,7 @@ Works in many MCP clients that accept JSON stdio server definitions.
|
|
|
61
59
|
"mcpServers": {
|
|
62
60
|
"ultralytics": {
|
|
63
61
|
"command": "npx",
|
|
64
|
-
"args": ["-y", "ultralytics-mcp"],
|
|
62
|
+
"args": ["-y", "ultralytics-mcp@latest"],
|
|
65
63
|
"env": {
|
|
66
64
|
"ULTRALYTICS_API_KEY": "ul_your_api_key_here"
|
|
67
65
|
}
|
|
@@ -70,12 +68,34 @@ Works in many MCP clients that accept JSON stdio server definitions.
|
|
|
70
68
|
}
|
|
71
69
|
```
|
|
72
70
|
|
|
73
|
-
|
|
71
|
+
<details>
|
|
72
|
+
<summary>Antigravity</summary>
|
|
73
|
+
|
|
74
|
+
Add via the Antigravity settings or by updating your configuration file:
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"mcpServers": {
|
|
79
|
+
"ultralytics": {
|
|
80
|
+
"command": "npx",
|
|
81
|
+
"args": ["-y", "ultralytics-mcp@latest"],
|
|
82
|
+
"env": {
|
|
83
|
+
"ULTRALYTICS_API_KEY": "ul_your_api_key_here"
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
</details>
|
|
91
|
+
|
|
92
|
+
<details>
|
|
93
|
+
<summary>Claude Code</summary>
|
|
74
94
|
|
|
75
95
|
Add server with Claude Code CLI:
|
|
76
96
|
|
|
77
97
|
```bash
|
|
78
|
-
claude mcp add ultralytics --env ULTRALYTICS_API_KEY=ul_your_api_key_here -- npx -y ultralytics-mcp
|
|
98
|
+
claude mcp add ultralytics --env ULTRALYTICS_API_KEY=ul_your_api_key_here -- npx -y ultralytics-mcp@latest
|
|
79
99
|
```
|
|
80
100
|
|
|
81
101
|
Or add a project-scoped server in repo-root `.mcp.json`:
|
|
@@ -85,7 +105,7 @@ Or add a project-scoped server in repo-root `.mcp.json`:
|
|
|
85
105
|
"mcpServers": {
|
|
86
106
|
"ultralytics": {
|
|
87
107
|
"command": "npx",
|
|
88
|
-
"args": ["-y", "ultralytics-mcp"],
|
|
108
|
+
"args": ["-y", "ultralytics-mcp@latest"],
|
|
89
109
|
"env": {
|
|
90
110
|
"ULTRALYTICS_API_KEY": "ul_your_api_key_here"
|
|
91
111
|
}
|
|
@@ -94,12 +114,22 @@ Or add a project-scoped server in repo-root `.mcp.json`:
|
|
|
94
114
|
}
|
|
95
115
|
```
|
|
96
116
|
|
|
97
|
-
|
|
117
|
+
</details>
|
|
118
|
+
|
|
119
|
+
<details>
|
|
120
|
+
<summary>Claude Desktop</summary>
|
|
121
|
+
|
|
122
|
+
Follow the MCP install [guide](https://modelcontextprotocol.io/quickstart/user), use the standard config above.
|
|
123
|
+
|
|
124
|
+
</details>
|
|
125
|
+
|
|
126
|
+
<details>
|
|
127
|
+
<summary>Codex</summary>
|
|
98
128
|
|
|
99
129
|
Add server with Codex CLI:
|
|
100
130
|
|
|
101
131
|
```bash
|
|
102
|
-
codex mcp add ultralytics --env ULTRALYTICS_API_KEY=ul_your_api_key_here -- npx -y ultralytics-mcp
|
|
132
|
+
codex mcp add ultralytics --env ULTRALYTICS_API_KEY=ul_your_api_key_here -- npx -y ultralytics-mcp@latest
|
|
103
133
|
```
|
|
104
134
|
|
|
105
135
|
Or add it directly to `~/.codex/config.toml`:
|
|
@@ -107,12 +137,62 @@ Or add it directly to `~/.codex/config.toml`:
|
|
|
107
137
|
```toml
|
|
108
138
|
[mcp_servers.ultralytics]
|
|
109
139
|
command = "npx"
|
|
110
|
-
args = ["-y", "ultralytics-mcp"]
|
|
140
|
+
args = ["-y", "ultralytics-mcp@latest"]
|
|
111
141
|
|
|
112
142
|
[mcp_servers.ultralytics.env]
|
|
113
143
|
ULTRALYTICS_API_KEY = "ul_your_api_key_here"
|
|
114
144
|
```
|
|
115
145
|
|
|
146
|
+
</details>
|
|
147
|
+
|
|
148
|
+
<details>
|
|
149
|
+
<summary>Cursor</summary>
|
|
150
|
+
|
|
151
|
+
#### Click the button to install:
|
|
152
|
+
|
|
153
|
+
[<img src="https://cursor.com/deeplink/mcp-install-dark.svg" alt="Install in Cursor">](https://cursor.com/en/install-mcp?name=ultralytics&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsInVsdHJhbHl0aWNzLW1jcEBsYXRlc3QiXSwiZW52Ijp7IlVMVFJBTFlUSUNTX0FQSV9LRVkiOiJ1bF95b3VyX2FwaV9rZXlfaGVyZSJ9fQ%3D%3D)
|
|
154
|
+
|
|
155
|
+
> **Important**
|
|
156
|
+
> The install button writes a placeholder key. After installing, open your Cursor MCP config and replace `ul_your_api_key_here` with your Ultralytics API key, then restart Cursor.
|
|
157
|
+
|
|
158
|
+
#### Or install manually:
|
|
159
|
+
|
|
160
|
+
Go to `Cursor Settings` -> `MCP` -> `Add new MCP Server` (or edit `~/.cursor/mcp.json` directly) and use the standard config above: `command` set to `npx`, `args` set to `["-y", "ultralytics-mcp@latest"]`, and `ULTRALYTICS_API_KEY` in `env`.
|
|
161
|
+
|
|
162
|
+
</details>
|
|
163
|
+
|
|
164
|
+
<details>
|
|
165
|
+
<summary>Gemini CLI</summary>
|
|
166
|
+
|
|
167
|
+
Follow the MCP install [guide](https://github.com/google-gemini/gemini-cli/blob/main/docs/tools/mcp-server.md#configure-the-mcp-server-in-settingsjson), use the standard config above.
|
|
168
|
+
|
|
169
|
+
</details>
|
|
170
|
+
|
|
171
|
+
<details>
|
|
172
|
+
<summary>VS Code / Copilot</summary>
|
|
173
|
+
|
|
174
|
+
#### Click the button to install:
|
|
175
|
+
|
|
176
|
+
[<img src="https://img.shields.io/badge/VS_Code-VS_Code?style=flat-square&label=Install%20Server&color=0098FF" alt="Install in VS Code">](https://insiders.vscode.dev/redirect?url=vscode%3Amcp%2Finstall%3F%257B%2522name%2522%253A%2522ultralytics%2522%252C%2522command%2522%253A%2522npx%2522%252C%2522args%2522%253A%255B%2522-y%2522%252C%2522ultralytics-mcp%2540latest%2522%255D%252C%2522env%2522%253A%257B%2522ULTRALYTICS_API_KEY%2522%253A%2522ul_your_api_key_here%2522%257D%257D)
|
|
177
|
+
|
|
178
|
+
> **Important**
|
|
179
|
+
> The install button writes a placeholder key. After installing, open your VS Code MCP config and replace `ul_your_api_key_here` with your Ultralytics API key, then restart VS Code.
|
|
180
|
+
|
|
181
|
+
#### Or install manually:
|
|
182
|
+
|
|
183
|
+
Follow the MCP install [guide](https://code.visualstudio.com/docs/copilot/chat/mcp-servers#_add-an-mcp-server), use the standard config above. You can also install the server using the VS Code CLI:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
# For VS Code
|
|
187
|
+
code --add-mcp '{"name":"ultralytics","command":"npx","args":["-y","ultralytics-mcp@latest"],"env":{"ULTRALYTICS_API_KEY":"ul_your_api_key_here"}}'
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
After installation, the Ultralytics MCP server will be available for use with your GitHub Copilot agent in VS Code.
|
|
191
|
+
|
|
192
|
+
</details>
|
|
193
|
+
|
|
194
|
+
These examples track latest published npm release. Restart MCP client or session after upgrading so new server process picks up latest package.
|
|
195
|
+
|
|
116
196
|
## Verify Setup
|
|
117
197
|
|
|
118
198
|
### Claude Code
|
|
@@ -161,6 +241,8 @@ See [TOOLS.md](./TOOLS.md) for full parameter reference, safety notes, local-pat
|
|
|
161
241
|
- `training_start` requires `confirm_cost: true`
|
|
162
242
|
- Ambiguous project or dataset refs fail instead of guessing
|
|
163
243
|
- Signed upload and download URLs do not forward `Authorization`
|
|
244
|
+
- Local upload tools read files from the MCP client host; approve calls only for paths you expect to share with Ultralytics
|
|
245
|
+
- `model_download` writes to the requested local path; review `output_path` and `overwrite` before approving
|
|
164
246
|
|
|
165
247
|
## Troubleshooting
|
|
166
248
|
|
|
@@ -185,7 +267,7 @@ characters after prefix.
|
|
|
185
267
|
### Manual server smoke test
|
|
186
268
|
|
|
187
269
|
```bash
|
|
188
|
-
ULTRALYTICS_API_KEY=ul_your_api_key_here npx -y ultralytics-mcp
|
|
270
|
+
ULTRALYTICS_API_KEY=ul_your_api_key_here npx -y ultralytics-mcp@latest
|
|
189
271
|
```
|
|
190
272
|
|
|
191
273
|
If command exits immediately with config error, fix environment first.
|
package/TOOLS.md
CHANGED
|
@@ -16,6 +16,8 @@ Auto-generated reference for Ultralytics Platform MCP tools.
|
|
|
16
16
|
- `dataset_upload_folder` uploads a local image folder.
|
|
17
17
|
- `dataset_upload_video` extracts frames from a local video file with `ffmpeg`.
|
|
18
18
|
- `model_download` writes model weights to a local destination path.
|
|
19
|
+
- Review local upload paths before approving tool calls; upload tools read from the MCP client host.
|
|
20
|
+
- Review `model_download.output_path` and `overwrite` before approving downloads.
|
|
19
21
|
|
|
20
22
|
## Cost and Safety
|
|
21
23
|
|
package/dist/tools/downloads.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/** Model weight download tool. Writes to an explicit local path; the signed-URL
|
|
2
2
|
* fetch never forwards API credentials (handled by client.downloadBytes).
|
|
3
3
|
*/
|
|
4
|
-
import { stat, writeFile } from "node:fs/promises";
|
|
4
|
+
import { lstat, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
5
5
|
import { homedir } from "node:os";
|
|
6
|
-
import { dirname, join, resolve } from "node:path";
|
|
6
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
7
7
|
import { resolveModel } from "../resolve.js";
|
|
8
8
|
import { asRecord } from "./shared.js";
|
|
9
9
|
function fileName(info) {
|
|
@@ -59,6 +59,31 @@ async function statSafe(target) {
|
|
|
59
59
|
return { exists: false, isDir: false };
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
|
+
async function lstatSafe(target) {
|
|
63
|
+
try {
|
|
64
|
+
const info = await lstat(target);
|
|
65
|
+
return {
|
|
66
|
+
exists: true,
|
|
67
|
+
isDir: info.isDirectory(),
|
|
68
|
+
isSymlink: info.isSymbolicLink(),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return { exists: false, isDir: false, isSymlink: false };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async function writeFileAtomic(target, content) {
|
|
76
|
+
const parent = dirname(target);
|
|
77
|
+
const temporary = join(parent, `.${basename(target)}.${process.pid}.${Date.now()}.tmp`);
|
|
78
|
+
try {
|
|
79
|
+
await writeFile(temporary, content, { flag: "wx" });
|
|
80
|
+
await rename(temporary, target);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
await rm(temporary, { force: true }).catch(() => undefined);
|
|
84
|
+
throw error;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
62
87
|
async function downloadTarget(outputPath, overwrite) {
|
|
63
88
|
if (!outputPath?.trim()) {
|
|
64
89
|
throw new Error("`output_path` is required.");
|
|
@@ -72,10 +97,13 @@ async function downloadTarget(outputPath, overwrite) {
|
|
|
72
97
|
if (!parentInfo.isDir) {
|
|
73
98
|
throw new Error(`Output parent is not a directory: ${parent}`);
|
|
74
99
|
}
|
|
75
|
-
const targetInfo = await
|
|
100
|
+
const targetInfo = await lstatSafe(target);
|
|
76
101
|
if (targetInfo.exists && targetInfo.isDir) {
|
|
77
102
|
throw new Error(`Output path is a directory: ${target}`);
|
|
78
103
|
}
|
|
104
|
+
if (targetInfo.exists && targetInfo.isSymlink) {
|
|
105
|
+
throw new Error(`Output path is a symbolic link: ${target}`);
|
|
106
|
+
}
|
|
79
107
|
if (targetInfo.exists && !overwrite) {
|
|
80
108
|
throw new Error(`Output path exists: ${target}. Pass overwrite=true to replace it.`);
|
|
81
109
|
}
|
|
@@ -94,7 +122,7 @@ export async function modelDownload(client, model, options) {
|
|
|
94
122
|
throw new Error(`Model file '${selectedName}' did not include a download URL.`);
|
|
95
123
|
}
|
|
96
124
|
const content = await client.downloadBytes(signedUrl);
|
|
97
|
-
await
|
|
125
|
+
await writeFileAtomic(target, content);
|
|
98
126
|
return {
|
|
99
127
|
summary: `Downloaded ${selectedName} to ${target} (${content.length} bytes).`,
|
|
100
128
|
data: {
|
package/dist/tools/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/** Tool registration for the MCP server.
|
|
2
2
|
*
|
|
3
3
|
* Logic functions live in the sibling modules and are re-exported for tests and
|
|
4
|
-
* the parity fixture runner.
|
|
5
|
-
* with Zod input schemas. User-facing tool names stay snake_case for
|
|
6
|
-
* the Python package.
|
|
4
|
+
* the parity fixture runner. Registration helpers wire tools onto an
|
|
5
|
+
* `McpServer` with Zod input schemas. User-facing tool names stay snake_case for
|
|
6
|
+
* parity with the Python package.
|
|
7
7
|
*/
|
|
8
8
|
import { z } from "zod";
|
|
9
9
|
import { toMcpTextResult } from "../tool-result.js";
|
|
@@ -72,7 +72,7 @@ export const TOOL_DEFINITIONS = [
|
|
|
72
72
|
}),
|
|
73
73
|
tool({
|
|
74
74
|
name: "projects_create",
|
|
75
|
-
registrationGroup: "
|
|
75
|
+
registrationGroup: "write",
|
|
76
76
|
stateChanging: true,
|
|
77
77
|
description: "Create a project in your Ultralytics workspace.",
|
|
78
78
|
inputSchema: {
|
|
@@ -93,7 +93,7 @@ export const TOOL_DEFINITIONS = [
|
|
|
93
93
|
}),
|
|
94
94
|
tool({
|
|
95
95
|
name: "projects_delete",
|
|
96
|
-
registrationGroup: "
|
|
96
|
+
registrationGroup: "write",
|
|
97
97
|
stateChanging: true,
|
|
98
98
|
description: "Soft-delete a project by id, slug, username/slug, or project ul:// URI.",
|
|
99
99
|
inputSchema: {
|
|
@@ -155,7 +155,7 @@ export const TOOL_DEFINITIONS = [
|
|
|
155
155
|
}),
|
|
156
156
|
tool({
|
|
157
157
|
name: "datasets_create",
|
|
158
|
-
registrationGroup: "
|
|
158
|
+
registrationGroup: "write",
|
|
159
159
|
stateChanging: true,
|
|
160
160
|
description: "Create a dataset in your Ultralytics workspace.",
|
|
161
161
|
inputSchema: {
|
|
@@ -230,7 +230,7 @@ export const TOOL_DEFINITIONS = [
|
|
|
230
230
|
}),
|
|
231
231
|
tool({
|
|
232
232
|
name: "dataset_version_create",
|
|
233
|
-
registrationGroup: "
|
|
233
|
+
registrationGroup: "write",
|
|
234
234
|
stateChanging: true,
|
|
235
235
|
description: "Create a frozen dataset version snapshot.",
|
|
236
236
|
inputSchema: {
|
|
@@ -251,7 +251,7 @@ export const TOOL_DEFINITIONS = [
|
|
|
251
251
|
}),
|
|
252
252
|
tool({
|
|
253
253
|
name: "datasets_delete",
|
|
254
|
-
registrationGroup: "
|
|
254
|
+
registrationGroup: "write",
|
|
255
255
|
stateChanging: true,
|
|
256
256
|
description: "Soft-delete a dataset by id, slug, username/slug, or dataset ul:// URI.",
|
|
257
257
|
inputSchema: {
|
|
@@ -268,7 +268,7 @@ export const TOOL_DEFINITIONS = [
|
|
|
268
268
|
}),
|
|
269
269
|
tool({
|
|
270
270
|
name: "dataset_ingest",
|
|
271
|
-
registrationGroup: "
|
|
271
|
+
registrationGroup: "write",
|
|
272
272
|
stateChanging: true,
|
|
273
273
|
description: "Start a remote URL ingest job for an existing dataset.",
|
|
274
274
|
inputSchema: {
|
|
@@ -292,7 +292,7 @@ export const TOOL_DEFINITIONS = [
|
|
|
292
292
|
}),
|
|
293
293
|
tool({
|
|
294
294
|
name: "dataset_upload_file",
|
|
295
|
-
registrationGroup: "
|
|
295
|
+
registrationGroup: "write",
|
|
296
296
|
stateChanging: true,
|
|
297
297
|
description: "Upload a local dataset archive file and start ingest for an existing dataset.",
|
|
298
298
|
inputSchema: {
|
|
@@ -326,7 +326,7 @@ export const TOOL_DEFINITIONS = [
|
|
|
326
326
|
}),
|
|
327
327
|
tool({
|
|
328
328
|
name: "dataset_upload_folder",
|
|
329
|
-
registrationGroup: "
|
|
329
|
+
registrationGroup: "write",
|
|
330
330
|
stateChanging: true,
|
|
331
331
|
description: "Upload a local image folder as a zip and start ingest for an existing dataset.",
|
|
332
332
|
inputSchema: {
|
|
@@ -360,7 +360,7 @@ export const TOOL_DEFINITIONS = [
|
|
|
360
360
|
}),
|
|
361
361
|
tool({
|
|
362
362
|
name: "dataset_upload_video",
|
|
363
|
-
registrationGroup: "
|
|
363
|
+
registrationGroup: "write",
|
|
364
364
|
stateChanging: true,
|
|
365
365
|
description: "Upload a local video by extracting JPEG frames with ffmpeg, then start dataset ingest for an existing dataset.",
|
|
366
366
|
inputSchema: {
|
|
@@ -443,7 +443,7 @@ export const TOOL_DEFINITIONS = [
|
|
|
443
443
|
}),
|
|
444
444
|
tool({
|
|
445
445
|
name: "training_monitor",
|
|
446
|
-
registrationGroup: "
|
|
446
|
+
registrationGroup: "read",
|
|
447
447
|
stateChanging: false,
|
|
448
448
|
description: "Report a model's training status and progress (works for private and public projects).",
|
|
449
449
|
inputSchema: {
|
|
@@ -468,7 +468,7 @@ export const TOOL_DEFINITIONS = [
|
|
|
468
468
|
}),
|
|
469
469
|
tool({
|
|
470
470
|
name: "model_predict",
|
|
471
|
-
registrationGroup: "
|
|
471
|
+
registrationGroup: "read",
|
|
472
472
|
stateChanging: false,
|
|
473
473
|
description: "Run inference with a trained model on an image URL or base64 source (no local file paths).",
|
|
474
474
|
inputSchema: {
|
|
@@ -554,7 +554,7 @@ export const TOOL_DEFINITIONS = [
|
|
|
554
554
|
}),
|
|
555
555
|
tool({
|
|
556
556
|
name: "exports_list",
|
|
557
|
-
registrationGroup: "
|
|
557
|
+
registrationGroup: "read",
|
|
558
558
|
stateChanging: false,
|
|
559
559
|
description: "List export jobs for a model.",
|
|
560
560
|
inputSchema: {
|
|
@@ -568,7 +568,7 @@ export const TOOL_DEFINITIONS = [
|
|
|
568
568
|
}),
|
|
569
569
|
tool({
|
|
570
570
|
name: "export_status",
|
|
571
|
-
registrationGroup: "
|
|
571
|
+
registrationGroup: "read",
|
|
572
572
|
stateChanging: false,
|
|
573
573
|
description: "Get status for one export job by 24-character export id.",
|
|
574
574
|
inputSchema: {
|
|
@@ -720,11 +720,11 @@ function registerToolDefinitions(server, getClient, registrationGroup) {
|
|
|
720
720
|
export function registerReadTools(server, getClient) {
|
|
721
721
|
registerToolDefinitions(server, getClient, "read");
|
|
722
722
|
}
|
|
723
|
-
/** Register
|
|
723
|
+
/** Register local action tools. */
|
|
724
724
|
export function registerActionTools(server, getClient) {
|
|
725
725
|
registerToolDefinitions(server, getClient, "action");
|
|
726
726
|
}
|
|
727
|
-
/** Register
|
|
727
|
+
/** Register remote mutation tools. The cost-incurring ones are guarded. */
|
|
728
728
|
export function registerWriteTools(server, getClient) {
|
|
729
729
|
registerToolDefinitions(server, getClient, "write");
|
|
730
730
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ultralytics-mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "MCP for Ultralytics Platform workflows, datasets, training, prediction, and model operations.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -37,10 +37,16 @@
|
|
|
37
37
|
"test": "vitest run"
|
|
38
38
|
},
|
|
39
39
|
"keywords": [
|
|
40
|
-
"mcp",
|
|
41
40
|
"ultralytics",
|
|
42
41
|
"yolo",
|
|
43
|
-
"
|
|
42
|
+
"mcp",
|
|
43
|
+
"model-context-protocol",
|
|
44
|
+
"claude",
|
|
45
|
+
"codex",
|
|
46
|
+
"computer-vision",
|
|
47
|
+
"object-detection",
|
|
48
|
+
"model-training",
|
|
49
|
+
"inference"
|
|
44
50
|
],
|
|
45
51
|
"author": "Aman Harsh",
|
|
46
52
|
"license": "MIT",
|