@cloudgrid-io/mcp 0.19.2 → 0.20.2
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/README.md +35 -25
- package/package.json +2 -1
- package/src/auth.js +1 -1
- package/src/cli-shim.mjs +1 -1
- package/src/corpus/capability-map.md +3 -2
- package/src/corpus/cli-reference.md +19 -19
- package/src/corpus/cookbook.md +10 -10
- package/src/corpus/install-for-agents.md +5 -5
- package/src/corpus/install.md +5 -5
- package/src/corpus/rules/publish-fallbacks.md +2 -2
- package/src/corpus/skill-brain.md +6 -6
- package/src/corpus/skill-claim.md +1 -1
- package/src/corpus/skill-feedback.md +6 -6
- package/src/corpus/skill-init.md +8 -8
- package/src/corpus/skill-login.md +3 -3
- package/src/corpus/skill-logs.md +5 -5
- package/src/corpus/skill-plug.md +9 -9
- package/src/corpus/skill-share.md +6 -6
- package/src/corpus/skills-readme.md +2 -2
- package/src/corpus/templates/docs-app/astro.config.mjs +42 -0
- package/src/corpus/templates/docs-app/cloudgrid.yaml +24 -0
- package/src/corpus/templates/docs-app/index.md +40 -0
- package/src/corpus/templates/docs-app/package.json +19 -0
- package/src/corpus/templates/docs-app/src/content/docs/guides/getting-started.md +18 -0
- package/src/corpus/templates/docs-app/src/content/docs/index.mdx +22 -0
- package/src/corpus/templates/docs-app/src/content/docs/reference/overview.md +13 -0
- package/src/corpus/templates/docs-app/src/content.config.ts +7 -0
- package/src/corpus/templates/docs-app/tsconfig.json +5 -0
- package/src/corpus/troubleshooting/deploy-errors.md +1 -1
- package/src/corpus/usage.md +1 -1
- package/src/corpus/workflows/app-with-data.md +1 -1
- package/src/corpus/workflows/docs-app.md +120 -0
- package/src/corpus/workflows/docs-site.md +1 -1
- package/src/index.js +29 -0
- package/src/log-sink.js +45 -0
- package/src/session-logger.js +256 -0
- package/src/tools.js +61 -46
- package/src/web.js +15 -0
|
@@ -4,7 +4,7 @@ name: share
|
|
|
4
4
|
description: |
|
|
5
5
|
Make a CloudGrid entity shareable and print its URL. Use when the user wants to
|
|
6
6
|
share a link, make something public, send an app to someone, or get a shareable
|
|
7
|
-
URL. Wraps
|
|
7
|
+
URL. Wraps grid visibility.
|
|
8
8
|
argument-hint: "[name]"
|
|
9
9
|
allowed-tools: Bash
|
|
10
10
|
---
|
|
@@ -12,12 +12,12 @@ allowed-tools: Bash
|
|
|
12
12
|
# CloudGrid Share
|
|
13
13
|
|
|
14
14
|
Set an entity's visibility so others can reach it, then print the URL. Wraps
|
|
15
|
-
`
|
|
15
|
+
`grid visibility set`.
|
|
16
16
|
|
|
17
17
|
## Step 0 — Bootstrap
|
|
18
18
|
|
|
19
|
-
1. If `
|
|
20
|
-
2. If `
|
|
19
|
+
1. If `grid` is not on `$PATH`: `npm install -g @cloudgrid-io/cli`
|
|
20
|
+
2. If `grid whoami` fails: ask the user to run `grid login`. Wait for
|
|
21
21
|
confirmation.
|
|
22
22
|
|
|
23
23
|
## UX rules
|
|
@@ -31,14 +31,14 @@ Set an entity's visibility so others can reach it, then print the URL. Wraps
|
|
|
31
31
|
To make an entity reachable by anyone with the link:
|
|
32
32
|
|
|
33
33
|
```
|
|
34
|
-
|
|
34
|
+
grid visibility set my-thing link
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
The command prints the outlet URL. Hand that URL to the user.
|
|
38
38
|
|
|
39
39
|
## Visibility modes
|
|
40
40
|
|
|
41
|
-
`
|
|
41
|
+
`grid visibility set <slug> <mode>` accepts:
|
|
42
42
|
|
|
43
43
|
- `link` — anyone with the URL can open it. Use this for sharing.
|
|
44
44
|
- `private` — only the owner.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Multi-agent skills for CloudGrid. Install them in Claude Code, Codex, or Cursor,
|
|
4
4
|
and your agent can build, ship, and run things on CloudGrid through the
|
|
5
|
-
`
|
|
5
|
+
`grid` CLI.
|
|
6
6
|
|
|
7
7
|
## Why CloudGrid
|
|
8
8
|
|
|
@@ -22,7 +22,7 @@ behalf: scaffold, deploy, tail logs, share, read feedback. Everything here is fr
|
|
|
22
22
|
2. Log in:
|
|
23
23
|
|
|
24
24
|
```
|
|
25
|
-
|
|
25
|
+
grid login
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
3. Add the agent-core. In Claude Code (recommended):
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { defineConfig } from 'astro/config';
|
|
3
|
+
import starlight from '@astrojs/starlight';
|
|
4
|
+
import starlightLlmsTxt from 'starlight-llms-txt';
|
|
5
|
+
|
|
6
|
+
// A docs-app is served at the entity ROOT (e.g. https://my-docs--<grid>.cloudgrid.io/),
|
|
7
|
+
// so there is NO `base`. (A base is only needed when a docs site is mounted under
|
|
8
|
+
// a sub-path like /docs — that is a special case, not the default.)
|
|
9
|
+
// https://astro.build/config
|
|
10
|
+
export default defineConfig({
|
|
11
|
+
site: 'https://example.com',
|
|
12
|
+
integrations: [
|
|
13
|
+
starlight({
|
|
14
|
+
// Emit agent-readable docs on every build: /llms.txt (index) and
|
|
15
|
+
// /llms-full.txt (full content). Keeps in sync with the content.
|
|
16
|
+
plugins: [
|
|
17
|
+
starlightLlmsTxt({
|
|
18
|
+
projectName: 'My Project',
|
|
19
|
+
description: 'One-line summary of what this project is — shown to agents at /llms.txt.',
|
|
20
|
+
}),
|
|
21
|
+
],
|
|
22
|
+
title: 'My Project Docs',
|
|
23
|
+
description: 'Documentation for My Project.',
|
|
24
|
+
social: [
|
|
25
|
+
{ icon: 'github', label: 'GitHub', href: 'https://github.com/your-org/your-repo' },
|
|
26
|
+
],
|
|
27
|
+
sidebar: [
|
|
28
|
+
{
|
|
29
|
+
label: 'Start here',
|
|
30
|
+
items: [
|
|
31
|
+
{ label: 'Introduction', slug: 'index' },
|
|
32
|
+
{ label: 'Getting started', slug: 'guides/getting-started' },
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
label: 'Reference',
|
|
37
|
+
items: [{ label: 'Overview', slug: 'reference/overview' }],
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
}),
|
|
41
|
+
],
|
|
42
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# docs-app — a multi-page documentation SITE (Astro Starlight): sidebar,
|
|
2
|
+
# client-side search, and agent-readable llms.txt / llms-full.txt.
|
|
3
|
+
#
|
|
4
|
+
# It is a static site WITH a build step, served at the entity ROOT. Multi-file +
|
|
5
|
+
# build → deploy is async (like a runtime app) and needs the LOCAL edition
|
|
6
|
+
# (Claude Desktop/Code or the CLI); the hosted MCP cannot build it. Deploy with
|
|
7
|
+
# `grid plug` on the linked folder. `llms.txt` and `llms-full.txt` are generated
|
|
8
|
+
# automatically at the site root.
|
|
9
|
+
#
|
|
10
|
+
# For a quick single-page doc with no build, use the `docs-site` archetype instead.
|
|
11
|
+
name: docs-app
|
|
12
|
+
services:
|
|
13
|
+
site:
|
|
14
|
+
type: static
|
|
15
|
+
path: /
|
|
16
|
+
node_version: "22"
|
|
17
|
+
# source.path: . tells the platform the project is at the folder ROOT (not
|
|
18
|
+
# under services/site/). Required for a single root-level build like this;
|
|
19
|
+
# without it the build looks for services/<name>/ and fails.
|
|
20
|
+
source:
|
|
21
|
+
path: .
|
|
22
|
+
build:
|
|
23
|
+
command: "npm run build"
|
|
24
|
+
output: "dist"
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# docs-app template
|
|
2
|
+
|
|
3
|
+
A multi-page documentation **site** for CloudGrid, built with
|
|
4
|
+
[Astro Starlight](https://starlight.astro.build): sidebar navigation,
|
|
5
|
+
client-side full-text search, and agent-readable `llms.txt` / `llms-full.txt`
|
|
6
|
+
generated on every build.
|
|
7
|
+
|
|
8
|
+
Use this when the docs are more than one page and you will keep editing them.
|
|
9
|
+
For a quick single-page doc baked into one HTML file (instant, works on the
|
|
10
|
+
hosted MCP), use the `docs-site` archetype instead.
|
|
11
|
+
|
|
12
|
+
## Layout
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
package.json Astro + Starlight + starlight-llms-txt
|
|
16
|
+
astro.config.mjs site config, sidebar, the llms.txt plugin
|
|
17
|
+
tsconfig.json
|
|
18
|
+
cloudgrid.yaml static + build block, served at the entity root
|
|
19
|
+
src/content.config.ts
|
|
20
|
+
src/content/docs/
|
|
21
|
+
index.mdx the home page
|
|
22
|
+
guides/getting-started.md
|
|
23
|
+
reference/overview.md
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Build + deploy
|
|
27
|
+
|
|
28
|
+
This is a **built** static site, so it needs the local edition (Claude
|
|
29
|
+
Desktop/Code) or the CLI — the hosted MCP cannot build it.
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
npm install
|
|
33
|
+
npm run build # produces dist/ (and dist/llms.txt, dist/llms-full.txt)
|
|
34
|
+
grid plug # deploys the folder; live in ~30s at the entity root
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
`cloudgrid.yaml` declares a single `static` service with a `build:` block
|
|
38
|
+
(`npm run build` → `dist`). The deploy is async — poll to the live URL, then
|
|
39
|
+
return it. Add pages under `src/content/docs/` and list them in the
|
|
40
|
+
`sidebar` in `astro.config.mjs`.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "docs-app",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"description": "A multi-page documentation site on CloudGrid (Astro Starlight + agent-readable llms.txt).",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "astro dev",
|
|
8
|
+
"build": "astro build",
|
|
9
|
+
"preview": "astro preview"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@astrojs/starlight": "^0.41.3",
|
|
13
|
+
"astro": "^7.0.2",
|
|
14
|
+
"sharp": "^0.34.5"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"starlight-llms-txt": "^0.11.0"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Getting started
|
|
3
|
+
description: Install and run My Project.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Replace this guide with real getting-started steps for your project.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
# however your users install it
|
|
12
|
+
npm install my-project
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## First run
|
|
16
|
+
|
|
17
|
+
Explain the smallest useful thing a reader can do, then link them to the
|
|
18
|
+
[reference](/reference/overview/) for the details.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: My Project
|
|
3
|
+
description: Documentation for My Project. Replace this with a one-line summary.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
import { Card, CardGrid, LinkCard } from '@astrojs/starlight/components';
|
|
7
|
+
|
|
8
|
+
Welcome to the documentation for **My Project**. Replace this page with your own
|
|
9
|
+
introduction: what the project is, who it is for, and where to start.
|
|
10
|
+
|
|
11
|
+
<CardGrid>
|
|
12
|
+
<LinkCard title="Getting started" href="/guides/getting-started/" description="Install and run My Project in a few minutes." />
|
|
13
|
+
<LinkCard title="Reference" href="/reference/overview/" description="Full reference for the API and configuration." />
|
|
14
|
+
</CardGrid>
|
|
15
|
+
|
|
16
|
+
## What is here
|
|
17
|
+
|
|
18
|
+
- **Guides** — task-oriented walkthroughs.
|
|
19
|
+
- **Reference** — the complete, look-it-up documentation.
|
|
20
|
+
|
|
21
|
+
The sidebar and search box are generated automatically. Add pages under
|
|
22
|
+
`src/content/docs/` and list them in `astro.config.mjs`.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Reference overview
|
|
3
|
+
description: The complete reference for My Project.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Replace this with your reference material — API, configuration, CLI flags, and so
|
|
7
|
+
on. Reference pages are for looking things up, not for reading top to bottom.
|
|
8
|
+
|
|
9
|
+
## Configuration
|
|
10
|
+
|
|
11
|
+
| Option | Default | What it does |
|
|
12
|
+
| --- | --- | --- |
|
|
13
|
+
| `example` | `false` | Replace with a real option. |
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { defineCollection } from 'astro:content';
|
|
2
|
+
import { docsLoader } from '@astrojs/starlight/loaders';
|
|
3
|
+
import { docsSchema } from '@astrojs/starlight/schema';
|
|
4
|
+
|
|
5
|
+
export const collections = {
|
|
6
|
+
docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }),
|
|
7
|
+
};
|
|
@@ -10,7 +10,7 @@ Match the symptom to the row, apply the fix, and stop. Do not retry permutations
|
|
|
10
10
|
|
|
11
11
|
| Symptom | Cause | Fix |
|
|
12
12
|
| --- | --- | --- |
|
|
13
|
-
| `SCOPE_INVALID` on deploy | Known platform issue, not your request | Deploy from a terminal with `grid plug <path
|
|
13
|
+
| `SCOPE_INVALID` on deploy | Known platform issue, not your request | Deploy from a terminal with `grid plug <path>`. Do not retry flag or path permutations. If no terminal is available, tell the user it is a known issue that needs the CLI. |
|
|
14
14
|
| `429` anonymous cap reached | Anonymous deploy quota is exhausted | Stop. Do not log in to work around it and do not retry today. Tell the user the cap is reached; they can try later or sign in for a higher limit as a deliberate choice. |
|
|
15
15
|
| `409 EDIT_REJECTED` on re-plug | The target entity is archived or expired | Do not silently create a new entity — that mints a new URL and orphans the shared one. Ask the user before creating a fresh entity. |
|
|
16
16
|
| `401` on an anonymous edit | Missing or stale `owner_token` | Re-plug with the `owner_token` from the last deploy of that entity. Each anonymous edit returns a fresh token — store the new one and use it next time. |
|
package/src/corpus/usage.md
CHANGED
|
@@ -15,7 +15,7 @@ Which one you use depends on the client. Pick your client below.
|
|
|
15
15
|
|
|
16
16
|
- **Node 18+** (for `npx`).
|
|
17
17
|
- **No login needed to try it** — anonymous drop works out of the box. For owned
|
|
18
|
-
drops (into your org), run `
|
|
18
|
+
drops (into your org), run `grid login` once, or use the `login` skill / the
|
|
19
19
|
`grid_login` MCP tool.
|
|
20
20
|
|
|
21
21
|
---
|
|
@@ -115,7 +115,7 @@ response is `status: "building"` with a `poll_url` / entity, NOT a live URL yet.
|
|
|
115
115
|
|
|
116
116
|
Give the user the live app URL — that is the deliverable. To iterate, re-plug
|
|
117
117
|
the SAME entity (`target_entity_id`) so it updates the same URL. Runtime re-plug
|
|
118
|
-
uses the CLI path (`
|
|
118
|
+
uses the CLI path (`grid plug` in the linked folder), per the plug
|
|
119
119
|
description.
|
|
120
120
|
|
|
121
121
|
Keep it honest: async build, local-edition only, credentials injected by the
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: docs-app
|
|
3
|
+
when: multi-page documentation SITE, developer docs portal, knowledge base, help center you'll keep editing — docs with a sidebar, full-text search, and agent-readable llms.txt, built with Astro/Starlight. SEPARATE content files, not one page. For a quick single-page doc baked into one HTML file (instant, works on the hosted MCP), use docs-site instead. For an interactive REST API endpoint reference, use api-docs.
|
|
4
|
+
needs: none
|
|
5
|
+
deploy: static build
|
|
6
|
+
editions: local
|
|
7
|
+
capabilities_note: a built, multi-page static documentation site (Astro Starlight) — sidebar nav, client-side search, and llms.txt / llms-full.txt generated on every build. No infrastructure (no needs:). Because it BUILDS from multiple files, it deploys async and needs the local edition; the hosted MCP cannot build it. Served at the entity root via grid_plug.
|
|
8
|
+
summary: Scaffold an Astro Starlight docs site from the docs-app template, fill in the content, build it, deploy the folder with grid_plug (async → poll to a live URL), then ask the user what visibility they want. llms.txt / llms-full.txt are generated automatically.
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Workflow: docs-app
|
|
12
|
+
|
|
13
|
+
The user wants a **real, multi-page documentation site** they will keep editing —
|
|
14
|
+
a docs portal / knowledge base with a sidebar, search, and agent-readable
|
|
15
|
+
`llms.txt`. That is a **built static site** (Astro Starlight), not a single page.
|
|
16
|
+
|
|
17
|
+
Choose the right archetype first:
|
|
18
|
+
- **Quick, single-page doc**, or you're on the **hosted MCP** (Claude Web) → use
|
|
19
|
+
`docs-site` (one self-contained HTML file, instant inspiration, any edition).
|
|
20
|
+
- **Interactive REST API endpoint reference** → use `api-docs`.
|
|
21
|
+
- **Multi-page site you'll maintain (sidebar + search + llms.txt)** → `docs-app`,
|
|
22
|
+
this workflow.
|
|
23
|
+
|
|
24
|
+
Be honest that a `docs-app` deploy is a build (async, not instant like a single
|
|
25
|
+
HTML drop) and that it needs the local edition.
|
|
26
|
+
|
|
27
|
+
## 1. Edition check FIRST (hard gate)
|
|
28
|
+
|
|
29
|
+
A docs-app is built (`npm run build`) from multiple files, so it requires the
|
|
30
|
+
**local edition** (Claude Desktop / Claude Code) or the CLI — the grid folder-plugs
|
|
31
|
+
and builds your project.
|
|
32
|
+
|
|
33
|
+
- **Hosted edition (Claude Web / hosted MCP):** you CANNOT build a multi-file
|
|
34
|
+
site. Tell the user plainly: "A multi-page docs site needs the local edition
|
|
35
|
+
(Claude Desktop/Code) or the CloudGrid CLI; the hosted edition can only publish
|
|
36
|
+
a single page — I can make you a one-page `docs-site` instead." Offer the
|
|
37
|
+
`docs-site` fallback; do not try to build here.
|
|
38
|
+
- **Local edition:** continue.
|
|
39
|
+
|
|
40
|
+
## 2. Auth + grid
|
|
41
|
+
|
|
42
|
+
1. Ensure signed in: `grid_login_status`; if not, `grid_login`.
|
|
43
|
+
2. A grid is required. Respect the grid picker: if the user has more than one
|
|
44
|
+
grid, ask which to use; do not assume a target.
|
|
45
|
+
|
|
46
|
+
## 3. Scaffold
|
|
47
|
+
|
|
48
|
+
`grid_init` an app `<name>`. `init` creates the entity + `.cloudgrid/link.json`
|
|
49
|
+
and writes a `cloudgrid.yaml`. Then fetch the template:
|
|
50
|
+
`grid_fetch("template", "docs-app")` — a minimal Astro Starlight project:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
package.json Astro + Starlight + starlight-llms-txt
|
|
54
|
+
astro.config.mjs site config, sidebar, the llms.txt plugin
|
|
55
|
+
tsconfig.json
|
|
56
|
+
cloudgrid.yaml static + build block, served at the entity root
|
|
57
|
+
src/content.config.ts
|
|
58
|
+
src/content/docs/index.mdx + guides/ + reference/
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Write those files into the linked folder (keep the project at the folder root —
|
|
62
|
+
this is a static build, so unlike a `node`/`nextjs` service the project is NOT
|
|
63
|
+
nested under `services/<name>/`).
|
|
64
|
+
|
|
65
|
+
## 4. Fill in the content
|
|
66
|
+
|
|
67
|
+
- Set `title`, `description`, and the `starlightLlmsTxt({ projectName, description })`
|
|
68
|
+
values in `astro.config.mjs` to the user's project.
|
|
69
|
+
- Write the actual pages under `src/content/docs/` (Markdown/MDX, one file per
|
|
70
|
+
page) and list them in the `sidebar` array in `astro.config.mjs`.
|
|
71
|
+
- Keep internal links root-relative (`/guides/getting-started/`). The site is
|
|
72
|
+
served at the entity **root**, so do NOT set a `base`.
|
|
73
|
+
- Do not add external CDN scripts, fonts, or stylesheets.
|
|
74
|
+
|
|
75
|
+
## 5. cloudgrid.yaml
|
|
76
|
+
|
|
77
|
+
The template already declares the right shape — a single `static` service with a
|
|
78
|
+
build step, served at the root:
|
|
79
|
+
|
|
80
|
+
```yaml
|
|
81
|
+
name: my-docs
|
|
82
|
+
services:
|
|
83
|
+
site:
|
|
84
|
+
type: static
|
|
85
|
+
path: /
|
|
86
|
+
node_version: "22"
|
|
87
|
+
source:
|
|
88
|
+
path: . # project is at the folder root, not under services/site/
|
|
89
|
+
build:
|
|
90
|
+
command: "npm run build"
|
|
91
|
+
output: "dist"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
`source.path: .` is REQUIRED for this root-level build — without it the platform
|
|
95
|
+
looks for `services/site/` and fails with "Service directory not found". No
|
|
96
|
+
`needs:` — a docs site has no infrastructure. Never author an active `needs:` and
|
|
97
|
+
`requires:` together (the validator rejects the combo).
|
|
98
|
+
|
|
99
|
+
## 6. Build + deploy (async)
|
|
100
|
+
|
|
101
|
+
Deploy the folder with `grid_plug`. The platform (Cloud Build) runs `npm run
|
|
102
|
+
build` for you and serves the `dist/` output — you do NOT need to build first. A build deploy is **ASYNC**: the first response is
|
|
103
|
+
`status: "building"` with a `poll_url` / entity, NOT a live URL yet.
|
|
104
|
+
- Poll `grid_status` (or the returned poll_url) until the entity is live.
|
|
105
|
+
- Surface a liveness signal while it builds — never a bare silent wait.
|
|
106
|
+
- Only once it is live, return the deployed URL.
|
|
107
|
+
|
|
108
|
+
## 7. Return the live URL, point at llms.txt, and ASK visibility
|
|
109
|
+
|
|
110
|
+
- Give the user the live docs URL — that is the deliverable.
|
|
111
|
+
- Point out the agent-readable docs: `<url>/llms.txt` (index) and
|
|
112
|
+
`<url>/llms-full.txt` (full content), generated automatically.
|
|
113
|
+
- This is a NEW deploy, so ASK the user who should be able to open it (private /
|
|
114
|
+
a space / your grid / anyone with the link / anyone signed in) and set their
|
|
115
|
+
choice with `grid_visibility`. Do not pick the visibility for them.
|
|
116
|
+
|
|
117
|
+
To iterate, edit the content and re-plug the SAME entity (`target_entity_id`) so
|
|
118
|
+
it updates the same URL.
|
|
119
|
+
|
|
120
|
+
Keep it honest: multi-file build, async deploy, local-edition only.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: docs-site
|
|
3
|
-
when:
|
|
3
|
+
when: single-page docs, a quick guide/manual/README-as-a-page, small knowledge base (static, content baked into ONE HTML file). For a MULTI-PAGE site you'll keep editing (sidebar + full-text search + llms.txt, built with Starlight), use docs-app instead. For an interactive API endpoint reference, use api-docs instead.
|
|
4
4
|
needs: none
|
|
5
5
|
deploy: inspiration
|
|
6
6
|
editions: all
|
package/src/index.js
CHANGED
|
@@ -15,6 +15,9 @@ import {
|
|
|
15
15
|
writeCredentials,
|
|
16
16
|
credentialsPath,
|
|
17
17
|
} from "./auth.js";
|
|
18
|
+
import { randomUUID } from "node:crypto";
|
|
19
|
+
import { createSessionLogger } from "./session-logger.js";
|
|
20
|
+
import { createSink } from "./log-sink.js";
|
|
18
21
|
|
|
19
22
|
const { version } = JSON.parse(readFileSync(new URL("../package.json", import.meta.url)));
|
|
20
23
|
|
|
@@ -28,6 +31,18 @@ const ctx = {
|
|
|
28
31
|
savedLocationNote: () => `Credentials saved to ${credentialsPath()}.`,
|
|
29
32
|
};
|
|
30
33
|
|
|
34
|
+
// QA session log (dark by default: no CLOUDGRID_QA_SLACK_WEBHOOK → null → no-op).
|
|
35
|
+
// The stdio process IS the session. user_request is forwarded by Claude Code via
|
|
36
|
+
// CLOUDGRID_USER_REQUEST when present.
|
|
37
|
+
ctx.sessionId = `cli-${randomUUID()}`;
|
|
38
|
+
ctx.logger = createSessionLogger({
|
|
39
|
+
transport: "stdio",
|
|
40
|
+
sessionId: ctx.sessionId,
|
|
41
|
+
sink: createSink(process.env),
|
|
42
|
+
ctx,
|
|
43
|
+
userRequest: process.env.CLOUDGRID_USER_REQUEST || null,
|
|
44
|
+
});
|
|
45
|
+
|
|
31
46
|
const server = new McpServer({ name: "cloudgrid-mcp", version });
|
|
32
47
|
registerTools(server, ctx);
|
|
33
48
|
|
|
@@ -45,3 +60,17 @@ server.server.oninitialized = () => {
|
|
|
45
60
|
|
|
46
61
|
const transport = new StdioServerTransport();
|
|
47
62
|
await server.connect(transport);
|
|
63
|
+
|
|
64
|
+
// Flush the QA log once on shutdown if nothing triggered a flush during the
|
|
65
|
+
// session (abandoned / build-only session). Best-effort — a hard kill may cut
|
|
66
|
+
// delivery short; that is acceptable for QA. Guarded so it never crashes exit.
|
|
67
|
+
let shuttingDown = false;
|
|
68
|
+
async function flushAndExit(code) {
|
|
69
|
+
if (shuttingDown) return;
|
|
70
|
+
shuttingDown = true;
|
|
71
|
+
try { await ctx.logger?.flush("abandoned"); } catch { /* never */ }
|
|
72
|
+
process.exit(code);
|
|
73
|
+
}
|
|
74
|
+
process.on("SIGINT", () => flushAndExit(0));
|
|
75
|
+
process.on("SIGTERM", () => flushAndExit(0));
|
|
76
|
+
process.on("beforeExit", () => { ctx.logger?.flush("abandoned").catch(() => {}); });
|
package/src/log-sink.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// src/log-sink.js
|
|
2
|
+
// Pluggable delivery for the QA session log. Default sink posts to a Slack
|
|
3
|
+
// incoming webhook. Dark by default: createSink returns null when the webhook
|
|
4
|
+
// env var is unset, so the logger factory returns null and capture is a no-op.
|
|
5
|
+
//
|
|
6
|
+
// NOTE: Slack incoming webhooks cannot upload file attachments — only a JSON
|
|
7
|
+
// message body. We post the summary + the full log inside a fenced code block.
|
|
8
|
+
// True file attachment (files.upload) needs a bot token and is deferred.
|
|
9
|
+
const SLACK_TEXT_LIMIT = 38000; // headroom under Slack's ~40k message cap
|
|
10
|
+
|
|
11
|
+
export class SlackWebhookSink {
|
|
12
|
+
constructor(url, { fetchImpl } = {}) {
|
|
13
|
+
this.url = url;
|
|
14
|
+
this.fetchImpl = fetchImpl || globalThis.fetch;
|
|
15
|
+
}
|
|
16
|
+
async send({ filename, summary, text }) {
|
|
17
|
+
try {
|
|
18
|
+
const body = String(text || "");
|
|
19
|
+
const clipped = body.length > SLACK_TEXT_LIMIT
|
|
20
|
+
? body.slice(0, SLACK_TEXT_LIMIT) + "\n…(truncated)"
|
|
21
|
+
: body;
|
|
22
|
+
const message = `*${filename}* — ${summary}\n\`\`\`\n${clipped}\n\`\`\``;
|
|
23
|
+
// Bound the POST so a hung webhook host can't stall flushAndExit on
|
|
24
|
+
// SIGINT/SIGTERM. Abort after 5s; clear the timer once the fetch settles.
|
|
25
|
+
const ac = new AbortController();
|
|
26
|
+
const timer = setTimeout(() => ac.abort(), 5000);
|
|
27
|
+
try {
|
|
28
|
+
await this.fetchImpl(this.url, {
|
|
29
|
+
method: "POST",
|
|
30
|
+
headers: { "content-type": "application/json" },
|
|
31
|
+
body: JSON.stringify({ text: message }),
|
|
32
|
+
signal: ac.signal,
|
|
33
|
+
});
|
|
34
|
+
} finally {
|
|
35
|
+
clearTimeout(timer);
|
|
36
|
+
}
|
|
37
|
+
} catch { /* delivery is best-effort; never throws */ }
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function createSink(env = process.env) {
|
|
42
|
+
const url = env.CLOUDGRID_QA_SLACK_WEBHOOK;
|
|
43
|
+
if (!url) return null;
|
|
44
|
+
return new SlackWebhookSink(url);
|
|
45
|
+
}
|