@experia-labs/plugin-dev-mcp 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.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +82 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +13 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/data/api-endpoints.d.ts +15 -0
  8. package/dist/data/api-endpoints.d.ts.map +1 -0
  9. package/dist/data/api-endpoints.js +80 -0
  10. package/dist/data/api-endpoints.js.map +1 -0
  11. package/dist/data/events.d.ts +13 -0
  12. package/dist/data/events.d.ts.map +1 -0
  13. package/dist/data/events.js +110 -0
  14. package/dist/data/events.js.map +1 -0
  15. package/dist/data/scopes.d.ts +10 -0
  16. package/dist/data/scopes.d.ts.map +1 -0
  17. package/dist/data/scopes.js +70 -0
  18. package/dist/data/scopes.js.map +1 -0
  19. package/dist/data/slots.d.ts +9 -0
  20. package/dist/data/slots.d.ts.map +1 -0
  21. package/dist/data/slots.js +34 -0
  22. package/dist/data/slots.js.map +1 -0
  23. package/dist/index.d.ts +16 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +10 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/manifest/starter.d.ts +16 -0
  28. package/dist/manifest/starter.d.ts.map +1 -0
  29. package/dist/manifest/starter.js +79 -0
  30. package/dist/manifest/starter.js.map +1 -0
  31. package/dist/manifest/validate.d.ts +8 -0
  32. package/dist/manifest/validate.d.ts.map +1 -0
  33. package/dist/manifest/validate.js +182 -0
  34. package/dist/manifest/validate.js.map +1 -0
  35. package/dist/server.d.ts +7 -0
  36. package/dist/server.d.ts.map +1 -0
  37. package/dist/server.js +243 -0
  38. package/dist/server.js.map +1 -0
  39. package/dist/webhook/verify.d.ts +28 -0
  40. package/dist/webhook/verify.d.ts.map +1 -0
  41. package/dist/webhook/verify.js +42 -0
  42. package/dist/webhook/verify.js.map +1 -0
  43. package/package.json +62 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Experia Labs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,82 @@
