ultralytics-mcp 0.1.2 → 0.1.3

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 CHANGED
@@ -8,18 +8,20 @@ Current milestone: read, monitor, predict, export, and initial project and
8
8
  dataset lifecycle tools are available. Additional resource-management tools
9
9
  land incrementally from here.
10
10
 
11
- ## Tools (20)
11
+ ## Tools (23)
12
12
 
13
13
  | Tool | Description |
14
14
  | --- | --- |
15
15
  | `projects_list` / `projects_get` | Browse projects |
16
16
  | `projects_create` / `projects_delete` | Create / soft-delete projects |
17
- | `datasets_list` / `datasets_get` / `datasets_create` / `datasets_delete` / `dataset_ingest` / `dataset_upload_file` | Browse / create / soft-delete datasets, start remote ingest jobs, and upload archive files |
17
+ | `datasets_list` / `datasets_get` / `datasets_create` / `datasets_delete` / `dataset_images_list` / `dataset_ingest` / `dataset_upload_file` | Browse / create / soft-delete datasets, inspect images, start remote ingest jobs, and upload archive files |
18
18
  | `models_list` / `models_get` | Browse trained models and metrics |
19
19
  | `training_monitor` | Status, progress, and latest metrics |
20
20
  | `model_predict` | Run inference on an image URL or base64 source |
21
21
  | `model_download` | Download a model weight file to a local path |
22
22
  | `gpu_availability` | Cloud GPU stock status |
23
+ | `dataset_export` | Get export link for latest or frozen dataset version |
24
+ | `dataset_version_create` | Create a frozen dataset version snapshot |
23
25
  | `exports_list` / `export_status` | List / check export jobs |
24
26
  | `export_create` | Create an export job — **requires `confirm_cost: true`** |
25
27
  | `training_start` | Start cloud training — **requires `confirm_cost: true`** |
@@ -117,6 +117,72 @@ export async function datasetsCreate(client, options) {
117
117
  data: item,
118
118
  };
119
119
  }
120
+ /** List images in a dataset with optional filtering. */
121
+ export async function datasetImagesList(client, options) {
122
+ if (options.split !== undefined && !TARGET_SPLITS.has(options.split)) {
123
+ const allowed = Array.from(TARGET_SPLITS).sort().join(", ");
124
+ throw new Error(`Unsupported split '${options.split}'. Expected one of: ${allowed}.`);
125
+ }
126
+ if (options.limit !== undefined) {
127
+ if (options.limit <= 0) {
128
+ throw new Error("`limit` must be greater than 0.");
129
+ }
130
+ if (options.limit > 5000) {
131
+ throw new Error("`limit` must be at most 5000.");
132
+ }
133
+ }
134
+ if (options.offset !== undefined && options.offset < 0) {
135
+ throw new Error("`offset` must be greater than or equal to 0.");
136
+ }
137
+ const datasetId = await resolveDataset(client, options.dataset);
138
+ const params = {};
139
+ if (options.split !== undefined) {
140
+ params.split = options.split;
141
+ }
142
+ if (options.search !== undefined) {
143
+ params.search = options.search;
144
+ }
145
+ if (options.hasLabel !== undefined) {
146
+ params.hasLabel = options.hasLabel;
147
+ }
148
+ if (options.classIds && options.classIds.length > 0) {
149
+ params.classIds = options.classIds.join(",");
150
+ }
151
+ if (options.limit !== undefined) {
152
+ params.limit = options.limit;
153
+ }
154
+ if (options.offset !== undefined) {
155
+ params.offset = options.offset;
156
+ }
157
+ if (options.includeImageUrls !== undefined) {
158
+ params.includeImageUrls = options.includeImageUrls;
159
+ }
160
+ const data = await client.get(`/datasets/${datasetId}/images`, Object.keys(params).length > 0 ? params : undefined);
161
+ const record = asRecord(data);
162
+ const images = listField(data, "images").map((image) => ({
163
+ id: image._id ?? image.id ?? null,
164
+ name: image.name ?? null,
165
+ ext: image.ext ?? null,
166
+ split: image.split ?? null,
167
+ width: image.width ?? null,
168
+ height: image.height ?? null,
169
+ labelCount: image.labelCount ?? null,
170
+ bytes: image.bytes ?? null,
171
+ ...(image.imageUrl !== undefined ? { imageUrl: image.imageUrl } : {}),
172
+ ...(image.thumbnailUrl !== undefined
173
+ ? { thumbnailUrl: image.thumbnailUrl }
174
+ : {}),
175
+ }));
176
+ return {
177
+ summary: `${images.length} image(s) (total ${String(record.total ?? null)})`,
178
+ data: {
179
+ total: record.total ?? null,
180
+ hasMore: record.hasMore ?? null,
181
+ nextCursor: record.nextCursor ?? null,
182
+ images,
183
+ },
184
+ };
185
+ }
120
186
  /** Soft-delete a dataset by id, slug, username/slug, or dataset ul:// URI. */
121
187
  export async function datasetsDelete(client, dataset) {
122
188
  const datasetId = await resolveDataset(client, dataset);
@@ -182,3 +248,38 @@ export async function datasetUploadFile(client, options) {
182
248
  },
183
249
  };
184
250
  }
