@okostream/mcp 0.12.7 → 0.12.8
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/dist/server.js +63 -21
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -116224,7 +116224,7 @@ function sanitizeScopes(scopes) {
|
|
|
116224
116224
|
}
|
|
116225
116225
|
|
|
116226
116226
|
// build/version.js
|
|
116227
|
-
var OKO_MCP_VERSION = "0.12.
|
|
116227
|
+
var OKO_MCP_VERSION = "0.12.8";
|
|
116228
116228
|
|
|
116229
116229
|
// build/auth.js
|
|
116230
116230
|
var state = null;
|
|
@@ -116348,29 +116348,40 @@ async function exchangeApiKey() {
|
|
|
116348
116348
|
latestVersion: typeof data.latestVersion === "string" && parseVersion(data.latestVersion) ? data.latestVersion.trim() : null
|
|
116349
116349
|
};
|
|
116350
116350
|
}
|
|
116351
|
-
|
|
116351
|
+
function singleFlight(run) {
|
|
116352
|
+
let inFlight = null;
|
|
116353
|
+
return () => {
|
|
116354
|
+
inFlight ??= run().finally(() => {
|
|
116355
|
+
inFlight = null;
|
|
116356
|
+
});
|
|
116357
|
+
return inFlight;
|
|
116358
|
+
};
|
|
116359
|
+
}
|
|
116360
|
+
var refreshSession = singleFlight(async () => {
|
|
116352
116361
|
const now = Date.now();
|
|
116353
|
-
|
|
116354
|
-
|
|
116355
|
-
|
|
116356
|
-
|
|
116357
|
-
|
|
116358
|
-
throw new OkoAuthError("unavailable", "OKO MCP received an organizer session but could not initialize it. Reconnect and try again.");
|
|
116359
|
-
}
|
|
116360
|
-
state = {
|
|
116361
|
-
uid: exchanged.organizerUid,
|
|
116362
|
-
scopes: exchanged.scopes,
|
|
116363
|
-
expiresAt: now + exchanged.expiresIn * 1e3
|
|
116364
|
-
};
|
|
116365
|
-
if (exchanged.latestVersion)
|
|
116366
|
-
recordLatestPublishedVersion(exchanged.latestVersion);
|
|
116362
|
+
const exchanged = await exchangeApiKey();
|
|
116363
|
+
try {
|
|
116364
|
+
await signInWithCustomToken(auth, exchanged.customToken);
|
|
116365
|
+
} catch {
|
|
116366
|
+
throw new OkoAuthError("unavailable", "OKO MCP received an organizer session but could not initialize it. Reconnect and try again.");
|
|
116367
116367
|
}
|
|
116368
|
+
state = {
|
|
116369
|
+
uid: exchanged.organizerUid,
|
|
116370
|
+
scopes: exchanged.scopes,
|
|
116371
|
+
expiresAt: now + exchanged.expiresIn * 1e3
|
|
116372
|
+
};
|
|
116373
|
+
if (exchanged.latestVersion)
|
|
116374
|
+
recordLatestPublishedVersion(exchanged.latestVersion);
|
|
116375
|
+
return state;
|
|
116376
|
+
});
|
|
116377
|
+
async function ensureAuth(requiredScopes = []) {
|
|
116378
|
+
const current = state && Date.now() <= state.expiresAt - 5 * 60 * 1e3 && auth.currentUser ? state : await refreshSession();
|
|
116368
116379
|
for (const scope of requiredScopes) {
|
|
116369
|
-
if (!
|
|
116380
|
+
if (!current.scopes.includes(scope)) {
|
|
116370
116381
|
throw new OkoScopeError(scope);
|
|
116371
116382
|
}
|
|
116372
116383
|
}
|
|
116373
|
-
return
|
|
116384
|
+
return current;
|
|
116374
116385
|
}
|
|
116375
116386
|
function currentScopes() {
|
|
116376
116387
|
return state?.scopes ?? [];
|
|
@@ -116665,6 +116676,27 @@ async function responseBufferWithLimit(response, maxBytes) {
|
|
|
116665
116676
|
}
|
|
116666
116677
|
return Buffer.concat(chunks, total);
|
|
116667
116678
|
}
|
|
116679
|
+
function shareLinkHint(url) {
|
|
116680
|
+
let host = "";
|
|
116681
|
+
try {
|
|
116682
|
+
host = new URL(url).hostname.toLowerCase();
|
|
116683
|
+
} catch {
|
|
116684
|
+
return "";
|
|
116685
|
+
}
|
|
116686
|
+
if (host === "drive.google.com" || host === "docs.google.com") {
|
|
116687
|
+
return " This is a Google Drive page, not the file: share it as 'anyone with the link' and use https://drive.google.com/uc?export=download&id=<fileId>, or download the file and pass source.path.";
|
|
116688
|
+
}
|
|
116689
|
+
if (host.endsWith("disk.yandex.ru") || host.endsWith("disk.yandex.com") || host === "yadi.sk" || host.endsWith("disk.360.yandex.ru")) {
|
|
116690
|
+
return " This is a Yandex Disk page, not the file: use the direct download link from the page (\u0421\u043A\u0430\u0447\u0430\u0442\u044C \u2192 copy link), or download the file and pass source.path.";
|
|
116691
|
+
}
|
|
116692
|
+
if (host === "dropbox.com" || host.endsWith(".dropbox.com")) {
|
|
116693
|
+
return " This is a Dropbox page: replace ?dl=0 with ?dl=1 in the link, or download the file and pass source.path.";
|
|
116694
|
+
}
|
|
116695
|
+
if (host.endsWith("onedrive.live.com") || host === "1drv.ms" || host.endsWith("sharepoint.com")) {
|
|
116696
|
+
return " This is a OneDrive page: use its direct download link, or download the file and pass source.path.";
|
|
116697
|
+
}
|
|
116698
|
+
return " Use a direct link to the image file (right-click the image \u2192 copy image address), or download the file and pass source.path.";
|
|
116699
|
+
}
|
|
116668
116700
|
async function readRemoteImage(rawUrl, redirects = 0) {
|
|
116669
116701
|
if (redirects > REMOTE_IMAGE_MAX_REDIRECTS) {
|
|
116670
116702
|
throw new Error("Image URL has too many redirects.");
|
|
@@ -116697,7 +116729,7 @@ async function readRemoteImage(rawUrl, redirects = 0) {
|
|
|
116697
116729
|
}
|
|
116698
116730
|
const contentType = (response.headers.get("content-type") ?? "").split(";")[0]?.trim().toLowerCase();
|
|
116699
116731
|
if (!contentType || !contentType.startsWith("image/")) {
|
|
116700
|
-
throw new Error(
|
|
116732
|
+
throw new Error(`Image URL must return Content-Type image/* (got ${contentType || "none"}).${shareLinkHint(rawUrl)}`);
|
|
116701
116733
|
}
|
|
116702
116734
|
if (!ALLOWED_REMOTE_IMAGE_TYPES.has(contentType)) {
|
|
116703
116735
|
throw new Error(`Image URL Content-Type ${contentType} is not supported. Use JPEG, PNG, WEBP, GIF, or AVIF.`);
|
|
@@ -116760,6 +116792,12 @@ function serverFetchRefusal(error3) {
|
|
|
116760
116792
|
if (code === "functions/invalid-argument" && message.includes("Image payload is empty or too large")) {
|
|
116761
116793
|
return { reason: "server_without_url_support", message: "The OKO server release in use does not fetch URLs yet." };
|
|
116762
116794
|
}
|
|
116795
|
+
if (code === "functions/deadline-exceeded") {
|
|
116796
|
+
return { reason: "server_timeout", message: "The OKO server did not finish fetching the URL within its time limit." };
|
|
116797
|
+
}
|
|
116798
|
+
if (code === "functions/internal") {
|
|
116799
|
+
return { reason: "server_error", message: message && message !== "internal" ? message : "The OKO server failed while fetching the URL." };
|
|
116800
|
+
}
|
|
116763
116801
|
return null;
|
|
116764
116802
|
}
|
|
116765
116803
|
var SERVER_FETCH_NOTE = "Image fetched by the OKO server directly from the URL; this machine's network was not involved.";
|
|
@@ -118358,7 +118396,10 @@ function registerEventTools(server2) {
|
|
|
118358
118396
|
summary: "Read one OKO event visible to the organizer.",
|
|
118359
118397
|
args: ["eventId: OKO event document id."],
|
|
118360
118398
|
returns: "full event document fields plus id and public event URL.",
|
|
118361
|
-
examples: ["Use after oko_create_webinar to verify setup and return the event URL to the user."]
|
|
118399
|
+
examples: ["Use after oko_create_webinar to verify setup and return the event URL to the user."],
|
|
118400
|
+
notes: [
|
|
118401
|
+
"blocks.chat.mode is a legacy field written by older cabinet versions and read by nothing; chat visibility is blocks.chat.visibility (always | hidden). Ignore mode."
|
|
118402
|
+
]
|
|
118362
118403
|
}),
|
|
118363
118404
|
inputSchema: { eventId: eventIdField },
|
|
118364
118405
|
outputSchema: eventOutputSchema,
|
|
@@ -120474,7 +120515,7 @@ function registerWorkspaceTools(server2) {
|
|
|
120474
120515
|
description: toolDescription({
|
|
120475
120516
|
summary: "Accept a workspace invite code for the authenticated organizer.",
|
|
120476
120517
|
args: ["code: invite code from /invite/{code}.", "confirm: must be true."],
|
|
120477
|
-
returns: "success
|
|
120518
|
+
returns: "success, workspace id/name, and keptExistingPermissions: true when the organizer was already a member \u2014 an invite never changes existing permissions; the owner changes them with oko_update_workspace_member.",
|
|
120478
120519
|
examples: ["Use when the organizer wants to join a workspace from an invite code."]
|
|
120479
120520
|
}),
|
|
120480
120521
|
inputSchema: {
|
|
@@ -120483,6 +120524,7 @@ function registerWorkspaceTools(server2) {
|
|
|
120483
120524
|
},
|
|
120484
120525
|
outputSchema: external_exports.object({
|
|
120485
120526
|
success: external_exports.boolean(),
|
|
120527
|
+
keptExistingPermissions: external_exports.boolean().optional(),
|
|
120486
120528
|
workspace: external_exports.object({ id: external_exports.string(), name: external_exports.string() }).passthrough()
|
|
120487
120529
|
}).passthrough(),
|
|
120488
120530
|
annotations: writeTool
|