@okostream/mcp 0.7.0 → 0.7.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/CHANGELOG.md +16 -0
- package/README.md +73 -122
- package/dist/auth.js +11 -2
- package/dist/env.js +24 -8
- package/dist/guides.js +1 -1
- package/dist/server.js +6 -4
- package/dist/tools.js +3 -0
- package/dist/version.js +1 -0
- package/package.json +16 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.7.2 - 2026-07-23
|
|
4
|
+
|
|
5
|
+
- Replaced the maintainer-oriented npm README with a concise organizer setup,
|
|
6
|
+
capability, safety, image-access, and troubleshooting guide.
|
|
7
|
+
- Removed the private repository link and added public homepage, author, and
|
|
8
|
+
discovery metadata.
|
|
9
|
+
- Disabled local image reads until `OKO_IMAGE_ROOTS` explicitly lists trusted
|
|
10
|
+
directories.
|
|
11
|
+
- Added the MCP client version to API-key exchange requests so the platform can
|
|
12
|
+
introduce a controlled minimum-version gate in a separate auth release.
|
|
13
|
+
|
|
14
|
+
## 0.7.1 - 2026-07-22
|
|
15
|
+
|
|
16
|
+
- Refreshed transitive dependencies after new npm advisories without changing the MCP tool/resource/prompt surface.
|
|
17
|
+
- Kept the remaining Windows-only static-server advisory below the release threshold; OKO MCP continues to run over stdio.
|
|
18
|
+
|
|
3
19
|
## 0.7.0 - 2026-07-22
|
|
4
20
|
|
|
5
21
|
- Routed standard webinar analytics Start/End through the same idempotent server callables used by the dashboard.
|
package/README.md
CHANGED
|
@@ -1,20 +1,25 @@
|
|
|
1
|
-
# OKO MCP
|
|
1
|
+
# OKO MCP
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Control OKO Stream webinars from Claude, Codex, or another stdio MCP client.
|
|
4
|
+
Create webinar pages, configure audience blocks, manage live interactions, and
|
|
5
|
+
read analytics without switching to the organizer dashboard.
|
|
4
6
|
|
|
5
|
-
##
|
|
7
|
+
## Connect
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
2. Add the server to your MCP client config.
|
|
9
|
+
You need an OKO organizer account and Node.js 20.18.1 or newer.
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
1. Open [OKO MCP settings](https://okostream.app/app/mcp).
|
|
12
|
+
2. Create an access key and select only the permissions you need.
|
|
13
|
+
3. Add OKO to your MCP client.
|
|
14
|
+
|
|
15
|
+
### Claude Desktop or Claude Code
|
|
11
16
|
|
|
12
17
|
```json
|
|
13
18
|
{
|
|
14
19
|
"mcpServers": {
|
|
15
20
|
"oko": {
|
|
16
21
|
"command": "npx",
|
|
17
|
-
"args": ["-y", "@okostream/mcp"],
|
|
22
|
+
"args": ["-y", "@okostream/mcp@latest"],
|
|
18
23
|
"env": {
|
|
19
24
|
"OKO_API_KEY": "oko_sk_..."
|
|
20
25
|
}
|
|
@@ -23,160 +28,106 @@ Claude Desktop / Claude Code:
|
|
|
23
28
|
}
|
|
24
29
|
```
|
|
25
30
|
|
|
26
|
-
Codex
|
|
31
|
+
### Codex
|
|
27
32
|
|
|
28
33
|
```toml
|
|
29
34
|
[mcp_servers.oko]
|
|
30
35
|
command = "npx"
|
|
31
|
-
args = ["-y", "@okostream/mcp"]
|
|
36
|
+
args = ["-y", "@okostream/mcp@latest"]
|
|
32
37
|
|
|
33
38
|
[mcp_servers.oko.env]
|
|
34
39
|
OKO_API_KEY = "oko_sk_..."
|
|
35
40
|
```
|
|
36
41
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
OKO_EXCHANGE_URL=...
|
|
41
|
-
OKO_FIREBASE_API_KEY=...
|
|
42
|
-
OKO_FIREBASE_AUTH_DOMAIN=...
|
|
43
|
-
OKO_FIREBASE_DATABASE_URL=...
|
|
44
|
-
OKO_FIREBASE_CHAT_DB_URL=...
|
|
45
|
-
OKO_FIREBASE_PROJECT_ID=...
|
|
46
|
-
OKO_FIREBASE_STORAGE_BUCKET=...
|
|
47
|
-
OKO_FIREBASE_MESSAGING_SENDER_ID=...
|
|
48
|
-
OKO_FIREBASE_APP_ID=...
|
|
49
|
-
# Path-delimited allowlist for local image reads; defaults to the process cwd.
|
|
50
|
-
OKO_IMAGE_ROOTS=/trusted/assets:/another/trusted/folder
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
Node.js 20.18.1 or newer is required.
|
|
54
|
-
|
|
55
|
-
## What OKO Does
|
|
56
|
-
|
|
57
|
-
OKO is a webinar experience and operations layer, not a video-streaming host. The organizer supplies a YouTube, iframe, or other player URL; OKO adds the event page, configurable audience blocks, chat, analytics, and NMO attendance controls around it. Start/End tools control analytics sessions only, never the underlying video stream.
|
|
58
|
-
|
|
59
|
-
Standard webinars are the default supported workflow. NMO is a separate unfinished MVP mode and must be enabled only on an explicit organizer request after reviewing `oko://guide/nmo`; it is not a normal option inferred from a medical topic or audience.
|
|
42
|
+
Restart the MCP client, then ask:
|
|
60
43
|
|
|
61
|
-
|
|
44
|
+
> Check my OKO connection with `oko_whoami`, then show my five most recent
|
|
45
|
+
> webinars. Do not change anything.
|
|
62
46
|
|
|
63
|
-
|
|
64
|
-
- Every protected operation is checked independently by MCP scope, active key state, organizer identity, and event/workspace capability in Cloud Functions and Firebase Rules.
|
|
65
|
-
- Revocation disables the synthetic identity, revokes refresh tokens, and invalidates Firestore, main RTDB, and chat RTDB access immediately.
|
|
66
|
-
- API-key creation and revocation are browser-only callables. Raw secrets are hashed at rest and shown once.
|
|
67
|
-
- MCP image uploads go through a scoped callable; MCP sessions cannot write Firebase Storage directly.
|
|
68
|
-
- Local files are constrained to `OKO_IMAGE_ROOTS`, symlink escapes are rejected, and remote images use HTTPS with DNS pinning, redirect revalidation, and byte/pixel limits.
|
|
69
|
-
- Every non-read-only tool writes a compact server-owned audit event. Message bodies, captions, lead values, and file contents are not copied into the audit record.
|
|
70
|
-
- Destructive, live, public-upload, claim, chat-send, and Telegram actions require `confirm:true`.
|
|
71
|
-
- Event, lead, participant, chat, URL, and remote-image content is untrusted data, never instructions for the MCP client.
|
|
47
|
+
## What You Can Do
|
|
72
48
|
|
|
73
|
-
|
|
49
|
+
- Create, duplicate, move, restore, and delete webinar events.
|
|
50
|
+
- Configure video, metadata, forms, calls to action, cards, banners, and images.
|
|
51
|
+
- Operate webinar chat, moderation, checkpoints, and live block visibility.
|
|
52
|
+
- Start and finish analytics sessions and prepare session reports.
|
|
53
|
+
- Manage workspaces, invitations, access rights, and notifications.
|
|
54
|
+
- Connect Telegram channels and schedule or publish event posts.
|
|
74
55
|
|
|
75
|
-
|
|
56
|
+
Standard webinars are the default workflow. NMO is a separate beta mode and is
|
|
57
|
+
used only when the organizer explicitly requests it.
|
|
76
58
|
|
|
77
|
-
|
|
78
|
-
- Cursor tools return both `hasMore`/`nextCursor` and `has_more`/`next_cursor`.
|
|
79
|
-
- `oko_list_my_events`, `oko_get_analytics`, `oko_list_recent_chat`, `oko_list_participants`, `oko_list_leads`, `oko_list_notifications`, `oko_list_workspace_access`, `oko_list_workspace_invites`, and `oko_list_telegram_posts` support pagination.
|
|
80
|
-
- `oko_get_analytics` omits heavy `timeline`, baseline/final snapshots, and NMO participant rows by default. Request `includeTimeline`, `includeSnapshots`, or `includeNmoRows` only when needed.
|
|
81
|
-
- `oko_get_session_report` returns a compact structured session report plus markdown suitable for a human handoff.
|
|
82
|
-
- Standard webinar Start/End uses server-owned Analytics v3 callables shared with the dashboard; completed reports include explicit data-quality markers. NMO remains a separate unfinished special-mode workflow.
|
|
83
|
-
- Oversized responses are truncated with `truncated: true` and a `truncationMessage`.
|
|
59
|
+
## Images
|
|
84
60
|
|
|
85
|
-
|
|
61
|
+
Public HTTPS image URLs work without additional configuration.
|
|
86
62
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
63
|
+
Local file access is disabled by default. To let OKO MCP upload images from your
|
|
64
|
+
computer, add an explicit trusted-directory allowlist to the client config.
|
|
65
|
+
Use a dedicated folder rather than your home directory.
|
|
90
66
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
## Local Development
|
|
94
|
-
|
|
95
|
-
```bash
|
|
96
|
-
cd mcp
|
|
97
|
-
npm install
|
|
98
|
-
npm run build
|
|
99
|
-
npm start
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
Local config without npm publishing:
|
|
67
|
+
### Claude with Local Images
|
|
103
68
|
|
|
104
69
|
```json
|
|
105
70
|
{
|
|
106
71
|
"mcpServers": {
|
|
107
72
|
"oko": {
|
|
108
|
-
"command": "
|
|
109
|
-
"args": ["
|
|
73
|
+
"command": "npx",
|
|
74
|
+
"args": ["-y", "@okostream/mcp@latest"],
|
|
110
75
|
"env": {
|
|
111
|
-
"OKO_API_KEY": "oko_sk_..."
|
|
76
|
+
"OKO_API_KEY": "oko_sk_...",
|
|
77
|
+
"OKO_IMAGE_ROOTS": "/Users/you/Documents/OKO"
|
|
112
78
|
}
|
|
113
79
|
}
|
|
114
80
|
}
|
|
115
81
|
}
|
|
116
82
|
```
|
|
117
83
|
|
|
118
|
-
|
|
84
|
+
### Codex with Local Images
|
|
119
85
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
- `oko_whoami`, `oko_list_workspaces`, `oko_list_my_events`, `oko_get_event`
|
|
125
|
-
- `oko_validate_event_setup`
|
|
126
|
-
- `oko_update_profile`, `oko_list_notifications`, `oko_mark_notifications_read`
|
|
127
|
-
- `oko_get_live_state`, `oko_get_analytics`, `oko_get_session_report`, `oko_list_recent_chat`, `oko_list_participants`, `oko_list_leads`, `oko_delete_lead`
|
|
128
|
-
|
|
129
|
-
Event/setup/media tools:
|
|
130
|
-
|
|
131
|
-
- `oko_create_webinar`, `oko_update_event`, `oko_delete_event` (30-day trash compatibility alias)
|
|
132
|
-
- `oko_trash_event`, `oko_restore_event`, `oko_delete_event_permanently`
|
|
133
|
-
- `oko_duplicate_event`, `oko_move_event`
|
|
134
|
-
- `oko_configure_blocks`, `oko_configure_cards`
|
|
135
|
-
- `oko_upload_image`, `oko_upload_card_images_batch`, `oko_wait_for_image_variants`, `oko_delete_image`
|
|
136
|
-
|
|
137
|
-
Live/session/chat/NMO tools:
|
|
86
|
+
```toml
|
|
87
|
+
[mcp_servers.oko]
|
|
88
|
+
command = "npx"
|
|
89
|
+
args = ["-y", "@okostream/mcp@latest"]
|
|
138
90
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
- `oko_add_nmo_participant`, `oko_import_nmo_participants`, `oko_remove_nmo_participant`
|
|
91
|
+
[mcp_servers.oko.env]
|
|
92
|
+
OKO_API_KEY = "oko_sk_..."
|
|
93
|
+
OKO_IMAGE_ROOTS = "/Users/you/Documents/OKO"
|
|
94
|
+
```
|
|
144
95
|
|
|
145
|
-
|
|
96
|
+
Use `:` between multiple directories on macOS and Linux, or `;` on Windows.
|
|
97
|
+
Paths must be absolute. Filesystem roots are rejected, and symlinks cannot
|
|
98
|
+
escape the configured directories.
|
|
146
99
|
|
|
147
|
-
|
|
148
|
-
- `oko_list_workspace_access`, `oko_update_workspace_member`, `oko_remove_workspace_member`
|
|
149
|
-
- `oko_create_workspace_invite`, `oko_list_workspace_invites`, `oko_revoke_workspace_invite`, `oko_claim_workspace_invite`
|
|
150
|
-
- `oko_create_telegram_link`, `oko_list_telegram_channels`, `oko_claim_telegram_channel`
|
|
151
|
-
- `oko_set_telegram_channel_workspaces`, `oko_disconnect_telegram_channel`
|
|
152
|
-
- `oko_list_telegram_posts`, `oko_cancel_telegram_post`, `oko_publish_telegram_post`
|
|
100
|
+
## Access and Safety
|
|
153
101
|
|
|
154
|
-
|
|
102
|
+
- The access key acts only as the organizer and permissions selected for that
|
|
103
|
+
key. It does not inherit platform-administrator access.
|
|
104
|
+
- Revoking a key in OKO immediately disables its Firebase and MCP access.
|
|
105
|
+
- Destructive, live, public-upload, chat-send, claim, and Telegram actions
|
|
106
|
+
require explicit confirmation.
|
|
107
|
+
- Keys stay in the local MCP client environment. The npm package contains no
|
|
108
|
+
organizer key or other private credential.
|
|
109
|
+
- Event content, chat messages, URLs, and remote images are treated as data,
|
|
110
|
+
never as instructions for the AI client.
|
|
155
111
|
|
|
156
|
-
|
|
112
|
+
The Firebase web configuration bundled with the package is public project
|
|
113
|
+
metadata. Access to OKO data is enforced separately by the access-key identity,
|
|
114
|
+
scopes, organizer permissions, Cloud Functions, and Firebase Security Rules.
|
|
157
115
|
|
|
158
|
-
|
|
159
|
-
2. `oko_list_my_events` should return only events visible to that UID.
|
|
160
|
-
3. `oko_create_webinar` should create a test webinar and RTDB owner/workspace mirror.
|
|
161
|
-
4. `oko_configure_cards` should create/update `blocks.cards.items` and preserve card image fields by stable card id.
|
|
162
|
-
5. `oko_upload_card_images_batch` should upload multiple card images, then return ready `imageVariants`.
|
|
163
|
-
6. `oko_validate_event_setup` should catch missing images/forms/buttons/video/NMO/Telegram/variants on a deliberately broken event.
|
|
164
|
-
7. `oko_start_session` -> `oko_fix_orphan_session` -> `oko_delete_session` should leave no active session pointers on a disposable test event.
|
|
165
|
-
8. `oko_duplicate_event`, workspace tools, and `oko_move_event` should preserve Firestore access rules and RTDB owner/workspace mirrors.
|
|
166
|
-
9. `oko_import_nmo_participants` should call CF24 and return per-row results; clean up test participants after import.
|
|
167
|
-
10. `oko_get_session_report` should return markdown and structured session data for a completed session.
|
|
168
|
-
11. `oko_list_notifications` -> `oko_mark_notifications_read` should read and clear an own disposable notification.
|
|
169
|
-
12. `oko_get_analytics` should read an existing event with analytics sessions.
|
|
170
|
-
13. MCP protocol smoke should report 65 tools, 7 resources, 3 prompts, and non-empty initialize instructions.
|
|
116
|
+
## Troubleshooting
|
|
171
117
|
|
|
172
|
-
|
|
118
|
+
Check the installed package:
|
|
173
119
|
|
|
174
120
|
```bash
|
|
175
|
-
npx -y @okostream/mcp --help
|
|
121
|
+
npx -y @okostream/mcp@latest --help
|
|
176
122
|
```
|
|
177
123
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
124
|
+
- **Invalid or revoked key:** create a new key in
|
|
125
|
+
[OKO MCP settings](https://okostream.app/app/mcp) and replace
|
|
126
|
+
`OKO_API_KEY`.
|
|
127
|
+
- **Claude reports `Unexpected token`:** make sure the config uses
|
|
128
|
+
`@okostream/mcp@latest`, fully quit the MCP client, and open it again.
|
|
129
|
+
- **A local image is rejected:** add its directory to `OKO_IMAGE_ROOTS`, then
|
|
130
|
+
restart the client.
|
|
181
131
|
|
|
182
|
-
|
|
132
|
+
Settings, key management, and installation snippets are always available at
|
|
133
|
+
[okostream.app/app/mcp](https://okostream.app/app/mcp).
|
package/dist/auth.js
CHANGED
|
@@ -2,18 +2,27 @@ import { signInWithCustomToken } from "firebase/auth";
|
|
|
2
2
|
import { auth } from "./firebase.js";
|
|
3
3
|
import { env } from "./env.js";
|
|
4
4
|
import { sanitizeScopes } from "./scopes.js";
|
|
5
|
+
import { OKO_MCP_VERSION } from "./version.js";
|
|
5
6
|
let state = null;
|
|
6
7
|
async function exchangeApiKey() {
|
|
7
8
|
const response = await fetch(env.exchangeUrl, {
|
|
8
9
|
method: "POST",
|
|
9
10
|
headers: { "content-type": "application/json" },
|
|
10
|
-
body: JSON.stringify({ apiKey: env.apiKey }),
|
|
11
|
+
body: JSON.stringify({ apiKey: env.apiKey, clientVersion: OKO_MCP_VERSION }),
|
|
11
12
|
});
|
|
12
13
|
if (!response.ok) {
|
|
13
14
|
const status = response.status;
|
|
15
|
+
const errorBody = await response.json().catch(() => ({}));
|
|
16
|
+
if (status === 426) {
|
|
17
|
+
const minimumVersion = typeof errorBody.minimumVersion === "string"
|
|
18
|
+
? errorBody.minimumVersion
|
|
19
|
+
: "the current release";
|
|
20
|
+
throw new Error(`OKO MCP ${OKO_MCP_VERSION} is no longer supported. Update to @okostream/mcp@latest ` +
|
|
21
|
+
`(minimum ${minimumVersion}) and restart the MCP client.`);
|
|
22
|
+
}
|
|
14
23
|
throw new Error(status === 401
|
|
15
24
|
? "OKO API key is invalid or revoked. Create a fresh key in OKO Settings and set OKO_API_KEY."
|
|
16
|
-
: `OKO API key exchange failed with HTTP ${status}. Check
|
|
25
|
+
: `OKO API key exchange failed with HTTP ${status}. Check your connection and try again.`);
|
|
17
26
|
}
|
|
18
27
|
const data = await response.json();
|
|
19
28
|
if (typeof data.customToken !== "string") {
|
package/dist/env.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { config } from "dotenv";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
|
-
import { delimiter, join, resolve } from "node:path";
|
|
3
|
+
import { delimiter, isAbsolute, join, parse, resolve } from "node:path";
|
|
4
4
|
import { DEFAULT_EXCHANGE_URL, DEFAULT_FIREBASE_CONFIG } from "./firebaseDefaults.js";
|
|
5
5
|
config({ path: join(homedir(), ".env"), quiet: true });
|
|
6
6
|
function readEnv(...names) {
|
|
@@ -19,15 +19,31 @@ function readEnvWithDefault(defaultValue, ...names) {
|
|
|
19
19
|
}
|
|
20
20
|
return defaultValue;
|
|
21
21
|
}
|
|
22
|
+
function readImageRoots() {
|
|
23
|
+
const rawRoots = process.env.OKO_IMAGE_ROOTS?.trim();
|
|
24
|
+
if (!rawRoots)
|
|
25
|
+
return [];
|
|
26
|
+
return rawRoots.split(delimiter).map((value) => {
|
|
27
|
+
const root = value.trim();
|
|
28
|
+
if (!root) {
|
|
29
|
+
throw new Error("OKO_IMAGE_ROOTS contains an empty directory entry.");
|
|
30
|
+
}
|
|
31
|
+
const expanded = root === "~" || root.startsWith("~/")
|
|
32
|
+
? join(homedir(), root.slice(2))
|
|
33
|
+
: root;
|
|
34
|
+
if (!isAbsolute(expanded)) {
|
|
35
|
+
throw new Error(`OKO_IMAGE_ROOTS entries must be absolute paths: ${root}`);
|
|
36
|
+
}
|
|
37
|
+
const resolved = resolve(expanded);
|
|
38
|
+
if (resolved === parse(resolved).root) {
|
|
39
|
+
throw new Error("OKO_IMAGE_ROOTS must not allow an entire filesystem root.");
|
|
40
|
+
}
|
|
41
|
+
return resolved;
|
|
42
|
+
});
|
|
43
|
+
}
|
|
22
44
|
export const env = {
|
|
23
45
|
apiKey: readEnv("OKO_API_KEY"),
|
|
24
|
-
imageRoots: (
|
|
25
|
-
.split(delimiter)
|
|
26
|
-
.map((root) => root.trim())
|
|
27
|
-
.map((root) => root === "~" || root.startsWith("~/")
|
|
28
|
-
? resolve(join(homedir(), root.slice(2)))
|
|
29
|
-
: resolve(root))
|
|
30
|
-
.filter(Boolean),
|
|
46
|
+
imageRoots: readImageRoots(),
|
|
31
47
|
exchangeUrl: readEnvWithDefault(DEFAULT_EXCHANGE_URL, "OKO_EXCHANGE_URL"),
|
|
32
48
|
firebase: {
|
|
33
49
|
apiKey: readEnvWithDefault(DEFAULT_FIREBASE_CONFIG.apiKey, "OKO_FIREBASE_API_KEY", "NEXT_PUBLIC_FIREBASE_API_KEY"),
|
package/dist/guides.js
CHANGED
|
@@ -112,7 +112,7 @@ const GUIDE_RESOURCES = [
|
|
|
112
112
|
"- MCP image bytes cross a scoped callable; MCP sessions cannot write Firebase Storage directly.",
|
|
113
113
|
"- Every write tool emits a server-owned audit record without storing message/caption/body content.",
|
|
114
114
|
"- Destructive, live, or external side-effect tools require explicit `confirm:true`.",
|
|
115
|
-
"- Local image
|
|
115
|
+
"- Local image reads are disabled by default. `OKO_IMAGE_ROOTS` enables a path-delimited allowlist; symlink escapes are blocked.",
|
|
116
116
|
"- Remote image downloads require public HTTPS, pin the validated DNS address, revalidate redirects, and enforce byte/pixel limits.",
|
|
117
117
|
"- Wrong API-key exchanges are counted per keyId; after 10 failures the keyId is locked for 15 minutes.",
|
|
118
118
|
"",
|
package/dist/server.js
CHANGED
|
@@ -3,19 +3,21 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
4
|
import { OKO_MCP_INSTRUCTIONS, registerGuides } from "./guides.js";
|
|
5
5
|
import { registerTools } from "./tools.js";
|
|
6
|
+
import { OKO_MCP_VERSION } from "./version.js";
|
|
6
7
|
if (process.argv.includes("--help")) {
|
|
7
8
|
process.stdout.write([
|
|
8
9
|
"OKO MCP Server",
|
|
9
10
|
"",
|
|
10
11
|
"Usage:",
|
|
11
12
|
" oko-mcp",
|
|
12
|
-
" npx -y @okostream/mcp",
|
|
13
|
+
" npx -y @okostream/mcp@latest",
|
|
13
14
|
"",
|
|
14
15
|
"Required env:",
|
|
15
16
|
" OKO_API_KEY=oko_sk_...",
|
|
16
17
|
"",
|
|
17
|
-
"Optional
|
|
18
|
-
"
|
|
18
|
+
"Optional local image access:",
|
|
19
|
+
" OKO_IMAGE_ROOTS=/trusted/image/directory",
|
|
20
|
+
" Local file reads are disabled unless this allowlist is set.",
|
|
19
21
|
"",
|
|
20
22
|
"The server speaks MCP over stdio. Do not run it manually before connecting a client.",
|
|
21
23
|
].join("\n") + "\n");
|
|
@@ -23,7 +25,7 @@ if (process.argv.includes("--help")) {
|
|
|
23
25
|
}
|
|
24
26
|
const server = new McpServer({
|
|
25
27
|
name: "oko-mcp-server",
|
|
26
|
-
version:
|
|
28
|
+
version: OKO_MCP_VERSION,
|
|
27
29
|
}, {
|
|
28
30
|
instructions: OKO_MCP_INSTRUCTIONS,
|
|
29
31
|
});
|
package/dist/tools.js
CHANGED
|
@@ -499,6 +499,9 @@ async function readRemoteImage(rawUrl, redirects = 0) {
|
|
|
499
499
|
}
|
|
500
500
|
}
|
|
501
501
|
async function readLocalImage(inputPath) {
|
|
502
|
+
if (env.imageRoots.length === 0) {
|
|
503
|
+
throw new Error("Local image reads are disabled. Set OKO_IMAGE_ROOTS to an explicit trusted directory and restart the MCP client.");
|
|
504
|
+
}
|
|
502
505
|
const filePath = await realpath(resolveLocalImagePath(inputPath));
|
|
503
506
|
const roots = await Promise.all(env.imageRoots.map(async (root) => {
|
|
504
507
|
try {
|
package/dist/version.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const OKO_MCP_VERSION = "0.7.2";
|
package/package.json
CHANGED
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@okostream/mcp",
|
|
3
|
-
"version": "0.7.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.7.2",
|
|
4
|
+
"description": "Control OKO Stream webinars from Claude, Codex, and other MCP clients.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "OKO Stream",
|
|
8
|
+
"url": "https://okostream.app"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://okostream.app/app/mcp",
|
|
11
|
+
"keywords": [
|
|
12
|
+
"mcp",
|
|
13
|
+
"model-context-protocol",
|
|
14
|
+
"webinar",
|
|
15
|
+
"webinars",
|
|
16
|
+
"claude",
|
|
17
|
+
"codex",
|
|
18
|
+
"okostream"
|
|
19
|
+
],
|
|
6
20
|
"type": "module",
|
|
7
21
|
"main": "dist/server.js",
|
|
8
|
-
"repository": {
|
|
9
|
-
"type": "git",
|
|
10
|
-
"url": "git+https://github.com/BelfanioXL/okostreamcore.git",
|
|
11
|
-
"directory": "mcp"
|
|
12
|
-
},
|
|
13
22
|
"publishConfig": {
|
|
14
23
|
"access": "public"
|
|
15
24
|
},
|