@oobe-protocol-labs/sap-mcp-server 0.7.3 → 0.8.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.
Files changed (90) hide show
  1. package/CHANGELOG.md +139 -0
  2. package/README.md +14 -7
  3. package/USER_DOCS/00_START_HERE.md +45 -7
  4. package/USER_DOCS/01_HOSTED_REMOTE_MCP.md +2 -0
  5. package/USER_DOCS/03_PAYMENTS_X402_PAYSH.md +13 -5
  6. package/USER_DOCS/04_CLIENT_CONFIGS.md +25 -15
  7. package/USER_DOCS/06_DESKTOP_GUI_WIZARD.md +36 -21
  8. package/assets/logos/drift.svg +12 -0
  9. package/assets/logos/jupiter.ico +0 -0
  10. package/assets/logos/mcp.svg +11 -0
  11. package/assets/logos/meteora.png +0 -0
  12. package/assets/logos/orca.ico +0 -0
  13. package/assets/logos/raydium.ico +0 -0
  14. package/assets/logos/smithery.svg +11 -0
  15. package/assets/oobe-logo.png +0 -0
  16. package/dist/config/mcp-client-injection.d.ts +26 -7
  17. package/dist/config/mcp-client-injection.d.ts.map +1 -1
  18. package/dist/config/mcp-client-injection.js +182 -58
  19. package/dist/config/mcp-client-injection.js.map +1 -1
  20. package/dist/config/wizard.d.ts.map +1 -1
  21. package/dist/config/wizard.js +92 -57
  22. package/dist/config/wizard.js.map +1 -1
  23. package/dist/core/constants.d.ts +1 -1
  24. package/dist/core/constants.js +1 -1
  25. package/dist/payments/pricing.d.ts.map +1 -1
  26. package/dist/payments/pricing.js +11 -0
  27. package/dist/payments/pricing.js.map +1 -1
  28. package/dist/payments/x402-paid-call.d.ts +85 -1
  29. package/dist/payments/x402-paid-call.d.ts.map +1 -1
  30. package/dist/payments/x402-paid-call.js +168 -4
  31. package/dist/payments/x402-paid-call.js.map +1 -1
  32. package/dist/prompts/context/sap-agent-context.prompt.js +6 -3
  33. package/dist/prompts/context/sap-agent-context.prompt.js.map +1 -1
  34. package/dist/remote/public-home/escape.d.ts +11 -0
  35. package/dist/remote/public-home/escape.d.ts.map +1 -0
  36. package/dist/remote/public-home/escape.js +20 -0
  37. package/dist/remote/public-home/escape.js.map +1 -0
  38. package/dist/remote/public-home/index.d.ts +8 -0
  39. package/dist/remote/public-home/index.d.ts.map +1 -0
  40. package/dist/remote/public-home/index.js +57 -0
  41. package/dist/remote/public-home/index.js.map +1 -0
  42. package/dist/remote/public-home/scripts.d.ts +6 -0
  43. package/dist/remote/public-home/scripts.d.ts.map +1 -0
  44. package/dist/remote/public-home/scripts.js +106 -0
  45. package/dist/remote/public-home/scripts.js.map +1 -0
  46. package/dist/remote/public-home/sections.d.ts +67 -0
  47. package/dist/remote/public-home/sections.d.ts.map +1 -0
  48. package/dist/remote/public-home/sections.js +727 -0
  49. package/dist/remote/public-home/sections.js.map +1 -0
  50. package/dist/remote/public-home/styles.d.ts +6 -0
  51. package/dist/remote/public-home/styles.d.ts.map +1 -0
  52. package/dist/remote/public-home/styles.js +1534 -0
  53. package/dist/remote/public-home/styles.js.map +1 -0
  54. package/dist/remote/public-home/types.d.ts +95 -0
  55. package/dist/remote/public-home/types.d.ts.map +1 -0
  56. package/dist/remote/public-home/types.js +2 -0
  57. package/dist/remote/public-home/types.js.map +1 -0
  58. package/dist/remote/server.d.ts +41 -1
  59. package/dist/remote/server.d.ts.map +1 -1
  60. package/dist/remote/server.js +109 -292
  61. package/dist/remote/server.js.map +1 -1
  62. package/dist/security/tool-permissions.d.ts.map +1 -1
  63. package/dist/security/tool-permissions.js +5 -0
  64. package/dist/security/tool-permissions.js.map +1 -1
  65. package/dist/tools/magicblock-tools.js +6 -6
  66. package/dist/tools/magicblock-tools.js.map +1 -1
  67. package/dist/tools/profile-tools.d.ts.map +1 -1
  68. package/dist/tools/profile-tools.js +136 -33
  69. package/dist/tools/profile-tools.js.map +1 -1
  70. package/dist/tools/register-tools.d.ts.map +1 -1
  71. package/dist/tools/register-tools.js +5 -0
  72. package/dist/tools/register-tools.js.map +1 -1
  73. package/dist/tools/x402-paid-call-tool.d.ts +1 -1
  74. package/dist/tools/x402-paid-call-tool.d.ts.map +1 -1
  75. package/dist/tools/x402-paid-call-tool.js +314 -28
  76. package/dist/tools/x402-paid-call-tool.js.map +1 -1
  77. package/dist/wizard-core/desktop-flow.d.ts +40 -1
  78. package/dist/wizard-core/desktop-flow.d.ts.map +1 -1
  79. package/dist/wizard-core/desktop-flow.js +206 -15
  80. package/dist/wizard-core/desktop-flow.js.map +1 -1
  81. package/docs/03_CONFIGURATION_AND_WIZARD.md +6 -2
  82. package/docs/06_PAYMENTS_X402_AND_PAYSH.md +29 -7
  83. package/docs/07_ENDPOINTS_AND_CLIENTS.md +1 -1
  84. package/docs/14_DESKTOP_WIZARD_RELEASE.md +24 -5
  85. package/docs/15_DASHBOARD_SCREENSHARE_SCRIPT.md +137 -0
  86. package/docs/README.md +23 -2
  87. package/package.json +1 -1
  88. package/server.json +3 -3
  89. package/skills/sap-mcp/SKILL.md +23 -7
  90. package/skills/sap-payments-x402/SKILL.md +37 -13
