@skyelight/mcp 0.6.0 → 0.7.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/CHANGELOG.md +26 -1
- package/README.md +48 -26
- package/package.json +1 -1
- package/src/brand.js +1 -4
- package/src/client.js +1 -1
- package/src/tools.d.ts +1 -0
- package/src/tools.js +77 -31
- package/src/version.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -11,7 +11,32 @@ keeps working. A **patch** is a fix or a wording change. A **major** would be
|
|
|
11
11
|
removing a tool or an argument, or changing what an existing field means, and
|
|
12
12
|
there has not been one.
|
|
13
13
|
|
|
14
|
-
## 0.
|
|
14
|
+
## 0.7.1 — unreleased
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- **Docs.** The README lists `publish_review_link` and says what the MCP
|
|
19
|
+
does on Free. No change to the tools.
|
|
20
|
+
|
|
21
|
+
## 0.7.0 — 2026-10-05
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- **`publish_prototype` is now `publish_review_link`, and takes `code` or
|
|
26
|
+
`url`.** With `code`, as before: Skyelight hosts one file at its own link.
|
|
27
|
+
With `url`, a deployed app (Lovable, v0, Bolt, Vercel) goes on the
|
|
28
|
+
project's Review Links, and the answer carries the script tag to add to
|
|
29
|
+
the app's `<head>`. Code that is part of a larger app is no longer hosted;
|
|
30
|
+
the answer says to send the app's `url`. The server still answers the old
|
|
31
|
+
name, so 0.6.0 keeps working.
|
|
32
|
+
- **`source`:** where a hosted prototype was made (`claude`, `openai`, `v0`,
|
|
33
|
+
`lovable` and others), shown as its logo on the project's Review Links.
|
|
34
|
+
|
|
35
|
+
- **`list_workspaces` says what an agent can't do in a workspace:** a
|
|
36
|
+
reviewer seat, a plan without agent tools, or Free, whose MCP publishes
|
|
37
|
+
prototypes.
|
|
38
|
+
|
|
39
|
+
## 0.6.0 — 2026-10-05
|
|
15
40
|
|
|
16
41
|
### Added
|
|
17
42
|
|
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Full guide: [skyelight.ai/docs/mcp](https://skyelight.ai/docs/mcp). The REST
|
|
|
8
8
|
API behind the local server is documented at
|
|
9
9
|
[skyelight.ai/docs/api](https://skyelight.ai/docs/api).
|
|
10
10
|
|
|
11
|
-
Two ways to connect, with the same
|
|
11
|
+
Two ways to connect, with the same eighteen tools either way:
|
|
12
12
|
|
|
13
13
|
- **Remote, with OAuth** — the default. Your agent talks to Skyelight over
|
|
14
14
|
HTTP and you sign in once in the browser. Nothing is pasted and no key is
|
|
@@ -18,8 +18,10 @@ Two ways to connect, with the same seventeen tools either way:
|
|
|
18
18
|
browser sign-in is not an option.
|
|
19
19
|
|
|
20
20
|
Coding agents need a paid seat (owner, admin or collaborator) on a Pro plan or
|
|
21
|
-
above.
|
|
22
|
-
agent
|
|
21
|
+
above. On Free, the same seat connects too and can publish to Skyelight
|
|
22
|
+
(`publish_review_link`, one hosted prototype); reading feedback with an agent
|
|
23
|
+
is on Pro. A reviewer seat reads and comments in the web app but does not
|
|
24
|
+
carry agent tools.
|
|
23
25
|
|
|
24
26
|
## The short way
|
|
25
27
|
|
|
@@ -101,25 +103,41 @@ agent calls `list_projects` first rather than guess.
|
|
|
101
103
|
|
|
102
104
|
## Tools
|
|
103
105
|
|
|
104
|
-
| Tool
|
|
105
|
-
|
|
|
106
|
-
| `list_workspaces`
|
|
107
|
-
| `list_projects`
|
|
108
|
-
| `list_items`
|
|
109
|
-
| `search_items`
|
|
110
|
-
| `get_item`
|
|
111
|
-
| `post_update`
|
|
112
|
-
| `create_item`
|
|
113
|
-
| `set_status`
|
|
114
|
-
| `list_members`
|
|
115
|
-
| `assign`
|
|
116
|
-
| `whats_new`
|
|
117
|
-
| `project_review`
|
|
118
|
-
| `decision_log`
|
|
119
|
-
| `save_rule`
|
|
120
|
-
| `find_by_source`
|
|
121
|
-
| `find_similar`
|
|
122
|
-
| `merge_items`
|
|
106
|
+
| Tool | What it is for |
|
|
107
|
+
| --------------------- | ------------------------------------------------------------------------------------ |
|
|
108
|
+
| `list_workspaces` | Which workspaces this credential can reach, and who you are. |
|
|
109
|
+
| `list_projects` | The projects inside them, with the ids the other tools take. |
|
|
110
|
+
| `list_items` | What is outstanding. Filter by page, type, status, assignee. |
|
|
111
|
+
| `search_items` | Find items whose thread mentions some text, replies included. |
|
|
112
|
+
| `get_item` | Everything needed to work one item: thread, page, anchor, code, images. |
|
|
113
|
+
| `post_update` | Report back on the thread the feedback came from. |
|
|
114
|
+
| `create_item` | Raise a new item — an audit finding, something you noticed. |
|
|
115
|
+
| `set_status` | Move an item to open, deferred or resolved. |
|
|
116
|
+
| `list_members` | Who is in the workspace, so you can name an assignee or a mention. |
|
|
117
|
+
| `assign` | Hand an item to a person, or unassign it. |
|
|
118
|
+
| `whats_new` | What changed since you last looked, from your own bookmark. |
|
|
119
|
+
| `project_review` | Where a project landed, for a wrap-up or hand-off document. |
|
|
120
|
+
| `decision_log` | What the team decided in its threads, quoted, and its current rules. |
|
|
121
|
+
| `save_rule` | Keep an agreed rule in the project context (owners and admins). |
|
|
122
|
+
| `find_by_source` | Feedback on a file or component before you edit it, or the hot spots. |
|
|
123
|
+
| `find_similar` | Check for an existing report before creating one. |
|
|
124
|
+
| `merge_items` | Fold duplicate items into one. |
|
|
125
|
+
| `publish_review_link` | Share something for review: code for Skyelight to host, or a deployed app's address. |
|
|
126
|
+
|
|
127
|
+
**Publishing for review.** `publish_review_link` takes one of two things:
|
|
128
|
+
|
|
129
|
+
- `code`: one HTML page, or one React component with an export default (a
|
|
130
|
+
Claude prototype, a v0 snippet). Skyelight hosts it at its own link on
|
|
131
|
+
`skyelight.page` with the review badge on it, in a project you name or a new
|
|
132
|
+
one. Publishing again makes a new version at the same link.
|
|
133
|
+
- `url`: an app already deployed, such as a Lovable, v0 or Bolt project on
|
|
134
|
+
`*.lovable.app` or `*.vercel.app`. The address goes on the project's Review
|
|
135
|
+
Links, and the answer carries a script tag for the app's `<head>` and the
|
|
136
|
+
review link to share (the address with `?skyelight=1`).
|
|
137
|
+
|
|
138
|
+
Code that imports the rest of its app is not hosted; the answer says to send
|
|
139
|
+
the app's `url` instead. It answers to `publish_prototype` too, its name
|
|
140
|
+
before 0.7.0.
|
|
123
141
|
|
|
124
142
|
`list_items` leads with a summary — totals, breakdown by type and by page — so
|
|
125
143
|
an agent can tell you the shape of the work before pulling any of it. Rows are
|
|
@@ -205,10 +223,14 @@ The server enforces nothing; the API does. The agent can do what your account
|
|
|
205
223
|
can do in that workspace, and nothing more:
|
|
206
224
|
|
|
207
225
|
- Agent tools need a **paid seat** (owner, admin or collaborator) in an
|
|
208
|
-
organization on **Pro or above**. A reviewer seat
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
226
|
+
organization on **Pro or above**. A reviewer seat is refused with the
|
|
227
|
+
reason — the workspace is listed and marked rather than hidden, so you are
|
|
228
|
+
told which gate closed instead of being told it does not exist.
|
|
229
|
+
- **On Free**, a paid seat connects for publishing: `list_workspaces`,
|
|
230
|
+
`list_projects` and `publish_review_link` (one hosted prototype). The
|
|
231
|
+
reading tools answer with how much feedback is waiting and that reading it
|
|
232
|
+
is on Pro; the rest name the plan.
|
|
233
|
+
- Adding a deployed app's address to Review Links is for owners and admins.
|
|
212
234
|
- Owners, admins and collaborators read, reply, raise items and change any
|
|
213
235
|
thread's status.
|
|
214
236
|
- A token only reaches workspaces in the organization it was created in.
|
package/package.json
CHANGED
package/src/brand.js
CHANGED
|
@@ -61,8 +61,5 @@ export const STATUS = {
|
|
|
61
61
|
merge_items: ["Merging duplicates", "Merged the duplicates"],
|
|
62
62
|
decision_log: ["Reading the decisions", "Read the decisions"],
|
|
63
63
|
save_rule: ["Saving the rule", "Saved the rule"],
|
|
64
|
-
|
|
65
|
-
"Publishing the prototype to Skyelight",
|
|
66
|
-
"Published the prototype",
|
|
67
|
-
],
|
|
64
|
+
publish_review_link: ["Publishing to Skyelight", "Published to Skyelight"],
|
|
68
65
|
};
|
package/src/client.js
CHANGED
|
@@ -110,6 +110,6 @@ export function createClient({ apiUrl, token, fetchImpl = fetch }) {
|
|
|
110
110
|
mergeItems: (body) => post("/api/v1/items/merge", body),
|
|
111
111
|
decisionLog: (params) => request("/api/v1/decisions", params),
|
|
112
112
|
saveRule: (body) => post("/api/v1/rules", body),
|
|
113
|
-
|
|
113
|
+
publishReviewLink: (body) => post("/api/v1/review-links", body),
|
|
114
114
|
};
|
|
115
115
|
}
|
package/src/tools.d.ts
CHANGED
|
@@ -42,6 +42,7 @@ export declare function renderMembers(result: unknown): string;
|
|
|
42
42
|
export declare function renderAssigned(result: unknown): string;
|
|
43
43
|
|
|
44
44
|
export declare function renderPublished(result: unknown): string;
|
|
45
|
+
export declare function renderReviewLink(result: unknown): string;
|
|
45
46
|
export declare function renderPosted(
|
|
46
47
|
result: unknown,
|
|
47
48
|
opts: { kind: "update" | "item" },
|
package/src/tools.js
CHANGED
|
@@ -204,31 +204,42 @@ export function toolDefinitions(opts = {}) {
|
|
|
204
204
|
},
|
|
205
205
|
},
|
|
206
206
|
{
|
|
207
|
-
name: "
|
|
207
|
+
name: "publish_review_link",
|
|
208
208
|
description:
|
|
209
|
-
"
|
|
210
|
-
"
|
|
211
|
-
"
|
|
212
|
-
"an export default (Tailwind classes and npm imports work; local
|
|
213
|
-
"@/components do not).
|
|
214
|
-
"
|
|
215
|
-
"
|
|
209
|
+
"Share something with Skyelight for review, and get a link people can pin feedback on. " +
|
|
210
|
+
"Two ways:\n" +
|
|
211
|
+
"- code: one file Skyelight hosts at its own link with the review badge on it. A whole HTML page, " +
|
|
212
|
+
"or one React component with an export default (Tailwind classes and npm imports work; local " +
|
|
213
|
+
"imports such as @/components do not). For Claude prototypes, v0 snippets and single pages. " +
|
|
214
|
+
"Publishing again with the same prototypeId, or the same name in the same project, makes a new " +
|
|
215
|
+
"version at the same link.\n" +
|
|
216
|
+
"- url: an app already deployed (a Lovable, v0, Bolt or Vercel project: anything with more than " +
|
|
217
|
+
"one file). Adds its address to the project's Review Links and returns a script tag to add to the " +
|
|
218
|
+
"app's <head> (index.html, or the root layout); add it and redeploy. Owners and admins.\n" +
|
|
219
|
+
"Returns the share link and the project link; give both to the person. A hosted link is public " +
|
|
220
|
+
"to anyone who has it.",
|
|
216
221
|
inputSchema: {
|
|
217
222
|
type: "object",
|
|
218
223
|
properties: {
|
|
219
|
-
|
|
224
|
+
code: {
|
|
220
225
|
type: "string",
|
|
221
226
|
description:
|
|
222
|
-
"
|
|
227
|
+
"For Skyelight to host: the complete file, never a summary or an excerpt. Or give url.",
|
|
223
228
|
},
|
|
224
|
-
|
|
229
|
+
url: {
|
|
225
230
|
type: "string",
|
|
226
|
-
description:
|
|
231
|
+
description:
|
|
232
|
+
"Where the app is deployed, e.g. https://my-app.lovable.app. Or give code.",
|
|
233
|
+
},
|
|
234
|
+
name: {
|
|
235
|
+
type: "string",
|
|
236
|
+
description:
|
|
237
|
+
"What it is, in a few words. Names the hosted link and, when no project is given, a new project.",
|
|
227
238
|
},
|
|
228
239
|
kind: {
|
|
229
240
|
type: "string",
|
|
230
241
|
enum: ["html", "react"],
|
|
231
|
-
description: "
|
|
242
|
+
description: "With code; worked out from it when left out.",
|
|
232
243
|
},
|
|
233
244
|
projectId: {
|
|
234
245
|
type: "string",
|
|
@@ -238,15 +249,19 @@ export function toolDefinitions(opts = {}) {
|
|
|
238
249
|
prototypeId: {
|
|
239
250
|
type: "string",
|
|
240
251
|
description:
|
|
241
|
-
"
|
|
252
|
+
"With code: to publish a new version of a prototype published before.",
|
|
242
253
|
},
|
|
243
254
|
workspaceId: {
|
|
244
255
|
type: "string",
|
|
245
256
|
description:
|
|
246
257
|
"When you are in more than one workspace and give no project, from list_workspaces.",
|
|
247
258
|
},
|
|
259
|
+
source: {
|
|
260
|
+
type: "string",
|
|
261
|
+
description:
|
|
262
|
+
'With code: where it was made, shown as its logo in Skyelight: "claude", "claude-code", "openai" (ChatGPT), "cursor", "windsurf", "v0", "lovable" or "other". Name yourself.',
|
|
263
|
+
},
|
|
248
264
|
},
|
|
249
|
-
required: ["code"],
|
|
250
265
|
},
|
|
251
266
|
},
|
|
252
267
|
{
|
|
@@ -386,8 +401,9 @@ const TOOL_ANNOTATIONS = {
|
|
|
386
401
|
save_rule: { ...WRITE, idempotentHint: true },
|
|
387
402
|
// Hides items from every list (reversible in the app, but not here).
|
|
388
403
|
merge_items: { ...WRITE, destructiveHint: true },
|
|
389
|
-
// Puts code at a public link
|
|
390
|
-
|
|
404
|
+
// Puts code at a public link, or lets reviewers sign in on another site:
|
|
405
|
+
// either way, something the person should agree to.
|
|
406
|
+
publish_review_link: { ...WRITE, openWorldHint: true },
|
|
391
407
|
};
|
|
392
408
|
|
|
393
409
|
function plural(n, one, many) {
|
|
@@ -433,6 +449,9 @@ export function renderWorkspaces(result) {
|
|
|
433
449
|
const projects = plural(w.projectCount, "project", "projects");
|
|
434
450
|
lines.push(` ${w.name} — ${w.role}, ${projects}`);
|
|
435
451
|
lines.push(` ${w.id}`);
|
|
452
|
+
// What an agent cannot do here, and why: a seat to ask for, a plan to
|
|
453
|
+
// upgrade, or Free's MCP, which publishes prototypes.
|
|
454
|
+
if (w.unavailableReason) lines.push(` ${w.unavailableReason}`);
|
|
436
455
|
}
|
|
437
456
|
return lines.join("\n");
|
|
438
457
|
}
|
|
@@ -810,6 +829,19 @@ export function renderPublished(result) {
|
|
|
810
829
|
return lines.join("\n");
|
|
811
830
|
}
|
|
812
831
|
|
|
832
|
+
export function renderReviewLink(result) {
|
|
833
|
+
return [
|
|
834
|
+
result.alreadyAdded
|
|
835
|
+
? `${result.origin} was already on ${result.projectName}'s Review Links.`
|
|
836
|
+
: `Added ${result.origin} to ${result.projectName}'s Review Links${result.createdProject ? " (new project)" : ""}.`,
|
|
837
|
+
"Add this to the app's <head> (index.html, or the root layout), then redeploy:",
|
|
838
|
+
result.scriptTag,
|
|
839
|
+
`Share link: ${result.shareUrl}`,
|
|
840
|
+
`Project: ${result.projectUrl}`,
|
|
841
|
+
"Reviewers sign in to Skyelight from the badge to leave pins.",
|
|
842
|
+
].join("\n");
|
|
843
|
+
}
|
|
844
|
+
|
|
813
845
|
export function renderMembers(result) {
|
|
814
846
|
const members = result?.members ?? [];
|
|
815
847
|
const where = result?.workspace?.name ? ` in ${result.workspace.name}` : "";
|
|
@@ -897,24 +929,38 @@ export async function callTool(name, args, { client, config }) {
|
|
|
897
929
|
return { text: renderPosted(result, { kind: "item" }), data: result };
|
|
898
930
|
}
|
|
899
931
|
|
|
900
|
-
if (name === "publish_prototype") {
|
|
901
|
-
|
|
932
|
+
if (name === "publish_review_link" || name === "publish_prototype") {
|
|
933
|
+
const hasCode = !!args.code?.trim();
|
|
934
|
+
const hasUrl = !!args.url?.trim();
|
|
935
|
+
if (hasCode === hasUrl) {
|
|
902
936
|
throw new Error(
|
|
903
|
-
"
|
|
937
|
+
"publish_review_link takes code (one file for Skyelight to host) or url (where the app is deployed)",
|
|
904
938
|
);
|
|
905
939
|
}
|
|
906
|
-
if (!args.prototypeId && !args.name?.trim()) {
|
|
907
|
-
throw new Error("
|
|
940
|
+
if (hasCode && !args.prototypeId && !args.name?.trim()) {
|
|
941
|
+
throw new Error("publish_review_link needs a name");
|
|
908
942
|
}
|
|
909
|
-
const
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
943
|
+
const pick = (keys) =>
|
|
944
|
+
Object.fromEntries(keys.filter((k) => args[k]).map((k) => [k, args[k]]));
|
|
945
|
+
const result = await client.publishReviewLink(
|
|
946
|
+
hasUrl
|
|
947
|
+
? pick(["url", "projectId", "name", "workspaceId"])
|
|
948
|
+
: {
|
|
949
|
+
name: args.name ?? "",
|
|
950
|
+
...pick([
|
|
951
|
+
"code",
|
|
952
|
+
"kind",
|
|
953
|
+
"projectId",
|
|
954
|
+
"prototypeId",
|
|
955
|
+
"workspaceId",
|
|
956
|
+
"source",
|
|
957
|
+
]),
|
|
958
|
+
},
|
|
959
|
+
);
|
|
960
|
+
return {
|
|
961
|
+
text: result?.linked ? renderReviewLink(result) : renderPublished(result),
|
|
962
|
+
data: result,
|
|
963
|
+
};
|
|
918
964
|
}
|
|
919
965
|
|
|
920
966
|
if (name === "list_members") {
|
package/src/version.js
CHANGED