mcp-ts-template 2.1.7 → 2.2.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/README.md +58 -49
- package/dist/index.js +336 -124
- package/package.json +5 -3
- package/dist/worker.js +0 -60707
package/dist/index.js
CHANGED
|
@@ -117229,7 +117229,7 @@ var z = /* @__PURE__ */ Object.freeze({
|
|
|
117229
117229
|
// package.json
|
|
117230
117230
|
var package_default = {
|
|
117231
117231
|
name: "mcp-ts-template",
|
|
117232
|
-
version: "2.1.
|
|
117232
|
+
version: "2.1.8",
|
|
117233
117233
|
mcpName: "io.github.cyanheads/mcp-ts-template",
|
|
117234
117234
|
description: "The definitive, production-grade template for building powerful and scalable Model Context Protocol (MCP) servers with TypeScript, featuring built-in observability (OpenTelemetry), declarative tooling, robust error handling, and a modular, DI-driven architecture.",
|
|
117235
117235
|
main: "dist/index.js",
|
|
@@ -117284,8 +117284,8 @@ var package_default = {
|
|
|
117284
117284
|
prepare: "[ -d .husky ] && husky || true",
|
|
117285
117285
|
inspector: "bunx mcp-inspector --config mcp.json --server mcp-ts-template",
|
|
117286
117286
|
"db:duckdb-example": "MCP_LOG_LEVEL=debug tsc && node dist/storage/duckdbExample.js",
|
|
117287
|
-
test: "bun test",
|
|
117288
|
-
"test:coverage": "bun test --coverage",
|
|
117287
|
+
test: "bun test --config vitest.config.ts",
|
|
117288
|
+
"test:coverage": "bun test --coverage --config vitest.config.ts",
|
|
117289
117289
|
audit: "bun audit",
|
|
117290
117290
|
"audit:fix": "bun audit --fix",
|
|
117291
117291
|
"publish-mcp": "bun scripts/validate-mcp-publish-schema.ts"
|
|
@@ -117307,7 +117307,7 @@ var package_default = {
|
|
|
117307
117307
|
"chrono-node": "^2.9.0",
|
|
117308
117308
|
dotenv: "^17.2.2",
|
|
117309
117309
|
"fast-xml-parser": "^5.2.5",
|
|
117310
|
-
hono: "^4.9.
|
|
117310
|
+
hono: "^4.9.9",
|
|
117311
117311
|
ignore: "^7.0.5",
|
|
117312
117312
|
jose: "^6.1.0",
|
|
117313
117313
|
"js-yaml": "^4.1.0",
|
|
@@ -117319,6 +117319,7 @@ var package_default = {
|
|
|
117319
117319
|
"reflect-metadata": "^0.2.2",
|
|
117320
117320
|
repomix: "^1.6.0",
|
|
117321
117321
|
"sanitize-html": "^2.17.0",
|
|
117322
|
+
"@apidevtools/swagger-parser": "^12.0.0",
|
|
117322
117323
|
tslib: "^2.8.1",
|
|
117323
117324
|
tsyringe: "^4.10.0",
|
|
117324
117325
|
validator: "13.15.15",
|
|
@@ -117749,6 +117750,7 @@ var JsonRpcErrorCode;
|
|
|
117749
117750
|
JsonRpcErrorCode2[JsonRpcErrorCode2["ConfigurationError"] = -32008] = "ConfigurationError";
|
|
117750
117751
|
JsonRpcErrorCode2[JsonRpcErrorCode2["InitializationFailed"] = -32009] = "InitializationFailed";
|
|
117751
117752
|
JsonRpcErrorCode2[JsonRpcErrorCode2["DatabaseError"] = -32010] = "DatabaseError";
|
|
117753
|
+
JsonRpcErrorCode2[JsonRpcErrorCode2["SerializationError"] = -32070] = "SerializationError";
|
|
117752
117754
|
JsonRpcErrorCode2[JsonRpcErrorCode2["UnknownError"] = -32099] = "UnknownError";
|
|
117753
117755
|
})(JsonRpcErrorCode ||= {});
|
|
117754
117756
|
|
|
@@ -124912,6 +124914,8 @@ var import_tsyringe5 = __toESM(require_cjs3(), 1);
|
|
|
124912
124914
|
import { existsSync, mkdirSync } from "fs";
|
|
124913
124915
|
import { readFile, readdir, rm, writeFile } from "fs/promises";
|
|
124914
124916
|
import path2 from "path";
|
|
124917
|
+
var FILE_ENVELOPE_VERSION = 1;
|
|
124918
|
+
|
|
124915
124919
|
class FileSystemProvider {
|
|
124916
124920
|
storagePath;
|
|
124917
124921
|
constructor(storagePath) {
|
|
@@ -124948,12 +124952,38 @@ class FileSystemProvider {
|
|
|
124948
124952
|
}
|
|
124949
124953
|
return filePath;
|
|
124950
124954
|
}
|
|
124955
|
+
buildEnvelope(value, options) {
|
|
124956
|
+
const expiresAt = options?.ttl ? Date.now() + options.ttl * 1000 : undefined;
|
|
124957
|
+
return {
|
|
124958
|
+
__mcp: { v: FILE_ENVELOPE_VERSION, ...expiresAt ? { expiresAt } : {} },
|
|
124959
|
+
value
|
|
124960
|
+
};
|
|
124961
|
+
}
|
|
124962
|
+
async parseAndValidate(raw, tenantId, key, filePath, context) {
|
|
124963
|
+
try {
|
|
124964
|
+
const parsed = JSON.parse(raw);
|
|
124965
|
+
if (parsed && typeof parsed === "object" && "__mcp" in parsed) {
|
|
124966
|
+
const env2 = parsed;
|
|
124967
|
+
const expiresAt = env2.__mcp?.expiresAt;
|
|
124968
|
+
if (expiresAt && Date.now() > expiresAt) {
|
|
124969
|
+
try {
|
|
124970
|
+
await rm(filePath);
|
|
124971
|
+
} catch {}
|
|
124972
|
+
return null;
|
|
124973
|
+
}
|
|
124974
|
+
return env2.value;
|
|
124975
|
+
}
|
|
124976
|
+
return parsed;
|
|
124977
|
+
} catch (error2) {
|
|
124978
|
+
throw new McpError(-32070 /* SerializationError */, `Failed to parse stored JSON for key "${key}" (tenant "${tenantId}").`, { ...context, error: error2 });
|
|
124979
|
+
}
|
|
124980
|
+
}
|
|
124951
124981
|
async get(tenantId, key, context) {
|
|
124952
124982
|
const filePath = this.getFilePath(tenantId, key);
|
|
124953
124983
|
return ErrorHandler.tryCatch(async () => {
|
|
124954
124984
|
try {
|
|
124955
124985
|
const data = await readFile(filePath, "utf-8");
|
|
124956
|
-
return
|
|
124986
|
+
return this.parseAndValidate(data, tenantId, key, filePath, context);
|
|
124957
124987
|
} catch (error2) {
|
|
124958
124988
|
if (error2 instanceof Error && "code" in error2 && error2.code === "ENOENT") {
|
|
124959
124989
|
return null;
|
|
@@ -124966,10 +124996,11 @@ class FileSystemProvider {
|
|
|
124966
124996
|
input: { tenantId, key }
|
|
124967
124997
|
});
|
|
124968
124998
|
}
|
|
124969
|
-
async set(tenantId, key, value, context) {
|
|
124999
|
+
async set(tenantId, key, value, context, options) {
|
|
124970
125000
|
const filePath = this.getFilePath(tenantId, key);
|
|
124971
125001
|
return ErrorHandler.tryCatch(async () => {
|
|
124972
|
-
const
|
|
125002
|
+
const envelope = this.buildEnvelope(value, options);
|
|
125003
|
+
const content = JSON.stringify(envelope, null, 2);
|
|
124973
125004
|
mkdirSync(path2.dirname(filePath), { recursive: true });
|
|
124974
125005
|
await writeFile(filePath, content, "utf-8");
|
|
124975
125006
|
}, {
|
|
@@ -124996,11 +125027,39 @@ class FileSystemProvider {
|
|
|
124996
125027
|
input: { tenantId, key }
|
|
124997
125028
|
});
|
|
124998
125029
|
}
|
|
125030
|
+
async listFilesRecursively(dir, baseDir) {
|
|
125031
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
125032
|
+
const results = [];
|
|
125033
|
+
for (const entry of entries) {
|
|
125034
|
+
const fullPath = path2.join(dir, entry.name);
|
|
125035
|
+
if (entry.isDirectory()) {
|
|
125036
|
+
results.push(...await this.listFilesRecursively(fullPath, baseDir));
|
|
125037
|
+
} else if (entry.isFile()) {
|
|
125038
|
+
const rel = path2.relative(baseDir, fullPath);
|
|
125039
|
+
results.push(rel.split(path2.sep).join("/"));
|
|
125040
|
+
}
|
|
125041
|
+
}
|
|
125042
|
+
return results;
|
|
125043
|
+
}
|
|
124999
125044
|
async list(tenantId, prefix, context) {
|
|
125000
125045
|
return ErrorHandler.tryCatch(async () => {
|
|
125001
125046
|
const tenantPath = this.getTenantPath(tenantId);
|
|
125002
|
-
const
|
|
125003
|
-
|
|
125047
|
+
const allKeys = await this.listFilesRecursively(tenantPath, tenantPath);
|
|
125048
|
+
const candidateKeys = allKeys.filter((k) => k.startsWith(prefix));
|
|
125049
|
+
const validKeys = [];
|
|
125050
|
+
for (const k of candidateKeys) {
|
|
125051
|
+
const filePath = this.getFilePath(tenantId, k);
|
|
125052
|
+
try {
|
|
125053
|
+
const raw = await readFile(filePath, "utf-8");
|
|
125054
|
+
const value = await this.parseAndValidate(raw, tenantId, k, filePath, context);
|
|
125055
|
+
if (value !== null) {
|
|
125056
|
+
validKeys.push(k);
|
|
125057
|
+
}
|
|
125058
|
+
} catch (_e) {
|
|
125059
|
+
continue;
|
|
125060
|
+
}
|
|
125061
|
+
}
|
|
125062
|
+
return validKeys;
|
|
125004
125063
|
}, {
|
|
125005
125064
|
operation: "FileSystemProvider.list",
|
|
125006
125065
|
context,
|
|
@@ -125153,6 +125212,8 @@ SupabaseProvider = __legacyDecorateClassTS([
|
|
|
125153
125212
|
], SupabaseProvider);
|
|
125154
125213
|
|
|
125155
125214
|
// src/storage/providers/cloudflare/r2Provider.ts
|
|
125215
|
+
var R2_ENVELOPE_VERSION = 1;
|
|
125216
|
+
|
|
125156
125217
|
class R2Provider {
|
|
125157
125218
|
bucket;
|
|
125158
125219
|
constructor(bucket) {
|
|
@@ -125161,58 +125222,99 @@ class R2Provider {
|
|
|
125161
125222
|
getR2Key(tenantId, key) {
|
|
125162
125223
|
return `${tenantId}:${key}`;
|
|
125163
125224
|
}
|
|
125164
|
-
|
|
125165
|
-
const
|
|
125166
|
-
|
|
125167
|
-
|
|
125168
|
-
|
|
125169
|
-
|
|
125170
|
-
|
|
125171
|
-
|
|
125225
|
+
buildEnvelope(value, options) {
|
|
125226
|
+
const expiresAt = options?.ttl ? Date.now() + options.ttl * 1000 : undefined;
|
|
125227
|
+
return {
|
|
125228
|
+
__mcp: { v: R2_ENVELOPE_VERSION, ...expiresAt ? { expiresAt } : {} },
|
|
125229
|
+
value
|
|
125230
|
+
};
|
|
125231
|
+
}
|
|
125232
|
+
parseAndValidate(raw, tenantId, key, context) {
|
|
125172
125233
|
try {
|
|
125173
|
-
|
|
125234
|
+
const parsed = JSON.parse(raw);
|
|
125235
|
+
if (parsed && typeof parsed === "object" && "__mcp" in parsed) {
|
|
125236
|
+
const env2 = parsed;
|
|
125237
|
+
const expiresAt = env2.__mcp?.expiresAt;
|
|
125238
|
+
if (expiresAt && Date.now() > expiresAt) {
|
|
125239
|
+
return null;
|
|
125240
|
+
}
|
|
125241
|
+
return env2.value;
|
|
125242
|
+
}
|
|
125243
|
+
return parsed;
|
|
125174
125244
|
} catch (error2) {
|
|
125175
|
-
|
|
125176
|
-
...context,
|
|
125177
|
-
error: error2
|
|
125178
|
-
});
|
|
125179
|
-
return null;
|
|
125245
|
+
throw new McpError(-32070 /* SerializationError */, `[R2Provider] Failed to parse JSON for key: ${this.getR2Key(tenantId, key)}`, { ...context, error: error2 });
|
|
125180
125246
|
}
|
|
125181
125247
|
}
|
|
125248
|
+
async get(tenantId, key, context) {
|
|
125249
|
+
const r2Key = this.getR2Key(tenantId, key);
|
|
125250
|
+
return ErrorHandler.tryCatch(async () => {
|
|
125251
|
+
logger.debug(`[R2Provider] Getting key: ${r2Key}`, context);
|
|
125252
|
+
const object = await this.bucket.get(r2Key);
|
|
125253
|
+
if (object === null) {
|
|
125254
|
+
return null;
|
|
125255
|
+
}
|
|
125256
|
+
const text = await object.text();
|
|
125257
|
+
const value = this.parseAndValidate(text, tenantId, key, context);
|
|
125258
|
+
if (value === null) {
|
|
125259
|
+
await this.bucket.delete(r2Key).catch(() => {});
|
|
125260
|
+
logger.debug(`[R2Provider] Key expired and removed: ${r2Key}`, context);
|
|
125261
|
+
}
|
|
125262
|
+
return value;
|
|
125263
|
+
}, {
|
|
125264
|
+
operation: "R2Provider.get",
|
|
125265
|
+
context,
|
|
125266
|
+
input: { tenantId, key }
|
|
125267
|
+
});
|
|
125268
|
+
}
|
|
125182
125269
|
async set(tenantId, key, value, context, options) {
|
|
125183
125270
|
const r2Key = this.getR2Key(tenantId, key);
|
|
125184
|
-
|
|
125185
|
-
|
|
125186
|
-
|
|
125187
|
-
|
|
125188
|
-
|
|
125189
|
-
|
|
125190
|
-
|
|
125191
|
-
|
|
125271
|
+
return ErrorHandler.tryCatch(async () => {
|
|
125272
|
+
logger.debug(`[R2Provider] Setting key: ${r2Key}`, {
|
|
125273
|
+
...context,
|
|
125274
|
+
options
|
|
125275
|
+
});
|
|
125276
|
+
const envelope = this.buildEnvelope(value, options);
|
|
125277
|
+
const body = JSON.stringify(envelope);
|
|
125278
|
+
await this.bucket.put(r2Key, body);
|
|
125279
|
+
logger.debug(`[R2Provider] Successfully set key: ${r2Key}`, context);
|
|
125280
|
+
}, {
|
|
125281
|
+
operation: "R2Provider.set",
|
|
125282
|
+
context,
|
|
125283
|
+
input: { tenantId, key }
|
|
125284
|
+
});
|
|
125192
125285
|
}
|
|
125193
125286
|
async delete(tenantId, key, context) {
|
|
125194
125287
|
const r2Key = this.getR2Key(tenantId, key);
|
|
125195
|
-
|
|
125196
|
-
|
|
125197
|
-
|
|
125198
|
-
|
|
125199
|
-
|
|
125200
|
-
|
|
125201
|
-
|
|
125202
|
-
|
|
125203
|
-
|
|
125288
|
+
return ErrorHandler.tryCatch(async () => {
|
|
125289
|
+
logger.debug(`[R2Provider] Deleting key: ${r2Key}`, context);
|
|
125290
|
+
const head = await this.bucket.head(r2Key);
|
|
125291
|
+
if (head === null) {
|
|
125292
|
+
logger.debug(`[R2Provider] Key to delete not found: ${r2Key}`, context);
|
|
125293
|
+
return false;
|
|
125294
|
+
}
|
|
125295
|
+
await this.bucket.delete(r2Key);
|
|
125296
|
+
logger.debug(`[R2Provider] Successfully deleted key: ${r2Key}`, context);
|
|
125297
|
+
return true;
|
|
125298
|
+
}, {
|
|
125299
|
+
operation: "R2Provider.delete",
|
|
125300
|
+
context,
|
|
125301
|
+
input: { tenantId, key }
|
|
125302
|
+
});
|
|
125204
125303
|
}
|
|
125205
125304
|
async list(tenantId, prefix, context) {
|
|
125206
125305
|
const r2Prefix = this.getR2Key(tenantId, prefix);
|
|
125207
|
-
|
|
125208
|
-
|
|
125209
|
-
prefix: r2Prefix
|
|
125210
|
-
|
|
125211
|
-
|
|
125212
|
-
|
|
125213
|
-
|
|
125214
|
-
|
|
125215
|
-
|
|
125306
|
+
return ErrorHandler.tryCatch(async () => {
|
|
125307
|
+
logger.debug(`[R2Provider] Listing keys with prefix: ${r2Prefix}`, context);
|
|
125308
|
+
const listed = await this.bucket.list({ prefix: r2Prefix });
|
|
125309
|
+
const tenantPrefix = `${tenantId}:`;
|
|
125310
|
+
const keys = listed.objects.map((obj) => obj.key.startsWith(tenantPrefix) ? obj.key.substring(tenantPrefix.length) : obj.key);
|
|
125311
|
+
logger.debug(`[R2Provider] Found ${keys.length} keys with prefix: ${r2Prefix}`, context);
|
|
125312
|
+
return keys;
|
|
125313
|
+
}, {
|
|
125314
|
+
operation: "R2Provider.list",
|
|
125315
|
+
context,
|
|
125316
|
+
input: { tenantId, prefix }
|
|
125317
|
+
});
|
|
125216
125318
|
}
|
|
125217
125319
|
}
|
|
125218
125320
|
|
|
@@ -125227,59 +125329,78 @@ class KvProvider {
|
|
|
125227
125329
|
}
|
|
125228
125330
|
async get(tenantId, key, context) {
|
|
125229
125331
|
const kvKey = this.getKvKey(tenantId, key);
|
|
125230
|
-
|
|
125231
|
-
|
|
125232
|
-
|
|
125233
|
-
|
|
125234
|
-
|
|
125235
|
-
|
|
125332
|
+
return ErrorHandler.tryCatch(async () => {
|
|
125333
|
+
logger.debug(`[KvProvider] Getting key: ${kvKey}`, context);
|
|
125334
|
+
try {
|
|
125335
|
+
const result = await this.kv.get(kvKey, "json");
|
|
125336
|
+
return result;
|
|
125337
|
+
} catch (error2) {
|
|
125338
|
+
throw new McpError(-32070 /* SerializationError */, `[KvProvider] Failed to parse JSON for key: ${kvKey}`, { ...context, error: error2 });
|
|
125236
125339
|
}
|
|
125237
|
-
|
|
125238
|
-
|
|
125239
|
-
|
|
125240
|
-
|
|
125241
|
-
|
|
125242
|
-
});
|
|
125243
|
-
return null;
|
|
125244
|
-
}
|
|
125340
|
+
}, {
|
|
125341
|
+
operation: "KvProvider.get",
|
|
125342
|
+
context,
|
|
125343
|
+
input: { tenantId, key }
|
|
125344
|
+
});
|
|
125245
125345
|
}
|
|
125246
125346
|
async set(tenantId, key, value, context, options) {
|
|
125247
125347
|
const kvKey = this.getKvKey(tenantId, key);
|
|
125248
|
-
|
|
125249
|
-
|
|
125250
|
-
|
|
125251
|
-
|
|
125252
|
-
|
|
125253
|
-
|
|
125254
|
-
|
|
125255
|
-
|
|
125348
|
+
return ErrorHandler.tryCatch(async () => {
|
|
125349
|
+
logger.debug(`[KvProvider] Setting key: ${kvKey}`, {
|
|
125350
|
+
...context,
|
|
125351
|
+
options
|
|
125352
|
+
});
|
|
125353
|
+
const valueToStore = JSON.stringify(value);
|
|
125354
|
+
const putOptions = {};
|
|
125355
|
+
if (options?.ttl) {
|
|
125356
|
+
putOptions.expirationTtl = options.ttl;
|
|
125357
|
+
}
|
|
125358
|
+
await this.kv.put(kvKey, valueToStore, putOptions);
|
|
125359
|
+
logger.debug(`[KvProvider] Successfully set key: ${kvKey}`, context);
|
|
125360
|
+
}, {
|
|
125361
|
+
operation: "KvProvider.set",
|
|
125362
|
+
context,
|
|
125363
|
+
input: { tenantId, key }
|
|
125364
|
+
});
|
|
125256
125365
|
}
|
|
125257
125366
|
async delete(tenantId, key, context) {
|
|
125258
125367
|
const kvKey = this.getKvKey(tenantId, key);
|
|
125259
|
-
|
|
125260
|
-
|
|
125261
|
-
|
|
125262
|
-
|
|
125263
|
-
|
|
125264
|
-
|
|
125265
|
-
|
|
125266
|
-
|
|
125267
|
-
|
|
125368
|
+
return ErrorHandler.tryCatch(async () => {
|
|
125369
|
+
logger.debug(`[KvProvider] Deleting key: ${kvKey}`, context);
|
|
125370
|
+
const value = await this.kv.get(kvKey);
|
|
125371
|
+
if (value === null) {
|
|
125372
|
+
logger.debug(`[KvProvider] Key to delete not found: ${kvKey}`, context);
|
|
125373
|
+
return false;
|
|
125374
|
+
}
|
|
125375
|
+
await this.kv.delete(kvKey);
|
|
125376
|
+
logger.debug(`[KvProvider] Successfully deleted key: ${kvKey}`, context);
|
|
125377
|
+
return true;
|
|
125378
|
+
}, {
|
|
125379
|
+
operation: "KvProvider.delete",
|
|
125380
|
+
context,
|
|
125381
|
+
input: { tenantId, key }
|
|
125382
|
+
});
|
|
125268
125383
|
}
|
|
125269
125384
|
async list(tenantId, prefix, context) {
|
|
125270
125385
|
const kvPrefix = this.getKvKey(tenantId, prefix);
|
|
125271
|
-
|
|
125272
|
-
|
|
125273
|
-
|
|
125274
|
-
|
|
125275
|
-
|
|
125276
|
-
|
|
125386
|
+
return ErrorHandler.tryCatch(async () => {
|
|
125387
|
+
logger.debug(`[KvProvider] Listing keys with prefix: ${kvPrefix}`, context);
|
|
125388
|
+
const listed = await this.kv.list({ prefix: kvPrefix });
|
|
125389
|
+
const tenantPrefix = `${tenantId}:`;
|
|
125390
|
+
const keys = listed.keys.map((keyInfo) => keyInfo.name.startsWith(tenantPrefix) ? keyInfo.name.substring(tenantPrefix.length) : keyInfo.name);
|
|
125391
|
+
logger.debug(`[KvProvider] Found ${keys.length} keys with prefix: ${kvPrefix}`, context);
|
|
125392
|
+
return keys;
|
|
125393
|
+
}, {
|
|
125394
|
+
operation: "KvProvider.list",
|
|
125395
|
+
context,
|
|
125396
|
+
input: { tenantId, prefix }
|
|
125397
|
+
});
|
|
125277
125398
|
}
|
|
125278
125399
|
}
|
|
125279
125400
|
|
|
125280
125401
|
// src/storage/core/storageFactory.ts
|
|
125281
125402
|
var isServerless3 = typeof process === "undefined" || process.env.IS_SERVERLESS === "true";
|
|
125282
|
-
function createStorageProvider(config2) {
|
|
125403
|
+
function createStorageProvider(config2, deps = {}) {
|
|
125283
125404
|
const context = requestContextService.createRequestContext({
|
|
125284
125405
|
operation: "createStorageProvider"
|
|
125285
125406
|
});
|
|
@@ -125301,16 +125422,19 @@ function createStorageProvider(config2) {
|
|
|
125301
125422
|
if (!config2.supabase?.url || !config2.supabase?.serviceRoleKey) {
|
|
125302
125423
|
throw new McpError(-32008 /* ConfigurationError */, "SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY must be set for the supabase storage provider.", context);
|
|
125303
125424
|
}
|
|
125425
|
+
if (deps.supabaseClient) {
|
|
125426
|
+
return new SupabaseProvider(deps.supabaseClient);
|
|
125427
|
+
}
|
|
125304
125428
|
return import_tsyringe5.container.resolve(SupabaseProvider);
|
|
125305
125429
|
case "cloudflare-r2":
|
|
125306
125430
|
if (isServerless3) {
|
|
125307
|
-
const bucket = globalThis.R2_BUCKET;
|
|
125431
|
+
const bucket = deps.r2Bucket ?? globalThis.R2_BUCKET;
|
|
125308
125432
|
return new R2Provider(bucket);
|
|
125309
125433
|
}
|
|
125310
125434
|
throw new McpError(-32008 /* ConfigurationError */, "Cloudflare R2 storage is only available in a Cloudflare Worker environment.", context);
|
|
125311
125435
|
case "cloudflare-kv":
|
|
125312
125436
|
if (isServerless3) {
|
|
125313
|
-
const kv = globalThis.KV_NAMESPACE;
|
|
125437
|
+
const kv = deps.kvNamespace ?? globalThis.KV_NAMESPACE;
|
|
125314
125438
|
return new KvProvider(kv);
|
|
125315
125439
|
}
|
|
125316
125440
|
throw new McpError(-32008 /* ConfigurationError */, "Cloudflare KV storage is only available in a Cloudflare Worker environment.", context);
|
|
@@ -125386,9 +125510,9 @@ function withRequiredScopes(requiredScopes) {
|
|
|
125386
125510
|
|
|
125387
125511
|
// src/mcp-server/transports/auth/lib/withAuth.ts
|
|
125388
125512
|
function withToolAuth(requiredScopes, logicFn) {
|
|
125389
|
-
return async (input, context) => {
|
|
125513
|
+
return async (input, context, sdkContext) => {
|
|
125390
125514
|
withRequiredScopes(requiredScopes);
|
|
125391
|
-
return Promise.resolve(logicFn(input, context));
|
|
125515
|
+
return Promise.resolve(logicFn(input, context, sdkContext));
|
|
125392
125516
|
};
|
|
125393
125517
|
}
|
|
125394
125518
|
function withResourceAuth(requiredScopes, logicFn) {
|
|
@@ -128692,7 +128816,7 @@ async function registerResource(server, def) {
|
|
|
128692
128816
|
description: def.description,
|
|
128693
128817
|
mimeType,
|
|
128694
128818
|
...def.examples && { examples: def.examples }
|
|
128695
|
-
}, (uri, params, callContext) => {
|
|
128819
|
+
}, async (uri, params, callContext) => {
|
|
128696
128820
|
const sessionId = typeof callContext?.sessionId === "string" ? callContext.sessionId : undefined;
|
|
128697
128821
|
const handlerContext = requestContextService.createRequestContext({
|
|
128698
128822
|
parentContext: callContext,
|
|
@@ -128705,7 +128829,7 @@ async function registerResource(server, def) {
|
|
|
128705
128829
|
});
|
|
128706
128830
|
try {
|
|
128707
128831
|
const parsedParams = def.paramsSchema.parse(params);
|
|
128708
|
-
const responseData = def.logic(uri, parsedParams, handlerContext);
|
|
128832
|
+
const responseData = await def.logic(uri, parsedParams, handlerContext);
|
|
128709
128833
|
const rawContents = formatter(responseData, {
|
|
128710
128834
|
uri,
|
|
128711
128835
|
mimeType
|
|
@@ -128767,7 +128891,7 @@ var import_tsyringe8 = __toESM(require_cjs3(), 1);
|
|
|
128767
128891
|
|
|
128768
128892
|
// src/mcp-server/tools/definitions/template-cat-fact.tool.ts
|
|
128769
128893
|
var TOOL_NAME = "template_cat_fact";
|
|
128770
|
-
var TOOL_TITLE = "
|
|
128894
|
+
var TOOL_TITLE = "Template Cat Fact";
|
|
128771
128895
|
var TOOL_DESCRIPTION = "Fetches a random cat fact from a public API with an optional maximum length.";
|
|
128772
128896
|
var TOOL_ANNOTATIONS = {
|
|
128773
128897
|
readOnlyHint: true,
|
|
@@ -128789,20 +128913,20 @@ var OutputSchema2 = z.object({
|
|
|
128789
128913
|
requestedMaxLength: z.number().int().optional().describe("The maximum length that was requested for the fact."),
|
|
128790
128914
|
timestamp: z.string().datetime().describe("ISO 8601 timestamp of when the response was generated.")
|
|
128791
128915
|
}).describe("Cat fact tool response payload.");
|
|
128792
|
-
async function catFactToolLogic(input,
|
|
128916
|
+
async function catFactToolLogic(input, appContext, _sdkContext) {
|
|
128793
128917
|
logger.debug("Processing template_cat_fact logic.", {
|
|
128794
|
-
...
|
|
128918
|
+
...appContext,
|
|
128795
128919
|
toolInput: input
|
|
128796
128920
|
});
|
|
128797
128921
|
const url = input.maxLength !== undefined ? `${CAT_FACT_API_URL}?max_length=${input.maxLength}` : CAT_FACT_API_URL;
|
|
128798
|
-
logger.info(`Fetching random cat fact from: ${url}`,
|
|
128799
|
-
const response = await fetchWithTimeout(url, CAT_FACT_API_TIMEOUT_MS,
|
|
128922
|
+
logger.info(`Fetching random cat fact from: ${url}`, appContext);
|
|
128923
|
+
const response = await fetchWithTimeout(url, CAT_FACT_API_TIMEOUT_MS, appContext);
|
|
128800
128924
|
if (!response.ok) {
|
|
128801
128925
|
const errorText = await response.text().catch(() => {
|
|
128802
128926
|
return;
|
|
128803
128927
|
});
|
|
128804
128928
|
throw new McpError(-32000 /* ServiceUnavailable */, `Cat Fact API request failed: ${response.status} ${response.statusText}`, {
|
|
128805
|
-
requestId:
|
|
128929
|
+
requestId: appContext.requestId,
|
|
128806
128930
|
httpStatusCode: response.status,
|
|
128807
128931
|
responseBody: errorText
|
|
128808
128932
|
});
|
|
@@ -128811,12 +128935,12 @@ async function catFactToolLogic(input, context) {
|
|
|
128811
128935
|
const parsed = CatFactApiSchema.safeParse(rawData);
|
|
128812
128936
|
if (!parsed.success) {
|
|
128813
128937
|
logger.error("Cat Fact API response validation failed", {
|
|
128814
|
-
...
|
|
128938
|
+
...appContext,
|
|
128815
128939
|
receivedData: rawData,
|
|
128816
128940
|
issues: parsed.error.issues
|
|
128817
128941
|
});
|
|
128818
128942
|
throw new McpError(-32000 /* ServiceUnavailable */, "Cat Fact API returned unexpected data format.", {
|
|
128819
|
-
requestId:
|
|
128943
|
+
requestId: appContext.requestId,
|
|
128820
128944
|
issues: parsed.error.issues
|
|
128821
128945
|
});
|
|
128822
128946
|
}
|
|
@@ -128828,7 +128952,7 @@ async function catFactToolLogic(input, context) {
|
|
|
128828
128952
|
timestamp: new Date().toISOString()
|
|
128829
128953
|
};
|
|
128830
128954
|
logger.notice("Random cat fact fetched and processed successfully.", {
|
|
128831
|
-
...
|
|
128955
|
+
...appContext,
|
|
128832
128956
|
factLength: toolResponse.length
|
|
128833
128957
|
});
|
|
128834
128958
|
return toolResponse;
|
|
@@ -128854,7 +128978,7 @@ var catFactTool = {
|
|
|
128854
128978
|
|
|
128855
128979
|
// src/mcp-server/tools/definitions/template-echo-message.tool.ts
|
|
128856
128980
|
var TOOL_NAME2 = "template_echo_message";
|
|
128857
|
-
var TOOL_TITLE2 = "Echo Message";
|
|
128981
|
+
var TOOL_TITLE2 = "Template Echo Message";
|
|
128858
128982
|
var TOOL_DESCRIPTION2 = "Echoes a message back with optional formatting and repetition.";
|
|
128859
128983
|
var TOOL_ANNOTATIONS2 = {
|
|
128860
128984
|
readOnlyHint: true,
|
|
@@ -128880,17 +129004,17 @@ var OutputSchema3 = z.object({
|
|
|
128880
129004
|
repeatCount: z.number().int().min(1).describe("The number of times the message was repeated."),
|
|
128881
129005
|
timestamp: z.string().datetime().optional().describe("Optional ISO 8601 timestamp of when the response was generated.")
|
|
128882
129006
|
}).describe("Echo tool response payload.");
|
|
128883
|
-
async function echoToolLogic(input,
|
|
129007
|
+
async function echoToolLogic(input, appContext, _sdkContext) {
|
|
128884
129008
|
logger.debug("Processing echo message logic.", {
|
|
128885
|
-
...
|
|
129009
|
+
...appContext,
|
|
128886
129010
|
toolInput: input
|
|
128887
129011
|
});
|
|
128888
129012
|
if (input.message === TEST_ERROR_TRIGGER_MESSAGE) {
|
|
128889
129013
|
const errorData = {
|
|
128890
|
-
requestId:
|
|
129014
|
+
requestId: appContext.requestId
|
|
128891
129015
|
};
|
|
128892
|
-
if (typeof
|
|
128893
|
-
errorData.traceId =
|
|
129016
|
+
if (typeof appContext.traceId === "string") {
|
|
129017
|
+
errorData.traceId = appContext.traceId;
|
|
128894
129018
|
}
|
|
128895
129019
|
throw new McpError(-32007 /* ValidationError */, "Deliberate failure triggered.", errorData);
|
|
128896
129020
|
}
|
|
@@ -128949,7 +129073,7 @@ function arrayBufferToBase64(buffer) {
|
|
|
128949
129073
|
|
|
128950
129074
|
// src/mcp-server/tools/definitions/template-image-test.tool.ts
|
|
128951
129075
|
var TOOL_NAME3 = "template_image_test";
|
|
128952
|
-
var TOOL_TITLE3 = "
|
|
129076
|
+
var TOOL_TITLE3 = "Template Image Test";
|
|
128953
129077
|
var TOOL_DESCRIPTION3 = "Fetches a random cat image and returns it base64-encoded with the MIME type. Useful for testing image handling.";
|
|
128954
129078
|
var TOOL_ANNOTATIONS3 = {
|
|
128955
129079
|
readOnlyHint: true,
|
|
@@ -128964,25 +129088,25 @@ var OutputSchema4 = z.object({
|
|
|
128964
129088
|
data: z.string().describe("Base64 encoded image data."),
|
|
128965
129089
|
mimeType: z.string().describe("The MIME type of the image (e.g., 'image/jpeg').")
|
|
128966
129090
|
}).describe("Image tool response payload.");
|
|
128967
|
-
async function imageTestToolLogic(input,
|
|
129091
|
+
async function imageTestToolLogic(input, appContext, _sdkContext) {
|
|
128968
129092
|
logger.debug("Processing template_image_test logic.", {
|
|
128969
|
-
...
|
|
129093
|
+
...appContext,
|
|
128970
129094
|
toolInput: input
|
|
128971
129095
|
});
|
|
128972
|
-
const response = await fetchWithTimeout(CAT_API_URL, API_TIMEOUT_MS,
|
|
129096
|
+
const response = await fetchWithTimeout(CAT_API_URL, API_TIMEOUT_MS, appContext);
|
|
128973
129097
|
if (!response.ok) {
|
|
128974
129098
|
const errorText = await response.text().catch(() => {
|
|
128975
129099
|
return;
|
|
128976
129100
|
});
|
|
128977
129101
|
throw new McpError(-32000 /* ServiceUnavailable */, `Image API request failed: ${response.status} ${response.statusText}`, {
|
|
128978
|
-
requestId:
|
|
129102
|
+
requestId: appContext.requestId,
|
|
128979
129103
|
httpStatusCode: response.status,
|
|
128980
129104
|
responseBody: errorText
|
|
128981
129105
|
});
|
|
128982
129106
|
}
|
|
128983
129107
|
const arrayBuf = await response.arrayBuffer();
|
|
128984
129108
|
if (arrayBuf.byteLength === 0) {
|
|
128985
|
-
throw new McpError(-32000 /* ServiceUnavailable */, "Image API returned an empty payload.", { requestId:
|
|
129109
|
+
throw new McpError(-32000 /* ServiceUnavailable */, "Image API returned an empty payload.", { requestId: appContext.requestId });
|
|
128986
129110
|
}
|
|
128987
129111
|
const mimeType = response.headers.get("content-type") || "image/jpeg";
|
|
128988
129112
|
const result = {
|
|
@@ -128990,7 +129114,7 @@ async function imageTestToolLogic(input, context) {
|
|
|
128990
129114
|
mimeType
|
|
128991
129115
|
};
|
|
128992
129116
|
logger.notice("Image fetched and encoded successfully.", {
|
|
128993
|
-
...
|
|
129117
|
+
...appContext,
|
|
128994
129118
|
mimeType,
|
|
128995
129119
|
byteLength: arrayBuf.byteLength
|
|
128996
129120
|
});
|
|
@@ -129016,8 +129140,91 @@ var imageTestTool = {
|
|
|
129016
129140
|
responseFormatter: responseFormatter3
|
|
129017
129141
|
};
|
|
129018
129142
|
|
|
129143
|
+
// src/mcp-server/tools/definitions/template_madlibs_elicitation.tool.ts
|
|
129144
|
+
var TOOL_NAME4 = "template_madlibs_elicitation";
|
|
129145
|
+
var TOOL_TITLE4 = "Mad Libs Elicitation Game";
|
|
129146
|
+
var TOOL_DESCRIPTION4 = "Plays a game of Mad Libs. If any parts of speech (noun, verb, adjective) are missing, it will use elicitation to ask the user for them.";
|
|
129147
|
+
var TOOL_ANNOTATIONS4 = {
|
|
129148
|
+
readOnlyHint: true,
|
|
129149
|
+
idempotentHint: false,
|
|
129150
|
+
openWorldHint: false
|
|
129151
|
+
};
|
|
129152
|
+
var InputSchema4 = z.object({
|
|
129153
|
+
noun: z.string().optional().describe("A noun for the story."),
|
|
129154
|
+
verb: z.string().optional().describe("A verb (past tense) for the story."),
|
|
129155
|
+
adjective: z.string().optional().describe("An adjective for the story.")
|
|
129156
|
+
}).describe("Inputs for the Mad Libs game. Any missing fields will be elicited.");
|
|
129157
|
+
var OutputSchema5 = z.object({
|
|
129158
|
+
story: z.string().describe("The final, generated Mad Libs story."),
|
|
129159
|
+
noun: z.string().describe("The noun used in the story."),
|
|
129160
|
+
verb: z.string().describe("The verb used in the story."),
|
|
129161
|
+
adjective: z.string().describe("The adjective used in the story.")
|
|
129162
|
+
}).describe("The completed Mad Libs story and the words used.");
|
|
129163
|
+
function hasElicitInput(ctx) {
|
|
129164
|
+
return typeof ctx?.elicitInput === "function";
|
|
129165
|
+
}
|
|
129166
|
+
async function elicitAndValidate(partOfSpeech, sdkContext) {
|
|
129167
|
+
if (!hasElicitInput(sdkContext)) {
|
|
129168
|
+
throw new McpError(-32600 /* InvalidRequest */, "Elicitation is not available in the current context.", { requestId: sdkContext.requestId, operation: "madlibs.elicit" });
|
|
129169
|
+
}
|
|
129170
|
+
const elicitedUnknown = await sdkContext.elicitInput({
|
|
129171
|
+
message: `I need a ${partOfSpeech}.`,
|
|
129172
|
+
schema: { type: "string" }
|
|
129173
|
+
});
|
|
129174
|
+
const validation = z.string().min(1).safeParse(elicitedUnknown);
|
|
129175
|
+
if (!validation.success) {
|
|
129176
|
+
throw new McpError(-32602 /* InvalidParams */, `Invalid ${partOfSpeech} received from user.`, { provided: elicitedUnknown });
|
|
129177
|
+
}
|
|
129178
|
+
return validation.data;
|
|
129179
|
+
}
|
|
129180
|
+
async function madlibsToolLogic(input, appContext, sdkContext) {
|
|
129181
|
+
logger.debug("Processing Mad Libs logic.", { ...appContext, toolInput: input });
|
|
129182
|
+
const noun = input.noun ?? await elicitAndValidate("noun", sdkContext);
|
|
129183
|
+
const verb = input.verb ?? await elicitAndValidate("verb", sdkContext);
|
|
129184
|
+
const adjective = input.adjective ?? await elicitAndValidate("adjective", sdkContext);
|
|
129185
|
+
const story = `The ${adjective} ${noun} ${verb} over the lazy dog.`;
|
|
129186
|
+
const response = {
|
|
129187
|
+
story,
|
|
129188
|
+
noun,
|
|
129189
|
+
verb,
|
|
129190
|
+
adjective
|
|
129191
|
+
};
|
|
129192
|
+
return Promise.resolve(response);
|
|
129193
|
+
}
|
|
129194
|
+
function responseFormatter4(result) {
|
|
129195
|
+
return [
|
|
129196
|
+
{
|
|
129197
|
+
type: "text",
|
|
129198
|
+
text: result.story
|
|
129199
|
+
},
|
|
129200
|
+
{
|
|
129201
|
+
type: "text",
|
|
129202
|
+
text: JSON.stringify({
|
|
129203
|
+
noun: result.noun,
|
|
129204
|
+
verb: result.verb,
|
|
129205
|
+
adjective: result.adjective
|
|
129206
|
+
}, null, 2)
|
|
129207
|
+
}
|
|
129208
|
+
];
|
|
129209
|
+
}
|
|
129210
|
+
var madlibsElicitationTool = {
|
|
129211
|
+
name: TOOL_NAME4,
|
|
129212
|
+
title: TOOL_TITLE4,
|
|
129213
|
+
description: TOOL_DESCRIPTION4,
|
|
129214
|
+
inputSchema: InputSchema4,
|
|
129215
|
+
outputSchema: OutputSchema5,
|
|
129216
|
+
annotations: TOOL_ANNOTATIONS4,
|
|
129217
|
+
logic: withToolAuth(["tool:madlibs:play"], madlibsToolLogic),
|
|
129218
|
+
responseFormatter: responseFormatter4
|
|
129219
|
+
};
|
|
129220
|
+
|
|
129019
129221
|
// src/mcp-server/tools/definitions/index.ts
|
|
129020
|
-
var allToolDefinitions = [
|
|
129222
|
+
var allToolDefinitions = [
|
|
129223
|
+
catFactTool,
|
|
129224
|
+
echoTool,
|
|
129225
|
+
imageTestTool,
|
|
129226
|
+
madlibsElicitationTool
|
|
129227
|
+
];
|
|
129021
129228
|
|
|
129022
129229
|
// src/mcp-server/tools/utils/toolHandlerFactory.ts
|
|
129023
129230
|
var defaultResponseFormatter2 = (result) => [
|
|
@@ -129026,25 +129233,29 @@ var defaultResponseFormatter2 = (result) => [
|
|
|
129026
129233
|
function createMcpToolHandler({
|
|
129027
129234
|
toolName,
|
|
129028
129235
|
logic,
|
|
129029
|
-
responseFormatter:
|
|
129236
|
+
responseFormatter: responseFormatter5 = defaultResponseFormatter2
|
|
129030
129237
|
}) {
|
|
129031
129238
|
return async (input, callContext) => {
|
|
129032
|
-
const
|
|
129033
|
-
const
|
|
129034
|
-
|
|
129239
|
+
const sdkContext = callContext;
|
|
129240
|
+
const sessionId = typeof sdkContext?.sessionId === "string" ? sdkContext.sessionId : undefined;
|
|
129241
|
+
const appContext = requestContextService.createRequestContext({
|
|
129242
|
+
parentContext: sdkContext,
|
|
129035
129243
|
operation: "HandleToolRequest",
|
|
129036
129244
|
additionalContext: { toolName, sessionId, input }
|
|
129037
129245
|
});
|
|
129246
|
+
if ("elicitInput" in sdkContext && typeof sdkContext.elicitInput === "function") {
|
|
129247
|
+
appContext.elicitInput = sdkContext.elicitInput;
|
|
129248
|
+
}
|
|
129038
129249
|
try {
|
|
129039
|
-
const result = await measureToolExecution(() => logic(input,
|
|
129250
|
+
const result = await measureToolExecution(() => logic(input, appContext, sdkContext), { ...appContext, toolName }, input);
|
|
129040
129251
|
return {
|
|
129041
129252
|
structuredContent: result,
|
|
129042
|
-
content:
|
|
129253
|
+
content: responseFormatter5(result)
|
|
129043
129254
|
};
|
|
129044
129255
|
} catch (error2) {
|
|
129045
129256
|
const mcpError = ErrorHandler.handleError(error2, {
|
|
129046
129257
|
operation: `tool:${toolName}`,
|
|
129047
|
-
context:
|
|
129258
|
+
context: appContext,
|
|
129048
129259
|
input
|
|
129049
129260
|
});
|
|
129050
129261
|
return {
|
|
@@ -133919,7 +134130,8 @@ async function createMcpServerInstance() {
|
|
|
133919
134130
|
capabilities: {
|
|
133920
134131
|
logging: {},
|
|
133921
134132
|
resources: { listChanged: true },
|
|
133922
|
-
tools: { listChanged: true }
|
|
134133
|
+
tools: { listChanged: true },
|
|
134134
|
+
elicitation: {}
|
|
133923
134135
|
}
|
|
133924
134136
|
});
|
|
133925
134137
|
try {
|