@helix3/helix-mcp 0.2.2-helix3.14
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 +21 -0
- package/README.md +46 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +353 -0
- package/dist/server.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/docs/catalog.md +28 -0
- package/docs/character-world.md +506 -0
- package/docs/manifest.md +51 -0
- package/docs/multiplayer-logic.md +394 -0
- package/docs/multiplayer-templates/chrono-orchard.md +123 -0
- package/docs/multiplayer-templates/collect-a-thon.md +126 -0
- package/docs/multiplayer-templates/collections.md +116 -0
- package/docs/multiplayer-templates/hangout.md +184 -0
- package/docs/multiplayer-templates/obby.md +84 -0
- package/docs/multiplayer-templates/physics-bumper.md +153 -0
- package/docs/multiplayer-templates/physics-football.md +133 -0
- package/docs/multiplayer-templates/relic-bearers.md +140 -0
- package/docs/multiplayer-templates/server-motion.md +128 -0
- package/docs/multiplayer-templates/team-control.md +98 -0
- package/docs/multiplayer-templates/turn-arena.md +159 -0
- package/docs/multiplayer-templates/wave-survival.md +141 -0
- package/docs/multiplayer-world.md +231 -0
- package/docs/publishing.md +42 -0
- package/docs/sdk.md +117 -0
- package/docs/world-recipe.md +137 -0
- package/package.json +33 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Publishing to HELIX Instant
|
|
2
|
+
|
|
3
|
+
## The pipeline
|
|
4
|
+
|
|
5
|
+
`publish_world` runs the full creator pipeline against the platform:
|
|
6
|
+
|
|
7
|
+
1. **Local validation** — the bundle directory is checked with the exact rules the server enforces (manifest schema, slug format, entry exists, file types, size budget). `validate_world` runs the same check standalone.
|
|
8
|
+
2. **World resolution** — the manifest `slug` is matched against your existing worlds; a new world is created on first publish. Re-publishing a slug creates the **next build** (builds are immutable; the newest finalized build is what players get).
|
|
9
|
+
3. **Upload** — each file is uploaded to CDN storage via presigned URLs (size and content type are cryptographically pinned; a mismatched upload is rejected by storage itself).
|
|
10
|
+
4. **Finalize** — the platform verifies every declared file landed byte-exact, then atomically activates the build. A draft world auto-publishes on its first successful build.
|
|
11
|
+
5. You get back the **play URL** — shareable, instant, no install.
|
|
12
|
+
|
|
13
|
+
## Login (human prerequisite)
|
|
14
|
+
|
|
15
|
+
Publishing requires a creator account session. Agents cannot log in — the flow is interactive. If `whoami` says not logged in, ask the human to run:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm i -g @hypersoniclabs/helix-cli # NOT `npx helix` — that's an unrelated package
|
|
19
|
+
helix login
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Creator access is currently invite-only (curated launch); the account must have the creator flag.
|
|
23
|
+
|
|
24
|
+
## Error semantics
|
|
25
|
+
|
|
26
|
+
- Validation errors list every problem at once — fix all of them, rebuild, re-validate.
|
|
27
|
+
- `409` on world creation: the slug is taken by another creator. Choose a different slug in `helix.json`.
|
|
28
|
+
- "missing upload" / "size mismatch" at finalize: the build directory changed between validate and publish — rebuild and re-publish.
|
|
29
|
+
- `401`/`403`: login expired or the account lacks the creator flag — back to the human.
|
|
30
|
+
|
|
31
|
+
## After publishing
|
|
32
|
+
|
|
33
|
+
- World page: `https://helix-instant-website-production.up.railway.app/w/<slug>`
|
|
34
|
+
- Instant play: `https://helix-instant-website-production.up.railway.app/play/<slug>`
|
|
35
|
+
- Title, content rating, mobile support, and `requiresAuth` on the world page all come from the manifest — re-publish to update them.
|
|
36
|
+
|
|
37
|
+
## Keeping the toolchain current
|
|
38
|
+
|
|
39
|
+
The `@helix` packages publish independently; call `check_for_updates` (or `helix doctor`) to see what's behind and get the exact update command.
|
|
40
|
+
|
|
41
|
+
- **CLI and MCP** — run them via `npx -y @hypersoniclabs/helix-cli@latest` / `npx -y @hypersoniclabs/helix-mcp@latest` and they're always current (the MCP config already does this). A global install goes stale; refresh it with `npm i -g @hypersoniclabs/helix-cli@latest`.
|
|
42
|
+
- **SDK** (`@hypersoniclabs/helix-sdk`, pinned in a world's `package.json`) — a `^0.x` range locks the minor, so a new minor isn't picked up by `npm update`. Bump the range and reinstall: `npm i @hypersoniclabs/helix-sdk@latest`.
|
package/docs/sdk.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# @hypersoniclabs/helix-sdk
|
|
2
|
+
|
|
3
|
+
The HELIX Instant SDK. Worlds running on HELIX Instant use it for player identity today, and multiplayer / voice / wallet / inventory in upcoming versions. It is the **only** way a world talks to the platform — worlds never call platform APIs or internal services directly.
|
|
4
|
+
|
|
5
|
+
> This document is the SDK contract. It is written to be sufficient for an AI agent to integrate a world without reading the SDK source.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @hypersoniclabs/helix-sdk
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Core concepts
|
|
14
|
+
|
|
15
|
+
1. **Your world runs in a sandboxed iframe** inside the HELIX shell (the portal play page, or the `helix dev` shell during local development). The SDK talks to the shell via `postMessage`; the shell talks to the platform.
|
|
16
|
+
2. **Identity is granted, not taken.** Your world receives a short-lived, world-scoped session that only unlocks the permissions declared in your `helix.json` manifest. You never see the player's platform credentials.
|
|
17
|
+
3. **Login UI belongs to the shell.** Your world cannot render a login form — it *requests* login, and the shell overlays its own UI. This is deliberate (anti-phishing) and means you never handle passwords.
|
|
18
|
+
4. **Standalone mode.** When the world is opened directly (e.g. `vite dev` without a shell), `init()` resolves with `embedded: false` and all identity APIs return `null`/`false`. Your world should still run — treat identity as an enhancement.
|
|
19
|
+
|
|
20
|
+
## Quick start
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { Helix } from '@hypersoniclabs/helix-sdk';
|
|
24
|
+
|
|
25
|
+
const { embedded, user, world } = await Helix.init(); // call once, before anything else
|
|
26
|
+
|
|
27
|
+
if (user) {
|
|
28
|
+
greet(user.displayName ?? user.username);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// React to login/logout at any time (e.g. update the HUD):
|
|
32
|
+
Helix.auth.onAuthChanged((user) => updateHud(user));
|
|
33
|
+
|
|
34
|
+
// Prompt login at a moment that makes sense in your world:
|
|
35
|
+
saveButton.onclick = async () => {
|
|
36
|
+
try {
|
|
37
|
+
const user = await Helix.auth.requestLogin(); // shell overlay; no page reload
|
|
38
|
+
await saveProgress(user.id);
|
|
39
|
+
} catch {
|
|
40
|
+
// player dismissed the login — keep playing, nothing is lost
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## API
|
|
46
|
+
|
|
47
|
+
### `Helix.init(): Promise<HelixInitResult>`
|
|
48
|
+
|
|
49
|
+
Performs the shell handshake. **Must be called once before any other API.** Safe to call again (returns the same state). Resolves within ~3s even with no shell present.
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
type HelixInitResult = {
|
|
53
|
+
embedded: boolean; // false when running standalone (local dev)
|
|
54
|
+
world: { id: string; slug: string; title: string } | null;
|
|
55
|
+
user: HelixUser | null; // null when not logged in
|
|
56
|
+
};
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### `Helix.auth.getUser(): Promise<HelixUser | null>`
|
|
60
|
+
|
|
61
|
+
The current player, or `null` when unauthenticated. Requires the `auth.profile` permission in your manifest.
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
type HelixUser = {
|
|
65
|
+
id: string; // stable player id (UUID) — use this as your save key
|
|
66
|
+
username: string; // unique handle
|
|
67
|
+
displayName: string | null;
|
|
68
|
+
};
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### `Helix.auth.isAuthenticated(): boolean`
|
|
72
|
+
|
|
73
|
+
Synchronous check.
|
|
74
|
+
|
|
75
|
+
### `Helix.auth.requestLogin(): Promise<HelixUser>`
|
|
76
|
+
|
|
77
|
+
Asks the shell to show its login overlay. Resolves with the user on success. Rejects when: the player dismisses the overlay (`'dismissed'`), no shell is present (standalone), or the request times out. **The world keeps running throughout — there is no reload, and your state is preserved.** If already logged in, resolves immediately.
|
|
78
|
+
|
|
79
|
+
### `Helix.auth.onAuthChanged(cb: (user: HelixUser | null) => void): () => void`
|
|
80
|
+
|
|
81
|
+
Subscribes to login/logout. Fires with the user on login and `null` on logout. Returns an unsubscribe function.
|
|
82
|
+
|
|
83
|
+
### `Helix.getSessionToken(): string | null`
|
|
84
|
+
|
|
85
|
+
The raw world-scoped session token (JWT, `aud: helix-instant-world`). Most worlds never need this; later SDK modules use it internally.
|
|
86
|
+
|
|
87
|
+
### `Helix.avatar.getEquipped(): Promise<EquippedAvatar | null>`
|
|
88
|
+
|
|
89
|
+
The local player's equipped **universal avatar** — the single character a world renders for them.
|
|
90
|
+
`EquippedAvatar = { source: 'equipped' | 'auto' | 'default', itemId, glbUrl, skeleton }`. Resolves `null` for
|
|
91
|
+
guests / standalone / any failure — the world falls back to the default body, never breaks. Feed it to
|
|
92
|
+
`loadCharacterAssets`'s `avatar` option (single-player) or the `AvatarModelCache` (multiplayer) — see the
|
|
93
|
+
character recipe §8 and the `hangout` template §3a. **Gate on `skeleton === 'helix-humanoid'`** (the
|
|
94
|
+
`UNIVERSAL_AVATAR_SKELETON` export): only a converted avatar can be driven by the platform clips; the
|
|
95
|
+
`loadCharacterAssets` `avatar` option does this gate for you. Call **after `Helix.init()`** and **before**
|
|
96
|
+
character assets load — the body is bind-once. In multiplayer, remote players' avatars arrive on room state
|
|
97
|
+
(`player.avatarUrl`, `''` = none) — you never look up another user's avatar yourself.
|
|
98
|
+
|
|
99
|
+
## Manifest requirements
|
|
100
|
+
|
|
101
|
+
Your bundle root must contain a `helix.json` manifest (see `@hypersoniclabs/helix-manifest`). To use the identity APIs, declare the permission:
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"helixVersion": "0.1",
|
|
106
|
+
"title": "My World",
|
|
107
|
+
"slug": "my-world",
|
|
108
|
+
"entry": "index.html",
|
|
109
|
+
"permissions": ["auth.profile"]
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Calling an API whose permission is not declared returns an error — permissions are enforced server-side on the session token, not just in the SDK.
|
|
114
|
+
|
|
115
|
+
## Coming in later versions
|
|
116
|
+
|
|
117
|
+
`Helix.multiplayer` (instances), `Helix.voice`, `Helix.wallet`, `Helix.inventory`, `Helix.cloudSave`, `Helix.leaderboards`. The shapes follow the same pattern: capability declared in the manifest → granted on the session → exposed as a namespace.
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# HELIX Instant — World Project Recipe
|
|
2
|
+
|
|
3
|
+
Follow this recipe exactly to generate a **publishable HELIX Instant world**. A world is a static web app (Vite-built) that runs sandboxed in the HELIX portal and talks to the platform only through `@hypersoniclabs/helix-sdk`.
|
|
4
|
+
|
|
5
|
+
## Project layout
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
my-world/
|
|
9
|
+
├── package.json
|
|
10
|
+
├── vite.config.ts
|
|
11
|
+
├── index.html
|
|
12
|
+
├── public/
|
|
13
|
+
│ └── helix.json ← the manifest; lands at dist/ root on build
|
|
14
|
+
└── src/
|
|
15
|
+
└── main.ts
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## package.json
|
|
19
|
+
|
|
20
|
+
```json
|
|
21
|
+
{
|
|
22
|
+
"name": "my-world",
|
|
23
|
+
"private": true,
|
|
24
|
+
"type": "module",
|
|
25
|
+
"scripts": {
|
|
26
|
+
"dev": "vite",
|
|
27
|
+
"build": "vite build"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@hypersoniclabs/helix-sdk": "^0.1.0",
|
|
31
|
+
"three": "^0.172.0"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/three": "^0.172.0",
|
|
35
|
+
"typescript": "~5.7.3",
|
|
36
|
+
"vite": "^6.0.0"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Three.js is the usual choice but any web stack works — the only hard requirements are the manifest, the SDK, and a static `dist/` output.
|
|
42
|
+
|
|
43
|
+
## vite.config.ts — `base: './'` is REQUIRED
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
import { defineConfig } from 'vite';
|
|
47
|
+
|
|
48
|
+
// base './' makes asset URLs relative so the bundle loads from any CDN path.
|
|
49
|
+
export default defineConfig({
|
|
50
|
+
base: './',
|
|
51
|
+
build: { target: 'es2022' },
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## public/helix.json — the manifest
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"helixVersion": "0.1",
|
|
60
|
+
"title": "My World",
|
|
61
|
+
"slug": "my-world",
|
|
62
|
+
"entry": "index.html",
|
|
63
|
+
"maxPlayers": 1,
|
|
64
|
+
"permissions": ["auth.profile"],
|
|
65
|
+
"supportsMobile": true,
|
|
66
|
+
"requiresAuth": false,
|
|
67
|
+
"contentRating": "everyone"
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Rules that commonly bite:
|
|
72
|
+
- `slug`: 3–50 chars, lowercase letters/digits/hyphens, no leading/trailing hyphen, **globally unique**. Pick something distinctive.
|
|
73
|
+
- `entry` must exist in the built output and be an `.html` file.
|
|
74
|
+
- Only declare permissions you use; `auth.profile` is the only one in v0.1.
|
|
75
|
+
- Read `helix://docs/manifest` for every field and the bundle limits.
|
|
76
|
+
|
|
77
|
+
## index.html
|
|
78
|
+
|
|
79
|
+
```html
|
|
80
|
+
<!doctype html>
|
|
81
|
+
<html lang="en">
|
|
82
|
+
<head>
|
|
83
|
+
<meta charset="utf-8" />
|
|
84
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
85
|
+
<title>My World</title>
|
|
86
|
+
<style>html, body { margin: 0; height: 100%; overflow: hidden; background: #0a0a12; }</style>
|
|
87
|
+
</head>
|
|
88
|
+
<body>
|
|
89
|
+
<script type="module" src="/src/main.ts"></script>
|
|
90
|
+
</body>
|
|
91
|
+
</html>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## src/main.ts — SDK integration pattern
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
import * as THREE from 'three';
|
|
98
|
+
import { Helix } from '@hypersoniclabs/helix-sdk';
|
|
99
|
+
import type { HelixUser } from '@hypersoniclabs/helix-sdk'; // type-only import — required
|
|
100
|
+
|
|
101
|
+
// 1. Build your scene/game first so the world renders even without identity.
|
|
102
|
+
|
|
103
|
+
// 2. Initialize the SDK once, early:
|
|
104
|
+
const { embedded, user } = await Helix.init();
|
|
105
|
+
|
|
106
|
+
// 3. Use identity as an enhancement:
|
|
107
|
+
if (user) {
|
|
108
|
+
// greet the player: user.username, user.displayName, user.id (stable save key)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// 4. React to login/logout while running:
|
|
112
|
+
Helix.auth.onAuthChanged((nextUser: HelixUser | null) => {
|
|
113
|
+
// update HUD / game state — fires on overlay login AND logout
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// 5. Offer login at a natural moment (never required to render):
|
|
117
|
+
// try { await Helix.auth.requestLogin(); } catch { /* player declined — fine */ }
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Hard-won specifics:
|
|
121
|
+
- `import type { HelixUser }` — it is a type-only export; a value import breaks the build.
|
|
122
|
+
- The world MUST run standalone (`npm run dev` with no shell): `embedded` is false there and identity APIs return null. Never block rendering on identity unless the manifest sets `requiresAuth: true`.
|
|
123
|
+
- Never render your own login form — call `Helix.auth.requestLogin()` and the portal overlays the real one.
|
|
124
|
+
|
|
125
|
+
## Build, validate, publish
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
npm install
|
|
129
|
+
npm run build # → dist/ (contains helix.json, index.html, assets/)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Then use the MCP tools, in order:
|
|
133
|
+
1. `validate_world` with the **absolute path to `dist/`** — fix every reported problem.
|
|
134
|
+
2. `whoami` — confirm a creator login exists (if not, the human must run `helix login`).
|
|
135
|
+
3. `publish_world` with the same dist path — returns the public play URL.
|
|
136
|
+
|
|
137
|
+
Budget: ≤ 200 files, ≤ 25 MB per file, ≤ 50 MB total. Allowed types include html/js/css/json/wasm, images (png/jpg/webp/svg/ktx2), models (glb/gltf/bin), audio (mp3/ogg/wav), fonts.
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@helix3/helix-mcp",
|
|
3
|
+
"version": "0.2.2-helix3.14",
|
|
4
|
+
"description": "HELIX Instant MCP server — gives AI coding agents the platform contract: world recipes, manifest schema, validation, catalog discovery, and publishing.",
|
|
5
|
+
"type": "commonjs",
|
|
6
|
+
"main": "dist/server.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"helix-mcp": "dist/server.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"docs"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc -p tsconfig.build.json",
|
|
16
|
+
"lint": "eslint \"src/**/*.ts\"",
|
|
17
|
+
"test": "node scripts/smoke.mjs"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@hypersoniclabs/helix-cli": "npm:@helix3/helix-cli@0.1.4-helix3.24",
|
|
21
|
+
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
22
|
+
"zod": "^3.24.0"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/node": "^22.10.0",
|
|
26
|
+
"typescript": "~5.7.3"
|
|
27
|
+
},
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public",
|
|
31
|
+
"registry": "https://registry.npmjs.org"
|
|
32
|
+
}
|
|
33
|
+
}
|