251
+ /** Get dataset export link for latest or one frozen version. */
252
+ export async function datasetExport(client, options) {
253
+ if (options.version !== undefined && options.version <= 0) {
254
+ throw new Error("`version` must be greater than 0.");
255
+ }
256
+ const datasetId = await resolveDataset(client, options.dataset);
257
+ const data = asRecord(await client.get(`/datasets/${datasetId}/export`, options.version !== undefined ? { v: options.version } : undefined));
258
+ const cached = typeof data.cached === "boolean"
259
+ ? String(data.cached)
260
+ : String(data.cached ?? null);
261
+ return {
262
+ summary: `Export link for ${options.dataset} ` +
263
+ `(version ${String(options.version ?? "latest")}, cached=${cached})`,
264
+ data: {
265
+ downloadUrl: data.downloadUrl ?? null,
266
+ cached: data.cached ?? null,
267
+ },
268
+ };
269
+ }
270
+ /** Create frozen dataset export version. */
271
+ export async function datasetVersionCreate(client, options) {
272
+ const datasetId = await resolveDataset(client, options.dataset);
273
+ const payload = {};
274
+ if (options.description !== undefined) {
275
+ payload.description = options.description;
276
+ }
277
+ const data = asRecord(await client.postJson(`/datasets/${datasetId}/export`, payload));
278
+ return {
279
+ summary: `Created dataset version ${String(data.version ?? null)}`,
280
+ data: {
281
+ version: data.version ?? null,
282
+ downloadUrl: data.downloadUrl ?? null,
283
+ },
284
+ };
285
+ }
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import { z } from "zod";
9
9
  import { toMcpTextResult } from "../tool-result.js";
10
- import { datasetsCreate, datasetsDelete, datasetsGet, datasetsIngest, datasetsList, datasetUploadFile, } from "./datasets.js";
10
+ import { datasetExport, datasetImagesList, datasetsCreate, datasetsDelete, datasetsGet, datasetsIngest, datasetsList, datasetUploadFile, datasetVersionCreate, } from "./datasets.js";
11
11
  import { modelDownload } from "./downloads.js";
12
12
  import { exportCreate, exportStatus, exportsList } from "./exports.js";
13
13
  import { gpuAvailability } from "./gpu.js";
@@ -15,7 +15,7 @@ import { modelsGet, modelsList } from "./models.js";
15
15
  import { modelPredict } from "./predict.js";
16
16
  import { projectsCreate, projectsDelete, projectsGet, projectsList, } from "./projects.js";
17
17
  import { trainingMonitor, trainingStart } from "./training.js";
18
- export { datasetsCreate, datasetsDelete, datasetsGet, datasetsIngest, datasetsList, datasetUploadFile, } from "./datasets.js";
18
+ export { datasetExport, datasetImagesList, datasetsCreate, datasetsDelete, datasetsGet, datasetsIngest, datasetsList, datasetUploadFile, datasetVersionCreate, } from "./datasets.js";
19
19
  export { modelDownload } from "./downloads.js";
20
20
  export { exportCreate, exportStatus, exportsList } from "./exports.js";
21
21
  export { gpuAvailability } from "./gpu.js";
@@ -32,6 +32,9 @@ export const READ_TOOL_NAMES = [
32
32
  "datasets_list",
33
33
  "datasets_get",
34
34
  "datasets_create",
35
+ "dataset_images_list",
36
+ "dataset_export",
37
+ "dataset_version_create",
35
38
  "datasets_delete",
36
39
  "dataset_ingest",
37
40
  "dataset_upload_file",
@@ -87,6 +90,42 @@ export function registerReadTools(server, getClient) {
87
90
  visibility,
88
91
  classNames,
89
92
  })));
93
+ server.registerTool("dataset_images_list", {
94
+ description: "List images in a dataset with optional filtering.",
95
+ inputSchema: {
96
+ dataset: z.string(),
97
+ split: z.string().optional(),
98
+ search: z.string().optional(),
99
+ hasLabel: z.boolean().optional(),
100
+ classIds: z.array(z.string()).optional(),
101
+ limit: z.number().optional(),
102
+ offset: z.number().optional(),
103
+ includeImageUrls: z.boolean().optional(),
104
+ },
105
+ }, async ({ dataset, split, search, hasLabel, classIds, limit, offset, includeImageUrls, }) => toMcpTextResult(await datasetImagesList(getClient(), {
106
+ dataset,
107
+ split,
108
+ search,
109
+ hasLabel,
110
+ classIds,
111
+ limit,
112
+ offset,
113
+ includeImageUrls,
114
+ })));
115
+ server.registerTool("dataset_export", {
116
+ description: "Get export link for latest or one frozen dataset version.",
117
+ inputSchema: {
118
+ dataset: z.string(),
119
+ version: z.number().optional(),
120
+ },
121
+ }, async ({ dataset, version }) => toMcpTextResult(await datasetExport(getClient(), { dataset, version })));
122
+ server.registerTool("dataset_version_create", {
123
+ description: "Create a frozen dataset version snapshot.",
124
+ inputSchema: {
125
+ dataset: z.string(),
126
+ description: z.string().optional(),
127
+ },
128
+ }, async ({ dataset, description }) => toMcpTextResult(await datasetVersionCreate(getClient(), { dataset, description })));
90
129
  server.registerTool("datasets_delete", {
91
130
  description: "Soft-delete a dataset by id, slug, username/slug, or dataset ul:// URI.",
92
131
  inputSchema: { dataset: z.string() },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ultralytics-mcp",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "MCP for Ultralytics Platform workflows, datasets, training, prediction, and model operations.",
5
5
  "type": "module",
6
6
  "bin": {