@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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 1,
3
- "generated_at": "2026-05-15T16:15:28.430Z",
3
+ "generated_at": "2026-05-22T20:23:11.858Z",
4
4
  "presets": [
5
5
  {
6
6
  "preset": "bounce",
@@ -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
- const response = await fetch(url, {
77
- method: 'POST',
78
- headers,
79
- body: JSON.stringify(body),
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
- if (!response.ok) {
83
- throw new Error(`hosted MCP search failed (${response.status})`);
100
+ lastStatus = response.status;
101
+ if (response.status !== 429 && response.status < 500) break;
102
+ await sleep(getRetryDelayMs(response, attempt));
84
103
  }
85
104
 
86
- return response.json();
105
+ throw new Error(`hosted MCP search failed (${lastStatus})`);
87
106
  }
88
107
 
89
108
  async function postPublicSearch(url, headers, body) {
90
- const response = await fetch(url, {
91
- method: 'POST',
92
- headers,
93
- body: JSON.stringify(body),
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
- if (!response.ok) {
97
- throw new Error(`public MCP search failed (${response.status})`);
121
+ lastStatus = response.status;
122
+ if (response.status !== 429 && response.status < 500) break;
123
+ await sleep(getRetryDelayMs(response, attempt));
98
124
  }
99
125
 
100
- return response.json();
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.7",
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-15T15:58:55.425Z",
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.6",
9
+ "mcpPackageVersion": "0.4.7",
10
10
  "display": {
11
11
  "freeIconsRounded": "20,000+",
12
12
  "freeIconsLabel": "20,000+ curated SVG icons",