@vectros-ai/mcp-server 0.17.2 → 0.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +55 -0
- package/README.md +52 -29
- package/dist/cli-http.js +210 -169
- package/dist/cli-http.js.map +1 -1
- package/dist/cli-http.mjs +210 -169
- package/dist/cli-http.mjs.map +1 -1
- package/dist/cli.js +210 -169
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +210 -169
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +210 -169
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +210 -169
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/cli-http.mjs
CHANGED
|
@@ -23,6 +23,7 @@ __export(api_exports, {
|
|
|
23
23
|
ContentTooLargeError: () => ContentTooLargeError,
|
|
24
24
|
DocumentContextEvent: () => DocumentContextEvent,
|
|
25
25
|
DocumentLookupRequest: () => DocumentLookupRequest,
|
|
26
|
+
DocumentPatchRequest: () => DocumentPatchRequest,
|
|
26
27
|
DocumentRequest: () => DocumentRequest,
|
|
27
28
|
DocumentResponse: () => DocumentResponse,
|
|
28
29
|
DoneEvent: () => DoneEvent,
|
|
@@ -366,6 +367,13 @@ var DocumentLookupRequest;
|
|
|
366
367
|
Desc: "desc"
|
|
367
368
|
};
|
|
368
369
|
})(DocumentLookupRequest || (DocumentLookupRequest = {}));
|
|
370
|
+
var DocumentPatchRequest;
|
|
371
|
+
((DocumentPatchRequest2) => {
|
|
372
|
+
DocumentPatchRequest2.Status = {
|
|
373
|
+
Active: "ACTIVE",
|
|
374
|
+
Archived: "ARCHIVED"
|
|
375
|
+
};
|
|
376
|
+
})(DocumentPatchRequest || (DocumentPatchRequest = {}));
|
|
369
377
|
var FileUploadRequest;
|
|
370
378
|
((FileUploadRequest2) => {
|
|
371
379
|
FileUploadRequest2.IndexMode = {
|
|
@@ -378,6 +386,7 @@ var FileUploadRequest;
|
|
|
378
386
|
var documents_exports = {};
|
|
379
387
|
__export(documents_exports, {
|
|
380
388
|
DocumentLookupRequest: () => DocumentLookupRequest,
|
|
389
|
+
DocumentPatchRequest: () => DocumentPatchRequest,
|
|
381
390
|
FileUploadRequest: () => FileUploadRequest,
|
|
382
391
|
LookupDocumentsRequestOrder: () => LookupDocumentsRequestOrder
|
|
383
392
|
});
|
|
@@ -2424,7 +2433,7 @@ var AuthClient = class {
|
|
|
2424
2433
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/auth/jwks");
|
|
2425
2434
|
}
|
|
2426
2435
|
/**
|
|
2427
|
-
* Returns a page of per-subject PHI read-access rows: who read which subject's PHI, when, against which record, and whether any sensitive value was actually revealed in plaintext. Metadata only — never the PHI itself.
|
|
2436
|
+
* Returns a page of per-subject PHI read-access rows: who read which subject's PHI, when, against which record, and whether any sensitive value was actually revealed in plaintext. Metadata only — never the PHI itself. Rows exist only where read-access logging is enabled. Provide at least one query axis: a subject (`subjectType` + `subjectId`) within a `contextId` for the primary accounting query; `resourceId` within a `contextId` for 'who read this record'; `callerKeyId` for 'what did this credential read' (account-wide forensic); or `contextId` alone to enumerate a whole context. `from`/`to` bound the time window. Results are scoped to your account, derived from your token — never from input. Requires the `access-log:r` scope.
|
|
2428
2437
|
*
|
|
2429
2438
|
* @param {Vectros.GetAccessLogRequest} request
|
|
2430
2439
|
* @param {AuthClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -3042,6 +3051,7 @@ var AuthClient = class {
|
|
|
3042
3051
|
* @param {AuthClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
3043
3052
|
*
|
|
3044
3053
|
* @throws {@link Vectros.BadRequestError}
|
|
3054
|
+
* @throws {@link Vectros.PaymentRequiredError}
|
|
3045
3055
|
* @throws {@link Vectros.ForbiddenError}
|
|
3046
3056
|
* @throws {@link Vectros.TooManyRequestsError}
|
|
3047
3057
|
*
|
|
@@ -3091,6 +3101,8 @@ var AuthClient = class {
|
|
|
3091
3101
|
switch (_response.error.statusCode) {
|
|
3092
3102
|
case 400:
|
|
3093
3103
|
throw new BadRequestError(_response.error.body, _response.rawResponse);
|
|
3104
|
+
case 402:
|
|
3105
|
+
throw new PaymentRequiredError(_response.error.body, _response.rawResponse);
|
|
3094
3106
|
case 403:
|
|
3095
3107
|
throw new ForbiddenError(_response.error.body, _response.rawResponse);
|
|
3096
3108
|
case 429:
|
|
@@ -4126,7 +4138,7 @@ var AuthClient = class {
|
|
|
4126
4138
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/auth/issuers/{issuerId}");
|
|
4127
4139
|
}
|
|
4128
4140
|
/**
|
|
4129
|
-
* Updates the mutable fields of a registered issuer: `subClaim`, `emailClaim`, `userinfoUri`, `capturedClaims`, `restrictedToDomain` (a new non-blank value must already be a VERIFIED domain for your account; an empty string clears it
|
|
4141
|
+
* Updates the mutable fields of a registered issuer: `subClaim`, `emailClaim`, `userinfoUri`, `capturedClaims`, `restrictedToDomain` (a new non-blank value must already be a VERIFIED domain for your account; an empty string clears it where permitted; see `IssuerUpdateRequest.restrictedToDomain` for the full semantics), `status` (`active`/`suspended` — a registration awaiting verification (`pending_verification`) accepts no status change until it is verified; a suspended issuer's tokens are rejected identically to an unregistered issuer at exchange time), and `selfSignupPolicies`. Fields omitted from the body are left unchanged (partial update). `issuer`, `jwksUri`, `audience`, and `contextId` are trust-anchor / routing-pin fields and are immutable via this route — supplying a value that differs from the current registration is rejected with 400; supplying the current value back is a no-op. Rotating a trust anchor requires deleting and re-registering the issuer, which is itself refused while any user is bound through it. **`subClaim` is identity-determining, not merely cosmetic**: it names which verified JWT claim is read as the federated user's identifier, so changing it on an issuer that already has bound users would silently re-identify (or, under self-signup, orphan) every one of them — changing it is therefore refused once any user has bound through this issuer, the same guard `DELETE` already applies, and is only free before the first real login. Requires a root API key or the bootstrap's provisioning capability, gated identically to every other operation on this surface. A credential confined to one app context may only update an issuer registered in that context; naming one registered in another context returns 404, identically to a nonexistent issuerId. A root API key may update any issuer.
|
|
4130
4142
|
*
|
|
4131
4143
|
* @param {Vectros.IssuerUpdateRequest} request
|
|
4132
4144
|
* @param {AuthClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -4936,7 +4948,7 @@ var ComplianceClient = class {
|
|
|
4936
4948
|
this._options = normalizeClientOptionsWithAuth(options);
|
|
4937
4949
|
}
|
|
4938
4950
|
/**
|
|
4939
|
-
* Submits
|
|
4951
|
+
* Submits an erasure request for a single end-subject (a user, or an identity entity in any namespace). Erasure deletes the records, documents, folders and record schemas the subject solely owns across the declared contexts (and, for a user, its access profiles there), plus its identity and lookup rows when all contexts are covered. Rows co-owned with another owner scope or principal are kept; read-access log entries are not erased. 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.
|
|
4940
4952
|
*
|
|
4941
4953
|
* @param {Vectros.ErasureRequest} request
|
|
4942
4954
|
* @param {ComplianceClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -4999,7 +5011,7 @@ var ComplianceClient = class {
|
|
|
4999
5011
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "POST", "/v1/erasure-requests");
|
|
5000
5012
|
}
|
|
5001
5013
|
/**
|
|
5002
|
-
* 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
|
|
5014
|
+
* 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 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.
|
|
5003
5015
|
*
|
|
5004
5016
|
* @param {Vectros.GetErasureRequestRequest} request
|
|
5005
5017
|
* @param {ComplianceClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -5242,7 +5254,7 @@ var DocumentsClient = class {
|
|
|
5242
5254
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/documents");
|
|
5243
5255
|
}
|
|
5244
5256
|
/**
|
|
5245
|
-
* 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.
|
|
5257
|
+
* 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.
|
|
5246
5258
|
*
|
|
5247
5259
|
* @param {Vectros.IngestDocumentRequest} request
|
|
5248
5260
|
* @param {DocumentsClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -5262,10 +5274,11 @@ var DocumentsClient = class {
|
|
|
5262
5274
|
return HttpResponsePromise.fromPromise(this.__ingestDocument(request, requestOptions));
|
|
5263
5275
|
}
|
|
5264
5276
|
async __ingestDocument(request, requestOptions) {
|
|
5265
|
-
const { upsert, allowClear, body: _body } = request;
|
|
5277
|
+
const { upsert, allowClear, confirmUntyped, body: _body } = request;
|
|
5266
5278
|
const _queryParams = {
|
|
5267
5279
|
upsert,
|
|
5268
|
-
allowClear
|
|
5280
|
+
allowClear,
|
|
5281
|
+
confirmUntyped
|
|
5269
5282
|
};
|
|
5270
5283
|
const _authRequest = await this._options.authProvider.getAuthRequest();
|
|
5271
5284
|
const _headers = mergeHeaders(
|
|
@@ -5500,7 +5513,7 @@ var DocumentsClient = class {
|
|
|
5500
5513
|
/**
|
|
5501
5514
|
* 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.
|
|
5502
5515
|
*
|
|
5503
|
-
* @param {Vectros.
|
|
5516
|
+
* @param {Vectros.DocumentPatchRequest} request
|
|
5504
5517
|
* @param {DocumentsClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
5505
5518
|
*
|
|
5506
5519
|
* @throws {@link Vectros.BadRequestError}
|
|
@@ -5511,17 +5524,14 @@ var DocumentsClient = class {
|
|
|
5511
5524
|
*
|
|
5512
5525
|
* @example
|
|
5513
5526
|
* await client.documents.patchDocument({
|
|
5514
|
-
* id: "id"
|
|
5515
|
-
* body: {
|
|
5516
|
-
* title: "Patient Intake Form \u2014 Jane Doe"
|
|
5517
|
-
* }
|
|
5527
|
+
* id: "id"
|
|
5518
5528
|
* })
|
|
5519
5529
|
*/
|
|
5520
5530
|
patchDocument(request, requestOptions) {
|
|
5521
5531
|
return HttpResponsePromise.fromPromise(this.__patchDocument(request, requestOptions));
|
|
5522
5532
|
}
|
|
5523
5533
|
async __patchDocument(request, requestOptions) {
|
|
5524
|
-
const { id,
|
|
5534
|
+
const { id, ..._body } = request;
|
|
5525
5535
|
const _authRequest = await this._options.authProvider.getAuthRequest();
|
|
5526
5536
|
const _headers = mergeHeaders(
|
|
5527
5537
|
_authRequest.headers,
|
|
@@ -5893,7 +5903,7 @@ var DocumentsClient = class {
|
|
|
5893
5903
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/documents/{id}/versions");
|
|
5894
5904
|
}
|
|
5895
5905
|
/**
|
|
5896
|
-
* 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.
|
|
5906
|
+
* 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.
|
|
5897
5907
|
*
|
|
5898
5908
|
* @param {Vectros.FileUploadRequest} request
|
|
5899
5909
|
* @param {DocumentsClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -5912,9 +5922,10 @@ var DocumentsClient = class {
|
|
|
5912
5922
|
return HttpResponsePromise.fromPromise(this.__uploadDocument(request, requestOptions));
|
|
5913
5923
|
}
|
|
5914
5924
|
async __uploadDocument(request, requestOptions) {
|
|
5915
|
-
const { upsert, ..._body } = request;
|
|
5925
|
+
const { upsert, confirmUntyped, ..._body } = request;
|
|
5916
5926
|
const _queryParams = {
|
|
5917
|
-
upsert
|
|
5927
|
+
upsert,
|
|
5928
|
+
confirmUntyped
|
|
5918
5929
|
};
|
|
5919
5930
|
const _authRequest = await this._options.authProvider.getAuthRequest();
|
|
5920
5931
|
const _headers = mergeHeaders(
|
|
@@ -7819,6 +7830,8 @@ var InferenceClient = class {
|
|
|
7819
7830
|
throw new PaymentRequiredError(_response.error.body, _response.rawResponse);
|
|
7820
7831
|
case 403:
|
|
7821
7832
|
throw new ForbiddenError(_response.error.body, _response.rawResponse);
|
|
7833
|
+
case 413:
|
|
7834
|
+
throw new ContentTooLargeError(_response.error.body, _response.rawResponse);
|
|
7822
7835
|
case 429:
|
|
7823
7836
|
throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
|
|
7824
7837
|
default:
|
|
@@ -7958,6 +7971,8 @@ var InferenceClient = class {
|
|
|
7958
7971
|
throw new PaymentRequiredError(_response.error.body, _response.rawResponse);
|
|
7959
7972
|
case 403:
|
|
7960
7973
|
throw new ForbiddenError(_response.error.body, _response.rawResponse);
|
|
7974
|
+
case 413:
|
|
7975
|
+
throw new ContentTooLargeError(_response.error.body, _response.rawResponse);
|
|
7961
7976
|
case 429:
|
|
7962
7977
|
throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
|
|
7963
7978
|
case 500:
|
|
@@ -10215,7 +10230,7 @@ import {
|
|
|
10215
10230
|
ListToolsRequestSchema,
|
|
10216
10231
|
ReadResourceRequestSchema
|
|
10217
10232
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
10218
|
-
import { z as
|
|
10233
|
+
import { z as z25 } from "zod";
|
|
10219
10234
|
|
|
10220
10235
|
// src/auth.ts
|
|
10221
10236
|
var KEY_RE = /^(sk|ssk|st)_(live|test)_/;
|
|
@@ -10247,7 +10262,7 @@ function warnOnSuboptimalKey(key, log) {
|
|
|
10247
10262
|
if (key.prefix === "sk") {
|
|
10248
10263
|
log.warn(
|
|
10249
10264
|
{ prefix: key.prefix, env: key.env },
|
|
10250
|
-
'wildcard-scope key (sk_*) on a desktop MCP server is overly broad. For production, prefer a scoped ssk_* key bound to a narrowed AccessProfile
|
|
10265
|
+
'wildcard-scope key (sk_*) on a desktop MCP server is overly broad. For production, prefer a scoped ssk_* key bound to a narrowed AccessProfile: `npx -y @vectros-ai/cli bootstrap` mints one, and the "Recommended credential" section of this package\'s README describes it.'
|
|
10251
10266
|
);
|
|
10252
10267
|
} else if (key.prefix === "st") {
|
|
10253
10268
|
log.warn(
|
|
@@ -10259,8 +10274,8 @@ function warnOnSuboptimalKey(key, log) {
|
|
|
10259
10274
|
|
|
10260
10275
|
// src/build-info.ts
|
|
10261
10276
|
var BUILD_INFO = {
|
|
10262
|
-
mcpServer: true ? "0.
|
|
10263
|
-
sdk: true ? "0.
|
|
10277
|
+
mcpServer: true ? "0.18.1" : "dev",
|
|
10278
|
+
sdk: true ? "0.47.0" : "dev"
|
|
10264
10279
|
};
|
|
10265
10280
|
|
|
10266
10281
|
// src/log.ts
|
|
@@ -10552,7 +10567,7 @@ var inputSchema = {
|
|
|
10552
10567
|
"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.)"
|
|
10553
10568
|
),
|
|
10554
10569
|
limit: z.number().int().min(1).max(MCP_MAX_LIMIT).optional().describe(
|
|
10555
|
-
`Max hits per page. Defaults to a low ${MCP_DEFAULT_LIMIT} to protect the agent context window; raise up to ${MCP_MAX_LIMIT} (
|
|
10570
|
+
`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.`
|
|
10556
10571
|
),
|
|
10557
10572
|
offset: z.number().int().min(0).max(200).optional().describe("Skip the first N hits \u2014 for pagination (0\u2013200)."),
|
|
10558
10573
|
folderId: z.string().optional().describe("Scope to content in this EXACT folder (Vectros folder id)."),
|
|
@@ -11301,52 +11316,65 @@ var recordDelete = ({ client, log }) => ({
|
|
|
11301
11316
|
var record_delete_default = recordDelete;
|
|
11302
11317
|
|
|
11303
11318
|
// src/tools/rag_ask.ts
|
|
11319
|
+
import { z as z10 } from "zod";
|
|
11320
|
+
|
|
11321
|
+
// src/tools/provider-alias.ts
|
|
11304
11322
|
import { z as z9 } from "zod";
|
|
11323
|
+
var providerAliasInput = z9.string().min(1, "providerAlias must be non-empty when supplied").optional().describe(
|
|
11324
|
+
"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. If your account has accepted the Business Associate Agreement with Vectros in the developer portal, an account owner must also have attested that provider config in the developer portal (Model Providers); until then the platform refuses the call with a 403 that says it needs a BAA-holder attestation. A call served by your own provider leaves the Vectros perimeter. 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."
|
|
11325
|
+
);
|
|
11326
|
+
|
|
11327
|
+
// src/tools/rag_ask.ts
|
|
11305
11328
|
var SEARCH_MCP_DEFAULT_LIMIT = 5;
|
|
11306
11329
|
var SEARCH_MCP_MAX_LIMIT = 50;
|
|
11307
11330
|
var inputSchema9 = {
|
|
11308
|
-
query:
|
|
11309
|
-
instructions:
|
|
11331
|
+
query: z10.string().min(1, "query must be non-empty").describe("Question to ground against retrieved content."),
|
|
11332
|
+
instructions: z10.string().optional().describe(
|
|
11310
11333
|
'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.'
|
|
11311
11334
|
),
|
|
11312
|
-
model:
|
|
11313
|
-
"Inference model alias (e.g. claude-haiku-
|
|
11335
|
+
model: z10.string().optional().describe(
|
|
11336
|
+
"Inference model alias (e.g. claude-haiku-5-5, claude-sonnet-5-5, claude-opus-5-5). Omit it to use the platform default, which GET /v1/models reports as `defaultModel`; that endpoint also lists the catalog the calling key can reach. When `providerAlias` is set, this instead names the model on that provider's own id space."
|
|
11314
11337
|
),
|
|
11315
|
-
|
|
11316
|
-
|
|
11317
|
-
|
|
11318
|
-
|
|
11338
|
+
providerAlias: providerAliasInput,
|
|
11339
|
+
search: z10.object({
|
|
11340
|
+
mode: z10.enum(["HYBRID", "TEXT", "SEMANTIC"]).optional().describe("Retrieval mode. Default HYBRID."),
|
|
11341
|
+
limit: z10.number().int().min(1).max(SEARCH_MCP_MAX_LIMIT).optional().describe(
|
|
11342
|
+
`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.`
|
|
11319
11343
|
),
|
|
11320
11344
|
// Retrieval scoping — parity with hybrid_search so an agent can ground the
|
|
11321
11345
|
// answer on a specific owner / folder / type / metadata subset, not just the
|
|
11322
11346
|
// whole-tenant corpus.
|
|
11323
|
-
userId:
|
|
11324
|
-
scope:
|
|
11347
|
+
userId: z10.string().optional().describe("Restrict retrieval to content owned by this user (Vectros UUID)."),
|
|
11348
|
+
scope: z10.string().optional().describe(
|
|
11325
11349
|
'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.'
|
|
11326
11350
|
),
|
|
11327
|
-
scopeFilters:
|
|
11351
|
+
scopeFilters: z10.array(z10.string()).min(1, "scopeFilters must name at least one dimension when supplied").optional().describe(
|
|
11328
11352
|
'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`.'
|
|
11329
11353
|
),
|
|
11330
|
-
folderId:
|
|
11331
|
-
rootFolderId:
|
|
11332
|
-
typeName:
|
|
11333
|
-
contentTypes:
|
|
11334
|
-
filters:
|
|
11354
|
+
folderId: z10.string().optional().describe("Restrict retrieval to this exact folder."),
|
|
11355
|
+
rootFolderId: z10.string().optional().describe("Restrict retrieval to this folder and all its descendants."),
|
|
11356
|
+
typeName: z10.string().optional().describe("Restrict record retrieval to this schema type."),
|
|
11357
|
+
contentTypes: z10.array(z10.enum(["documents", "records"])).optional().describe('Narrow retrieval to content types. ["documents"] or ["records"]; omit for both.'),
|
|
11358
|
+
filters: z10.record(z10.unknown()).optional().describe(
|
|
11335
11359
|
'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"}.'
|
|
11336
11360
|
),
|
|
11337
|
-
createdAfter:
|
|
11361
|
+
createdAfter: z10.string().optional().describe(
|
|
11338
11362
|
"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."
|
|
11339
11363
|
),
|
|
11340
|
-
createdBefore:
|
|
11341
|
-
requireComplete:
|
|
11364
|
+
createdBefore: z10.string().optional().describe("Same creation-time basis as createdAfter, bounding at/before this ISO 8601 UTC value."),
|
|
11365
|
+
requireComplete: z10.boolean().optional().describe("Fail closed (503) on a degraded search backend instead of grounding on partial results. Default false.")
|
|
11342
11366
|
}).optional().describe("Retrieval params + scoping. Default mode HYBRID, limit " + SEARCH_MCP_DEFAULT_LIMIT + "."),
|
|
11343
|
-
maxTokens:
|
|
11344
|
-
|
|
11367
|
+
maxTokens: z10.number().int().min(1).optional().describe(
|
|
11368
|
+
"Max output tokens. claude-haiku-5-5, claude-sonnet-5, claude-sonnet-5-5 and claude-opus-5-5 can reason before they answer; when they do, the reasoning counts against this limit, so a small value can return little or no text. Leave headroom: 1024 or more for a short answer."
|
|
11369
|
+
),
|
|
11370
|
+
temperature: z10.number().min(0).max(1).optional().describe(
|
|
11371
|
+
"Sampling temperature (0.0\u20131.0). Default 0.3 \u2014 lower favors deterministic, retrieval-grounded answers. The platform ignores it for claude-haiku-5-5, claude-sonnet-5, claude-sonnet-5-5 and claude-opus-5-5, which sample at their own default; it applies to models that accept a temperature, such as claude-haiku-4-5."
|
|
11372
|
+
)
|
|
11345
11373
|
};
|
|
11346
11374
|
var ragAsk = ({ client, log }) => ({
|
|
11347
11375
|
name: "rag_ask",
|
|
11348
11376
|
title: "RAG ask (corpus-wide)",
|
|
11349
|
-
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`
|
|
11377
|
+
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` (and `temperature`, for the models that accept one). 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.",
|
|
11350
11378
|
inputSchema: inputSchema9,
|
|
11351
11379
|
// NOT a pure read: this call reserves an atomic hold against the caller's prepaid inference
|
|
11352
11380
|
// balance before generation starts, then debits it on completion — a real financial side
|
|
@@ -11388,6 +11416,7 @@ var ragAsk = ({ client, log }) => ({
|
|
|
11388
11416
|
query: args.query,
|
|
11389
11417
|
instructions: args.instructions,
|
|
11390
11418
|
model: args.model,
|
|
11419
|
+
providerAlias: args.providerAlias,
|
|
11391
11420
|
search,
|
|
11392
11421
|
maxTokens: args.maxTokens,
|
|
11393
11422
|
temperature: args.temperature
|
|
@@ -11442,19 +11471,22 @@ var ragAsk = ({ client, log }) => ({
|
|
|
11442
11471
|
var rag_ask_default = ragAsk;
|
|
11443
11472
|
|
|
11444
11473
|
// src/tools/document_ask.ts
|
|
11445
|
-
import { z as
|
|
11474
|
+
import { z as z11 } from "zod";
|
|
11446
11475
|
var inputSchema10 = {
|
|
11447
|
-
documentId:
|
|
11448
|
-
prompt:
|
|
11449
|
-
model:
|
|
11450
|
-
"Inference model alias.
|
|
11476
|
+
documentId: z11.string().min(1, "documentId is required").describe("ID of the document to ask against."),
|
|
11477
|
+
prompt: z11.string().min(1, "prompt is required").describe("Question to ask about the document."),
|
|
11478
|
+
model: z11.string().optional().describe(
|
|
11479
|
+
"Inference model alias. Omit it to use the platform default, which GET /v1/models reports as `defaultModel`; that endpoint also lists the catalog the calling key can reach. When `providerAlias` is set, this instead names the model on that provider's own id space."
|
|
11451
11480
|
),
|
|
11452
|
-
|
|
11481
|
+
providerAlias: providerAliasInput,
|
|
11482
|
+
maxTokens: z11.number().int().min(1).optional().describe(
|
|
11483
|
+
"Max output tokens. claude-haiku-5-5, claude-sonnet-5, claude-sonnet-5-5 and claude-opus-5-5 can reason before they answer; when they do, the reasoning counts against this limit, so a small value can return little or no text. Leave headroom: 1024 or more for a short answer."
|
|
11484
|
+
)
|
|
11453
11485
|
};
|
|
11454
11486
|
var documentAsk = ({ client, log }) => ({
|
|
11455
11487
|
name: "document_ask",
|
|
11456
11488
|
title: "Document ask (single-document)",
|
|
11457
|
-
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`.
|
|
11489
|
+
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.",
|
|
11458
11490
|
inputSchema: inputSchema10,
|
|
11459
11491
|
// NOT a pure read: this call reserves an atomic hold against the caller's prepaid inference
|
|
11460
11492
|
// balance before generation starts, then debits it on completion — a real financial side
|
|
@@ -11471,6 +11503,7 @@ var documentAsk = ({ client, log }) => ({
|
|
|
11471
11503
|
id: args.documentId,
|
|
11472
11504
|
prompt: args.prompt,
|
|
11473
11505
|
model: args.model,
|
|
11506
|
+
providerAlias: args.providerAlias,
|
|
11474
11507
|
maxTokens: args.maxTokens
|
|
11475
11508
|
});
|
|
11476
11509
|
const progressToken = extra._meta?.progressToken;
|
|
@@ -11523,18 +11556,18 @@ var documentAsk = ({ client, log }) => ({
|
|
|
11523
11556
|
var document_ask_default = documentAsk;
|
|
11524
11557
|
|
|
11525
11558
|
// src/tools/list_schemas.ts
|
|
11526
|
-
import { z as
|
|
11559
|
+
import { z as z12 } from "zod";
|
|
11527
11560
|
var inputSchema11 = {
|
|
11528
|
-
userId:
|
|
11561
|
+
userId: z12.string().optional().describe(
|
|
11529
11562
|
"Filter to schemas visible to a specific user. Optional; default returns all schemas the credential can see."
|
|
11530
11563
|
),
|
|
11531
|
-
scope:
|
|
11564
|
+
scope: z12.string().optional().describe(
|
|
11532
11565
|
'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.'
|
|
11533
11566
|
),
|
|
11534
|
-
surface:
|
|
11567
|
+
surface: z12.enum(["record", "document", "user", "entity"]).optional().describe(
|
|
11535
11568
|
"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."
|
|
11536
11569
|
),
|
|
11537
|
-
recordType:
|
|
11570
|
+
recordType: z12.string().optional().describe(
|
|
11538
11571
|
'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.'
|
|
11539
11572
|
)
|
|
11540
11573
|
};
|
|
@@ -11570,19 +11603,19 @@ var listSchemas = ({ client, log }) => ({
|
|
|
11570
11603
|
var list_schemas_default = listSchemas;
|
|
11571
11604
|
|
|
11572
11605
|
// src/tools/document_get.ts
|
|
11573
|
-
import { z as
|
|
11606
|
+
import { z as z13 } from "zod";
|
|
11574
11607
|
var MAX_TEXT_CHARS = 32e3;
|
|
11575
11608
|
var inputSchema12 = {
|
|
11576
|
-
documentId:
|
|
11577
|
-
externalId:
|
|
11609
|
+
documentId: z13.string().optional().describe("The document ID returned by document_ingest or hybrid_search. Provide this OR externalId+type."),
|
|
11610
|
+
externalId: z13.string().optional().describe(
|
|
11578
11611
|
"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."
|
|
11579
11612
|
),
|
|
11580
|
-
type:
|
|
11581
|
-
includeText:
|
|
11613
|
+
type: z13.string().optional().describe("Document type \u2014 REQUIRED when selecting by `externalId` (externalId is unique within a type)."),
|
|
11614
|
+
includeText: z13.boolean().optional().describe(
|
|
11582
11615
|
"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."
|
|
11583
11616
|
),
|
|
11584
|
-
includeDownloadUrl:
|
|
11585
|
-
"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."
|
|
11617
|
+
includeDownloadUrl: z13.boolean().optional().describe(
|
|
11618
|
+
"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."
|
|
11586
11619
|
)
|
|
11587
11620
|
};
|
|
11588
11621
|
function truncateText(text) {
|
|
@@ -11665,28 +11698,28 @@ var documentGet = ({ client, log }) => ({
|
|
|
11665
11698
|
var document_get_default = documentGet;
|
|
11666
11699
|
|
|
11667
11700
|
// src/tools/document_query.ts
|
|
11668
|
-
import { z as
|
|
11701
|
+
import { z as z14 } from "zod";
|
|
11669
11702
|
var MCP_DEFAULT_LIMIT3 = 3;
|
|
11670
11703
|
var MCP_MAX_LIMIT3 = 100;
|
|
11671
11704
|
var inputSchema13 = {
|
|
11672
11705
|
// Lookup-mode args — provide `field` plus EXACTLY ONE of: value | from+to | prefix.
|
|
11673
|
-
field:
|
|
11674
|
-
value:
|
|
11675
|
-
from:
|
|
11676
|
-
to:
|
|
11677
|
-
prefix:
|
|
11678
|
-
order:
|
|
11706
|
+
field: z14.string().optional().describe("Lookup mode: name of the lookup-indexed field to query by."),
|
|
11707
|
+
value: z14.string().optional().describe("Lookup mode (equality): exact-match value for `field`. Works on sensitive fields too."),
|
|
11708
|
+
from: z14.string().optional().describe("Lookup mode (range): inclusive lower bound; requires `to`. Range-enabled, non-sensitive fields only."),
|
|
11709
|
+
to: z14.string().optional().describe("Lookup mode (range): inclusive upper bound; requires `from`."),
|
|
11710
|
+
prefix: z14.string().optional().describe("Lookup mode (prefix): match values starting with this. Range-enabled string fields only."),
|
|
11711
|
+
order: z14.enum(["asc", "desc"]).optional().describe(
|
|
11679
11712
|
"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."
|
|
11680
11713
|
),
|
|
11681
|
-
type:
|
|
11714
|
+
type: z14.string().optional().describe("Lookup mode: the document type (the bound schema's type). Required with `field`."),
|
|
11682
11715
|
// List-mode args:
|
|
11683
|
-
folderId:
|
|
11684
|
-
userId:
|
|
11685
|
-
scope:
|
|
11716
|
+
folderId: z14.string().optional().describe("List mode: only documents in this folder (Vectros folder id)."),
|
|
11717
|
+
userId: z14.string().optional().describe("List mode: scope to documents owned by this user."),
|
|
11718
|
+
scope: z14.string().optional().describe(
|
|
11686
11719
|
'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.'
|
|
11687
11720
|
),
|
|
11688
|
-
startFrom:
|
|
11689
|
-
limit:
|
|
11721
|
+
startFrom: z14.string().optional().describe("Pagination cursor \u2014 pass the `nextCursor` from the previous page to fetch the next. Works in both list and lookup mode."),
|
|
11722
|
+
limit: z14.number().int().min(1).max(MCP_MAX_LIMIT3).optional().describe(
|
|
11690
11723
|
`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.`
|
|
11691
11724
|
)
|
|
11692
11725
|
};
|
|
@@ -11776,29 +11809,29 @@ var documentQuery = ({ client, log }) => ({
|
|
|
11776
11809
|
var document_query_default = documentQuery;
|
|
11777
11810
|
|
|
11778
11811
|
// src/tools/document_update.ts
|
|
11779
|
-
import { z as
|
|
11812
|
+
import { z as z15 } from "zod";
|
|
11780
11813
|
var inputSchema14 = {
|
|
11781
|
-
documentId:
|
|
11782
|
-
externalId:
|
|
11814
|
+
documentId: z15.string().optional().describe("The Vectros document id to update. Provide this OR externalId+type."),
|
|
11815
|
+
externalId: z15.string().optional().describe(
|
|
11783
11816
|
"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."
|
|
11784
11817
|
),
|
|
11785
|
-
type:
|
|
11786
|
-
title:
|
|
11787
|
-
fields:
|
|
11818
|
+
type: z15.string().optional().describe("Document type \u2014 REQUIRED when selecting by `externalId` (externalId is unique within a type)."),
|
|
11819
|
+
title: z15.string().optional().describe("New title. Omit to keep the current title."),
|
|
11820
|
+
fields: z15.record(z15.string(), z15.unknown()).optional().describe(
|
|
11788
11821
|
"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."
|
|
11789
11822
|
),
|
|
11790
|
-
text:
|
|
11823
|
+
text: z15.string().optional().describe(
|
|
11791
11824
|
"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."
|
|
11792
11825
|
),
|
|
11793
|
-
folderId:
|
|
11794
|
-
status:
|
|
11826
|
+
folderId: z15.string().optional().describe("Move the document into this folder (cannot be cleared once set)."),
|
|
11827
|
+
status: z15.enum(["ACTIVE", "ARCHIVED"]).optional().describe(
|
|
11795
11828
|
"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."
|
|
11796
11829
|
),
|
|
11797
|
-
userId:
|
|
11798
|
-
scopes:
|
|
11830
|
+
userId: z15.string().optional().describe("Reassign the owning user (Vectros UUID)."),
|
|
11831
|
+
scopes: z15.array(z15.string()).optional().describe(
|
|
11799
11832
|
'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).'
|
|
11800
11833
|
),
|
|
11801
|
-
expectedVersion:
|
|
11834
|
+
expectedVersion: z15.number().int().optional().describe(
|
|
11802
11835
|
"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."
|
|
11803
11836
|
)
|
|
11804
11837
|
};
|
|
@@ -11826,18 +11859,18 @@ var documentUpdate = ({ client, log }) => ({
|
|
|
11826
11859
|
try {
|
|
11827
11860
|
const resolved = await resolveDocumentIdByExternalId(client, { id: documentId, externalId, type });
|
|
11828
11861
|
if ("error" in resolved) return toolError("document_update", new Error(resolved.error));
|
|
11829
|
-
const
|
|
11830
|
-
if (title !== void 0)
|
|
11831
|
-
if (fields !== void 0)
|
|
11832
|
-
if (text !== void 0)
|
|
11833
|
-
if (folderId !== void 0)
|
|
11834
|
-
if (status !== void 0)
|
|
11835
|
-
if (userId !== void 0)
|
|
11836
|
-
if (scopes !== void 0)
|
|
11837
|
-
if (expectedVersion !== void 0)
|
|
11862
|
+
const patch = {};
|
|
11863
|
+
if (title !== void 0) patch.title = title;
|
|
11864
|
+
if (fields !== void 0) patch.payload = fields;
|
|
11865
|
+
if (text !== void 0) patch.text = text;
|
|
11866
|
+
if (folderId !== void 0) patch.folderId = folderId;
|
|
11867
|
+
if (status !== void 0) patch.status = status;
|
|
11868
|
+
if (userId !== void 0) patch.userId = userId;
|
|
11869
|
+
if (scopes !== void 0) patch.scopes = scopes;
|
|
11870
|
+
if (expectedVersion !== void 0) patch.expectedVersion = expectedVersion;
|
|
11838
11871
|
const updated = await client.documents.patchDocument({
|
|
11839
11872
|
id: resolved.id,
|
|
11840
|
-
|
|
11873
|
+
...patch
|
|
11841
11874
|
});
|
|
11842
11875
|
log.debug({ tool: "document_update", documentId: resolved.id, externalId }, "document_update ok");
|
|
11843
11876
|
return { content: [{ type: "text", text: JSON.stringify(updated, null, 2) }] };
|
|
@@ -11850,9 +11883,9 @@ var documentUpdate = ({ client, log }) => ({
|
|
|
11850
11883
|
var document_update_default = documentUpdate;
|
|
11851
11884
|
|
|
11852
11885
|
// src/tools/document_delete.ts
|
|
11853
|
-
import { z as
|
|
11886
|
+
import { z as z16 } from "zod";
|
|
11854
11887
|
var inputSchema15 = {
|
|
11855
|
-
documentId:
|
|
11888
|
+
documentId: z16.string().min(1, "documentId is required").describe("The Vectros document id to delete.")
|
|
11856
11889
|
};
|
|
11857
11890
|
var documentDelete = ({ client, log }) => ({
|
|
11858
11891
|
name: "document_delete",
|
|
@@ -11879,18 +11912,18 @@ var documentDelete = ({ client, log }) => ({
|
|
|
11879
11912
|
var document_delete_default = documentDelete;
|
|
11880
11913
|
|
|
11881
11914
|
// src/tools/folder_query.ts
|
|
11882
|
-
import { z as
|
|
11915
|
+
import { z as z17 } from "zod";
|
|
11883
11916
|
var MCP_DEFAULT_LIMIT4 = 10;
|
|
11884
11917
|
var MCP_MAX_LIMIT4 = 100;
|
|
11885
11918
|
var inputSchema16 = {
|
|
11886
|
-
id:
|
|
11887
|
-
parentId:
|
|
11888
|
-
userId:
|
|
11889
|
-
scope:
|
|
11919
|
+
id: z17.string().optional().describe("Get mode: fetch this single folder by id."),
|
|
11920
|
+
parentId: z17.string().optional().describe("List mode: direct children of this folder (tree navigation). Omit for a flat tenant list."),
|
|
11921
|
+
userId: z17.string().optional().describe("List mode: scope to folders owned by this user."),
|
|
11922
|
+
scope: z17.string().optional().describe(
|
|
11890
11923
|
'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.'
|
|
11891
11924
|
),
|
|
11892
|
-
startFrom:
|
|
11893
|
-
limit:
|
|
11925
|
+
startFrom: z17.string().optional().describe("List mode: pagination cursor \u2014 pass the `nextCursor` from the previous page to fetch the next."),
|
|
11926
|
+
limit: z17.number().int().min(1).max(MCP_MAX_LIMIT4).optional().describe(
|
|
11894
11927
|
`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\`.`
|
|
11895
11928
|
)
|
|
11896
11929
|
};
|
|
@@ -11930,16 +11963,16 @@ var folderQuery = ({ client, log }) => ({
|
|
|
11930
11963
|
var folder_query_default = folderQuery;
|
|
11931
11964
|
|
|
11932
11965
|
// src/tools/folder_create.ts
|
|
11933
|
-
import { z as
|
|
11966
|
+
import { z as z18 } from "zod";
|
|
11934
11967
|
var inputSchema17 = {
|
|
11935
|
-
name:
|
|
11936
|
-
description:
|
|
11937
|
-
parentId:
|
|
11938
|
-
slug:
|
|
11968
|
+
name: z18.string().min(1, "name is required").describe("Folder display name."),
|
|
11969
|
+
description: z18.string().optional().describe("Optional description of the folder's purpose."),
|
|
11970
|
+
parentId: z18.string().optional().describe("Parent folder id \u2014 places the folder under this parent. Omit for the context default root. Create-only."),
|
|
11971
|
+
slug: z18.string().optional().describe(
|
|
11939
11972
|
"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."
|
|
11940
11973
|
),
|
|
11941
|
-
userId:
|
|
11942
|
-
scopes:
|
|
11974
|
+
userId: z18.string().optional().describe("Owning user (Vectros UUID)."),
|
|
11975
|
+
scopes: z18.array(z18.string()).optional().describe(
|
|
11943
11976
|
'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.'
|
|
11944
11977
|
)
|
|
11945
11978
|
};
|
|
@@ -11981,16 +12014,16 @@ var folderCreate = ({ client, log }) => ({
|
|
|
11981
12014
|
var folder_create_default = folderCreate;
|
|
11982
12015
|
|
|
11983
12016
|
// src/tools/folder_update.ts
|
|
11984
|
-
import { z as
|
|
12017
|
+
import { z as z19 } from "zod";
|
|
11985
12018
|
var inputSchema18 = {
|
|
11986
|
-
id:
|
|
11987
|
-
name:
|
|
11988
|
-
description:
|
|
11989
|
-
userId:
|
|
11990
|
-
scopes:
|
|
12019
|
+
id: z19.string().min(1, "id is required").describe("The Vectros folder id to update."),
|
|
12020
|
+
name: z19.string().optional().describe("New folder name. Omit to keep the current name."),
|
|
12021
|
+
description: z19.string().optional().describe("New description. Omit to leave unchanged."),
|
|
12022
|
+
userId: z19.string().optional().describe("Reassign the owning user (Vectros UUID)."),
|
|
12023
|
+
scopes: z19.array(z19.string()).optional().describe(
|
|
11991
12024
|
'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).'
|
|
11992
12025
|
),
|
|
11993
|
-
expectedVersion:
|
|
12026
|
+
expectedVersion: z19.number().int().optional().describe(
|
|
11994
12027
|
"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."
|
|
11995
12028
|
)
|
|
11996
12029
|
};
|
|
@@ -12029,14 +12062,14 @@ var folderUpdate = ({ client, log }) => ({
|
|
|
12029
12062
|
var folder_update_default = folderUpdate;
|
|
12030
12063
|
|
|
12031
12064
|
// src/tools/folder_delete.ts
|
|
12032
|
-
import { z as
|
|
12065
|
+
import { z as z20 } from "zod";
|
|
12033
12066
|
var inputSchema19 = {
|
|
12034
|
-
id:
|
|
12067
|
+
id: z20.string().min(1, "id is required").describe("The Vectros folder id to delete.")
|
|
12035
12068
|
};
|
|
12036
12069
|
var folderDelete = ({ client, log }) => ({
|
|
12037
12070
|
name: "folder_delete",
|
|
12038
12071
|
title: "Delete a folder",
|
|
12039
|
-
description: 'Permanently delete a folder by id. The folder must be EMPTY first \u2014 it must contain no documents, no records, and no sub-folders \u2014 and a non-empty folder is refused, which is the most common way this call fails. Use record_query with this folderId, and document_query, to see what is in it. Clearing it differs by content type: a document can be moved out (document_update with a different folderId) or deleted. A RECORD can also be re-filed into another folder \u2014 the API supports it \u2014 but THIS SERVER does not expose that yet: record_update has no folderId argument, so from here your only option is record_delete (needs records:d). Do NOT read that as "the record cannot be moved" and delete
|
|
12072
|
+
description: 'Permanently delete a folder by id. The folder must be EMPTY first \u2014 it must contain no documents, no records, and no sub-folders \u2014 and a non-empty folder is refused, which is the most common way this call fails. Use record_query with this folderId, and document_query, to see what is in it. Clearing it differs by content type: a document can be moved out (document_update with a different folderId) or deleted. A RECORD can also be re-filed into another folder \u2014 the API supports it \u2014 but THIS SERVER does not expose that yet: record_update has no folderId argument, so from here your only option is record_delete (needs records:d). Do NOT read that as "the record cannot be moved" and delete the record on that basis: if the record should be kept, tell the user to move it with the Vectros API/SDK directly rather than deleting it here. A sub-folder cannot be re-parented at all, so nested folders have to be emptied and deleted innermost-first. Note the emptiness check counts everything in the folder, INCLUDING items your credential cannot read \u2014 so a refusal you cannot account for from what you can list is expected behaviour, not a bug, and retrying will not clear it. Requires the key to allow folders:d \u2014 a key without it gets a permission error. Protected folders (e.g. a context root) cannot be deleted at all, however empty.',
|
|
12040
12073
|
inputSchema: inputSchema19,
|
|
12041
12074
|
// Deletes. Idempotent in the standard REST sense: the end state ("this id no longer
|
|
12042
12075
|
// resolves") is the same whether this is the first delete or a repeat of one.
|
|
@@ -12081,7 +12114,7 @@ var currentIdentity = ({ log, apiKey, environment }) => ({
|
|
|
12081
12114
|
var current_identity_default = currentIdentity;
|
|
12082
12115
|
|
|
12083
12116
|
// src/tools/document_ingest.ts
|
|
12084
|
-
import { z as
|
|
12117
|
+
import { z as z21 } from "zod";
|
|
12085
12118
|
import { readFile, realpath } from "fs/promises";
|
|
12086
12119
|
import { basename, extname, resolve, relative, isAbsolute } from "path";
|
|
12087
12120
|
var IngestPathError = class extends Error {
|
|
@@ -12157,43 +12190,46 @@ function inferMimeType(filePath) {
|
|
|
12157
12190
|
return EXT_TO_MIME[ext] ?? "application/octet-stream";
|
|
12158
12191
|
}
|
|
12159
12192
|
var inputSchema21 = {
|
|
12160
|
-
title:
|
|
12161
|
-
indexMode:
|
|
12193
|
+
title: z21.string().min(1, "title is required").describe("Human-readable document title \u2014 appears in search results and the UI."),
|
|
12194
|
+
indexMode: z21.enum(["HYBRID", "SEMANTIC", "TEXT", "NONE"]).optional().describe(
|
|
12162
12195
|
"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."
|
|
12163
12196
|
),
|
|
12164
|
-
externalId:
|
|
12165
|
-
'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.'
|
|
12197
|
+
externalId: z21.string().optional().describe(
|
|
12198
|
+
'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.'
|
|
12166
12199
|
),
|
|
12167
|
-
upsert:
|
|
12168
|
-
"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,
|
|
12200
|
+
upsert: z21.boolean().optional().describe(
|
|
12201
|
+
"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)."
|
|
12169
12202
|
),
|
|
12170
|
-
schemaId:
|
|
12171
|
-
"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."
|
|
12203
|
+
schemaId: z21.string().optional().describe(
|
|
12204
|
+
"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`)."
|
|
12172
12205
|
),
|
|
12173
|
-
|
|
12206
|
+
confirmUntyped: z21.boolean().optional().describe(
|
|
12207
|
+
"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."
|
|
12208
|
+
),
|
|
12209
|
+
payload: z21.record(z21.string(), z21.unknown()).optional().describe(
|
|
12174
12210
|
"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."
|
|
12175
12211
|
),
|
|
12176
12212
|
// Inline text mode (mutually exclusive with filePath):
|
|
12177
|
-
text:
|
|
12178
|
-
storeText:
|
|
12213
|
+
text: z21.string().min(1).optional().describe("Text body to ingest inline. Mutually exclusive with filePath. Either text or filePath is required."),
|
|
12214
|
+
storeText: z21.boolean().optional().describe(
|
|
12179
12215
|
"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."
|
|
12180
12216
|
),
|
|
12181
12217
|
// File upload mode (mutually exclusive with text; stdio-transport-only):
|
|
12182
|
-
filePath:
|
|
12218
|
+
filePath: z21.string().min(1).optional().describe(
|
|
12183
12219
|
"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."
|
|
12184
12220
|
),
|
|
12185
|
-
fileType:
|
|
12221
|
+
fileType: z21.string().optional().describe('MIME type of the file (e.g. "application/pdf"). Inferred from filePath extension if omitted.'),
|
|
12186
12222
|
// Common (both modes):
|
|
12187
|
-
folderId:
|
|
12188
|
-
userId:
|
|
12189
|
-
scopes:
|
|
12223
|
+
folderId: z21.string().optional().describe("Optional folder to ingest into. Default: tenant root."),
|
|
12224
|
+
userId: z21.string().optional().describe("Owning user ID. Optional."),
|
|
12225
|
+
scopes: z21.array(z21.string()).optional().describe(
|
|
12190
12226
|
"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."
|
|
12191
12227
|
)
|
|
12192
12228
|
};
|
|
12193
12229
|
var documentIngest = ({ client, log, transport, ingestRoot }) => ({
|
|
12194
12230
|
name: "document_ingest",
|
|
12195
12231
|
title: "Ingest a new document (text body or file upload)",
|
|
12196
|
-
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
|
|
12232
|
+
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`.",
|
|
12197
12233
|
inputSchema: inputSchema21,
|
|
12198
12234
|
// Creates by default, idempotent ONLY when the caller supplies `externalId` (optional,
|
|
12199
12235
|
// per the doc comment above) — re-ingest then returns the existing document rather than
|
|
@@ -12211,6 +12247,7 @@ var documentIngest = ({ client, log, transport, ingestRoot }) => ({
|
|
|
12211
12247
|
const filePath = args.filePath;
|
|
12212
12248
|
const schemaId = args.schemaId;
|
|
12213
12249
|
const upsert = args.upsert;
|
|
12250
|
+
const confirmUntyped = args.confirmUntyped;
|
|
12214
12251
|
const indexMode = args.indexMode ?? (schemaId ? void 0 : "HYBRID");
|
|
12215
12252
|
if (!text && !filePath) {
|
|
12216
12253
|
return toolError(
|
|
@@ -12259,6 +12296,7 @@ var documentIngest = ({ client, log, transport, ingestRoot }) => ({
|
|
|
12259
12296
|
if (text) {
|
|
12260
12297
|
const result = await client.documents.ingestDocument({
|
|
12261
12298
|
upsert,
|
|
12299
|
+
confirmUntyped,
|
|
12262
12300
|
body: {
|
|
12263
12301
|
title,
|
|
12264
12302
|
text,
|
|
@@ -12299,6 +12337,7 @@ var documentIngest = ({ client, log, transport, ingestRoot }) => ({
|
|
|
12299
12337
|
const storeTextFile = args.storeText ?? true;
|
|
12300
12338
|
const upload = await client.documents.uploadDocument({
|
|
12301
12339
|
upsert,
|
|
12340
|
+
confirmUntyped,
|
|
12302
12341
|
fileName,
|
|
12303
12342
|
fileType,
|
|
12304
12343
|
indexMode,
|
|
@@ -12331,6 +12370,8 @@ var documentIngest = ({ client, log, transport, ingestRoot }) => ({
|
|
|
12331
12370
|
{ tool: "document_ingest", mode: "file", id: docId, fileName, fileType, bytes: bytes.length },
|
|
12332
12371
|
"document_ingest file ok"
|
|
12333
12372
|
);
|
|
12373
|
+
const uploadCreated = upload?.created;
|
|
12374
|
+
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.";
|
|
12334
12375
|
return {
|
|
12335
12376
|
content: [
|
|
12336
12377
|
{
|
|
@@ -12339,7 +12380,7 @@ var documentIngest = ({ client, log, transport, ingestRoot }) => ({
|
|
|
12339
12380
|
{
|
|
12340
12381
|
...upload,
|
|
12341
12382
|
indexStatus: "PENDING_INDEX",
|
|
12342
|
-
_note:
|
|
12383
|
+
_note: note
|
|
12343
12384
|
},
|
|
12344
12385
|
null,
|
|
12345
12386
|
2
|
|
@@ -12363,29 +12404,29 @@ function presignedUploadHeaders(response) {
|
|
|
12363
12404
|
}
|
|
12364
12405
|
|
|
12365
12406
|
// src/tools/lookup_principal.ts
|
|
12366
|
-
import { z as
|
|
12407
|
+
import { z as z22 } from "zod";
|
|
12367
12408
|
var MCP_DEFAULT_LIMIT5 = 10;
|
|
12368
12409
|
var MCP_MAX_LIMIT5 = 100;
|
|
12369
12410
|
var inputSchema22 = {
|
|
12370
|
-
kind:
|
|
12411
|
+
kind: z22.string().describe(
|
|
12371
12412
|
'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.'
|
|
12372
12413
|
),
|
|
12373
|
-
externalId:
|
|
12414
|
+
externalId: z22.string().optional().describe(
|
|
12374
12415
|
"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."
|
|
12375
12416
|
),
|
|
12376
|
-
contextId:
|
|
12417
|
+
contextId: z22.string().optional().describe(
|
|
12377
12418
|
"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."
|
|
12378
12419
|
),
|
|
12379
12420
|
// Lookup-mode args — provide `field` plus EXACTLY ONE of: value | from+to | prefix.
|
|
12380
|
-
type:
|
|
12381
|
-
field:
|
|
12382
|
-
value:
|
|
12383
|
-
from:
|
|
12384
|
-
to:
|
|
12385
|
-
prefix:
|
|
12386
|
-
order:
|
|
12387
|
-
startFrom:
|
|
12388
|
-
limit:
|
|
12421
|
+
type: z22.string().optional().describe('Lookup mode: the identity schema\'s record type (e.g. "person_v1"). Required with `field`.'),
|
|
12422
|
+
field: z22.string().optional().describe('Lookup mode: name of the schema-declared lookup field to query by (e.g. "email").'),
|
|
12423
|
+
value: z22.string().optional().describe("Lookup mode (equality): exact-match value for `field`. Works on sensitive fields."),
|
|
12424
|
+
from: z22.string().optional().describe("Lookup mode (range): inclusive lower bound; requires `to`. Non-sensitive fields only."),
|
|
12425
|
+
to: z22.string().optional().describe("Lookup mode (range): inclusive upper bound; requires `from`."),
|
|
12426
|
+
prefix: z22.string().optional().describe("Lookup mode (prefix): match values starting with this. Range-enabled string fields only."),
|
|
12427
|
+
order: z22.enum(["asc", "desc"]).optional().describe("Lookup mode: sort direction by the looked-up field. `asc` (default) or `desc`."),
|
|
12428
|
+
startFrom: z22.string().optional().describe("Lookup mode: pagination cursor \u2014 pass the `nextCursor` from the previous page to fetch the next."),
|
|
12429
|
+
limit: z22.number().int().min(1).max(MCP_MAX_LIMIT5).optional().describe(
|
|
12389
12430
|
`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\`.`
|
|
12390
12431
|
)
|
|
12391
12432
|
};
|
|
@@ -12469,11 +12510,11 @@ var lookupPrincipal = ({ client, log }) => ({
|
|
|
12469
12510
|
var lookup_principal_default = lookupPrincipal;
|
|
12470
12511
|
|
|
12471
12512
|
// src/tools/version_history.ts
|
|
12472
|
-
import { z as
|
|
12513
|
+
import { z as z23 } from "zod";
|
|
12473
12514
|
var inputSchema23 = {
|
|
12474
|
-
resourceType:
|
|
12475
|
-
id:
|
|
12476
|
-
startFrom:
|
|
12515
|
+
resourceType: z23.enum(["record", "document"]).describe("Which kind of entity the id refers to: a record or a document."),
|
|
12516
|
+
id: z23.string().min(1, "id is required").describe("The Vectros id of the record or document whose history you want."),
|
|
12517
|
+
startFrom: z23.string().optional().describe("Pagination cursor \u2014 pass the `nextCursor` from the previous page to fetch older entries.")
|
|
12477
12518
|
};
|
|
12478
12519
|
var versionHistory = ({ client, log }) => ({
|
|
12479
12520
|
name: "version_history",
|
|
@@ -12597,7 +12638,7 @@ var ALL_RESOURCE_FACTORIES = {
|
|
|
12597
12638
|
};
|
|
12598
12639
|
|
|
12599
12640
|
// src/zod-to-json-schema.ts
|
|
12600
|
-
import { z as
|
|
12641
|
+
import { z as z24 } from "zod";
|
|
12601
12642
|
function zodShapeToJsonSchema(shape) {
|
|
12602
12643
|
const properties = {};
|
|
12603
12644
|
const required = [];
|
|
@@ -12612,40 +12653,40 @@ function zodShapeToJsonSchema(shape) {
|
|
|
12612
12653
|
function zodTypeToJsonSchema(schema) {
|
|
12613
12654
|
const description = schema.description;
|
|
12614
12655
|
let current = schema;
|
|
12615
|
-
while (current instanceof
|
|
12656
|
+
while (current instanceof z24.ZodOptional || current instanceof z24.ZodDefault || current instanceof z24.ZodNullable) {
|
|
12616
12657
|
current = current._def.innerType;
|
|
12617
12658
|
}
|
|
12618
12659
|
const base = description ? { description } : {};
|
|
12619
|
-
if (current instanceof
|
|
12660
|
+
if (current instanceof z24.ZodString) {
|
|
12620
12661
|
return { ...base, type: "string" };
|
|
12621
12662
|
}
|
|
12622
|
-
if (current instanceof
|
|
12663
|
+
if (current instanceof z24.ZodNumber) {
|
|
12623
12664
|
return { ...base, type: "number" };
|
|
12624
12665
|
}
|
|
12625
|
-
if (current instanceof
|
|
12666
|
+
if (current instanceof z24.ZodBoolean) {
|
|
12626
12667
|
return { ...base, type: "boolean" };
|
|
12627
12668
|
}
|
|
12628
|
-
if (current instanceof
|
|
12669
|
+
if (current instanceof z24.ZodEnum) {
|
|
12629
12670
|
return {
|
|
12630
12671
|
...base,
|
|
12631
12672
|
type: "string",
|
|
12632
12673
|
enum: current.options
|
|
12633
12674
|
};
|
|
12634
12675
|
}
|
|
12635
|
-
if (current instanceof
|
|
12676
|
+
if (current instanceof z24.ZodArray) {
|
|
12636
12677
|
return {
|
|
12637
12678
|
...base,
|
|
12638
12679
|
type: "array",
|
|
12639
12680
|
items: zodTypeToJsonSchema(current.element)
|
|
12640
12681
|
};
|
|
12641
12682
|
}
|
|
12642
|
-
if (current instanceof
|
|
12683
|
+
if (current instanceof z24.ZodObject) {
|
|
12643
12684
|
return {
|
|
12644
12685
|
...base,
|
|
12645
12686
|
...zodShapeToJsonSchema(current.shape)
|
|
12646
12687
|
};
|
|
12647
12688
|
}
|
|
12648
|
-
if (current instanceof
|
|
12689
|
+
if (current instanceof z24.ZodRecord) {
|
|
12649
12690
|
const valueType = current._def.valueType;
|
|
12650
12691
|
return {
|
|
12651
12692
|
...base,
|
|
@@ -12774,7 +12815,7 @@ var VectrosMCPServer = class {
|
|
|
12774
12815
|
if (!tool) {
|
|
12775
12816
|
result = toolError(req.params.name ?? "unknown", new Error("No such tool."));
|
|
12776
12817
|
} else {
|
|
12777
|
-
const parsed =
|
|
12818
|
+
const parsed = z25.object(tool.inputSchema).strict().safeParse(req.params.arguments ?? {});
|
|
12778
12819
|
if (!parsed.success) {
|
|
12779
12820
|
result = toolError(tool.name, new Error(formatArgError(tool, parsed.error)));
|
|
12780
12821
|
} else {
|