@vectros-ai/mcp-server 0.17.2 → 0.18.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/dist/cli.js CHANGED
@@ -26,7 +26,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
26
26
  // src/server.ts
27
27
  var import_server = require("@modelcontextprotocol/sdk/server/index.js");
28
28
 
29
- // ../../node_modules/@vectros-ai/sdk/dist/index.mjs
29
+ // node_modules/@vectros-ai/sdk/dist/index.mjs
30
30
  var __defProp2 = Object.defineProperty;
31
31
  var __export = (target, all) => {
32
32
  for (var name in all)
@@ -46,6 +46,7 @@ __export(api_exports, {
46
46
  ContentTooLargeError: () => ContentTooLargeError,
47
47
  DocumentContextEvent: () => DocumentContextEvent,
48
48
  DocumentLookupRequest: () => DocumentLookupRequest,
49
+ DocumentPatchRequest: () => DocumentPatchRequest,
49
50
  DocumentRequest: () => DocumentRequest,
50
51
  DocumentResponse: () => DocumentResponse,
51
52
  DoneEvent: () => DoneEvent,
@@ -389,6 +390,13 @@ var DocumentLookupRequest;
389
390
  Desc: "desc"
390
391
  };
391
392
  })(DocumentLookupRequest || (DocumentLookupRequest = {}));
393
+ var DocumentPatchRequest;
394
+ ((DocumentPatchRequest2) => {
395
+ DocumentPatchRequest2.Status = {
396
+ Active: "ACTIVE",
397
+ Archived: "ARCHIVED"
398
+ };
399
+ })(DocumentPatchRequest || (DocumentPatchRequest = {}));
392
400
  var FileUploadRequest;
