@withpica/mcp-server-directory 1.1.0 → 1.2.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 +43 -26
- package/dist/prompts/index.d.ts +5 -6
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +92 -135
- package/dist/prompts/index.js.map +1 -1
- package/dist/prompts/public-question-atlas.d.ts +121 -0
- package/dist/prompts/public-question-atlas.d.ts.map +1 -0
- package/dist/prompts/public-question-atlas.js +404 -0
- package/dist/prompts/public-question-atlas.js.map +1 -0
- package/dist/tools/chain.d.ts +12 -0
- package/dist/tools/chain.d.ts.map +1 -0
- package/dist/tools/chain.js +109 -0
- package/dist/tools/chain.js.map +1 -0
- package/dist/tools/index.d.ts +9 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +2 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/people.d.ts +0 -1
- package/dist/tools/people.d.ts.map +1 -1
- package/dist/tools/people.js +23 -36
- package/dist/tools/people.js.map +1 -1
- package/dist/tools/recordings.d.ts.map +1 -1
- package/dist/tools/recordings.js +7 -3
- package/dist/tools/recordings.js.map +1 -1
- package/dist/tools/search.d.ts.map +1 -1
- package/dist/tools/search.js +7 -4
- package/dist/tools/search.js.map +1 -1
- package/dist/tools/works.d.ts +0 -1
- package/dist/tools/works.d.ts.map +1 -1
- package/dist/tools/works.js +41 -42
- package/dist/tools/works.js.map +1 -1
- package/package.json +3 -2
- package/src/__tests__/prompts/index.test.ts +47 -64
- package/src/__tests__/prompts/prompt-eval-harness.test.ts +135 -104
- package/src/__tests__/tools/chain.test.ts +122 -0
- package/src/__tests__/tools/composability-chains.test.ts +4 -2
- package/src/__tests__/tools/people.test.ts +9 -3
- package/src/__tests__/tools/works.test.ts +32 -3
- package/src/prompts/index.ts +97 -141
- package/src/prompts/public-question-atlas.ts +540 -0
- package/src/tools/chain.ts +118 -0
- package/src/tools/index.ts +12 -0
- package/src/tools/people.ts +22 -41
- package/src/tools/recordings.ts +7 -3
- package/src/tools/search.ts +7 -4
- package/src/tools/works.ts +39 -46
package/CHANGELOG.md
CHANGED
|
@@ -1,39 +1,56 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
All notable changes to `@withpica/mcp-server-directory`
|
|
3
|
+
All notable changes to `@withpica/mcp-server-directory` are documented here.
|
|
4
4
|
|
|
5
|
-
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
-
and this project adheres to
|
|
7
|
-
|
|
8
|
-
> **Rule of the road:** every version bump to this package MUST land with a
|
|
9
|
-
> matching entry here in the same commit. See the project's "npm publish
|
|
10
|
-
> discipline" memory entry for the enforcement rationale.
|
|
5
|
+
The format is loosely based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to semantic versioning where the major number is incremented
|
|
7
|
+
for breaking tool-surface changes.
|
|
11
8
|
|
|
12
9
|
## [Unreleased]
|
|
13
10
|
|
|
14
|
-
## [1.1.0]
|
|
11
|
+
## [1.1.0] - 2026-04-21
|
|
15
12
|
|
|
16
|
-
|
|
13
|
+
Shipped as minor rather than major despite the `*_full` tool removal:
|
|
14
|
+
the removed names had near-zero external adoption (they shipped recently
|
|
15
|
+
and weren't advertised externally), and staying on the 1.x line keeps
|
|
16
|
+
`^1.0.0` consumers on the upgrade path rather than stranding them on
|
|
17
|
+
the broken cascade. Clients that cached the `*_full` names will see a
|
|
18
|
+
tool-not-found error and need to refresh their tool list.
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
3 prompts → 2 skills, each with decision trees, domain knowledge,
|
|
20
|
-
and the shared preamble (tone, discovery principle, read-only note).
|
|
20
|
+
### Breaking
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
- **Removed `directory_lookup_person_full` and `directory_lookup_work_full`.**
|
|
23
|
+
Both tools hit the same upstream endpoints as their non-`_full` counterparts
|
|
24
|
+
with only a formatting difference — there was no capability delta. The
|
|
25
|
+
`_full` variants are now the canonical names (`directory_lookup_person`
|
|
26
|
+
and `directory_lookup_work`); the thin variants have been deleted. Clients
|
|
27
|
+
that cached the `_full` names need to update their tool list; the
|
|
28
|
+
replacements return a superset of the prior data, so no output is lost.
|
|
23
29
|
|
|
24
|
-
|
|
25
|
-
`find-music` → `discover-music` (adds equal discovery principle,
|
|
26
|
-
reference track search, similarity exploration).
|
|
27
|
-
`directory-autopilot` routing folded into `research-creator`
|
|
28
|
-
(identifier resolution, browsing, creator lookup all in one skill).
|
|
29
|
-
`research-creator` gains collaborator network, similarity search,
|
|
30
|
-
rights landscape, and identifier routing from the old autopilot.
|
|
30
|
+
### Added
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
- **`directory_chain` tool** — one-call rights-chain lookup. Accepts a
|
|
33
|
+
free-text query, a direct ISWC/ISRC `identifier`, or audio-only filters
|
|
34
|
+
(BPM / key / energy / mood). Returns the already-public `ChainResult`
|
|
35
|
+
shape: work + writers + publishers (names + roles only, no IPIs or
|
|
36
|
+
splits) + linked recording + audio characteristics. Wraps the existing
|
|
37
|
+
public `/api/public/directory/chain` endpoint — no new backing API work.
|
|
38
|
+
- `directory_list_people` now accepts `letter` (A–Z, `#`) for alphabetical
|
|
39
|
+
browsing. The backend has supported this for months; only the MCP tool
|
|
40
|
+
was missing the parameter.
|
|
41
|
+
- `directory_list_works` now accepts `letter`, `sort` (`title` | `recent`),
|
|
42
|
+
and `isrc` — all previously backend-only.
|
|
33
43
|
|
|
34
|
-
###
|
|
44
|
+
### Changed
|
|
35
45
|
|
|
36
|
-
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
46
|
+
- **`directory_lookup_person` now matches its description.** Previously the
|
|
47
|
+
tool advertised ISNI / IPI / MusicBrainz ID support but the backing query
|
|
48
|
+
only matched `global_creator_id` — any non-UUID identifier silently 404'd.
|
|
49
|
+
The query now cascades through `global_creator_id` → `isni` →
|
|
50
|
+
`cae_ipi_number` → `musicbrainz_id`, first hit wins.
|
|
51
|
+
- `directory_search` description rewritten to drop the false "ranked" claim.
|
|
52
|
+
The backing endpoint is a fan-out (`listWorks` + `listPeople`,
|
|
53
|
+
half-limit each), not cross-type ranking. Callers should prefer typed
|
|
54
|
+
list tools when they know the entity type.
|
|
55
|
+
- `directory_lookup_isrc` description rewritten to frame it honestly as a
|
|
56
|
+
pinned filter preset on `list_works` rather than a distinct lookup.
|
package/dist/prompts/index.d.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* Deployed as upgraded prompts; will convert to MCP skills format
|
|
5
|
-
* when the spec extension ships (ADR-171).
|
|
2
|
+
* Prompt Registry for Directory MCP Server
|
|
3
|
+
* Guided workflows for music discovery, sync licensing, and rights research
|
|
6
4
|
*/
|
|
7
5
|
export interface PromptDefinition {
|
|
8
6
|
name: string;
|
|
@@ -27,7 +25,8 @@ export interface PromptResult {
|
|
|
27
25
|
export declare class PromptRegistry {
|
|
28
26
|
listPrompts(): PromptDefinition[];
|
|
29
27
|
getPrompt(name: string, args?: Record<string, any>): Promise<PromptResult>;
|
|
30
|
-
private
|
|
31
|
-
private
|
|
28
|
+
private getFindMusicPrompt;
|
|
29
|
+
private getResearchCreatorPrompt;
|
|
30
|
+
private getDirectoryAutopilotPrompt;
|
|
32
31
|
}
|
|
33
32
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAEA;;;GAGG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,KAAK,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;KACpB,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE;QACP,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,qBAAa,cAAc;IACzB,WAAW,IAAI,gBAAgB,EAAE;IAoC3B,SAAS,CACb,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GACzB,OAAO,CAAC,YAAY,CAAC;IAaxB,OAAO,CAAC,kBAAkB;IA6C1B,OAAO,CAAC,wBAAwB;IAwChC,OAAO,CAAC,2BAA2B;CAqCpC"}
|
package/dist/prompts/index.js
CHANGED
|
@@ -1,25 +1,10 @@
|
|
|
1
1
|
// Copyright (c) 2024-2026 Withpica Ltd. All rights reserved.
|
|
2
|
-
const SHARED_PREAMBLE = `You are guiding a music seeker through the PICA public directory — a discovery layer over verified music catalogs.
|
|
3
|
-
|
|
4
|
-
Tone: knowledgeable friend. You know what's available and how to find it. Straightforward, never salesy.
|
|
5
|
-
|
|
6
|
-
Discovery principle: every creator's work has equal discoverability. Catalog quality determines visibility, not fame or follower count. Results are sorted by musical fit, not popularity. An unknown songwriter with analysed audio ranks the same as a major artist.
|
|
7
|
-
|
|
8
|
-
Before starting this workflow:
|
|
9
|
-
1. Read the llms://primer resource to understand what's available in the directory
|
|
10
|
-
2. This is a read-only public directory — you can search and look up, but you can't create or modify anything
|
|
11
|
-
3. Only works from organisations that opted into the directory are visible
|
|
12
|
-
|
|
13
|
-
After completing this workflow:
|
|
14
|
-
- Summarise what you found in one short paragraph
|
|
15
|
-
- Suggest the natural next step
|
|
16
|
-
- If they say no, that's fine. Don't ask twice.`;
|
|
17
2
|
export class PromptRegistry {
|
|
18
3
|
listPrompts() {
|
|
19
4
|
return [
|
|
20
5
|
{
|
|
21
|
-
name: "
|
|
22
|
-
description: "Find music for a sync brief, playlist, or project — search by mood, BPM, key, energy, or description
|
|
6
|
+
name: "find-music",
|
|
7
|
+
description: "Find music for a sync brief, playlist, or project — search by mood, BPM, key, energy, or description",
|
|
23
8
|
arguments: [
|
|
24
9
|
{
|
|
25
10
|
name: "brief",
|
|
@@ -30,7 +15,7 @@ export class PromptRegistry {
|
|
|
30
15
|
},
|
|
31
16
|
{
|
|
32
17
|
name: "research-creator",
|
|
33
|
-
description: "Research a songwriter, composer, or performer —
|
|
18
|
+
description: "Research a songwriter, composer, or performer — see their works, identifiers, collaborators, and verification status",
|
|
34
19
|
arguments: [
|
|
35
20
|
{
|
|
36
21
|
name: "name_or_id",
|
|
@@ -39,166 +24,138 @@ export class PromptRegistry {
|
|
|
39
24
|
},
|
|
40
25
|
],
|
|
41
26
|
},
|
|
27
|
+
{
|
|
28
|
+
name: "directory-autopilot",
|
|
29
|
+
description: "Not sure where to start? Describe what you need and get routed to the right workflow — sync search, rights research, or identifier lookup",
|
|
30
|
+
arguments: [],
|
|
31
|
+
},
|
|
42
32
|
];
|
|
43
33
|
}
|
|
44
34
|
async getPrompt(name, args) {
|
|
45
35
|
switch (name) {
|
|
46
|
-
case "
|
|
47
|
-
return this.
|
|
36
|
+
case "find-music":
|
|
37
|
+
return this.getFindMusicPrompt(args?.brief);
|
|
48
38
|
case "research-creator":
|
|
49
|
-
return this.
|
|
39
|
+
return this.getResearchCreatorPrompt(args?.name_or_id);
|
|
40
|
+
case "directory-autopilot":
|
|
41
|
+
return this.getDirectoryAutopilotPrompt();
|
|
50
42
|
default:
|
|
51
43
|
throw new Error(`Prompt not found: ${name}`);
|
|
52
44
|
}
|
|
53
45
|
}
|
|
54
|
-
|
|
46
|
+
getFindMusicPrompt(brief) {
|
|
55
47
|
const briefInstruction = brief
|
|
56
48
|
? `The user is looking for: "${brief}". Translate this into audio search parameters.`
|
|
57
|
-
: `Ask what
|
|
49
|
+
: `Ask me what I'm looking for — a mood, a scene, a vibe, or specific audio characteristics (BPM, key, energy).`;
|
|
58
50
|
return {
|
|
59
51
|
messages: [
|
|
60
52
|
{
|
|
61
53
|
role: "user",
|
|
62
54
|
content: {
|
|
63
55
|
type: "text",
|
|
64
|
-
text:
|
|
56
|
+
text: `Help me find music in the PICA public directory for a sync brief or project.
|
|
65
57
|
|
|
66
|
-
|
|
58
|
+
${briefInstruction}
|
|
67
59
|
|
|
68
|
-
|
|
60
|
+
Workflow:
|
|
61
|
+
1. Translate the brief into search parameters for directory_search_recordings:
|
|
62
|
+
- Mood descriptions → energy, danceability, key_mode, mood filters
|
|
63
|
+
- "Upbeat" → min_energy: 0.6, min_danceability: 0.5
|
|
64
|
+
- "Dark/moody" → max_energy: 0.4, key_mode: minor
|
|
65
|
+
- "Chill" → max_energy: 0.4, max_bpm: 100
|
|
66
|
+
- Specific requests → use BPM, key, duration filters directly
|
|
69
67
|
|
|
70
|
-
|
|
68
|
+
2. Run directory_search_recordings with the parameters.
|
|
69
|
+
|
|
70
|
+
3. For each promising result, use directory_lookup_work to get:
|
|
71
|
+
- Who wrote it (credits with IPI numbers)
|
|
72
|
+
- Whether credits are attested (verified ownership)
|
|
73
|
+
- DSP links (Spotify, Apple Music — so the user can listen)
|
|
74
|
+
- Registration score (higher = cleaner rights chain)
|
|
71
75
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
- "Upbeat" → min_energy: 0.6, min_danceability: 0.5
|
|
77
|
-
- "Dark/moody" → max_energy: 0.4, key_mode: minor
|
|
78
|
-
- "Chill" → max_energy: 0.4, max_bpm: 100
|
|
79
|
-
- Specific requests → use BPM, key, duration filters directly
|
|
80
|
-
→ Run directory_search_recordings with the parameters
|
|
81
|
-
→ Present results by musical fit, not popularity:
|
|
82
|
-
"here are [N] tracks that match. sorted by how closely they fit your brief, not by who made them."
|
|
83
|
-
→ Per result: title, creator, BPM, key, mood tags, duration.
|
|
84
|
-
No follower counts. No stream numbers.
|
|
85
|
-
|
|
86
|
-
For each promising result, use directory_lookup_work_full to get:
|
|
87
|
-
- Who wrote it (credits with IPI numbers)
|
|
88
|
-
- Whether credits are attested (verified ownership)
|
|
89
|
-
- DSP links (Spotify, Apple Music — so the user can listen)
|
|
90
|
-
- Registration score (higher = cleaner rights chain)
|
|
91
|
-
|
|
92
|
-
Present as a shortlist with:
|
|
93
|
-
- Title, artist, BPM, key, energy
|
|
94
|
-
- Credits summary (who to contact for licensing)
|
|
95
|
-
- Any flags (unattested credits, low registration score, missing ISRC)
|
|
96
|
-
|
|
97
|
-
Reference track search:
|
|
98
|
-
→ "got a reference track? tell me what you like about it."
|
|
99
|
-
→ Parse what they value: tempo, mood, instrumentation, vocal style
|
|
100
|
-
→ Search by those parameters
|
|
101
|
-
|
|
102
|
-
Similarity exploration:
|
|
103
|
-
→ "want to find music similar to [track] by someone you've never heard of?"
|
|
104
|
-
→ Search by the sound, not the name — this is where the discovery principle lives
|
|
105
|
-
|
|
106
|
-
If they like one:
|
|
107
|
-
→ "want to hear more from this creator, or find similar tracks?"
|
|
108
|
-
→ Similar → search with same parameters
|
|
109
|
-
→ More from creator → pivot to research-creator skill
|
|
110
|
-
|
|
111
|
-
Rights check:
|
|
112
|
-
→ For any track: "want to check the rights situation?"
|
|
113
|
-
→ Show ownership, publisher, contact path via directory_lookup_work_full
|
|
114
|
-
→ If enquiry → guide through submission
|
|
76
|
+
4. Present results as a shortlist with:
|
|
77
|
+
- Title, artist, BPM, key, energy
|
|
78
|
+
- Credits summary (who to contact for licensing)
|
|
79
|
+
- Any flags (unattested credits, low registration score, missing ISRC)
|
|
115
80
|
|
|
116
81
|
If no results match, suggest broadening the search (wider BPM range, drop key filter, etc.).
|
|
117
82
|
|
|
118
|
-
|
|
83
|
+
Important: This is a public directory — only works from organisations that opted in are visible. If the catalog is small, say so.`,
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
getResearchCreatorPrompt(nameOrId) {
|
|
90
|
+
const searchInstruction = nameOrId
|
|
91
|
+
? `Look up: "${nameOrId}". Try directory_lookup_person first (it accepts name, IPI, ISNI, or MusicBrainz ID). If that doesn't match, use directory_list_people with a text search.`
|
|
92
|
+
: `Ask me for the creator's name, IPI number, ISNI, or MusicBrainz ID.`;
|
|
93
|
+
return {
|
|
94
|
+
messages: [
|
|
95
|
+
{
|
|
96
|
+
role: "user",
|
|
97
|
+
content: {
|
|
98
|
+
type: "text",
|
|
99
|
+
text: `Help me research a music creator in the PICA public directory.
|
|
119
100
|
|
|
120
|
-
|
|
121
|
-
- Results sorted by audio-parameter match, not streams or followers
|
|
122
|
-
- Reference track searching works by extracting musical qualities, not artist similarity
|
|
123
|
-
- Rights information is always available — the directory doesn't hide who owns what
|
|
124
|
-
- Sync supervisors think in briefs (mood + tempo + energy + duration), not artist names
|
|
125
|
-
- Similarity search by audio surfaces genuinely similar music the seeker might never have found
|
|
101
|
+
${searchInstruction}
|
|
126
102
|
|
|
127
|
-
|
|
103
|
+
Once you find the person, use directory_lookup_person to get their complete profile:
|
|
104
|
+
- Identifiers (IPI, ISNI, MusicBrainz) — essential for rights verification
|
|
105
|
+
- All credited works with roles (writer, composer, performer, producer)
|
|
106
|
+
- Collaborator network — who they work with
|
|
107
|
+
- Verification score — how complete their profile is
|
|
108
|
+
|
|
109
|
+
Then for their most notable works (up to 5), use directory_lookup_work to get:
|
|
110
|
+
- Full credits and splits (are they the sole writer or one of many?)
|
|
111
|
+
- Recordings with ISRCs
|
|
112
|
+
- Audio analysis (BPM, key, energy)
|
|
113
|
+
- DSP links and registration status
|
|
114
|
+
|
|
115
|
+
Present a summary:
|
|
116
|
+
- Creator profile (name, identifiers, role patterns)
|
|
117
|
+
- Catalog overview (how many works, typical roles, common collaborators)
|
|
118
|
+
- Notable works with credit details
|
|
119
|
+
- Any gaps (missing identifiers, unattested credits, low scores)
|
|
120
|
+
|
|
121
|
+
This is useful for: rights research, due diligence before licensing, publisher evaluation, or understanding a catalog before acquisition.`,
|
|
128
122
|
},
|
|
129
123
|
},
|
|
130
124
|
],
|
|
131
125
|
};
|
|
132
126
|
}
|
|
133
|
-
|
|
134
|
-
const searchInstruction = nameOrId
|
|
135
|
-
? `Look up: "${nameOrId}". Try directory_lookup_person_full first (it accepts name, IPI, ISNI, or MusicBrainz ID). If that doesn't match, use directory_list_people with a text search.`
|
|
136
|
-
: `Ask for the creator's name, IPI number, ISNI, or MusicBrainz ID.`;
|
|
127
|
+
getDirectoryAutopilotPrompt() {
|
|
137
128
|
return {
|
|
138
129
|
messages: [
|
|
139
130
|
{
|
|
140
131
|
role: "user",
|
|
141
132
|
content: {
|
|
142
133
|
type: "text",
|
|
143
|
-
text:
|
|
134
|
+
text: `You've connected to the PICA public music directory. Help me find what I need.
|
|
144
135
|
|
|
145
|
-
|
|
136
|
+
First, read the llms://primer resource to understand what's available.
|
|
146
137
|
|
|
147
|
-
|
|
138
|
+
Then ask me what I'm looking for. Based on my answer, route to the right workflow:
|
|
148
139
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
→ ISRC (e.g. USABC1234567) → directory_lookup_isrc → then directory_lookup_work_full
|
|
152
|
-
→ ISWC (e.g. T-123.456.789-0) → directory_lookup_work_full
|
|
153
|
-
→ IPI or ISNI → directory_lookup_person_full
|
|
154
|
-
→ MusicBrainz ID → directory_lookup_person_full
|
|
155
|
-
- If the user wants to browse → use directory_search with a broad query, or directory_list_works / directory_list_people
|
|
140
|
+
If I'm looking for MUSIC FOR A PROJECT (sync brief, playlist, mood search):
|
|
141
|
+
→ Use the find-music workflow. Translate my description into audio search parameters and search recordings by BPM, key, energy, mood. Then look up full details on promising matches.
|
|
156
142
|
|
|
157
|
-
|
|
143
|
+
If I'm looking for INFORMATION ABOUT A CREATOR (songwriter, composer, performer):
|
|
144
|
+
→ Use the research-creator workflow. Look up their profile, works, identifiers, and collaborators.
|
|
158
145
|
|
|
159
|
-
|
|
146
|
+
If I have a SPECIFIC IDENTIFIER to resolve (ISRC, ISWC, IPI, ISNI):
|
|
147
|
+
→ Route directly to the right lookup tool:
|
|
148
|
+
- ISRC (e.g. USABC1234567) → directory_lookup_isrc → then directory_lookup_work
|
|
149
|
+
- ISWC (e.g. T-123.456.789-0) → directory_lookup_work
|
|
150
|
+
- IPI or ISNI → directory_lookup_person
|
|
151
|
+
- MusicBrainz ID → directory_lookup_person
|
|
152
|
+
|
|
153
|
+
If I want to BROWSE what's in the directory:
|
|
154
|
+
→ Use directory_search with a broad query, or directory_list_works / directory_list_people to paginate.
|
|
155
|
+
|
|
156
|
+
Tell me which workflow you chose and why, in one sentence. Offer alternatives.
|
|
160
157
|
|
|
161
|
-
|
|
162
|
-
→ Find the person using directory_lookup_person_full
|
|
163
|
-
→ If multiple matches: present with distinguishing works/roles
|
|
164
|
-
|
|
165
|
-
Creator profile:
|
|
166
|
-
→ Full catalog: all works, roles, co-writers
|
|
167
|
-
→ Identifiers: IPI, ISNI, MusicBrainz, IPN
|
|
168
|
-
→ Collaborator network: "frequently works with [names]"
|
|
169
|
-
→ Genre/mood footprint: based on analysed audio across catalog
|
|
170
|
-
|
|
171
|
-
For their most notable works (up to 5), use directory_lookup_work_full to get:
|
|
172
|
-
- Full credits and splits (are they the sole writer or one of many?)
|
|
173
|
-
- Recordings with ISRCs
|
|
174
|
-
- Audio analysis (BPM, key, energy)
|
|
175
|
-
- DSP links and registration status
|
|
176
|
-
|
|
177
|
-
Cross-reference:
|
|
178
|
-
→ "want to verify their identifiers against ISNI or MusicBrainz?"
|
|
179
|
-
→ Flag discrepancies
|
|
180
|
-
|
|
181
|
-
Similarity exploration:
|
|
182
|
-
→ "want to find other creators with a similar sound?"
|
|
183
|
-
→ Use directory_search_recordings by audio characteristics of their catalog
|
|
184
|
-
→ Equal discovery: results by sound, not fame
|
|
185
|
-
|
|
186
|
-
Rights landscape:
|
|
187
|
-
→ "want to know who controls their catalog?"
|
|
188
|
-
→ Publishers, agreements, licensing paths
|
|
189
|
-
|
|
190
|
-
After research:
|
|
191
|
-
→ Summary: creator profile, catalog overview, notable works, gaps
|
|
192
|
-
→ "want to submit a licensing enquiry, or explore more creators?"
|
|
193
|
-
|
|
194
|
-
Domain knowledge:
|
|
195
|
-
- Creator research often starts from one work and expands via collaborator network — adjacent talent discovery
|
|
196
|
-
- Identifier verification across sources catches discrepancies that matter for rights
|
|
197
|
-
- Similarity search by audio surfaces genuinely similar music through non-traditional channels
|
|
198
|
-
- The collaborator network is how you discover creators no algorithm would surface
|
|
199
|
-
- This is useful for: rights research, due diligence before licensing, publisher evaluation, or catalog acquisition
|
|
200
|
-
|
|
201
|
-
Tools: directory_lookup_person_full, directory_lookup_work_full, directory_search_recordings, directory_search, directory_lookup_isrc, directory_list_works, directory_list_people`,
|
|
158
|
+
Important: This is a read-only public directory. I can search and look up, but I can't create or modify anything. Only works from organisations that opted into the directory are visible.`,
|
|
202
159
|
},
|
|
203
160
|
},
|
|
204
161
|
],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAAA,6DAA6D;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAAA,6DAA6D;AA8B7D,MAAM,OAAO,cAAc;IACzB,WAAW;QACT,OAAO;YACL;gBACE,IAAI,EAAE,YAAY;gBAClB,WAAW,EACT,sGAAsG;gBACxG,SAAS,EAAE;oBACT;wBACE,IAAI,EAAE,OAAO;wBACb,WAAW,EACT,+EAA+E;wBACjF,QAAQ,EAAE,KAAK;qBAChB;iBACF;aACF;YACD;gBACE,IAAI,EAAE,kBAAkB;gBACxB,WAAW,EACT,sHAAsH;gBACxH,SAAS,EAAE;oBACT;wBACE,IAAI,EAAE,YAAY;wBAClB,WAAW,EAAE,mDAAmD;wBAChE,QAAQ,EAAE,KAAK;qBAChB;iBACF;aACF;YACD;gBACE,IAAI,EAAE,qBAAqB;gBAC3B,WAAW,EACT,2IAA2I;gBAC7I,SAAS,EAAE,EAAE;aACd;SACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,SAAS,CACb,IAAY,EACZ,IAA0B;QAE1B,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,YAAY;gBACf,OAAO,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAC9C,KAAK,kBAAkB;gBACrB,OAAO,IAAI,CAAC,wBAAwB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;YACzD,KAAK,qBAAqB;gBACxB,OAAO,IAAI,CAAC,2BAA2B,EAAE,CAAC;YAC5C;gBACE,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,EAAE,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAEO,kBAAkB,CAAC,KAAc;QACvC,MAAM,gBAAgB,GAAG,KAAK;YAC5B,CAAC,CAAC,6BAA6B,KAAK,iDAAiD;YACrF,CAAC,CAAC,8GAA8G,CAAC;QAEnH,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE;wBACP,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE;;EAEhB,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;kIAyBgH;qBACvH;iBACF;aACF;SACF,CAAC;IACJ,CAAC;IAEO,wBAAwB,CAAC,QAAiB;QAChD,MAAM,iBAAiB,GAAG,QAAQ;YAChC,CAAC,CAAC,aAAa,QAAQ,4JAA4J;YACnL,CAAC,CAAC,qEAAqE,CAAC;QAE1E,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE;wBACP,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE;;EAEhB,iBAAiB;;;;;;;;;;;;;;;;;;;;0IAoBuH;qBAC/H;iBACF;aACF;SACF,CAAC;IACJ,CAAC;IAEO,2BAA2B;QACjC,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE;wBACP,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;2LAwByK;qBAChL;iBACF;aACF;SACF,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public Question Atlas — ADR-229 Decision 1.
|
|
3
|
+
*
|
|
4
|
+
* Source-of-truth registry mapping natural public-discovery questions to
|
|
5
|
+
* the canonical directory-MCP tool resolution. Sister of:
|
|
6
|
+
* - `mcp-server/src/prompts/creator-question-atlas.ts` (ADR-226, customer)
|
|
7
|
+
* - `team-mcp-server/src/prompts/operator-question-atlas.ts` (ADR-228, operator)
|
|
8
|
+
*
|
|
9
|
+
* Read by:
|
|
10
|
+
*
|
|
11
|
+
* - lint Rule 11F (extended in ADR-229) — validates every `directory_*`
|
|
12
|
+
* tool's `Use when the user asks` block cites questions resolving
|
|
13
|
+
* here, rejects creator/operator atlas cross-pollination, asserts
|
|
14
|
+
* mutual exclusivity of `clean_empty_state` and `fallback_when_empty`,
|
|
15
|
+
* and asserts `disambiguation` shape integrity
|
|
16
|
+
* - `scripts/intent-resolution-eval.ts --surface=directory` (ADR-229 PR-3)
|
|
17
|
+
* - the Phase 4 description rewrites — `Use when the user asks` blocks
|
|
18
|
+
* pull question + synonym strings from here
|
|
19
|
+
*
|
|
20
|
+
* The `AtlasEntry` type is inline-duplicated rather than imported from a
|
|
21
|
+
* shared package, mirroring ADR-228's choice (Open Question 3 default —
|
|
22
|
+
* extract to `packages/mcp-atlas-types/` only if a fourth MCP surface
|
|
23
|
+
* lands or the type drift becomes painful).
|
|
24
|
+
*
|
|
25
|
+
* Two shape extensions vs the creator and operator atlases (per ADR-229
|
|
26
|
+
* Decision 4):
|
|
27
|
+
*
|
|
28
|
+
* 1. `clean_empty_state?: { message; suggest_query_shape }` — public-
|
|
29
|
+
* surface analog of `fallback_when_empty`. The directory has no
|
|
30
|
+
* internal action to nudge toward (the empty state IS the final
|
|
31
|
+
* answer for the anonymous user); this field carries the prescribed
|
|
32
|
+
* empty-state copy plus a query-shape hint for the calling LLM.
|
|
33
|
+
*
|
|
34
|
+
* 2. `disambiguation?: { ambiguous_terms[]; resolver_tool; resolver_intent }` —
|
|
35
|
+
* first-class concern on the public surface (creator/operator MCPs
|
|
36
|
+
* have a calling-context that narrows the search; the public
|
|
37
|
+
* directory hits "Bowie", "Sade", "Madonna", "Lover Boy" constantly
|
|
38
|
+
* and must declare an explicit resolver step).
|
|
39
|
+
*
|
|
40
|
+
* `clean_empty_state` and `fallback_when_empty` are mutually exclusive on
|
|
41
|
+
* a single entry — Rule 11F enforces this at lint time.
|
|
42
|
+
*
|
|
43
|
+
* The public atlas omits `natural_domain` (creator-side binds to
|
|
44
|
+
* `discovery.ts` CATEGORIES; the directory MCP has no equivalent
|
|
45
|
+
* taxonomy — the discovery surface is search and lookup, not category-
|
|
46
|
+
* faceted browse). It also omits `available_when` (the operator atlas's
|
|
47
|
+
* forward-compat hook for unshipped sections; the directory has no
|
|
48
|
+
* deferred-section concept).
|
|
49
|
+
*/
|
|
50
|
+
export interface AtlasFallback {
|
|
51
|
+
message: string;
|
|
52
|
+
next_tool: string;
|
|
53
|
+
}
|
|
54
|
+
export interface AtlasCleanEmptyState {
|
|
55
|
+
/**
|
|
56
|
+
* Atlas-prescribed copy for the empty-state response. The calling LLM
|
|
57
|
+
* may render in its own voice; the suggested-query-shape hint is the
|
|
58
|
+
* load-bearing part.
|
|
59
|
+
*/
|
|
60
|
+
message: string;
|
|
61
|
+
/**
|
|
62
|
+
* Free-text hint for how to refine the query, interpreted by the LLM
|
|
63
|
+
* as guidance (not rendered verbatim). Example:
|
|
64
|
+
* `"title + writer | title + year | ISWC if known"`.
|
|
65
|
+
*/
|
|
66
|
+
suggest_query_shape: string;
|
|
67
|
+
}
|
|
68
|
+
export interface AtlasDisambiguation {
|
|
69
|
+
/**
|
|
70
|
+
* Names known to be ambiguous in the music-metadata domain (multiple
|
|
71
|
+
* persons, artist projects, or works with the same string). v1 ships
|
|
72
|
+
* a static list; v2 (deferred per ADR-229 § Risks #3) could resolve
|
|
73
|
+
* dynamically against the index's name-collision frequency.
|
|
74
|
+
*/
|
|
75
|
+
ambiguous_terms: string[];
|
|
76
|
+
/**
|
|
77
|
+
* The directory tool the agent should call FIRST to surface candidate
|
|
78
|
+
* entities for the user to disambiguate before committing to the
|
|
79
|
+
* lookup tool in `resolves_to`.
|
|
80
|
+
*/
|
|
81
|
+
resolver_tool: string;
|
|
82
|
+
/**
|
|
83
|
+
* Free-text guidance for the LLM on how to run the resolver step.
|
|
84
|
+
* Example: `"Call directory_lookup_person first to surface candidates;
|
|
85
|
+
* ask which one before calling directory_list_works."`
|
|
86
|
+
*/
|
|
87
|
+
resolver_intent: string;
|
|
88
|
+
}
|
|
89
|
+
export type AtlasResolution = {
|
|
90
|
+
kind: "tool";
|
|
91
|
+
name: string;
|
|
92
|
+
default_args?: Record<string, unknown>;
|
|
93
|
+
} | {
|
|
94
|
+
kind: "prompt";
|
|
95
|
+
name: string;
|
|
96
|
+
};
|
|
97
|
+
export interface AtlasEntry {
|
|
98
|
+
question: string;
|
|
99
|
+
synonyms: string[];
|
|
100
|
+
resolves_to: AtlasResolution;
|
|
101
|
+
/** Mutually exclusive with `clean_empty_state` (lint-enforced). */
|
|
102
|
+
fallback_when_empty?: AtlasFallback;
|
|
103
|
+
/** ADR-229 Decision 4 — public-surface empty-state contract. */
|
|
104
|
+
clean_empty_state?: AtlasCleanEmptyState;
|
|
105
|
+
/** ADR-229 Decision 4 — public-surface name-collision contract. */
|
|
106
|
+
disambiguation?: AtlasDisambiguation;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Names known-ambiguous in the music-metadata domain — multiple persons
|
|
110
|
+
* sharing a stage name, or artist project names that collide with
|
|
111
|
+
* person names. Seed list per ADR-229 § Open Q2 (case-insensitive — the
|
|
112
|
+
* lint and the resolver normalise on lowercase).
|
|
113
|
+
*
|
|
114
|
+
* Grow this list as Phase 5 eval data surfaces real collisions the
|
|
115
|
+
* static seed misses. Do not prune without eval evidence — the cost of
|
|
116
|
+
* missing a real collision (wrong-tool routing on a public-facing
|
|
117
|
+
* surface) is higher than the cost of an extra resolver call.
|
|
118
|
+
*/
|
|
119
|
+
export declare const AMBIGUOUS_NAMES: string[];
|
|
120
|
+
export declare const PUBLIC_ATLAS: AtlasEntry[];
|
|
121
|
+
//# sourceMappingURL=public-question-atlas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public-question-atlas.d.ts","sourceRoot":"","sources":["../../src/prompts/public-question-atlas.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAEH,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,mBAAmB;IAClC;;;;;OAKG;IACH,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B;;;;OAIG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GACtE;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAErC,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,EAAE,eAAe,CAAC;IAC7B,mEAAmE;IACnE,mBAAmB,CAAC,EAAE,aAAa,CAAC;IACpC,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,oBAAoB,CAAC;IACzC,mEAAmE;IACnE,cAAc,CAAC,EAAE,mBAAmB,CAAC;CACtC;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,EAWnC,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,UAAU,EAqZpC,CAAC"}
|