@chrischall/gemini-mcp 1.12.0 → 1.13.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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/dist/bundle.js +476 -152
- package/dist/jobs.js +2 -2
- package/dist/tools/_confirm.js +2 -2
- package/dist/tools/files.js +6 -6
- package/dist/tools/jobs.js +2 -2
- package/dist/tools/library.js +7 -7
- package/dist/tools/models.js +2 -2
- package/dist/tools/shared.js +2 -2
- package/dist/tools/uploads.js +2 -2
- package/dist/tools/usage.js +2 -2
- package/dist/version.js +1 -1
- package/mint.yaml +6 -0
- package/package.json +2 -2
- package/server.json +2 -2
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
},
|
|
8
8
|
"metadata": {
|
|
9
9
|
"description": "MCP server for Google Gemini image generation and editing — generate and edit images via the Gemini API",
|
|
10
|
-
"version": "1.
|
|
10
|
+
"version": "1.13.0"
|
|
11
11
|
},
|
|
12
12
|
"plugins": [
|
|
13
13
|
{
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"displayName": "Gemini Images",
|
|
16
16
|
"source": "./",
|
|
17
17
|
"description": "Generate and edit images with Google Gemini image models (Nano Banana / Nano Banana Pro) via natural language prompts",
|
|
18
|
-
"version": "1.
|
|
18
|
+
"version": "1.13.0",
|
|
19
19
|
"author": {
|
|
20
20
|
"name": "Chris Hall"
|
|
21
21
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gemini-mcp",
|
|
3
3
|
"displayName": "Gemini Images",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.13.0",
|
|
5
5
|
"description": "MCP server for Google Gemini image generation and editing — generate and edit images via the Gemini API",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Chris Hall",
|
package/dist/bundle.js
CHANGED
|
@@ -26542,9 +26542,28 @@ var require_utils = __commonJS({
|
|
|
26542
26542
|
"use strict";
|
|
26543
26543
|
var isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu);
|
|
26544
26544
|
var isIPv4 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u);
|
|
26545
|
+
var isPort = RegExp.prototype.test.bind(/^\d*$/u);
|
|
26545
26546
|
var isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu);
|
|
26546
26547
|
var isUnreserved = RegExp.prototype.test.bind(/^[\da-z\-._~]$/iu);
|
|
26547
|
-
var isPathCharacter = RegExp.prototype.test.bind(/^[
|
|
26548
|
+
var isPathCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/]$/u);
|
|
26549
|
+
var isQueryFragmentCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/?]$/u);
|
|
26550
|
+
var isUserinfoCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:]$/u);
|
|
26551
|
+
var BYTE_HEX = new Array(256);
|
|
26552
|
+
{
|
|
26553
|
+
const HEX_DIGITS = "0123456789ABCDEF";
|
|
26554
|
+
for (let i = 0; i < 256; i++) {
|
|
26555
|
+
BYTE_HEX[i] = "%" + HEX_DIGITS[i >> 4] + HEX_DIGITS[i & 15];
|
|
26556
|
+
}
|
|
26557
|
+
}
|
|
26558
|
+
function percentEncodeNonAscii(cp) {
|
|
26559
|
+
if (cp < 2048) {
|
|
26560
|
+
return BYTE_HEX[192 | cp >> 6] + BYTE_HEX[128 | cp & 63];
|
|
26561
|
+
}
|
|
26562
|
+
if (cp < 65536) {
|
|
26563
|
+
return BYTE_HEX[224 | cp >> 12] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
|
|
26564
|
+
}
|
|
26565
|
+
return BYTE_HEX[240 | cp >> 18] + BYTE_HEX[128 | cp >> 12 & 63] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
|
|
26566
|
+
}
|
|
26548
26567
|
function stringArrayToHexStripped(input) {
|
|
26549
26568
|
let acc = "";
|
|
26550
26569
|
let code = 0;
|
|
@@ -26569,91 +26588,105 @@ var require_utils = __commonJS({
|
|
|
26569
26588
|
}
|
|
26570
26589
|
return acc;
|
|
26571
26590
|
}
|
|
26591
|
+
var isHextet = RegExp.prototype.test.bind(/^[\dA-Fa-f]{1,4}$/);
|
|
26592
|
+
var isIPvFuture = RegExp.prototype.test.bind(/^[vV][\dA-Fa-f]+\.[A-Za-z\d\-._~!$&'()*+,;=:]+$/);
|
|
26593
|
+
var isZoneCharacter = RegExp.prototype.test.bind(/^[A-Za-z\d\-._~]$/);
|
|
26572
26594
|
var nonSimpleDomain = RegExp.prototype.test.bind(/[^!"$&'()*+,\-.;=_`a-z{}~]/u);
|
|
26573
|
-
function
|
|
26574
|
-
|
|
26575
|
-
|
|
26576
|
-
|
|
26577
|
-
|
|
26578
|
-
|
|
26579
|
-
|
|
26580
|
-
if (hex3 !== "") {
|
|
26581
|
-
address.push(hex3);
|
|
26582
|
-
} else {
|
|
26583
|
-
output.error = true;
|
|
26584
|
-
return false;
|
|
26595
|
+
function isZoneIdentifier(zone) {
|
|
26596
|
+
if (zone.length === 0) return false;
|
|
26597
|
+
for (let i = 0; i < zone.length; i++) {
|
|
26598
|
+
if (isZoneCharacter(zone[i])) continue;
|
|
26599
|
+
if (zone[i] === "%" && i + 2 < zone.length && isHexPair(zone.slice(i + 1, i + 3))) {
|
|
26600
|
+
i += 2;
|
|
26601
|
+
continue;
|
|
26585
26602
|
}
|
|
26586
|
-
|
|
26603
|
+
return false;
|
|
26587
26604
|
}
|
|
26588
26605
|
return true;
|
|
26589
26606
|
}
|
|
26590
|
-
function
|
|
26591
|
-
let
|
|
26592
|
-
|
|
26593
|
-
|
|
26594
|
-
|
|
26595
|
-
let
|
|
26596
|
-
|
|
26597
|
-
|
|
26598
|
-
|
|
26599
|
-
|
|
26600
|
-
|
|
26601
|
-
|
|
26602
|
-
}
|
|
26603
|
-
if (cursor === ":") {
|
|
26604
|
-
if (endipv6Encountered === true) {
|
|
26605
|
-
endIpv6 = true;
|
|
26606
|
-
}
|
|
26607
|
-
if (!consume(buffer, address, output)) {
|
|
26608
|
-
break;
|
|
26609
|
-
}
|
|
26610
|
-
if (++tokenCount > 7) {
|
|
26611
|
-
output.error = true;
|
|
26612
|
-
break;
|
|
26613
|
-
}
|
|
26614
|
-
if (i > 0 && input[i - 1] === ":") {
|
|
26615
|
-
endipv6Encountered = true;
|
|
26607
|
+
function compressIPv6ZeroRun(hextets) {
|
|
26608
|
+
let bestStart = -1;
|
|
26609
|
+
let bestLength = 0;
|
|
26610
|
+
let runStart = -1;
|
|
26611
|
+
let runLength = 0;
|
|
26612
|
+
for (let i = 0; i < hextets.length; i++) {
|
|
26613
|
+
if (hextets[i] === "0") {
|
|
26614
|
+
if (runStart === -1) runStart = i;
|
|
26615
|
+
runLength++;
|
|
26616
|
+
if (runLength > bestLength) {
|
|
26617
|
+
bestLength = runLength;
|
|
26618
|
+
bestStart = runStart;
|
|
26616
26619
|
}
|
|
26617
|
-
address.push(":");
|
|
26618
|
-
continue;
|
|
26619
|
-
} else if (cursor === "%") {
|
|
26620
|
-
if (!consume(buffer, address, output)) {
|
|
26621
|
-
break;
|
|
26622
|
-
}
|
|
26623
|
-
consume = consumeIsZone;
|
|
26624
26620
|
} else {
|
|
26625
|
-
|
|
26621
|
+
runStart = -1;
|
|
26622
|
+
runLength = 0;
|
|
26623
|
+
}
|
|
26624
|
+
}
|
|
26625
|
+
if (bestLength < 2) return hextets.join(":");
|
|
26626
|
+
const head = hextets.slice(0, bestStart).join(":");
|
|
26627
|
+
const tail = hextets.slice(bestStart + bestLength).join(":");
|
|
26628
|
+
return head + "::" + tail;
|
|
26629
|
+
}
|
|
26630
|
+
function normalizeIPv6Address(input) {
|
|
26631
|
+
const compression = input.indexOf("::");
|
|
26632
|
+
if (compression !== -1 && input.indexOf("::", compression + 1) !== -1) return void 0;
|
|
26633
|
+
const left = compression === -1 ? input.split(":") : input.slice(0, compression).split(":");
|
|
26634
|
+
const right = compression === -1 ? [] : input.slice(compression + 2).split(":");
|
|
26635
|
+
if (compression !== -1) {
|
|
26636
|
+
if (left.length === 1 && left[0] === "") left.length = 0;
|
|
26637
|
+
if (right.length === 1 && right[0] === "") right.length = 0;
|
|
26638
|
+
}
|
|
26639
|
+
const parts = left.concat(right);
|
|
26640
|
+
let hextetCount = 0;
|
|
26641
|
+
for (let i = 0; i < parts.length; i++) {
|
|
26642
|
+
const part = parts[i];
|
|
26643
|
+
if (part === "") return void 0;
|
|
26644
|
+
if (part.indexOf(".") !== -1) {
|
|
26645
|
+
if (i !== parts.length - 1 || compression !== -1 && right.length === 0 || !isIPv4(part)) return void 0;
|
|
26646
|
+
hextetCount += 2;
|
|
26626
26647
|
continue;
|
|
26627
26648
|
}
|
|
26649
|
+
if (!isHextet(part)) return void 0;
|
|
26650
|
+
parts[i] = parseInt(part, 16).toString(16);
|
|
26651
|
+
hextetCount++;
|
|
26628
26652
|
}
|
|
26629
|
-
if (
|
|
26630
|
-
if (
|
|
26631
|
-
|
|
26632
|
-
} else if (endIpv6) {
|
|
26633
|
-
address.push(buffer.join(""));
|
|
26634
|
-
} else {
|
|
26635
|
-
address.push(stringArrayToHexStripped(buffer));
|
|
26636
|
-
}
|
|
26653
|
+
if (compression === -1) {
|
|
26654
|
+
if (hextetCount !== 8) return void 0;
|
|
26655
|
+
return compressIPv6ZeroRun(parts);
|
|
26637
26656
|
}
|
|
26638
|
-
|
|
26639
|
-
|
|
26657
|
+
if (hextetCount >= 8) return void 0;
|
|
26658
|
+
const expanded = parts.slice(0, left.length);
|
|
26659
|
+
for (let i = hextetCount; i < 8; i++) expanded.push("0");
|
|
26660
|
+
for (let i = left.length; i < parts.length; i++) expanded.push(parts[i]);
|
|
26661
|
+
return compressIPv6ZeroRun(expanded);
|
|
26640
26662
|
}
|
|
26641
26663
|
function normalizeIPv6(host) {
|
|
26642
|
-
|
|
26643
|
-
|
|
26644
|
-
}
|
|
26645
|
-
|
|
26646
|
-
if (
|
|
26647
|
-
|
|
26648
|
-
|
|
26649
|
-
|
|
26650
|
-
|
|
26651
|
-
|
|
26652
|
-
|
|
26653
|
-
|
|
26654
|
-
|
|
26655
|
-
|
|
26656
|
-
|
|
26664
|
+
const bracketed = host[0] === "[" && host[host.length - 1] === "]";
|
|
26665
|
+
const hasBracket = host[0] === "[" || host[host.length - 1] === "]";
|
|
26666
|
+
if (hasBracket && !bracketed) return { host, isIPV6: false, error: true };
|
|
26667
|
+
let input = bracketed ? host.slice(1, -1) : host;
|
|
26668
|
+
if (bracketed && isIPvFuture(input)) {
|
|
26669
|
+
input = input.toLowerCase();
|
|
26670
|
+
return { host: `[${input}]`, escapedHost: input, isIPV6: false, isIPVFuture: true };
|
|
26671
|
+
}
|
|
26672
|
+
if (findToken(input, ":") < 2) {
|
|
26673
|
+
return { host, isIPV6: false, error: bracketed };
|
|
26674
|
+
}
|
|
26675
|
+
let zoneIdentifier = "";
|
|
26676
|
+
const zoneSeparator = input.indexOf("%");
|
|
26677
|
+
if (zoneSeparator !== -1) {
|
|
26678
|
+
const separatorLength = input.slice(zoneSeparator, zoneSeparator + 3).toLowerCase() === "%25" ? 3 : 1;
|
|
26679
|
+
zoneIdentifier = input.slice(zoneSeparator + separatorLength);
|
|
26680
|
+
if (!isZoneIdentifier(zoneIdentifier)) return { host, isIPV6: false, error: true };
|
|
26681
|
+
input = input.slice(0, zoneSeparator);
|
|
26682
|
+
}
|
|
26683
|
+
const address = normalizeIPv6Address(input);
|
|
26684
|
+
if (address === void 0) return { host, isIPV6: false, error: true };
|
|
26685
|
+
return {
|
|
26686
|
+
host: address + (zoneIdentifier ? "%" + zoneIdentifier : ""),
|
|
26687
|
+
escapedHost: address + (zoneIdentifier ? "%25" + zoneIdentifier : ""),
|
|
26688
|
+
isIPV6: true
|
|
26689
|
+
};
|
|
26657
26690
|
}
|
|
26658
26691
|
function findToken(str, token) {
|
|
26659
26692
|
let ind = 0;
|
|
@@ -26772,7 +26805,8 @@ var require_utils = __commonJS({
|
|
|
26772
26805
|
function normalizePathEncoding(input) {
|
|
26773
26806
|
let output = "";
|
|
26774
26807
|
for (let i = 0; i < input.length; i++) {
|
|
26775
|
-
|
|
26808
|
+
const ch = input[i];
|
|
26809
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
26776
26810
|
const hex3 = input.slice(i + 1, i + 3);
|
|
26777
26811
|
if (isHexPair(hex3)) {
|
|
26778
26812
|
const normalizedHex = hex3.toUpperCase();
|
|
@@ -26786,10 +26820,152 @@ var require_utils = __commonJS({
|
|
|
26786
26820
|
continue;
|
|
26787
26821
|
}
|
|
26788
26822
|
}
|
|
26789
|
-
if (isPathCharacter(
|
|
26790
|
-
output +=
|
|
26823
|
+
if (isPathCharacter(ch)) {
|
|
26824
|
+
output += ch;
|
|
26791
26825
|
} else {
|
|
26792
|
-
|
|
26826
|
+
const code = input.charCodeAt(i);
|
|
26827
|
+
if (code < 128) {
|
|
26828
|
+
output += isEscapeSafe(code) ? ch : BYTE_HEX[code];
|
|
26829
|
+
} else if (code < 55296 || code > 57343) {
|
|
26830
|
+
output += percentEncodeNonAscii(code);
|
|
26831
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
26832
|
+
const low = input.charCodeAt(i + 1);
|
|
26833
|
+
if (low >= 56320 && low <= 57343) {
|
|
26834
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
26835
|
+
i++;
|
|
26836
|
+
} else {
|
|
26837
|
+
output += percentEncodeNonAscii(65533);
|
|
26838
|
+
}
|
|
26839
|
+
} else {
|
|
26840
|
+
output += percentEncodeNonAscii(65533);
|
|
26841
|
+
}
|
|
26842
|
+
}
|
|
26843
|
+
}
|
|
26844
|
+
return output;
|
|
26845
|
+
}
|
|
26846
|
+
function serializePathEncoding(input, pathNoScheme = false) {
|
|
26847
|
+
let output = "";
|
|
26848
|
+
let firstSegment = pathNoScheme && input[0] !== "/";
|
|
26849
|
+
for (let i = 0; i < input.length; i++) {
|
|
26850
|
+
const ch = input[i];
|
|
26851
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
26852
|
+
const hex3 = input.slice(i + 1, i + 3);
|
|
26853
|
+
if (isHexPair(hex3)) {
|
|
26854
|
+
output += "%" + hex3.toUpperCase();
|
|
26855
|
+
i += 2;
|
|
26856
|
+
continue;
|
|
26857
|
+
}
|
|
26858
|
+
}
|
|
26859
|
+
if (ch === "/") {
|
|
26860
|
+
firstSegment = false;
|
|
26861
|
+
}
|
|
26862
|
+
if (isPathCharacter(ch) && (ch !== ":" || !firstSegment)) {
|
|
26863
|
+
output += ch;
|
|
26864
|
+
} else {
|
|
26865
|
+
const code = input.charCodeAt(i);
|
|
26866
|
+
if (code < 128) {
|
|
26867
|
+
output += BYTE_HEX[code];
|
|
26868
|
+
} else if (code < 55296 || code > 57343) {
|
|
26869
|
+
output += percentEncodeNonAscii(code);
|
|
26870
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
26871
|
+
const low = input.charCodeAt(i + 1);
|
|
26872
|
+
if (low >= 56320 && low <= 57343) {
|
|
26873
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
26874
|
+
i++;
|
|
26875
|
+
} else {
|
|
26876
|
+
output += percentEncodeNonAscii(65533);
|
|
26877
|
+
}
|
|
26878
|
+
} else {
|
|
26879
|
+
output += percentEncodeNonAscii(65533);
|
|
26880
|
+
}
|
|
26881
|
+
}
|
|
26882
|
+
}
|
|
26883
|
+
return output;
|
|
26884
|
+
}
|
|
26885
|
+
function encodeComponent(input, isAllowed) {
|
|
26886
|
+
let output = "";
|
|
26887
|
+
for (let i = 0; i < input.length; i++) {
|
|
26888
|
+
const ch = input[i];
|
|
26889
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
26890
|
+
const hex3 = input.slice(i + 1, i + 3);
|
|
26891
|
+
if (isHexPair(hex3)) {
|
|
26892
|
+
output += "%" + hex3.toUpperCase();
|
|
26893
|
+
i += 2;
|
|
26894
|
+
continue;
|
|
26895
|
+
}
|
|
26896
|
+
}
|
|
26897
|
+
if (isAllowed(ch)) {
|
|
26898
|
+
output += ch;
|
|
26899
|
+
} else {
|
|
26900
|
+
const code = input.charCodeAt(i);
|
|
26901
|
+
if (code < 128) {
|
|
26902
|
+
output += BYTE_HEX[code];
|
|
26903
|
+
} else if (code < 55296 || code > 57343) {
|
|
26904
|
+
output += percentEncodeNonAscii(code);
|
|
26905
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
26906
|
+
const low = input.charCodeAt(i + 1);
|
|
26907
|
+
if (low >= 56320 && low <= 57343) {
|
|
26908
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
26909
|
+
i++;
|
|
26910
|
+
} else {
|
|
26911
|
+
output += percentEncodeNonAscii(65533);
|
|
26912
|
+
}
|
|
26913
|
+
} else {
|
|
26914
|
+
output += percentEncodeNonAscii(65533);
|
|
26915
|
+
}
|
|
26916
|
+
}
|
|
26917
|
+
}
|
|
26918
|
+
return output;
|
|
26919
|
+
}
|
|
26920
|
+
function encodeUserinfo(input) {
|
|
26921
|
+
return encodeComponent(input, isUserinfoCharacter);
|
|
26922
|
+
}
|
|
26923
|
+
function encodeQuery(input) {
|
|
26924
|
+
return encodeComponent(input, isQueryFragmentCharacter);
|
|
26925
|
+
}
|
|
26926
|
+
function encodeFragment(input) {
|
|
26927
|
+
return encodeComponent(input, isQueryFragmentCharacter);
|
|
26928
|
+
}
|
|
26929
|
+
function isEscapeSafe(cp) {
|
|
26930
|
+
return cp >= 48 && cp <= 57 || cp >= 65 && cp <= 90 || cp >= 97 && cp <= 122 || cp === 42 || cp === 43 || cp === 45 || cp === 46 || cp === 47 || cp === 64 || cp === 95;
|
|
26931
|
+
}
|
|
26932
|
+
function normalizeQueryFragmentEncoding(input) {
|
|
26933
|
+
let output = "";
|
|
26934
|
+
for (let i = 0; i < input.length; i++) {
|
|
26935
|
+
const ch = input[i];
|
|
26936
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
26937
|
+
const hex3 = input.slice(i + 1, i + 3);
|
|
26938
|
+
if (isHexPair(hex3)) {
|
|
26939
|
+
const normalizedHex = hex3.toUpperCase();
|
|
26940
|
+
const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
|
|
26941
|
+
if (isUnreserved(decoded)) {
|
|
26942
|
+
output += decoded;
|
|
26943
|
+
} else {
|
|
26944
|
+
output += "%" + normalizedHex;
|
|
26945
|
+
}
|
|
26946
|
+
i += 2;
|
|
26947
|
+
continue;
|
|
26948
|
+
}
|
|
26949
|
+
}
|
|
26950
|
+
if (isQueryFragmentCharacter(ch)) {
|
|
26951
|
+
output += ch;
|
|
26952
|
+
} else {
|
|
26953
|
+
const code = input.charCodeAt(i);
|
|
26954
|
+
if (code < 128) {
|
|
26955
|
+
output += isEscapeSafe(code) ? ch : BYTE_HEX[code];
|
|
26956
|
+
} else if (code < 55296 || code > 57343) {
|
|
26957
|
+
output += percentEncodeNonAscii(code);
|
|
26958
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
26959
|
+
const low = input.charCodeAt(i + 1);
|
|
26960
|
+
if (low >= 56320 && low <= 57343) {
|
|
26961
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
26962
|
+
i++;
|
|
26963
|
+
} else {
|
|
26964
|
+
output += percentEncodeNonAscii(65533);
|
|
26965
|
+
}
|
|
26966
|
+
} else {
|
|
26967
|
+
output += percentEncodeNonAscii(65533);
|
|
26968
|
+
}
|
|
26793
26969
|
}
|
|
26794
26970
|
}
|
|
26795
26971
|
return output;
|
|
@@ -26812,14 +26988,18 @@ var require_utils = __commonJS({
|
|
|
26812
26988
|
function recomposeAuthority(component) {
|
|
26813
26989
|
const uriTokens = [];
|
|
26814
26990
|
if (component.userinfo !== void 0) {
|
|
26815
|
-
uriTokens.push(component.userinfo);
|
|
26991
|
+
uriTokens.push(encodeUserinfo(component.userinfo));
|
|
26816
26992
|
uriTokens.push("@");
|
|
26817
26993
|
}
|
|
26818
26994
|
if (component.host !== void 0) {
|
|
26819
|
-
let host =
|
|
26995
|
+
let host = component.host;
|
|
26820
26996
|
if (!isIPv4(host)) {
|
|
26821
|
-
|
|
26822
|
-
if (ipV6res.isIPV6
|
|
26997
|
+
let ipV6res = normalizeIPv6(host);
|
|
26998
|
+
if (ipV6res.isIPV6 !== true && ipV6res.isIPVFuture !== true) {
|
|
26999
|
+
host = normalizePercentEncoding(host, true);
|
|
27000
|
+
ipV6res = normalizeIPv6(host);
|
|
27001
|
+
}
|
|
27002
|
+
if (ipV6res.isIPV6 === true || ipV6res.isIPVFuture === true) {
|
|
26823
27003
|
host = `[${ipV6res.escapedHost}]`;
|
|
26824
27004
|
} else {
|
|
26825
27005
|
host = reescapeHostDelimiters(host, false);
|
|
@@ -26828,8 +27008,12 @@ var require_utils = __commonJS({
|
|
|
26828
27008
|
uriTokens.push(host);
|
|
26829
27009
|
}
|
|
26830
27010
|
if (typeof component.port === "number" || typeof component.port === "string") {
|
|
27011
|
+
const port = String(component.port);
|
|
27012
|
+
if (!isPort(port)) {
|
|
27013
|
+
throw new TypeError("URI port is malformed.");
|
|
27014
|
+
}
|
|
26831
27015
|
uriTokens.push(":");
|
|
26832
|
-
uriTokens.push(
|
|
27016
|
+
uriTokens.push(port);
|
|
26833
27017
|
}
|
|
26834
27018
|
return uriTokens.length ? uriTokens.join("") : void 0;
|
|
26835
27019
|
}
|
|
@@ -26839,6 +27023,11 @@ var require_utils = __commonJS({
|
|
|
26839
27023
|
reescapeHostDelimiters,
|
|
26840
27024
|
normalizePercentEncoding,
|
|
26841
27025
|
normalizePathEncoding,
|
|
27026
|
+
serializePathEncoding,
|
|
27027
|
+
normalizeQueryFragmentEncoding,
|
|
27028
|
+
encodeUserinfo,
|
|
27029
|
+
encodeQuery,
|
|
27030
|
+
encodeFragment,
|
|
26842
27031
|
escapePreservingEscapes,
|
|
26843
27032
|
removeDotSegments,
|
|
26844
27033
|
isIPv4,
|
|
@@ -26854,7 +27043,7 @@ var require_schemes = __commonJS({
|
|
|
26854
27043
|
"node_modules/fast-uri/lib/schemes.js"(exports, module) {
|
|
26855
27044
|
"use strict";
|
|
26856
27045
|
var { isUUID } = require_utils();
|
|
26857
|
-
var URN_REG =
|
|
27046
|
+
var URN_REG = /^([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-./:;=@]|%[\da-f]{2})+)$/iu;
|
|
26858
27047
|
var supportedSchemeNames = (
|
|
26859
27048
|
/** @type {const} */
|
|
26860
27049
|
[
|
|
@@ -26915,9 +27104,10 @@ var require_schemes = __commonJS({
|
|
|
26915
27104
|
wsComponent.secure = void 0;
|
|
26916
27105
|
}
|
|
26917
27106
|
if (wsComponent.resourceName) {
|
|
26918
|
-
const
|
|
27107
|
+
const queryIndex = wsComponent.resourceName.indexOf("?");
|
|
27108
|
+
const path = queryIndex === -1 ? wsComponent.resourceName : wsComponent.resourceName.slice(0, queryIndex);
|
|
26919
27109
|
wsComponent.path = path && path !== "/" ? path : void 0;
|
|
26920
|
-
wsComponent.query =
|
|
27110
|
+
wsComponent.query = queryIndex === -1 ? void 0 : wsComponent.resourceName.slice(queryIndex + 1);
|
|
26921
27111
|
wsComponent.resourceName = void 0;
|
|
26922
27112
|
}
|
|
26923
27113
|
wsComponent.fragment = void 0;
|
|
@@ -26929,7 +27119,7 @@ var require_schemes = __commonJS({
|
|
|
26929
27119
|
return urnComponent;
|
|
26930
27120
|
}
|
|
26931
27121
|
const matches = urnComponent.path.match(URN_REG);
|
|
26932
|
-
if (matches) {
|
|
27122
|
+
if (matches && matches[0] === urnComponent.path) {
|
|
26933
27123
|
const scheme = options.scheme || urnComponent.scheme || "urn";
|
|
26934
27124
|
urnComponent.nid = matches[1].toLowerCase();
|
|
26935
27125
|
urnComponent.nss = matches[2];
|
|
@@ -27063,8 +27253,17 @@ var require_schemes = __commonJS({
|
|
|
27063
27253
|
var require_fast_uri = __commonJS({
|
|
27064
27254
|
"node_modules/fast-uri/index.js"(exports, module) {
|
|
27065
27255
|
"use strict";
|
|
27066
|
-
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding,
|
|
27256
|
+
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, serializePathEncoding, normalizeQueryFragmentEncoding, encodeQuery, encodeFragment, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
|
|
27067
27257
|
var { SCHEMES, getSchemeHandler } = require_schemes();
|
|
27258
|
+
var VALID_SCHEME = /^[A-Za-z][A-Za-z0-9+.-]*$/u;
|
|
27259
|
+
var MALFORMED_SCHEME_ERROR = "URI scheme is malformed.";
|
|
27260
|
+
function decodeValidScheme(scheme) {
|
|
27261
|
+
const decodedScheme = unescape(String(scheme));
|
|
27262
|
+
if (!VALID_SCHEME.test(decodedScheme)) {
|
|
27263
|
+
throw new TypeError(MALFORMED_SCHEME_ERROR);
|
|
27264
|
+
}
|
|
27265
|
+
return decodedScheme;
|
|
27266
|
+
}
|
|
27068
27267
|
function normalize(uri, options) {
|
|
27069
27268
|
if (typeof uri === "string") {
|
|
27070
27269
|
uri = /** @type {T} */
|
|
@@ -27077,12 +27276,34 @@ var require_fast_uri = __commonJS({
|
|
|
27077
27276
|
}
|
|
27078
27277
|
function resolve2(baseURI, relativeURI, options) {
|
|
27079
27278
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
27080
|
-
const {
|
|
27081
|
-
|
|
27082
|
-
|
|
27279
|
+
const {
|
|
27280
|
+
parsed: baseParsed,
|
|
27281
|
+
malformedAuthorityOrPort: baseMalformed,
|
|
27282
|
+
malformedPercentEncoding: baseMalformedPercentEncoding,
|
|
27283
|
+
malformedSchemeSpecific: baseMalformedSchemeSpecific,
|
|
27284
|
+
malformedHost: baseMalformedHost,
|
|
27285
|
+
malformedScheme: baseMalformedScheme
|
|
27286
|
+
} = parseWithStatus(baseURI, schemelessOptions);
|
|
27287
|
+
const {
|
|
27288
|
+
parsed: relativeParsed,
|
|
27289
|
+
malformedAuthorityOrPort: relativeMalformed,
|
|
27290
|
+
malformedPercentEncoding: relativeMalformedPercentEncoding,
|
|
27291
|
+
malformedSchemeSpecific: relativeMalformedSchemeSpecific,
|
|
27292
|
+
malformedHost: relativeMalformedHost,
|
|
27293
|
+
malformedScheme: relativeMalformedScheme
|
|
27294
|
+
} = parseWithStatus(relativeURI, schemelessOptions);
|
|
27295
|
+
if (baseMalformed || relativeMalformed || baseMalformedPercentEncoding || relativeMalformedPercentEncoding || baseMalformedSchemeSpecific || relativeMalformedSchemeSpecific || baseMalformedHost || relativeMalformedHost || baseMalformedScheme || relativeMalformedScheme) {
|
|
27083
27296
|
throw new Error(baseParsed.error || relativeParsed.error || "URI is malformed.");
|
|
27084
27297
|
}
|
|
27085
27298
|
const resolved = resolveComponent(baseParsed, relativeParsed, schemelessOptions, true);
|
|
27299
|
+
const resolvedSchemeHandler = getSchemeHandler(options && options.scheme || resolved.scheme);
|
|
27300
|
+
const resolvedHost = resolved.host;
|
|
27301
|
+
const resolvedHostIsIP = resolvedHost !== void 0 && resolvedHost !== "" && (isIPv4(resolvedHost) || normalizeIPv6(resolvedHost).isIPV6);
|
|
27302
|
+
canonicalizeHost(resolved, options || {}, resolvedSchemeHandler, resolvedHostIsIP);
|
|
27303
|
+
const encodedASCIIHost = resolvedHost && resolvedHost.indexOf("%") !== -1 && !/\P{ASCII}/u.test(resolvedHost);
|
|
27304
|
+
if (resolved.error && !encodedASCIIHost) {
|
|
27305
|
+
throw new Error(resolved.error);
|
|
27306
|
+
}
|
|
27086
27307
|
schemelessOptions.skipEscape = true;
|
|
27087
27308
|
return serialize(resolved, schemelessOptions);
|
|
27088
27309
|
}
|
|
@@ -27142,7 +27363,7 @@ var require_fast_uri = __commonJS({
|
|
|
27142
27363
|
function equal(uriA, uriB, options) {
|
|
27143
27364
|
const normalizedA = normalizeComparableURI(uriA, options);
|
|
27144
27365
|
const normalizedB = normalizeComparableURI(uriB, options);
|
|
27145
|
-
return normalizedA !== void 0 && normalizedB !== void 0 && normalizedA
|
|
27366
|
+
return normalizedA !== void 0 && normalizedB !== void 0 && normalizedA === normalizedB;
|
|
27146
27367
|
}
|
|
27147
27368
|
function serialize(cmpts, opts) {
|
|
27148
27369
|
const component = {
|
|
@@ -27163,19 +27384,22 @@ var require_fast_uri = __commonJS({
|
|
|
27163
27384
|
};
|
|
27164
27385
|
const options = Object.assign({}, opts);
|
|
27165
27386
|
const uriTokens = [];
|
|
27387
|
+
if (component.scheme) {
|
|
27388
|
+
component.scheme = decodeValidScheme(component.scheme);
|
|
27389
|
+
}
|
|
27166
27390
|
const schemeHandler = getSchemeHandler(options.scheme || component.scheme);
|
|
27167
27391
|
if (schemeHandler && schemeHandler.serialize) schemeHandler.serialize(component, options);
|
|
27392
|
+
const hasAuthority = component.userinfo !== void 0 || component.host !== void 0 || component.port !== void 0;
|
|
27393
|
+
const pathNoScheme = !options.skipEscape && component.scheme === void 0 && !hasAuthority;
|
|
27168
27394
|
if (component.path !== void 0) {
|
|
27169
27395
|
if (!options.skipEscape) {
|
|
27170
|
-
component.path =
|
|
27171
|
-
if (component.scheme !== void 0) {
|
|
27172
|
-
component.path = component.path.split("%3A").join(":");
|
|
27173
|
-
}
|
|
27396
|
+
component.path = serializePathEncoding(component.path, pathNoScheme);
|
|
27174
27397
|
} else {
|
|
27175
27398
|
component.path = normalizePercentEncoding(component.path);
|
|
27176
27399
|
}
|
|
27177
27400
|
}
|
|
27178
27401
|
if (options.reference !== "suffix" && component.scheme) {
|
|
27402
|
+
component.scheme = decodeValidScheme(component.scheme);
|
|
27179
27403
|
uriTokens.push(component.scheme, ":");
|
|
27180
27404
|
}
|
|
27181
27405
|
const authority = recomposeAuthority(component);
|
|
@@ -27193,16 +27417,19 @@ var require_fast_uri = __commonJS({
|
|
|
27193
27417
|
if (!options.absolutePath && (!schemeHandler || !schemeHandler.absolutePath)) {
|
|
27194
27418
|
s = removeDotSegments(s);
|
|
27195
27419
|
}
|
|
27420
|
+
if (pathNoScheme) {
|
|
27421
|
+
s = serializePathEncoding(s, true);
|
|
27422
|
+
}
|
|
27196
27423
|
if (authority === void 0 && s[0] === "/" && s[1] === "/") {
|
|
27197
27424
|
s = "/%2F" + s.slice(2);
|
|
27198
27425
|
}
|
|
27199
27426
|
uriTokens.push(s);
|
|
27200
27427
|
}
|
|
27201
27428
|
if (component.query !== void 0) {
|
|
27202
|
-
uriTokens.push("?", component.query);
|
|
27429
|
+
uriTokens.push("?", encodeQuery(component.query));
|
|
27203
27430
|
}
|
|
27204
27431
|
if (component.fragment !== void 0) {
|
|
27205
|
-
uriTokens.push("#", component.fragment);
|
|
27432
|
+
uriTokens.push("#", encodeFragment(component.fragment));
|
|
27206
27433
|
}
|
|
27207
27434
|
return uriTokens.join("");
|
|
27208
27435
|
}
|
|
@@ -27218,6 +27445,35 @@ var require_fast_uri = __commonJS({
|
|
|
27218
27445
|
}
|
|
27219
27446
|
return void 0;
|
|
27220
27447
|
}
|
|
27448
|
+
function hasMalformedPercentEncoding(component) {
|
|
27449
|
+
if (component === void 0) return false;
|
|
27450
|
+
let percent = component.indexOf("%");
|
|
27451
|
+
while (percent !== -1) {
|
|
27452
|
+
if (percent + 2 >= component.length || !/^[\da-f]{2}$/iu.test(component.slice(percent + 1, percent + 3))) {
|
|
27453
|
+
return true;
|
|
27454
|
+
}
|
|
27455
|
+
percent = component.indexOf("%", percent + 3);
|
|
27456
|
+
}
|
|
27457
|
+
return false;
|
|
27458
|
+
}
|
|
27459
|
+
function isIPLiteral(host) {
|
|
27460
|
+
return host[0] === "[" && host[host.length - 1] === "]";
|
|
27461
|
+
}
|
|
27462
|
+
function hasMalformedComponentPercentEncoding(matches) {
|
|
27463
|
+
const host = matches[4];
|
|
27464
|
+
return hasMalformedPercentEncoding(matches[3]) || host !== void 0 && !isIPLiteral(host) && hasMalformedPercentEncoding(host) || hasMalformedPercentEncoding(matches[6]) || hasMalformedPercentEncoding(matches[7]) || hasMalformedPercentEncoding(matches[8]);
|
|
27465
|
+
}
|
|
27466
|
+
function canonicalizeHost(parsed, options, schemeHandler, isIP) {
|
|
27467
|
+
if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport) && parsed.host && !isIPLiteral(parsed.host) && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP === false && nonSimpleDomain(parsed.host)) {
|
|
27468
|
+
try {
|
|
27469
|
+
parsed.host = new URL("http://" + parsed.host).hostname;
|
|
27470
|
+
} catch (e) {
|
|
27471
|
+
parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e;
|
|
27472
|
+
return true;
|
|
27473
|
+
}
|
|
27474
|
+
}
|
|
27475
|
+
return false;
|
|
27476
|
+
}
|
|
27221
27477
|
function parseWithStatus(uri, opts) {
|
|
27222
27478
|
const options = Object.assign({}, opts);
|
|
27223
27479
|
const parsed = {
|
|
@@ -27230,6 +27486,11 @@ var require_fast_uri = __commonJS({
|
|
|
27230
27486
|
fragment: void 0
|
|
27231
27487
|
};
|
|
27232
27488
|
let malformedAuthorityOrPort = false;
|
|
27489
|
+
let malformedPercentEncoding = false;
|
|
27490
|
+
let malformedSchemeSpecific = false;
|
|
27491
|
+
let malformedHost = false;
|
|
27492
|
+
let malformedIPLiteral = false;
|
|
27493
|
+
let malformedScheme = false;
|
|
27233
27494
|
let isIP = false;
|
|
27234
27495
|
if (options.reference === "suffix") {
|
|
27235
27496
|
if (options.scheme) {
|
|
@@ -27266,6 +27527,19 @@ var require_fast_uri = __commonJS({
|
|
|
27266
27527
|
parsed.path = matches[6] || "";
|
|
27267
27528
|
parsed.query = matches[7];
|
|
27268
27529
|
parsed.fragment = matches[8];
|
|
27530
|
+
if (parsed.scheme !== void 0) {
|
|
27531
|
+
const decodedScheme = unescape(parsed.scheme);
|
|
27532
|
+
if (VALID_SCHEME.test(decodedScheme)) {
|
|
27533
|
+
parsed.scheme = decodedScheme.toLowerCase();
|
|
27534
|
+
} else {
|
|
27535
|
+
parsed.error = parsed.error || MALFORMED_SCHEME_ERROR;
|
|
27536
|
+
malformedScheme = true;
|
|
27537
|
+
}
|
|
27538
|
+
}
|
|
27539
|
+
malformedPercentEncoding = hasMalformedComponentPercentEncoding(matches);
|
|
27540
|
+
if (malformedPercentEncoding) {
|
|
27541
|
+
parsed.error = parsed.error || "URI contains malformed percent-encoding.";
|
|
27542
|
+
}
|
|
27269
27543
|
if (isNaN(parsed.port)) {
|
|
27270
27544
|
parsed.port = matches[5];
|
|
27271
27545
|
}
|
|
@@ -27277,9 +27551,16 @@ var require_fast_uri = __commonJS({
|
|
|
27277
27551
|
if (parsed.host) {
|
|
27278
27552
|
const ipv4result = isIPv4(parsed.host);
|
|
27279
27553
|
if (ipv4result === false) {
|
|
27554
|
+
const bracketedIPLiteral = isIPLiteral(parsed.host);
|
|
27555
|
+
const hasIPLiteralBracket = parsed.host.indexOf("[") !== -1 || parsed.host.indexOf("]") !== -1;
|
|
27280
27556
|
const ipv6result = normalizeIPv6(parsed.host);
|
|
27281
|
-
|
|
27282
|
-
|
|
27557
|
+
isIP = ipv6result.isIPV6 || ipv6result.isIPVFuture === true;
|
|
27558
|
+
malformedIPLiteral = hasIPLiteralBracket && (!bracketedIPLiteral || ipv6result.error === true);
|
|
27559
|
+
parsed.host = isIP ? ipv6result.host : ipv6result.host.toLowerCase();
|
|
27560
|
+
if (malformedIPLiteral) {
|
|
27561
|
+
parsed.error = parsed.error || "URI host is malformed.";
|
|
27562
|
+
malformedAuthorityOrPort = true;
|
|
27563
|
+
}
|
|
27283
27564
|
} else {
|
|
27284
27565
|
isIP = true;
|
|
27285
27566
|
}
|
|
@@ -27297,42 +27578,36 @@ var require_fast_uri = __commonJS({
|
|
|
27297
27578
|
parsed.error = parsed.error || "URI is not a " + options.reference + " reference.";
|
|
27298
27579
|
}
|
|
27299
27580
|
const schemeHandler = getSchemeHandler(options.scheme || parsed.scheme);
|
|
27300
|
-
if (!
|
|
27301
|
-
|
|
27302
|
-
try {
|
|
27303
|
-
parsed.host = new URL("http://" + parsed.host).hostname;
|
|
27304
|
-
} catch (e) {
|
|
27305
|
-
parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e;
|
|
27306
|
-
}
|
|
27307
|
-
}
|
|
27581
|
+
if (!malformedIPLiteral) {
|
|
27582
|
+
malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP);
|
|
27308
27583
|
}
|
|
27309
27584
|
if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
|
|
27310
27585
|
if (uri.indexOf("%") !== -1) {
|
|
27311
|
-
if (parsed.
|
|
27312
|
-
parsed.
|
|
27313
|
-
|
|
27314
|
-
if (parsed.host !== void 0) {
|
|
27315
|
-
parsed.host = reescapeHostDelimiters(unescape(parsed.host), isIP);
|
|
27586
|
+
if (parsed.host !== void 0 && !malformedIPLiteral) {
|
|
27587
|
+
const host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
|
|
27588
|
+
parsed.host = reescapeHostDelimiters(host, isIP);
|
|
27316
27589
|
}
|
|
27317
27590
|
}
|
|
27318
27591
|
if (parsed.path) {
|
|
27319
27592
|
parsed.path = normalizePathEncoding(parsed.path);
|
|
27320
27593
|
}
|
|
27594
|
+
if (parsed.query) {
|
|
27595
|
+
parsed.query = normalizeQueryFragmentEncoding(parsed.query);
|
|
27596
|
+
}
|
|
27321
27597
|
if (parsed.fragment) {
|
|
27322
|
-
|
|
27323
|
-
parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment));
|
|
27324
|
-
} catch {
|
|
27325
|
-
parsed.error = parsed.error || "URI malformed";
|
|
27326
|
-
}
|
|
27598
|
+
parsed.fragment = normalizeQueryFragmentEncoding(parsed.fragment);
|
|
27327
27599
|
}
|
|
27328
27600
|
}
|
|
27329
27601
|
if (schemeHandler && schemeHandler.parse) {
|
|
27330
27602
|
schemeHandler.parse(parsed, options);
|
|
27603
|
+
if (schemeHandler === SCHEMES.urn && parsed.nid === void 0) {
|
|
27604
|
+
malformedSchemeSpecific = true;
|
|
27605
|
+
}
|
|
27331
27606
|
}
|
|
27332
27607
|
} else {
|
|
27333
27608
|
parsed.error = parsed.error || "URI can not be parsed.";
|
|
27334
27609
|
}
|
|
27335
|
-
return { parsed, malformedAuthorityOrPort };
|
|
27610
|
+
return { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme };
|
|
27336
27611
|
}
|
|
27337
27612
|
function parse3(uri, opts) {
|
|
27338
27613
|
return parseWithStatus(uri, opts).parsed;
|
|
@@ -27341,20 +27616,28 @@ var require_fast_uri = __commonJS({
|
|
|
27341
27616
|
return normalizeStringWithStatus(uri, opts).normalized;
|
|
27342
27617
|
}
|
|
27343
27618
|
function normalizeStringWithStatus(uri, opts) {
|
|
27344
|
-
const { parsed, malformedAuthorityOrPort } = parseWithStatus(uri, opts);
|
|
27619
|
+
const { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = parseWithStatus(uri, opts);
|
|
27345
27620
|
return {
|
|
27346
|
-
normalized: malformedAuthorityOrPort ? uri : serialize(parsed, opts),
|
|
27347
|
-
malformedAuthorityOrPort
|
|
27621
|
+
normalized: malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? uri : serialize(parsed, opts),
|
|
27622
|
+
malformedAuthorityOrPort,
|
|
27623
|
+
malformedPercentEncoding,
|
|
27624
|
+
malformedSchemeSpecific,
|
|
27625
|
+
malformedHost,
|
|
27626
|
+
malformedScheme
|
|
27348
27627
|
};
|
|
27349
27628
|
}
|
|
27350
27629
|
function normalizeComparableURI(uri, opts) {
|
|
27351
|
-
if (typeof uri
|
|
27352
|
-
|
|
27353
|
-
return malformedAuthorityOrPort ? void 0 : normalized;
|
|
27630
|
+
if (typeof uri !== "string" && typeof uri !== "object") {
|
|
27631
|
+
return void 0;
|
|
27354
27632
|
}
|
|
27355
|
-
|
|
27356
|
-
|
|
27633
|
+
let value;
|
|
27634
|
+
try {
|
|
27635
|
+
value = typeof uri === "string" ? uri : serialize(uri, opts);
|
|
27636
|
+
} catch {
|
|
27637
|
+
return void 0;
|
|
27357
27638
|
}
|
|
27639
|
+
const { normalized, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = normalizeStringWithStatus(value, opts);
|
|
27640
|
+
return malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? void 0 : normalized;
|
|
27358
27641
|
}
|
|
27359
27642
|
var fastUri = {
|
|
27360
27643
|
SCHEMES,
|
|
@@ -32157,12 +32440,25 @@ var init_errors4 = __esm({
|
|
|
32157
32440
|
}
|
|
32158
32441
|
});
|
|
32159
32442
|
|
|
32160
|
-
// node_modules/@chrischall/mcp-utils/dist/response/
|
|
32161
|
-
function
|
|
32162
|
-
return {
|
|
32163
|
-
content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
|
|
32164
|
-
};
|
|
32443
|
+
// node_modules/@chrischall/mcp-utils/dist/response/view.js
|
|
32444
|
+
function minifiedResult(data) {
|
|
32445
|
+
return { content: [{ type: "text", text: JSON.stringify(data) }] };
|
|
32165
32446
|
}
|
|
32447
|
+
var init_view = __esm({
|
|
32448
|
+
"node_modules/@chrischall/mcp-utils/dist/response/view.js"() {
|
|
32449
|
+
}
|
|
32450
|
+
});
|
|
32451
|
+
|
|
32452
|
+
// node_modules/@chrischall/mcp-utils/dist/response/media.js
|
|
32453
|
+
var MEDIA_NOUN, MEDIA_KEY;
|
|
32454
|
+
var init_media = __esm({
|
|
32455
|
+
"node_modules/@chrischall/mcp-utils/dist/response/media.js"() {
|
|
32456
|
+
MEDIA_NOUN = "(?:avatar|tall_avatar|cover_photo|cover_image|picture|photo|thumbnail|thumb|image|icon|banner|profile_pic(?:ture)?|logo)";
|
|
32457
|
+
MEDIA_KEY = new RegExp(`^${MEDIA_NOUN}s?(?:(?:link|uri|url)s?)?$`, "i");
|
|
32458
|
+
}
|
|
32459
|
+
});
|
|
32460
|
+
|
|
32461
|
+
// node_modules/@chrischall/mcp-utils/dist/response/index.js
|
|
32166
32462
|
function errorResult(message) {
|
|
32167
32463
|
return {
|
|
32168
32464
|
content: [{ type: "text", text: redactSecrets(message) }],
|
|
@@ -32172,6 +32468,8 @@ function errorResult(message) {
|
|
|
32172
32468
|
var init_response = __esm({
|
|
32173
32469
|
"node_modules/@chrischall/mcp-utils/dist/response/index.js"() {
|
|
32174
32470
|
init_errors4();
|
|
32471
|
+
init_view();
|
|
32472
|
+
init_media();
|
|
32175
32473
|
}
|
|
32176
32474
|
});
|
|
32177
32475
|
|
|
@@ -32881,7 +33179,7 @@ async function loadStdioDotenv() {
|
|
|
32881
33179
|
}
|
|
32882
33180
|
|
|
32883
33181
|
// src/version.ts
|
|
32884
|
-
var VERSION = "1.
|
|
33182
|
+
var VERSION = "1.13.0";
|
|
32885
33183
|
|
|
32886
33184
|
// src/errors.ts
|
|
32887
33185
|
init_dist();
|
|
@@ -32952,7 +33250,7 @@ function registerModelTools(server, client2) {
|
|
|
32952
33250
|
},
|
|
32953
33251
|
async () => {
|
|
32954
33252
|
const models = await client2.listModels();
|
|
32955
|
-
return
|
|
33253
|
+
return minifiedResult({ default: client2.defaultModel(), models });
|
|
32956
33254
|
}
|
|
32957
33255
|
);
|
|
32958
33256
|
}
|
|
@@ -32965,6 +33263,18 @@ function statusOf(err) {
|
|
|
32965
33263
|
const s = err.status ?? err.statusCode;
|
|
32966
33264
|
return typeof s === "number" ? s : void 0;
|
|
32967
33265
|
}
|
|
33266
|
+
var CREDENTIAL_ARMS = /* @__PURE__ */ new Set([
|
|
33267
|
+
"ok",
|
|
33268
|
+
"no_credential",
|
|
33269
|
+
"credential_rejected",
|
|
33270
|
+
"timeout",
|
|
33271
|
+
"http",
|
|
33272
|
+
"transport",
|
|
33273
|
+
"unknown"
|
|
33274
|
+
]);
|
|
33275
|
+
function isArm(kind) {
|
|
33276
|
+
return kind !== void 0 && CREDENTIAL_ARMS.has(kind);
|
|
33277
|
+
}
|
|
32968
33278
|
function credentialHint(arm, prefix, hostLabel, source) {
|
|
32969
33279
|
switch (arm) {
|
|
32970
33280
|
case "ok":
|
|
@@ -33002,13 +33312,27 @@ function registerCredentialHealthcheckTool(args) {
|
|
|
33002
33312
|
try {
|
|
33003
33313
|
state = await resolveCredential();
|
|
33004
33314
|
} catch (e) {
|
|
33315
|
+
const classified = classifyThrown?.(e);
|
|
33005
33316
|
const result2 = {
|
|
33006
33317
|
ok: false,
|
|
33318
|
+
// Still false, and still no source: a classification explains WHY
|
|
33319
|
+
// nothing resolved, it does not invent a credential that did.
|
|
33007
33320
|
credential: { source: null, resolved: false },
|
|
33008
33321
|
// No `url`: nothing was probed, and naming one implies it was tried.
|
|
33009
33322
|
probe: { elapsed_ms: 0 },
|
|
33010
|
-
error: {
|
|
33011
|
-
|
|
33323
|
+
error: {
|
|
33324
|
+
kind: classified?.kind ?? "no_credential",
|
|
33325
|
+
message: truncateErrorMessage(messageOf(e)),
|
|
33326
|
+
...classified?.detail !== void 0 ? { detail: classified.detail } : {}
|
|
33327
|
+
},
|
|
33328
|
+
// The hint must follow the KIND beside it. Falling back to
|
|
33329
|
+
// `no_credential`'s copy under a classified kind would state a cause
|
|
33330
|
+
// the kind contradicts — the same disagreement this path exists to
|
|
33331
|
+
// remove. So: an inline hint wins; else the classified arm's own
|
|
33332
|
+
// copy (consumer override first); else, for a kind this module has
|
|
33333
|
+
// no copy for, the neutral `unknown` text rather than one that
|
|
33334
|
+
// asserts a cause; else the unclassified `no_credential` default.
|
|
33335
|
+
hint: classified?.hint ?? (isArm(classified?.kind) ? hints?.[classified.kind] ?? credentialHint(classified.kind, prefix, hostLabel, null) : classified !== void 0 ? credentialHint("unknown", prefix, hostLabel, null) : hints?.no_credential ?? credentialHint("no_credential", prefix, hostLabel, null))
|
|
33012
33336
|
};
|
|
33013
33337
|
return { content: [{ type: "text", text: JSON.stringify(result2, null, 2) }] };
|
|
33014
33338
|
}
|
|
@@ -34000,7 +34324,7 @@ async function emitMedia(named, kind, opts, meta3, onWritten) {
|
|
|
34000
34324
|
}))
|
|
34001
34325
|
} : {};
|
|
34002
34326
|
const storage = sink.persistsFiles ? {} : { storage: sink.kind, storage_note: storageNote };
|
|
34003
|
-
return
|
|
34327
|
+
return minifiedResult({ [`${kind}s`]: refs, ...media, ...unavailable, ...note, ...storage, ...meta3 });
|
|
34004
34328
|
}
|
|
34005
34329
|
async function emit(named, opts, meta3, onWritten) {
|
|
34006
34330
|
return emitMedia(named.map((n) => ({ media: n.image, base: n.base })), "image", opts, meta3, onWritten);
|
|
@@ -34295,7 +34619,7 @@ function annotateReused(result, jobId) {
|
|
|
34295
34619
|
};
|
|
34296
34620
|
}
|
|
34297
34621
|
function jobHandle(jobId, status, durable = false) {
|
|
34298
|
-
return
|
|
34622
|
+
return minifiedResult({
|
|
34299
34623
|
job_id: jobId,
|
|
34300
34624
|
status,
|
|
34301
34625
|
hint: durable ? `Generation running in the background. Poll gemini_get_result with job_id "${jobId}" until status is "done". The job record is stored durably, so a poll still works if this connector restarts \u2014 but background work is NOT restarted, so a long generation is safer with max_wait_ms than with async.` : `Generation running in the background. Poll gemini_get_result with job_id "${jobId}" until status is "done" (results are per-process and expire ~10 min after completion).`
|
|
@@ -34784,7 +35108,7 @@ init_dist();
|
|
|
34784
35108
|
init_images();
|
|
34785
35109
|
function previewUnlessConfirmed(confirm, action, method, path, body) {
|
|
34786
35110
|
if (confirm === true) return null;
|
|
34787
|
-
return
|
|
35111
|
+
return minifiedResult({
|
|
34788
35112
|
dryRun: true,
|
|
34789
35113
|
action,
|
|
34790
35114
|
method,
|
|
@@ -36924,7 +37248,7 @@ function recoveryNote(recordedError) {
|
|
|
36924
37248
|
return `${cause} The generation had already completed upstream and its output was recovered \u2014 it was not re-run, and you were not billed twice.`;
|
|
36925
37249
|
}
|
|
36926
37250
|
function stillRunning(jobId, interactionId) {
|
|
36927
|
-
return
|
|
37251
|
+
return minifiedResult({
|
|
36928
37252
|
job_id: jobId,
|
|
36929
37253
|
status: "running",
|
|
36930
37254
|
interaction_id: interactionId,
|
|
@@ -36963,7 +37287,7 @@ function registerUsageTools(server, client2) {
|
|
|
36963
37287
|
client2.session.costUsd = void 0;
|
|
36964
37288
|
client2.session.pricedCalls = 0;
|
|
36965
37289
|
}
|
|
36966
|
-
return
|
|
37290
|
+
return minifiedResult({
|
|
36967
37291
|
usage: usage ?? null,
|
|
36968
37292
|
billed_calls: calls,
|
|
36969
37293
|
estimated_cost_usd: costUsd ?? null,
|
|
@@ -36986,7 +37310,7 @@ var UPLOAD_URL_MAX_BYTES_HOSTED = 25 * 1024 * 1024;
|
|
|
36986
37310
|
var UPLOAD_ACCEPT = ["image/", "video/", "audio/"];
|
|
36987
37311
|
var RETENTION_NOTE = "Gemini retains uploaded files for ~48h. Until then this reference can be reused across any number of calls (images_file_uris on gemini_image_generate / _edit / _set / gemini_interact, or video_url) without re-sending the bytes.";
|
|
36988
37312
|
function uploadResult(file2) {
|
|
36989
|
-
return
|
|
37313
|
+
return minifiedResult({
|
|
36990
37314
|
// The `files/<id>` form is what every tool parameter documents, so it leads.
|
|
36991
37315
|
file_uri: file2.name,
|
|
36992
37316
|
// The absolute uri, for callers that would rather pass it through verbatim.
|
|
@@ -37099,7 +37423,7 @@ function registerFileTools(server, client2) {
|
|
|
37099
37423
|
},
|
|
37100
37424
|
async (args) => {
|
|
37101
37425
|
const files = await client2.listFiles(args.page_size ?? 100);
|
|
37102
|
-
return
|
|
37426
|
+
return minifiedResult({
|
|
37103
37427
|
count: files.length,
|
|
37104
37428
|
files: files.map((f) => ({
|
|
37105
37429
|
file_uri: f.name,
|
|
@@ -37139,7 +37463,7 @@ function registerFileTools(server, client2) {
|
|
|
37139
37463
|
{ hint: "Objects are swept on a retention schedule (MEDIA_TTL_DAYS, default 7 days)." }
|
|
37140
37464
|
);
|
|
37141
37465
|
}
|
|
37142
|
-
return
|
|
37466
|
+
return minifiedResult({
|
|
37143
37467
|
url: fresh.ref,
|
|
37144
37468
|
r2_key: fresh.key,
|
|
37145
37469
|
...fresh.expiresAt ? { expires_at: fresh.expiresAt } : {},
|
|
@@ -37168,7 +37492,7 @@ function registerFileTools(server, client2) {
|
|
|
37168
37492
|
const limit = args.limit ?? 20;
|
|
37169
37493
|
const page = sink.listRecentPage ? await sink.listRecentPage({ limit, sinceDay: args.since_day }) : { media: await sink.listRecent({ limit, sinceDay: args.since_day }), truncated: false };
|
|
37170
37494
|
const found = page.media;
|
|
37171
|
-
return
|
|
37495
|
+
return minifiedResult({
|
|
37172
37496
|
count: found.length,
|
|
37173
37497
|
// Never let a bounded walk pass for the whole picture: concluding an
|
|
37174
37498
|
// image is gone is what makes someone pay to generate it twice.
|
|
@@ -37200,7 +37524,7 @@ function registerFileTools(server, client2) {
|
|
|
37200
37524
|
const gate = previewUnlessConfirmed(args.confirm, "Delete an uploaded Gemini file", "DELETE", `/v1beta/${args.file_uri}`);
|
|
37201
37525
|
if (gate) return gate;
|
|
37202
37526
|
await client2.deleteFile(args.file_uri);
|
|
37203
|
-
return
|
|
37527
|
+
return minifiedResult({ deleted: args.file_uri });
|
|
37204
37528
|
}
|
|
37205
37529
|
);
|
|
37206
37530
|
}
|
|
@@ -37226,7 +37550,7 @@ function registerUploadUrlTools(server, client2) {
|
|
|
37226
37550
|
`minting a signed upload URL for ${args.filename} (${args.content_type})`,
|
|
37227
37551
|
() => minter.mint(args.filename, args.content_type)
|
|
37228
37552
|
);
|
|
37229
|
-
return
|
|
37553
|
+
return minifiedResult({
|
|
37230
37554
|
upload_url: minted.url,
|
|
37231
37555
|
method: "PUT",
|
|
37232
37556
|
r2_key: minted.key,
|
|
@@ -37297,7 +37621,7 @@ function registerLibraryTools(server, client2) {
|
|
|
37297
37621
|
() => resolveLibraryImage(client2, args, true)
|
|
37298
37622
|
);
|
|
37299
37623
|
const record2 = await library.saveCharacter({ name: args.name, description: args.description, image });
|
|
37300
|
-
return
|
|
37624
|
+
return minifiedResult({
|
|
37301
37625
|
saved: "character",
|
|
37302
37626
|
name: record2.name,
|
|
37303
37627
|
description: record2.description,
|
|
@@ -37317,7 +37641,7 @@ function registerLibraryTools(server, client2) {
|
|
|
37317
37641
|
},
|
|
37318
37642
|
async () => {
|
|
37319
37643
|
const characters = await library.listCharacters();
|
|
37320
|
-
return
|
|
37644
|
+
return minifiedResult({
|
|
37321
37645
|
count: characters.length,
|
|
37322
37646
|
characters: characters.map((c) => ({
|
|
37323
37647
|
name: c.name,
|
|
@@ -37344,7 +37668,7 @@ function registerLibraryTools(server, client2) {
|
|
|
37344
37668
|
if (!existed) {
|
|
37345
37669
|
throw new McpToolError(`No saved character "${args.name}". List what exists with gemini_list_characters.`);
|
|
37346
37670
|
}
|
|
37347
|
-
return
|
|
37671
|
+
return minifiedResult({ deleted: "character", name: args.name });
|
|
37348
37672
|
}
|
|
37349
37673
|
);
|
|
37350
37674
|
server.registerTool(
|
|
@@ -37366,7 +37690,7 @@ function registerLibraryTools(server, client2) {
|
|
|
37366
37690
|
() => resolveLibraryImage(client2, args, false)
|
|
37367
37691
|
);
|
|
37368
37692
|
const record2 = await library.saveStyle({ name: args.name, promptFragment: args.prompt_fragment, image });
|
|
37369
|
-
return
|
|
37693
|
+
return minifiedResult({
|
|
37370
37694
|
saved: "style",
|
|
37371
37695
|
name: record2.name,
|
|
37372
37696
|
prompt_fragment: record2.prompt_fragment,
|
|
@@ -37386,7 +37710,7 @@ function registerLibraryTools(server, client2) {
|
|
|
37386
37710
|
},
|
|
37387
37711
|
async () => {
|
|
37388
37712
|
const styles = await library.listStyles();
|
|
37389
|
-
return
|
|
37713
|
+
return minifiedResult({
|
|
37390
37714
|
count: styles.length,
|
|
37391
37715
|
styles: styles.map((s) => ({
|
|
37392
37716
|
name: s.name,
|
|
@@ -37413,7 +37737,7 @@ function registerLibraryTools(server, client2) {
|
|
|
37413
37737
|
if (!existed) {
|
|
37414
37738
|
throw new McpToolError(`No saved style "${args.name}". List what exists with gemini_list_styles.`);
|
|
37415
37739
|
}
|
|
37416
|
-
return
|
|
37740
|
+
return minifiedResult({ deleted: "style", name: args.name });
|
|
37417
37741
|
}
|
|
37418
37742
|
);
|
|
37419
37743
|
}
|
package/dist/jobs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { randomUUID, createHash } from 'node:crypto';
|
|
2
|
-
import {
|
|
2
|
+
import { McpToolError, minifiedResult } from '@chrischall/mcp-utils';
|
|
3
3
|
import { downloadFilename } from './media-name.js';
|
|
4
4
|
import { HEARTBEAT_MS } from './job-store.js';
|
|
5
5
|
import { annotateReusedUsage } from './usage.js';
|
|
@@ -151,7 +151,7 @@ function annotateReused(result, jobId) {
|
|
|
151
151
|
}
|
|
152
152
|
/** Immediate handle for an async call — the caller polls `gemini_get_result`. */
|
|
153
153
|
function jobHandle(jobId, status, durable = false) {
|
|
154
|
-
return
|
|
154
|
+
return minifiedResult({
|
|
155
155
|
job_id: jobId,
|
|
156
156
|
status,
|
|
157
157
|
hint: durable
|
package/dist/tools/_confirm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { minifiedResult, schemaConfirm } from '@chrischall/mcp-utils';
|
|
2
2
|
import { previewImageInput, previewVideoInput } from '../images.js';
|
|
3
3
|
export { schemaConfirm };
|
|
4
4
|
/**
|
|
@@ -9,7 +9,7 @@ export { schemaConfirm };
|
|
|
9
9
|
export function previewUnlessConfirmed(confirm, action, method, path, body) {
|
|
10
10
|
if (confirm === true)
|
|
11
11
|
return null;
|
|
12
|
-
return
|
|
12
|
+
return minifiedResult({
|
|
13
13
|
dryRun: true,
|
|
14
14
|
action,
|
|
15
15
|
method,
|
package/dist/tools/files.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { McpToolError,
|
|
2
|
+
import { McpToolError, minifiedResult } from '@chrischall/mcp-utils';
|
|
3
3
|
import { withProgressHeartbeat } from './shared.js';
|
|
4
4
|
import { base64ToBytes, wholeMb } from '../bytes.js';
|
|
5
5
|
import { fileNameFromUrl } from '../fetch-image.js';
|
|
@@ -47,7 +47,7 @@ const RETENTION_NOTE = 'Gemini retains uploaded files for ~48h. Until then this
|
|
|
47
47
|
'(images_file_uris on gemini_image_generate / _edit / _set / gemini_interact, or video_url) without re-sending the bytes.';
|
|
48
48
|
/** Shape returned by every upload path. */
|
|
49
49
|
function uploadResult(file) {
|
|
50
|
-
return
|
|
50
|
+
return minifiedResult({
|
|
51
51
|
// The `files/<id>` form is what every tool parameter documents, so it leads.
|
|
52
52
|
file_uri: file.name,
|
|
53
53
|
// The absolute uri, for callers that would rather pass it through verbatim.
|
|
@@ -178,7 +178,7 @@ export function registerFileTools(server, client) {
|
|
|
178
178
|
},
|
|
179
179
|
}, async (args) => {
|
|
180
180
|
const files = await client.listFiles(args.page_size ?? 100);
|
|
181
|
-
return
|
|
181
|
+
return minifiedResult({
|
|
182
182
|
count: files.length,
|
|
183
183
|
files: files.map((f) => ({
|
|
184
184
|
file_uri: f.name,
|
|
@@ -220,7 +220,7 @@ export function registerFileTools(server, client) {
|
|
|
220
220
|
// Remediation goes in the MESSAGE: MCP serialization drops hints.
|
|
221
221
|
throw new McpToolError(`No stored media for r2_key "${args.r2_key}" — it has probably passed its retention window. Re-run the generation to get a new one.`, { hint: 'Objects are swept on a retention schedule (MEDIA_TTL_DAYS, default 7 days).' });
|
|
222
222
|
}
|
|
223
|
-
return
|
|
223
|
+
return minifiedResult({
|
|
224
224
|
url: fresh.ref,
|
|
225
225
|
r2_key: fresh.key,
|
|
226
226
|
...(fresh.expiresAt ? { expires_at: fresh.expiresAt } : {}),
|
|
@@ -258,7 +258,7 @@ export function registerFileTools(server, client) {
|
|
|
258
258
|
? await sink.listRecentPage({ limit, sinceDay: args.since_day })
|
|
259
259
|
: { media: await sink.listRecent({ limit, sinceDay: args.since_day }), truncated: false };
|
|
260
260
|
const found = page.media;
|
|
261
|
-
return
|
|
261
|
+
return minifiedResult({
|
|
262
262
|
count: found.length,
|
|
263
263
|
// Never let a bounded walk pass for the whole picture: concluding an
|
|
264
264
|
// image is gone is what makes someone pay to generate it twice.
|
|
@@ -293,6 +293,6 @@ export function registerFileTools(server, client) {
|
|
|
293
293
|
if (gate)
|
|
294
294
|
return gate;
|
|
295
295
|
await client.deleteFile(args.file_uri);
|
|
296
|
-
return
|
|
296
|
+
return minifiedResult({ deleted: args.file_uri });
|
|
297
297
|
});
|
|
298
298
|
}
|
package/dist/tools/jobs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { McpToolError,
|
|
2
|
+
import { McpToolError, minifiedResult } from '@chrischall/mcp-utils';
|
|
3
3
|
import { TERMINAL_INTERACTION_STATUSES } from '../client.js';
|
|
4
4
|
import { emitMedia } from './shared.js';
|
|
5
5
|
import { slugify } from '../images.js';
|
|
@@ -128,7 +128,7 @@ function recoveryNote(recordedError) {
|
|
|
128
128
|
}
|
|
129
129
|
/** The generation outlived its executor and is not finished yet. */
|
|
130
130
|
function stillRunning(jobId, interactionId) {
|
|
131
|
-
return
|
|
131
|
+
return minifiedResult({
|
|
132
132
|
job_id: jobId,
|
|
133
133
|
status: 'running',
|
|
134
134
|
interaction_id: interactionId,
|
package/dist/tools/library.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { McpToolError,
|
|
2
|
+
import { McpToolError, minifiedResult } from '@chrischall/mcp-utils';
|
|
3
3
|
import { LIBRARY_NAME_PATTERN } from '../library.js';
|
|
4
4
|
import { acceptableUploadType } from '../upload-url.js';
|
|
5
5
|
import { withProgressHeartbeat } from './shared.js';
|
|
@@ -79,7 +79,7 @@ export function registerLibraryTools(server, client) {
|
|
|
79
79
|
}, async (args, extra) => {
|
|
80
80
|
const image = (await withProgressHeartbeat(extra, 'Loading the reference image', () => resolveLibraryImage(client, args, true)));
|
|
81
81
|
const record = await library.saveCharacter({ name: args.name, description: args.description, image });
|
|
82
|
-
return
|
|
82
|
+
return minifiedResult({
|
|
83
83
|
saved: 'character',
|
|
84
84
|
name: record.name,
|
|
85
85
|
description: record.description,
|
|
@@ -96,7 +96,7 @@ export function registerLibraryTools(server, client) {
|
|
|
96
96
|
inputSchema: {},
|
|
97
97
|
}, async () => {
|
|
98
98
|
const characters = await library.listCharacters();
|
|
99
|
-
return
|
|
99
|
+
return minifiedResult({
|
|
100
100
|
count: characters.length,
|
|
101
101
|
characters: characters.map((c) => ({
|
|
102
102
|
name: c.name,
|
|
@@ -122,7 +122,7 @@ export function registerLibraryTools(server, client) {
|
|
|
122
122
|
if (!existed) {
|
|
123
123
|
throw new McpToolError(`No saved character "${args.name}". List what exists with gemini_list_characters.`);
|
|
124
124
|
}
|
|
125
|
-
return
|
|
125
|
+
return minifiedResult({ deleted: 'character', name: args.name });
|
|
126
126
|
});
|
|
127
127
|
server.registerTool('gemini_save_style', {
|
|
128
128
|
description: 'Save a named style preset to this account\'s persistent reference library: a reusable prompt fragment (and ' +
|
|
@@ -141,7 +141,7 @@ export function registerLibraryTools(server, client) {
|
|
|
141
141
|
}, async (args, extra) => {
|
|
142
142
|
const image = await withProgressHeartbeat(extra, 'Loading the style reference image', () => resolveLibraryImage(client, args, false));
|
|
143
143
|
const record = await library.saveStyle({ name: args.name, promptFragment: args.prompt_fragment, image });
|
|
144
|
-
return
|
|
144
|
+
return minifiedResult({
|
|
145
145
|
saved: 'style',
|
|
146
146
|
name: record.name,
|
|
147
147
|
prompt_fragment: record.prompt_fragment,
|
|
@@ -157,7 +157,7 @@ export function registerLibraryTools(server, client) {
|
|
|
157
157
|
inputSchema: {},
|
|
158
158
|
}, async () => {
|
|
159
159
|
const styles = await library.listStyles();
|
|
160
|
-
return
|
|
160
|
+
return minifiedResult({
|
|
161
161
|
count: styles.length,
|
|
162
162
|
styles: styles.map((s) => ({
|
|
163
163
|
name: s.name,
|
|
@@ -181,6 +181,6 @@ export function registerLibraryTools(server, client) {
|
|
|
181
181
|
if (!existed) {
|
|
182
182
|
throw new McpToolError(`No saved style "${args.name}". List what exists with gemini_list_styles.`);
|
|
183
183
|
}
|
|
184
|
-
return
|
|
184
|
+
return minifiedResult({ deleted: 'style', name: args.name });
|
|
185
185
|
});
|
|
186
186
|
}
|
package/dist/tools/models.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { minifiedResult } from '@chrischall/mcp-utils';
|
|
2
2
|
export function registerModelTools(server, client) {
|
|
3
3
|
server.registerTool('gemini_list_models', {
|
|
4
4
|
description: 'List the Gemini image-generation models available to your API key (Nano Banana / Nano Banana Pro family), and the current default model.',
|
|
5
5
|
annotations: { readOnlyHint: true },
|
|
6
6
|
}, async () => {
|
|
7
7
|
const models = await client.listModels();
|
|
8
|
-
return
|
|
8
|
+
return minifiedResult({ default: client.defaultModel(), models });
|
|
9
9
|
});
|
|
10
10
|
}
|
package/dist/tools/shared.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import {
|
|
2
|
+
import { McpToolError, minifiedResult, readEnvVar } from '@chrischall/mcp-utils';
|
|
3
3
|
import { resolveVideoPath, videoMimeType } from '../images.js';
|
|
4
4
|
import { IMAGE_URL_MAX_BYTES, IMAGE_INLINE_MAX_BYTES } from '../fetch-image.js';
|
|
5
5
|
import { bytesToBase64, base64ToBytes, wholeMb } from '../bytes.js';
|
|
@@ -535,7 +535,7 @@ export async function emitMedia(named, kind, opts, meta, onWritten) {
|
|
|
535
535
|
}
|
|
536
536
|
: {};
|
|
537
537
|
const storage = sink.persistsFiles ? {} : { storage: sink.kind, storage_note: storageNote };
|
|
538
|
-
return
|
|
538
|
+
return minifiedResult({ [`${kind}s`]: refs, ...media, ...unavailable, ...note, ...storage, ...meta });
|
|
539
539
|
}
|
|
540
540
|
/**
|
|
541
541
|
* Image convenience wrapper over {@link emitMedia} — preserves the original
|
package/dist/tools/uploads.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import {
|
|
2
|
+
import { minifiedResult } from '@chrischall/mcp-utils';
|
|
3
3
|
import { UPLOAD_MAX_BYTES, RASTER_IMAGE_TYPE_PATTERN } from '../upload-url.js';
|
|
4
4
|
import { wholeMb } from '../bytes.js';
|
|
5
5
|
import { step } from '../errors.js';
|
|
@@ -71,7 +71,7 @@ export function registerUploadUrlTools(server, client) {
|
|
|
71
71
|
// between them a mint failure can no longer reach the client as a bare
|
|
72
72
|
// "Error occurred during tool execution".
|
|
73
73
|
const minted = await step(`minting a signed upload URL for ${args.filename} (${args.content_type})`, () => minter.mint(args.filename, args.content_type));
|
|
74
|
-
return
|
|
74
|
+
return minifiedResult({
|
|
75
75
|
upload_url: minted.url,
|
|
76
76
|
method: 'PUT',
|
|
77
77
|
r2_key: minted.key,
|
package/dist/tools/usage.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import {
|
|
2
|
+
import { minifiedResult, toolAnnotations } from '@chrischall/mcp-utils';
|
|
3
3
|
import { PRICED_AT } from '../pricing.js';
|
|
4
4
|
/**
|
|
5
5
|
* What this session has spent, in tokens.
|
|
@@ -51,7 +51,7 @@ export function registerUsageTools(server, client) {
|
|
|
51
51
|
client.session.costUsd = undefined;
|
|
52
52
|
client.session.pricedCalls = 0;
|
|
53
53
|
}
|
|
54
|
-
return
|
|
54
|
+
return minifiedResult({
|
|
55
55
|
usage: usage ?? null,
|
|
56
56
|
billed_calls: calls,
|
|
57
57
|
estimated_cost_usd: costUsd ?? null,
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Single source of the server version. release-please bumps the literal below. */
|
|
2
|
-
export const VERSION = '1.
|
|
2
|
+
export const VERSION = '1.13.0'; // x-release-please-version
|
package/mint.yaml
CHANGED
|
@@ -38,6 +38,12 @@ env:
|
|
|
38
38
|
How often, in milliseconds, to emit a progress notification while a
|
|
39
39
|
generation is in flight. Hosts reset their tools/call timeout on progress,
|
|
40
40
|
so this lets a long 4K/Pro generation outlive the default budget.
|
|
41
|
+
- name: GEMINI_RATE_CARD
|
|
42
|
+
required: false
|
|
43
|
+
help: >-
|
|
44
|
+
JSON overriding or extending the built-in pricing card, so a stale rate is
|
|
45
|
+
yours to fix in your own environment rather than waiting on a release.
|
|
46
|
+
Anything absent from the card prices as unknown rather than zero.
|
|
41
47
|
egress:
|
|
42
48
|
allow:
|
|
43
49
|
# Only hosts the SERVER process actually fetches. Hosts that appear
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chrischall/gemini-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.0",
|
|
4
4
|
"mcpName": "io.github.chrischall/gemini-mcp",
|
|
5
5
|
"description": "Gemini image-generation MCP server for Claude — developed and maintained by AI (Claude Code)",
|
|
6
6
|
"author": "Claude Code (AI) <https://www.anthropic.com/claude>",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"typecheck": "tsc -p tsconfig.test.json"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@chrischall/mcp-utils": "^0.
|
|
49
|
+
"@chrischall/mcp-utils": "^0.23.0",
|
|
50
50
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
51
51
|
"dotenv": "^17.4.0",
|
|
52
52
|
"zod": "^4.4.2"
|
package/server.json
CHANGED
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
"url": "https://github.com/chrischall/gemini-mcp",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "1.
|
|
9
|
+
"version": "1.13.0",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"identifier": "@chrischall/gemini-mcp",
|
|
14
|
-
"version": "1.
|
|
14
|
+
"version": "1.13.0",
|
|
15
15
|
"transport": {
|
|
16
16
|
"type": "stdio"
|
|
17
17
|
},
|