curatedmcp 2.0.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/LICENSE +21 -0
- package/README.md +175 -0
- package/dist/audit/catalog.d.ts +5 -0
- package/dist/audit/catalog.d.ts.map +1 -0
- package/dist/audit/catalog.js +69 -0
- package/dist/audit/index.d.ts +10 -0
- package/dist/audit/index.d.ts.map +1 -0
- package/dist/audit/index.js +32 -0
- package/dist/audit/report.d.ts +6 -0
- package/dist/audit/report.d.ts.map +1 -0
- package/dist/audit/report.js +79 -0
- package/dist/audit/risk.d.ts +3 -0
- package/dist/audit/risk.d.ts.map +1 -0
- package/dist/audit/risk.js +68 -0
- package/dist/audit/scanner.d.ts +8 -0
- package/dist/audit/scanner.d.ts.map +1 -0
- package/dist/audit/scanner.js +69 -0
- package/dist/audit/types.d.ts +29 -0
- package/dist/audit/types.d.ts.map +1 -0
- package/dist/audit/types.js +2 -0
- package/dist/auth.d.ts +23 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +52 -0
- package/dist/cli/add.d.ts +18 -0
- package/dist/cli/add.d.ts.map +1 -0
- package/dist/cli/add.js +114 -0
- package/dist/cli/audit.d.ts +2 -0
- package/dist/cli/audit.d.ts.map +1 -0
- package/dist/cli/audit.js +58 -0
- package/dist/cli/guard.d.ts +2 -0
- package/dist/cli/guard.d.ts.map +1 -0
- package/dist/cli/guard.js +58 -0
- package/dist/cli/init.d.ts +2 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +44 -0
- package/dist/cli/list.d.ts +5 -0
- package/dist/cli/list.d.ts.map +1 -0
- package/dist/cli/list.js +33 -0
- package/dist/cli/login.d.ts +6 -0
- package/dist/cli/login.d.ts.map +1 -0
- package/dist/cli/login.js +43 -0
- package/dist/cli/remove.d.ts +6 -0
- package/dist/cli/remove.d.ts.map +1 -0
- package/dist/cli/remove.js +15 -0
- package/dist/cli/sync.d.ts +2 -0
- package/dist/cli/sync.d.ts.map +1 -0
- package/dist/cli/sync.js +104 -0
- package/dist/cli.d.ts +10 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +132 -0
- package/dist/guard/broker.d.ts +62 -0
- package/dist/guard/broker.d.ts.map +1 -0
- package/dist/guard/broker.js +147 -0
- package/dist/guard/dashboard.d.ts +14 -0
- package/dist/guard/dashboard.d.ts.map +1 -0
- package/dist/guard/dashboard.js +428 -0
- package/dist/guard/default-policy.json +33 -0
- package/dist/guard/index.d.ts +20 -0
- package/dist/guard/index.d.ts.map +1 -0
- package/dist/guard/index.js +61 -0
- package/dist/guard/logger.d.ts +30 -0
- package/dist/guard/logger.d.ts.map +1 -0
- package/dist/guard/logger.js +118 -0
- package/dist/guard/policy.d.ts +19 -0
- package/dist/guard/policy.d.ts.map +1 -0
- package/dist/guard/policy.js +108 -0
- package/dist/guard/proxy.d.ts +29 -0
- package/dist/guard/proxy.d.ts.map +1 -0
- package/dist/guard/proxy.js +109 -0
- package/dist/guard/types.d.ts +70 -0
- package/dist/guard/types.d.ts.map +1 -0
- package/dist/guard/types.js +2 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +259 -0
- package/dist/proxy.d.ts +122 -0
- package/dist/proxy.d.ts.map +1 -0
- package/dist/proxy.js +165 -0
- package/dist/stack.d.ts +45 -0
- package/dist/stack.d.ts.map +1 -0
- package/dist/stack.js +93 -0
- package/dist/telemetry.d.ts +15 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +71 -0
- package/dist/tools/get-details.d.ts +14 -0
- package/dist/tools/get-details.d.ts.map +1 -0
- package/dist/tools/get-details.js +27 -0
- package/dist/tools/install.d.ts +2 -0
- package/dist/tools/install.d.ts.map +1 -0
- package/dist/tools/install.js +74 -0
- package/dist/tools/list-categories.d.ts +2 -0
- package/dist/tools/list-categories.d.ts.map +1 -0
- package/dist/tools/list-categories.js +13 -0
- package/dist/tools/search.d.ts +16 -0
- package/dist/tools/search.d.ts.map +1 -0
- package/dist/tools/search.js +17 -0
- package/package.json +78 -0
package/dist/stack.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stack — read/write the user's local MCP server registry at ~/.curatedmcp/stack.json
|
|
3
|
+
*
|
|
4
|
+
* This is the source of truth for which MCP servers Launcher proxies. It's intentionally
|
|
5
|
+
* file-based (no cloud sync, no auth) so users own their config and can hand-edit if they want.
|
|
6
|
+
*
|
|
7
|
+
* Schema is versioned so we can migrate forward without breaking older installs.
|
|
8
|
+
*/
|
|
9
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, renameSync, } from "fs";
|
|
10
|
+
import { homedir } from "os";
|
|
11
|
+
import { join } from "path";
|
|
12
|
+
const CONFIG_DIR = join(homedir(), ".curatedmcp");
|
|
13
|
+
const STACK_FILE = join(CONFIG_DIR, "stack.json");
|
|
14
|
+
const EMPTY_STACK = { version: 1, entries: [] };
|
|
15
|
+
/** Returns the path to stack.json (so callers can show it to users). */
|
|
16
|
+
export function stackPath() {
|
|
17
|
+
return STACK_FILE;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Read the stack from disk.
|
|
21
|
+
* Returns an empty stack if the file is missing, unreadable, or malformed —
|
|
22
|
+
* so a corrupt config never crashes the launcher.
|
|
23
|
+
*/
|
|
24
|
+
export function readStack() {
|
|
25
|
+
if (!existsSync(STACK_FILE))
|
|
26
|
+
return { ...EMPTY_STACK, entries: [] };
|
|
27
|
+
try {
|
|
28
|
+
const raw = readFileSync(STACK_FILE, "utf-8");
|
|
29
|
+
const parsed = JSON.parse(raw);
|
|
30
|
+
if (!parsed || parsed.version !== 1 || !Array.isArray(parsed.entries)) {
|
|
31
|
+
console.error(`[stack] ${STACK_FILE} has unexpected shape; treating as empty.`);
|
|
32
|
+
return { ...EMPTY_STACK, entries: [] };
|
|
33
|
+
}
|
|
34
|
+
return { version: 1, entries: parsed.entries.filter(isValidEntry) };
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
console.error(`[stack] Failed to read ${STACK_FILE}:`, err);
|
|
38
|
+
return { ...EMPTY_STACK, entries: [] };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Atomically write the stack to disk.
|
|
43
|
+
* Writes to a temp sibling file, then renames — avoids a half-written file
|
|
44
|
+
* if the process is killed mid-write.
|
|
45
|
+
*/
|
|
46
|
+
export function writeStack(stack) {
|
|
47
|
+
if (!existsSync(CONFIG_DIR)) {
|
|
48
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
49
|
+
}
|
|
50
|
+
const tmp = `${STACK_FILE}.tmp-${process.pid}`;
|
|
51
|
+
writeFileSync(tmp, JSON.stringify(stack, null, 2) + "\n", "utf-8");
|
|
52
|
+
renameSync(tmp, STACK_FILE);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Add or replace an entry by slug. If an entry with the same slug exists,
|
|
56
|
+
* it's overwritten (so calling `add` twice updates env vars cleanly).
|
|
57
|
+
*/
|
|
58
|
+
export function upsertEntry(entry) {
|
|
59
|
+
const stack = readStack();
|
|
60
|
+
const idx = stack.entries.findIndex((e) => e.slug === entry.slug);
|
|
61
|
+
const stamped = {
|
|
62
|
+
...entry,
|
|
63
|
+
addedAt: entry.addedAt ?? new Date().toISOString(),
|
|
64
|
+
};
|
|
65
|
+
if (idx >= 0) {
|
|
66
|
+
stack.entries[idx] = stamped;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
stack.entries.push(stamped);
|
|
70
|
+
}
|
|
71
|
+
writeStack(stack);
|
|
72
|
+
return stack;
|
|
73
|
+
}
|
|
74
|
+
/** Remove an entry by slug. No-op (returns false) if it wasn't there. */
|
|
75
|
+
export function removeEntry(slug) {
|
|
76
|
+
const stack = readStack();
|
|
77
|
+
const before = stack.entries.length;
|
|
78
|
+
stack.entries = stack.entries.filter((e) => e.slug !== slug);
|
|
79
|
+
if (stack.entries.length === before)
|
|
80
|
+
return false;
|
|
81
|
+
writeStack(stack);
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
function isValidEntry(e) {
|
|
85
|
+
if (!e || typeof e !== "object")
|
|
86
|
+
return false;
|
|
87
|
+
const x = e;
|
|
88
|
+
return (typeof x.slug === "string" &&
|
|
89
|
+
typeof x.command === "string" &&
|
|
90
|
+
Array.isArray(x.args) &&
|
|
91
|
+
x.args.every((a) => typeof a === "string"));
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=stack.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
interface Event {
|
|
2
|
+
event: "search" | "install" | "details" | "list-categories";
|
|
3
|
+
slug: string | null;
|
|
4
|
+
client: string | null;
|
|
5
|
+
query: string | null;
|
|
6
|
+
}
|
|
7
|
+
export declare class Telemetry {
|
|
8
|
+
private anonId;
|
|
9
|
+
private enabled;
|
|
10
|
+
constructor();
|
|
11
|
+
private loadOrCreateAnonId;
|
|
12
|
+
logEvent(event: Event): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=telemetry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"AAcA,UAAU,KAAK;IACb,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,iBAAiB,CAAC;IAC5D,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAU;;IAUzB,OAAO,CAAC,kBAAkB;IA6BpB,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;CA4B5C"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { randomUUID } from "crypto";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
3
|
+
import { homedir } from "os";
|
|
4
|
+
import { join } from "path";
|
|
5
|
+
const API_URL = process.env.CURATOR_API_URL || "https://www.curatedmcp.com";
|
|
6
|
+
const CONFIG_DIR = join(homedir(), ".curatedmcp");
|
|
7
|
+
const CONFIG_FILE = join(CONFIG_DIR, "launcher.json");
|
|
8
|
+
export class Telemetry {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.enabled =
|
|
11
|
+
process.env.CURATOR_TELEMETRY !== "false" &&
|
|
12
|
+
process.argv[process.argv.length - 1] !== "--no-telemetry";
|
|
13
|
+
this.anonId = this.loadOrCreateAnonId();
|
|
14
|
+
}
|
|
15
|
+
loadOrCreateAnonId() {
|
|
16
|
+
try {
|
|
17
|
+
// Try to read existing config
|
|
18
|
+
const data = readFileSync(CONFIG_FILE, "utf-8");
|
|
19
|
+
const config = JSON.parse(data);
|
|
20
|
+
return config.anonId;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// Create new config with fresh UUID
|
|
24
|
+
const anonId = randomUUID();
|
|
25
|
+
try {
|
|
26
|
+
const config = {
|
|
27
|
+
anonId,
|
|
28
|
+
version: "1.0.1",
|
|
29
|
+
};
|
|
30
|
+
if (!existsSync(CONFIG_DIR)) {
|
|
31
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
32
|
+
}
|
|
33
|
+
writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
// Silently fail if we can't write config
|
|
37
|
+
console.error("[telemetry] Failed to write config (non-blocking):", err);
|
|
38
|
+
}
|
|
39
|
+
return anonId;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async logEvent(event) {
|
|
43
|
+
if (!this.enabled)
|
|
44
|
+
return;
|
|
45
|
+
try {
|
|
46
|
+
const payload = {
|
|
47
|
+
event: event.event,
|
|
48
|
+
anonId: this.anonId,
|
|
49
|
+
slug: event.slug,
|
|
50
|
+
client: event.client,
|
|
51
|
+
query: event.query,
|
|
52
|
+
ts: new Date().toISOString(),
|
|
53
|
+
};
|
|
54
|
+
await fetch(`${API_URL}/api/launcher/telemetry`, {
|
|
55
|
+
method: "POST",
|
|
56
|
+
headers: {
|
|
57
|
+
"Content-Type": "application/json",
|
|
58
|
+
"User-Agent": "@curatedmcp/launcher/1.0.1",
|
|
59
|
+
},
|
|
60
|
+
body: JSON.stringify(payload),
|
|
61
|
+
}).catch(() => {
|
|
62
|
+
// Silently fail on network error
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
// Non-blocking telemetry failures
|
|
67
|
+
// console.error("[telemetry] error:", err);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=telemetry.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface ServerDetails {
|
|
2
|
+
slug: string;
|
|
3
|
+
name: string;
|
|
4
|
+
tagline: string;
|
|
5
|
+
description: string;
|
|
6
|
+
category: string;
|
|
7
|
+
pricingType: string;
|
|
8
|
+
rating: number | null;
|
|
9
|
+
downloadCount: number;
|
|
10
|
+
repo?: string;
|
|
11
|
+
docsUrl?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function getServerDetails(slug: string): Promise<ServerDetails>;
|
|
14
|
+
//# sourceMappingURL=get-details.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-details.d.ts","sourceRoot":"","sources":["../../src/tools/get-details.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CA0B3E"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const API_URL = process.env.CURATOR_API_URL || "https://www.curatedmcp.com";
|
|
2
|
+
export async function getServerDetails(slug) {
|
|
3
|
+
const url = `${API_URL}/api/servers/${slug}`;
|
|
4
|
+
const res = await fetch(url, {
|
|
5
|
+
headers: { "User-Agent": "@curatedmcp/launcher/1.0.0" },
|
|
6
|
+
});
|
|
7
|
+
if (!res.ok) {
|
|
8
|
+
if (res.status === 404) {
|
|
9
|
+
throw new Error(`Server "${slug}" not found`);
|
|
10
|
+
}
|
|
11
|
+
throw new Error(`Failed to fetch details: ${res.status} ${res.statusText}`);
|
|
12
|
+
}
|
|
13
|
+
const data = (await res.json());
|
|
14
|
+
return {
|
|
15
|
+
slug: data.slug,
|
|
16
|
+
name: data.name,
|
|
17
|
+
tagline: data.tagline,
|
|
18
|
+
description: data.description,
|
|
19
|
+
category: data.category,
|
|
20
|
+
pricingType: data.pricingType,
|
|
21
|
+
rating: data.rating,
|
|
22
|
+
downloadCount: data.downloadCount,
|
|
23
|
+
repo: data.repository,
|
|
24
|
+
docsUrl: data.documentationUrl,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=get-details.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/tools/install.ts"],"names":[],"mappings":"AAgBA,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,MAAM,GAAE,QAAQ,GAAG,QAAQ,GAAG,UAAqB,GAClD,OAAO,CAAC,MAAM,CAAC,CAgFjB"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
const API_URL = process.env.CURATOR_API_URL || "https://www.curatedmcp.com";
|
|
2
|
+
const CLIENT_PATHS = {
|
|
3
|
+
claude: "~/Library/Application Support/Claude/claude_desktop_config.json",
|
|
4
|
+
cursor: "~/.cursor/mcp.json",
|
|
5
|
+
windsurf: "~/.codeium/windsurf/mcp_config.json",
|
|
6
|
+
};
|
|
7
|
+
export async function installServer(slug, client = "claude") {
|
|
8
|
+
// Fetch server metadata
|
|
9
|
+
const url = `${API_URL}/api/servers/${slug}`;
|
|
10
|
+
const res = await fetch(url, {
|
|
11
|
+
headers: { "User-Agent": "@curatedmcp/launcher/1.0.0" },
|
|
12
|
+
});
|
|
13
|
+
if (!res.ok) {
|
|
14
|
+
if (res.status === 404) {
|
|
15
|
+
throw new Error(`Server "${slug}" not found`);
|
|
16
|
+
}
|
|
17
|
+
throw new Error(`Failed to fetch server: ${res.status}`);
|
|
18
|
+
}
|
|
19
|
+
const server = (await res.json());
|
|
20
|
+
const configPath = CLIENT_PATHS[client];
|
|
21
|
+
// Build config snippet based on server command type
|
|
22
|
+
const configEntry = {};
|
|
23
|
+
if (server.command === "npx") {
|
|
24
|
+
configEntry.command = "npx";
|
|
25
|
+
configEntry.args = ["-y", server.args?.[0] || slug];
|
|
26
|
+
}
|
|
27
|
+
else if (server.command === "uvx") {
|
|
28
|
+
configEntry.command = "uvx";
|
|
29
|
+
configEntry.args = server.args || [];
|
|
30
|
+
}
|
|
31
|
+
else if (server.command === "node") {
|
|
32
|
+
configEntry.command = "node";
|
|
33
|
+
configEntry.args = server.args || [];
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
configEntry.command = server.command;
|
|
37
|
+
configEntry.args = server.args || [];
|
|
38
|
+
}
|
|
39
|
+
// Add environment variables if present
|
|
40
|
+
if (server.environmentVariables && server.environmentVariables.length > 0) {
|
|
41
|
+
configEntry.env = server.environmentVariables.reduce((acc, v) => {
|
|
42
|
+
acc[v.key] = `<your-${v.key.toLowerCase()}>`;
|
|
43
|
+
return acc;
|
|
44
|
+
}, {});
|
|
45
|
+
}
|
|
46
|
+
const configJson = JSON.stringify({
|
|
47
|
+
mcpServers: {
|
|
48
|
+
[slug]: configEntry,
|
|
49
|
+
},
|
|
50
|
+
}, null, 2);
|
|
51
|
+
// Prepare markdown response
|
|
52
|
+
const markdown = `# Install ${server.name}
|
|
53
|
+
|
|
54
|
+
Add this to your \`${client}\` MCP config file:
|
|
55
|
+
|
|
56
|
+
\`\`\`json
|
|
57
|
+
${configJson}
|
|
58
|
+
\`\`\`
|
|
59
|
+
|
|
60
|
+
**Config path for ${client.toUpperCase()}:**
|
|
61
|
+
\`\`\`
|
|
62
|
+
${configPath}
|
|
63
|
+
\`\`\`
|
|
64
|
+
|
|
65
|
+
${server.environmentVariables && server.environmentVariables.length > 0
|
|
66
|
+
? `**Environment variables needed:**\n\n${server.environmentVariables.map((v) => `- \`${v.key}\`: ${v.description || "See docs"}`).join("\n")}\n\n`
|
|
67
|
+
: ""}
|
|
68
|
+
|
|
69
|
+
**Learn more:** ${server.documentationUrl || `https://www.curatedmcp.com/marketplace/${slug}`}
|
|
70
|
+
|
|
71
|
+
Once installed, restart your client and ${server.name} will be available to use with \`@\` prompts.`;
|
|
72
|
+
return markdown;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-categories.d.ts","sourceRoot":"","sources":["../../src/tools/list-categories.ts"],"names":[],"mappings":"AAAA,wBAAgB,cAAc,IAAI,MAAM,EAAE,CAWzC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
interface SearchResult {
|
|
2
|
+
slug: string;
|
|
3
|
+
name: string;
|
|
4
|
+
tagline: string;
|
|
5
|
+
category: string;
|
|
6
|
+
pricing: string;
|
|
7
|
+
rating: number | null;
|
|
8
|
+
downloads: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function searchServers({ query, category, limit, }: {
|
|
11
|
+
query: string;
|
|
12
|
+
category?: string;
|
|
13
|
+
limit?: number;
|
|
14
|
+
}): Promise<SearchResult[]>;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/tools/search.ts"],"names":[],"mappings":"AAEA,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,aAAa,CAAC,EAClC,KAAK,EACL,QAAQ,EACR,KAAU,GACX,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAgB1B"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const API_URL = process.env.CURATOR_API_URL || "https://www.curatedmcp.com";
|
|
2
|
+
export async function searchServers({ query, category, limit = 10, }) {
|
|
3
|
+
const params = new URLSearchParams();
|
|
4
|
+
params.set("q", query);
|
|
5
|
+
if (category)
|
|
6
|
+
params.set("category", category);
|
|
7
|
+
params.set("limit", Math.min(limit, 50).toString());
|
|
8
|
+
const url = `${API_URL}/api/launcher/search?${params}`;
|
|
9
|
+
const res = await fetch(url, {
|
|
10
|
+
headers: { "User-Agent": "@curatedmcp/launcher/1.0.0" },
|
|
11
|
+
});
|
|
12
|
+
if (!res.ok) {
|
|
13
|
+
throw new Error(`Search failed: ${res.status} ${res.statusText}`);
|
|
14
|
+
}
|
|
15
|
+
return (await res.json());
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=search.js.map
|
package/package.json
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "curatedmcp",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "The CuratedMCP agent — discover, run, audit, and govern every MCP server your AI tools (Claude, Cursor, Windsurf, Copilot, Gemini) use",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"curatedmcp": "./dist/index.js",
|
|
9
|
+
"launcher": "./dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"main": "./dist/index.js",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"require": "./dist/index.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist/**/*.js",
|
|
20
|
+
"dist/**/*.json",
|
|
21
|
+
"dist/**/*.d.ts",
|
|
22
|
+
"dist/**/*.d.ts.map",
|
|
23
|
+
"!dist/__tests__/",
|
|
24
|
+
"README.md",
|
|
25
|
+
"LICENSE",
|
|
26
|
+
"package.json"
|
|
27
|
+
],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "tsc && cp src/guard/default-policy.json dist/guard/default-policy.json",
|
|
30
|
+
"dev": "node --loader ts-node/esm src/index.ts",
|
|
31
|
+
"test": "vitest run",
|
|
32
|
+
"prepublishOnly": "npm run build"
|
|
33
|
+
},
|
|
34
|
+
"keywords": [
|
|
35
|
+
"mcp",
|
|
36
|
+
"mcp-hub",
|
|
37
|
+
"mcp-server",
|
|
38
|
+
"mcp-client",
|
|
39
|
+
"mcp-gateway",
|
|
40
|
+
"mcp-proxy",
|
|
41
|
+
"mcp-orchestrator",
|
|
42
|
+
"launcher",
|
|
43
|
+
"install",
|
|
44
|
+
"model-context-protocol",
|
|
45
|
+
"claude",
|
|
46
|
+
"claude-desktop",
|
|
47
|
+
"cursor",
|
|
48
|
+
"windsurf",
|
|
49
|
+
"copilot",
|
|
50
|
+
"gemini",
|
|
51
|
+
"anthropic",
|
|
52
|
+
"ai-tools",
|
|
53
|
+
"ai-agent",
|
|
54
|
+
"agent-orchestration",
|
|
55
|
+
"discovery"
|
|
56
|
+
],
|
|
57
|
+
"author": "CuratedMCP",
|
|
58
|
+
"homepage": "https://curatedmcp.com/launcher",
|
|
59
|
+
"repository": {
|
|
60
|
+
"type": "git",
|
|
61
|
+
"url": "https://github.com/oneprofile-dev/mcp-launcher"
|
|
62
|
+
},
|
|
63
|
+
"bugs": {
|
|
64
|
+
"url": "https://github.com/oneprofile-dev/mcp-launcher/issues"
|
|
65
|
+
},
|
|
66
|
+
"dependencies": {
|
|
67
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
68
|
+
"chalk": "^5.3.0",
|
|
69
|
+
"express": "^4.18.0",
|
|
70
|
+
"minimatch": "^9.0.0"
|
|
71
|
+
},
|
|
72
|
+
"devDependencies": {
|
|
73
|
+
"@types/express": "^4.17.0",
|
|
74
|
+
"@types/node": "^20",
|
|
75
|
+
"typescript": "^5",
|
|
76
|
+
"vitest": "^1.0.0"
|
|
77
|
+
}
|
|
78
|
+
}
|