@labelgrid/mcp 0.6.1 → 0.7.0
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/CHANGELOG.md +15 -0
- package/README.md +1 -1
- package/dist/coverage.js +1 -0
- package/dist/projection.js +1 -0
- package/dist/tools/catalog.js +35 -5
- package/package.json +2 -2
- package/server.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,21 @@ All notable changes to `@labelgrid/mcp` are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.7.0] - 2026-08-20
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- `delete_catalog_item` accepts `replace_with` for writers and publishers. The
|
|
13
|
+
replacement receives every credit before the original is deleted. Other
|
|
14
|
+
entity types reject the parameter without sending a delete request.
|
|
15
|
+
- `query_financials` concise responses include `credit_amount`, preserving
|
|
16
|
+
positive, zero and explicit null values from the API.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- Writer and publisher deletion guidance now names all references that can
|
|
21
|
+
block deletion and documents the `REPLACEMENT_UNAVAILABLE` response.
|
|
22
|
+
|
|
8
23
|
## [0.6.1] - 2026-08-05
|
|
9
24
|
|
|
10
25
|
### Changed
|
package/README.md
CHANGED
|
@@ -129,7 +129,7 @@ tool definitions by `npm run gen-docs` — do not edit it by hand._
|
|
|
129
129
|
| `get_catalog_item` | read | Retrieve one catalog entity by id, with full detail (e.g. a release’s metadata and track listing, a track’s contributors and royalty splits, a writer’s PRO/IPI). |
|
|
130
130
|
| `create_catalog_item` | write | Create a catalog entity: pass its attributes in `fields` — the API owns all validation. Required and common fields per entity: label — required: name, default_email; optional: support email, website/platform URLs, default copyright lines, isrc_base. artist — required: artist_name; optional: full_name, email, location, bios, isni, default_language, platform profile URLs. writer — required: first_name, last_name; optional: middle_name, display_credits, email, country, pro, ipi, isni, publisher_id (or publisher_name/publisher_pro/publisher_ipi). publisher — required: name; optional: ipi, pro, isni, controlled_publisher. release — required on create: content_type, label_id, artists, titles, cat (catalog number), artwork_ai_usage, primary_genre_id; many optional fields (dates, copyright lines, genres, per-outlet URLs). track — required on create: release_id, disc, track_num, composition_type, artists, audio_ai_usage, composition_ai_usage, commercial_samples, audio_language, contributors, and recording_country (ISO 3166-1 alpha-2, e.g. "US"); optional: titles, isrc, iswc, writers, publishers, splits, and more. A release is created in DRAFT state — add tracks, then run the release checks before distributing. |
|
|
131
131
|
| `update_catalog_item` | write | Update a catalog entity: supply only the fields to change in `fields` (same field sets as create_catalog_item). Once a release is submitted or distributed, some release and track fields are locked — changing one returns a 403 with code RELEASE_LOCKED_FIELDS naming exactly which fields cannot change. |
|
|
132
|
-
| `delete_catalog_item` | write | Delete a catalog entity. The API refuses deletes that would orphan data — label: refused while the label still has releases — remove or reassign its releases first. artist: refused while still referenced by releases or tracks. writer: refused while still referenced by tracks. publisher: refused while still referenced by
|
|
132
|
+
| `delete_catalog_item` | write | Delete a catalog entity. The API refuses deletes that would orphan data — label: refused while the label still has releases — remove or reassign its releases first. artist: refused while still referenced by releases or tracks. writer: refused while still referenced by tracks or artists, unless replace_with reassigns those credits. publisher: refused while still referenced by tracks or label default publishers, unless replace_with reassigns those credits. release: only a never-submitted draft can be deleted. track: refused once the release is no longer an editable draft. `replace_with` — writer and publisher only — is the id inheriting those credits; a 422 REPLACEMENT_UNAVAILABLE means nothing was deleted. |
|
|
133
133
|
| `upload_image` | write | Upload a label image (logo, dark-mode logo, or background) or an artist photo from a local image file, per `target`. |
|
|
134
134
|
| `get_asset` | read | Read a track or release asset. Valid combinations: (1) mode='info' + parent='track' + asset stereo\|dolby\|lyrics — file metadata (not the bytes) incl. processing state. (2) mode='info' + parent='release' + asset square\|tall — motion-artwork (animated cover) video metadata. (3) mode='download_url' + parent='track' + asset audio_16\|audio_24\|audio_32 (WAV master) or audio_preview_full\|audio_preview_clip (MP3 preview) — returns { download_url, expires_in }, a signed URL that expires roughly 10 minutes after issue; fetch it directly — do not send your API token to it. Any other combination is refused. |
|
|
135
135
|
|
package/dist/coverage.js
CHANGED
|
@@ -145,6 +145,7 @@ export const EXCLUDED = {
|
|
|
145
145
|
'GET /resolve/label/{labelSlug}': 'label-website resolution — not exposed in v1',
|
|
146
146
|
'GET /site-settings/{label}': 'label-website settings — not exposed in v1',
|
|
147
147
|
'GET /site-settings/links/{label}': 'label-website settings — not exposed in v1',
|
|
148
|
+
'GET /tracks/{track}/file-upload-attempts/{uploadAttempt}': 'per-upload audio processing status — not exposed in v1',
|
|
148
149
|
'GET /tracks/{track}/licenses/{trackLicense}/download': 'license file download — not exposed in v1',
|
|
149
150
|
'GET /transactions/csv': 'transaction CSV export — not exposed in v1',
|
|
150
151
|
};
|
package/dist/projection.js
CHANGED
package/dist/tools/catalog.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* `response_format: 'detailed'` returning the verbatim API response.
|
|
12
12
|
*/
|
|
13
13
|
import { statSync } from 'node:fs';
|
|
14
|
-
import { ENTITIES, ENTITY_NAMES, assertAllowedExtension, } from '@labelgrid/core';
|
|
14
|
+
import { ENTITIES, ENTITY_NAMES, REPLACEMENT_ENTITIES, assertAllowedExtension, } from '@labelgrid/core';
|
|
15
15
|
import { z } from 'zod';
|
|
16
16
|
import { applyProjection } from '../projection.js';
|
|
17
17
|
/** Accepted image extensions for the catalog image uploads. */
|
|
@@ -135,17 +135,47 @@ const updateCatalogItem = {
|
|
|
135
135
|
return client.patch(`${spec.path}/${args.id}`, args.fields);
|
|
136
136
|
},
|
|
137
137
|
};
|
|
138
|
+
/** 'writer and publisher' — read off the registry, never spelled out by hand. */
|
|
139
|
+
const REPLACEMENT_ENTITY_LIST = REPLACEMENT_ENTITIES.join(' and ');
|
|
138
140
|
const deleteCatalogItem = {
|
|
139
141
|
name: 'delete_catalog_item',
|
|
140
142
|
toolset: 'catalog',
|
|
141
143
|
gate: 'safe_write',
|
|
142
144
|
title: 'Delete a catalog item',
|
|
143
|
-
description: `Delete a catalog entity. The API refuses deletes that would orphan data — ${entityDoc((s) => s.deleteNote)}
|
|
144
|
-
|
|
145
|
+
description: `Delete a catalog entity. The API refuses deletes that would orphan data — ${entityDoc((s) => s.deleteNote)}` +
|
|
146
|
+
` \`replace_with\` — ${REPLACEMENT_ENTITY_LIST} only — is the id inheriting those credits; a 422 REPLACEMENT_UNAVAILABLE means nothing was deleted.`,
|
|
147
|
+
inputShape: {
|
|
148
|
+
entity: entityArg,
|
|
149
|
+
id: idArg,
|
|
150
|
+
replace_with: z
|
|
151
|
+
.number()
|
|
152
|
+
.int()
|
|
153
|
+
.positive()
|
|
154
|
+
.optional()
|
|
155
|
+
.describe(`${REPLACEMENT_ENTITY_LIST} only: the id that takes over every credit held by the one being deleted.`),
|
|
156
|
+
},
|
|
145
157
|
annotations: { destructiveHint: true },
|
|
146
158
|
handler: (args, { client }) => {
|
|
147
|
-
const
|
|
148
|
-
|
|
159
|
+
const entity = args.entity;
|
|
160
|
+
const spec = ENTITIES[entity];
|
|
161
|
+
const path = `${spec.path}/${args.id}`;
|
|
162
|
+
const replaceWith = args.replace_with;
|
|
163
|
+
if (replaceWith === undefined) {
|
|
164
|
+
return client.delete(path);
|
|
165
|
+
}
|
|
166
|
+
// Only two endpoints take the parameter. Dropping it for the others would
|
|
167
|
+
// delete on the caller's behalf while silently ignoring the reassignment
|
|
168
|
+
// they asked for, so the call is refused before anything is sent.
|
|
169
|
+
if (!spec.acceptsDeleteReplacement) {
|
|
170
|
+
return Promise.resolve({
|
|
171
|
+
error: {
|
|
172
|
+
code: 'INVALID_SELECTOR',
|
|
173
|
+
message: `The ${entity} delete does not accept replace_with — only ${REPLACEMENT_ENTITY_LIST} deletes do. Delete without it, or clear the references first.`,
|
|
174
|
+
status: 0,
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
return client.delete(path, { replace_with: replaceWith });
|
|
149
179
|
},
|
|
150
180
|
};
|
|
151
181
|
/** Maps the label image targets to the API's imageType path segment. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@labelgrid/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"mcpName": "io.github.labelgrid/labelgrid-mcp",
|
|
5
5
|
"description": "Official LabelGrid MCP server — connect your AI client to your LabelGrid account",
|
|
6
6
|
"type": "module",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"node": ">=20"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@labelgrid/core": "0.2.
|
|
30
|
+
"@labelgrid/core": "0.2.2",
|
|
31
31
|
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
32
32
|
"zod": "^3.24.0"
|
|
33
33
|
}
|
package/server.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
3
|
"name": "io.github.labelgrid/labelgrid-mcp",
|
|
4
4
|
"description": "Official LabelGrid MCP server — manage your music catalog, releases, analytics and distribution.",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.7.0",
|
|
6
6
|
"websiteUrl": "https://labelgrid.com",
|
|
7
7
|
"repository": {
|
|
8
8
|
"url": "https://github.com/labelgrid/labelgrid-mcp",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
{
|
|
13
13
|
"registryType": "npm",
|
|
14
14
|
"identifier": "@labelgrid/mcp",
|
|
15
|
-
"version": "0.
|
|
15
|
+
"version": "0.7.0",
|
|
16
16
|
"transport": {
|
|
17
17
|
"type": "stdio"
|
|
18
18
|
},
|