kompass-sdk 0.12.0 → 0.14.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.
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * MCP Registry Source Adapter
3
- * Crawls registry.modelcontextprotocol.io for MCP servers
4
- * No auth required. Public REST API with cursor pagination.
3
+ * Fetches servers from registry.modelcontextprotocol.io
4
+ * Uses local cache + text search against descriptions (not just names)
5
5
  */
6
6
  import type { SourceAdapter } from "./types.js";
7
7
  export declare const mcpRegistryAdapter: SourceAdapter;
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-registry.d.ts","sourceRoot":"","sources":["../../src/sources/mcp-registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAqC,MAAM,YAAY,CAAC;AAcnF,eAAO,MAAM,kBAAkB,EAAE,aA2ChC,CAAC"}
1
+ {"version":3,"file":"mcp-registry.d.ts","sourceRoot":"","sources":["../../src/sources/mcp-registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAqC,MAAM,YAAY,CAAC;AAwFnF,eAAO,MAAM,kBAAkB,EAAE,aA0ChC,CAAC"}
@@ -1,35 +1,102 @@
1
1
  /**
2
2
  * MCP Registry Source Adapter
3
- * Crawls registry.modelcontextprotocol.io for MCP servers
4
- * No auth required. Public REST API with cursor pagination.
3
+ * Fetches servers from registry.modelcontextprotocol.io
4
+ * Uses local cache + text search against descriptions (not just names)
5
5
  */
6
6
  const BASE_URL = "https://registry.modelcontextprotocol.io";
7
+ // In-memory cache of all servers — fetched once, reused
8
+ let serverCache = null;
9
+ let cacheTime = 0;
10
+ const CACHE_TTL = 10 * 60 * 1000; // 10 minutes
11
+ async function fetchAllServers(timeout) {
12
+ // Return cache if fresh
13
+ if (serverCache && Date.now() - cacheTime < CACHE_TTL) {
14
+ return serverCache;
15
+ }
16
+ const allServers = [];
17
+ let cursor;
18
+ // Paginate through all servers (max 3 pages of 96)
19
+ for (let page = 0; page < 3; page++) {
20
+ const url = new URL("/v0.1/servers", BASE_URL);
21
+ url.searchParams.set("limit", "96");
22
+ url.searchParams.set("version", "latest");
23
+ if (cursor)
24
+ url.searchParams.set("cursor", cursor);
25
+ const res = await fetch(url.toString(), { signal: AbortSignal.timeout(timeout) });
26
+ if (!res.ok)
27
+ break;
28
+ const data = await res.json();
29
+ const servers = (data.servers ?? []).map((item) => item.server ?? item);
30
+ allServers.push(...servers);
31
+ cursor = data.metadata?.nextCursor ?? data.nextCursor;
32
+ if (!cursor)
33
+ break;
34
+ }
35
+ serverCache = allServers;
36
+ cacheTime = Date.now();
37
+ return allServers;
38
+ }
39
+ /**
40
+ * Search servers locally by matching query against name + description.
41
+ * Much better than the registry's keyword search which only matches names.
42
+ */
43
+ function searchLocally(servers, query, limit) {
44
+ const queryTerms = query.toLowerCase().split(/\s+/).filter((t) => t.length > 2);
45
+ return servers
46
+ .map((server) => {
47
+ const text = `${server.name} ${server.description ?? ""}`.toLowerCase();
48
+ let score = 0;
49
+ for (const term of queryTerms) {
50
+ // Exact word match in description
51
+ if (text.includes(term))
52
+ score += 3;
53
+ // Name match is stronger
54
+ if (server.name.toLowerCase().includes(term))
55
+ score += 5;
56
+ }
57
+ // Bonus for having remote endpoints (actually callable)
58
+ if (server.remotes && server.remotes.length > 0)
59
+ score += 2;
60
+ // Bonus for no auth required
61
+ const noAuth = server.remotes?.some((r) => !r.headers?.some((h) => h.isRequired && h.name.toLowerCase() === "authorization"));
62
+ if (noAuth)
63
+ score += 1;
64
+ return { server, score };
65
+ })
66
+ .filter((s) => s.score > 0)
67
+ .sort((a, b) => b.score - a.score)
68
+ .slice(0, limit)
69
+ .map((s) => s.server);
70
+ }
7
71
  export const mcpRegistryAdapter = {
8
72
  name: "mcp-registry",
9
73
  displayName: "MCP Registry (Anthropic)",
10
74
  async search(query, options) {
11
- const limit = options?.limit ?? 50;
12
- const timeout = options?.timeout ?? 10000;
75
+ const limit = options?.limit ?? 20;
76
+ const timeout = options?.timeout ?? 15000;
13
77
  try {
14
- const url = new URL("/v0.1/servers", BASE_URL);
15
- url.searchParams.set("limit", String(Math.min(limit, 96)));
16
- if (query)
17
- url.searchParams.set("search", query);
18
- url.searchParams.set("version", "latest");
19
- const controller = new AbortController();
20
- const timer = setTimeout(() => controller.abort(), timeout);
21
- const res = await fetch(url.toString(), { signal: controller.signal });
22
- clearTimeout(timer);
23
- if (!res.ok)
24
- return [];
25
- const data = await res.json();
26
- const rawServers = data.servers ?? data.data ?? [];
27
- // MCP registry wraps in { server: {...} } objects
28
- const servers = rawServers.map((item) => item.server ?? item);
29
- return servers.slice(0, limit).map((server) => mapMcpServer(server));
78
+ const allServers = await fetchAllServers(timeout);
79
+ const matched = searchLocally(allServers, query, limit);
80
+ return matched.map(mapMcpServer);
30
81
  }
31
82
  catch {
32
- return [];
83
+ // Fallback to direct API search if cache fetch fails
84
+ try {
85
+ const url = new URL("/v0.1/servers", BASE_URL);
86
+ url.searchParams.set("limit", String(limit));
87
+ if (query)
88
+ url.searchParams.set("search", query.split(/\s+/)[0]); // Single word fallback
89
+ url.searchParams.set("version", "latest");
90
+ const res = await fetch(url.toString(), { signal: AbortSignal.timeout(timeout) });
91
+ if (!res.ok)
92
+ return [];
93
+ const data = await res.json();
94
+ const servers = (data.servers ?? []).map((item) => item.server ?? item);
95
+ return servers.slice(0, limit).map(mapMcpServer);
96
+ }
97
+ catch {
98
+ return [];
99
+ }
33
100
  }
34
101
  },
35
102
  async ping() {
@@ -45,7 +112,7 @@ export const mcpRegistryAdapter = {
45
112
  },
46
113
  };
47
114
  function mapMcpServer(server) {
48
- const remoteUrl = server.remotes?.[0]?.url;
115
+ const remote = server.remotes?.find((r) => !r.headers?.some((h) => h.isRequired && h.name.toLowerCase() === "authorization")) ?? server.remotes?.[0];
49
116
  const categories = extractCategories(server.description ?? server.name);
50
117
  return {
51
118
  id: `mcp-registry:${server.name}`,
@@ -57,11 +124,11 @@ function mapMcpServer(server) {
57
124
  source: "mcp-registry",
58
125
  protocol: "mcp",
59
126
  endpoints: {
60
- mcp: remoteUrl,
61
- http: server.website ?? server.repo,
127
+ mcp: remote?.url,
128
+ http: server.websiteUrl ?? server.website ?? server.repository?.url ?? server.repo,
62
129
  },
63
130
  pricing: { model: "free" },
64
- verified: !!server.repo,
131
+ verified: !!remote,
65
132
  raw: server,
66
133
  };
67
134
  }
@@ -75,6 +142,8 @@ function extractCategories(text) {
75
142
  file: "tools", browser: "tools", web: "tools",
76
143
  ai: "ai", llm: "ai", model: "ai",
77
144
  image: "media", video: "media", audio: "media",
145
+ trading: "trading", market: "trading", price: "trading",
146
+ email: "communication", slack: "communication", chat: "communication",
78
147
  };
79
148
  for (const [keyword, cat] of Object.entries(keywords)) {
80
149
  if (lower.includes(keyword) && !cats.includes(cat))
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-registry.js","sourceRoot":"","sources":["../../src/sources/mcp-registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mcp-registry.js","sourceRoot":"","sources":["../../src/sources/mcp-registry.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kompass-sdk",
3
- "version": "0.12.0",
3
+ "version": "0.14.0",
4
4
  "description": "Get any job done. Universal agent capability discovery + coordination across ACP, MCP, x402, A2A, skills, L402, and ERC-8004.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * MCP Registry Source Adapter
3
- * Crawls registry.modelcontextprotocol.io for MCP servers
4
- * No auth required. Public REST API with cursor pagination.
3
+ * Fetches servers from registry.modelcontextprotocol.io
4
+ * Uses local cache + text search against descriptions (not just names)
5
5
  */
6
6
 
7
7
  import type { SourceAdapter, UnifiedAgent, SourceSearchOptions } from "./types.js";
@@ -13,9 +13,83 @@ interface McpServer {
13
13
  description?: string;
14
14
  version?: string;
15
15
  repo?: string;
16
+ repository?: { url?: string };
17
+ websiteUrl?: string;
16
18
  website?: string;
17
- packages?: { registry: string; name: string }[];
18
- remotes?: { transport: string; url: string }[];
19
+ remotes?: { type: string; url: string; headers?: { name: string; isRequired?: boolean }[] }[];
20
+ }
21
+
22
+ // In-memory cache of all servers — fetched once, reused
23
+ let serverCache: McpServer[] | null = null;
24
+ let cacheTime = 0;
25
+ const CACHE_TTL = 10 * 60 * 1000; // 10 minutes
26
+
27
+ async function fetchAllServers(timeout: number): Promise<McpServer[]> {
28
+ // Return cache if fresh
29
+ if (serverCache && Date.now() - cacheTime < CACHE_TTL) {
30
+ return serverCache;
31
+ }
32
+
33
+ const allServers: McpServer[] = [];
34
+ let cursor: string | undefined;
35
+
36
+ // Paginate through all servers (max 3 pages of 96)
37
+ for (let page = 0; page < 3; page++) {
38
+ const url = new URL("/v0.1/servers", BASE_URL);
39
+ url.searchParams.set("limit", "96");
40
+ url.searchParams.set("version", "latest");
41
+ if (cursor) url.searchParams.set("cursor", cursor);
42
+
43
+ const res = await fetch(url.toString(), { signal: AbortSignal.timeout(timeout) });
44
+ if (!res.ok) break;
45
+
46
+ const data = await res.json();
47
+ const servers = (data.servers ?? []).map((item: any) => item.server ?? item);
48
+ allServers.push(...servers);
49
+
50
+ cursor = data.metadata?.nextCursor ?? data.nextCursor;
51
+ if (!cursor) break;
52
+ }
53
+
54
+ serverCache = allServers;
55
+ cacheTime = Date.now();
56
+ return allServers;
57
+ }
58
+
59
+ /**
60
+ * Search servers locally by matching query against name + description.
61
+ * Much better than the registry's keyword search which only matches names.
62
+ */
63
+ function searchLocally(servers: McpServer[], query: string, limit: number): McpServer[] {
64
+ const queryTerms = query.toLowerCase().split(/\s+/).filter((t) => t.length > 2);
65
+
66
+ return servers
67
+ .map((server) => {
68
+ const text = `${server.name} ${server.description ?? ""}`.toLowerCase();
69
+ let score = 0;
70
+
71
+ for (const term of queryTerms) {
72
+ // Exact word match in description
73
+ if (text.includes(term)) score += 3;
74
+ // Name match is stronger
75
+ if (server.name.toLowerCase().includes(term)) score += 5;
76
+ }
77
+
78
+ // Bonus for having remote endpoints (actually callable)
79
+ if (server.remotes && server.remotes.length > 0) score += 2;
80
+
81
+ // Bonus for no auth required
82
+ const noAuth = server.remotes?.some((r) =>
83
+ !r.headers?.some((h) => h.isRequired && h.name.toLowerCase() === "authorization")
84
+ );
85
+ if (noAuth) score += 1;
86
+
87
+ return { server, score };
88
+ })
89
+ .filter((s) => s.score > 0)
90
+ .sort((a, b) => b.score - a.score)
91
+ .slice(0, limit)
92
+ .map((s) => s.server);
19
93
  }
20
94
 
21
95
  export const mcpRegistryAdapter: SourceAdapter = {
@@ -23,31 +97,30 @@ export const mcpRegistryAdapter: SourceAdapter = {
23
97
  displayName: "MCP Registry (Anthropic)",
24
98
 
25
99
  async search(query: string, options?: SourceSearchOptions): Promise<UnifiedAgent[]> {
26
- const limit = options?.limit ?? 50;
27
- const timeout = options?.timeout ?? 10000;
100
+ const limit = options?.limit ?? 20;
101
+ const timeout = options?.timeout ?? 15000;
28
102
 
29
103
  try {
30
- const url = new URL("/v0.1/servers", BASE_URL);
31
- url.searchParams.set("limit", String(Math.min(limit, 96)));
32
- if (query) url.searchParams.set("search", query);
33
- url.searchParams.set("version", "latest");
34
-
35
- const controller = new AbortController();
36
- const timer = setTimeout(() => controller.abort(), timeout);
37
-
38
- const res = await fetch(url.toString(), { signal: controller.signal });
39
- clearTimeout(timer);
40
-
41
- if (!res.ok) return [];
104
+ const allServers = await fetchAllServers(timeout);
105
+ const matched = searchLocally(allServers, query, limit);
106
+ return matched.map(mapMcpServer);
107
+ } catch {
108
+ // Fallback to direct API search if cache fetch fails
109
+ try {
110
+ const url = new URL("/v0.1/servers", BASE_URL);
111
+ url.searchParams.set("limit", String(limit));
112
+ if (query) url.searchParams.set("search", query.split(/\s+/)[0]); // Single word fallback
113
+ url.searchParams.set("version", "latest");
42
114
 
43
- const data = await res.json();
44
- const rawServers = data.servers ?? data.data ?? [];
45
- // MCP registry wraps in { server: {...} } objects
46
- const servers: McpServer[] = rawServers.map((item: any) => item.server ?? item);
115
+ const res = await fetch(url.toString(), { signal: AbortSignal.timeout(timeout) });
116
+ if (!res.ok) return [];
47
117
 
48
- return servers.slice(0, limit).map((server) => mapMcpServer(server));
49
- } catch {
50
- return [];
118
+ const data = await res.json();
119
+ const servers = (data.servers ?? []).map((item: any) => item.server ?? item);
120
+ return servers.slice(0, limit).map(mapMcpServer);
121
+ } catch {
122
+ return [];
123
+ }
51
124
  }
52
125
  },
53
126
 
@@ -64,7 +137,10 @@ export const mcpRegistryAdapter: SourceAdapter = {
64
137
  };
65
138
 
66
139
  function mapMcpServer(server: McpServer): UnifiedAgent {
67
- const remoteUrl = server.remotes?.[0]?.url;
140
+ const remote = server.remotes?.find((r) =>
141
+ !r.headers?.some((h) => h.isRequired && h.name.toLowerCase() === "authorization")
142
+ ) ?? server.remotes?.[0];
143
+
68
144
  const categories = extractCategories(server.description ?? server.name);
69
145
 
70
146
  return {
@@ -77,11 +153,11 @@ function mapMcpServer(server: McpServer): UnifiedAgent {
77
153
  source: "mcp-registry",
78
154
  protocol: "mcp",
79
155
  endpoints: {
80
- mcp: remoteUrl,
81
- http: server.website ?? server.repo,
156
+ mcp: remote?.url,
157
+ http: server.websiteUrl ?? server.website ?? (server.repository as any)?.url ?? server.repo,
82
158
  },
83
159
  pricing: { model: "free" },
84
- verified: !!server.repo,
160
+ verified: !!remote,
85
161
  raw: server,
86
162
  };
87
163
  }
@@ -96,6 +172,8 @@ function extractCategories(text: string): string[] {
96
172
  file: "tools", browser: "tools", web: "tools",
97
173
  ai: "ai", llm: "ai", model: "ai",
98
174
  image: "media", video: "media", audio: "media",
175
+ trading: "trading", market: "trading", price: "trading",
176
+ email: "communication", slack: "communication", chat: "communication",
99
177
  };
100
178
  for (const [keyword, cat] of Object.entries(keywords)) {
101
179
  if (lower.includes(keyword) && !cats.includes(cat)) cats.push(cat);