@kigo-dev/sindri 0.1.0
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 +93 -0
- package/dist/index.js +36899 -0
- package/manifest.json +48 -0
- package/package.json +44 -0
package/README.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# @kigo-dev/sindri — the Sindri connector
|
|
2
|
+
|
|
3
|
+
An MCP server (stdio) that turns a product manager's Claude into a builder of Kigo internal
|
|
4
|
+
apps. Claude edits the app files on the PM's computer with the PM's own plan; this connector
|
|
5
|
+
does everything around that: installs the toolchain, runs the app locally with an embedded
|
|
6
|
+
database, publishes it at `https://<name>.sindri.kigo.dev` and keeps versions.
|
|
7
|
+
|
|
8
|
+
Everything the PM reads (the `summary` of every tool result, error messages) is Spanish; tool
|
|
9
|
+
names, parameters and this document are English. The contract lives in
|
|
10
|
+
`docs/conector-v4-contratos.md`, section D.
|
|
11
|
+
|
|
12
|
+
## Tools
|
|
13
|
+
|
|
14
|
+
| Tool | Arguments | What it does |
|
|
15
|
+
|---|---|---|
|
|
16
|
+
| `setup` | – | Installs Node LTS and pnpm under the user's home with [fnm](https://github.com/Schniz/fnm) (no sudo), creates `~/Sindri`. Reuses an existing Node ≥ 20 + pnpm. Idempotent. |
|
|
17
|
+
| `login` | – | OAuth 2.0 authorization code + PKCE (S256) with a loopback redirect, Vercel-CLI style: listens on `http://127.0.0.1:<random>/callback`, opens Identity's `authorization_endpoint` (client `sindri-connector`, public, `audience=sindri-api`), validates `state`, exchanges the code with the verifier, shows "Listo, ya entraste a Sindri" and closes. Waits up to 5 minutes. Device flow only as a fallback when no browser can be opened and discovery advertises the device grant. Tokens go to the macOS keychain (service `sindri`) or `~/.sindri/credentials.json` (0600). Refreshes silently. |
|
|
18
|
+
| `create_app` | `name`, `description` | `POST /v1/apps`, downloads the personalised template into `~/Sindri/<name>`, `pnpm install`, migrates and seeds the local database. |
|
|
19
|
+
| `preview` | `app` | `pnpm db:migrate` (and seed on first run), then `pnpm dev --port <free>` detached with `KIGO_ENV=local` (PGlite), waits for `/healthz`, opens the browser. Reuses a healthy preview. |
|
|
20
|
+
| `publish` | `app`, `message` | `tsc --noEmit`, checks the running preview, tars the tree (without `node_modules`, `.next`, `.sindri`, `.env*`, `dist`, `.turbo`), `POST /v1/apps/<app>/publish`. On failure the published version does not change. |
|
|
21
|
+
| `status` | `app` | Address and last version from the API, plus whether the local folder exists and has unpublished edits (tree hash vs `.sindri/last-published.json`). |
|
|
22
|
+
| `list_apps` | – | The PM's apps, with local folder state. |
|
|
23
|
+
| `versions` | `app` | Published versions, most recent first. |
|
|
24
|
+
| `rollback` | `app`, `version` | `POST rollback`, then downloads that version's archive and replaces the local tree (keeps `node_modules`, `.sindri`, `.env.local`). Stops the preview first: PGlite allows one process per data dir. |
|
|
25
|
+
| `share` | `app` | The Slack line. |
|
|
26
|
+
|
|
27
|
+
Every result is `{ ok, summary, ...data }`. `needs_login: true` / `needs_setup: true` tell Claude
|
|
28
|
+
which tool to run first. The server also ships `instructions` describing how to talk to the PM.
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
**Claude Desktop (recommended for PMs):** double-click the `sindri.mcpb` extension (built from
|
|
33
|
+
`manifest.json` with `npx @anthropic-ai/mcpb pack`), accept, done. The first conversation runs
|
|
34
|
+
`setup` and `login`.
|
|
35
|
+
|
|
36
|
+
**Claude Code:**
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
claude mcp add sindri -- npx -y @kigo-dev/sindri
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Manual check without an MCP client:**
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
npx @kigo-dev/sindri status '{"app":"visitas"}'
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Configuration
|
|
49
|
+
|
|
50
|
+
| Variable | Default | Meaning |
|
|
51
|
+
|---|---|---|
|
|
52
|
+
| `SINDRI_API_URL` | `https://api.sindri.kigo.dev` | Sindri API |
|
|
53
|
+
| `SINDRI_ISSUER` | `https://id.kigo.dev` | Identity issuer (OpenID discovery) |
|
|
54
|
+
| `SINDRI_CLIENT_ID` | `sindri-connector` | Public OAuth client |
|
|
55
|
+
| `SINDRI_AUDIENCE` | `sindri-api` | Audience requested for the access token |
|
|
56
|
+
| `SINDRI_HOME` | `~/Sindri` | Where app folders live |
|
|
57
|
+
| `SINDRI_STATE_DIR` | `~/.sindri` | Credentials fallback, preview registry |
|
|
58
|
+
| `SINDRI_CREDENTIAL_STORE` | keychain on macOS, file elsewhere | `file` forces the JSON file |
|
|
59
|
+
| `SINDRI_FNM_DIR` | `~/.local/share/fnm` | Where `setup` installs Node |
|
|
60
|
+
| `SINDRI_OPENER` | `open` / `xdg-open` | Browser opener; empty disables |
|
|
61
|
+
|
|
62
|
+
## Development
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
pnpm install --ignore-workspace
|
|
66
|
+
pnpm typecheck && pnpm test && pnpm build
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Tests run against a fake Identity issuer (`/authorize` redirecting to the loopback, `/token`
|
|
70
|
+
checking the PKCE verifier, plus the device endpoints for the fallback), a fake Sindri API and
|
|
71
|
+
stub `node`/`pnpm` binaries under a temporary HOME; nothing is installed on the developer's machine.
|
|
72
|
+
|
|
73
|
+
Identity must register `sindri-connector` as a PUBLIC client with `redirect_uri_globs`
|
|
74
|
+
`http://127.0.0.1:*/callback` (loopback ports are random, RFC 8252 §7.3), PKCE required, grant
|
|
75
|
+
types `authorization_code` and `refresh_token`.
|
|
76
|
+
|
|
77
|
+
## Local layout
|
|
78
|
+
|
|
79
|
+
`~/Sindri/<name>/` is the sparse root of the kigo-sindri-apps monorepo exactly as Sindri's
|
|
80
|
+
archive ships it (`package.json`, `pnpm-workspace.yaml`, `pnpm-lock.yaml`, `tsconfig.base.json`,
|
|
81
|
+
`packages/`, `apps/<owner>/<name>`), because the app uses `catalog:` and `workspace:` specifiers
|
|
82
|
+
and cannot install standalone. `pnpm install` runs at that root; `preview`, `db:migrate`,
|
|
83
|
+
`db:seed`, `tsc`, the tree hash, `.env.local`, `.sindri/last-published.json` and the `publish`
|
|
84
|
+
tarball (paths relative to the app) all live at `apps/<owner>/<name>`. `replaceTree` swaps the
|
|
85
|
+
whole root on `create_app`/`rollback` but keeps every `node_modules` and the app's `.sindri/`
|
|
86
|
+
and `.env*`. The owner is the single folder under `apps/`, else the `owner` from `GET /v1/me`
|
|
87
|
+
(cached in `~/.sindri/me.json`).
|
|
88
|
+
|
|
89
|
+
## Local database
|
|
90
|
+
|
|
91
|
+
The template runs on PGlite when `KIGO_ENV=local` and no `DATABASE_URL` is set; data lives in
|
|
92
|
+
`<app>/.sindri/pglite/`. PGlite is single-process: the connector never runs migrations while a
|
|
93
|
+
preview is up, and stops the preview before a rollback replaces the tree.
|