1
+ # @experia-labs/plugin-dev-mcp
2
+
3
+ A Model Context Protocol server that helps developers build plugins for the
4
+ [Experia](https://experialabs.com) platform. Plug it into Claude Code (or any
5
+ MCP-aware IDE) and ask things like:
6
+
7
+ > "Generate a starter manifest for an organizer-tool plugin called acme.standup."
8
+ >
9
+ > "Validate this manifest" *(paste it)*
10
+ >
11
+ > "Which scope do I need to call POST /messaging/send?"
12
+ >
13
+ > "Why is my webhook returning 401?" *(paste payload + header + secret)*
14
+
15
+ The same validation rules used by the platform's publish endpoint run inside
16
+ this server — if `validate_manifest` passes locally, your `POST
17
+ /developer-portal/plugins/:id/versions` call will too.
18
+
19
+ ## Install + run via Claude Code
20
+
21
+ ```bash
22
+ claude mcp add experia-plugin-dev -- npx -y @experia-labs/plugin-dev-mcp
23
+ ```
24
+
25
+ Or, while developing locally:
26
+
27
+ ```bash
28
+ cd creatoros-api/packages/plugin-dev-mcp
29
+ npm install
30
+ npm run build
31
+ claude mcp add experia-plugin-dev -- node $(pwd)/dist/cli.js
32
+ ```
33
+
34
+ To use it inside a non-Claude MCP client, point the client at the same binary
35
+ and use stdio transport.
36
+
37
+ ## Tools
38
+
39
+ | Tool | What it does |
40
+ |------|--------------|
41
+ | `list_scopes` | Every OAuth-style scope, what it grants, which endpoints it unlocks. |
42
+ | `list_events` | Lifecycle + domain webhook events with example payloads. |
43
+ | `list_extension_slots` | Where in the host UI your iframe can render. |
44
+ | `list_api_endpoints` | Every `/plugin-api/v1` endpoint and the scope it requires. |
45
+ | `validate_manifest` | Runs the platform's publish-time validator on your manifest. |
46
+ | `get_starter_manifest` | Scaffolds a manifest (`minimal` / `attendee-app` / `organizer-tool`). |
47
+ | `verify_webhook_signature` | Verifies an `X-Experia-Signature` header against a payload + secret. Use to debug 401/403s. |
48
+
49
+ ## Resources
50
+
51
+ | URI | Contents |
52
+ |-----|----------|
53
+ | `experia://docs/overview` | Plugin lifecycle, manifests, webhooks, /plugin-api/v1. |
54
+ | `experia://docs/manifest` | Field-by-field manifest reference. |
55
+ | `experia://docs/webhooks` | Signature scheme, replay window, retries. |
56
+
57
+ ## Library use
58
+
59
+ The same helpers are exported from the package root if you want to use them
60
+ in CI checks or your own tooling:
61
+
62
+ ```ts
63
+ import {
64
+ validateManifest,
65
+ generateStarterManifest,
66
+ verifyWebhookSignature,
67
+ } from '@experia-labs/plugin-dev-mcp';
68
+ ```
69
+
70
+ ## Develop
71
+
72
+ ```bash
73
+ npm install
74
+ npm run build # compile TS
75
+ npm test # 25+ unit tests
76
+ npm run verify # tsc --noEmit
77
+ ```
78
+
79
+ Static data files in `src/data/` (scopes, events, slots, API endpoints) must
80
+ stay in sync with their counterparts in `creatoros-api/src/features/plugin-platform/`.
81
+ The `data/registry.spec.ts` tests catch obvious drift; the
82
+ `manifest/validate.spec.ts` tests cover the validator.
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { createServer } from './server.js';
4
+ async function main() {
5
+ const server = createServer();
6
+ const transport = new StdioServerTransport();
7
+ await server.connect(transport);
8
+ }
9
+ main().catch((err) => {
10
+ console.error('experia-plugin-dev-mcp: fatal', err);
11
+ process.exit(1);
12
+ });
13
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,GAAG,CAAC,CAAC;IACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,15 @@
1
+ export interface ApiEndpointInfo {
2
+ method: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';
3
+ path: string;
4
+ scope: string;
5
+ description: string;
6
+ exampleResponse?: unknown;
7
+ }
8
+ /**
9
+ * /plugin-api/v1/* endpoints. Bearer token auth (the
10
+ * `installationToken` delivered in the plugin.installed webhook).
11
+ * Scope on each endpoint must be present in the granted scope set
12
+ * or the call returns 403.
13
+ */
14
+ export declare const PLUGIN_API_ENDPOINTS: ApiEndpointInfo[];
15
+ //# sourceMappingURL=api-endpoints.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-endpoints.d.ts","sourceRoot":"","sources":["../../src/data/api-endpoints.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,EAAE,eAAe,EA4EjD,CAAC"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * /plugin-api/v1/* endpoints. Bearer token auth (the
3
+ * `installationToken` delivered in the plugin.installed webhook).
4
+ * Scope on each endpoint must be present in the granted scope set
5
+ * or the call returns 403.
6
+ */
7
+ export const PLUGIN_API_ENDPOINTS = [
8
+ {
9
+ method: 'GET',
10
+ path: '/plugin-api/v1/event',
11
+ scope: 'event.read',
12
+ description: 'Returns metadata for the event this installation is bound to.',
13
+ exampleResponse: {
14
+ id: 'evt_01HXXX',
15
+ name: 'Manila Tech Summit 2026',
16
+ slug: 'manila-tech-summit-2026',
17
+ startsAt: '2026-06-01T19:00:00.000Z',
18
+ endsAt: '2026-06-01T23:00:00.000Z',
19
+ status: 'PUBLISHED',
20
+ venue: { name: 'SMX Convention', address: 'Pasay City, PH' },
21
+ },
22
+ },
23
+ {
24
+ method: 'GET',
25
+ path: '/plugin-api/v1/event/attendees',
26
+ scope: 'event.attendees.read',
27
+ description: 'Paginated list of attendees with tickets for the bound event.',
28
+ exampleResponse: {
29
+ page: 1,
30
+ pageSize: 50,
31
+ total: 1234,
32
+ items: [
33
+ { id: 'att_01HXXX', email: 'a@b.com', firstName: 'Ana', lastName: 'Doe' },
34
+ ],
35
+ },
36
+ },
37
+ {
38
+ method: 'GET',
39
+ path: '/plugin-api/v1/event/attendees/:id',
40
+ scope: 'event.attendees.read',
41
+ description: 'Single attendee record.',
42
+ },
43
+ {
44
+ method: 'POST',
45
+ path: '/plugin-api/v1/messaging/send',
46
+ scope: 'messaging.send',
47
+ description: 'Send a message to attendees over a single channel. Body: { channel: IN_APP|PUSH|EMAIL, recipients: string[], title?, body, deepLink? }. Subject to plugin-level rate limits (60/min default).',
48
+ },
49
+ {
50
+ method: 'GET',
51
+ path: '/plugin-api/v1/storage/:key',
52
+ scope: 'storage.read',
53
+ description: 'Get a value from the plugin\'s sandboxed KV store for THIS installation.',
54
+ },
55
+ {
56
+ method: 'PUT',
57
+ path: '/plugin-api/v1/storage/:key',
58
+ scope: 'storage.write',
59
+ description: 'Set a value in the plugin\'s sandboxed KV store. Body: { value: any }. 64KB max per key.',
60
+ },
61
+ {
62
+ method: 'DELETE',
63
+ path: '/plugin-api/v1/storage/:key',
64
+ scope: 'storage.write',
65
+ description: 'Delete a key from the plugin\'s sandboxed KV store.',
66
+ },
67
+ {
68
+ method: 'GET',
69
+ path: '/plugin-api/v1/membership/communities',
70
+ scope: 'membership.read',
71
+ description: 'List communities + tiers for the installed organization.',
72
+ },
73
+ {
74
+ method: 'POST',
75
+ path: '/plugin-api/v1/membership/communities/:slug/prompt',
76
+ scope: 'membership.subscribe.prompt',
77
+ description: 'Trigger an in-app/push "subscribe to community" prompt for an attendee.',
78
+ },
79
+ ];
80
+ //# sourceMappingURL=api-endpoints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-endpoints.js","sourceRoot":"","sources":["../../src/data/api-endpoints.ts"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAsB;IACrD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,sBAAsB;QAC5B,KAAK,EAAE,YAAY;QACnB,WAAW,EAAE,+DAA+D;QAC5E,eAAe,EAAE;YACf,EAAE,EAAE,YAAY;YAChB,IAAI,EAAE,yBAAyB;YAC/B,IAAI,EAAE,yBAAyB;YAC/B,QAAQ,EAAE,0BAA0B;YACpC,MAAM,EAAE,0BAA0B;YAClC,MAAM,EAAE,WAAW;YACnB,KAAK,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,gBAAgB,EAAE;SAC7D;KACF;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,gCAAgC;QACtC,KAAK,EAAE,sBAAsB;QAC7B,WAAW,EAAE,+DAA+D;QAC5E,eAAe,EAAE;YACf,IAAI,EAAE,CAAC;YACP,QAAQ,EAAE,EAAE;YACZ,KAAK,EAAE,IAAI;YACX,KAAK,EAAE;gBACL,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE;aAC1E;SACF;KACF;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,oCAAoC;QAC1C,KAAK,EAAE,sBAAsB;QAC7B,WAAW,EAAE,yBAAyB;KACvC;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,+BAA+B;QACrC,KAAK,EAAE,gBAAgB;QACvB,WAAW,EACT,+LAA+L;KAClM;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,6BAA6B;QACnC,KAAK,EAAE,cAAc;QACrB,WAAW,EACT,0EAA0E;KAC7E;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,6BAA6B;QACnC,KAAK,EAAE,eAAe;QACtB,WAAW,EACT,0FAA0F;KAC7F;IACD;QACE,MAAM,EAAE,QAAQ;QAChB,IAAI,EAAE,6BAA6B;QACnC,KAAK,EAAE,eAAe;QACtB,WAAW,EAAE,qDAAqD;KACnE;IACD;QACE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,uCAAuC;QAC7C,KAAK,EAAE,iBAAiB;QACxB,WAAW,EAAE,0DAA0D;KACxE;IACD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,oDAAoD;QAC1D,KAAK,EAAE,6BAA6B;QACpC,WAAW,EACT,yEAAyE;KAC5E;CACF,CAAC"}
@@ -0,0 +1,13 @@
1
+ export interface EventInfo {
2
+ type: string;
3
+ category: 'lifecycle' | 'domain';
4
+ description: string;
5
+ /** Example HTTP body the plugin will receive (truncated for brevity). */
6
+ examplePayload: Record<string, unknown>;
7
+ }
8
+ export declare const LIFECYCLE_EVENTS: EventInfo[];
9
+ export declare const DOMAIN_EVENTS: EventInfo[];
10
+ export declare const ALL_EVENTS: EventInfo[];
11
+ export declare const VALID_DOMAIN_EVENT_TYPES: string[];
12
+ export declare function isValidDomainEvent(s: string): boolean;
13
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/data/events.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,WAAW,GAAG,QAAQ,CAAC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACzC;AAED,eAAO,MAAM,gBAAgB,EAAE,SAAS,EA4CvC,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,SAAS,EA6DpC,CAAC;AAEF,eAAO,MAAM,UAAU,aAA0C,CAAC;AAElE,eAAO,MAAM,wBAAwB,UAAmC,CAAC;AAEzE,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAErD"}
@@ -0,0 +1,110 @@
1
+ // Mirrors creatoros-api/src/features/plugin-platform/events/plugin-events.constants.ts
2
+ export const LIFECYCLE_EVENTS = [
3
+ {
4
+ type: 'plugin.installed',
5
+ category: 'lifecycle',
6
+ description: 'Fired when an organizer installs the plugin on an event. The payload includes a one-time `installationToken` (Bearer for /plugin-api/v1/*) and `webhookSecret` (HMAC for verifying future deliveries). PERSIST BOTH IMMEDIATELY — they are only delivered once.',
7
+ examplePayload: {
8
+ type: 'plugin.installed',
9
+ eventPluginId: 'epi_01HXXX',
10
+ orgId: 'org_01HXXX',
11
+ eventId: 'evt_01HXXX',
12
+ pluginKey: 'acme.sponsors-lounge',
13
+ pluginVersion: '1.0.0',
14
+ config: { theme: 'dark' },
15
+ grantedScopes: ['event.read', 'event.attendees.read'],
16
+ installationToken: 'pit_xxxxx',
17
+ webhookSecret: 'whsec_xxxxx',
18
+ },
19
+ },
20
+ {
21
+ type: 'plugin.uninstalled',
22
+ category: 'lifecycle',
23
+ description: 'Fired when the organizer disables/removes the plugin from an event. After this, the installation token is revoked. Use to clean up plugin-side state.',
24
+ examplePayload: {
25
+ type: 'plugin.uninstalled',
26
+ eventPluginId: 'epi_01HXXX',
27
+ eventId: 'evt_01HXXX',
28
+ },
29
+ },
30
+ {
31
+ type: 'plugin.config_updated',
32
+ category: 'lifecycle',
33
+ description: 'Fired when the organizer changes plugin config OR when the platform upgrades the pinned plugin version (then `fromVersion`/`toVersion` are present).',
34
+ examplePayload: {
35
+ type: 'plugin.config_updated',
36
+ eventPluginId: 'epi_01HXXX',
37
+ eventId: 'evt_01HXXX',
38
+ config: { theme: 'light' },
39
+ fromVersion: '1.0.0',
40
+ toVersion: '1.1.0',
41
+ },
42
+ },
43
+ ];
44
+ export const DOMAIN_EVENTS = [
45
+ {
46
+ type: 'event.started',
47
+ category: 'domain',
48
+ description: 'Fires once when the event\'s startsAt is reached. Use to unlock features.',
49
+ examplePayload: {
50
+ type: 'event.started',
51
+ eventPluginId: 'epi_01HXXX',
52
+ eventId: 'evt_01HXXX',
53
+ startedAt: '2026-06-01T19:00:00.000Z',
54
+ },
55
+ },
56
+ {
57
+ type: 'event.ended',
58
+ category: 'domain',
59
+ description: 'Fires when the event\'s endsAt is reached. Use to enter wind-down mode.',
60
+ examplePayload: {
61
+ type: 'event.ended',
62
+ eventPluginId: 'epi_01HXXX',
63
+ eventId: 'evt_01HXXX',
64
+ endedAt: '2026-06-01T22:00:00.000Z',
65
+ },
66
+ },
67
+ {
68
+ type: 'attendee.registered',
69
+ category: 'domain',
70
+ description: 'Fires when an attendee\'s ticket is generated (post-payment).',
71
+ examplePayload: {
72
+ type: 'attendee.registered',
73
+ eventPluginId: 'epi_01HXXX',
74
+ eventId: 'evt_01HXXX',
75
+ attendeeId: 'att_01HXXX',
76
+ ticketTypeId: 'tt_01HXXX',
77
+ },
78
+ },
79
+ {
80
+ type: 'attendee.checked_in',
81
+ category: 'domain',
82
+ description: 'Fires when an attendee\'s ticket is scanned at the event.',
83
+ examplePayload: {
84
+ type: 'attendee.checked_in',
85
+ eventPluginId: 'epi_01HXXX',
86
+ eventId: 'evt_01HXXX',
87
+ attendeeId: 'att_01HXXX',
88
+ checkedInAt: '2026-06-01T19:12:34.000Z',
89
+ },
90
+ },
91
+ {
92
+ type: 'membership.subscribed',
93
+ category: 'domain',
94
+ description: 'Fires when an attendee subscribes to one of the org\'s communities. Used for community-continuity flows.',
95
+ examplePayload: {
96
+ type: 'membership.subscribed',
97
+ eventPluginId: 'epi_01HXXX',
98
+ eventId: 'evt_01HXXX',
99
+ attendeeId: 'att_01HXXX',
100
+ communitySlug: 'acme-club',
101
+ tierId: 'tier_01HXXX',
102
+ },
103
+ },
104
+ ];
105
+ export const ALL_EVENTS = [...LIFECYCLE_EVENTS, ...DOMAIN_EVENTS];
106
+ export const VALID_DOMAIN_EVENT_TYPES = DOMAIN_EVENTS.map((e) => e.type);
107
+ export function isValidDomainEvent(s) {
108
+ return VALID_DOMAIN_EVENT_TYPES.includes(s);
109
+ }
110
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/data/events.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export interface ScopeInfo {
2
+ scope: string;
3
+ description: string;
4
+ /** What endpoints under /plugin-api/v1 this scope unlocks. */
5
+ unlocks: string[];
6
+ }
7
+ export declare const SCOPE_REGISTRY: ScopeInfo[];
8
+ export declare const ALL_SCOPES: string[];
9
+ export declare function isValidScope(s: string): boolean;
10
+ //# sourceMappingURL=scopes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scopes.d.ts","sourceRoot":"","sources":["../../src/data/scopes.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,eAAO,MAAM,cAAc,EAAE,SAAS,EAqErC,CAAC;AAEF,eAAO,MAAM,UAAU,UAAqC,CAAC;AAE7D,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAE/C"}
@@ -0,0 +1,70 @@
1
+ // Mirrors creatoros-api/src/features/plugin-platform/scopes/plugin-scopes.constants.ts
2
+ // Kept self-contained so this MCP server is publishable without the API repo.
3
+ export const SCOPE_REGISTRY = [
4
+ {
5
+ scope: 'event.read',
6
+ description: 'Read event metadata (name, dates, venue, status). Almost every plugin needs this.',
7
+ unlocks: ['GET /plugin-api/v1/event'],
8
+ },
9
+ {
10
+ scope: 'event.attendees.read',
11
+ description: 'Read the attendee list for the installed event. Required for directory/networking plugins.',
12
+ unlocks: [
13
+ 'GET /plugin-api/v1/event/attendees',
14
+ 'GET /plugin-api/v1/event/attendees/:id',
15
+ ],
16
+ },
17
+ {
18
+ scope: 'event.attendees.write',
19
+ description: 'Tag/note attendees. Use for CRM-style enrichment plugins. Cannot create or delete attendees.',
20
+ unlocks: ['PATCH /plugin-api/v1/event/attendees/:id'],
21
+ },
22
+ {
23
+ scope: 'event.tickets.read',
24
+ description: 'Read ticket types and inventory for the installed event.',
25
+ unlocks: ['GET /plugin-api/v1/event/tickets'],
26
+ },
27
+ {
28
+ scope: 'attendee.profile.read',
29
+ description: 'Read the attendee profile of users currently viewing the plugin via iframe. Bound to the iframe JWT, not bulk.',
30
+ unlocks: ['GET /plugin-api/v1/me'],
31
+ },
32
+ {
33
+ scope: 'attendee.profile.write',
34
+ description: 'Update the viewing attendee\'s profile fields managed by the plugin. Required for profile-builder plugins (e.g. Networking).',
35
+ unlocks: ['PATCH /plugin-api/v1/me'],
36
+ },
37
+ {
38
+ scope: 'messaging.send',
39
+ description: 'Send messages to attendees over IN_APP / PUSH / EMAIL. Subject to per-plugin rate limits.',
40
+ unlocks: ['POST /plugin-api/v1/messaging/send'],
41
+ },
42
+ {
43
+ scope: 'storage.read',
44
+ description: 'Read the plugin\'s sandboxed key-value store for this installation.',
45
+ unlocks: ['GET /plugin-api/v1/storage/:key'],
46
+ },
47
+ {
48
+ scope: 'storage.write',
49
+ description: 'Write to the plugin\'s sandboxed key-value store for this installation.',
50
+ unlocks: [
51
+ 'PUT /plugin-api/v1/storage/:key',
52
+ 'DELETE /plugin-api/v1/storage/:key',
53
+ ],
54
+ },
55
+ {
56
+ scope: 'membership.read',
57
+ description: 'Read communities and tiers belonging to the installed organization.',
58
+ unlocks: ['GET /plugin-api/v1/membership/communities'],
59
+ },
60
+ {
61
+ scope: 'membership.subscribe.prompt',
62
+ description: 'Trigger a "subscribe to community" prompt for the viewing attendee. Used by post-event continuity flows.',
63
+ unlocks: ['POST /plugin-api/v1/membership/communities/:slug/prompt'],
64
+ },
65
+ ];
66
+ export const ALL_SCOPES = SCOPE_REGISTRY.map((s) => s.scope);
67
+ export function isValidScope(s) {
68
+ return ALL_SCOPES.includes(s);
69
+ }
70
+ //# sourceMappingURL=scopes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scopes.js","sourceRoot":"","sources":["../../src/data/scopes.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,8EAA8E;AAS9E,MAAM,CAAC,MAAM,cAAc,GAAgB;IACzC;QACE,KAAK,EAAE,YAAY;QACnB,WAAW,EACT,mFAAmF;QACrF,OAAO,EAAE,CAAC,0BAA0B,CAAC;KACtC;IACD;QACE,KAAK,EAAE,sBAAsB;QAC7B,WAAW,EACT,4FAA4F;QAC9F,OAAO,EAAE;YACP,oCAAoC;YACpC,wCAAwC;SACzC;KACF;IACD;QACE,KAAK,EAAE,uBAAuB;QAC9B,WAAW,EACT,8FAA8F;QAChG,OAAO,EAAE,CAAC,0CAA0C,CAAC;KACtD;IACD;QACE,KAAK,EAAE,oBAAoB;QAC3B,WAAW,EAAE,0DAA0D;QACvE,OAAO,EAAE,CAAC,kCAAkC,CAAC;KAC9C;IACD;QACE,KAAK,EAAE,uBAAuB;QAC9B,WAAW,EACT,gHAAgH;QAClH,OAAO,EAAE,CAAC,uBAAuB,CAAC;KACnC;IACD;QACE,KAAK,EAAE,wBAAwB;QAC/B,WAAW,EACT,8HAA8H;QAChI,OAAO,EAAE,CAAC,yBAAyB,CAAC;KACrC;IACD;QACE,KAAK,EAAE,gBAAgB;QACvB,WAAW,EACT,2FAA2F;QAC7F,OAAO,EAAE,CAAC,oCAAoC,CAAC;KAChD;IACD;QACE,KAAK,EAAE,cAAc;QACrB,WAAW,EAAE,qEAAqE;QAClF,OAAO,EAAE,CAAC,iCAAiC,CAAC;KAC7C;IACD;QACE,KAAK,EAAE,eAAe;QACtB,WAAW,EAAE,yEAAyE;QACtF,OAAO,EAAE;YACP,iCAAiC;YACjC,oCAAoC;SACrC;KACF;IACD;QACE,KAAK,EAAE,iBAAiB;QACxB,WAAW,EAAE,qEAAqE;QAClF,OAAO,EAAE,CAAC,2CAA2C,CAAC;KACvD;IACD;QACE,KAAK,EAAE,6BAA6B;QACpC,WAAW,EACT,0GAA0G;QAC5G,OAAO,EAAE,CAAC,yDAAyD,CAAC;KACrE;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AAE7D,MAAM,UAAU,YAAY,CAAC,CAAS;IACpC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAChC,CAAC"}
@@ -0,0 +1,9 @@
1
+ export interface SlotInfo {
2
+ slot: string;
3
+ rendersIn: string;
4
+ iframeContext: string;
5
+ exampleUseCase: string;
6
+ }
7
+ export declare const SLOT_REGISTRY: SlotInfo[];
8
+ export declare const ALL_SLOTS: string[];
9
+ //# sourceMappingURL=slots.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slots.d.ts","sourceRoot":"","sources":["../../src/data/slots.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,aAAa,EAAE,QAAQ,EAmCnC,CAAC;AAEF,eAAO,MAAM,SAAS,UAAmC,CAAC"}
@@ -0,0 +1,34 @@
1
+ export const SLOT_REGISTRY = [
2
+ {
3
+ slot: 'organizer.event.tabs',
4
+ rendersIn: 'Per-event editor in the organizer dashboard, as a new tab.',
5
+ iframeContext: 'Hosted by Creator OS FE. Available URL params: {eventId}, {orgId}, {pluginVersion}.',
6
+ exampleUseCase: 'Plugin configuration form (e.g. Networking → "Configure quests, leaderboard").',
7
+ },
8
+ {
9
+ slot: 'organizer.dashboard.cards',
10
+ rendersIn: 'Org-level dashboard home page, as a card.',
11
+ iframeContext: 'Available URL params: {orgId}.',
12
+ exampleUseCase: 'Cross-event analytics summary (e.g. "Plugins active across 12 events, 4.2k connections made").',
13
+ },
14
+ {
15
+ slot: 'experia.event.tabs',
16
+ rendersIn: 'Experia mobile/web app, on the event detail screen.',
17
+ iframeContext: 'Available URL params: {eventId}, {pluginJwt} (short-lived attendee JWT scoped to the plugin).',
18
+ exampleUseCase: 'Networking, Live Polls, Sponsor Booths.',
19
+ },
20
+ {
21
+ slot: 'experia.account.cards',
22
+ rendersIn: 'Experia mobile/web app, on the attendee account screen.',
23
+ iframeContext: 'Available URL params: {pluginJwt}.',
24
+ exampleUseCase: '"Your networking profile", "Your collected badges".',
25
+ },
26
+ {
27
+ slot: 'attendee.checkin.actions',
28
+ rendersIn: 'Event check-in flow, as an action button.',
29
+ iframeContext: 'Available URL params: {eventId}, {attendeeId}, {pluginJwt}.',
30
+ exampleUseCase: '"Add to networking directory" prompt at scan time.',
31
+ },
32
+ ];
33
+ export const ALL_SLOTS = SLOT_REGISTRY.map((s) => s.slot);
34
+ //# sourceMappingURL=slots.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slots.js","sourceRoot":"","sources":["../../src/data/slots.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,MAAM,aAAa,GAAe;IACvC;QACE,IAAI,EAAE,sBAAsB;QAC5B,SAAS,EAAE,4DAA4D;QACvE,aAAa,EACX,qFAAqF;QACvF,cAAc,EACZ,gFAAgF;KACnF;IACD;QACE,IAAI,EAAE,2BAA2B;QACjC,SAAS,EAAE,2CAA2C;QACtD,aAAa,EAAE,gCAAgC;QAC/C,cAAc,EACZ,gGAAgG;KACnG;IACD;QACE,IAAI,EAAE,oBAAoB;QAC1B,SAAS,EAAE,qDAAqD;QAChE,aAAa,EACX,+FAA+F;QACjG,cAAc,EAAE,yCAAyC;KAC1D;IACD;QACE,IAAI,EAAE,uBAAuB;QAC7B,SAAS,EAAE,yDAAyD;QACpE,aAAa,EAAE,oCAAoC;QACnD,cAAc,EAAE,qDAAqD;KACtE;IACD;QACE,IAAI,EAAE,0BAA0B;QAChC,SAAS,EAAE,2CAA2C;QACtD,aAAa,EAAE,6DAA6D;QAC5E,cAAc,EAAE,oDAAoD;KACrE;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC"}
@@ -0,0 +1,16 @@
1
+ export { validateManifest } from './manifest/validate.js';
2
+ export type { ManifestValidationResult } from './manifest/validate.js';
3
+ export { generateStarterManifest } from './manifest/starter.js';
4
+ export type { StarterArgs, StarterFlavor } from './manifest/starter.js';
5
+ export { verifyWebhookSignature } from './webhook/verify.js';
6
+ export type { VerifyWebhookArgs, VerifyWebhookResult, } from './webhook/verify.js';
7
+ export { SCOPE_REGISTRY, ALL_SCOPES } from './data/scopes.js';
8
+ export type { ScopeInfo } from './data/scopes.js';
9
+ export { LIFECYCLE_EVENTS, DOMAIN_EVENTS, ALL_EVENTS, } from './data/events.js';
10
+ export type { EventInfo } from './data/events.js';
11
+ export { SLOT_REGISTRY, ALL_SLOTS } from './data/slots.js';
12
+ export type { SlotInfo } from './data/slots.js';
13
+ export { PLUGIN_API_ENDPOINTS } from './data/api-endpoints.js';
14
+ export type { ApiEndpointInfo } from './data/api-endpoints.js';
15
+ export { createServer } from './server.js';
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,YAAY,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AACvE,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,YAAY,EACV,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9D,YAAY,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,UAAU,GACX,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC3D,YAAY,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ // Public exports — re-exported for tests and library consumers.
2
+ export { validateManifest } from './manifest/validate.js';
3
+ export { generateStarterManifest } from './manifest/starter.js';
4
+ export { verifyWebhookSignature } from './webhook/verify.js';
5
+ export { SCOPE_REGISTRY, ALL_SCOPES } from './data/scopes.js';
6
+ export { LIFECYCLE_EVENTS, DOMAIN_EVENTS, ALL_EVENTS, } from './data/events.js';
7
+ export { SLOT_REGISTRY, ALL_SLOTS } from './data/slots.js';
8
+ export { PLUGIN_API_ENDPOINTS } from './data/api-endpoints.js';
9
+ export { createServer } from './server.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAEhE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAEhE,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAM7D,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9D,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,UAAU,GACX,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAG/D,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,16 @@
1
+ export type StarterFlavor = 'minimal' | 'attendee-app' | 'organizer-tool';
2
+ export interface StarterArgs {
3
+ /** Vendor-prefixed key, e.g. "acme.sponsors-lounge". */
4
+ key: string;
5
+ /** Display name. */
6
+ name: string;
7
+ /** Developer name (org name). */
8
+ developerName: string;
9
+ /** Developer contact email. */
10
+ developerEmail: string;
11
+ /** Base URL where your plugin is hosted (no trailing slash). */
12
+ baseUrl: string;
13
+ flavor?: StarterFlavor;
14
+ }
15
+ export declare function generateStarterManifest(args: StarterArgs): Record<string, unknown>;
16
+ //# sourceMappingURL=starter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"starter.d.ts","sourceRoot":"","sources":["../../src/manifest/starter.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,cAAc,GAAG,gBAAgB,CAAC;AAE1E,MAAM,WAAW,WAAW;IAC1B,wDAAwD;IACxD,GAAG,EAAE,MAAM,CAAC;IACZ,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,+BAA+B;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,gEAAgE;IAChE,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAiFlF"}