393
401
  ((FileUploadRequest2) => {
394
402
  FileUploadRequest2.IndexMode = {
@@ -401,6 +409,7 @@ var FileUploadRequest;
401
409
  var documents_exports = {};
402
410
  __export(documents_exports, {
403
411
  DocumentLookupRequest: () => DocumentLookupRequest,
412
+ DocumentPatchRequest: () => DocumentPatchRequest,
404
413
  FileUploadRequest: () => FileUploadRequest,
405
414
  LookupDocumentsRequestOrder: () => LookupDocumentsRequestOrder
406
415
  });
@@ -3065,6 +3074,7 @@ var AuthClient = class {
3065
3074
  * @param {AuthClient.RequestOptions} requestOptions - Request-specific configuration.
3066
3075
  *
3067
3076
  * @throws {@link Vectros.BadRequestError}
3077
+ * @throws {@link Vectros.PaymentRequiredError}
3068
3078
  * @throws {@link Vectros.ForbiddenError}
3069
3079
  * @throws {@link Vectros.TooManyRequestsError}
3070
3080
  *
@@ -3114,6 +3124,8 @@ var AuthClient = class {
3114
3124
  switch (_response.error.statusCode) {
3115
3125
  case 400:
3116
3126
  throw new BadRequestError(_response.error.body, _response.rawResponse);
3127
+ case 402:
3128
+ throw new PaymentRequiredError(_response.error.body, _response.rawResponse);
3117
3129
  case 403:
3118
3130
  throw new ForbiddenError(_response.error.body, _response.rawResponse);
3119
3131
  case 429:
@@ -4959,7 +4971,7 @@ var ComplianceClient = class {
4959
4971
  this._options = normalizeClientOptionsWithAuth(options);
4960
4972
  }
4961
4973
  /**
4962
- * Submits a right-to-erasure request for a single end-subject (a user, or an identity entity in any namespace). Erasure removes exactly the data the subject solely owns across the declared contexts, plus the subject's identity and lookup rows. It never touches another account's data and never cascades into another subject's data. The request is asynchronous: it returns 202 with a `requestId`; poll `GET /v1/erasure-requests/{id}` until the job completes to obtain the completion certificate. Requires a root API key — a scoped credential is rejected with 403.
4974
+ * Submits a right-to-erasure request for a single end-subject (a user, or an identity entity in any namespace). Erasure removes exactly the data the subject solely owns across the declared contexts, plus its identity and lookup rows when all contexts are covered. It never touches another account's data and never cascades into another subject's data. The request is asynchronous: it returns 202 with a `requestId`; poll `GET /v1/erasure-requests/{id}` until the job completes to obtain the completion certificate. Requires a root API key — a scoped credential is rejected with 403.
4963
4975
  *
4964
4976
  * @param {Vectros.ErasureRequest} request
4965
4977
  * @param {ComplianceClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -5022,7 +5034,7 @@ var ComplianceClient = class {
5022
5034
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "POST", "/v1/erasure-requests");
5023
5035
  }
5024
5036
  /**
5025
- * Polls an erasure request by id. While the job is still running this returns its status only; once it completes, the response also includes the verifiable completion certificate (which contexts were swept, per-context deletion counts, and reports of dangling references and shared rows that were left intact). Requires a root API key.
5037
+ * Polls an erasure request by id. While the job is still running this returns its status only; once it completes, the response also includes the verifiable completion certificate (which contexts were swept, per-context deletion counts, whether the identity was kept, and reports of dangling references and shared rows left intact). Requires a root API key.
5026
5038
  *
5027
5039
  * @param {Vectros.GetErasureRequestRequest} request
5028
5040
  * @param {ComplianceClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -5265,7 +5277,7 @@ var DocumentsClient = class {
5265
5277
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/documents");
5266
5278
  }
5267
5279
  /**
5268
- * Creates a document from a raw text string and queues it for asynchronous indexing so it becomes searchable. Optionally supply an `externalId` to make the create idempotent — if a document with the same `externalId` already exists in your context, that existing document is returned unchanged instead of a duplicate being created. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing document was returned) tells the two apart. To overwrite an existing document's content instead of returning it unchanged, set `?upsert=true` (this also requires the `documents:u` scope). Requires the `documents:c` scope to create. Being returned the existing document on a collision is a read of that document's data and additionally requires the `documents:r` scope — a credential holding `documents:c` alone receives a `400` ("already exists") on collision instead of the document.
5280
+ * Creates a document from a raw text string and queues it for asynchronous indexing so it becomes searchable. Optionally supply an `externalId` to make the create idempotent — if a document with the same `externalId` already exists in your context, that existing document is returned unchanged instead of a duplicate being created. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing document was returned) tells the two apart. To overwrite an existing document's content instead of returning it unchanged, set `?upsert=true` (this also requires the `documents:u` scope). Requires the `documents:c` scope to create. Being returned the existing document on a collision is a read of that document's data and additionally requires the `documents:r` scope — a credential holding `documents:c` alone receives a `400` ("already exists") on collision instead of the document. Supplying `externalId` WITHOUT `schemaId` is refused (`400`) unless you also pass `confirmUntyped=true` — externalId uniqueness is scoped per schema, so omitting `schemaId` by mistake would otherwise silently create a separate untyped document instead of targeting the typed one you likely meant.
5269
5281
  *
5270
5282
  * @param {Vectros.IngestDocumentRequest} request
5271
5283
  * @param {DocumentsClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -5285,10 +5297,11 @@ var DocumentsClient = class {
5285
5297
  return HttpResponsePromise.fromPromise(this.__ingestDocument(request, requestOptions));
5286
5298
  }
5287
5299
  async __ingestDocument(request, requestOptions) {
5288
- const { upsert, allowClear, body: _body } = request;
5300
+ const { upsert, allowClear, confirmUntyped, body: _body } = request;
5289
5301
  const _queryParams = {
5290
5302
  upsert,
5291
- allowClear
5303
+ allowClear,
5304
+ confirmUntyped
5292
5305
  };
5293
5306
  const _authRequest = await this._options.authProvider.getAuthRequest();
5294
5307
  const _headers = mergeHeaders(
@@ -5523,7 +5536,7 @@ var DocumentsClient = class {
5523
5536
  /**
5524
5537
  * Partially updates a document using an RFC 7386 JSON Merge Patch. The `payload` object is deep-merged: keys you send overwrite existing values (recursing into nested objects), a key set to `null` is deleted, and keys you omit are preserved — unlike PUT, which replaces the whole payload. Top-level fields (`title`, `folderId`, `schemaId`, ownership) are set when present and left unchanged when omitted; sending a top-level field as `null` is rejected. Supplying `text` re-ingests the document body (same as PUT). `indexMode`, `externalId`, and `storeText` (text retention is fixed at ingest) are immutable and rejected if present. The merged result is validated against the bound schema. Pass `expectedVersion` for optimistic concurrency (409 on conflict). Requires the `documents:u` scope.
5525
5538
  *
5526
- * @param {Vectros.PatchDocumentRequest} request
5539
+ * @param {Vectros.DocumentPatchRequest} request
5527
5540
  * @param {DocumentsClient.RequestOptions} requestOptions - Request-specific configuration.
5528
5541
  *
5529
5542
  * @throws {@link Vectros.BadRequestError}
@@ -5534,17 +5547,14 @@ var DocumentsClient = class {
5534
5547
  *
5535
5548
  * @example
5536
5549
  * await client.documents.patchDocument({
5537
- * id: "id",
5538
- * body: {
5539
- * title: "Patient Intake Form \u2014 Jane Doe"
5540
- * }
5550
+ * id: "id"
5541
5551
  * })
5542
5552
  */
5543
5553
  patchDocument(request, requestOptions) {
5544
5554
  return HttpResponsePromise.fromPromise(this.__patchDocument(request, requestOptions));
5545
5555
  }
5546
5556
  async __patchDocument(request, requestOptions) {
5547
- const { id, body: _body } = request;
5557
+ const { id, ..._body } = request;
5548
5558
  const _authRequest = await this._options.authProvider.getAuthRequest();
5549
5559
  const _headers = mergeHeaders(
5550
5560
  _authRequest.headers,
@@ -5916,7 +5926,7 @@ var DocumentsClient = class {
5916
5926
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/documents/{id}/versions");
5917
5927
  }
5918
5928
  /**
5919
- * Starts a file-based document by returning a short-lived presigned S3 PUT URL. Upload the file bytes directly to `uploadUrl`; the document is then automatically queued for text extraction and asynchronous indexing. Supplying an `externalId` makes this idempotent — re-initiating an upload with the same `externalId` re-issues a fresh presigned URL for the SAME existing document, targeting a newly-staged object rather than the document's current one — your PUT lands there first, and the document only adopts it once the upload is validated (so a re-upload inherently replaces the file body) rather than creating a duplicate. The response's `created` field (and the HTTP status — 201 when a new document was minted, 200 when an existing one was matched) tells the two apart. With `?upsert=true`, the submitted `payload`/`title` are also applied to the matched document (file-body divergence cannot be diffed at upload-init — the bytes have not arrived yet — so the re-upload itself replaces the body). Creating a NEW document requires the `documents:c` scope. Re-uploading over an EXISTING document overwrites (and re-indexes) its body, so it is an update: it requires the `documents:u` scope (as does `?upsert=true` for the metadata). **Your PUT to `uploadUrl` MUST include the header named in the response's `requiredHeaderName`, set to `requiredHeaderValue` exactly.** It is a signed part of the presigned request — the PUT never reaches this service either way, so neither failure uses this API's JSON error shape. Omitting it, or sending a different value, invalidates the request's signature and S3 rejects it with a 403 `SignatureDoesNotMatch`. Sending it correctly makes the URL single-use: `requiredHeaderName` is always `If-None-Match` and `requiredHeaderValue` is always `*` — a create, a recovery upload for a document whose earlier file is missing, and a re-upload ALL target a freshly-minted, never-written key, so the same S3 conditional-write precondition applies uniformly (S3's own documented conditional-write behavior): a replay after the object already exists (from your own completed PUT, or anyone else's) fails with `412 Precondition Failed`; a replay after the object was deleted and never re-created finds an absent key again and can succeed — single-use is a property of the object's existence, not a one-time token. **Either precondition can also fail with `409 Conflict` if your PUT genuinely races a concurrent delete on the same object.** Whichever of `412` or `409` you receive, the remedy is the same: call this endpoint again for a fresh URL rather than retrying the same PUT — a fresh call always targets a new key, so it is never subject to whatever raced the previous one.
5929
+ * Starts a file-based document by returning a short-lived presigned S3 PUT URL. Upload the file bytes directly to `uploadUrl`; the document is then automatically queued for text extraction and asynchronous indexing. Supplying an `externalId` makes this idempotent — re-initiating an upload with the same `externalId` re-issues a fresh presigned URL for the SAME existing document, targeting a newly-staged object rather than the document's current one — your PUT lands there first, and the document only adopts it once the upload is validated (so a re-upload inherently replaces the file body) rather than creating a duplicate. The response's `created` field (and the HTTP status — 201 when a new document was minted, 200 when an existing one was matched) tells the two apart. With `?upsert=true`, the submitted `payload`/`title` are also applied to the matched document (file-body divergence cannot be diffed at upload-init — the bytes have not arrived yet — so the re-upload itself replaces the body). Creating a NEW document requires the `documents:c` scope. Re-uploading over an EXISTING document overwrites (and re-indexes) its body, so it is an update: it requires the `documents:u` scope (as does `?upsert=true` for the metadata). **Your PUT to `uploadUrl` MUST include the header named in the response's `requiredHeaderName`, set to `requiredHeaderValue` exactly.** It is a signed part of the presigned request — the PUT never reaches this service either way, so neither failure uses this API's JSON error shape. Omitting it, or sending a different value, invalidates the request's signature and S3 rejects it with a 403 `SignatureDoesNotMatch`. Sending it correctly makes the URL single-use: `requiredHeaderName` is always `If-None-Match` and `requiredHeaderValue` is always `*` — a create, a recovery upload for a document whose earlier file is missing, and a re-upload ALL target a freshly-minted, never-written key, so the same S3 conditional-write precondition applies uniformly (S3's own documented conditional-write behavior): a replay after the object already exists (from your own completed PUT, or anyone else's) fails with `412 Precondition Failed`; a replay after the object was deleted and never re-created finds an absent key again and can succeed — single-use is a property of the object's existence, not a one-time token. **Either precondition can also fail with `409 Conflict` if your PUT genuinely races a concurrent delete on the same object.** Whichever of `412` or `409` you receive, the remedy is the same: call this endpoint again for a fresh URL rather than retrying the same PUT — a fresh call always targets a new key, so it is never subject to whatever raced the previous one. Supplying `externalId` WITHOUT `schemaId` is refused (`400`) unless you also pass `confirmUntyped=true` — externalId uniqueness is scoped per schema, so omitting `schemaId` by mistake would otherwise silently create a separate untyped document instead of targeting the typed one you likely meant.
5920
5930
  *
5921
5931
  * @param {Vectros.FileUploadRequest} request
5922
5932
  * @param {DocumentsClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -5935,9 +5945,10 @@ var DocumentsClient = class {
5935
5945
  return HttpResponsePromise.fromPromise(this.__uploadDocument(request, requestOptions));
5936
5946
  }
5937
5947
  async __uploadDocument(request, requestOptions) {
5938
- const { upsert, ..._body } = request;
5948
+ const { upsert, confirmUntyped, ..._body } = request;
5939
5949
  const _queryParams = {
5940
- upsert
5950
+ upsert,
5951
+ confirmUntyped
5941
5952
  };
5942
5953
  const _authRequest = await this._options.authProvider.getAuthRequest();
5943
5954
  const _headers = mergeHeaders(
@@ -10233,7 +10244,7 @@ var logging;
10233
10244
 
10234
10245
  // src/server.ts
10235
10246
  var import_types3 = require("@modelcontextprotocol/sdk/types.js");
10236
- var import_zod24 = require("zod");
10247
+ var import_zod25 = require("zod");
10237
10248
 
10238
10249
  // src/auth.ts
10239
10250
  var KEY_RE = /^(sk|ssk|st)_(live|test)_/;
@@ -10277,8 +10288,8 @@ function warnOnSuboptimalKey(key, log) {
10277
10288
 
10278
10289
  // src/build-info.ts
10279
10290
  var BUILD_INFO = {
10280
- mcpServer: true ? "0.17.2" : "dev",
10281
- sdk: true ? "0.45.0" : "dev"
10291
+ mcpServer: true ? "0.18.0" : "dev",
10292
+ sdk: true ? "0.46.0" : "dev"
10282
10293
  };
10283
10294
  function formatBuildInfo() {
10284
10295
  return `vectros-mcp-server ${BUILD_INFO.mcpServer} (sdk ${BUILD_INFO.sdk})`;
@@ -10573,7 +10584,7 @@ var inputSchema = {
10573
10584
  "Keyword-match precision for the BM25 leg (TEXT/HYBRID modes). OR = any term (broad recall), AND = all terms (higher precision), PHRASE = contiguous phrase. Default: PHRASE (slop 3) in HYBRID, OR in TEXT. (The advanced raw-query COMPLEX mode is intentionally not exposed here.)"
10574
10585
  ),
10575
10586
  limit: import_zod.z.number().int().min(1).max(MCP_MAX_LIMIT).optional().describe(
10576
- `Max hits per page. Defaults to a low ${MCP_DEFAULT_LIMIT} to protect the agent context window; raise up to ${MCP_MAX_LIMIT} (the most a single search returns) in one call when you can accept the larger result, or page with \`offset\` instead.`
10587
+ `Max hits per page. Defaults to a low ${MCP_DEFAULT_LIMIT} to protect the agent context window; raise up to ${MCP_MAX_LIMIT} (this tool's ceiling) in one call when you can accept the larger result, or page with \`offset\` instead.`
10577
10588
  ),
10578
10589
  offset: import_zod.z.number().int().min(0).max(200).optional().describe("Skip the first N hits \u2014 for pagination (0\u2013200)."),
10579
10590
  folderId: import_zod.z.string().optional().describe("Scope to content in this EXACT folder (Vectros folder id)."),
@@ -11322,52 +11333,61 @@ var recordDelete = ({ client, log }) => ({
11322
11333
  var record_delete_default = recordDelete;
11323
11334
 
11324
11335
  // src/tools/rag_ask.ts
11336
+ var import_zod10 = require("zod");
11337
+
11338
+ // src/tools/provider-alias.ts
11325
11339
  var import_zod9 = require("zod");
11340
+ var providerAliasInput = import_zod9.z.string().min(1, "providerAlias must be non-empty when supplied").optional().describe(
11341
+ "Route THIS call through your own model provider instead of the platform-hosted default, by the alias of a provider config your account has activated. It works only after your account has set up that provider and signed the platform's risk-acceptance waiver; without both, the platform refuses the call with a 403, which is returned to you as written. A call served by your own provider leaves the platform-hosted Bedrock path, and Vectros's AWS BAA boundary. Omit it (the default) to use the platform-hosted path. When set, `model` names the model on your provider's own id space, and falls back to that provider config's default model when omitted."
11342
+ );
11343
+
11344
+ // src/tools/rag_ask.ts
11326
11345
  var SEARCH_MCP_DEFAULT_LIMIT = 5;
11327
11346
  var SEARCH_MCP_MAX_LIMIT = 50;
11328
11347
  var inputSchema9 = {
11329
- query: import_zod9.z.string().min(1, "query must be non-empty").describe("Question to ground against retrieved content."),
11330
- instructions: import_zod9.z.string().optional().describe(
11348
+ query: import_zod10.z.string().min(1, "query must be non-empty").describe("Question to ground against retrieved content."),
11349
+ instructions: import_zod10.z.string().optional().describe(
11331
11350
  'System prompt that overrides the default for the generation step \u2014 e.g. "answer only from the provided context, cite sources, be concise". Default: a generic answer-from-context instruction.'
11332
11351
  ),
11333
- model: import_zod9.z.string().optional().describe(
11334
- "Inference model alias (e.g. claude-haiku-4-5, claude-sonnet-5, claude-opus-4-8). Default = tier-appropriate Haiku. See GET /v1/models for the catalog the calling key can reach."
11352
+ model: import_zod10.z.string().optional().describe(
11353
+ "Inference model alias (e.g. claude-haiku-4-5, claude-sonnet-5, claude-opus-5-5). Default = tier-appropriate Haiku. See GET /v1/models for the catalog the calling key can reach. When `providerAlias` is set, this instead names the model on that provider's own id space."
11335
11354
  ),
11336
- search: import_zod9.z.object({
11337
- mode: import_zod9.z.enum(["HYBRID", "TEXT", "SEMANTIC"]).optional().describe("Retrieval mode. Default HYBRID."),
11338
- limit: import_zod9.z.number().int().min(1).max(SEARCH_MCP_MAX_LIMIT).optional().describe(
11339
- `Passages to retrieve before generating (the grounding-corpus size). Default ${SEARCH_MCP_DEFAULT_LIMIT}; raise up to ${SEARCH_MCP_MAX_LIMIT} (the RAG search API max) for a broader corpus when the extra grounding is worth the larger prompt.`
11355
+ providerAlias: providerAliasInput,
11356
+ search: import_zod10.z.object({
11357
+ mode: import_zod10.z.enum(["HYBRID", "TEXT", "SEMANTIC"]).optional().describe("Retrieval mode. Default HYBRID."),
11358
+ limit: import_zod10.z.number().int().min(1).max(SEARCH_MCP_MAX_LIMIT).optional().describe(
11359
+ `Passages to retrieve before generating (the grounding-corpus size). Default ${SEARCH_MCP_DEFAULT_LIMIT}; raise up to ${SEARCH_MCP_MAX_LIMIT} (this tool's ceiling) for a broader corpus when the extra grounding is worth the larger prompt.`
11340
11360
  ),
11341
11361
  // Retrieval scoping — parity with hybrid_search so an agent can ground the
11342
11362
  // answer on a specific owner / folder / type / metadata subset, not just the
11343
11363
  // whole-tenant corpus.
11344
- userId: import_zod9.z.string().optional().describe("Restrict retrieval to content owned by this user (Vectros UUID)."),
11345
- scope: import_zod9.z.string().optional().describe(
11364
+ userId: import_zod10.z.string().optional().describe("Restrict retrieval to content owned by this user (Vectros UUID)."),
11365
+ scope: import_zod10.z.string().optional().describe(
11346
11366
  'Restrict retrieval to content carrying this scope value, in `namespace:value` form (e.g. "org:<uuid>", "client:<uuid>", "group:eng-team"). `org` and `client` are reserved namespace names, registered like any other; others are namespaces you registered yourself. Mutually exclusive with `scopeFilters` \u2014 use this for ONE dimension.'
11347
11367
  ),
11348
- scopeFilters: import_zod9.z.array(import_zod9.z.string()).min(1, "scopeFilters must name at least one dimension when supplied").optional().describe(
11368
+ scopeFilters: import_zod10.z.array(import_zod10.z.string()).min(1, "scopeFilters must name at least one dimension when supplied").optional().describe(
11349
11369
  'Restrict retrieval to content matching ALL of these scope values \u2014 one per namespace \u2014 for a credential whose access spans more than one ownership dimension. e.g. ["org:<uuid>", "client:<uuid>"] grounds the answer on one specific client WITHIN one specific org, which `scope` alone cannot express. Naming the same namespace twice is rejected. Mutually exclusive with `scope`.'
11350
11370
  ),
11351
- folderId: import_zod9.z.string().optional().describe("Restrict retrieval to this exact folder."),
11352
- rootFolderId: import_zod9.z.string().optional().describe("Restrict retrieval to this folder and all its descendants."),
11353
- typeName: import_zod9.z.string().optional().describe("Restrict record retrieval to this schema type."),
11354
- contentTypes: import_zod9.z.array(import_zod9.z.enum(["documents", "records"])).optional().describe('Narrow retrieval to content types. ["documents"] or ["records"]; omit for both.'),
11355
- filters: import_zod9.z.record(import_zod9.z.unknown()).optional().describe(
11371
+ folderId: import_zod10.z.string().optional().describe("Restrict retrieval to this exact folder."),
11372
+ rootFolderId: import_zod10.z.string().optional().describe("Restrict retrieval to this folder and all its descendants."),
11373
+ typeName: import_zod10.z.string().optional().describe("Restrict record retrieval to this schema type."),
11374
+ contentTypes: import_zod10.z.array(import_zod10.z.enum(["documents", "records"])).optional().describe('Narrow retrieval to content types. ["documents"] or ["records"]; omit for both.'),
11375
+ filters: import_zod10.z.record(import_zod10.z.unknown()).optional().describe(
11356
11376
  'Field-level metadata filters (AND-combined). Value = scalar (equality), array (OR-set), or operator map ($eq/$ne/$gt/$gte/$lt/$lte, $in/$nin). e.g. {"status":"open"}.'
11357
11377
  ),
11358
- createdAfter: import_zod9.z.string().optional().describe(
11378
+ createdAfter: import_zod10.z.string().optional().describe(
11359
11379
  "Restrict retrieval to content CREATED at/after this ISO 8601 UTC timestamp \u2014 the item's own creation time, which does not move when it is re-indexed. An item matched on its FIRST index may be checked against its index time instead, a bounded clock-skew allowance."
11360
11380
  ),
11361
- createdBefore: import_zod9.z.string().optional().describe("Same creation-time basis as createdAfter, bounding at/before this ISO 8601 UTC value."),
11362
- requireComplete: import_zod9.z.boolean().optional().describe("Fail closed (503) on a degraded search backend instead of grounding on partial results. Default false.")
11381
+ createdBefore: import_zod10.z.string().optional().describe("Same creation-time basis as createdAfter, bounding at/before this ISO 8601 UTC value."),
11382
+ requireComplete: import_zod10.z.boolean().optional().describe("Fail closed (503) on a degraded search backend instead of grounding on partial results. Default false.")
11363
11383
  }).optional().describe("Retrieval params + scoping. Default mode HYBRID, limit " + SEARCH_MCP_DEFAULT_LIMIT + "."),
11364
- maxTokens: import_zod9.z.number().int().min(1).optional().describe("Max output tokens."),
11365
- temperature: import_zod9.z.number().min(0).max(1).optional().describe("Sampling temperature (0.0\u20131.0). Default 0.3 \u2014 lower favors deterministic, retrieval-grounded answers.")
11384
+ maxTokens: import_zod10.z.number().int().min(1).optional().describe("Max output tokens."),
11385
+ temperature: import_zod10.z.number().min(0).max(1).optional().describe("Sampling temperature (0.0\u20131.0). Default 0.3 \u2014 lower favors deterministic, retrieval-grounded answers.")
11366
11386
  };
11367
11387
  var ragAsk = ({ client, log }) => ({
11368
11388
  name: "rag_ask",
11369
11389
  title: "RAG ask (corpus-wide)",
11370
- description: "Ask a question grounded against your tenant's indexed content. Vectros performs a hybrid search, injects the top-K passages into the prompt, and streams a model answer back. Scope retrieval with `search` (ownership \u2014 `scope` for one ownership dimension or `scopeFilters` for several at once, e.g. one client within one org \u2014 folder, type, metadata filters, date window) to ground on a subset \u2014 e.g. one patient or one folder \u2014 and steer generation with `instructions` / `temperature`. The full answer is returned as a single response; progress notifications keep the call alive during the 30-45s generation window. Inference runs in-perimeter against AWS Bedrock \u2014 PHI never leaves the BAA boundary.",
11390
+ description: "Ask a question grounded against your tenant's indexed content. Vectros performs a hybrid search, injects the top-K passages into the prompt, and streams a model answer back. Scope retrieval with `search` (ownership \u2014 `scope` for one ownership dimension or `scopeFilters` for several at once, e.g. one client within one org \u2014 folder, type, metadata filters, date window) to ground on a subset \u2014 e.g. one patient or one folder \u2014 and steer generation with `instructions` / `temperature`. The full answer is returned as a single response; progress notifications keep the call alive during the 30-45s generation window. Calls without `providerAlias` are served by platform-hosted AWS Bedrock. A call that sets `providerAlias` goes to your own model provider, outside Vectros's AWS BAA boundary.",
11371
11391
  inputSchema: inputSchema9,
11372
11392
  // NOT a pure read: this call reserves an atomic hold against the caller's prepaid inference
11373
11393
  // balance before generation starts, then debits it on completion — a real financial side
@@ -11409,6 +11429,7 @@ var ragAsk = ({ client, log }) => ({
11409
11429
  query: args.query,
11410
11430
  instructions: args.instructions,
11411
11431
  model: args.model,
11432
+ providerAlias: args.providerAlias,
11412
11433
  search,
11413
11434
  maxTokens: args.maxTokens,
11414
11435
  temperature: args.temperature
@@ -11463,19 +11484,20 @@ var ragAsk = ({ client, log }) => ({
11463
11484
  var rag_ask_default = ragAsk;
11464
11485
 
11465
11486
  // src/tools/document_ask.ts
11466
- var import_zod10 = require("zod");
11487
+ var import_zod11 = require("zod");
11467
11488
  var inputSchema10 = {
11468
- documentId: import_zod10.z.string().min(1, "documentId is required").describe("ID of the document to ask against."),
11469
- prompt: import_zod10.z.string().min(1, "prompt is required").describe("Question to ask about the document."),
11470
- model: import_zod10.z.string().optional().describe(
11471
- "Inference model alias. Default = tier-appropriate Haiku. See GET /v1/models for the catalog the calling key can reach."
11489
+ documentId: import_zod11.z.string().min(1, "documentId is required").describe("ID of the document to ask against."),
11490
+ prompt: import_zod11.z.string().min(1, "prompt is required").describe("Question to ask about the document."),
11491
+ model: import_zod11.z.string().optional().describe(
11492
+ "Inference model alias. Default = tier-appropriate Haiku. See GET /v1/models for the catalog the calling key can reach. When `providerAlias` is set, this instead names the model on that provider's own id space."
11472
11493
  ),
11473
- maxTokens: import_zod10.z.number().int().min(1).optional().describe("Max output tokens.")
11494
+ providerAlias: providerAliasInput,
11495
+ maxTokens: import_zod11.z.number().int().min(1).optional().describe("Max output tokens.")
11474
11496
  };
11475
11497
  var documentAsk = ({ client, log }) => ({
11476
11498
  name: "document_ask",
11477
11499
  title: "Document ask (single-document)",
11478
- description: "Ask a question against a single indexed document. Returns a grounded answer with the document context that informed it. For documents exceeding the input-token cap, the API returns a structured 413 with `estimatedTokens` and `limitTokens`. Inference runs in-perimeter against AWS Bedrock \u2014 PHI never leaves the BAA boundary.",
11500
+ description: "Ask a question against a single indexed document. Returns a grounded answer with the document context that informed it. For documents exceeding the input-token cap, the API returns a structured 413 with `estimatedTokens` and `limitTokens`. Calls without `providerAlias` are served by platform-hosted AWS Bedrock. A call that sets `providerAlias` goes to your own model provider, outside Vectros's AWS BAA boundary.",
11479
11501
  inputSchema: inputSchema10,
11480
11502
  // NOT a pure read: this call reserves an atomic hold against the caller's prepaid inference
11481
11503
  // balance before generation starts, then debits it on completion — a real financial side
@@ -11492,6 +11514,7 @@ var documentAsk = ({ client, log }) => ({
11492
11514
  id: args.documentId,
11493
11515
  prompt: args.prompt,
11494
11516
  model: args.model,
11517
+ providerAlias: args.providerAlias,
11495
11518
  maxTokens: args.maxTokens
11496
11519
  });
11497
11520
  const progressToken = extra._meta?.progressToken;
@@ -11544,18 +11567,18 @@ var documentAsk = ({ client, log }) => ({
11544
11567
  var document_ask_default = documentAsk;
11545
11568
 
11546
11569
  // src/tools/list_schemas.ts
11547
- var import_zod11 = require("zod");
11570
+ var import_zod12 = require("zod");
11548
11571
  var inputSchema11 = {
11549
- userId: import_zod11.z.string().optional().describe(
11572
+ userId: import_zod12.z.string().optional().describe(
11550
11573
  "Filter to schemas visible to a specific user. Optional; default returns all schemas the credential can see."
11551
11574
  ),
11552
- scope: import_zod11.z.string().optional().describe(
11575
+ scope: import_zod12.z.string().optional().describe(
11553
11576
  'Filter to schemas carrying this scope value, in `namespace:value` form (e.g. "org:<uuid>", "group:eng-team"). `org` and `client` are reserved namespace names, registered like any other. Optional; default returns all schemas the credential can see.'
11554
11577
  ),
11555
- surface: import_zod11.z.enum(["record", "document", "user", "entity"]).optional().describe(
11578
+ surface: import_zod12.z.enum(["record", "document", "user", "entity"]).optional().describe(
11556
11579
  "Filter to schemas bindable to this surface \u2014 e.g. `document` to list only document types, or `record` for record types. Identity entities in any namespace (org/client/one you registered) bind under the single `entity` surface; `user` and `entity` are account-wide. Optional."
11557
11580
  ),
11558
- recordType: import_zod11.z.string().optional().describe(
11581
+ recordType: import_zod12.z.string().optional().describe(
11559
11582
  'Resolve the single schema for this record type (its natural handle, e.g. "patient") instead of listing \u2014 returns a one-element result, or empty if none. Combine with `surface=user|entity` for an identity schema. Takes precedence over userId. Optional.'
11560
11583
  )
11561
11584
  };
@@ -11591,19 +11614,19 @@ var listSchemas = ({ client, log }) => ({
11591
11614
  var list_schemas_default = listSchemas;
11592
11615
 
11593
11616
  // src/tools/document_get.ts
11594
- var import_zod12 = require("zod");
11617
+ var import_zod13 = require("zod");
11595
11618
  var MAX_TEXT_CHARS = 32e3;
11596
11619
  var inputSchema12 = {
11597
- documentId: import_zod12.z.string().optional().describe("The document ID returned by document_ingest or hybrid_search. Provide this OR externalId+type."),
11598
- externalId: import_zod12.z.string().optional().describe(
11620
+ documentId: import_zod13.z.string().optional().describe("The document ID returned by document_ingest or hybrid_search. Provide this OR externalId+type."),
11621
+ externalId: import_zod13.z.string().optional().describe(
11599
11622
  "Your caller-owned externalId \u2014 an alternative selector to `documentId` (requires `type`). Fetches the document you ingested under that externalId without a manual lookup first."
11600
11623
  ),
11601
- type: import_zod12.z.string().optional().describe("Document type \u2014 REQUIRED when selecting by `externalId` (externalId is unique within a type)."),
11602
- includeText: import_zod12.z.boolean().optional().describe(
11624
+ type: import_zod13.z.string().optional().describe("Document type \u2014 REQUIRED when selecting by `externalId` (externalId is unique within a type)."),
11625
+ includeText: import_zod13.z.boolean().optional().describe(
11603
11626
  "If true, fetch and include the document text (capped at ~8K tokens, truncated: true flag if cut). Default false \u2014 metadata only. For larger documents, prefer `document_ask` over dumping text into context."
11604
11627
  ),
11605
- includeDownloadUrl: import_zod12.z.boolean().optional().describe(
11606
- "If true, also return a short-lived presigned `downloadUrl` for the original file (file-backed documents only \u2014 the way to retrieve the raw bytes of a document ingested via file mode). Default false. Unavailable for text-only documents \u2014 `downloadAvailable: false` is set instead."
11628
+ includeDownloadUrl: import_zod13.z.boolean().optional().describe(
11629
+ "If true, also return a short-lived presigned `downloadUrl` for the original file (file-backed documents only \u2014 the way to retrieve the raw bytes of a document ingested via file mode). Default false. Unavailable for text-only documents \u2014 `downloadAvailable: false` is set instead. `downloadExpires` is an upper bound, not a guarantee: if the file behind this document is replaced (a document_ingest upsert) after this URL is minted, the URL can stop working before that time. Request a fresh one after any re-ingest rather than reusing one you already hold."
11607
11630
  )
11608
11631
  };
11609
11632
  function truncateText(text) {
@@ -11686,28 +11709,28 @@ var documentGet = ({ client, log }) => ({
11686
11709
  var document_get_default = documentGet;
11687
11710
 
11688
11711
  // src/tools/document_query.ts
11689
- var import_zod13 = require("zod");
11712
+ var import_zod14 = require("zod");
11690
11713
  var MCP_DEFAULT_LIMIT3 = 3;
11691
11714
  var MCP_MAX_LIMIT3 = 100;
11692
11715
  var inputSchema13 = {
11693
11716
  // Lookup-mode args — provide `field` plus EXACTLY ONE of: value | from+to | prefix.
11694
- field: import_zod13.z.string().optional().describe("Lookup mode: name of the lookup-indexed field to query by."),
11695
- value: import_zod13.z.string().optional().describe("Lookup mode (equality): exact-match value for `field`. Works on sensitive fields too."),
11696
- from: import_zod13.z.string().optional().describe("Lookup mode (range): inclusive lower bound; requires `to`. Range-enabled, non-sensitive fields only."),
11697
- to: import_zod13.z.string().optional().describe("Lookup mode (range): inclusive upper bound; requires `from`."),
11698
- prefix: import_zod13.z.string().optional().describe("Lookup mode (prefix): match values starting with this. Range-enabled string fields only."),
11699
- order: import_zod13.z.enum(["asc", "desc"]).optional().describe(
11717
+ field: import_zod14.z.string().optional().describe("Lookup mode: name of the lookup-indexed field to query by."),
11718
+ value: import_zod14.z.string().optional().describe("Lookup mode (equality): exact-match value for `field`. Works on sensitive fields too."),
11719
+ from: import_zod14.z.string().optional().describe("Lookup mode (range): inclusive lower bound; requires `to`. Range-enabled, non-sensitive fields only."),
11720
+ to: import_zod14.z.string().optional().describe("Lookup mode (range): inclusive upper bound; requires `from`."),
11721
+ prefix: import_zod14.z.string().optional().describe("Lookup mode (prefix): match values starting with this. Range-enabled string fields only."),
11722
+ order: import_zod14.z.enum(["asc", "desc"]).optional().describe(
11700
11723
  "Lookup mode: sort direction by the looked-up field. `asc` (default) or `desc` \u2014 use `desc` with a range/prefix lookup to get the most-recent / highest values first (e.g. latest-N). Ignored in list mode."
11701
11724
  ),
11702
- type: import_zod13.z.string().optional().describe("Lookup mode: the document type (the bound schema's type). Required with `field`."),
11725
+ type: import_zod14.z.string().optional().describe("Lookup mode: the document type (the bound schema's type). Required with `field`."),
11703
11726
  // List-mode args:
11704
- folderId: import_zod13.z.string().optional().describe("List mode: only documents in this folder (Vectros folder id)."),
11705
- userId: import_zod13.z.string().optional().describe("List mode: scope to documents owned by this user."),
11706
- scope: import_zod13.z.string().optional().describe(
11727
+ folderId: import_zod14.z.string().optional().describe("List mode: only documents in this folder (Vectros folder id)."),
11728
+ userId: import_zod14.z.string().optional().describe("List mode: scope to documents owned by this user."),
11729
+ scope: import_zod14.z.string().optional().describe(
11707
11730
  'List mode: filter to documents carrying this scope value, in `namespace:value` form (e.g. "org:<uuid>", "client:<uuid>", "group:eng-team"). `org` and `client` are reserved namespace names, registered like any other; others are namespaces you registered yourself.'
11708
11731
  ),
11709
- startFrom: import_zod13.z.string().optional().describe("Pagination cursor \u2014 pass the `nextCursor` from the previous page to fetch the next. Works in both list and lookup mode."),
11710
- limit: import_zod13.z.number().int().min(1).max(MCP_MAX_LIMIT3).optional().describe(
11732
+ startFrom: import_zod14.z.string().optional().describe("Pagination cursor \u2014 pass the `nextCursor` from the previous page to fetch the next. Works in both list and lookup mode."),
11733
+ limit: import_zod14.z.number().int().min(1).max(MCP_MAX_LIMIT3).optional().describe(
11711
11734
  `Max documents per page. Defaults to a low ${MCP_DEFAULT_LIMIT3} to protect the agent context window; raise up to ${MCP_MAX_LIMIT3} (the documents API max) in one call when you can accept the larger payload, or page with \`startFrom\` instead.`
11712
11735
  )
11713
11736
  };
@@ -11797,29 +11820,29 @@ var documentQuery = ({ client, log }) => ({
11797
11820
  var document_query_default = documentQuery;
11798
11821
 
11799
11822
  // src/tools/document_update.ts
11800
- var import_zod14 = require("zod");
11823
+ var import_zod15 = require("zod");
11801
11824
  var inputSchema14 = {
11802
- documentId: import_zod14.z.string().optional().describe("The Vectros document id to update. Provide this OR externalId+type."),
11803
- externalId: import_zod14.z.string().optional().describe(
11825
+ documentId: import_zod15.z.string().optional().describe("The Vectros document id to update. Provide this OR externalId+type."),
11826
+ externalId: import_zod15.z.string().optional().describe(
11804
11827
  "Your caller-owned externalId \u2014 an alternative selector to `documentId` (requires `type`). Updates the document you ingested under that externalId without a manual lookup first."
11805
11828
  ),
11806
- type: import_zod14.z.string().optional().describe("Document type \u2014 REQUIRED when selecting by `externalId` (externalId is unique within a type)."),
11807
- title: import_zod14.z.string().optional().describe("New title. Omit to keep the current title."),
11808
- fields: import_zod14.z.record(import_zod14.z.string(), import_zod14.z.unknown()).optional().describe(
11829
+ type: import_zod15.z.string().optional().describe("Document type \u2014 REQUIRED when selecting by `externalId` (externalId is unique within a type)."),
11830
+ title: import_zod15.z.string().optional().describe("New title. Omit to keep the current title."),
11831
+ fields: import_zod15.z.record(import_zod15.z.string(), import_zod15.z.unknown()).optional().describe(
11809
11832
  "Typed-payload field\u2192value changes DEEP-MERGED into the existing payload (a field set to `null` is deleted; unspecified fields preserved). Omit to leave the payload unchanged."
11810
11833
  ),
11811
- text: import_zod14.z.string().optional().describe(
11834
+ text: import_zod15.z.string().optional().describe(
11812
11835
  "New raw text body. Supplying it re-ingests the document body and re-queues it for indexing, so the search index reflects the edit (text-ingested documents only \u2014 not file-backed ones). Omit to leave the stored text unchanged. This is the in-place alternative to re-ingesting with upsert:true."
11813
11836
  ),
11814
- folderId: import_zod14.z.string().optional().describe("Move the document into this folder (cannot be cleared once set)."),
11815
- status: import_zod14.z.enum(["ACTIVE", "ARCHIVED"]).optional().describe(
11837
+ folderId: import_zod15.z.string().optional().describe("Move the document into this folder (cannot be cleared once set)."),
11838
+ status: import_zod15.z.enum(["ACTIVE", "ARCHIVED"]).optional().describe(
11816
11839
  "Lifecycle status. `ARCHIVED` soft-retracts the document \u2014 it is pulled from search and recall but kept and recoverable; set it back to `ACTIVE` to re-index and restore it. The way to retire superseded content when the credential has no delete authority. Omit to leave unchanged."
11817
11840
  ),
11818
- userId: import_zod14.z.string().optional().describe("Reassign the owning user (Vectros UUID)."),
11819
- scopes: import_zod14.z.array(import_zod14.z.string()).optional().describe(
11841
+ userId: import_zod15.z.string().optional().describe("Reassign the owning user (Vectros UUID)."),
11842
+ scopes: import_zod15.z.array(import_zod15.z.string()).optional().describe(
11820
11843
  'Reassign scope ownership as `namespace:value` entries, at most 2 (e.g. ["org:<uuid>", "group:eng-team"]) \u2014 the COMPLETE new parent set. `org`/`client` are reserved namespace names, registered like any other. Omit to leave ownership unchanged; `[]` clears it (private to the owning user).'
11821
11844
  ),
11822
- expectedVersion: import_zod14.z.number().int().optional().describe(
11845
+ expectedVersion: import_zod15.z.number().int().optional().describe(
11823
11846
  "Optimistic concurrency: the version you last read. If the document changed since, the update is refused as a conflict (re-read and retry). Omit for last-write-wins."
11824
11847
  )
11825
11848
  };
@@ -11847,18 +11870,18 @@ var documentUpdate = ({ client, log }) => ({
11847
11870
  try {
11848
11871
  const resolved = await resolveDocumentIdByExternalId(client, { id: documentId, externalId, type });
11849
11872
  if ("error" in resolved) return toolError("document_update", new Error(resolved.error));
11850
- const body = {};
11851
- if (title !== void 0) body.title = title;
11852
- if (fields !== void 0) body.payload = fields;
11853
- if (text !== void 0) body.text = text;
11854
- if (folderId !== void 0) body.folderId = folderId;
11855
- if (status !== void 0) body.status = status;
11856
- if (userId !== void 0) body.userId = userId;
11857
- if (scopes !== void 0) body.scopes = scopes;
11858
- if (expectedVersion !== void 0) body.expectedVersion = expectedVersion;
11873
+ const patch = {};
11874
+ if (title !== void 0) patch.title = title;
11875
+ if (fields !== void 0) patch.payload = fields;
11876
+ if (text !== void 0) patch.text = text;
11877
+ if (folderId !== void 0) patch.folderId = folderId;
11878
+ if (status !== void 0) patch.status = status;
11879
+ if (userId !== void 0) patch.userId = userId;
11880
+ if (scopes !== void 0) patch.scopes = scopes;
11881
+ if (expectedVersion !== void 0) patch.expectedVersion = expectedVersion;
11859
11882
  const updated = await client.documents.patchDocument({
11860
11883
  id: resolved.id,
11861
- body
11884
+ ...patch
11862
11885
  });
11863
11886
  log.debug({ tool: "document_update", documentId: resolved.id, externalId }, "document_update ok");
11864
11887
  return { content: [{ type: "text", text: JSON.stringify(updated, null, 2) }] };
@@ -11871,9 +11894,9 @@ var documentUpdate = ({ client, log }) => ({
11871
11894
  var document_update_default = documentUpdate;
11872
11895
 
11873
11896
  // src/tools/document_delete.ts
11874
- var import_zod15 = require("zod");
11897
+ var import_zod16 = require("zod");
11875
11898
  var inputSchema15 = {
11876
- documentId: import_zod15.z.string().min(1, "documentId is required").describe("The Vectros document id to delete.")
11899
+ documentId: import_zod16.z.string().min(1, "documentId is required").describe("The Vectros document id to delete.")
11877
11900
  };
11878
11901
  var documentDelete = ({ client, log }) => ({
11879
11902
  name: "document_delete",
@@ -11900,18 +11923,18 @@ var documentDelete = ({ client, log }) => ({
11900
11923
  var document_delete_default = documentDelete;
11901
11924
 
11902
11925
  // src/tools/folder_query.ts
11903
- var import_zod16 = require("zod");
11926
+ var import_zod17 = require("zod");
11904
11927
  var MCP_DEFAULT_LIMIT4 = 10;
11905
11928
  var MCP_MAX_LIMIT4 = 100;
11906
11929
  var inputSchema16 = {
11907
- id: import_zod16.z.string().optional().describe("Get mode: fetch this single folder by id."),
11908
- parentId: import_zod16.z.string().optional().describe("List mode: direct children of this folder (tree navigation). Omit for a flat tenant list."),
11909
- userId: import_zod16.z.string().optional().describe("List mode: scope to folders owned by this user."),
11910
- scope: import_zod16.z.string().optional().describe(
11930
+ id: import_zod17.z.string().optional().describe("Get mode: fetch this single folder by id."),
11931
+ parentId: import_zod17.z.string().optional().describe("List mode: direct children of this folder (tree navigation). Omit for a flat tenant list."),
11932
+ userId: import_zod17.z.string().optional().describe("List mode: scope to folders owned by this user."),
11933
+ scope: import_zod17.z.string().optional().describe(
11911
11934
  'List mode: filter to folders carrying this scope value, in `namespace:value` form (e.g. "org:<uuid>", "client:<uuid>", "group:eng-team"). `org` and `client` are reserved namespace names, registered like any other; others are namespaces you registered yourself.'
11912
11935
  ),
11913
- startFrom: import_zod16.z.string().optional().describe("List mode: pagination cursor \u2014 pass the `nextCursor` from the previous page to fetch the next."),
11914
- limit: import_zod16.z.number().int().min(1).max(MCP_MAX_LIMIT4).optional().describe(
11936
+ startFrom: import_zod17.z.string().optional().describe("List mode: pagination cursor \u2014 pass the `nextCursor` from the previous page to fetch the next."),
11937
+ limit: import_zod17.z.number().int().min(1).max(MCP_MAX_LIMIT4).optional().describe(
11915
11938
  `List mode: max folders per page. Default 10; raise up to ${MCP_MAX_LIMIT4} (the folders API max) in one call when you can accept the larger page, or page with \`startFrom\`.`
11916
11939
  )
11917
11940
  };
@@ -11951,16 +11974,16 @@ var folderQuery = ({ client, log }) => ({
11951
11974
  var folder_query_default = folderQuery;
11952
11975
 
11953
11976
  // src/tools/folder_create.ts
11954
- var import_zod17 = require("zod");
11977
+ var import_zod18 = require("zod");
11955
11978
  var inputSchema17 = {
11956
- name: import_zod17.z.string().min(1, "name is required").describe("Folder display name."),
11957
- description: import_zod17.z.string().optional().describe("Optional description of the folder's purpose."),
11958
- parentId: import_zod17.z.string().optional().describe("Parent folder id \u2014 places the folder under this parent. Omit for the context default root. Create-only."),
11959
- slug: import_zod17.z.string().optional().describe(
11979
+ name: import_zod18.z.string().min(1, "name is required").describe("Folder display name."),
11980
+ description: import_zod18.z.string().optional().describe("Optional description of the folder's purpose."),
11981
+ parentId: import_zod18.z.string().optional().describe("Parent folder id \u2014 places the folder under this parent. Omit for the context default root. Create-only."),
11982
+ slug: import_zod18.z.string().optional().describe(
11960
11983
  "Optional stable slug (sibling-unique; idempotency key). Lowercase letters/digits/hyphens. SUPPLY THIS to make a retry safe \u2014 if omitted, a derived slug is only ever a freshly-proved-free one, so a redelivered call creates a new sibling folder every time rather than matching the first."
11961
11984
  ),
11962
- userId: import_zod17.z.string().optional().describe("Owning user (Vectros UUID)."),
11963
- scopes: import_zod17.z.array(import_zod17.z.string()).optional().describe(
11985
+ userId: import_zod18.z.string().optional().describe("Owning user (Vectros UUID)."),
11986
+ scopes: import_zod18.z.array(import_zod18.z.string()).optional().describe(
11964
11987
  'Scope ownership as `namespace:value` entries, at most 2 (e.g. ["org:<uuid>", "group:eng-team"]). `org` and `client` are reserved namespace names, registered like any other; others are namespaces you registered yourself. This is the folder\'s COMPLETE scope declaration and values must come from the credential\'s own identity. An empty array `[]` creates a PRIVATE folder owned by the calling user alone. Omit to stamp the credential\'s full identity \u2014 the default.'
11965
11988
  )
11966
11989
  };
@@ -12002,16 +12025,16 @@ var folderCreate = ({ client, log }) => ({
12002
12025
  var folder_create_default = folderCreate;
12003
12026
 
12004
12027
  // src/tools/folder_update.ts
12005
- var import_zod18 = require("zod");
12028
+ var import_zod19 = require("zod");
12006
12029
  var inputSchema18 = {
12007
- id: import_zod18.z.string().min(1, "id is required").describe("The Vectros folder id to update."),
12008
- name: import_zod18.z.string().optional().describe("New folder name. Omit to keep the current name."),
12009
- description: import_zod18.z.string().optional().describe("New description. Omit to leave unchanged."),
12010
- userId: import_zod18.z.string().optional().describe("Reassign the owning user (Vectros UUID)."),
12011
- scopes: import_zod18.z.array(import_zod18.z.string()).optional().describe(
12030
+ id: import_zod19.z.string().min(1, "id is required").describe("The Vectros folder id to update."),
12031
+ name: import_zod19.z.string().optional().describe("New folder name. Omit to keep the current name."),
12032
+ description: import_zod19.z.string().optional().describe("New description. Omit to leave unchanged."),
12033
+ userId: import_zod19.z.string().optional().describe("Reassign the owning user (Vectros UUID)."),
12034
+ scopes: import_zod19.z.array(import_zod19.z.string()).optional().describe(
12012
12035
  'Reassign scope ownership as `namespace:value` entries, at most 2 (e.g. ["org:<uuid>", "group:eng-team"]) \u2014 the COMPLETE new parent set. `org`/`client` are reserved namespace names, registered like any other. Omit to leave ownership unchanged; `[]` clears it (private to the owning user).'
12013
12036
  ),
12014
- expectedVersion: import_zod18.z.number().int().optional().describe(
12037
+ expectedVersion: import_zod19.z.number().int().optional().describe(
12015
12038
  "Optimistic concurrency: the version you last read. If the folder changed since, the update is refused as a conflict (re-read and retry). Omit for last-write-wins."
12016
12039
  )
12017
12040
  };
@@ -12050,9 +12073,9 @@ var folderUpdate = ({ client, log }) => ({
12050
12073
  var folder_update_default = folderUpdate;
12051
12074
 
12052
12075
  // src/tools/folder_delete.ts
12053
- var import_zod19 = require("zod");
12076
+ var import_zod20 = require("zod");
12054
12077
  var inputSchema19 = {
12055
- id: import_zod19.z.string().min(1, "id is required").describe("The Vectros folder id to delete.")
12078
+ id: import_zod20.z.string().min(1, "id is required").describe("The Vectros folder id to delete.")
12056
12079
  };
12057
12080
  var folderDelete = ({ client, log }) => ({
12058
12081
  name: "folder_delete",
@@ -12102,7 +12125,7 @@ var currentIdentity = ({ log, apiKey, environment }) => ({
12102
12125
  var current_identity_default = currentIdentity;
12103
12126
 
12104
12127
  // src/tools/document_ingest.ts
12105
- var import_zod20 = require("zod");
12128
+ var import_zod21 = require("zod");
12106
12129
  var import_promises = require("fs/promises");
12107
12130
  var import_node_path = require("path");
12108
12131
  var IngestPathError = class extends Error {
@@ -12178,43 +12201,46 @@ function inferMimeType(filePath) {
12178
12201
  return EXT_TO_MIME[ext] ?? "application/octet-stream";
12179
12202
  }
12180
12203
  var inputSchema21 = {
12181
- title: import_zod20.z.string().min(1, "title is required").describe("Human-readable document title \u2014 appears in search results and the UI."),
12182
- indexMode: import_zod20.z.enum(["HYBRID", "SEMANTIC", "TEXT", "NONE"]).optional().describe(
12204
+ title: import_zod21.z.string().min(1, "title is required").describe("Human-readable document title \u2014 appears in search results and the UI."),
12205
+ indexMode: import_zod21.z.enum(["HYBRID", "SEMANTIC", "TEXT", "NONE"]).optional().describe(
12183
12206
  "Index strategy. HYBRID (BM25 + dense, default; best for general retrieval), SEMANTIC (dense only; concept-driven queries), TEXT (BM25 only; exact-match / keyword), NONE (store-only / archival \u2014 retrievable by id and structured-field lookup but never in search results). Omit to inherit the bound schema's default."
12184
12207
  ),
12185
- externalId: import_zod20.z.string().optional().describe(
12186
- 'Stable caller-supplied id. Immutable; unique per type within your context. Re-ingesting with the same externalId returns the existing document (idempotent) instead of creating a duplicate \u2014 use it to make ingests safely retryable and as the key other records reference. Mirrors record_create. Receiving the existing document back is a read of it and needs documents:r in addition to documents:c; a create-only key gets an "already exists" error instead of the document.'
12208
+ externalId: import_zod21.z.string().optional().describe(
12209
+ 'Stable caller-supplied id. Immutable; unique per type within your context. Re-ingesting with the same externalId returns the existing document (idempotent) instead of creating a duplicate \u2014 use it to make ingests safely retryable and as the key other records reference. Mirrors record_create. Receiving the existing document back is a read of it and needs documents:r in addition to documents:c; a create-only key gets an "already exists" error instead of the document. Pass `schemaId` with it: an externalId with no `schemaId` is refused (400) unless `confirmUntyped` is true.'
12210
+ ),
12211
+ upsert: import_zod21.z.boolean().optional().describe(
12212
+ "When true, re-ingesting an existing externalId OVERWRITES that document and re-indexes the new body (text mode) / re-uploads and re-indexes the new file (file mode), instead of returning the existing one unchanged. This is the curation/re-sync primitive: edit a source, re-ingest with upsert:true, and the search index reflects the new content. Requires the documents:u scope. IMPORTANT: pass the SAME schemaId (and type) you used originally \u2014 externalId is unique WITHIN a type. Omitting schemaId is refused (400) unless `confirmUntyped` is true, and with it the call targets the UNTYPED namespace, so it mints or updates an untyped document and never touches the typed one. The response `created` flag confirms which happened (created:true = a new document was minted)."
12187
12213
  ),
12188
- upsert: import_zod20.z.boolean().optional().describe(
12189
- "When true, re-ingesting an existing externalId OVERWRITES that document and re-indexes the new body (text mode) / re-uploads and re-indexes the new file (file mode), instead of returning the existing one unchanged. This is the curation/re-sync primitive: edit a source, re-ingest with upsert:true, and the search index reflects the new content. Requires the documents:u scope. IMPORTANT: pass the SAME schemaId (and type) you used originally \u2014 externalId is unique WITHIN a type, so omitting schemaId resolves in the untyped namespace and mints a duplicate instead of updating. The response `created` flag confirms which happened (created:true = a new document was minted)."
12214
+ schemaId: import_zod21.z.string().optional().describe(
12215
+ "Bind this document to a record schema. When set, `payload` is validated against the schema and its lookup fields become directly queryable via document_query (records parity). Resolve a schema id from its type via list_schemas. Omit for an untyped document (an untyped document that also carries an `externalId` needs `confirmUntyped`)."
12190
12216
  ),
12191
- schemaId: import_zod20.z.string().optional().describe(
12192
- "Bind this document to a record schema. When set, `payload` is validated against the schema and its lookup fields become directly queryable via document_query (records parity). Resolve a schema id from its type via list_schemas. Omit for an untyped document."
12217
+ confirmUntyped: import_zod21.z.boolean().optional().describe(
12218
+ "Set true to confirm that an UNTYPED document is what you intend when you pass `externalId` without `schemaId`. Without it the platform refuses that combination (400): externalId is unique per schema, so a forgotten `schemaId` would otherwise quietly create a separate untyped copy instead of reaching the typed document you meant. Do not set it just to get past that error \u2014 check that the document really is untyped first. Ignored when `schemaId` is given or `externalId` is omitted."
12193
12219
  ),
12194
- payload: import_zod20.z.record(import_zod20.z.string(), import_zod20.z.unknown()).optional().describe(
12220
+ payload: import_zod21.z.record(import_zod21.z.string(), import_zod21.z.unknown()).optional().describe(
12195
12221
  "The document's structured data \u2014 a flat key/value object. With `schemaId`, declared fields are validated and lookup fields indexed; undeclared keys pass through as free-form and are searchable via the hybrid_search `filters` param. Without a schema it is stored as free-form metadata. Every number must fall within the signed 64-bit range \u2014 send a larger whole number as a STRING (stored exactly, exact-match lookup), else the ingest is refused with a 400 naming the field."
12196
12222
  ),
12197
12223
  // Inline text mode (mutually exclusive with filePath):
12198
- text: import_zod20.z.string().min(1).optional().describe("Text body to ingest inline. Mutually exclusive with filePath. Either text or filePath is required."),
12199
- storeText: import_zod20.z.boolean().optional().describe(
12224
+ text: import_zod21.z.string().min(1).optional().describe("Text body to ingest inline. Mutually exclusive with filePath. Either text or filePath is required."),
12225
+ storeText: import_zod21.z.boolean().optional().describe(
12200
12226
  "FILE MODE ONLY. Whether the uploaded file's EXTRACTED text is retained after indexing (default true), fixed at ingest. true keeps the extracted text retrievable via document_get(includeText:true) and usable by document_ask; false discards it once indexing completes \u2014 search still works and the original file remains downloadable, but includeText returns textAvailable:false and document_ask is unavailable. NOT accepted with `text`: a text-ingested body is the document itself and is ALWAYS retained, so the backend has no storeText knob on the text path \u2014 passing it with `text` is rejected rather than silently ignored."
12201
12227
  ),
12202
12228
  // File upload mode (mutually exclusive with text; stdio-transport-only):
12203
- filePath: import_zod20.z.string().min(1).optional().describe(
12229
+ filePath: import_zod21.z.string().min(1).optional().describe(
12204
12230
  "Local filesystem path to upload. Mutually exclusive with text. STDIO TRANSPORT ONLY \u2014 rejected on HTTP transport (remote MCP servers can't read your filesystem; use text mode or call the SDK's uploadDocument directly). Must resolve INSIDE the configured ingest root (VECTROS_MCP_INGEST_ROOT, else the server's working directory); paths that escape it (traversal/absolute/symlink) or match a sensitive pattern are rejected."
12205
12231
  ),
12206
- fileType: import_zod20.z.string().optional().describe('MIME type of the file (e.g. "application/pdf"). Inferred from filePath extension if omitted.'),
12232
+ fileType: import_zod21.z.string().optional().describe('MIME type of the file (e.g. "application/pdf"). Inferred from filePath extension if omitted.'),
12207
12233
  // Common (both modes):
12208
- folderId: import_zod20.z.string().optional().describe("Optional folder to ingest into. Default: tenant root."),
12209
- userId: import_zod20.z.string().optional().describe("Owning user ID. Optional."),
12210
- scopes: import_zod20.z.array(import_zod20.z.string()).optional().describe(
12234
+ folderId: import_zod21.z.string().optional().describe("Optional folder to ingest into. Default: tenant root."),
12235
+ userId: import_zod21.z.string().optional().describe("Owning user ID. Optional."),
12236
+ scopes: import_zod21.z.array(import_zod21.z.string()).optional().describe(
12211
12237
  "TEXT MODE ONLY. Scope ownership as `namespace:value` entries, at most 2 (e.g. [\"org:<uuid>\", \"group:eng-team\"]). `org` and `client` are reserved namespace names, registered like any other; others are namespaces you registered yourself. This is the document's COMPLETE scope declaration and values must come from the credential's own identity. An empty array `[]` creates a PRIVATE document owned by the calling user alone. Omit to stamp the credential's full identity \u2014 the default. Rejected with `filePath` (file uploads do not accept a scope declaration): a file-uploaded document is stamped with the credential's full identity."
12212
12238
  )
12213
12239
  };
12214
12240
  var documentIngest = ({ client, log, transport, ingestRoot }) => ({
12215
12241
  name: "document_ingest",
12216
12242
  title: "Ingest a new document (text body or file upload)",
12217
- description: "Create a new document in your Vectros tenant. Two modes:\n \u2022 Text mode: pass `text` (string body). Single-call. Use for crawled content, notes, generated text.\n \u2022 File mode: pass `filePath` (local path on the MCP server's host machine). STDIO-TRANSPORT ONLY \u2014 rejected on HTTP transport. MCP server reads the bytes, requests a presigned upload URL, and PUTs them. Returns when the upload is accepted (indexStatus: PENDING_INDEX); poll with `document_get` until indexStatus is INDEXED.\nEither `text` or `filePath` must be present; both is an error. Idempotent by `externalId` (re-ingest returns the existing document, not a duplicate \u2014 requires documents:r in addition to documents:c, since being handed the existing document is a read of it). To UPDATE an existing document instead \u2014 re-index an edited body \u2014 pass `upsert:true` with the same `externalId` (and the same `schemaId`); this is the re-sync primitive for keeping a knowledge base current. Pass `schemaId` + `payload` for a typed, lookup-queryable document (records parity). indexMode defaults to HYBRID for untyped documents (omit to inherit a bound schema's default). storeText is a FILE-MODE knob (default true): false discards the uploaded file's extracted text after indexing (search + file download keep working; text retrieval and document_ask do not). Text-mode bodies are always retained, so storeText is not accepted with `text`.",
12243
+ description: "Create a new document in your Vectros tenant. Two modes:\n \u2022 Text mode: pass `text` (string body). Single-call. Use for crawled content, notes, generated text.\n \u2022 File mode: pass `filePath` (local path on the MCP server's host machine). STDIO-TRANSPORT ONLY \u2014 rejected on HTTP transport. MCP server reads the bytes, requests a presigned upload URL, and PUTs them. Returns when the upload is accepted (indexStatus: PENDING_INDEX); poll `document_get` until indexStatus is INDEXED. EXCEPTION \u2014 re-ingesting file mode against an externalId that already has a document (response `created:false`): the file body is replaced by ANY such re-ingest, whether or not `upsert` was set (`upsert` there only additionally applies `payload`/`title` to the matched document). The document keeps serving the OLD file's bytes until the new one is adopted, and indexStatus already reads INDEXED left over from that old file, so polling it returns immediately without waiting for the new content. Poll `document_get` and watch `fileItemId` instead \u2014 once it differs from the value it held before this call, the new file has been adopted. Re-request any download URL after that: one minted before adoption can stop working even within its stated `downloadExpires`.\nEither `text` or `filePath` must be present; both is an error. Idempotent by `externalId` (re-ingest returns the existing document, not a duplicate \u2014 requires documents:r in addition to documents:c, since being handed the existing document is a read of it; in FILE MODE a re-ingest against an existing externalId needs documents:u). TEXT MODE: without `upsert`, the existing document's content is genuinely unchanged. FILE MODE: as noted above, a re-ingest against an existing externalId always replaces the file body regardless of `upsert` \u2014 only the `payload`/`title` metadata overwrite is gated by it. To UPDATE an existing document instead \u2014 re-index an edited body \u2014 pass `upsert:true` with the same `externalId` (and the same `schemaId`); this is the re-sync primitive for keeping a knowledge base current. Pass `schemaId` + `payload` for a typed, lookup-queryable document (records parity). An `externalId` with no `schemaId` is refused (400) unless you also pass `confirmUntyped:true` to confirm that an untyped document is intended. indexMode defaults to HYBRID for untyped documents (omit to inherit a bound schema's default). storeText is a FILE-MODE knob (default true): false discards the uploaded file's extracted text after indexing (search + file download keep working; text retrieval and document_ask do not). Text-mode bodies are always retained, so storeText is not accepted with `text`.",
12218
12244
  inputSchema: inputSchema21,
12219
12245
  // Creates by default, idempotent ONLY when the caller supplies `externalId` (optional,
12220
12246
  // per the doc comment above) — re-ingest then returns the existing document rather than
@@ -12232,6 +12258,7 @@ var documentIngest = ({ client, log, transport, ingestRoot }) => ({
12232
12258
  const filePath = args.filePath;
12233
12259
  const schemaId = args.schemaId;
12234
12260
  const upsert = args.upsert;
12261
+ const confirmUntyped = args.confirmUntyped;
12235
12262
  const indexMode = args.indexMode ?? (schemaId ? void 0 : "HYBRID");
12236
12263
  if (!text && !filePath) {
12237
12264
  return toolError(
@@ -12280,6 +12307,7 @@ var documentIngest = ({ client, log, transport, ingestRoot }) => ({
12280
12307
  if (text) {
12281
12308
  const result = await client.documents.ingestDocument({
12282
12309
  upsert,
12310
+ confirmUntyped,
12283
12311
  body: {
12284
12312
  title,
12285
12313
  text,
@@ -12320,6 +12348,7 @@ var documentIngest = ({ client, log, transport, ingestRoot }) => ({
12320
12348
  const storeTextFile = args.storeText ?? true;
12321
12349
  const upload = await client.documents.uploadDocument({
12322
12350
  upsert,
12351
+ confirmUntyped,
12323
12352
  fileName,
12324
12353
  fileType,
12325
12354
  indexMode,
@@ -12352,6 +12381,8 @@ var documentIngest = ({ client, log, transport, ingestRoot }) => ({
12352
12381
  { tool: "document_ingest", mode: "file", id: docId, fileName, fileType, bytes: bytes.length },
12353
12382
  "document_ingest file ok"
12354
12383
  );
12384
+ const uploadCreated = upload?.created;
12385
+ const note = uploadCreated === false ? "File replaced: this re-ingest matched an existing externalId, which always replaces that document's file body (upsert or not \u2014 upsert only additionally applies payload/title to it). The next document_get call may already show indexStatus: INDEXED \u2014 that is left over from the PREVIOUS file, not confirmation the new one is ready, and the document keeps serving the old file's bytes until adoption completes. Poll document_get(id) and watch fileItemId instead: once it differs from the value it held before this call, the new file has been adopted. Any download URL already held for this document was minted for the old file and can stop working before its stated downloadExpires once adoption happens \u2014 request a fresh one after fileItemId changes." : "File uploaded; indexing is asynchronous. Poll document_get(id) until indexStatus is INDEXED.";
12355
12386
  return {
12356
12387
  content: [
12357
12388
  {
@@ -12360,7 +12391,7 @@ var documentIngest = ({ client, log, transport, ingestRoot }) => ({
12360
12391
  {
12361
12392
  ...upload,
12362
12393
  indexStatus: "PENDING_INDEX",
12363
- _note: "File uploaded; indexing is asynchronous. Poll document_get(id) until indexStatus is INDEXED."
12394
+ _note: note
12364
12395
  },
12365
12396
  null,
12366
12397
  2
@@ -12384,29 +12415,29 @@ function presignedUploadHeaders(response) {
12384
12415
  }
12385
12416
 
12386
12417
  // src/tools/lookup_principal.ts
12387
- var import_zod21 = require("zod");
12418
+ var import_zod22 = require("zod");
12388
12419
  var MCP_DEFAULT_LIMIT5 = 10;
12389
12420
  var MCP_MAX_LIMIT5 = 100;
12390
12421
  var inputSchema22 = {
12391
- kind: import_zod21.z.string().describe(
12422
+ kind: import_zod22.z.string().describe(
12392
12423
  'Which principal to look up: "user" (the fixed principal surface), or an entity namespace \u2014 "org", "client" (reserved, registered like any other), or a namespace you registered.'
12393
12424
  ),
12394
- externalId: import_zod21.z.string().optional().describe(
12425
+ externalId: import_zod22.z.string().optional().describe(
12395
12426
  "Resolve mode: your own stable identifier for the principal. Returns the single matching principal (with its Vectros UUID), or an empty array if none. The fastest path to the UUID the ownership filters need. Takes precedence if both this and a `field` lookup are supplied."
12396
12427
  ),
12397
- contextId: import_zod21.z.string().optional().describe(
12428
+ contextId: import_zod22.z.string().optional().describe(
12398
12429
  "Entity kinds only (not `user`, which is always tenant-wide): the app context to look up entities in, for a namespace registered as context-owned rather than tenant-wide. A context-confined credential's own context is used automatically without this; supply it to name a context explicitly (required for an unconfined/root credential to reach a context-owned namespace). Rejected if the namespace turns out to be tenant-wide."
12399
12430
  ),
12400
12431
  // Lookup-mode args — provide `field` plus EXACTLY ONE of: value | from+to | prefix.
12401
- type: import_zod21.z.string().optional().describe('Lookup mode: the identity schema\'s record type (e.g. "person_v1"). Required with `field`.'),
12402
- field: import_zod21.z.string().optional().describe('Lookup mode: name of the schema-declared lookup field to query by (e.g. "email").'),
12403
- value: import_zod21.z.string().optional().describe("Lookup mode (equality): exact-match value for `field`. Works on sensitive fields."),
12404
- from: import_zod21.z.string().optional().describe("Lookup mode (range): inclusive lower bound; requires `to`. Non-sensitive fields only."),
12405
- to: import_zod21.z.string().optional().describe("Lookup mode (range): inclusive upper bound; requires `from`."),
12406
- prefix: import_zod21.z.string().optional().describe("Lookup mode (prefix): match values starting with this. Range-enabled string fields only."),
12407
- order: import_zod21.z.enum(["asc", "desc"]).optional().describe("Lookup mode: sort direction by the looked-up field. `asc` (default) or `desc`."),
12408
- startFrom: import_zod21.z.string().optional().describe("Lookup mode: pagination cursor \u2014 pass the `nextCursor` from the previous page to fetch the next."),
12409
- limit: import_zod21.z.number().int().min(1).max(MCP_MAX_LIMIT5).optional().describe(
12432
+ type: import_zod22.z.string().optional().describe('Lookup mode: the identity schema\'s record type (e.g. "person_v1"). Required with `field`.'),
12433
+ field: import_zod22.z.string().optional().describe('Lookup mode: name of the schema-declared lookup field to query by (e.g. "email").'),
12434
+ value: import_zod22.z.string().optional().describe("Lookup mode (equality): exact-match value for `field`. Works on sensitive fields."),
12435
+ from: import_zod22.z.string().optional().describe("Lookup mode (range): inclusive lower bound; requires `to`. Non-sensitive fields only."),
12436
+ to: import_zod22.z.string().optional().describe("Lookup mode (range): inclusive upper bound; requires `from`."),
12437
+ prefix: import_zod22.z.string().optional().describe("Lookup mode (prefix): match values starting with this. Range-enabled string fields only."),
12438
+ order: import_zod22.z.enum(["asc", "desc"]).optional().describe("Lookup mode: sort direction by the looked-up field. `asc` (default) or `desc`."),
12439
+ startFrom: import_zod22.z.string().optional().describe("Lookup mode: pagination cursor \u2014 pass the `nextCursor` from the previous page to fetch the next."),
12440
+ limit: import_zod22.z.number().int().min(1).max(MCP_MAX_LIMIT5).optional().describe(
12410
12441
  `Max principals per page. Defaults to ${MCP_DEFAULT_LIMIT5}; raise up to ${MCP_MAX_LIMIT5} (the principals API max) in one call when you can accept the payload, or page with \`startFrom\`.`
12411
12442
  )
12412
12443
  };
@@ -12490,11 +12521,11 @@ var lookupPrincipal = ({ client, log }) => ({
12490
12521
  var lookup_principal_default = lookupPrincipal;
12491
12522
 
12492
12523
  // src/tools/version_history.ts
12493
- var import_zod22 = require("zod");
12524
+ var import_zod23 = require("zod");
12494
12525
  var inputSchema23 = {
12495
- resourceType: import_zod22.z.enum(["record", "document"]).describe("Which kind of entity the id refers to: a record or a document."),
12496
- id: import_zod22.z.string().min(1, "id is required").describe("The Vectros id of the record or document whose history you want."),
12497
- startFrom: import_zod22.z.string().optional().describe("Pagination cursor \u2014 pass the `nextCursor` from the previous page to fetch older entries.")
12526
+ resourceType: import_zod23.z.enum(["record", "document"]).describe("Which kind of entity the id refers to: a record or a document."),
12527
+ id: import_zod23.z.string().min(1, "id is required").describe("The Vectros id of the record or document whose history you want."),
12528
+ startFrom: import_zod23.z.string().optional().describe("Pagination cursor \u2014 pass the `nextCursor` from the previous page to fetch older entries.")
12498
12529
  };
12499
12530
  var versionHistory = ({ client, log }) => ({
12500
12531
  name: "version_history",
@@ -12618,7 +12649,7 @@ var ALL_RESOURCE_FACTORIES = {
12618
12649
  };
12619
12650
 
12620
12651
  // src/zod-to-json-schema.ts
12621
- var import_zod23 = require("zod");
12652
+ var import_zod24 = require("zod");
12622
12653
  function zodShapeToJsonSchema(shape) {
12623
12654
  const properties = {};
12624
12655
  const required = [];
@@ -12633,40 +12664,40 @@ function zodShapeToJsonSchema(shape) {
12633
12664
  function zodTypeToJsonSchema(schema) {
12634
12665
  const description = schema.description;
12635
12666
  let current = schema;
12636
- while (current instanceof import_zod23.z.ZodOptional || current instanceof import_zod23.z.ZodDefault || current instanceof import_zod23.z.ZodNullable) {
12667
+ while (current instanceof import_zod24.z.ZodOptional || current instanceof import_zod24.z.ZodDefault || current instanceof import_zod24.z.ZodNullable) {
12637
12668
  current = current._def.innerType;
12638
12669
  }
12639
12670
  const base = description ? { description } : {};
12640
- if (current instanceof import_zod23.z.ZodString) {
12671
+ if (current instanceof import_zod24.z.ZodString) {
12641
12672
  return { ...base, type: "string" };
12642
12673
  }
12643
- if (current instanceof import_zod23.z.ZodNumber) {
12674
+ if (current instanceof import_zod24.z.ZodNumber) {
12644
12675
  return { ...base, type: "number" };
12645
12676
  }
12646
- if (current instanceof import_zod23.z.ZodBoolean) {
12677
+ if (current instanceof import_zod24.z.ZodBoolean) {
12647
12678
  return { ...base, type: "boolean" };
12648
12679
  }
12649
- if (current instanceof import_zod23.z.ZodEnum) {
12680
+ if (current instanceof import_zod24.z.ZodEnum) {
12650
12681
  return {
12651
12682
  ...base,
12652
12683
  type: "string",
12653
12684
  enum: current.options
12654
12685
  };
12655
12686
  }
12656
- if (current instanceof import_zod23.z.ZodArray) {
12687
+ if (current instanceof import_zod24.z.ZodArray) {
12657
12688
  return {
12658
12689
  ...base,
12659
12690
  type: "array",
12660
12691
  items: zodTypeToJsonSchema(current.element)
12661
12692
  };
12662
12693
  }
12663
- if (current instanceof import_zod23.z.ZodObject) {
12694
+ if (current instanceof import_zod24.z.ZodObject) {
12664
12695
  return {
12665
12696
  ...base,
12666
12697
  ...zodShapeToJsonSchema(current.shape)
12667
12698
  };
12668
12699
  }
12669
- if (current instanceof import_zod23.z.ZodRecord) {
12700
+ if (current instanceof import_zod24.z.ZodRecord) {
12670
12701
  const valueType = current._def.valueType;
12671
12702
  return {
12672
12703
  ...base,
@@ -12795,7 +12826,7 @@ var VectrosMCPServer = class {
12795
12826
  if (!tool) {
12796
12827
  result = toolError(req.params.name ?? "unknown", new Error("No such tool."));
12797
12828
  } else {
12798
- const parsed = import_zod24.z.object(tool.inputSchema).strict().safeParse(req.params.arguments ?? {});
12829
+ const parsed = import_zod25.z.object(tool.inputSchema).strict().safeParse(req.params.arguments ?? {});
12799
12830
  if (!parsed.success) {
12800
12831
  result = toolError(tool.name, new Error(formatArgError(tool, parsed.error)));
12801
12832
  } else {