@ductape/mcp 0.1.60 → 0.2.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/CHANGELOG.md +8 -0
- package/README.md +5 -0
- package/dist/index.js +502 -8
- package/package.json +7 -1
- package/scripts/check-frontend-analytics-guidance.mjs +0 -88
- package/src/index.ts +0 -4280
- package/src/proxy-client.ts +0 -172
- package/tsconfig.json +0 -17
package/package.json
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ductape/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "MCP server that exposes Ductape SDK operations via the backend proxy",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"bin": {
|
|
8
8
|
"ductape-mcp": "dist/index.js"
|
|
9
9
|
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"docs",
|
|
13
|
+
"README.md",
|
|
14
|
+
"CHANGELOG.md"
|
|
15
|
+
],
|
|
10
16
|
"scripts": {
|
|
11
17
|
"build": "tsc",
|
|
12
18
|
"test": "node scripts/check-frontend-analytics-guidance.mjs",
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
import { readFileSync } from 'node:fs';
|
|
3
|
-
import { fileURLToPath } from 'node:url';
|
|
4
|
-
import { dirname, resolve } from 'node:path';
|
|
5
|
-
|
|
6
|
-
const here = dirname(fileURLToPath(import.meta.url));
|
|
7
|
-
const source = readFileSync(resolve(here, '../src/index.ts'), 'utf8');
|
|
8
|
-
|
|
9
|
-
const checks = [
|
|
10
|
-
['dedicated docs topic', /'frontend-analytics': `/],
|
|
11
|
-
['anonymous analytics without an invented session', /Before login:[\s\S]*do not invent a session/i],
|
|
12
|
-
['identify after authentication', /After login\/registration:[\s\S]*identify\(fullSessionToken\)/i],
|
|
13
|
-
['identify after refresh', /After refresh:[\s\S]*identify\(newSessionToken\)/i],
|
|
14
|
-
['clear identity on logout and account switching', /LOGOUT \/ ACCOUNT SWITCHING[\s\S]*clearSession\(\)/],
|
|
15
|
-
['SPA route pageviews', /location\.pathname[\s\S]*analytics\.pageview/],
|
|
16
|
-
['pageviews and custom events', /CUSTOM EVENTS[\s\S]*PAGE VIEWS/],
|
|
17
|
-
['analytics is non-authoritative', /Analytics is never an authoritative order/],
|
|
18
|
-
['tokens excluded from properties', /session\/refresh tokens in event[\s\S]*properties/],
|
|
19
|
-
['hidden multiplayer state warning', /HIDDEN AND SENSITIVE DATA/],
|
|
20
|
-
['masking review before auto-capture', /AUTO-CAPTURE — OPT IN ONLY AFTER A PRIVACY AUDIT/],
|
|
21
|
-
['visitor ID is not authentication', /visitor ID is anonymous analytics identity, not authentication/i],
|
|
22
|
-
['trace correlation', /traceId\s*= correlation/],
|
|
23
|
-
['dashboard troubleshooting covers both tracks', /Investigate both tracks before blaming the SDK/],
|
|
24
|
-
['installed exports take precedence', /Installed package types and exports determine what can be called now/],
|
|
25
|
-
];
|
|
26
|
-
|
|
27
|
-
for (const [name, pattern] of checks) {
|
|
28
|
-
assert.match(source, pattern, `Missing frontend analytics guidance: ${name}`);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
assert.doesNotMatch(
|
|
32
|
-
source,
|
|
33
|
-
/analytics\.identify\(\{\s*userId/,
|
|
34
|
-
'MCP guidance must not use the obsolete identify({ userId, traits }) signature',
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
const safetyChecks = [
|
|
38
|
-
['admin execute calls removed', /ductape_execute\("[^"\n]*(?:create|update)/],
|
|
39
|
-
['obsolete NestJS consumer removed', /events\.consume in onModuleInit/],
|
|
40
|
-
['canonical NestJS consumer present', /@Events\.Consumer\(\{ event:/],
|
|
41
|
-
['request actor context documented', /AsyncLocalStorage[\s\S]*ActorContext/],
|
|
42
|
-
['raw token logging prohibited', /Never log,[\s\S]*raw session\/refresh token/],
|
|
43
|
-
['durable token expiry semantics documented', /does not expose an immutable[\s\S]*expired-token attribution contract/],
|
|
44
|
-
['frontend durable work prohibits persisted JWTs', /For delayed\/durable work, do not persist raw JWTs indefinitely/],
|
|
45
|
-
['browser events use frontend client', /CLIENT-SIDE \(browser — publishable key\):[\s\S]*import \{ createClient \} from '@ductape\/client';[\s\S]*ductape\.brokers\.publish/],
|
|
46
|
-
['resilience decision matrix present', /DECISION MATRIX[\s\S]*Database atomicity/],
|
|
47
|
-
['payload session-awareness metadata present', /session_awareness:[\s\S]*accepts_session/],
|
|
48
|
-
['execute blocks administrative mutations', /Administrative operation.*is blocked in ductape_execute/],
|
|
49
|
-
['CLI auth is remotely validated', /ductape workspaces list --json/],
|
|
50
|
-
['CLI 401 triggers login-required state', /authentication expired or was revoked \(HTTP 401\)[\s\S]*ductape login/],
|
|
51
|
-
['CLI distinguishes endpoint 401 from expired login', /session and active workspace are authenticated[\s\S]*Do not ask the user to log in again/],
|
|
52
|
-
['CLI auth guidance does not request secrets', /Never ask the user to paste their password/],
|
|
53
|
-
['notification CLI administration documented', /resources notifications create[\s\S]*notifications messages create/],
|
|
54
|
-
['notification command allowed by MCP', /ADMIN_SUBCOMMANDS[\s\S]*'notifications'/],
|
|
55
|
-
['notification template uses SDK shape', /push_notification\?: \{ title: string, body: string[\s\S]*email\?: \{ subject: string, template: string/],
|
|
56
|
-
['notification declarations require array shape', /file MUST be a top-level JSON array/],
|
|
57
|
-
['external CLI login is re-read', /authState === 'unknown' \|\| authState === 'none'/],
|
|
58
|
-
['compact product inventory documented', /products components list --tag <tag> --json/],
|
|
59
|
-
['features use installed events context', /ctx\.events\.produce inside a Feature/],
|
|
60
|
-
['features are code-first rather than Workbench-created', /Features have no CLI (?:create|creation)\s+command because (?:their )?definitions are code-first/],
|
|
61
|
-
['Firebase GCP cloud connection documented', /FIREBASE THROUGH A GCP CLOUD CONNECTION[\s\S]*authMode.*cloud_connection/],
|
|
62
|
-
['Slack and Discord sends documented', /notifications\.slack\.send[\s\S]*notifications\.discord\.send/],
|
|
63
|
-
];
|
|
64
|
-
|
|
65
|
-
for (const [name, pattern] of safetyChecks) {
|
|
66
|
-
if (name === 'admin execute calls removed' || name === 'obsolete NestJS consumer removed') {
|
|
67
|
-
assert.doesNotMatch(source, pattern, `Unsafe MCP guidance remains: ${name}`);
|
|
68
|
-
} else {
|
|
69
|
-
assert.match(source, pattern, `Missing MCP safety guidance: ${name}`);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const clientEventsSection = source.match(
|
|
74
|
-
/CLIENT-SIDE \(browser — publishable key\):[\s\S]*?SCHEDULED DISPATCH \(background job\):/,
|
|
75
|
-
)?.[0] ?? '';
|
|
76
|
-
assert.doesNotMatch(
|
|
77
|
-
clientEventsSection,
|
|
78
|
-
/from '@ductape\/sdk'/,
|
|
79
|
-
'Browser Events guidance must not import the server SDK',
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
assert.doesNotMatch(
|
|
83
|
-
source,
|
|
84
|
-
/ctx\.messaging\.produce/,
|
|
85
|
-
'Feature guidance must use the installed ctx.events API, not a nonexistent ctx.messaging alias',
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
console.log(`MCP guidance: ${checks.length + 1 + safetyChecks.length} acceptance checks passed`);
|