@withpica/mcp-server-directory 1.1.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 (76) hide show
  1. package/CHANGELOG.md +43 -26
  2. package/package.json +4 -2
  3. package/scripts/build-skills.ts +192 -0
  4. package/src/__tests__/prompts/index.test.ts +47 -64
  5. package/src/__tests__/prompts/prompt-eval-harness.test.ts +135 -104
  6. package/src/__tests__/skills/skills-registry.test.ts +63 -0
  7. package/src/__tests__/skills/skills-tools.test.ts +74 -0
  8. package/src/__tests__/tools/chain.test.ts +122 -0
  9. package/src/__tests__/tools/composability-chains.test.ts +4 -2
  10. package/src/__tests__/tools/people.test.ts +9 -3
  11. package/src/__tests__/tools/works.test.ts +32 -3
  12. package/src/prompts/index.ts +97 -141
  13. package/src/prompts/public-question-atlas.ts +557 -0
  14. package/src/server.ts +123 -11
  15. package/src/skills/find-music-for-sync-brief/SKILL.md +89 -0
  16. package/src/skills/index.ts +63 -0
  17. package/src/skills/skills.generated.ts +33 -0
  18. package/src/tools/chain.ts +118 -0
  19. package/src/tools/index.ts +15 -0
  20. package/src/tools/people.ts +22 -41
  21. package/src/tools/recordings.ts +7 -3
  22. package/src/tools/search.ts +7 -4
  23. package/src/tools/skills.ts +146 -0
  24. package/src/tools/works.ts +39 -46
  25. package/dist/client.d.ts +0 -12
  26. package/dist/client.d.ts.map +0 -1
  27. package/dist/client.js +0 -93
  28. package/dist/client.js.map +0 -1
  29. package/dist/config.d.ts +0 -9
  30. package/dist/config.d.ts.map +0 -1
  31. package/dist/config.js +0 -15
  32. package/dist/config.js.map +0 -1
  33. package/dist/index.d.ts +0 -3
  34. package/dist/index.d.ts.map +0 -1
  35. package/dist/index.js +0 -28
  36. package/dist/index.js.map +0 -1
  37. package/dist/prompts/index.d.ts +0 -33
  38. package/dist/prompts/index.d.ts.map +0 -1
  39. package/dist/prompts/index.js +0 -208
  40. package/dist/prompts/index.js.map +0 -1
  41. package/dist/resources/llms-primer.d.ts +0 -2
  42. package/dist/resources/llms-primer.d.ts.map +0 -1
  43. package/dist/resources/llms-primer.js +0 -35
  44. package/dist/resources/llms-primer.js.map +0 -1
  45. package/dist/server.d.ts +0 -13
  46. package/dist/server.d.ts.map +0 -1
  47. package/dist/server.js +0 -104
  48. package/dist/server.js.map +0 -1
  49. package/dist/tools/index.d.ts +0 -26
  50. package/dist/tools/index.d.ts.map +0 -1
  51. package/dist/tools/index.js +0 -43
  52. package/dist/tools/index.js.map +0 -1
  53. package/dist/tools/people.d.ts +0 -14
  54. package/dist/tools/people.d.ts.map +0 -1
  55. package/dist/tools/people.js +0 -190
  56. package/dist/tools/people.js.map +0 -1
  57. package/dist/tools/recordings.d.ts +0 -12
  58. package/dist/tools/recordings.d.ts.map +0 -1
  59. package/dist/tools/recordings.js +0 -141
  60. package/dist/tools/recordings.js.map +0 -1
  61. package/dist/tools/search.d.ts +0 -12
  62. package/dist/tools/search.d.ts.map +0 -1
  63. package/dist/tools/search.js +0 -53
  64. package/dist/tools/search.js.map +0 -1
  65. package/dist/tools/works.d.ts +0 -15
  66. package/dist/tools/works.d.ts.map +0 -1
  67. package/dist/tools/works.js +0 -249
  68. package/dist/tools/works.js.map +0 -1
  69. package/dist/utils/errors.d.ts +0 -14
  70. package/dist/utils/errors.d.ts.map +0 -1
  71. package/dist/utils/errors.js +0 -48
  72. package/dist/utils/errors.js.map +0 -1
  73. package/dist/utils/formatting.d.ts +0 -10
  74. package/dist/utils/formatting.d.ts.map +0 -1
  75. package/dist/utils/formatting.js +0 -16
  76. package/dist/utils/formatting.js.map +0 -1
