@@ -13,6 +13,10 @@ interface PageConfig {
1313
1414const github = `<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>` ;
1515
16+ const copyIcon = `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg>` ;
17+
18+ const checkIcon = `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M20 6L9 17l-5-5"/></svg>` ;
19+
1620const styles = `
1721* { margin: 0; padding: 0; box-sizing: border-box; }
1822body {
@@ -31,7 +35,11 @@ h1 code { color: #e5e5e5; }
3135section { margin-bottom: 2.5rem; }
3236.label { font-size: 13px; color: #666; margin-bottom: 0.75rem; }
3337.label span { color: #888; }
34- pre { background: #111; padding: 0.75rem; border-radius: 6px; font-size: 11px; line-height: 1.6; overflow: auto; border: 1px solid #222; color: #888; }
38+ .codeblock { position: relative; }
39+ .codeblock pre { background: #111; padding: 0.75rem; border-radius: 6px; font-size: 11px; line-height: 1.6; overflow: auto; border: 1px solid #222; color: #888; margin: 0; }
40+ .codeblock button { position: absolute; top: 0.5rem; right: 0.5rem; background: transparent; border: none; color: #444; cursor: pointer; padding: 0.25rem; display: flex; align-items: center; justify-content: center; border-radius: 4px; opacity: 0; transition: opacity 0.15s; }
41+ .codeblock:hover button { opacity: 1; }
42+ .codeblock button:hover { color: #888; background: #1a1a1a; }
3543.tools { display: flex; flex-direction: column; gap: 0.5rem; padding-left: 1rem; }
3644.tool { display: flex; align-items: center; gap: 0.75rem; font-size: 11px; }
3745.tool code { color: #999; }
@@ -42,6 +50,19 @@ footer a { color: #444; font-size: 11px; text-decoration: none; display: inline-
4250footer a:hover { color: #666; }
4351` ;
4452
53+ const script = `
54+ function copy(btn) {
55+ const pre = btn.parentElement.querySelector('pre');
56+ navigator.clipboard.writeText(pre.textContent);
57+ btn.innerHTML = '${ checkIcon . replace ( / ' / g, "\\'" ) } ';
58+ setTimeout(() => btn.innerHTML = '${ copyIcon . replace ( / ' / g, "\\'" ) } ', 1500);
59+ }
60+ ` ;
61+
62+ function codeblock ( content : string ) : string {
63+ return `<div class="codeblock"><pre>${ content } </pre><button type="button" onclick="copy(this)" aria-label="copy to clipboard">${ copyIcon } </button></div>` ;
64+ }
65+
4566export function mcppage ( config : PageConfig ) : string {
4667 const breadcrumb = config . path . split ( "/" ) . filter ( Boolean ) ;
4768 const breadcrumbHtml = breadcrumb
@@ -67,6 +88,25 @@ export function mcppage(config: PageConfig): string {
6788 const server = config . path . split ( "/" ) [ 1 ] ;
6889 const ogUrl = `https://kernelize.dev/og?server=${ server } ` ;
6990
91+ const cursorConfig = `{
92+ "mcpServers": {
93+ "${ config . name } ": {
94+ "url": "https://kernelize.dev${ config . path } "
95+ }
96+ }
97+ }` ;
98+
99+ const claudeCommand = `claude mcp add --transport http ${ config . name } https://kernelize.dev${ config . path } ` ;
100+
101+ const opencodeConfig = `{
102+ "mcpServers": {
103+ "${ config . name } ": {
104+ "type": "sse",
105+ "url": "https://kernelize.dev${ config . path } "
106+ }
107+ }
108+ }` ;
109+
70110 return `<!DOCTYPE html>
71111<html lang="en">
72112<head>
@@ -93,30 +133,17 @@ export function mcppage(config: PageConfig): string {
93133
94134 <section>
95135 <p class="label"><span>></span> cursor?</p>
96- <pre>{
97- "mcpServers": {
98- "${ config . name } ": {
99- "url": "https://kernelize.dev${ config . path } "
100- }
101- }
102- }</pre>
136+ ${ codeblock ( cursorConfig ) }
103137 </section>
104138
105139 <section>
106140 <p class="label"><span>></span> claude code?</p>
107- <pre>claude mcp add --transport http ${ config . name } https://kernelize.dev ${ config . path } </pre>
141+ ${ codeblock ( claudeCommand ) }
108142 </section>
109143
110144 <section>
111145 <p class="label"><span>></span> opencode?</p>
112- <pre>{
113- "mcpServers": {
114- "${ config . name } ": {
115- "type": "sse",
116- "url": "https://kernelize.dev${ config . path } "
117- }
118- }
119- }</pre>
146+ ${ codeblock ( opencodeConfig ) }
120147 </section>
121148
122149 <section>
@@ -147,6 +174,7 @@ export function mcppage(config: PageConfig): string {
147174 </a>
148175 </footer>
149176 </div>
177+ <script>${ script } </script>
150178</body>
151179</html>` ;
152180}
0 commit comments