@orchyn/mcp 1.16.1 → 1.17.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.
@@ -2,13 +2,13 @@
2
2
  * MCP Apps HTML UI template for Orchyn tools.
3
3
  *
4
4
  * Features:
5
- * - Skeleton loading shimmer while tool executes
5
+ * - Content renders when a tool result arrives (no loading screen)
6
+ * - Idle/resource-preview state shows a branded ready view
6
7
  * - Smooth fade-in transitions when data arrives
7
8
  * - Expandable analysis sections (click to expand/collapse)
8
9
  * - Click-to-copy on hashtags, hooks, quotes
9
10
  * - Hover micro-interactions on cards
10
11
  * - Dark/light theme auto-detection
11
- * - Progress indicator for multi-step tools
12
12
  * - Responsive layout
13
13
  */
14
14
  export const ORCHYN_UI_TEMPLATE = `<!DOCTYPE html>
@@ -35,29 +35,6 @@ export const ORCHYN_UI_TEMPLATE = `<!DOCTYPE html>
35
35
  *{margin:0;padding:0;box-sizing:border-box;}
36
36
  body{font-family:system-ui,-apple-system,'Segoe UI',sans-serif;background:var(--bg);color:var(--fg);padding:16px;line-height:1.5;}
37
37
 
38
- /* ─── Loading / Skeleton ─── */
39
- .loading-container{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:48px 24px;gap:12px;}
40
- .orchyn-logo{animation:logoSpin 3s ease-in-out infinite;}
41
- @keyframes logoSpin{0%,100%{transform:rotate(0deg) scale(1)}50%{transform:rotate(180deg) scale(1.1)}}
42
- .loading-brand{font-size:18px;font-weight:700;letter-spacing:-0.02em;color:var(--fg);}
43
- .loading-spinner{width:28px;height:28px;border:3px solid var(--border);border-top-color:var(--accent);border-radius:50%;animation:spin .8s linear infinite;}
44
- @keyframes spin{to{transform:rotate(360deg)}}
45
- .loading-text{font-size:13px;color:var(--muted);animation:pulse 1.5s ease-in-out infinite;}
46
- @keyframes pulse{0%,100%{opacity:1}50%{opacity:.5}}
47
-
48
- .skeleton{background:var(--tag);border-radius:var(--radius-sm);overflow:hidden;position:relative;}
49
- .skeleton::after{content:'';position:absolute;inset:0;background:linear-gradient(90deg,transparent,rgba(255,255,255,.08),transparent);animation:shimmer 1.5s infinite;}
50
- @keyframes shimmer{0%{transform:translateX(-100%)}100%{transform:translateX(100%)}}
51
- .skeleton-thumb{width:100%;height:180px;border-radius:var(--radius) var(--radius) 0 0;}
52
- .skeleton-line{height:14px;margin:8px 14px;border-radius:4px;}
53
- .skeleton-line.short{width:60%;}
54
- .skeleton-line.medium{width:80%;}
55
- .skeleton-badge{width:80px;height:20px;border-radius:999px;margin:12px 14px 0;}
56
- .skeleton-gallery{display:flex;flex-wrap:wrap;gap:10px;}
57
- .skeleton-card{width:300px;border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;background:var(--card);}
58
- .skeleton-creator{width:220px;border:1px solid var(--border);border-radius:var(--radius);padding:14px;background:var(--card);}
59
- .skeleton-avatar{width:48px;height:48px;border-radius:50%;margin-bottom:8px;}
60
-
61
38
  /* ─── Content entrance ─── */
62
39
  .fade-in{animation:fadeIn .4s ease-out;}
63
40
  @keyframes fadeIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