@@ -1,208 +0,0 @@
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
- export class PromptRegistry {
18
- listPrompts() {
19
- return [
20
- {
21
- name: "discover-music",
22
- description: "Find music for a sync brief, playlist, or project — search by mood, BPM, key, energy, or description. Equal discovery: results sorted by musical fit, not popularity",
23
- arguments: [
24
- {
25
- name: "brief",
26
- description: "What you're looking for — a mood, scene description, or audio characteristics",
27
- required: false,
28
- },
29
- ],
30
- },
31
- {
32
- name: "research-creator",
33
- description: "Research a songwriter, composer, or performer — full catalog, identifiers, collaborator network, rights landscape, and similarity search",
34
- arguments: [
35
- {
36
- name: "name_or_id",
37
- description: "Creator name, IPI number, ISNI, or MusicBrainz ID",
38
- required: false,
39
- },
40
- ],
41
- },
42
- ];
43
- }
44
- async getPrompt(name, args) {
45
- switch (name) {
46
- case "discover-music":
47
- return this.getDiscoverMusicSkill(args?.brief);
48
- case "research-creator":
49
- return this.getResearchCreatorSkill(args?.name_or_id);
50
- default:
51
- throw new Error(`Prompt not found: ${name}`);
52
- }
53
- }
54
- getDiscoverMusicSkill(brief) {
55
- const briefInstruction = brief
56
- ? `The user is looking for: "${brief}". Translate this into audio search parameters.`
57
- : `Ask what they're looking for — a mood, a scene, a vibe, or specific audio characteristics (BPM, key, energy).`;
58
- return {
59
- messages: [
60
- {
61
- role: "user",
62
- content: {
63
- type: "text",
64
- text: `${SHARED_PREAMBLE}
65
-
66
- --- SKILL: discover-music ---
67
-
68
- Help find music by what it sounds like, not who made it. Equal discovery — every well-catalogued work has the same chance.
69
-
70
- ${briefInstruction}
71
-
72
- Sync brief / mood-based search:
73
- → Extract parameters from natural language:
74
- mood, BPM range, key, energy, instrumentation, vocal/instrumental, duration constraints
75
- → Translate mood descriptions to search parameters for directory_search_recordings:
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
115
-
116
- If no results match, suggest broadening the search (wider BPM range, drop key filter, etc.).
117
-
118
- If the catalog is small, say so: "the directory currently has [N] works — it's growing. here's what matches from what's available."
119
-
120
- Domain knowledge:
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
126
-
127
- Tools: directory_search_recordings, directory_search, directory_lookup_work, directory_lookup_work_full, directory_lookup_person, directory_lookup_person_full`,
128
- },
129
- },
130
- ],
131
- };
132
- }
133
- getResearchCreatorSkill(nameOrId) {
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.`;
137
- return {
138
- messages: [
139
- {
140
- role: "user",
141
- content: {
142
- type: "text",
143
- text: `${SHARED_PREAMBLE}
144
-
145
- --- SKILL: research-creator ---
146
-
147
- Deep-dive on a specific creator. Full catalog, identifiers, collaborator network, rights landscape.
148
-
149
- Also handles routing that was previously in directory-autopilot:
150
- - If the user has a specific identifier to resolve (ISRC, ISWC, IPI, ISNI):
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
156
-
157
- "who do you want to learn about?"
158
-
159
- ${searchInstruction}
160
-
161
- Lookup by name, IPI, ISNI, or ISRC:
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`,
202
- },
203
- },
204
- ],
205
- };
206
- }
207
- }
208
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAgC7D,MAAM,eAAe,GAAG;;;;;;;;;;;;;;gDAcwB,CAAC;AAEjD,MAAM,OAAO,cAAc;IACzB,WAAW;QACT,OAAO;YACL;gBACE,IAAI,EAAE,gBAAgB;gBACtB,WAAW,EACT,sKAAsK;gBACxK,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,0IAA0I;gBAC5I,SAAS,EAAE;oBACT;wBACE,IAAI,EAAE,YAAY;wBAClB,WAAW,EAAE,mDAAmD;wBAChE,QAAQ,EAAE,KAAK;qBAChB;iBACF;aACF;SACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,SAAS,CACb,IAAY,EACZ,IAA0B;QAE1B,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,gBAAgB;gBACnB,OAAO,IAAI,CAAC,qBAAqB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACjD,KAAK,kBAAkB;gBACrB,OAAO,IAAI,CAAC,uBAAuB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;YACxD;gBACE,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,EAAE,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAEO,qBAAqB,CAAC,KAAc;QAC1C,MAAM,gBAAgB,GAAG,KAAK;YAC5B,CAAC,CAAC,6BAA6B,KAAK,iDAAiD;YACrF,CAAC,CAAC,+GAA+G,CAAC;QAEpH,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE;wBACP,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,GAAG,eAAe;;;;;;EAMlC,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+JAyD6I;qBACpJ;iBACF;aACF;SACF,CAAC;IACJ,CAAC;IAEO,uBAAuB,CAAC,QAAiB;QAC/C,MAAM,iBAAiB,GAAG,QAAQ;YAChC,CAAC,CAAC,aAAa,QAAQ,iKAAiK;YACxL,CAAC,CAAC,kEAAkE,CAAC;QAEvE,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE;wBACP,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,GAAG,eAAe;;;;;;;;;;;;;;;;EAgBlC,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mLA0CgK;qBACxK;iBACF;aACF;SACF,CAAC;IACJ,CAAC;CACF"}
@@ -1,2 +0,0 @@
1
- export declare const DIRECTORY_PRIMER = "# PICA Directory \u2014 Public Music Catalog Search\n\nRead-only access to published music catalog data. No authentication required.\nWorks and people are only visible if the owning organisation has opted into\nthe directory.\n\n## First Connection\n\nIf you're not sure where to start, invoke the **directory-autopilot** prompt.\nIt asks what you need and routes to the right workflow: sync search, rights\nresearch, or identifier lookup.\n\n## What You Can Do\n- Search works by title, ISWC, publisher, label\n- Search people by name, ISNI, IPI\n- Look up works by recording ISRC (directory_lookup_isrc)\n- Search recordings by audio characteristics (BPM, key, mood, energy)\n\n## What You Cannot Do\n- Create, update, or delete anything (read-only)\n- Access unpublished works or private catalog data\n- See financial data, agreements, or internal metadata\n\n## Entity Model\n- **Work**: composition with title, ISWC, credits, recordings\n- **Person**: writer/composer/performer with IPI, ISNI identifiers\n- **Recording**: audio capture with ISRC, linked to one work\n\n## Recommended Flow\n1. directory_search (broad text search across works + people)\n2. directory_lookup_work or directory_lookup_person (detailed view)\n3. directory_search_recordings (audio characteristic search for sync)\n";
2
- //# sourceMappingURL=llms-primer.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"llms-primer.d.ts","sourceRoot":"","sources":["../../src/resources/llms-primer.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,gBAAgB,wxCAgC5B,CAAC"}
@@ -1,35 +0,0 @@
1
- // Copyright (c) 2024-2026 Withpica Ltd. All rights reserved.
2
- export const DIRECTORY_PRIMER = `# PICA Directory — Public Music Catalog Search
3
-
4
- Read-only access to published music catalog data. No authentication required.
5
- Works and people are only visible if the owning organisation has opted into
6
- the directory.
7
-
8
- ## First Connection
9
-
10
- If you're not sure where to start, invoke the **directory-autopilot** prompt.
11
- It asks what you need and routes to the right workflow: sync search, rights
12
- research, or identifier lookup.
13
-
14
- ## What You Can Do
15
- - Search works by title, ISWC, publisher, label
16
- - Search people by name, ISNI, IPI
17
- - Look up works by recording ISRC (directory_lookup_isrc)
18
- - Search recordings by audio characteristics (BPM, key, mood, energy)
19
-
20
- ## What You Cannot Do
21
- - Create, update, or delete anything (read-only)
22
- - Access unpublished works or private catalog data
23
- - See financial data, agreements, or internal metadata
24
-
25
- ## Entity Model
26
- - **Work**: composition with title, ISWC, credits, recordings
27
- - **Person**: writer/composer/performer with IPI, ISNI identifiers
28
- - **Recording**: audio capture with ISRC, linked to one work
29
-
30
- ## Recommended Flow
31
- 1. directory_search (broad text search across works + people)
32
- 2. directory_lookup_work or directory_lookup_person (detailed view)
33
- 3. directory_search_recordings (audio characteristic search for sync)
34
- `;
35
- //# sourceMappingURL=llms-primer.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"llms-primer.js","sourceRoot":"","sources":["../../src/resources/llms-primer.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAE7D,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgC/B,CAAC"}
package/dist/server.d.ts DELETED
@@ -1,13 +0,0 @@
1
- import { ServerConfig } from "./config.js";
2
- export declare class DirectoryMcpServer {
3
- private server;
4
- private client;
5
- private toolRegistry;
6
- private promptRegistry;
7
- private config;
8
- constructor(config: ServerConfig);
9
- private setupHandlers;
10
- start(): Promise<void>;
11
- stop(): Promise<void>;
12
- }
13
- //# sourceMappingURL=server.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAM3C,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,MAAM,CAAe;gBAEjB,MAAM,EAAE,YAAY;IA2BhC,OAAO,CAAC,aAAa;IAkEf,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAUtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAI5B"}
package/dist/server.js DELETED
@@ -1,104 +0,0 @@
1
- // Copyright (c) 2024-2026 Withpica Ltd. All rights reserved.
2
- import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
- import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
5
- import { DirectoryClient } from "./client.js";
6
- import { ToolRegistry } from "./tools/index.js";
7
- import { PromptRegistry } from "./prompts/index.js";
8
- import { logError } from "./utils/errors.js";
9
- import { DIRECTORY_PRIMER } from "./resources/llms-primer.js";
10
- export class DirectoryMcpServer {
11
- server;
12
- client;
13
- toolRegistry;
14
- promptRegistry;
15
- config;
16
- constructor(config) {
17
- this.config = config;
18
- this.client = new DirectoryClient({
19
- baseUrl: config.directoryUrl,
20
- debug: config.debug,
21
- });
22
- this.server = new Server({
23
- name: config.serverName,
24
- version: config.version,
25
- }, {
26
- capabilities: {
27
- tools: {},
28
- resources: {},
29
- prompts: {},
30
- },
31
- });
32
- this.toolRegistry = new ToolRegistry(this.client);
33
- this.promptRegistry = new PromptRegistry();
34
- this.setupHandlers();
35
- }
36
- setupHandlers() {
37
- this.server.setRequestHandler(ListToolsRequestSchema, async () => {
38
- if (this.config.debug) {
39
- console.error("[Directory MCP] Listing tools");
40
- }
41
- return { tools: this.toolRegistry.listTools() };
42
- });
43
- this.server.setRequestHandler(ListResourcesRequestSchema, async () => {
44
- return {
45
- resources: [
46
- {
47
- uri: "llms://primer",
48
- name: "PICA Domain Primer",
49
- description: "Plain-language description of PICA's domain model, entity relationships, and recommended agent workflows. Read this first.",
50
- mimeType: "text/markdown",
51
- },
52
- ],
53
- };
54
- });
55
- this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
56
- const { uri } = request.params;
57
- if (uri === "llms://primer") {
58
- return {
59
- contents: [
60
- {
61
- uri: "llms://primer",
62
- mimeType: "text/markdown",
63
- text: DIRECTORY_PRIMER,
64
- },
65
- ],
66
- };
67
- }
68
- throw new Error(`Resource not found: ${uri}`);
69
- });
70
- this.server.setRequestHandler(ListPromptsRequestSchema, async () => {
71
- return { prompts: this.promptRegistry.listPrompts() };
72
- });
73
- this.server.setRequestHandler(GetPromptRequestSchema, async (request) => {
74
- const { name, arguments: args } = request.params;
75
- return await this.promptRegistry.getPrompt(name, args);
76
- });
77
- this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
78
- const { name, arguments: args } = request.params;
79
- if (this.config.debug) {
80
- console.error(`[Directory MCP] Executing tool: ${name}`, args);
81
- }
82
- try {
83
- return await this.toolRegistry.executeTool(name, args || {});
84
- }
85
- catch (error) {
86
- logError(`Tool execution: ${name}`, error);
87
- throw error;
88
- }
89
- });
90
- }
91
- async start() {
92
- const transport = new StdioServerTransport();
93
- await this.server.connect(transport);
94
- console.error("[Directory MCP] PICA Directory MCP Server started");
95
- console.error(`[Directory MCP] Version: ${this.config.version}`);
96
- console.error(`[Directory MCP] API URL: ${this.config.directoryUrl}`);
97
- console.error("[Directory MCP] Ready to accept connections");
98
- }
99
- async stop() {
100
- await this.server.close();
101
- console.error("[Directory MCP] Server stopped");
102
- }
103
- }
104
- //# sourceMappingURL=server.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -1,26 +0,0 @@
1
- import { DirectoryClient } from "../client.js";
2
- export interface ToolDefinition {
3
- name: string;
4
- description: string;
5
- inputSchema: {
6
- type: string;
7
- properties: Record<string, any>;
8
- required?: string[];
9
- };
10
- }
11
- export interface ToolResult {
12
- content: Array<{
13
- type: string;
14
- text: string;
15
- }>;
16
- structuredContent?: Record<string, unknown>;
17
- isError?: boolean;
18
- }
19
- export type ToolExecutor = (args: Record<string, any>) => Promise<any>;
20
- export declare class ToolRegistry {
21
- private tools;
22
- constructor(client: DirectoryClient);
23
- listTools(): ToolDefinition[];
24
- executeTool(name: string, args: Record<string, any>): Promise<any>;
25
- }
26
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAO/C,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE;QACX,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAChC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;CACH;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;AAEvE,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAGX;gBAEU,MAAM,EAAE,eAAe;IAiBnC,SAAS,IAAI,cAAc,EAAE;IAIvB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;CAgBzE"}
@@ -1,43 +0,0 @@
1
- // Copyright (c) 2024-2026 Withpica Ltd. All rights reserved.
2
- import { DirectoryWorksTools } from "./works.js";
3
- import { DirectoryPeopleTools } from "./people.js";
4
- import { DirectorySearchTools } from "./search.js";
5
- import { DirectoryRecordingsTools } from "./recordings.js";
6
- import { formatError, logError, ToolExecutionError } from "../utils/errors.js";
7
- export class ToolRegistry {
8
- tools;
9
- constructor(client) {
10
- this.tools = new Map();
11
- const groups = [
12
- new DirectoryWorksTools(client),
13
- new DirectoryPeopleTools(client),
14
- new DirectorySearchTools(client),
15
- new DirectoryRecordingsTools(client),
16
- ];
17
- for (const group of groups) {
18
- for (const tool of group.getTools()) {
19
- this.tools.set(tool.definition.name, tool);
20
- }
21
- }
22
- }
23
- listTools() {
24
- return Array.from(this.tools.values()).map((t) => t.definition);
25
- }
26
- async executeTool(name, args) {
27
- const tool = this.tools.get(name);
28
- if (!tool) {
29
- throw new ToolExecutionError(`Tool not found: ${name}`);
30
- }
31
- try {
32
- return await tool.executor(args);
33
- }
34
- catch (error) {
35
- logError(`Tool execution: ${name}`, error);
36
- return {
37
- content: [formatError(error)],
38
- isError: true,
39
- };
40
- }
41
- }
42
- }
43
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAG7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAoB/E,MAAM,OAAO,YAAY;IACf,KAAK,CAGX;IAEF,YAAY,MAAuB;QACjC,IAAI,CAAC,KAAK,GAAG,IAAI,GAAG,EAAE,CAAC;QAEvB,MAAM,MAAM,GAAG;YACb,IAAI,mBAAmB,CAAC,MAAM,CAAC;YAC/B,IAAI,oBAAoB,CAAC,MAAM,CAAC;YAChC,IAAI,oBAAoB,CAAC,MAAM,CAAC;YAChC,IAAI,wBAAwB,CAAC,MAAM,CAAC;SACrC,CAAC;QAEF,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,QAAQ,EAAE,EAAE,CAAC;gBACpC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC;IACH,CAAC;IAED,SAAS;QACP,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IAClE,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,IAAY,EAAE,IAAyB;QACvD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,kBAAkB,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAC;QAC1D,CAAC;QAED,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACnC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,QAAQ,CAAC,mBAAmB,IAAI,EAAE,EAAE,KAAK,CAAC,CAAC;YAC3C,OAAO;gBACL,OAAO,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;gBAC7B,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
@@ -1,14 +0,0 @@
1
- import { DirectoryClient } from "../client.js";
2
- import { ToolDefinition, ToolExecutor } from "./index.js";
3
- export declare class DirectoryPeopleTools {
4
- private client;
5
- constructor(client: DirectoryClient);
6
- getTools(): Array<{
7
- definition: ToolDefinition;
8
- executor: ToolExecutor;
9
- }>;
10
- private listPeople;
11
- private lookupPerson;
12
- private lookupPersonFull;
13
- }
14
- //# sourceMappingURL=people.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"people.d.ts","sourceRoot":"","sources":["../../src/tools/people.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG1D,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,MAAM,CAAkB;gBAEpB,MAAM,EAAE,eAAe;IAInC,QAAQ,IAAI,KAAK,CAAC;QAAE,UAAU,EAAE,cAAc,CAAC;QAAC,QAAQ,EAAE,YAAY,CAAA;KAAE,CAAC;YA+E3D,UAAU;YAuBV,YAAY;YAQZ,gBAAgB;CA2F/B"}