@@ -0,0 +1,727 @@
1
+ import { escapeHtml } from './escape.js';
2
+ /**
3
+ * @name formatUsd
4
+ * @description Formats public payment totals for the landing page.
5
+ */
6
+ function formatUsd(value) {
7
+ if (!Number.isFinite(value) || value <= 0) {
8
+ return '$0.00';
9
+ }
10
+ return `$${value.toLocaleString('en-US', {
11
+ minimumFractionDigits: value < 1 ? 3 : 2,
12
+ maximumFractionDigits: value < 1 ? 3 : 2,
13
+ })}`;
14
+ }
15
+ /**
16
+ * @name formatInteger
17
+ * @description Formats public counters with stable grouping.
18
+ */
19
+ function formatInteger(value) {
20
+ if (!Number.isFinite(value) || value <= 0) {
21
+ return '0';
22
+ }
23
+ return Math.trunc(value).toLocaleString('en-US');
24
+ }
25
+ /**
26
+ * @name renderOsIcon
27
+ * @description Renders inline platform marks for native wizard download cards.
28
+ */
29
+ function renderOsIcon(platform) {
30
+ if (platform === 'windows') {
31
+ return `
32
+ <svg viewBox="0 0 24 24" aria-hidden="true">
33
+ <path d="M3 5.2 10.7 4v7.2H3V5.2Zm9.3-1.4L21 2.5v8.7h-8.7V3.8ZM3 12.8h7.7V20L3 18.8v-6Zm9.3 0H21v8.7l-8.7-1.3v-7.4Z" />
34
+ </svg>
35
+ `;
36
+ }
37
+ if (platform === 'macos') {
38
+ return `
39
+ <svg viewBox="0 0 24 24" aria-hidden="true">
40
+ <path d="M16.7 2.4c.1 1.2-.4 2.4-1.2 3.3-.9 1-2.2 1.7-3.4 1.6-.2-1.2.4-2.4 1.2-3.2.9-1 2.3-1.7 3.4-1.7ZM20.2 17.4c-.5 1.2-.8 1.7-1.5 2.8-1 1.5-2.3 3.3-4 3.3-1.5 0-1.9-1-3.9-1s-2.5 1-4 1c-1.7 0-3-1.6-4-3.1-2.8-4.3-3.1-9.4-1.4-12.1 1.2-1.9 3-3 4.7-3 1.8 0 2.9 1 4.3 1 1.4 0 2.2-1 4.3-1 1.6 0 3.3.9 4.5 2.4-3.9 2.1-3.3 7.7 1 9.7Z" />
41
+ </svg>
42
+ `;
43
+ }
44
+ return `
45
+ <svg viewBox="0 0 24 24" aria-hidden="true">
46
+ <path d="M12 2.2c2.2 0 4 1.8 4 4v2.1c1.1.5 2 1.5 2.5 2.8l1.3 3.3c.4 1.1-.1 2.3-1.2 2.8l-1.1.5v1.2c0 1.6-1.3 2.9-2.9 2.9H9.4c-1.6 0-2.9-1.3-2.9-2.9v-1.2l-1.1-.5c-1.1-.5-1.6-1.7-1.2-2.8l1.3-3.3c.5-1.3 1.4-2.3 2.5-2.8V6.2c0-2.2 1.8-4 4-4Zm-2.2 16.2v.5c0 .4.3.7.7.7h3c.4 0 .7-.3.7-.7v-.5H9.8Zm2.2-14c-1 0-1.8.8-1.8 1.8v1.6h3.6V6.2c0-1-.8-1.8-1.8-1.8Zm-4.4 7.4-1.2 3.1 2.5 1.1h6.2l2.5-1.1-1.2-3.1c-.4-1-1.3-1.7-2.4-1.7H10c-1.1 0-2 .7-2.4 1.7Z" />
47
+ </svg>
48
+ `;
49
+ }
50
+ /**
51
+ * @name renderSolanaMark
52
+ * @description Renders the Solana mark used in the scroll coordination scene.
53
+ */
54
+ function renderSolanaMark() {
55
+ return `
56
+ <svg class="solana-mark" viewBox="0 0 397 311" aria-label="Solana">
57
+ <path d="M64.6 237.9c2.8-2.8 6.6-4.4 10.6-4.4h306.2c6.7 0 10.1 8.1 5.3 12.9l-60.5 60.5c-2.8 2.8-6.6 4.4-10.6 4.4H9.4c-6.7 0-10.1-8.1-5.3-12.9l60.5-60.5Z" />
58
+ <path d="M64.6 4.4C67.4 1.6 71.2 0 75.2 0h306.2c6.7 0 10.1 8.1 5.3 12.9l-60.5 60.5c-2.8 2.8-6.6 4.4-10.6 4.4H9.4C2.7 77.8-.7 69.7 4.1 64.9L64.6 4.4Z" />
59
+ <path d="M326.2 120.7c-2.8-2.8-6.6-4.4-10.6-4.4H9.4c-6.7 0-10.1 8.1-5.3 12.9l60.5 60.5c2.8 2.8 6.6 4.4 10.6 4.4h306.2c6.7 0 10.1-8.1 5.3-12.9l-60.5-60.5Z" />
60
+ </svg>
61
+ `;
62
+ }
63
+ /**
64
+ * @name renderDefiLogoRail
65
+ * @description Renders a compact animated rail for Solana DeFi protocol names exposed by SAP MCP.
66
+ */
67
+ function renderDefiLogoRail() {
68
+ const protocols = [
69
+ ['Jupiter', '/logos/jupiter.ico'],
70
+ ['Raydium', '/logos/raydium.ico'],
71
+ ['Orca', '/logos/orca.ico'],
72
+ ['Meteora', '/logos/meteora.png'],
73
+ ['Drift', '/logos/drift.svg'],
74
+ ];
75
+ const items = [...protocols, ...protocols];
76
+ return `
77
+ <div class="protocol-logo-rail" aria-label="Integrated Solana protocol logos">
78
+ <div>
79
+ ${items.map(([name, src]) => `
80
+ <span>
81
+ <img src="${escapeHtml(src)}" width="30" height="30" alt="${escapeHtml(name)}">
82
+ </span>
83
+ `).join('')}
84
+ </div>
85
+ </div>
86
+ `;
87
+ }
88
+ /**
89
+ * @name renderProtocolMedia
90
+ * @description Renders protocol-specific visual affordances inside the Protocol surface bento cards.
91
+ */
92
+ function renderProtocolMedia(key) {
93
+ if (key === 'defi') {
94
+ return renderDefiLogoRail();
95
+ }
96
+ if (key === 'rpc') {
97
+ return `<div class="protocol-avatar solana-avatar">${renderSolanaMark()}</div>`;
98
+ }
99
+ if (key === 'sap') {
100
+ return `
101
+ <div class="protocol-avatar sap-avatar">
102
+ <img src="/favicon.png" width="68" height="68" alt="SAP MCP">
103
+ </div>
104
+ `;
105
+ }
106
+ return '';
107
+ }
108
+ /**
109
+ * @name renderNavGlyph
110
+ * @description Renders compact glyphs for navigation dropdown rows without client-side icon dependencies.
111
+ */
112
+ function renderNavGlyph(label) {
113
+ const initials = label
114
+ .split(/[\s./-]+/)
115
+ .filter(Boolean)
116
+ .slice(0, 2)
117
+ .map((part) => part[0]?.toUpperCase() ?? '')
118
+ .join('');
119
+ return `<span class="nav-glyph" aria-hidden="true">${escapeHtml(initials || '•')}</span>`;
120
+ }
121
+ /**
122
+ * @name renderTopNavigation
123
+ * @description Renders the glass top navigation used by the hosted landing page.
124
+ */
125
+ export function renderTopNavigation(model) {
126
+ const runtimeLinks = [
127
+ ['Quick start', '#install', 'Choose native setup or CLI setup for hosted SAP MCP.'],
128
+ ['Payments', '#payments', 'x402, pay.sh, local paid-call bridge, and receipt flow.'],
129
+ ['Tool buckets', '#capabilities', 'Solana DeFi, Solana RPC, and Synapse Agent Protocol tools.'],
130
+ ['Endpoints', '#endpoints', 'Public HTTP surface, discovery URLs, and security boundary.'],
131
+ ];
132
+ const machineLinks = [
133
+ ['Server JSON', model.info.endpoints.serverInfo, 'Public server metadata for runtimes and marketplaces.'],
134
+ ['OpenAPI', model.info.endpoints.openApi, 'pay.sh catalog and HTTP integration schema.'],
135
+ ['Downloads JSON', model.info.endpoints.wizardDownloads, 'Native wizard release links by operating system.'],
136
+ ['Agent card', model.info.endpoints.agentCard, 'A2A-compatible agent card metadata.'],
137
+ ['MCP server card', model.info.endpoints.smitheryServerCard, 'Marketplace server card metadata.'],
138
+ ['Wizard descriptor', model.info.endpoints.wizardDescriptor, 'Wizard installer descriptor and setup hints.'],
139
+ ['x402 discovery', model.info.endpoints.x402Discovery, 'x402 payment discovery record.'],
140
+ ['pay.sh provider', model.info.endpoints.payShProvider, 'pay.sh provider YAML for catalog and proxy workflows.'],
141
+ ];
142
+ const renderDropdownLink = ([label, href, description]) => `
143
+ <a class="nav-menu-link" href="${escapeHtml(href)}">
144
+ ${renderNavGlyph(label)}
145
+ <span>
146
+ <strong>${escapeHtml(label)}</strong>
147
+ <small>${escapeHtml(description)}</small>
148
+ </span>
149
+ </a>
150
+ `;
151
+ return `
152
+ <nav class="site-nav" aria-label="Primary navigation">
153
+ <a class="brand" href="${escapeHtml(model.info.endpoints.landing)}">
154
+ <img src="/favicon.png" width="42" height="42" alt="SAP MCP">
155
+ <span>
156
+ <strong>SAP MCP</strong>
157
+ <span>OOBE Protocol</span>
158
+ </span>
159
+ </a>
160
+ <div class="nav-center">
161
+ <a class="nav-pill is-active" href="${escapeHtml(model.info.endpoints.landing)}">Home</a>
162
+ <a class="nav-pill oobe-nav" href="https://www.oobeprotocol.ai/">
163
+ <img src="/oobe-logo.png" width="24" height="24" alt="">
164
+ <span>OOBE</span>
165
+ </a>
166
+ <a class="nav-pill nav-pill-strong" href="${escapeHtml(model.info.endpoints.docs)}">Docs</a>
167
+ <details class="nav-dropdown" data-nav-dropdown>
168
+ <summary>
169
+ Gateway
170
+ <span aria-hidden="true">⌄</span>
171
+ </summary>
172
+ <div class="nav-menu nav-menu-small">
173
+ ${runtimeLinks.map(renderDropdownLink).join('')}
174
+ </div>
175
+ </details>
176
+ <details class="nav-dropdown" data-nav-dropdown>
177
+ <summary>
178
+ Metadata
179
+ <span aria-hidden="true">⌄</span>
180
+ </summary>
181
+ <div class="nav-menu nav-menu-wide">
182
+ ${machineLinks.map(renderDropdownLink).join('')}
183
+ </div>
184
+ </details>
185
+ </div>
186
+ <div class="nav-actions">
187
+ <span class="version-pill">v${escapeHtml(model.info.version)}</span>
188
+ <a class="button primary nav-install" href="#install">
189
+ <span class="install-os install-os-windows">${renderOsIcon('windows')}</span>
190
+ <span class="install-os install-os-macos">${renderOsIcon('macos')}</span>
191
+ <span class="install-os install-os-linux">${renderOsIcon('linux')}</span>
192
+ <span>Install</span>
193
+ </a>
194
+ </div>
195
+ </nav>
196
+ `;
197
+ }
198
+ /**
199
+ * @name renderDownloadActionGroup
200
+ * @description Renders direct OS download buttons for install steps and download cards.
201
+ */
202
+ function renderDownloadActionGroup(model, className = 'download-actions') {
203
+ const downloads = [
204
+ ['Windows', 'x64 .exe', 'windows', model.info.downloads.desktopWizard.windowsX64Setup],
205
+ ['macOS', 'Apple Silicon .dmg', 'macos', model.info.downloads.desktopWizard.macosArm64Dmg],
206
+ ['Linux', 'x64 .tar.gz', 'linux', model.info.downloads.desktopWizard.linuxX64TarGz],
207
+ ];
208
+ return `
209
+ <div class="${escapeHtml(className)}">
210
+ ${downloads.map(([label, caption, platform, href]) => `
211
+ <a class="download-action os-${escapeHtml(platform)}" href="${escapeHtml(href)}">
212
+ <span class="os-mark">${renderOsIcon(platform)}</span>
213
+ <span>
214
+ <strong>${escapeHtml(label)}</strong>
215
+ <small>${escapeHtml(caption)}</small>
216
+ </span>
217
+ </a>
218
+ `).join('')}
219
+ </div>
220
+ `;
221
+ }
222
+ /**
223
+ * @name renderHero
224
+ * @description Renders the first viewport with the animated protocol engine.
225
+ */
226
+ export function renderHero(model) {
227
+ const endpointLabel = model.endpoint === 'mcp'
228
+ ? 'Streamable HTTP MCP endpoint'
229
+ : 'Hosted MCP gateway';
230
+ return `
231
+ <header class="hero" id="top">
232
+ <div class="hero-copy">
233
+ <p class="eyebrow">OOBE Protocol · ${escapeHtml(endpointLabel)}</p>
234
+ <h1>Agent operations, wired into Solana.</h1>
235
+ <p class="lead">
236
+ SAP MCP is the hosted MCP surface for agents that need real Solana work:
237
+ protocol tools, registry state, identity, payments, policy, and local non-custodial signing.
238
+ </p>
239
+ <div class="hero-actions">
240
+ <a class="button primary" href="#install">Start with the wizard</a>
241
+ <a class="button" href="${escapeHtml(model.info.endpoints.docs)}">Read docs</a>
242
+ <a class="button" href="${escapeHtml(model.info.endpoints.mcp)}">MCP endpoint</a>
243
+ </div>
244
+ <p class="micro-copy">
245
+ Hosted tools run at <code>${escapeHtml(model.info.endpoints.mcp)}</code>. Paid and write calls
246
+ are authorized by the user-owned local <code>sap_payments</code> bridge or an external signer.
247
+ </p>
248
+ </div>
249
+ <div class="hero-visual" data-engine-scene aria-label="Animated SAP MCP protocol engine">
250
+ <div class="terminal-strip">
251
+ <span></span><span></span><span></span>
252
+ <code>sap:mcp://remote</code>
253
+ </div>
254
+ <div class="orbital-engine">
255
+ <div class="orbit orbit-a"></div>
256
+ <div class="orbit orbit-b"></div>
257
+ <div class="orbit orbit-c"></div>
258
+ <div class="orbit-core">
259
+ <img src="/favicon.png" alt="" width="52" height="52">
260
+ <strong>SAP</strong>
261
+ </div>
262
+ <div class="orbit-chip chip-a"><b>MCP</b><span>Tools</span></div>
263
+ <div class="orbit-chip chip-b"><b>x402</b><span>Receipts</span></div>
264
+ <div class="orbit-chip chip-c"><b>SNS</b><span>Identity</span></div>
265
+ <div class="orbit-chip chip-d"><b>RPC</b><span>Solana</span></div>
266
+ </div>
267
+ <div class="hero-bento-mini">
268
+ <div><span>Tools</span><strong>268</strong></div>
269
+ <div><span>Transport</span><strong>HTTP</strong></div>
270
+ <div><span>Keys</span><strong>Local</strong></div>
271
+ </div>
272
+ </div>
273
+ </header>
274
+ `;
275
+ }
276
+ /**
277
+ * @name renderHeroBento
278
+ * @description Renders the first bento grid with operational primitives and live stats.
279
+ */
280
+ export function renderHeroBento(model) {
281
+ const stats = model.paymentStats;
282
+ const cards = [
283
+ ['Solana DeFi Protocols', 'Jupiter, Raydium, Orca, Meteora, Drift, Pyth, DAS, Metaplex and more.', 'coral', 'protocols'],
284
+ ['Solana RPC Methods', 'Balances, token accounts, assets, simulation, programs, transactions and raw chain reads.', 'yellow', 'rpc'],
285
+ ['Synapse Agent Protocol', 'Registry, tools, reputation, attestations, escrow, settlement, memory, SNS identity.', 'green', 'sap'],
286
+ ['x402 / pay.sh Revenue', `${formatUsd(stats.totalVolumeUsd)} settled volume across ${formatInteger(stats.totalSettlements)} settlement events.`, 'aqua', 'payments'],
287
+ ];
288
+ const renderCard = ([title, body, tone, key], index) => `
289
+ <article class="bento-card bento-${escapeHtml(key)} wide" data-tone="${escapeHtml(tone)}">
290
+ <span>${escapeHtml(String(index + 1).padStart(2, '0'))}</span>
291
+ <h3>${escapeHtml(title)}</h3>
292
+ <p>${escapeHtml(body)}</p>
293
+ </article>
294
+ `;
295
+ return `
296
+ <section class="bento-strip bento-stack" aria-labelledby="bento-title">
297
+ <div class="bento-grid">
298
+ ${cards.slice(0, 2).map((card, index) => renderCard(card, index)).join('')}
299
+ <article class="bento-card full" data-tone="blue">
300
+ <span>Live endpoint</span>
301
+ <h3>Streamable HTTP MCP</h3>
302
+ <code>${escapeHtml(model.info.endpoints.mcp)}</code>
303
+ <p>Free discovery. Paid tools return x402 challenges. Local signatures stay on the user's machine.</p>
304
+ </article>
305
+ ${cards.slice(2).map((card, index) => renderCard(card, index + 2)).join('')}
306
+ </div>
307
+ <aside class="bento-sticky-copy">
308
+ <p class="eyebrow" id="bento-title">Agent coordination stack</p>
309
+ <h2>One gateway for discovery, execution, payment, and proof.</h2>
310
+ <p>
311
+ SAP MCP gives agent runtimes one hosted gateway for discovery and execution,
312
+ while payment receipts and signatures stay bound to the local profile.
313
+ </p>
314
+ </aside>
315
+ </section>
316
+ `;
317
+ }
318
+ /**
319
+ * @name renderScrollMachine
320
+ * @description Renders the large scroll-driven protocol assembly scene.
321
+ */
322
+ export function renderScrollMachine(model) {
323
+ return `
324
+ <section class="machine-section" data-machine-section aria-labelledby="machine-title">
325
+ <div class="machine-copy">
326
+ <p class="eyebrow" id="machine-title">Scroll the coordination engine</p>
327
+ <h2>Hosted calls open into local authorization.</h2>
328
+ <p>
329
+ The remote server exposes the tool surface. The local profile owns signer state.
330
+ The payment bridge resolves x402 challenges and replays the exact call with a receipt.
331
+ </p>
332
+ </div>
333
+ <div class="machine-stage">
334
+ <div class="machine-part part-remote">
335
+ <span>01</span>
336
+ <strong>Remote MCP</strong>
337
+ <p>${escapeHtml(model.info.endpoints.mcp)}</p>
338
+ </div>
339
+ <div class="machine-part part-policy">
340
+ <span>02</span>
341
+ <strong>Policy</strong>
342
+ <p>Limits, approvals, Bento optional.</p>
343
+ </div>
344
+ <div class="machine-core">
345
+ <div class="machine-core-ring"></div>
346
+ <div class="machine-logo-pair">
347
+ <img src="/favicon.png" alt="SAP MCP" width="98" height="98">
348
+ ${renderSolanaMark()}
349
+ </div>
350
+ </div>
351
+ <div class="machine-part part-payments">
352
+ <span>03</span>
353
+ <strong>x402/pay.sh</strong>
354
+ <p>Challenge, settlement, receipt.</p>
355
+ </div>
356
+ <div class="machine-part part-signer">
357
+ <span>04</span>
358
+ <strong>Local signer</strong>
359
+ <p>Keypair bytes never leave device.</p>
360
+ </div>
361
+ <div class="machine-rail rail-a"></div>
362
+ <div class="machine-rail rail-b"></div>
363
+ </div>
364
+ </section>
365
+ `;
366
+ }
367
+ /**
368
+ * @name renderDocsLaunchpad
369
+ * @description Renders a compact docs grid similar to a production documentation launchpad.
370
+ */
371
+ export function renderDocsLaunchpad(model) {
372
+ const docs = [
373
+ ['Getting started', `${model.info.endpoints.docs}/#/user/00_START_HERE`, 'coral'],
374
+ ['Hosted remote MCP', `${model.info.endpoints.docs}/#/user/01_HOSTED_REMOTE_MCP`, 'yellow'],
375
+ ['Client configs', `${model.info.endpoints.docs}/#/user/04_CLIENT_CONFIGS`, 'green'],
376
+ ['Desktop wizard', `${model.info.endpoints.docs}/#/user/06_DESKTOP_GUI_WIZARD`, 'blue'],
377
+ ['x402 and pay.sh', `${model.info.endpoints.docs}/#/user/03_PAYMENTS_X402_PAYSH`, 'aqua'],
378
+ ['Skills and tools', `${model.info.endpoints.docs}/#/user/05_SKILLS_AND_TOOLS`, 'green'],
379
+ ];
380
+ return `
381
+ <section class="docs-launchpad" aria-labelledby="docs-launchpad-title">
382
+ <p class="eyebrow" id="docs-launchpad-title">Start operating</p>
383
+ <h2>Documentation that maps to the agent workflow.</h2>
384
+ <div class="docs-grid">
385
+ ${docs.map(([label, href, tone]) => `
386
+ <a class="doc-tile" data-tone="${escapeHtml(tone)}" href="${escapeHtml(href)}">
387
+ <span></span>
388
+ <strong>${escapeHtml(label)}</strong>
389
+ <b aria-hidden="true">→</b>
390
+ </a>
391
+ `).join('')}
392
+ </div>
393
+ </section>
394
+ `;
395
+ }
396
+ /**
397
+ * @name renderMetrics
398
+ * @description Renders public payment ledger counters.
399
+ */
400
+ export function renderMetrics(model) {
401
+ const stats = model.paymentStats;
402
+ const lastSettlement = stats.ledgerAvailable
403
+ ? stats.lastSettlementAt ?? 'Waiting for first settlement'
404
+ : 'Ledger initializes after the first paid hosted call';
405
+ return `
406
+ <section class="section compact" aria-labelledby="metrics-title">
407
+ <div class="section-head">
408
+ <p class="eyebrow" id="metrics-title">Live hosted gateway</p>
409
+ <h2>Payment-aware MCP infrastructure.</h2>
410
+ <p>Public ledger counters show the hosted payment rail without exposing secrets, wallet files, or RPC credentials.</p>
411
+ </div>
412
+ <div class="metric-grid">
413
+ <article class="metric">
414
+ <span>Facilitator Volume</span>
415
+ <strong>${escapeHtml(formatUsd(stats.totalVolumeUsd))}</strong>
416
+ <p>Estimated settled x402/pay.sh tool volume recorded by the hosted ledger.</p>
417
+ </article>
418
+ <article class="metric">
419
+ <span>Total Settlements</span>
420
+ <strong>${escapeHtml(formatInteger(stats.totalSettlements))}</strong>
421
+ <p>${escapeHtml(lastSettlement)}</p>
422
+ </article>
423
+ <article class="metric">
424
+ <span>Payment Requests</span>
425
+ <strong>${escapeHtml(formatInteger(stats.totalPaymentRequests))}</strong>
426
+ <p>${escapeHtml(formatInteger(stats.totalVerifiedPayments))} verified, ${escapeHtml(formatInteger(stats.totalFailedSettlements))} failed settlements.</p>
427
+ </article>
428
+ </div>
429
+ </section>
430
+ `;
431
+ }
432
+ /**
433
+ * @name renderFeatureEngine
434
+ * @description Renders the capability matrix as a docs-style feature grid.
435
+ */
436
+ export function renderFeatureEngine() {
437
+ const features = [
438
+ ['Solana DeFi', 'Jupiter, Raydium, Orca, Meteora, Drift and market data flows.', 'wide', 'defi'],
439
+ ['Solana RPC', 'Balances, token accounts, DAS assets, transactions, programs and simulation.', '', 'rpc'],
440
+ ['SAP Protocol', 'Agent registry, discovery, reputation, escrow, settlement and attestations.', 'tall', 'sap'],
441
+ ['Identity', 'SNS domain checks, reverse lookup, linked identity and agent profile context.', '', 'identity'],
442
+ ['Payments', 'x402 challenge tools, pay.sh provider metadata, receipts and paid-call replay.', 'wide', 'payments'],
443
+ ['Policy', 'Local limits and optional Bento Guard policy checks before sensitive execution.', '', 'policy'],
444
+ ['Skills', 'Bundled agent skills explain how to choose tools, fetch context and avoid waste.', '', 'skills'],
445
+ ['Remote-first', 'Hosted Streamable HTTP with local non-custodial signing for paid/write calls.', 'wide', 'remote'],
446
+ ];
447
+ return `
448
+ <section class="section protocol-surface" id="capabilities" aria-labelledby="capabilities-title">
449
+ <div class="section-head">
450
+ <p class="eyebrow" id="capabilities-title">Protocol surface</p>
451
+ <h2>Three buckets. One agent operations layer.</h2>
452
+ <p>SAP MCP exposes Solana DeFi protocols, Solana RPC methods, and Synapse Agent Protocol operations through one MCP-compatible interface.</p>
453
+ </div>
454
+ <div class="protocol-bento">
455
+ ${features.map(([label, description, size, key], index) => `
456
+ <article class="protocol-card ${escapeHtml(size)} protocol-${escapeHtml(key)}">
457
+ <span class="protocol-index">${escapeHtml(String(index + 1).padStart(2, '0'))}</span>
458
+ ${renderProtocolMedia(key)}
459
+ <strong>${escapeHtml(label)}</strong>
460
+ <p>${escapeHtml(description)}</p>
461
+ </article>
462
+ `).join('')}
463
+ </div>
464
+ </section>
465
+ `;
466
+ }
467
+ /**
468
+ * @name renderRegistryListings
469
+ * @description Renders public marketplace and registry listings where SAP MCP can be verified.
470
+ */
471
+ export function renderRegistryListings() {
472
+ const listings = [
473
+ [
474
+ 'Smithery',
475
+ 'MCP server marketplace listing with hosted server metadata, tools, prompts, and configuration UX.',
476
+ 'https://smithery.ai/servers/oobe-protocol/sap-mcp',
477
+ '/logos/smithery.svg',
478
+ ],
479
+ [
480
+ 'Official MCP Registry',
481
+ 'Canonical Model Context Protocol registry entry for ai.oobeprotocol.sap.mcp/sap-mcp.',
482
+ 'https://registry.modelcontextprotocol.io/?q=ai.oobeprotocol.sap.mcp%2Fsap-mcp',
483
+ '/logos/mcp.svg',
484
+ ],
485
+ ];
486
+ return `
487
+ <section class="section registry-section" aria-labelledby="registry-title">
488
+ <div class="section-head">
489
+ <p class="eyebrow" id="registry-title">Listed and verifiable</p>
490
+ <h2>Discover SAP MCP from trusted MCP indexes.</h2>
491
+ <p>Hosted metadata is public, crawler-friendly, and linked from registries agents already inspect.</p>
492
+ </div>
493
+ <div class="registry-grid">
494
+ ${listings.map(([name, description, href, logo]) => `
495
+ <a class="registry-card" href="${escapeHtml(href)}" target="_blank" rel="noreferrer">
496
+ <span class="registry-logo">
497
+ <img src="${escapeHtml(logo)}" width="42" height="42" alt="${escapeHtml(name)}">
498
+ </span>
499
+ <span class="registry-copy">
500
+ <strong>${escapeHtml(name)}</strong>
501
+ <small>${escapeHtml(description)}</small>
502
+ </span>
503
+ <span class="registry-status">Verified</span>
504
+ </a>
505
+ `).join('')}
506
+ </div>
507
+ </section>
508
+ `;
509
+ }
510
+ /**
511
+ * @name renderIntegrationPath
512
+ * @description Renders the recommended setup paths for native and CLI users.
513
+ */
514
+ export function renderIntegrationPath(model) {
515
+ return `
516
+ <section class="section" id="install" aria-labelledby="install-title">
517
+ <div class="section-head">
518
+ <p class="eyebrow" id="install-title">Fast integration path</p>
519
+ <h2>Remote tools. Local signatures. Smooth payments.</h2>
520
+ <p>
521
+ Both paths end with the same production model: hosted SAP MCP tools at <code>/mcp</code>,
522
+ plus a local non-custodial <code>sap_payments</code> bridge for paid and write calls.
523
+ </p>
524
+ </div>
525
+ <div class="install-grid">
526
+ <article class="card">
527
+ <p class="eyebrow">Recommended for most users</p>
528
+ <h3>Native download</h3>
529
+ <p>Best when the user wants a guided desktop installer for profile creation, wallet isolation, runtime detection, and payment bridge repair.</p>
530
+ <ol class="step-list">
531
+ <li>
532
+ <b>1</b>
533
+ <span>
534
+ Download the desktop wizard for your operating system.
535
+ ${renderDownloadActionGroup(model, 'step-downloads')}
536
+ </span>
537
+ </li>
538
+ <li><b>2</b><span>Open the wizard and choose <strong>Full hosted SAP MCP setup</strong>.</span></li>
539
+ <li><b>3</b><span>Select detected runtimes such as Codex, Claude, Hermes, or OpenClaw.</span></li>
540
+ <li><b>4</b><span>Restart the agent and connect to the hosted <code>/mcp</code> endpoint.</span></li>
541
+ </ol>
542
+ <div class="inline-actions">
543
+ <a class="button" href="${escapeHtml(model.info.endpoints.docs)}/#/user/06_DESKTOP_GUI_WIZARD">Desktop docs</a>
544
+ </div>
545
+ </article>
546
+ <article class="card">
547
+ <p class="eyebrow">Developer path</p>
548
+ <h3>CLI wizard</h3>
549
+ <p>Best for terminals, servers, and deterministic setup from npm without touching runtime config files by hand.</p>
550
+ <ol class="step-list">
551
+ <li><b>1</b><span>Run the CLI wizard command.</span></li>
552
+ <li><b>2</b><span>Accept the default <code>hosted-api</code> mode for remote SAP MCP.</span></li>
553
+ <li><b>3</b><span>Let the wizard configure hosted <code>sap</code> plus local <code>sap_payments</code>.</span></li>
554
+ <li><b>4</b><span>Use <code>sap_payments_call_paid_tool</code> when hosted tools require x402 payment.</span></li>
555
+ </ol>
556
+ <pre class="code-block"><code>${escapeHtml(model.wizardCommand)}</code></pre>
557
+ <div class="inline-actions">
558
+ <a class="button" href="${escapeHtml(model.info.endpoints.docs)}">Start here</a>
559
+ <a class="button" href="${escapeHtml(model.info.endpoints.docs)}/#/user/04_CLIENT_CONFIGS">Client configs</a>
560
+ <a class="button" href="${escapeHtml(model.info.endpoints.docs)}/#/user/03_PAYMENTS_X402_PAYSH">Payments</a>
561
+ </div>
562
+ </article>
563
+ </div>
564
+ </section>
565
+ `;
566
+ }
567
+ /**
568
+ * @name renderDownloads
569
+ * @description Renders native wizard download cards and install commands.
570
+ */
571
+ export function renderDownloads(model) {
572
+ return `
573
+ <section class="section" id="downloads" aria-labelledby="downloads-title">
574
+ <div class="setup-grid">
575
+ <article class="card">
576
+ <p class="eyebrow" id="downloads-title">Install wizard</p>
577
+ <h2>Choose native or npm setup.</h2>
578
+ <p>Create a local SAP MCP profile, signer, policy limits, hosted client config, and payment bridge. For guided details, start with <a href="${escapeHtml(model.info.endpoints.docs)}">the user docs</a>.</p>
579
+ <div class="command-stack">
580
+ <div>
581
+ <span>Native installer script</span>
582
+ <pre class="code-block"><code>${escapeHtml(model.installScriptCommand)}</code></pre>
583
+ </div>
584
+ <div>
585
+ <span>npm wizard</span>
586
+ <pre class="code-block"><code>${escapeHtml(model.wizardCommand)}</code></pre>
587
+ </div>
588
+ </div>
589
+ </article>
590
+ <article class="card">
591
+ <p class="eyebrow">Native Downloads</p>
592
+ <h2>One-click desktop wizard.</h2>
593
+ <p>Download directly from the GitHub release for v${escapeHtml(model.info.version)}. The public downloads manifest remains available at <a href="${escapeHtml(model.info.endpoints.wizardDownloads)}">/wizard/downloads.json</a>.</p>
594
+ ${renderDownloadActionGroup(model)}
595
+ </article>
596
+ </div>
597
+ </section>
598
+ `;
599
+ }
600
+ /**
601
+ * @name renderPayments
602
+ * @description Renders x402 and pay.sh integration guidance.
603
+ */
604
+ export function renderPayments(model) {
605
+ return `
606
+ <section class="section" id="payments" aria-labelledby="payments-title">
607
+ <div class="section-head">
608
+ <p class="eyebrow" id="payments-title">x402 Challenge Tools For Agents</p>
609
+ <h2>Payment challenges are first-class tools.</h2>
610
+ <p>
611
+ Hosted paid calls return x402 requirements. The local <code>sap_payments</code> bridge
612
+ signs, settles, replays the exact tool call, and returns the receipt without sending
613
+ keypair bytes to OOBE.
614
+ </p>
615
+ </div>
616
+ <div class="install-grid">
617
+ <article class="card">
618
+ <h3>Agent-native paid call flow</h3>
619
+ <div class="timeline">
620
+ <div class="timeline-item"><b>1</b><p>Agent calls hosted SAP MCP tool.</p></div>
621
+ <div class="timeline-item"><b>2</b><p>Paid tools return an x402 challenge with resource, amount, asset, and payTo.</p></div>
622
+ <div class="timeline-item"><b>3</b><p>Local <code>sap_payments_call_paid_tool</code> signs payment proof and retries the call.</p></div>
623
+ <div class="timeline-item"><b>4</b><p>Hosted MCP verifies settlement and returns the tool output plus receipt.</p></div>
624
+ </div>
625
+ <pre class="code-block"><code>${escapeHtml(model.paidCallCommand)}</code></pre>
626
+ </article>
627
+ <article class="card">
628
+ <h3>Provider metadata</h3>
629
+ <p>pay.sh and x402 discovery endpoints are public, machine-readable, and secret-free.</p>
630
+ <ul>
631
+ <li><strong>x402:</strong> paid MCP tool calls return HTTP 402 with payment requirements, then settle through the OOBE facilitator.</li>
632
+ <li><strong>pay.sh:</strong> public provider YAML is available for catalog and proxy workflows.</li>
633
+ <li>x402 discovery: <a href="${escapeHtml(model.info.endpoints.x402Discovery)}">/.well-known/x402</a></li>
634
+ <li>pay.sh provider YAML: <a href="${escapeHtml(model.info.endpoints.payShProvider)}">/pay/provider.yml</a></li>
635
+ <li>OpenAPI catalog spec: <a href="${escapeHtml(model.info.endpoints.openApi)}">/openapi.json</a></li>
636
+ <li>Addon path: <code>${escapeHtml(model.paidCallAddonPath)}</code></li>
637
+ </ul>
638
+ </article>
639
+ </div>
640
+ </section>
641
+ `;
642
+ }
643
+ /**
644
+ * @name renderEndpointMap
645
+ * @description Renders operational endpoints and security boundary notes.
646
+ */
647
+ export function renderEndpointMap(model) {
648
+ const endpoints = [
649
+ ['POST', model.info.endpoints.mcp],
650
+ ['GET', model.info.endpoints.docs],
651
+ ['GET', model.info.endpoints.health],
652
+ ['GET', model.info.endpoints.serverInfo],
653
+ ['GET', model.info.endpoints.openApi],
654
+ ['GET', model.info.endpoints.x402Discovery],
655
+ ['GET', model.info.endpoints.payShProvider],
656
+ ['GET', model.info.endpoints.smitheryServerCard],
657
+ ['GET', model.info.endpoints.agentCard],
658
+ ['GET', model.info.endpoints.wizardDescriptor],
659
+ ];
660
+ return `
661
+ <section class="section" id="endpoints" aria-labelledby="endpoints-title">
662
+ <div class="endpoint-grid">
663
+ <article class="card">
664
+ <p class="eyebrow" id="endpoints-title">Endpoint map</p>
665
+ <h2>Public surface area.</h2>
666
+ <div class="endpoint-list">
667
+ ${endpoints.map(([method, url]) => `
668
+ <div class="endpoint-row">
669
+ <span class="method-badge method-${escapeHtml(method.toLowerCase())}">${escapeHtml(method)}</span>
670
+ <a href="${escapeHtml(url)}">${escapeHtml(url)}</a>
671
+ </div>
672
+ `).join('')}
673
+ </div>
674
+ <p>MCP clients should connect to <code>/mcp</code> with <code>Accept: application/json, text/event-stream</code>.</p>
675
+ </article>
676
+ <article class="card">
677
+ <p class="eyebrow">Security boundary</p>
678
+ <h2>Non-custodial by default.</h2>
679
+ <ul>
680
+ <li>Keypair bytes are never exposed by public endpoints.</li>
681
+ <li>RPC secrets are redacted from public metadata and UI.</li>
682
+ <li>Paid tools require payment before execution.</li>
683
+ <li>Write tools require a user-controlled local signer or external signer.</li>
684
+ </ul>
685
+ </article>
686
+ </div>
687
+ </section>
688
+ `;
689
+ }
690
+ /**
691
+ * @name renderFooter
692
+ * @description Renders final docs, marketplace, and protocol links.
693
+ */
694
+ export function renderFooter(model) {
695
+ return `
696
+ <footer class="footer">
697
+ <div class="footer-grid">
698
+ <div>
699
+ <strong>SAP MCP Server</strong>
700
+ <p>Hosted by OOBE Protocol for agentic Solana operations.</p>
701
+ </div>
702
+ <div>
703
+ <strong>Site</strong>
704
+ <a href="${escapeHtml(model.info.endpoints.landing)}">Home</a>
705
+ <a href="${escapeHtml(model.info.endpoints.docs)}">Documentation</a>
706
+ <a href="${escapeHtml(model.info.docs.github)}">GitHub</a>
707
+ <a href="${escapeHtml(model.info.docs.npm)}">npm</a>
708
+ </div>
709
+ <div>
710
+ <strong>Discovery</strong>
711
+ <a href="${escapeHtml(model.info.endpoints.serverInfo)}">Server JSON</a>
712
+ <a href="${escapeHtml(model.info.endpoints.openApi)}">OpenAPI</a>
713
+ <a href="${escapeHtml(model.info.endpoints.agentCard)}">Agent card</a>
714
+ <a href="${escapeHtml(model.info.endpoints.smitheryServerCard)}">MCP server card</a>
715
+ </div>
716
+ <div>
717
+ <strong>Payments</strong>
718
+ <a href="${escapeHtml(model.info.endpoints.x402Discovery)}">x402 discovery</a>
719
+ <a href="${escapeHtml(model.info.endpoints.payShProvider)}">pay.sh YAML</a>
720
+ <a href="${escapeHtml(model.info.endpoints.docs)}/#/user/03_PAYMENTS_X402_PAYSH">Payment docs</a>
721
+ <a href="${escapeHtml(model.info.endpoints.wizardDownloads)}">Wizard downloads</a>
722
+ </div>
723
+ </div>
724
+ </footer>
725
+ `;
726
+ }
727
+ //# sourceMappingURL=sections.js.map