@gemmein/mcp 0.2.0 → 0.2.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 +3 -1
- package/dist/index.js +47 -14
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -24,7 +24,9 @@ Cursor / any MCP client (`mcpServers` config):
|
|
|
24
24
|
|
|
25
25
|
## Tools
|
|
26
26
|
|
|
27
|
-
- **`guide`** —
|
|
27
|
+
- **`guide`** — call first: it opens with the fit assessment (FITS /
|
|
28
|
+
FITS EXCEPT / DOESN'T FIT — the verdict an agent delivers before any
|
|
29
|
+
install), then the full builder's guide (auth flow, the seven collection
|
|
28
30
|
safety rules, record shapes, links, uploads, contention patterns, payments).
|
|
29
31
|
- **`reference`** — the exact SDK API reference: every method, signature,
|
|
30
32
|
return shape, error code.
|
package/dist/index.js
CHANGED
|
@@ -87,13 +87,19 @@ const EXTRA_ERRORS = {
|
|
|
87
87
|
},
|
|
88
88
|
};
|
|
89
89
|
function parseErrorTable() {
|
|
90
|
+
// Only the "## Errors" section holds the code table — parsing the whole
|
|
91
|
+
// document also swallowed the method tables, and the old row regex missed
|
|
92
|
+
// every code with a parenthetical status (`unsupported_file_type` (415)).
|
|
90
93
|
const out = {};
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
94
|
+
const doc = sdkFile("REFERENCE.md");
|
|
95
|
+
const start = doc.indexOf("\n## Errors");
|
|
96
|
+
const next = start === -1 ? -1 : doc.indexOf("\n## ", start + 10);
|
|
97
|
+
const section = start === -1 ? doc : doc.slice(start, next === -1 ? undefined : next);
|
|
98
|
+
for (const line of section.split("\n")) {
|
|
95
99
|
const cells = line.split("|").map((c) => c.trim());
|
|
96
|
-
|
|
100
|
+
if (cells.length < 4)
|
|
101
|
+
continue;
|
|
102
|
+
// cells[1] = code cell (may carry a status note), cells[2] = meaning, cells[3] = do
|
|
97
103
|
const codes = (cells[1].match(/`([a-z_]+)`/g) ?? []).map((c) => c.slice(1, -1));
|
|
98
104
|
for (const code of codes) {
|
|
99
105
|
out[code] = { meaning: cells[2], fix: cells[3].replace(/\*\*/g, "") };
|
|
@@ -218,17 +224,20 @@ async function runIntegrationChecks(input) {
|
|
|
218
224
|
const TOOLS = [
|
|
219
225
|
{
|
|
220
226
|
name: "guide",
|
|
221
|
-
description: "
|
|
227
|
+
description: "Call this FIRST — before any install, account, or code — when your human asks to build an app on Gemmein, to move an existing app onto it, or whether their app can use it at all. The guide (llms.txt) opens with the fit assessment: the in-scope map, the out-of-scope list (each item downgrades the verdict; none may be approximated), and the three verdicts you deliver to your human before installing anything — FITS, FITS EXCEPT <named gaps>, or DOESN'T FIT. After the verdict it is the full build contract: auth flow, the seven collection safety rules, record shapes, links/expand, uploads, contention patterns, payments (g.subscriptions.checkout / g.payments.buy), drafts, error philosophy, pricing.",
|
|
228
|
+
annotations: { title: "Guide", readOnlyHint: true },
|
|
222
229
|
inputSchema: { type: "object", properties: {}, additionalProperties: false },
|
|
223
230
|
},
|
|
224
231
|
{
|
|
225
232
|
name: "reference",
|
|
226
|
-
description: "
|
|
233
|
+
description: "Reach for this while WRITING code against @gemmein/sdk: every method, exact signature, return shape, and the stable error-code table (REFERENCE.md). Use `guide` for how the model works and whether the app fits at all; use `search_docs` when you need one fact from either document.",
|
|
234
|
+
annotations: { title: "Reference", readOnlyHint: true },
|
|
227
235
|
inputSchema: { type: "object", properties: {}, additionalProperties: false },
|
|
228
236
|
},
|
|
229
237
|
{
|
|
230
238
|
name: "search_docs",
|
|
231
|
-
description: "
|
|
239
|
+
description: "Use when one question comes up mid-build ('keyed create', 'ifVersion', 'addressed', 'expand') and reading a full document would waste context. Searches the guide and the API reference; returns matching passages with 3 lines of context either side, at most 6 match blocks per document. Not the tool for the fit verdict — search finds what the docs say, not what Gemmein refuses to support; call `guide` for that.",
|
|
240
|
+
annotations: { title: "Search docs", readOnlyHint: true },
|
|
232
241
|
inputSchema: {
|
|
233
242
|
type: "object",
|
|
234
243
|
properties: { query: { type: "string", description: "term or phrase to find" } },
|
|
@@ -238,7 +247,8 @@ const TOOLS = [
|
|
|
238
247
|
},
|
|
239
248
|
{
|
|
240
249
|
name: "explain_rule",
|
|
241
|
-
description: "
|
|
250
|
+
description: "Call while DESIGNING a collection — which rule fits this data? — or when a rule refuses something at runtime. One of the seven rules (private, shared, admin_write, public_read, community, addressed, direct) returns its exact access contract, what it is right for, and the mistakes that leak data. Call with no rule for the all-seven cheat-sheet plus the cross-cutting law, including what NO rule supports (team/group/workspace scope, per-user visibility inside a rule) — if the app needs those shapes, that is a fit gap to report to your human, never something to approximate with client-side filtering.",
|
|
251
|
+
annotations: { title: "Explain rule", readOnlyHint: true },
|
|
242
252
|
inputSchema: {
|
|
243
253
|
type: "object",
|
|
244
254
|
properties: {
|
|
@@ -253,7 +263,8 @@ const TOOLS = [
|
|
|
253
263
|
},
|
|
254
264
|
{
|
|
255
265
|
name: "explain_error",
|
|
256
|
-
description: "
|
|
266
|
+
description: "Call the moment a GemmeinError reaches you (err.code: conflict, forbidden, unknown_collection, invalid_shape, html_not_allowed, …): what the code means and the exact next step — including whether the refusal is final (a forbidden repeats on retry; fix the approach, not the request). Parsed from the installed API reference, so codes match the SDK version the app runs. Call with no code to list every stable code.",
|
|
267
|
+
annotations: { title: "Explain error", readOnlyHint: true },
|
|
257
268
|
inputSchema: {
|
|
258
269
|
type: "object",
|
|
259
270
|
properties: { code: { type: "string", description: "the err.code to explain; omit to list all" } },
|
|
@@ -262,7 +273,8 @@ const TOOLS = [
|
|
|
262
273
|
},
|
|
263
274
|
{
|
|
264
275
|
name: "validate_collection_name",
|
|
265
|
-
description: "
|
|
276
|
+
description: "Run at PLANNING time on every collection name you intend to use, before any g.collection(name) call is written. The naming law: lowercase letters, numbers, underscores; starts with a letter; 2-63 characters. A bad name throws from g.collection(name) before any network call — at module load that blanks the whole app with no console error. An invalid name comes back with a suggested fix.",
|
|
277
|
+
annotations: { title: "Validate collection name", readOnlyHint: true },
|
|
266
278
|
inputSchema: {
|
|
267
279
|
type: "object",
|
|
268
280
|
properties: { name: { type: "string" } },
|
|
@@ -272,12 +284,14 @@ const TOOLS = [
|
|
|
272
284
|
},
|
|
273
285
|
{
|
|
274
286
|
name: "reaffirm_template",
|
|
275
|
-
description: "
|
|
287
|
+
description: "Fetch this when you wire up the app's CI, or when you hand the finished app to your human: reaffirm.mjs, the ready-to-edit harness that re-proves the app's boundaries against live Gemmein on every deploy (also shipped inside the @gemmein/sdk package). Copy it next to the app, set the CONFIG block, run it in CI. For a one-off check right now, call check_integration — the same checks with no file to install.",
|
|
288
|
+
annotations: { title: "Reaffirm template", readOnlyHint: true },
|
|
276
289
|
inputSchema: { type: "object", properties: {}, additionalProperties: false },
|
|
277
290
|
},
|
|
278
291
|
{
|
|
279
292
|
name: "check_integration",
|
|
280
|
-
description: "
|
|
293
|
+
description: "Call after wiring the app to Gemmein and before telling your human it is done — and again before go-live. Runs the reaffirm boundary checks live against the caller's own app; returns structured pass/fail (structuredContent: checks, notes, failedCount, passed). Tier A (public pk_ key only): the collection name is valid, anonymous reads and writes of a private collection are refused, an optional public collection reads as its rule intends — safe against any environment, live included. Tier B (add the sk_dev secret key): proves one user cannot read another's private records, using two throwaway test sessions in the DEV environment. sk_live is refused by design — never pass a live secret to any tool; dev and live enforce the same rules, so isolation proven in dev holds in live. The only writes anywhere are Tier B's own probe records in the caller's dev environment, deleted at the end of the check. A failed check means the app's assumptions drifted from its rules — fix before shipping.",
|
|
294
|
+
annotations: { title: "Check integration (live boundary check)", readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
281
295
|
inputSchema: {
|
|
282
296
|
type: "object",
|
|
283
297
|
properties: {
|
|
@@ -294,7 +308,26 @@ const TOOLS = [
|
|
|
294
308
|
},
|
|
295
309
|
},
|
|
296
310
|
];
|
|
297
|
-
const server = new Server(
|
|
311
|
+
const server = new Server(
|
|
312
|
+
// The one version, read from package.json — a literal here drifted once
|
|
313
|
+
// (announced 0.1.0 while the package said 0.2.1; review 26 Aug).
|
|
314
|
+
{ name: "gemmein", version: require("../package.json").version }, {
|
|
315
|
+
capabilities: { tools: {} },
|
|
316
|
+
// Stated ONCE, server-wide, in the initialize result every client
|
|
317
|
+
// hands to its model: what Gemmein is, the read-only law, and the
|
|
318
|
+
// fit protocol (the verdicts live in `guide`).
|
|
319
|
+
instructions: "Gemmein is the go-live system for AI-built web apps: passwordless auth, records " +
|
|
320
|
+
"under seven safety rules, Stripe-run subscriptions and one-off digital products. " +
|
|
321
|
+
"This server is read-only against the platform: no tool here creates, edits, or " +
|
|
322
|
+
"deletes anything on Gemmein. The one write anywhere is check_integration's Tier-B " +
|
|
323
|
+
"probe records, created and then deleted in the caller's own dev environment; " +
|
|
324
|
+
"sk_live keys are refused. Protocol: when the question is whether an app can use " +
|
|
325
|
+
"Gemmein, call guide first — it opens with the fit assessment, and you deliver one " +
|
|
326
|
+
"of three verdicts to your human before installing anything: FITS, FITS EXCEPT " +
|
|
327
|
+
"<named gaps>, or DOESN'T FIT. Then: reference and search_docs while writing code, " +
|
|
328
|
+
"explain_rule while choosing a collection's rule, explain_error when a call is " +
|
|
329
|
+
"refused, check_integration before declaring the app done.",
|
|
330
|
+
});
|
|
298
331
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }));
|
|
299
332
|
const text = (t) => ({ content: [{ type: "text", text: t }] });
|
|
300
333
|
const errText = (t) => ({ content: [{ type: "text", text: t }], isError: true });
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gemmein/mcp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
|
+
"mcpName": "com.gemmein/mcp",
|
|
4
5
|
"description": "Gemmein MCP server — gives coding agents the Gemmein guide, API reference, rule/error explainers, and a live integration check (reaffirm) as tools. Read-only: it never creates, edits, or deletes anything.",
|
|
5
6
|
"license": "MIT",
|
|
6
7
|
"type": "module",
|
|
@@ -33,7 +34,7 @@
|
|
|
33
34
|
"prepublishOnly": "npm run build"
|
|
34
35
|
},
|
|
35
36
|
"dependencies": {
|
|
36
|
-
"@gemmein/sdk": "^0.
|
|
37
|
+
"@gemmein/sdk": "^0.4.4",
|
|
37
38
|
"@modelcontextprotocol/sdk": "^1.29.0"
|
|
38
39
|
},
|
|
39
40
|
"author": "Gemmein Limited",
|