@withpica/mcp-server-directory 1.3.0 → 1.4.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 +28 -0
- package/dist/client.d.ts +12 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +93 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +9 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +15 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/changelog.d.ts +16 -0
- package/dist/lib/changelog.d.ts.map +1 -0
- package/dist/lib/changelog.generated.d.ts +4 -0
- package/dist/lib/changelog.generated.d.ts.map +1 -0
- package/dist/lib/changelog.generated.js +6 -0
- package/dist/lib/changelog.generated.js.map +1 -0
- package/dist/lib/changelog.js +84 -0
- package/dist/lib/changelog.js.map +1 -0
- package/dist/prompts/index.d.ts +32 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +165 -0
- package/dist/prompts/index.js.map +1 -0
- 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 +434 -0
- package/dist/prompts/public-question-atlas.js.map +1 -0
- package/dist/resources/llms-primer.d.ts +2 -0
- package/dist/resources/llms-primer.d.ts.map +1 -0
- package/dist/resources/llms-primer.js +35 -0
- package/dist/resources/llms-primer.js.map +1 -0
- package/dist/server.d.ts +33 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +223 -0
- package/dist/server.js.map +1 -0
- package/dist/skills/index.d.ts +32 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +50 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/skills/skills.generated.d.ts +18 -0
- package/dist/skills/skills.generated.d.ts.map +1 -0
- package/dist/skills/skills.generated.js +14 -0
- package/dist/skills/skills.generated.js.map +1 -0
- package/dist/tools/__tests__/release-notes.test.d.ts +2 -0
- package/dist/tools/__tests__/release-notes.test.d.ts.map +1 -0
- package/dist/tools/__tests__/release-notes.test.js +49 -0
- package/dist/tools/__tests__/release-notes.test.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 +36 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +49 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/people.d.ts +13 -0
- package/dist/tools/people.d.ts.map +1 -0
- package/dist/tools/people.js +177 -0
- package/dist/tools/people.js.map +1 -0
- package/dist/tools/recordings.d.ts +12 -0
- package/dist/tools/recordings.d.ts.map +1 -0
- package/dist/tools/recordings.js +145 -0
- package/dist/tools/recordings.js.map +1 -0
- package/dist/tools/release-notes.d.ts +22 -0
- package/dist/tools/release-notes.d.ts.map +1 -0
- package/dist/tools/release-notes.js +102 -0
- package/dist/tools/release-notes.js.map +1 -0
- package/dist/tools/search.d.ts +12 -0
- package/dist/tools/search.d.ts.map +1 -0
- package/dist/tools/search.js +56 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/skills.d.ts +19 -0
- package/dist/tools/skills.d.ts.map +1 -0
- package/dist/tools/skills.js +127 -0
- package/dist/tools/skills.js.map +1 -0
- package/dist/tools/works.d.ts +14 -0
- package/dist/tools/works.d.ts.map +1 -0
- package/dist/tools/works.js +248 -0
- package/dist/tools/works.js.map +1 -0
- package/dist/utils/errors.d.ts +14 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +48 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/formatting.d.ts +10 -0
- package/dist/utils/formatting.d.ts.map +1 -0
- package/dist/utils/formatting.js +16 -0
- package/dist/utils/formatting.js.map +1 -0
- package/package.json +4 -3
- package/scripts/build-changelog.ts +25 -0
- package/src/lib/changelog.ts +119 -0
- package/src/prompts/public-question-atlas.ts +19 -10
- package/src/server.ts +19 -0
- package/src/tools/__tests__/release-notes.test.ts +62 -0
- package/src/tools/index.ts +2 -0
- package/src/tools/release-notes.ts +148 -0
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,34 @@ for breaking tool-surface changes.
|
|
|
8
8
|
|
|
9
9
|
## [Unreleased]
|
|
10
10
|
|
|
11
|
+
## [1.4.0] - 2026-05-13
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **`directory_release_notes` tool + `release-notes://withpica/mcp-server-directory/latest` Resource (PR #414).**
|
|
16
|
+
Agent-facing surface for directory MCP release notes. Reads `CHANGELOG.md`
|
|
17
|
+
embedded at build time via `scripts/build-changelog.ts`. Returns the
|
|
18
|
+
last 3 versions by default with optional `since_version` and `sections`
|
|
19
|
+
filters. Resource counterpart serves the full CHANGELOG for
|
|
20
|
+
Resource-native clients. Sister of `pica_release_notes` (creator MCP)
|
|
21
|
+
and `team_release_notes` (team MCP). Disambiguated from catalogue-content
|
|
22
|
+
searches (`directory_search` / `directory_list_works` / `directory_chain`)
|
|
23
|
+
by the NOT-FOR clause in the description.
|
|
24
|
+
|
|
25
|
+
## [1.3.0] - 2026-05-11
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- **`directory_skill_list` + `directory_skill_get` — skill discovery on the public directory MCP (ADR-140 Phase 2b, PR #371).**
|
|
30
|
+
Lazy-loaded skill catalogue exposed via two meta-tools + one `skill://`
|
|
31
|
+
Resource per shipped skill (SEP-2640 bridge pattern). v1 ships
|
|
32
|
+
`find-music-for-sync-brief` — a methodology for searching the public
|
|
33
|
+
directory by audio characteristics + free-text brief. Skill metadata is
|
|
34
|
+
static at boot; bodies load on `skill_get` call. IP-protection lint
|
|
35
|
+
(Rule 14) gates skill content against trade-secret directories before
|
|
36
|
+
publish; cross-coverage parity lint asserts skill resource URIs match
|
|
37
|
+
between stdio and HTTP transports.
|
|
38
|
+
|
|
11
39
|
## [1.1.0] - 2026-04-21
|
|
12
40
|
|
|
13
41
|
Shipped as minor rather than major despite the `*_full` tool removal:
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface DirectoryClientConfig {
|
|
2
|
+
baseUrl: string;
|
|
3
|
+
debug?: boolean;
|
|
4
|
+
}
|
|
5
|
+
export declare class DirectoryClient {
|
|
6
|
+
private baseUrl;
|
|
7
|
+
private debug;
|
|
8
|
+
constructor(config: DirectoryClientConfig);
|
|
9
|
+
private fetchWithTimeout;
|
|
10
|
+
request<T>(path: string, params?: Record<string, string>): Promise<T>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,KAAK,CAAU;gBAEX,MAAM,EAAE,qBAAqB;YAK3B,gBAAgB;IAmBxB,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CAgF5E"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// Copyright (c) 2024-2026 Withpica Ltd. All rights reserved.
|
|
2
|
+
const DEFAULT_TIMEOUT_MS = 15_000;
|
|
3
|
+
const MAX_RETRIES = 2;
|
|
4
|
+
const RETRY_BASE_MS = 500;
|
|
5
|
+
function isRetryableStatus(status) {
|
|
6
|
+
return status === 429 || status === 502 || status === 503 || status === 504;
|
|
7
|
+
}
|
|
8
|
+
function sleep(ms) {
|
|
9
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
10
|
+
}
|
|
11
|
+
export class DirectoryClient {
|
|
12
|
+
baseUrl;
|
|
13
|
+
debug;
|
|
14
|
+
constructor(config) {
|
|
15
|
+
this.baseUrl = config.baseUrl.replace(/\/$/, "");
|
|
16
|
+
this.debug = config.debug || false;
|
|
17
|
+
}
|
|
18
|
+
async fetchWithTimeout(url, init, timeoutMs) {
|
|
19
|
+
const controller = new AbortController();
|
|
20
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
21
|
+
try {
|
|
22
|
+
return await fetch(url, { ...init, signal: controller.signal });
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
if (err.name === "AbortError") {
|
|
26
|
+
throw new Error(`Request timed out after ${timeoutMs}ms: GET ${url}`);
|
|
27
|
+
}
|
|
28
|
+
throw err;
|
|
29
|
+
}
|
|
30
|
+
finally {
|
|
31
|
+
clearTimeout(timer);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async request(path, params) {
|
|
35
|
+
const url = new URL(`${this.baseUrl}/api/public/directory${path}`);
|
|
36
|
+
if (params) {
|
|
37
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
38
|
+
if (value !== undefined && value !== "") {
|
|
39
|
+
url.searchParams.set(key, value);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
if (this.debug) {
|
|
44
|
+
console.error(`[Directory MCP] GET ${url.toString()} (timeout: ${DEFAULT_TIMEOUT_MS}ms)`);
|
|
45
|
+
}
|
|
46
|
+
let lastError;
|
|
47
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
48
|
+
try {
|
|
49
|
+
const response = await this.fetchWithTimeout(url.toString(), { method: "GET", headers: { Accept: "application/json" } }, DEFAULT_TIMEOUT_MS);
|
|
50
|
+
if (response.ok) {
|
|
51
|
+
const json = await response.json();
|
|
52
|
+
if (json.success === false) {
|
|
53
|
+
throw new Error(json.error || "API returned unsuccessful response");
|
|
54
|
+
}
|
|
55
|
+
return json;
|
|
56
|
+
}
|
|
57
|
+
const errorText = await response.text();
|
|
58
|
+
// Auth errors — fail fast, never retry
|
|
59
|
+
if (response.status === 401 || response.status === 403) {
|
|
60
|
+
throw new Error(`Authentication failed: ${response.status} ${errorText}`);
|
|
61
|
+
}
|
|
62
|
+
if (isRetryableStatus(response.status) && attempt < MAX_RETRIES) {
|
|
63
|
+
const retryAfter = response.headers.get("retry-after");
|
|
64
|
+
const parsed = retryAfter ? parseInt(retryAfter, 10) : NaN;
|
|
65
|
+
const delayMs = !isNaN(parsed)
|
|
66
|
+
? parsed * 1000
|
|
67
|
+
: RETRY_BASE_MS * Math.pow(2, attempt);
|
|
68
|
+
if (this.debug) {
|
|
69
|
+
console.error(`[Directory MCP] ${response.status} on attempt ${attempt + 1}, retrying in ${delayMs}ms`);
|
|
70
|
+
}
|
|
71
|
+
await sleep(delayMs);
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
throw new Error(`API request failed: ${response.status} ${errorText}`);
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
lastError = err;
|
|
78
|
+
if (err.message?.includes("timed out") &&
|
|
79
|
+
attempt < MAX_RETRIES) {
|
|
80
|
+
const delayMs = RETRY_BASE_MS * Math.pow(2, attempt);
|
|
81
|
+
if (this.debug) {
|
|
82
|
+
console.error(`[Directory MCP] timeout on attempt ${attempt + 1}, retrying in ${delayMs}ms`);
|
|
83
|
+
}
|
|
84
|
+
await sleep(delayMs);
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
throw err;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
throw lastError || new Error("Request failed after retries");
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface ServerConfig {
|
|
2
|
+
directoryUrl: string;
|
|
3
|
+
serverName: string;
|
|
4
|
+
version: string;
|
|
5
|
+
debug: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function loadConfig(): ServerConfig;
|
|
8
|
+
export declare function validateConfig(config: ServerConfig): void;
|
|
9
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,wBAAgB,UAAU,IAAI,YAAY,CAOzC;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAIzD"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Copyright (c) 2024-2026 Withpica Ltd. All rights reserved.
|
|
2
|
+
export function loadConfig() {
|
|
3
|
+
return {
|
|
4
|
+
directoryUrl: process.env.PICA_DIRECTORY_URL || "https://withpica.com",
|
|
5
|
+
serverName: "pica-directory-mcp-server",
|
|
6
|
+
version: "1.0.0",
|
|
7
|
+
debug: process.env.DEBUG === "true" || process.env.DEBUG === "1",
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export function validateConfig(config) {
|
|
11
|
+
if (!config.directoryUrl || !config.directoryUrl.startsWith("http")) {
|
|
12
|
+
throw new Error("Invalid PICA_DIRECTORY_URL");
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAS7D,MAAM,UAAU,UAAU;IACxB,OAAO;QACL,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,sBAAsB;QACtE,UAAU,EAAE,2BAA2B;QACvC,OAAO,EAAE,OAAO;QAChB,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,GAAG;KACjE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAoB;IACjD,IAAI,CAAC,MAAM,CAAC,YAAY,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAChD,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Copyright (c) 2024-2026 Withpica Ltd. All rights reserved.
|
|
3
|
+
import { loadConfig, validateConfig } from "./config.js";
|
|
4
|
+
import { DirectoryMcpServer } from "./server.js";
|
|
5
|
+
async function main() {
|
|
6
|
+
try {
|
|
7
|
+
const config = loadConfig();
|
|
8
|
+
validateConfig(config);
|
|
9
|
+
const server = new DirectoryMcpServer(config);
|
|
10
|
+
await server.start();
|
|
11
|
+
process.on("SIGINT", async () => {
|
|
12
|
+
console.error("[Directory MCP] Shutting down...");
|
|
13
|
+
await server.stop();
|
|
14
|
+
process.exit(0);
|
|
15
|
+
});
|
|
16
|
+
process.on("SIGTERM", async () => {
|
|
17
|
+
console.error("[Directory MCP] Shutting down...");
|
|
18
|
+
await server.stop();
|
|
19
|
+
process.exit(0);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
console.error("[Directory MCP] Fatal error:", error instanceof Error ? error.message : String(error));
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
main();
|
|
28
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,6DAA6D;AAG7D,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;QAC5B,cAAc,CAAC,MAAM,CAAC,CAAC;QAEvB,MAAM,MAAM,GAAG,IAAI,kBAAkB,CAAC,MAAM,CAAC,CAAC;QAC9C,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QAErB,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;YAC9B,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;YAClD,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE;YAC/B,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;YAClD,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CACX,8BAA8B,EAC9B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CACvD,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime CHANGELOG parser. Mirrors scripts/parse-changelog.ts but takes
|
|
3
|
+
* the markdown body as a string (no fs dependency) so the MCP runtime
|
|
4
|
+
* can read from a build-time embedded constant. Sister of
|
|
5
|
+
* mcp-server/src/lib/changelog.ts and team-mcp-server/src/lib/changelog.ts.
|
|
6
|
+
*/
|
|
7
|
+
export type ChangelogSectionName = "Added" | "Changed" | "Fixed" | "Removed" | "Security" | "Deprecated";
|
|
8
|
+
export declare const CHANGELOG_SECTION_NAMES: ChangelogSectionName[];
|
|
9
|
+
export interface ChangelogEntry {
|
|
10
|
+
version: string;
|
|
11
|
+
date: string | null;
|
|
12
|
+
sections: Partial<Record<ChangelogSectionName, string[]>>;
|
|
13
|
+
markdown: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function parseChangelogText(text: string): ChangelogEntry[];
|
|
16
|
+
//# sourceMappingURL=changelog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changelog.d.ts","sourceRoot":"","sources":["../../src/lib/changelog.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH,MAAM,MAAM,oBAAoB,GAC5B,OAAO,GACP,SAAS,GACT,OAAO,GACP,SAAS,GACT,UAAU,GACV,YAAY,CAAC;AAEjB,eAAO,MAAM,uBAAuB,EAAE,oBAAoB,EAOzD,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,oBAAoB,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IAC1D,QAAQ,EAAE,MAAM,CAAC;CAClB;AAMD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE,CAiFjE"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const CHANGELOG_MD = "# Changelog\n\nAll notable changes to `@withpica/mcp-server-directory` are documented here.\n\nThe format is loosely based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),\nand this project adheres to semantic versioning where the major number is incremented\nfor breaking tool-surface changes.\n\n## [Unreleased]\n\n## [1.4.0] - 2026-05-13\n\n### Added\n\n- **`directory_release_notes` tool + `release-notes://withpica/mcp-server-directory/latest` Resource (PR #414).**\n Agent-facing surface for directory MCP release notes. Reads `CHANGELOG.md`\n embedded at build time via `scripts/build-changelog.ts`. Returns the\n last 3 versions by default with optional `since_version` and `sections`\n filters. Resource counterpart serves the full CHANGELOG for\n Resource-native clients. Sister of `pica_release_notes` (creator MCP)\n and `team_release_notes` (team MCP). Disambiguated from catalogue-content\n searches (`directory_search` / `directory_list_works` / `directory_chain`)\n by the NOT-FOR clause in the description.\n\n## [1.3.0] - 2026-05-11\n\n### Added\n\n- **`directory_skill_list` + `directory_skill_get` \u2014 skill discovery on the public directory MCP (ADR-140 Phase 2b, PR #371).**\n Lazy-loaded skill catalogue exposed via two meta-tools + one `skill://`\n Resource per shipped skill (SEP-2640 bridge pattern). v1 ships\n `find-music-for-sync-brief` \u2014 a methodology for searching the public\n directory by audio characteristics + free-text brief. Skill metadata is\n static at boot; bodies load on `skill_get` call. IP-protection lint\n (Rule 14) gates skill content against trade-secret directories before\n publish; cross-coverage parity lint asserts skill resource URIs match\n between stdio and HTTP transports.\n\n## [1.1.0] - 2026-04-21\n\nShipped as minor rather than major despite the `*_full` tool removal:\nthe removed names had near-zero external adoption (they shipped recently\nand weren't advertised externally), and staying on the 1.x line keeps\n`^1.0.0` consumers on the upgrade path rather than stranding them on\nthe broken cascade. Clients that cached the `*_full` names will see a\ntool-not-found error and need to refresh their tool list.\n\n### Breaking\n\n- **Removed `directory_lookup_person_full` and `directory_lookup_work_full`.**\n Both tools hit the same upstream endpoints as their non-`_full` counterparts\n with only a formatting difference \u2014 there was no capability delta. The\n `_full` variants are now the canonical names (`directory_lookup_person`\n and `directory_lookup_work`); the thin variants have been deleted. Clients\n that cached the `_full` names need to update their tool list; the\n replacements return a superset of the prior data, so no output is lost.\n\n### Added\n\n- **`directory_chain` tool** \u2014 one-call rights-chain lookup. Accepts a\n free-text query, a direct ISWC/ISRC `identifier`, or audio-only filters\n (BPM / key / energy / mood). Returns the already-public `ChainResult`\n shape: work + writers + publishers (names + roles only, no IPIs or\n splits) + linked recording + audio characteristics. Wraps the existing\n public `/api/public/directory/chain` endpoint \u2014 no new backing API work.\n- `directory_list_people` now accepts `letter` (A\u2013Z, `#`) for alphabetical\n browsing. The backend has supported this for months; only the MCP tool\n was missing the parameter.\n- `directory_list_works` now accepts `letter`, `sort` (`title` | `recent`),\n and `isrc` \u2014 all previously backend-only.\n\n### Changed\n\n- **`directory_lookup_person` now matches its description.** Previously the\n tool advertised ISNI / IPI / MusicBrainz ID support but the backing query\n only matched `global_creator_id` \u2014 any non-UUID identifier silently 404'd.\n The query now cascades through `global_creator_id` \u2192 `isni` \u2192\n `cae_ipi_number` \u2192 `musicbrainz_id`, first hit wins.\n- `directory_search` description rewritten to drop the false \"ranked\" claim.\n The backing endpoint is a fan-out (`listWorks` + `listPeople`,\n half-limit each), not cross-type ranking. Callers should prefer typed\n list tools when they know the entity type.\n- `directory_lookup_isrc` description rewritten to frame it honestly as a\n pinned filter preset on `list_works` rather than a distinct lookup.\n";
|
|
2
|
+
export declare const PACKAGE_NAME = "@withpica/mcp-server-directory";
|
|
3
|
+
export declare const PACKAGE_VERSION = "1.4.0";
|
|
4
|
+
//# sourceMappingURL=changelog.generated.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changelog.generated.d.ts","sourceRoot":"","sources":["../../src/lib/changelog.generated.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,YAAY,+vIAAwsI,CAAC;AACluI,eAAO,MAAM,YAAY,mCAAmC,CAAC;AAC7D,eAAO,MAAM,eAAe,UAAU,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Copyright (c) 2024-2026 Withpica Ltd. All rights reserved.
|
|
2
|
+
// Generated by scripts/build-changelog.ts — do not edit.
|
|
3
|
+
export const CHANGELOG_MD = "# Changelog\n\nAll notable changes to `@withpica/mcp-server-directory` are documented here.\n\nThe format is loosely based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),\nand this project adheres to semantic versioning where the major number is incremented\nfor breaking tool-surface changes.\n\n## [Unreleased]\n\n## [1.4.0] - 2026-05-13\n\n### Added\n\n- **`directory_release_notes` tool + `release-notes://withpica/mcp-server-directory/latest` Resource (PR #414).**\n Agent-facing surface for directory MCP release notes. Reads `CHANGELOG.md`\n embedded at build time via `scripts/build-changelog.ts`. Returns the\n last 3 versions by default with optional `since_version` and `sections`\n filters. Resource counterpart serves the full CHANGELOG for\n Resource-native clients. Sister of `pica_release_notes` (creator MCP)\n and `team_release_notes` (team MCP). Disambiguated from catalogue-content\n searches (`directory_search` / `directory_list_works` / `directory_chain`)\n by the NOT-FOR clause in the description.\n\n## [1.3.0] - 2026-05-11\n\n### Added\n\n- **`directory_skill_list` + `directory_skill_get` — skill discovery on the public directory MCP (ADR-140 Phase 2b, PR #371).**\n Lazy-loaded skill catalogue exposed via two meta-tools + one `skill://`\n Resource per shipped skill (SEP-2640 bridge pattern). v1 ships\n `find-music-for-sync-brief` — a methodology for searching the public\n directory by audio characteristics + free-text brief. Skill metadata is\n static at boot; bodies load on `skill_get` call. IP-protection lint\n (Rule 14) gates skill content against trade-secret directories before\n publish; cross-coverage parity lint asserts skill resource URIs match\n between stdio and HTTP transports.\n\n## [1.1.0] - 2026-04-21\n\nShipped as minor rather than major despite the `*_full` tool removal:\nthe removed names had near-zero external adoption (they shipped recently\nand weren't advertised externally), and staying on the 1.x line keeps\n`^1.0.0` consumers on the upgrade path rather than stranding them on\nthe broken cascade. Clients that cached the `*_full` names will see a\ntool-not-found error and need to refresh their tool list.\n\n### Breaking\n\n- **Removed `directory_lookup_person_full` and `directory_lookup_work_full`.**\n Both tools hit the same upstream endpoints as their non-`_full` counterparts\n with only a formatting difference — there was no capability delta. The\n `_full` variants are now the canonical names (`directory_lookup_person`\n and `directory_lookup_work`); the thin variants have been deleted. Clients\n that cached the `_full` names need to update their tool list; the\n replacements return a superset of the prior data, so no output is lost.\n\n### Added\n\n- **`directory_chain` tool** — one-call rights-chain lookup. Accepts a\n free-text query, a direct ISWC/ISRC `identifier`, or audio-only filters\n (BPM / key / energy / mood). Returns the already-public `ChainResult`\n shape: work + writers + publishers (names + roles only, no IPIs or\n splits) + linked recording + audio characteristics. Wraps the existing\n public `/api/public/directory/chain` endpoint — no new backing API work.\n- `directory_list_people` now accepts `letter` (A–Z, `#`) for alphabetical\n browsing. The backend has supported this for months; only the MCP tool\n was missing the parameter.\n- `directory_list_works` now accepts `letter`, `sort` (`title` | `recent`),\n and `isrc` — all previously backend-only.\n\n### Changed\n\n- **`directory_lookup_person` now matches its description.** Previously the\n tool advertised ISNI / IPI / MusicBrainz ID support but the backing query\n only matched `global_creator_id` — any non-UUID identifier silently 404'd.\n The query now cascades through `global_creator_id` → `isni` →\n `cae_ipi_number` → `musicbrainz_id`, first hit wins.\n- `directory_search` description rewritten to drop the false \"ranked\" claim.\n The backing endpoint is a fan-out (`listWorks` + `listPeople`,\n half-limit each), not cross-type ranking. Callers should prefer typed\n list tools when they know the entity type.\n- `directory_lookup_isrc` description rewritten to frame it honestly as a\n pinned filter preset on `list_works` rather than a distinct lookup.\n";
|
|
4
|
+
export const PACKAGE_NAME = "@withpica/mcp-server-directory";
|
|
5
|
+
export const PACKAGE_VERSION = "1.4.0";
|
|
6
|
+
//# sourceMappingURL=changelog.generated.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changelog.generated.js","sourceRoot":"","sources":["../../src/lib/changelog.generated.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,yDAAyD;AAEzD,MAAM,CAAC,MAAM,YAAY,GAAG,qsIAAqsI,CAAC;AACluI,MAAM,CAAC,MAAM,YAAY,GAAG,gCAAgC,CAAC;AAC7D,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// Copyright (c) 2024-2026 Withpica Ltd. All rights reserved.
|
|
2
|
+
export const CHANGELOG_SECTION_NAMES = [
|
|
3
|
+
"Added",
|
|
4
|
+
"Changed",
|
|
5
|
+
"Fixed",
|
|
6
|
+
"Removed",
|
|
7
|
+
"Security",
|
|
8
|
+
"Deprecated",
|
|
9
|
+
];
|
|
10
|
+
const HEADING_RE = /^##\s+\[([^\]]+)\](?:\s*-\s*(\d{4}-\d{2}-\d{2}))?\s*$/;
|
|
11
|
+
const SECTION_RE = /^###\s+(\w+)\s*$/;
|
|
12
|
+
const BULLET_RE = /^-\s+(.*)$/;
|
|
13
|
+
export function parseChangelogText(text) {
|
|
14
|
+
const lines = text.split("\n");
|
|
15
|
+
const entries = [];
|
|
16
|
+
let current = null;
|
|
17
|
+
let currentSection = null;
|
|
18
|
+
let currentBullet = null;
|
|
19
|
+
const flush = (endLine) => {
|
|
20
|
+
if (current && current.version !== "Unreleased") {
|
|
21
|
+
current.markdown = lines
|
|
22
|
+
.slice(current._start, endLine)
|
|
23
|
+
.join("\n")
|
|
24
|
+
.trimEnd();
|
|
25
|
+
const { _start: _start, ...rest } = current;
|
|
26
|
+
entries.push(rest);
|
|
27
|
+
}
|
|
28
|
+
current = null;
|
|
29
|
+
currentSection = null;
|
|
30
|
+
currentBullet = null;
|
|
31
|
+
};
|
|
32
|
+
for (let i = 0; i < lines.length; i++) {
|
|
33
|
+
const line = lines[i];
|
|
34
|
+
const headingMatch = line.match(HEADING_RE);
|
|
35
|
+
if (headingMatch) {
|
|
36
|
+
flush(i);
|
|
37
|
+
current = {
|
|
38
|
+
version: headingMatch[1],
|
|
39
|
+
date: headingMatch[2] ?? null,
|
|
40
|
+
sections: {},
|
|
41
|
+
markdown: "",
|
|
42
|
+
_start: i,
|
|
43
|
+
};
|
|
44
|
+
currentSection = null;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (!current)
|
|
48
|
+
continue;
|
|
49
|
+
const sectionMatch = line.match(SECTION_RE);
|
|
50
|
+
if (sectionMatch) {
|
|
51
|
+
const name = sectionMatch[1];
|
|
52
|
+
if (CHANGELOG_SECTION_NAMES.includes(name)) {
|
|
53
|
+
currentSection = name;
|
|
54
|
+
if (!current.sections[name])
|
|
55
|
+
current.sections[name] = [];
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
currentSection = null;
|
|
59
|
+
}
|
|
60
|
+
currentBullet = null;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const bulletMatch = line.match(BULLET_RE);
|
|
64
|
+
if (bulletMatch && currentSection) {
|
|
65
|
+
const arr = current.sections[currentSection];
|
|
66
|
+
arr.push(bulletMatch[1].trim());
|
|
67
|
+
currentBullet = {
|
|
68
|
+
entry: current,
|
|
69
|
+
section: currentSection,
|
|
70
|
+
index: arr.length - 1,
|
|
71
|
+
};
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
if (currentBullet && line.startsWith(" ") && line.trim().length > 0) {
|
|
75
|
+
const arr = currentBullet.entry.sections[currentBullet.section];
|
|
76
|
+
arr[currentBullet.index] = `${arr[currentBullet.index]} ${line.trim()}`;
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
currentBullet = null;
|
|
80
|
+
}
|
|
81
|
+
flush(lines.length);
|
|
82
|
+
return entries;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=changelog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changelog.js","sourceRoot":"","sources":["../../src/lib/changelog.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompt Registry for Directory MCP Server
|
|
3
|
+
* Guided workflows for music discovery, sync licensing, and rights research
|
|
4
|
+
*/
|
|
5
|
+
export interface PromptDefinition {
|
|
6
|
+
name: string;
|
|
7
|
+
description: string;
|
|
8
|
+
arguments?: Array<{
|
|
9
|
+
name: string;
|
|
10
|
+
description: string;
|
|
11
|
+
required?: boolean;
|
|
12
|
+
}>;
|
|
13
|
+
}
|
|
14
|
+
export interface PromptMessage {
|
|
15
|
+
role: "user" | "assistant";
|
|
16
|
+
content: {
|
|
17
|
+
type: string;
|
|
18
|
+
text: string;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export interface PromptResult {
|
|
22
|
+
messages: PromptMessage[];
|
|
23
|
+
[key: string]: unknown;
|
|
24
|
+
}
|
|
25
|
+
export declare class PromptRegistry {
|
|
26
|
+
listPrompts(): PromptDefinition[];
|
|
27
|
+
getPrompt(name: string, args?: Record<string, any>): Promise<PromptResult>;
|
|
28
|
+
private getFindMusicPrompt;
|
|
29
|
+
private getResearchCreatorPrompt;
|
|
30
|
+
private getDirectoryAutopilotPrompt;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,165 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|