@kindgi/sdk 0.0.0-bootstrap.0 → 0.1.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/LICENSE +201 -0
- package/README.md +187 -1
- package/dist/build.d.ts +10 -0
- package/dist/build.d.ts.map +1 -0
- package/dist/build.js +11 -0
- package/dist/build.js.map +1 -0
- package/dist/client.d.ts +33 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +55 -0
- package/dist/client.js.map +1 -0
- package/dist/define.d.ts +25 -0
- package/dist/define.d.ts.map +1 -0
- package/dist/define.js +37 -0
- package/dist/define.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime-config.d.ts +53 -0
- package/dist/runtime-config.d.ts.map +1 -0
- package/dist/runtime-config.js +114 -0
- package/dist/runtime-config.js.map +1 -0
- package/dist/types.d.ts +16 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/dist/webhooks.d.ts +15 -0
- package/dist/webhooks.d.ts.map +1 -0
- package/dist/webhooks.js +16 -0
- package/dist/webhooks.js.map +1 -0
- package/package.json +88 -4
- package/skills/kindgi-authoring-agents/SKILL.md +252 -0
- package/skills/kindgi-authoring-flows/SKILL.md +302 -0
- package/skills/kindgi-authoring-guardrails/SKILL.md +297 -0
- package/skills/kindgi-authoring-mcp-servers/SKILL.md +289 -0
- package/skills/kindgi-authoring-providers/SKILL.md +705 -0
- package/skills/kindgi-authoring-tools/SKILL.md +298 -0
- package/skills/kindgi-framework-feedback/SKILL.md +211 -0
- package/skills/kindgi-getting-started/SKILL.md +189 -0
- package/skills/kindgi-python-authoring-agents/SKILL.md +205 -0
- package/skills/kindgi-python-authoring-flows/SKILL.md +325 -0
- package/skills/kindgi-python-authoring-guardrails/SKILL.md +176 -0
- package/skills/kindgi-python-authoring-tools/SKILL.md +305 -0
- package/skills/kindgi-python-getting-started/SKILL.md +242 -0
- package/src/build.ts +18 -0
- package/src/client.ts +177 -0
- package/src/define.ts +75 -0
- package/src/index.ts +20 -0
- package/src/runtime-config.ts +180 -0
- package/src/types.ts +86 -0
- package/src/webhooks.ts +34 -0
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kindgi-authoring-mcp-servers
|
|
3
|
+
description: >
|
|
4
|
+
Wire an MCP server into a Kindgi pack so the coding agent (Claude Code,
|
|
5
|
+
Cursor, VS Code, Windsurf, …) can discover a live external resource
|
|
6
|
+
through tools instead of asking the user to paste schemas or values.
|
|
7
|
+
Uses `kindgi secrets set` for the credential (interactive, no-echo) and
|
|
8
|
+
`kindgi mcp add <preset>` to write `.mcp.json` at the pack root. The
|
|
9
|
+
launcher (`kindgi mcp-launch`) spawns the actual MCP server as a
|
|
10
|
+
subprocess with the secret injected into its env — never onto the
|
|
11
|
+
model's transcript. Load this when the user says "I have a Postgres
|
|
12
|
+
URL, can you look at the schema", "connect to my database", "wire
|
|
13
|
+
MCP", "add a Postgres MCP", "let CC query my DB", "I don't want to
|
|
14
|
+
paste my table shape", or when the model is about to ask the user to
|
|
15
|
+
paste external schema/data that Kindgi could discover through MCP.
|
|
16
|
+
Credential storage is covered by kindgi-authoring-providers's
|
|
17
|
+
`kindgi secrets set` flow.
|
|
18
|
+
type: core
|
|
19
|
+
library: "@kindgi/sdk"
|
|
20
|
+
version: "0.3.0"
|
|
21
|
+
sdk_version: "0.0.0"
|
|
22
|
+
pack_languages: [node, python]
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
# Wiring an MCP server for a Kindgi pack
|
|
26
|
+
|
|
27
|
+
> **Running `kindgi`:** in a Node project the CLI is a devDependency
|
|
28
|
+
> (`@kindgi/cli`), not a global command. Run it through the project's
|
|
29
|
+
> package manager — `pnpm exec kindgi …`, `npx --no kindgi …` (npm),
|
|
30
|
+
> `yarn kindgi …` or `bun run kindgi …`. A Python pack (`[tool.kindgi]` in
|
|
31
|
+
> `pyproject.toml`) has no Node project: run the `kindgi` on `PATH`.
|
|
32
|
+
> Commands below are written `kindgi …` for brevity.
|
|
33
|
+
|
|
34
|
+
If the user has an external resource (Postgres DB, GitHub org, Notion
|
|
35
|
+
workspace, …) that would be useful to a coding agent, **wire an MCP
|
|
36
|
+
server** rather than asking the user to paste values. Kindgi keeps the
|
|
37
|
+
credential out of the model's transcript by injecting it into the
|
|
38
|
+
subprocess's environment; the model only sees the tools the MCP server
|
|
39
|
+
exposes.
|
|
40
|
+
|
|
41
|
+
## When to reach for this
|
|
42
|
+
|
|
43
|
+
Reach for MCP when the user hands you a live external resource by
|
|
44
|
+
reference (URL, host + credential, workspace id). Signals from the
|
|
45
|
+
user:
|
|
46
|
+
- "I have a Postgres database at $URL"
|
|
47
|
+
- "Connect to my Notion workspace at $TOKEN"
|
|
48
|
+
- "Let CC look at the schema of my DB"
|
|
49
|
+
- "Don't paste it, just query it"
|
|
50
|
+
|
|
51
|
+
**Do NOT reach for MCP when:**
|
|
52
|
+
- The resource is a static file the user has locally (just Read it).
|
|
53
|
+
- The resource is best-inspected once by a human (a one-shot answer, no
|
|
54
|
+
agent tools needed).
|
|
55
|
+
- The user is in a client that hasn't loaded `.mcp.json` yet — they'll
|
|
56
|
+
need to restart their MCP client after `kindgi mcp add` (see gotcha
|
|
57
|
+
#2 below).
|
|
58
|
+
|
|
59
|
+
## Mental model
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
Kindgi's SecretBinding .mcp.json (pack root) launcher subprocess MCP server subprocess
|
|
63
|
+
───────────────────── ──────────────────── ────────────────── ────────────────────
|
|
64
|
+
MY_DB_URL=… → { "command": "pnpm", → reads .env + → spawns child with
|
|
65
|
+
(.env / .env.local, or "args": ["exec","kindgi", .env.local (the DATABASE_URI in env,
|
|
66
|
+
`kindgi secrets set`) "mcp-launch", "--", …] } pack env files), stdio piped to CC
|
|
67
|
+
│ substitutes secret ▲ │
|
|
68
|
+
│ into child env │ ▼
|
|
69
|
+
▼ │ MCP protocol (stdio)
|
|
70
|
+
Claude Code / Cursor spawns │ ▲ │
|
|
71
|
+
`kindgi mcp-launch …` at │ │ ▼
|
|
72
|
+
startup ─────────────────────────────┘ ┌─────────────────┐
|
|
73
|
+
│ Claude Code │
|
|
74
|
+
│ (or Cursor…) │
|
|
75
|
+
└─────────────────┘
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Three moving parts:
|
|
79
|
+
|
|
80
|
+
1. **The secret on disk** — for `local`, the project's env files at the
|
|
81
|
+
pack root (`.env`, then `.env.local`; `dev.envFiles` to change);
|
|
82
|
+
other environments use `.env.<envName>`. Add it by hand or with
|
|
83
|
+
`kindgi secrets set` (interactive no-echo prompt; never the value on
|
|
84
|
+
argv), which writes `.env.local`. See `kindgi-authoring-providers`
|
|
85
|
+
for the same flow used for LLM API keys.
|
|
86
|
+
2. **`.mcp.json` at the pack root** — Kindgi writes this via
|
|
87
|
+
`kindgi mcp add`. Every entry runs the project's own `kindgi
|
|
88
|
+
mcp-launch -- <launcher-flags>...` through its package manager
|
|
89
|
+
(`"command": "pnpm", "args": ["exec", "kindgi", "mcp-launch", …]`;
|
|
90
|
+
npm: `npx --no kindgi …`) — never a global `kindgi`, never a
|
|
91
|
+
download. A Python pack has no Node project, so its entries run the
|
|
92
|
+
`kindgi` on `PATH` (`"command": "kindgi", "args": ["mcp-launch", …]`).
|
|
93
|
+
The file is safe to commit — it references secrets by NAME, not
|
|
94
|
+
value.
|
|
95
|
+
3. **The launcher** — `kindgi mcp-launch` is what the coding agent
|
|
96
|
+
actually spawns. It reads the referenced secret from the pack env files,
|
|
97
|
+
injects it into the child MCP server's env, and pipes stdio through.
|
|
98
|
+
|
|
99
|
+
## Path A — Postgres
|
|
100
|
+
|
|
101
|
+
Best-worn path. Uses `crystaldba/postgres-mcp` via Docker with
|
|
102
|
+
read-only access mode by default.
|
|
103
|
+
|
|
104
|
+
**Step 1 — set the DB URL** (interactive, no-echo):
|
|
105
|
+
|
|
106
|
+
```sh
|
|
107
|
+
kindgi secrets set MY_DB_URL --env=local --scope=tenant
|
|
108
|
+
# paste postgres://user:pass@host:port/db, press enter
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
For pipelines/CI: `pbpaste | kindgi secrets set … --from-stdin`, or
|
|
112
|
+
`--from-file=<path>` on a mode-0600 file. Never pass the value on argv.
|
|
113
|
+
|
|
114
|
+
**Step 2 — wire the MCP server:**
|
|
115
|
+
|
|
116
|
+
```sh
|
|
117
|
+
kindgi mcp add postgres --secret=MY_DB_URL
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Writes `.mcp.json` at the pack root (or merges into an existing one).
|
|
121
|
+
The server name defaults to `my_db` (derived from the secret
|
|
122
|
+
name — see "Server naming" below). Override with `--server-name=<label>`.
|
|
123
|
+
|
|
124
|
+
**Step 3 — restart your MCP client.** MCP servers are loaded at client
|
|
125
|
+
startup — a fresh `.mcp.json` doesn't take effect mid-session:
|
|
126
|
+
- **Claude Code:** exit + `claude` again in the same pack dir
|
|
127
|
+
- **Cursor:** ⌘⇧P → "Restart Extension Host" (or restart the app)
|
|
128
|
+
- **Claude Desktop:** quit + reopen
|
|
129
|
+
- **Windsurf:** Command Palette → "Restart Windsurf"
|
|
130
|
+
|
|
131
|
+
**Step 4 — use it.** Tools like `execute_sql`, `list_tables`,
|
|
132
|
+
`analyze_index_health` now appear. Ask the agent things like "what
|
|
133
|
+
tables are in this schema?" or "what's the shape of the customers
|
|
134
|
+
table?" or "how many rows are in orders where created_at > 2024?".
|
|
135
|
+
|
|
136
|
+
## Path B — Multiple servers in the same pack
|
|
137
|
+
|
|
138
|
+
Two connections against different DBs? Two `mcp add` invocations,
|
|
139
|
+
each with its own `--secret` and `--server-name`:
|
|
140
|
+
|
|
141
|
+
```sh
|
|
142
|
+
kindgi secrets set MY_DB_URL --env=local --scope=tenant
|
|
143
|
+
kindgi secrets set ANALYTICS_DB_URL --env=local --scope=tenant
|
|
144
|
+
|
|
145
|
+
kindgi mcp add postgres --secret=MY_DB_URL --server-name=my_db
|
|
146
|
+
kindgi mcp add postgres --secret=ANALYTICS_DB_URL --server-name=analytics_db
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
`.mcp.json` gets two entries. The agent picks the right one by name
|
|
150
|
+
when it invokes a tool (e.g. `my_db.execute_sql`).
|
|
151
|
+
|
|
152
|
+
## Server naming
|
|
153
|
+
|
|
154
|
+
`--server-name` defaults are derived from the secret name:
|
|
155
|
+
|
|
156
|
+
| Secret name | Default server name |
|
|
157
|
+
|---|---|
|
|
158
|
+
| `MY_DB_URL` | `my_db` |
|
|
159
|
+
| `ANALYTICS_DB_URL` | `analytics_db` |
|
|
160
|
+
| `ANTHROPIC_API_KEY` | `anthropic_api` |
|
|
161
|
+
| `GITHUB_PAT` | `github` |
|
|
162
|
+
| `DB_PASSWORD` | `db` |
|
|
163
|
+
|
|
164
|
+
The suffix-stripping (`_url` / `_uri` / `_key` / `_token` / `_pat` /
|
|
165
|
+
`_secret` / `_password`) is intentional — the server name should
|
|
166
|
+
describe the *resource*, not the *credential shape*. Override with
|
|
167
|
+
`--server-name=<label>` when the default reads wrong.
|
|
168
|
+
|
|
169
|
+
## Path C — Non-Claude-Code clients
|
|
170
|
+
|
|
171
|
+
`.mcp.json` at the pack root is what Claude Code reads natively. Other
|
|
172
|
+
clients read from their own paths (`.cursor/mcp.json`, `.vscode/mcp.json`,
|
|
173
|
+
Claude Desktop's system-wide config). To bridge:
|
|
174
|
+
|
|
175
|
+
1. Establish a symlink from the client's expected path to `.mcp.json`:
|
|
176
|
+
```sh
|
|
177
|
+
mkdir -p .cursor && ln -sfn ../.mcp.json .cursor/mcp.json
|
|
178
|
+
```
|
|
179
|
+
2. Restart the client.
|
|
180
|
+
|
|
181
|
+
Symlinks work because the FILE CONTENTS are portable across every MCP
|
|
182
|
+
client — the `mcpServers` block has the same shape everywhere. Only
|
|
183
|
+
the file LOCATION differs. Edits to `.mcp.json` flow through
|
|
184
|
+
automatically via the symlink; no re-sync needed.
|
|
185
|
+
|
|
186
|
+
Windows users without dev-drive symlinks: `cp .mcp.json .cursor/mcp.json`,
|
|
187
|
+
and re-copy after every `kindgi mcp` edit.
|
|
188
|
+
|
|
189
|
+
## Verifying end-to-end
|
|
190
|
+
|
|
191
|
+
```sh
|
|
192
|
+
# 1. Check the secret exists
|
|
193
|
+
kindgi secrets list --env=local --scope=tenant
|
|
194
|
+
|
|
195
|
+
# 2. Check .mcp.json
|
|
196
|
+
kindgi mcp list
|
|
197
|
+
|
|
198
|
+
# 3. Check available presets
|
|
199
|
+
kindgi mcp presets
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
`kindgi mcp list` prints the configured servers with their launcher
|
|
203
|
+
argv shape. `kindgi mcp presets` shows what presets are available and
|
|
204
|
+
their audit status. If the postgres preset audit says
|
|
205
|
+
`urlLeakInErrors: "pending"`, that's a known unresolved item — see
|
|
206
|
+
gotcha #4.
|
|
207
|
+
|
|
208
|
+
## Common mistakes
|
|
209
|
+
|
|
210
|
+
1. **Reading `.mcp.json` mid-session and asking about it.** `.mcp.json`
|
|
211
|
+
references secrets by NAME (e.g. `secret:MY_DB_URL@local:tenant`),
|
|
212
|
+
not by value. Safe to Read + describe to the user. **Do NOT** run
|
|
213
|
+
`cat .env`, `env | grep`, or Read `.env` / `.env.local` — those return
|
|
214
|
+
the raw URL, which enters your transcript, gets sent to the model
|
|
215
|
+
provider on every subsequent turn, and can be exfiltrated via
|
|
216
|
+
prompt injection. Once a secret is in a model's context, it's a
|
|
217
|
+
rotation event, not a "clean up the log" event.
|
|
218
|
+
|
|
219
|
+
2. **Expecting the new server to activate without a restart.** MCP
|
|
220
|
+
servers are loaded at client startup. `kindgi mcp add` writes the
|
|
221
|
+
config file; the CLIENT doesn't re-scan it until a restart. Tell
|
|
222
|
+
the user to restart their client after `mcp add`, and don't call
|
|
223
|
+
MCP tools before that restart happens in your current session.
|
|
224
|
+
|
|
225
|
+
3. **`--env` / `--scope` mismatch between `secrets set` and `mcp add`.**
|
|
226
|
+
Both flags need to agree — the launcher looks up the secret using
|
|
227
|
+
whatever `--env` + `--scope` you passed to `mcp add`. Default is
|
|
228
|
+
`--env=local --scope=tenant`; match this on both commands.
|
|
229
|
+
|
|
230
|
+
4. **Trusting a preset's audit metadata that says `pending`.** Every
|
|
231
|
+
preset carries `audit.urlLeakInErrors`. Only `"verified-safe"` means
|
|
232
|
+
someone has confirmed the wrapped MCP server doesn't echo the
|
|
233
|
+
secret in its error/debug output. `"pending"` means the audit
|
|
234
|
+
hasn't run — the server may or may not leak. When you see a
|
|
235
|
+
`pending` preset in a session that handles real credentials, tell
|
|
236
|
+
the user: "this preset works but its URL-echo safety isn't
|
|
237
|
+
verified for this version; watch tool error messages for the raw
|
|
238
|
+
URL, and file feedback if you see one."
|
|
239
|
+
|
|
240
|
+
5. **Trying to use MCP against a `localhost` DB from Docker on Mac
|
|
241
|
+
without the host-remap.** Docker containers on Mac can't reach the
|
|
242
|
+
host's `localhost`. The `postgres` preset carries `hostRemap:
|
|
243
|
+
"docker-desktop"`, which the launcher applies automatically — it
|
|
244
|
+
rewrites `@localhost` / `@127.0.0.1` in the resolved URL to
|
|
245
|
+
`@host.docker.internal` before injecting into the container's env.
|
|
246
|
+
If you author a preset with a Docker runtime + a localhost
|
|
247
|
+
consumer, include `"hostRemap": "docker-desktop"` in the preset JSON.
|
|
248
|
+
|
|
249
|
+
6. **`kindgi mcp add` fails with "Secret X not in .env, .env.local".** The
|
|
250
|
+
secret hasn't been stored yet. Run `kindgi secrets set X --env=local
|
|
251
|
+
--scope=tenant` first. The error message includes this fix pointer.
|
|
252
|
+
|
|
253
|
+
## Security discipline
|
|
254
|
+
|
|
255
|
+
The invariants this skill inherits — every bullet here is enforced by
|
|
256
|
+
you, the coding agent, in the session where MCP is wired:
|
|
257
|
+
|
|
258
|
+
- **Never Read `.env`, `.env.local` or `.env.<envName>` files.** Their contents are the raw
|
|
259
|
+
secret values. Reading them puts the secret in your tool result and
|
|
260
|
+
from there in every subsequent turn's context sent to the model
|
|
261
|
+
provider.
|
|
262
|
+
- **Never run `env | grep SECRET_NAME`, `printenv SECRET_NAME`, or
|
|
263
|
+
equivalent** in a bash tool. Same failure — the value returns in the
|
|
264
|
+
tool result.
|
|
265
|
+
- **When a tool errors, check the error message before summarizing.**
|
|
266
|
+
Some MCP servers echo the connection string in `connection refused`
|
|
267
|
+
errors. If you see the URL in a tool error, redact when
|
|
268
|
+
summarizing to the user, and file the incident via the
|
|
269
|
+
`kindgi-framework-feedback` skill so the preset's audit gets updated.
|
|
270
|
+
- **Prefer `kindgi mcp list` over Reading `.mcp.json`** when the user
|
|
271
|
+
asks "what's configured?" — the list output has the same info in a
|
|
272
|
+
cleaner shape and is safe to include in your reply.
|
|
273
|
+
- **Never repeat the resolved URL back to the user** — even in a
|
|
274
|
+
"here's what I wired up" summary. Refer to the secret by NAME and
|
|
275
|
+
to the server by its `.mcp.json` label. The point of MCP is that
|
|
276
|
+
the value stays out of every layer that a model can see; repeating
|
|
277
|
+
it in your reply defeats the invariant.
|
|
278
|
+
|
|
279
|
+
## When the framework itself is the problem
|
|
280
|
+
|
|
281
|
+
If you diagnose that the bug lives in Kindgi/`@kindgi/cli` itself
|
|
282
|
+
(`kindgi mcp add` writes malformed JSON, `mcp-launch` hangs, a preset
|
|
283
|
+
has bad `defaultArgs`, launcher can't resolve a secret that clearly
|
|
284
|
+
exists in the pack env files, an MCP server echoes the URL in its
|
|
285
|
+
error tool result) — not in your pack's `.mcp.json` or secret setup —
|
|
286
|
+
load the `kindgi-framework-feedback` skill and file a structured
|
|
287
|
+
report with `kindgi feedback write`. That diagnostic is high-signal
|
|
288
|
+
input the maintainers can act on; don't let it disappear into the
|
|
289
|
+
transcript.
|