naro-mcp 0.5.3 → 0.6.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.
Files changed (2) hide show
  1. package/dist/index.js +162 -9
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -108,8 +108,149 @@ function controlPlaneUrl(env = process.env) {
108
108
 
109
109
  // ../../packages/sdk/src/callback-server.ts
110
110
  import { createServer } from "http";
111
- var DONE_HTML = "<html><body><p>\u2705 Logged in. You can close this tab and return to the terminal.</p></body></html>";
112
- var FAIL_HTML = "<html><body><p>Login failed. You can close this tab and return to the terminal.</p></body></html>";
111
+
112
+ // ../../packages/sdk/src/callback-page.ts
113
+ function escapeHtml(value) {
114
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
115
+ }
116
+ var FAVICON = `data:image/svg+xml,${encodeURIComponent(
117
+ '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><rect width="32" height="32" rx="8" fill="#ededed"/><text x="16" y="23" text-anchor="middle" fill="#000" font-family="system-ui,sans-serif" font-size="20" font-weight="700">n</text></svg>'
118
+ )}`;
119
+ var CHECK_ICON = '<svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M5 12.5 10 17.5 19 7.5" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>';
120
+ var CROSS_ICON = '<svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M7 7 17 17M17 7 7 17" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>';
121
+ var STYLES = `
122
+ *{box-sizing:border-box}
123
+ :root{
124
+ --bg:#000;--surface:#0a0a0a;--surface-2:#111;--border:#232323;
125
+ --text:#ededed;--muted:#a1a1a1;--faint:#6f6f6f;
126
+ --sans:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;
127
+ --mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
128
+ }
129
+ html{color-scheme:dark;-webkit-font-smoothing:antialiased}
130
+ body{
131
+ margin:0;min-height:100vh;display:grid;place-items:center;padding:24px;
132
+ background:var(--bg);color:var(--text);font-family:var(--sans);
133
+ font-size:14px;line-height:1.5;letter-spacing:-.006em;
134
+ }
135
+ body::before{
136
+ content:"";position:fixed;inset:0;pointer-events:none;
137
+ background:radial-gradient(62% 46% at 50% 0%,var(--glow),transparent 72%);
138
+ }
139
+ .card{
140
+ position:relative;width:100%;max-width:400px;padding:34px 32px 28px;
141
+ background:var(--surface);border:1px solid var(--border);border-radius:14px;
142
+ text-align:center;animation:rise .4s cubic-bezier(.2,.7,.3,1) both;
143
+ }
144
+ .brand{
145
+ display:inline-flex;align-items:center;gap:8px;
146
+ font-size:14px;font-weight:600;letter-spacing:-.02em;color:var(--muted);
147
+ }
148
+ .brand-mark{
149
+ display:inline-grid;width:22px;height:22px;place-items:center;
150
+ background:var(--text);color:#000;border-radius:6px;
151
+ font-size:12px;font-weight:700;line-height:1;
152
+ }
153
+ .glyph{
154
+ width:52px;height:52px;margin:26px auto 20px;display:grid;place-items:center;
155
+ border-radius:50%;color:var(--tone);
156
+ background:var(--tone-soft);border:1px solid var(--tone-edge);
157
+ }
158
+ .glyph svg{width:26px;height:26px}
159
+ .glyph path{stroke-dasharray:32;stroke-dashoffset:32;animation:draw .5s .15s cubic-bezier(.2,.7,.3,1) forwards}
160
+ h1{margin:0 0 8px;font-size:19px;font-weight:600;letter-spacing:-.02em}
161
+ p{margin:0 auto;max-width:32ch;color:var(--muted)}
162
+ .detail{
163
+ margin-top:18px;padding:10px 12px;text-align:left;word-break:break-word;
164
+ background:var(--surface-2);border:1px solid var(--border);border-radius:8px;
165
+ font-family:var(--mono);font-size:12.5px;color:var(--muted);
166
+ }
167
+ .hint{
168
+ display:flex;align-items:center;gap:10px;margin-top:22px;padding:10px 12px;
169
+ background:var(--surface-2);border:1px solid var(--border);border-radius:8px;text-align:left;
170
+ }
171
+ .hint-label{
172
+ flex:none;font-size:10px;font-weight:600;letter-spacing:.09em;color:var(--faint);
173
+ }
174
+ .hint code{font-family:var(--mono);font-size:13px;color:var(--text)}
175
+ .hint code::before{content:"$ ";color:var(--faint)}
176
+ footer{margin-top:20px;font-size:12.5px;color:var(--faint)}
177
+ @keyframes rise{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
178
+ @keyframes draw{to{stroke-dashoffset:0}}
179
+ @media (prefers-reduced-motion:reduce){
180
+ .card{animation:none}
181
+ .glyph path{animation:none;stroke-dashoffset:0}
182
+ }
183
+ `;
184
+ var TONES = {
185
+ success: {
186
+ color: "#4ade80",
187
+ soft: "rgba(74,222,128,.12)",
188
+ edge: "rgba(74,222,128,.3)",
189
+ glow: "rgba(74,222,128,.09)",
190
+ icon: CHECK_ICON
191
+ },
192
+ failure: {
193
+ color: "#ff5c5c",
194
+ soft: "rgba(255,92,92,.12)",
195
+ edge: "rgba(255,92,92,.3)",
196
+ glow: "rgba(255,92,92,.09)",
197
+ icon: CROSS_ICON
198
+ }
199
+ };
200
+ function page(options) {
201
+ const tone = TONES[options.tone];
202
+ const title = escapeHtml(options.title);
203
+ const detail = options.detail ? `<div class="detail">${escapeHtml(options.detail)}</div>` : "";
204
+ return `<!doctype html>
205
+ <html lang="en">
206
+ <head>
207
+ <meta charset="utf-8">
208
+ <meta name="viewport" content="width=device-width,initial-scale=1">
209
+ <title>${title} \xB7 naro</title>
210
+ <link rel="icon" href="${FAVICON}">
211
+ <style>:root{--tone:${tone.color};--tone-soft:${tone.soft};--tone-edge:${tone.edge};--glow:${tone.glow}}${STYLES}</style>
212
+ </head>
213
+ <body>
214
+ <main class="card">
215
+ <span class="brand"><span class="brand-mark">n</span>naro</span>
216
+ <div class="glyph">${tone.icon}</div>
217
+ <h1>${title}</h1>
218
+ <p>${escapeHtml(options.message)}</p>
219
+ ${detail}
220
+ <div class="hint">
221
+ <span class="hint-label">${escapeHtml(options.hint.label)}</span>
222
+ <code>${escapeHtml(options.hint.command)}</code>
223
+ </div>
224
+ <footer>You can close this tab.</footer>
225
+ </main>
226
+ </body>
227
+ </html>`;
228
+ }
229
+ function successPage() {
230
+ return page({
231
+ tone: "success",
232
+ title: "You're signed in",
233
+ message: "The CLI saved your session. Head back to the terminal to keep going.",
234
+ hint: { label: "NEXT", command: "naro deploy" }
235
+ });
236
+ }
237
+ function failurePage(reason) {
238
+ return page({
239
+ tone: "failure",
240
+ title: "Sign-in failed",
241
+ message: "Nothing was saved. Return to the terminal and try again.",
242
+ detail: reason,
243
+ hint: { label: "RETRY", command: "naro login" }
244
+ });
245
+ }
246
+
247
+ // ../../packages/sdk/src/callback-server.ts
248
+ function sendPage(res, status, html) {
249
+ res.statusCode = status;
250
+ res.setHeader("content-type", "text/html; charset=utf-8");
251
+ res.setHeader("cache-control", "no-store");
252
+ res.end(html);
253
+ }
113
254
  async function startCallbackServer() {
114
255
  let resolveCode;
115
256
  let rejectCode;
@@ -127,18 +268,20 @@ async function startCallbackServer() {
127
268
  const error51 = url2.searchParams.get("error");
128
269
  const code = url2.searchParams.get("code");
129
270
  if (error51) {
130
- res.setHeader("content-type", "text/html");
131
- res.end(FAIL_HTML);
271
+ const description = url2.searchParams.get("error_description");
272
+ sendPage(res, 200, failurePage(description ?? error51));
132
273
  rejectCode(new Error(`GitHub authorization failed: ${error51}`));
133
274
  return;
134
275
  }
135
276
  if (!code) {
136
- res.statusCode = 400;
137
- res.end("Missing code");
277
+ sendPage(
278
+ res,
279
+ 400,
280
+ failurePage("The callback carried no authorization code.")
281
+ );
138
282
  return;
139
283
  }
140
- res.setHeader("content-type", "text/html");
141
- res.end(DONE_HTML);
284
+ sendPage(res, 200, successPage());
142
285
  resolveCode(code);
143
286
  });
144
287
  await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
@@ -722,6 +865,16 @@ import { join as join4 } from "path";
722
865
  var MAX_FILE_BYTES2 = 25 * 1024 * 1024;
723
866
  var MAX_ARTIFACT_BYTES = 64 * 1024 * 1024;
724
867
 
868
+ // ../../packages/core/src/deployment.ts
869
+ var PHASES = [
870
+ "QUEUED",
871
+ "CLONING",
872
+ "INSTALLING",
873
+ "BUILDING",
874
+ "DEPLOYING"
875
+ ];
876
+ var ACTIVE_STATUSES = new Set(PHASES);
877
+
725
878
  // ../../packages/core/src/git-remote.ts
726
879
  var SCP_LIKE = /^[^@\s/]+@([^:\s/]+):(.+)$/;
727
880
  function parseGitHubRemote(url2) {
@@ -16049,7 +16202,7 @@ function toolErrorJson(error51) {
16049
16202
  // src/server.ts
16050
16203
  function createServer2(deps) {
16051
16204
  const server = new Server(
16052
- { name: "naro", version: "0.5.3" },
16205
+ { name: "naro", version: "0.6.1" },
16053
16206
  { capabilities: { tools: {} } }
16054
16207
  );
16055
16208
  server.setRequestHandler(ListToolsRequestSchema, () => ({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "naro-mcp",
3
- "version": "0.5.3",
3
+ "version": "0.6.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "naro-mcp": "./dist/index.js"
@@ -15,7 +15,7 @@
15
15
  "dependencies": {
16
16
  "@modelcontextprotocol/sdk": "^1.0.0",
17
17
  "@supabase/supabase-js": "2.112.3",
18
- "naro-cli": "0.5.3"
18
+ "naro-cli": "0.6.1"
19
19
  },
20
20
  "devDependencies": {
21
21
  "tsup": "8.5.0",