@@ -117,10 +94,6 @@ body{font-family:system-ui,-apple-system,'Segoe UI',sans-serif;background:var(--
117
94
  .section-content.open{max-height:600px;padding:10px 12px;}
118
95
  .section-text{font-size:13px;color:var(--fg);line-height:1.6;}
119
96
 
120
- /* ─── Progress bar ─── */
121
- .progress-bar{height:6px;background:var(--tag);border-radius:999px;overflow:hidden;margin:6px 0;}
122
- .progress-fill{height:100%;border-radius:999px;transition:width .6s cubic-bezier(.4,0,.2,1);background:linear-gradient(90deg,var(--blue),var(--green));}
123
-
124
97
  /* ─── Hook strength ─── */
125
98
  .hook-bar-track{display:flex;align-items:center;gap:10px;margin-top:6px;}
126
99
  .hook-bar{flex:1;height:10px;background:var(--tag);border-radius:999px;overflow:hidden;}
@@ -167,30 +140,17 @@ body{font-family:system-ui,-apple-system,'Segoe UI',sans-serif;background:var(--
167
140
  </head>
168
141
  <body>
169
142
  <div id="app">
170
- <div class="loading-container">
171
- <div class="orchyn-logo">
172
- <svg width="40" height="40" viewBox="0 0 48 48" fill="none">
173
- <g fill="var(--accent)" transform="translate(24 24)">
174
- <circle r="4.1"/>
175
- <g id="r"><path d="M-2.85 -5.2 L0 -20.6 L2.85 -5.2 L1.15 1.1 L-1.15 1.1 Z"/></g>
176
- <use href="#r" transform="rotate(45)"/>
177
- <use href="#r" transform="rotate(90)"/>
178
- <use href="#r" transform="rotate(135)"/>
179
- <use href="#r" transform="rotate(180)"/>
180
- <use href="#r" transform="rotate(225)"/>
181
- <use href="#r" transform="rotate(270)"/>
182
- <use href="#r" transform="rotate(315)"/>
183
- </g>
184
- </svg>
185
- </div>
186
- <div class="loading-brand">Orchyn</div>
187
- <div class="loading-text">Analyzing…</div>
143
+ <div style="display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:220px;text-align:center;padding:40px 24px;background:var(--panel, #0d1117);color:var(--fg, #e6edf3);font-family:system-ui,-apple-system,sans-serif">
144
+ <svg width="52" height="52" viewBox="0 0 48 48" fill="none">
145
+ <g fill="var(--accent, #3fb950)" transform="translate(24 24)"><circle r="4.1"/><g id="ri"><path d="M-2.85 -5.2 L0 -20.6 L2.85 -5.2 L1.15 1.1 L-1.15 1.1 Z"/></g><use href="#ri" transform="rotate(45)"/><use href="#ri" transform="rotate(90)"/><use href="#ri" transform="rotate(135)"/><use href="#ri" transform="rotate(180)"/><use href="#ri" transform="rotate(225)"/><use href="#ri" transform="rotate(270)"/><use href="#ri" transform="rotate(315)"/></g>
146
+ </svg>
147
+ <div style="margin-top:16px;font-size:18px;font-weight:700">Orchyn</div>
148
+ <div style="margin-top:8px;font-size:14px;color:#8b949e;max-width:340px;line-height:1.5">Social media intelligence. This view will render your post, creator, and trend results as soon as a tool returns.</div>
188
149
  </div>
189
150
  </div>
190
151
  <script>
191
152
  (function(){
192
153
  var nextId=1;var pending=new Map();
193
- var loadingTimer=null;
194
154
  var currentTool="";
195
155
 
196
156
  function send(method,params){
@@ -207,69 +167,19 @@ body{font-family:system-ui,-apple-system,'Segoe UI',sans-serif;background:var(--
207
167
  if(d.id&&pending.has(d.id)){
208
168
  var p=pending.get(d.id);pending.delete(d.id);
209
169
  if(d.error)p.reject(new Error(d.error.message||JSON.stringify(d.error)));
210
- else p.resolve(d.result);return;
170
+ else p.resolve(d.result);
171
+ return;
211
172
  }
212
173
  if(d.method==="ui/notifications/tool-result"){
213
174
  toolResultReceived=true;
214
- clearTimeout(loadingTimer);
215
- clearTimeout(fallbackTimer);
216
175
  render(d.params);
217
176
  setTimeout(reportSize,50);
218
177
  }
219
178
  if(d.method==="ui/notifications/tool-input-partial"){
220
179
  currentTool=d.params&&d.params.name?d.params.name:"";
221
- updateProgress(d.params);
222
180
  }
223
181
  });
224
182
 
225
- // Show loading state after 300ms — branded spinner until tool name arrives,
226
- // then switch to the correct skeleton type.
227
- loadingTimer=setTimeout(function(){
228
- var app=document.getElementById("app");
229
- if(!app)return;
230
- if(currentTool){
231
- // Tool name already known → show correct skeleton
232
- app.innerHTML=renderSkeleton(currentTool);
233
- }else{
234
- // Tool name not yet known → show branded spinner (neutral)
235
- app.innerHTML='<div class="loading-container fade-in">'
236
- +'<div class="orchyn-logo"><svg width="40" height="40" viewBox="0 0 48 48" fill="none"><g fill="var(--accent)" transform="translate(24 24)"><circle r="4.1"/><g id="rl"><path d="M-2.85 -5.2 L0 -20.6 L2.85 -5.2 L1.15 1.1 L-1.15 1.1 Z"/></g><use href="#rl" transform="rotate(45)"/><use href="#rl" transform="rotate(90)"/><use href="#rl" transform="rotate(135)"/><use href="#rl" transform="rotate(180)"/><use href="#rl" transform="rotate(225)"/><use href="#rl" transform="rotate(270)"/><use href="#rl" transform="rotate(315)"/></g></svg></div>'
237
- +'<div class="loading-brand">Orchyn</div>'
238
- +'<div class="loading-text">Loading…</div>'
239
- +'</div>';
240
- }
241
- },300);
242
-
243
- // Fallback: if no tool-result arrives within 3s, check if data is embedded
244
- // in the page (some hosts pass structuredContent via URL hash or postMessage)
245
- var fallbackTimer=setTimeout(function(){
246
- if(toolResultReceived)return;
247
- // Try to extract data from URL hash (host may pass structuredContent here)
248
- try{
249
- var hash=window.location.hash.slice(1);
250
- if(hash){
251
- var decoded=JSON.parse(decodeURIComponent(hash));
252
- if(decoded&&typeof decoded==="object"){render(decoded);return;}
253
- }
254
- }catch(e){}
255
- // Try to extract from URL search params
256
- try{
257
- var params=new URLSearchParams(window.location.search);
258
- var dataParam=params.get("data");
259
- if(dataParam){
260
- var decoded=JSON.parse(decodeURIComponent(dataParam));
261
- if(decoded&&typeof decoded==="object"){render(decoded);return;}
262
- }
263
- }catch(e){}
264
- // Last resort: show a branded card indicating results are available
265
- var app=document.getElementById("app");
266
- if(app)app.innerHTML='<div class="card card-wide fade-in"><div class="card-body" style="text-align:center;padding:24px">'
267
- +'<svg width="28" height="28" viewBox="0 0 48 48" fill="none" style="margin-bottom:8px"><g fill="var(--accent)" transform="translate(24 24)"><circle r="4.1"/><g id="rf"><path d="M-2.85 -5.2 L0 -20.6 L2.85 -5.2 L1.15 1.1 L-1.15 1.1 Z"/></g><use href="#rf" transform="rotate(45)"/><use href="#rf" transform="rotate(90)"/><use href="#rf" transform="rotate(135)"/><use href="#rf" transform="rotate(180)"/><use href="#rf" transform="rotate(225)"/><use href="#rf" transform="rotate(270)"/><use href="#rf" transform="rotate(315)"/></g></svg>'
268
- +'<div style="font-size:14px;font-weight:600;margin-bottom:4px">✅ Results ready</div>'
269
- +'<div style="font-size:12px;color:var(--muted)">Orchyn analysis complete — see the full response in the chat.</div>'
270
- +'</div></div>';
271
- },3000);
272
-
273
183
  // MCP Apps handshake.
274
184
  // Claude's McpUiInitializeRequestSchema requires appInfo, appCapabilities
275
185
  // and protocolVersion (legacy hosts read capabilities/clientInfo), so send
@@ -332,70 +242,6 @@ body{font-family:system-ui,-apple-system,'Segoe UI',sans-serif;background:var(--
332
242
  navigator.clipboard.writeText(text).catch(function(){});
333
243
  }
334
244
 
335
- // ─── Skeleton ───
336
- // Tools that analyze/fetch a single URL: show 1 wide card skeleton
337
- var SINGLE_URL_TOOLS={analyze_post:1,get_social_media:1,understand_social_post:1,get_post_comments:1,analyze_creator_profile:1};
338
- // Tools that return galleries: show multiple small card skeletons
339
- var GALLERY_TOOLS={discover_social_posts:1,get_user_posts:1,search_creators:1,get_similar_creators:1,discover_sounds:1};
340
- // Tools that return credits/checkout: show 1 credit card skeleton
341
- var CREDIT_TOOLS={check_orchyn_credits:1,buy_orchyn_credits:1};
342
-
343
- function renderSkeleton(toolName){
344
- // Branded header above skeletons
345
- var brandHeader='<div style="display:flex;align-items:center;gap:8px;margin-bottom:14px;justify-content:center">'
346
- +'<svg width="20" height="20" viewBox="0 0 48 48" fill="none"><g fill="var(--accent)" transform="translate(24 24)"><circle r="4.1"/><g id="sb"><path d="M-2.85 -5.2 L0 -20.6 L2.85 -5.2 L1.15 1.1 L-1.15 1.1 Z"/></g><use href="#sb" transform="rotate(45)"/><use href="#sb" transform="rotate(90)"/><use href="#sb" transform="rotate(135)"/><use href="#sb" transform="rotate(180)"/><use href="#sb" transform="rotate(225)"/><use href="#sb" transform="rotate(270)"/><use href="#sb" transform="rotate(315)"/></g></svg>'
347
- +'<span style="font-size:13px;font-weight:600;color:var(--muted)">Orchyn</span></div>';
348
- // Single URL tools → 1 wide card skeleton
349
- if(SINGLE_URL_TOOLS[toolName]){
350
- return brandHeader+'<div class="fade-in">'
351
- +'<div class="skeleton-card" style="width:100%">'
352
- +'<div class="skeleton skeleton-thumb" style="height:220px"></div>'
353
- +'<div style="padding:14px 16px">'
354
- +'<div class="skeleton skeleton-badge"></div>'
355
- +'<div class="skeleton skeleton-line" style="width:90%"></div>'
356
- +'<div class="skeleton skeleton-line medium"></div>'
357
- +'<div style="display:flex;gap:6px;margin-top:10px">'
358
- +'<div class="skeleton" style="width:70px;height:28px;border-radius:999px"></div>'
359
- +'<div class="skeleton" style="width:60px;height:28px;border-radius:999px"></div>'
360
- +'<div class="skeleton" style="width:65px;height:28px;border-radius:999px"></div>'
361
- +'</div></div></div></div>';
362
- }
363
- // Credit tools → credit card skeleton
364
- if(CREDIT_TOOLS[toolName]){
365
- return brandHeader+'<div class="fade-in" style="max-width:380px">'
366
- +'<div class="credits-card" style="margin:0">'
367
- +'<div class="skeleton" style="width:120px;height:20px;margin-bottom:14px"></div>'
368
- +'<div class="skeleton" style="width:80px;height:40px;margin-bottom:8px"></div>'
369
- +'<div class="skeleton" style="width:140px;height:14px"></div>'
370
- +'</div></div>';
371
- }
372
- // Gallery tools → multiple small card skeletons
373
- // Unknown tool → default to 1 wide card (most common case: single URL tools)
374
- if(!toolName||SINGLE_URL_TOOLS[toolName]||CREDIT_TOOLS[toolName]){
375
- // Already handled above, but catch unknown tools with single card
376
- if(!toolName){
377
- return brandHeader+'<div class="fade-in" style="max-width:520px">'
378
- +'<div class="skeleton-card" style="width:100%">'
379
- +'<div class="skeleton skeleton-thumb" style="height:220px"></div>'
380
- +'<div style="padding:14px 16px">'
381
- +'<div class="skeleton skeleton-badge"></div>'
382
- +'<div class="skeleton skeleton-line" style="width:90%"></div>'
383
- +'<div class="skeleton skeleton-line medium"></div>'
384
- +'</div></div></div>';
385
- }
386
- }
387
- var count=toolName==='discover_sounds'?4:toolName==='search_creators'||toolName==='get_similar_creators'?3:6;
388
- return brandHeader+'<div class="skeleton-gallery stagger">'
389
- +Array(count).fill(0).map(function(){
390
- return '<div class="skeleton-card">'
391
- +'<div class="skeleton skeleton-thumb"></div>'
392
- +'<div class="skeleton skeleton-badge"></div>'
393
- +'<div class="skeleton skeleton-line medium"></div>'
394
- +'<div class="skeleton skeleton-line short"></div>'
395
- +'</div>';
396
- }).join("")+'</div>';
397
- }
398
-
399
245
  // ─── Post Card ───
400
246
  function postCard(p,wide){
401
247
  var platform=p.platform||"unknown",color=pColor(platform),brandSvg=pSvg(platform);
@@ -624,22 +470,11 @@ body{font-family:system-ui,-apple-system,'Segoe UI',sans-serif;background:var(--
624
470
  setTimeout(reportSize,50);
625
471
  }
626
472
 
473
+ // tool-input-partial — no loading UI anymore; just retain the tool name in
474
+ // case future logic needs it. Content only appears via tool-result.
627
475
  function updateProgress(params){
628
- var app=document.getElementById("app");
629
- if(!app)return;
630
- // Learn the tool name
631
- var toolName=params&&params.name?params.name:currentTool;
632
- if(toolName&&toolName!==currentTool){
633
- currentTool=toolName;
634
- // Switch from spinner to correct skeleton if still loading
635
- if(app.querySelector(".loading-spinner")||app.querySelector(".loading-container")||app.querySelector(".skeleton")){
636
- app.innerHTML=renderSkeleton(currentTool);
637
- }
638
- }
639
- // Add a progress bar below the existing content if not already present
640
- if(!app.querySelector(".progress-bar")){
641
- app.innerHTML=app.innerHTML+'<div style="text-align:center;margin-top:12px"><div class="progress-bar" style="width:200px;margin:0 auto"><div class="progress-fill" style="width:60%"></div></div></div>';
642
- }
476
+ var toolName=params&&params.name?params.name:null;
477
+ if(toolName)currentTool=toolName;
643
478
  }
644
479
 
645
480
  // Global helpers
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orchyn/mcp",
3
- "version": "1.16.1",
3
+ "version": "1.17.0",
4
4
  "description": "MCP server for orchyn - fetch, discover and understand TikTok/Instagram/YouTube/X/LinkedIn posts with AI (media metadata, niche discovery, hook & viral analysis)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",