@withpica/mcp-server-directory 1.2.0 → 1.3.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.
Files changed (71) hide show
  1. package/package.json +2 -1
  2. package/scripts/build-skills.ts +192 -0
  3. package/src/__tests__/skills/skills-registry.test.ts +63 -0
  4. package/src/__tests__/skills/skills-tools.test.ts +74 -0
  5. package/src/prompts/public-question-atlas.ts +17 -0
  6. package/src/server.ts +123 -11
  7. package/src/skills/find-music-for-sync-brief/SKILL.md +89 -0
  8. package/src/skills/index.ts +63 -0
  9. package/src/skills/skills.generated.ts +33 -0
  10. package/src/tools/index.ts +3 -0
  11. package/src/tools/skills.ts +146 -0
  12. package/dist/client.d.ts +0 -12
  13. package/dist/client.d.ts.map +0 -1
  14. package/dist/client.js +0 -93
  15. package/dist/client.js.map +0 -1
  16. package/dist/config.d.ts +0 -9
  17. package/dist/config.d.ts.map +0 -1
  18. package/dist/config.js +0 -15
  19. package/dist/config.js.map +0 -1
  20. package/dist/index.d.ts +0 -3
  21. package/dist/index.d.ts.map +0 -1
  22. package/dist/index.js +0 -28
  23. package/dist/index.js.map +0 -1
  24. package/dist/prompts/index.d.ts +0 -32
  25. package/dist/prompts/index.d.ts.map +0 -1
  26. package/dist/prompts/index.js +0 -165
  27. package/dist/prompts/index.js.map +0 -1
  28. package/dist/prompts/public-question-atlas.d.ts +0 -121
  29. package/dist/prompts/public-question-atlas.d.ts.map +0 -1
  30. package/dist/prompts/public-question-atlas.js +0 -404
  31. package/dist/prompts/public-question-atlas.js.map +0 -1
  32. package/dist/resources/llms-primer.d.ts +0 -2
  33. package/dist/resources/llms-primer.d.ts.map +0 -1
  34. package/dist/resources/llms-primer.js +0 -35
  35. package/dist/resources/llms-primer.js.map +0 -1
  36. package/dist/server.d.ts +0 -13
  37. package/dist/server.d.ts.map +0 -1
  38. package/dist/server.js +0 -104
  39. package/dist/server.js.map +0 -1
  40. package/dist/tools/chain.d.ts +0 -12
  41. package/dist/tools/chain.d.ts.map +0 -1
  42. package/dist/tools/chain.js +0 -109
  43. package/dist/tools/chain.js.map +0 -1
  44. package/dist/tools/index.d.ts +0 -35
  45. package/dist/tools/index.d.ts.map +0 -1
  46. package/dist/tools/index.js +0 -45
  47. package/dist/tools/index.js.map +0 -1
  48. package/dist/tools/people.d.ts +0 -13
  49. package/dist/tools/people.d.ts.map +0 -1
  50. package/dist/tools/people.js +0 -177
  51. package/dist/tools/people.js.map +0 -1
  52. package/dist/tools/recordings.d.ts +0 -12
  53. package/dist/tools/recordings.d.ts.map +0 -1
  54. package/dist/tools/recordings.js +0 -145
  55. package/dist/tools/recordings.js.map +0 -1
  56. package/dist/tools/search.d.ts +0 -12
  57. package/dist/tools/search.d.ts.map +0 -1
  58. package/dist/tools/search.js +0 -56
  59. package/dist/tools/search.js.map +0 -1
  60. package/dist/tools/works.d.ts +0 -14
  61. package/dist/tools/works.d.ts.map +0 -1
  62. package/dist/tools/works.js +0 -248
  63. package/dist/tools/works.js.map +0 -1
  64. package/dist/utils/errors.d.ts +0 -14
  65. package/dist/utils/errors.d.ts.map +0 -1
  66. package/dist/utils/errors.js +0 -48
  67. package/dist/utils/errors.js.map +0 -1
  68. package/dist/utils/formatting.d.ts +0 -10
  69. package/dist/utils/formatting.d.ts.map +0 -1
  70. package/dist/utils/formatting.js +0 -16
  71. package/dist/utils/formatting.js.map +0 -1
@@ -1,165 +0,0 @@
1
- // Copyright (c) 2024-2026 Withpica Ltd. All rights reserved.
2
- export class PromptRegistry {
3
- listPrompts() {
4
- return [
5
- {
6
- name: "find-music",
7
- description: "Find music for a sync brief, playlist, or project — search by mood, BPM, key, energy, or description",
8
- arguments: [
9
- {
10
- name: "brief",
11
- description: "What you're looking for — a mood, scene description, or audio characteristics",
12
- required: false,
13
- },
14
- ],
15
- },
16
- {
17
- name: "research-creator",
18
- description: "Research a songwriter, composer, or performer — see their works, identifiers, collaborators, and verification status",
19
- arguments: [
20
- {
21
- name: "name_or_id",
22
- description: "Creator name, IPI number, ISNI, or MusicBrainz ID",
23
- required: false,
24
- },
25
- ],
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
- },
32
- ];
33
- }
34
- async getPrompt(name, args) {
35
- switch (name) {
36
- case "find-music":
37
- return this.getFindMusicPrompt(args?.brief);
38
- case "research-creator":
39
- return this.getResearchCreatorPrompt(args?.name_or_id);
40
- case "directory-autopilot":
41
- return this.getDirectoryAutopilotPrompt();
42
- default:
43
- throw new Error(`Prompt not found: ${name}`);
44
- }
45
- }
46
- getFindMusicPrompt(brief) {
47
- const briefInstruction = brief
48
- ? `The user is looking for: "${brief}". Translate this into audio search parameters.`
49
- : `Ask me what I'm looking for — a mood, a scene, a vibe, or specific audio characteristics (BPM, key, energy).`;
50
- return {
51
- messages: [
52
- {
53
- role: "user",
54
- content: {
55
- type: "text",
56
- text: `Help me find music in the PICA public directory for a sync brief or project.
57
-
58
- ${briefInstruction}
59
-
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
67
-
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)
75
-
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)
80
-
81
- If no results match, suggest broadening the search (wider BPM range, drop key filter, etc.).
82
-
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.
100
-
101
- ${searchInstruction}
102
-
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.`,
122
- },
123
- },
124
- ],
125
- };
126
- }
127
- getDirectoryAutopilotPrompt() {
128
- return {
129
- messages: [
130
- {
131
- role: "user",
132
- content: {
133
- type: "text",
134
- text: `You've connected to the PICA public music directory. Help me find what I need.
135
-
136
- First, read the llms://primer resource to understand what's available.
137
-
138
- Then ask me what I'm looking for. Based on my answer, route to the right workflow:
139
-
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.
142
-
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.
145
-
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.
157
-
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.`,
159
- },
160
- },
161
- ],
162
- };
163
- }
164
- }
165
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
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"}
@@ -1,121 +0,0 @@
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
@@ -1 +0,0 @@
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"}