@supericons/mcp 0.4.7 → 0.4.9
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/generated/motion-lab-baseline.json +1 -1
- package/hosted-search-client.js +42 -16
- package/index.js +3 -1
- package/package.json +1 -1
- package/public/product-facts.json +2 -2
- package/recommend-icons.js +1016 -232
- package/remote-server.js +3 -1
- package/server.json +2 -2
package/hosted-search-client.js
CHANGED
|
@@ -51,6 +51,18 @@ function hasSearchResults(payload) {
|
|
|
51
51
|
return Array.isArray(payload?.results) && payload.results.length > 0;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
function sleep(ms) {
|
|
55
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function getRetryDelayMs(response, attempt) {
|
|
59
|
+
const retryAfter = Number(response.headers.get('retry-after'));
|
|
60
|
+
if (Number.isFinite(retryAfter) && retryAfter > 0) {
|
|
61
|
+
return Math.min(retryAfter * 1000, 5000);
|
|
62
|
+
}
|
|
63
|
+
return Math.min(500 * 2 ** attempt, 2500);
|
|
64
|
+
}
|
|
65
|
+
|
|
54
66
|
function buildLocalizedRetryQueries(query, locale) {
|
|
55
67
|
if (!locale || multilingualExpansionTerms.length === 0) return [];
|
|
56
68
|
|
|
@@ -73,31 +85,45 @@ function buildLocalizedRetryQueries(query, locale) {
|
|
|
73
85
|
}
|
|
74
86
|
|
|
75
87
|
async function postHostedSearch(url, headers, body) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
88
|
+
let lastStatus = 0;
|
|
89
|
+
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
90
|
+
const response = await fetch(url, {
|
|
91
|
+
method: 'POST',
|
|
92
|
+
headers,
|
|
93
|
+
body: JSON.stringify(body),
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
if (response.ok) {
|
|
97
|
+
return response.json();
|
|
98
|
+
}
|
|
81
99
|
|
|
82
|
-
|
|
83
|
-
|
|
100
|
+
lastStatus = response.status;
|
|
101
|
+
if (response.status !== 429 && response.status < 500) break;
|
|
102
|
+
await sleep(getRetryDelayMs(response, attempt));
|
|
84
103
|
}
|
|
85
104
|
|
|
86
|
-
|
|
105
|
+
throw new Error(`hosted MCP search failed (${lastStatus})`);
|
|
87
106
|
}
|
|
88
107
|
|
|
89
108
|
async function postPublicSearch(url, headers, body) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
109
|
+
let lastStatus = 0;
|
|
110
|
+
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
111
|
+
const response = await fetch(url, {
|
|
112
|
+
method: 'POST',
|
|
113
|
+
headers,
|
|
114
|
+
body: JSON.stringify(body),
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
if (response.ok) {
|
|
118
|
+
return response.json();
|
|
119
|
+
}
|
|
95
120
|
|
|
96
|
-
|
|
97
|
-
|
|
121
|
+
lastStatus = response.status;
|
|
122
|
+
if (response.status !== 429 && response.status < 500) break;
|
|
123
|
+
await sleep(getRetryDelayMs(response, attempt));
|
|
98
124
|
}
|
|
99
125
|
|
|
100
|
-
|
|
126
|
+
throw new Error(`public MCP search failed (${lastStatus})`);
|
|
101
127
|
}
|
|
102
128
|
|
|
103
129
|
async function retryLocalizedHostedSearch({ postSearch, url, headers, body, locale }) {
|
package/index.js
CHANGED
|
@@ -844,8 +844,9 @@ server.tool(
|
|
|
844
844
|
locale: z.enum(['zh-Hans', 'zh-Hant', 'ja', 'ko', 'es', 'de', 'pt', 'ar', 'hi', 'vi', 'th']).optional().describe('Optional locale for multilingual slot labels. Supported values: zh-Hans, zh-Hant, ja, ko, es, de, pt, ar, hi, vi, th.'),
|
|
845
845
|
slots: z.array(z.string().min(1)).min(1).max(12).describe('List of UI slots to fill, for example ["Home tab", "Create action", "Alerts tab", "Profile tab"].'),
|
|
846
846
|
limit_per_slot: z.number().min(1).max(5).optional().default(3).describe('How many choices to return per slot, including the top recommendation.'),
|
|
847
|
+
response_mode: z.enum(['plan', 'assets', 'full']).optional().default('plan').describe('Response size mode. Use plan for compact icon IDs and reasons, assets to include SVG only for each top recommendation, or full to include SVG and semantic payloads for all returned choices.'),
|
|
847
848
|
},
|
|
848
|
-
async ({ task, library, style, locale, slots, limit_per_slot }) => {
|
|
849
|
+
async ({ task, library, style, locale, slots, limit_per_slot, response_mode }) => {
|
|
849
850
|
if (libraryMeta[library]?.premium && !hasLibraryAccess(library)) {
|
|
850
851
|
return buildTextResponse(buildPremiumLibraryAccessError(libraryMeta[library].name));
|
|
851
852
|
}
|
|
@@ -858,6 +859,7 @@ server.tool(
|
|
|
858
859
|
locale,
|
|
859
860
|
slots,
|
|
860
861
|
limitPerSlot: limit_per_slot,
|
|
862
|
+
responseMode: response_mode,
|
|
861
863
|
semanticMap: semanticRegistryMap,
|
|
862
864
|
searchIconsForQuery: ({ query, library: searchLibrary, style: searchStyle, limit, locale: searchLocale }) =>
|
|
863
865
|
searchAccessibleIcons({ query, library: searchLibrary, style: searchStyle, limit, locale: searchLocale }),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@supericons/mcp",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.9",
|
|
4
4
|
"mcpName": "io.github.curlymolelabs/supericons",
|
|
5
5
|
"description": "MCP server for Supericons: multilingual semantic SVG icon search and recommendations for AI coding agents.",
|
|
6
6
|
"type": "module",
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
|
-
"generatedAt": "2026-05-
|
|
2
|
+
"generatedAt": "2026-05-15T19:37:45.780Z",
|
|
3
3
|
"freeIconCount": 21264,
|
|
4
4
|
"freeLibraryCount": 10,
|
|
5
5
|
"premiumCollectionCount": 8,
|
|
6
6
|
"premiumIconCount": 400,
|
|
7
7
|
"mcpToolCount": 13,
|
|
8
8
|
"mcpFreeToolCount": 3,
|
|
9
|
-
"mcpPackageVersion": "0.4.
|
|
9
|
+
"mcpPackageVersion": "0.4.7",
|
|
10
10
|
"display": {
|
|
11
11
|
"freeIconsRounded": "20,000+",
|
|
12
12
|
"freeIconsLabel": "20,000+ curated SVG icons",
|