@curatedmcp/tokenshield-core 0.3.0 → 1.0.1

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/dist/server.js CHANGED
@@ -71,6 +71,15 @@ export async function start(opts) {
71
71
  res.end(JSON.stringify({ ok: true, version: "0.1.0" }));
72
72
  return;
73
73
  }
74
+ // Friendly landing page for humans who hit the proxy port in a browser.
75
+ // The proxy itself only speaks /v1/messages, /v1/messages/stream, etc.
76
+ if (req.method === "GET" && (req.url === "/" || req.url === "/index.html")) {
77
+ res.statusCode = 200;
78
+ res.setHeader("content-type", "text/html; charset=utf-8");
79
+ res.setHeader("cache-control", "no-store");
80
+ res.end(proxyLandingHtml(opts.config));
81
+ return;
82
+ }
74
83
  handleAnthropicRequest(req, res, opts.config, sink).catch((err) => {
75
84
  if (!res.headersSent) {
76
85
  res.statusCode = 500;
@@ -154,4 +163,67 @@ function defaultDashboardHtml() {
154
163
  return `<!doctype html><meta charset="utf-8"><title>TokenShield</title>
155
164
  <body><h1>TokenShield</h1><p>Dashboard renderer not provided.</p></body>`;
156
165
  }
166
+ function proxyLandingHtml(config) {
167
+ const dashUrl = `http://${config.bind === "0.0.0.0" ? "127.0.0.1" : config.bind}:${config.dashboardPort}`;
168
+ const exportLine = `export ANTHROPIC_BASE_URL=http://${config.bind === "0.0.0.0" ? "127.0.0.1" : config.bind}:${config.port}`;
169
+ return `<!doctype html>
170
+ <html lang="en"><head>
171
+ <meta charset="utf-8">
172
+ <title>TokenShield proxy</title>
173
+ <meta name="viewport" content="width=device-width,initial-scale=1">
174
+ <style>
175
+ *{box-sizing:border-box}
176
+ body{font:15px/1.55 -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;background:#0b0d12;color:#e6e7ea;margin:0;padding:40px 20px;display:flex;justify-content:center}
177
+ main{max-width:640px;width:100%}
178
+ .pill{display:inline-flex;align-items:center;gap:6px;background:rgba(34,197,94,.12);color:#4ade80;padding:4px 10px;border-radius:999px;font-size:12px;font-weight:600}
179
+ .pill::before{content:'';width:6px;height:6px;border-radius:50%;background:#22c55e;animation:pulse 2s ease-in-out infinite}
180
+ @keyframes pulse{0%,100%{opacity:1}50%{opacity:.4}}
181
+ h1{font-size:28px;margin:16px 0 8px;font-weight:700}
182
+ .subtitle{color:#9ca3af;margin:0 0 28px}
183
+ .card{background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08);border-radius:12px;padding:20px 22px;margin:14px 0}
184
+ .card h2{font-size:14px;text-transform:uppercase;letter-spacing:.06em;color:#a5b4fc;margin:0 0 8px}
185
+ code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;background:rgba(255,255,255,.07);padding:2px 6px;border-radius:4px;font-size:13px;color:#fbbf24}
186
+ pre{background:rgba(0,0,0,.4);border:1px solid rgba(255,255,255,.08);border-radius:8px;padding:14px 16px;overflow-x:auto;margin:8px 0 0}
187
+ pre code{background:none;padding:0;color:#86efac}
188
+ a{color:#a5b4fc;text-decoration:none;border-bottom:1px solid rgba(165,180,252,.3)}
189
+ a:hover{border-color:#a5b4fc}
190
+ .footer{margin-top:32px;font-size:12px;color:#6b7280;text-align:center}
191
+ .dash-cta{display:inline-block;background:#22c55e;color:#0b0d12;font-weight:600;padding:10px 20px;border-radius:8px;text-decoration:none;border:0;margin-top:6px}
192
+ .dash-cta:hover{background:#16a34a}
193
+ </style>
194
+ </head><body><main>
195
+ <span class="pill">TokenShield is running</span>
196
+ <h1>This is the proxy, not the dashboard.</h1>
197
+ <p class="subtitle">You hit port ${config.port} — that's where Claude Code (or Cursor, Windsurf, Aider) sends its API requests. The proxy doesn't serve a UI; it forwards traffic to Anthropic.</p>
198
+
199
+ <div class="card">
200
+ <h2>→ Want the dashboard?</h2>
201
+ <p style="margin:0 0 12px">Live spend, requests, savings, and recent traffic:</p>
202
+ <a class="dash-cta" href="${dashUrl}">Open dashboard →</a>
203
+ </div>
204
+
205
+ <div class="card">
206
+ <h2>→ Route Claude Code through this proxy</h2>
207
+ <p style="margin:0 0 4px">In the shell where you run <code>claude</code>:</p>
208
+ <pre><code>${exportLine}</code></pre>
209
+ <p style="margin:12px 0 0;font-size:13px;color:#9ca3af">Your <code>ANTHROPIC_API_KEY</code> stays where it is. TokenShield never reads it.</p>
210
+ </div>
211
+
212
+ <div class="card">
213
+ <h2>→ Other clients</h2>
214
+ <p style="margin:0;font-size:13px;color:#9ca3af">
215
+ <strong style="color:#e6e7ea">Cursor / Windsurf:</strong> Settings → AI → Custom Base URL = <code>http://${config.bind === "0.0.0.0" ? "127.0.0.1" : config.bind}:${config.port}</code>
216
+ <br><br>
217
+ <strong style="color:#e6e7ea">Anthropic SDK:</strong> set <code>baseURL</code> when instantiating the client.
218
+ <br><br>
219
+ <strong style="color:#e6e7ea">Auto-configure your shell:</strong> <code>tokenshield integrations enable claude-code</code>
220
+ </p>
221
+ </div>
222
+
223
+ <p class="footer">
224
+ Docs: <a href="https://curatedmcp.com/tokenshield">curatedmcp.com/tokenshield</a> &nbsp;·&nbsp;
225
+ Source: <a href="https://github.com/oneprofile-dev/tokenshield">github.com/oneprofile-dev/tokenshield</a>
226
+ </p>
227
+ </main></body></html>`;
228
+ }
157
229
  //# sourceMappingURL=server.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@curatedmcp/tokenshield-core",
3
- "version": "0.3.0",
3
+ "version": "1.0.1",
4
4
  "description": "TokenShield proxy engine — Anthropic API-layer middleware with token accounting",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/src/server.ts CHANGED
@@ -91,6 +91,15 @@ export async function start(opts: StartOptions): Promise<ProxyServerHandle> {
91
91
  res.end(JSON.stringify({ ok: true, version: "0.1.0" }));
92
92
  return;
93
93
  }
94
+ // Friendly landing page for humans who hit the proxy port in a browser.
95
+ // The proxy itself only speaks /v1/messages, /v1/messages/stream, etc.
96
+ if (req.method === "GET" && (req.url === "/" || req.url === "/index.html")) {
97
+ res.statusCode = 200;
98
+ res.setHeader("content-type", "text/html; charset=utf-8");
99
+ res.setHeader("cache-control", "no-store");
100
+ res.end(proxyLandingHtml(opts.config));
101
+ return;
102
+ }
94
103
  handleAnthropicRequest(req, res, opts.config, sink).catch((err: unknown) => {
95
104
  if (!res.headersSent) {
96
105
  res.statusCode = 500;
@@ -178,3 +187,67 @@ function defaultDashboardHtml(): string {
178
187
  return `<!doctype html><meta charset="utf-8"><title>TokenShield</title>
179
188
  <body><h1>TokenShield</h1><p>Dashboard renderer not provided.</p></body>`;
180
189
  }
190
+
191
+ function proxyLandingHtml(config: ProxyConfig): string {
192
+ const dashUrl = `http://${config.bind === "0.0.0.0" ? "127.0.0.1" : config.bind}:${config.dashboardPort}`;
193
+ const exportLine = `export ANTHROPIC_BASE_URL=http://${config.bind === "0.0.0.0" ? "127.0.0.1" : config.bind}:${config.port}`;
194
+ return `<!doctype html>
195
+ <html lang="en"><head>
196
+ <meta charset="utf-8">
197
+ <title>TokenShield proxy</title>
198
+ <meta name="viewport" content="width=device-width,initial-scale=1">
199
+ <style>
200
+ *{box-sizing:border-box}
201
+ body{font:15px/1.55 -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;background:#0b0d12;color:#e6e7ea;margin:0;padding:40px 20px;display:flex;justify-content:center}
202
+ main{max-width:640px;width:100%}
203
+ .pill{display:inline-flex;align-items:center;gap:6px;background:rgba(34,197,94,.12);color:#4ade80;padding:4px 10px;border-radius:999px;font-size:12px;font-weight:600}
204
+ .pill::before{content:'';width:6px;height:6px;border-radius:50%;background:#22c55e;animation:pulse 2s ease-in-out infinite}
205
+ @keyframes pulse{0%,100%{opacity:1}50%{opacity:.4}}
206
+ h1{font-size:28px;margin:16px 0 8px;font-weight:700}
207
+ .subtitle{color:#9ca3af;margin:0 0 28px}
208
+ .card{background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08);border-radius:12px;padding:20px 22px;margin:14px 0}
209
+ .card h2{font-size:14px;text-transform:uppercase;letter-spacing:.06em;color:#a5b4fc;margin:0 0 8px}
210
+ code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;background:rgba(255,255,255,.07);padding:2px 6px;border-radius:4px;font-size:13px;color:#fbbf24}
211
+ pre{background:rgba(0,0,0,.4);border:1px solid rgba(255,255,255,.08);border-radius:8px;padding:14px 16px;overflow-x:auto;margin:8px 0 0}
212
+ pre code{background:none;padding:0;color:#86efac}
213
+ a{color:#a5b4fc;text-decoration:none;border-bottom:1px solid rgba(165,180,252,.3)}
214
+ a:hover{border-color:#a5b4fc}
215
+ .footer{margin-top:32px;font-size:12px;color:#6b7280;text-align:center}
216
+ .dash-cta{display:inline-block;background:#22c55e;color:#0b0d12;font-weight:600;padding:10px 20px;border-radius:8px;text-decoration:none;border:0;margin-top:6px}
217
+ .dash-cta:hover{background:#16a34a}
218
+ </style>
219
+ </head><body><main>
220
+ <span class="pill">TokenShield is running</span>
221
+ <h1>This is the proxy, not the dashboard.</h1>
222
+ <p class="subtitle">You hit port ${config.port} — that's where Claude Code (or Cursor, Windsurf, Aider) sends its API requests. The proxy doesn't serve a UI; it forwards traffic to Anthropic.</p>
223
+
224
+ <div class="card">
225
+ <h2>→ Want the dashboard?</h2>
226
+ <p style="margin:0 0 12px">Live spend, requests, savings, and recent traffic:</p>
227
+ <a class="dash-cta" href="${dashUrl}">Open dashboard →</a>
228
+ </div>
229
+
230
+ <div class="card">
231
+ <h2>→ Route Claude Code through this proxy</h2>
232
+ <p style="margin:0 0 4px">In the shell where you run <code>claude</code>:</p>
233
+ <pre><code>${exportLine}</code></pre>
234
+ <p style="margin:12px 0 0;font-size:13px;color:#9ca3af">Your <code>ANTHROPIC_API_KEY</code> stays where it is. TokenShield never reads it.</p>
235
+ </div>
236
+
237
+ <div class="card">
238
+ <h2>→ Other clients</h2>
239
+ <p style="margin:0;font-size:13px;color:#9ca3af">
240
+ <strong style="color:#e6e7ea">Cursor / Windsurf:</strong> Settings → AI → Custom Base URL = <code>http://${config.bind === "0.0.0.0" ? "127.0.0.1" : config.bind}:${config.port}</code>
241
+ <br><br>
242
+ <strong style="color:#e6e7ea">Anthropic SDK:</strong> set <code>baseURL</code> when instantiating the client.
243
+ <br><br>
244
+ <strong style="color:#e6e7ea">Auto-configure your shell:</strong> <code>tokenshield integrations enable claude-code</code>
245
+ </p>
246
+ </div>
247
+
248
+ <p class="footer">
249
+ Docs: <a href="https://curatedmcp.com/tokenshield">curatedmcp.com/tokenshield</a> &nbsp;·&nbsp;
250
+ Source: <a href="https://github.com/oneprofile-dev/tokenshield">github.com/oneprofile-dev/tokenshield</a>
251
+ </p>
252
+ </main></body></html>`;
253
+ }