@vectros-ai/mcp-server 0.17.1 → 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/CHANGELOG.md +37 -0
- package/README.md +37 -20
- package/dist/cli-http.js +275 -168
- package/dist/cli-http.js.map +1 -1
- package/dist/cli-http.mjs +275 -168
- package/dist/cli-http.mjs.map +1 -1
- package/dist/cli.js +275 -168
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +275 -168
- package/dist/cli.mjs.map +1 -1
- package/dist/index.js +275 -168
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +275 -168
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -62,6 +62,7 @@ __export2(api_exports, {
|
|
|
62
62
|
ContentTooLargeError: () => ContentTooLargeError,
|
|
63
63
|
DocumentContextEvent: () => DocumentContextEvent,
|
|
64
64
|
DocumentLookupRequest: () => DocumentLookupRequest,
|
|
65
|
+
DocumentPatchRequest: () => DocumentPatchRequest,
|
|
65
66
|
DocumentRequest: () => DocumentRequest,
|
|
66
67
|
DocumentResponse: () => DocumentResponse,
|
|
67
68
|
DoneEvent: () => DoneEvent,
|
|
@@ -405,6 +406,13 @@ var DocumentLookupRequest;
|
|
|
405
406
|
Desc: "desc"
|
|
406
407
|
};
|
|
407
408
|
})(DocumentLookupRequest || (DocumentLookupRequest = {}));
|
|
409
|
+
var DocumentPatchRequest;
|
|
410
|
+
((DocumentPatchRequest2) => {
|
|
411
|
+
DocumentPatchRequest2.Status = {
|
|
412
|
+
Active: "ACTIVE",
|
|
413
|
+
Archived: "ARCHIVED"
|
|
414
|
+
};
|
|
415
|
+
})(DocumentPatchRequest || (DocumentPatchRequest = {}));
|
|
408
416
|
var FileUploadRequest;
|
|
409
417
|
((FileUploadRequest2) => {
|
|
410
418
|
FileUploadRequest2.IndexMode = {
|
|
@@ -417,6 +425,7 @@ var FileUploadRequest;
|
|
|
417
425
|
var documents_exports = {};
|
|
418
426
|
__export2(documents_exports, {
|
|
419
427
|
DocumentLookupRequest: () => DocumentLookupRequest,
|
|
428
|
+
DocumentPatchRequest: () => DocumentPatchRequest,
|
|
420
429
|
FileUploadRequest: () => FileUploadRequest,
|
|
421
430
|
LookupDocumentsRequestOrder: () => LookupDocumentsRequestOrder
|
|
422
431
|
});
|
|
@@ -3081,6 +3090,7 @@ var AuthClient = class {
|
|
|
3081
3090
|
* @param {AuthClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
3082
3091
|
*
|
|
3083
3092
|
* @throws {@link Vectros.BadRequestError}
|
|
3093
|
+
* @throws {@link Vectros.PaymentRequiredError}
|
|
3084
3094
|
* @throws {@link Vectros.ForbiddenError}
|
|
3085
3095
|
* @throws {@link Vectros.TooManyRequestsError}
|
|
3086
3096
|
*
|
|
@@ -3130,6 +3140,8 @@ var AuthClient = class {
|
|
|
3130
3140
|
switch (_response.error.statusCode) {
|
|
3131
3141
|
case 400:
|
|
3132
3142
|
throw new BadRequestError(_response.error.body, _response.rawResponse);
|
|
3143
|
+
case 402:
|
|
3144
|
+
throw new PaymentRequiredError(_response.error.body, _response.rawResponse);
|
|
3133
3145
|
case 403:
|
|
3134
3146
|
throw new ForbiddenError(_response.error.body, _response.rawResponse);
|
|
3135
3147
|
case 429:
|
|
@@ -3562,7 +3574,7 @@ var AuthClient = class {
|
|
|
3562
3574
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/app-contexts/{contextId}");
|
|
3563
3575
|
}
|
|
3564
3576
|
/**
|
|
3565
|
-
* Updates
|
|
3577
|
+
* Updates an app context. This is a partial update: any field you omit (or send as null) keeps its existing value. The `contextId` is immutable and is taken from the URL path, so any `contextId` in the request body is ignored. Patchable fields: `name`, `description`, `companyName`; the per-principal metering trio (`meteringAxis`, `principalBurstLimit`, `principalUsageCap` — only takes effect for a partner with the corresponding account-level feature enabled); `readAccessLogDefault` (the PHI read-access-logging context default); and `identityProjectionClaims` (requires the platform provisioning capability on top of the ordinary scope below — see its own field description). Requires the `app-contexts:u` scope.
|
|
3566
3578
|
*
|
|
3567
3579
|
* @param {Vectros.UpdateAppContextRequest} request
|
|
3568
3580
|
* @param {AuthClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -4165,7 +4177,7 @@ var AuthClient = class {
|
|
|
4165
4177
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/auth/issuers/{issuerId}");
|
|
4166
4178
|
}
|
|
4167
4179
|
/**
|
|
4168
|
-
* 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 back to domain-less; see `IssuerUpdateRequest.restrictedToDomain` for the full semantics), `status` (`active`/`suspended` — 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.
|
|
4180
|
+
* 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 back to domain-less; 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.
|
|
4169
4181
|
*
|
|
4170
4182
|
* @param {Vectros.IssuerUpdateRequest} request
|
|
4171
4183
|
* @param {AuthClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -4358,7 +4370,7 @@ var AuthClient = class {
|
|
|
4358
4370
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/auth/issuers");
|
|
4359
4371
|
}
|
|
4360
4372
|
/**
|
|
4361
|
-
* Registers a trusted third-party IdP issuer that BYO-IdP token exchange (`POST /v1/auth/token/exchange`) may accept a `subject_token` from. Requires a root API key or the CLI bootstrap's provisioning capability — never an ordinary partner-grantable scope. A credential authorized only via the provisioning capability may register only against the app context it is bound to; naming a different one returns 403. A root API key is unaffected and may register against any of its contexts.
|
|
4373
|
+
* Registers a trusted third-party IdP issuer that BYO-IdP token exchange (`POST /v1/auth/token/exchange`) may accept a `subject_token` from. Requires a root API key or the CLI bootstrap's provisioning capability — never an ordinary partner-grantable scope. A credential authorized only via the provisioning capability may register only against the app context it is bound to; naming a different one returns 403. A root API key is unaffected and may register against any of its contexts. A registration without `restrictedToDomain` is created `pending_verification` with a one-time challenge (`verificationClaim`, `verificationNonce`, `verificationExpiresAt`) and accepts no token until you prove you control the issuer with `POST /v1/auth/issuers/{issuerId}/verify`; it claims no `(issuer, audience)` pair until then, so registering never reveals whether another tenant holds one. A registration scoped to an already-verified domain with `restrictedToDomain` is `active` at once. Idempotent by `issuerId` within your tenant. If `issuerId` collides with a registration owned by a different app context than the one you're confined to, the request fails with 400 rather than returning that context's configuration. An app context may have at most one active issuer — deregister the existing one first if you need to replace it. One issuer MAY serve several contexts today, each via its own registration row with a distinct `audience`. Optionally name `restrictedToDomain` to scope this registration's (issuer, audience) uniqueness to a specific VERIFIED domain rather than the bare pair — see that field's own description. A domain-scoped registration proves control of the DOMAIN, not of the issuer itself: it routes only tokens carrying that domain's `hd` claim.
|
|
4362
4374
|
*
|
|
4363
4375
|
* @param {Vectros.IssuerRequest} request
|
|
4364
4376
|
* @param {AuthClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -4424,6 +4436,82 @@ var AuthClient = class {
|
|
|
4424
4436
|
}
|
|
4425
4437
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "POST", "/v1/auth/issuers");
|
|
4426
4438
|
}
|
|
4439
|
+
/**
|
|
4440
|
+
* Proves you administer the IdP application a `pending_verification` registration names, activating it. A registration created without `restrictedToDomain` accepts no tokens until this succeeds. Configure your IdP, with an admin-controlled rule (an Auth0 Action, an Okta inline hook, an Entra claims-mapping policy, a Keycloak protocol mapper), to add the registration's `verificationClaim` to the tokens it issues, set to its `verificationNonce`; sign in once; and send that token here. The `jwksUri` you registered must be exactly the `jwks_uri` your issuer's OpenID Connect discovery document (`<issuer>/.well-known/openid-configuration`) publishes, and the token must verify against that key set — an issuer that publishes no discovery document cannot be verified this way. The token is checked and discarded; it is never stored. The `(issuer, audience)` pair is claimed at this moment, so a pair another registration already holds is refused with 400. A challenge expires 7 days after registration; an expired registration cannot be verified — delete it and register again. 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 verify an issuer registered in that context; naming one registered in another context returns 404, identically to a nonexistent issuerId.
|
|
4441
|
+
*
|
|
4442
|
+
* @param {Vectros.IssuerVerifyRequest} request
|
|
4443
|
+
* @param {AuthClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
4444
|
+
*
|
|
4445
|
+
* @throws {@link Vectros.BadRequestError}
|
|
4446
|
+
* @throws {@link Vectros.ForbiddenError}
|
|
4447
|
+
* @throws {@link Vectros.NotFoundError}
|
|
4448
|
+
* @throws {@link Vectros.ConflictError}
|
|
4449
|
+
* @throws {@link Vectros.TooManyRequestsError}
|
|
4450
|
+
*
|
|
4451
|
+
* @example
|
|
4452
|
+
* await client.auth.verifyIssuer({
|
|
4453
|
+
* issuerId: "auth0-prod",
|
|
4454
|
+
* token: "token"
|
|
4455
|
+
* })
|
|
4456
|
+
*/
|
|
4457
|
+
verifyIssuer(request, requestOptions) {
|
|
4458
|
+
return HttpResponsePromise.fromPromise(this.__verifyIssuer(request, requestOptions));
|
|
4459
|
+
}
|
|
4460
|
+
async __verifyIssuer(request, requestOptions) {
|
|
4461
|
+
const { issuerId, ..._body } = request;
|
|
4462
|
+
const _authRequest = await this._options.authProvider.getAuthRequest();
|
|
4463
|
+
const _headers = mergeHeaders(
|
|
4464
|
+
_authRequest.headers,
|
|
4465
|
+
this._options?.headers,
|
|
4466
|
+
requestOptions?.headers
|
|
4467
|
+
);
|
|
4468
|
+
const _response = await fetcher({
|
|
4469
|
+
url: url_exports.join(
|
|
4470
|
+
await Supplier.get(this._options.baseUrl) ?? await Supplier.get(this._options.environment),
|
|
4471
|
+
`v1/auth/issuers/${url_exports.encodePathParam(issuerId)}/verify`
|
|
4472
|
+
),
|
|
4473
|
+
method: "POST",
|
|
4474
|
+
headers: _headers,
|
|
4475
|
+
contentType: "application/json",
|
|
4476
|
+
queryString: url_exports.queryBuilder().mergeAdditional(requestOptions?.queryParams).build(),
|
|
4477
|
+
requestType: "json",
|
|
4478
|
+
body: _body,
|
|
4479
|
+
timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1e3,
|
|
4480
|
+
maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
|
|
4481
|
+
abortSignal: requestOptions?.abortSignal,
|
|
4482
|
+
fetchFn: this._options?.fetch,
|
|
4483
|
+
logging: this._options.logging
|
|
4484
|
+
});
|
|
4485
|
+
if (_response.ok) {
|
|
4486
|
+
return { data: _response.body, rawResponse: _response.rawResponse };
|
|
4487
|
+
}
|
|
4488
|
+
if (_response.error.reason === "status-code") {
|
|
4489
|
+
switch (_response.error.statusCode) {
|
|
4490
|
+
case 400:
|
|
4491
|
+
throw new BadRequestError(_response.error.body, _response.rawResponse);
|
|
4492
|
+
case 403:
|
|
4493
|
+
throw new ForbiddenError(_response.error.body, _response.rawResponse);
|
|
4494
|
+
case 404:
|
|
4495
|
+
throw new NotFoundError(_response.error.body, _response.rawResponse);
|
|
4496
|
+
case 409:
|
|
4497
|
+
throw new ConflictError(_response.error.body, _response.rawResponse);
|
|
4498
|
+
case 429:
|
|
4499
|
+
throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
|
|
4500
|
+
default:
|
|
4501
|
+
throw new VectrosError({
|
|
4502
|
+
statusCode: _response.error.statusCode,
|
|
4503
|
+
body: _response.error.body,
|
|
4504
|
+
rawResponse: _response.rawResponse
|
|
4505
|
+
});
|
|
4506
|
+
}
|
|
4507
|
+
}
|
|
4508
|
+
return handleNonStatusCodeError(
|
|
4509
|
+
_response.error,
|
|
4510
|
+
_response.rawResponse,
|
|
4511
|
+
"POST",
|
|
4512
|
+
"/v1/auth/issuers/{issuerId}/verify"
|
|
4513
|
+
);
|
|
4514
|
+
}
|
|
4427
4515
|
/**
|
|
4428
4516
|
* Returns the identity bound to your credential — your account, principal type, key id, and scope details — so you can confirm who you are authenticated as and that the credential is valid. MCP clients use this to render "signed in as ..." in a chat UI without a separate identity endpoint.
|
|
4429
4517
|
*
|
|
@@ -4899,7 +4987,7 @@ var ComplianceClient = class {
|
|
|
4899
4987
|
this._options = normalizeClientOptionsWithAuth(options);
|
|
4900
4988
|
}
|
|
4901
4989
|
/**
|
|
4902
|
-
* 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
|
|
4990
|
+
* 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.
|
|
4903
4991
|
*
|
|
4904
4992
|
* @param {Vectros.ErasureRequest} request
|
|
4905
4993
|
* @param {ComplianceClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -4962,7 +5050,7 @@ var ComplianceClient = class {
|
|
|
4962
5050
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "POST", "/v1/erasure-requests");
|
|
4963
5051
|
}
|
|
4964
5052
|
/**
|
|
4965
|
-
* 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
|
|
5053
|
+
* 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.
|
|
4966
5054
|
*
|
|
4967
5055
|
* @param {Vectros.GetErasureRequestRequest} request
|
|
4968
5056
|
* @param {ComplianceClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -5205,7 +5293,7 @@ var DocumentsClient = class {
|
|
|
5205
5293
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/documents");
|
|
5206
5294
|
}
|
|
5207
5295
|
/**
|
|
5208
|
-
* 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.
|
|
5296
|
+
* 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.
|
|
5209
5297
|
*
|
|
5210
5298
|
* @param {Vectros.IngestDocumentRequest} request
|
|
5211
5299
|
* @param {DocumentsClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -5225,10 +5313,11 @@ var DocumentsClient = class {
|
|
|
5225
5313
|
return HttpResponsePromise.fromPromise(this.__ingestDocument(request, requestOptions));
|
|
5226
5314
|
}
|
|
5227
5315
|
async __ingestDocument(request, requestOptions) {
|
|
5228
|
-
const { upsert, allowClear, body: _body } = request;
|
|
5316
|
+
const { upsert, allowClear, confirmUntyped, body: _body } = request;
|
|
5229
5317
|
const _queryParams = {
|
|
5230
5318
|
upsert,
|
|
5231
|
-
allowClear
|
|
5319
|
+
allowClear,
|
|
5320
|
+
confirmUntyped
|
|
5232
5321
|
};
|
|
5233
5322
|
const _authRequest = await this._options.authProvider.getAuthRequest();
|
|
5234
5323
|
const _headers = mergeHeaders(
|
|
@@ -5463,7 +5552,7 @@ var DocumentsClient = class {
|
|
|
5463
5552
|
/**
|
|
5464
5553
|
* 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.
|
|
5465
5554
|
*
|
|
5466
|
-
* @param {Vectros.
|
|
5555
|
+
* @param {Vectros.DocumentPatchRequest} request
|
|
5467
5556
|
* @param {DocumentsClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
5468
5557
|
*
|
|
5469
5558
|
* @throws {@link Vectros.BadRequestError}
|
|
@@ -5474,17 +5563,14 @@ var DocumentsClient = class {
|
|
|
5474
5563
|
*
|
|
5475
5564
|
* @example
|
|
5476
5565
|
* await client.documents.patchDocument({
|
|
5477
|
-
* id: "id"
|
|
5478
|
-
* body: {
|
|
5479
|
-
* title: "Patient Intake Form \u2014 Jane Doe"
|
|
5480
|
-
* }
|
|
5566
|
+
* id: "id"
|
|
5481
5567
|
* })
|
|
5482
5568
|
*/
|
|
5483
5569
|
patchDocument(request, requestOptions) {
|
|
5484
5570
|
return HttpResponsePromise.fromPromise(this.__patchDocument(request, requestOptions));
|
|
5485
5571
|
}
|
|
5486
5572
|
async __patchDocument(request, requestOptions) {
|
|
5487
|
-
const { id,
|
|
5573
|
+
const { id, ..._body } = request;
|
|
5488
5574
|
const _authRequest = await this._options.authProvider.getAuthRequest();
|
|
5489
5575
|
const _headers = mergeHeaders(
|
|
5490
5576
|
_authRequest.headers,
|
|
@@ -5856,7 +5942,7 @@ var DocumentsClient = class {
|
|
|
5856
5942
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/documents/{id}/versions");
|
|
5857
5943
|
}
|
|
5858
5944
|
/**
|
|
5859
|
-
* 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.
|
|
5945
|
+
* 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.
|
|
5860
5946
|
*
|
|
5861
5947
|
* @param {Vectros.FileUploadRequest} request
|
|
5862
5948
|
* @param {DocumentsClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -5875,9 +5961,10 @@ var DocumentsClient = class {
|
|
|
5875
5961
|
return HttpResponsePromise.fromPromise(this.__uploadDocument(request, requestOptions));
|
|
5876
5962
|
}
|
|
5877
5963
|
async __uploadDocument(request, requestOptions) {
|
|
5878
|
-
const { upsert, ..._body } = request;
|
|
5964
|
+
const { upsert, confirmUntyped, ..._body } = request;
|
|
5879
5965
|
const _queryParams = {
|
|
5880
|
-
upsert
|
|
5966
|
+
upsert,
|
|
5967
|
+
confirmUntyped
|
|
5881
5968
|
};
|
|
5882
5969
|
const _authRequest = await this._options.authProvider.getAuthRequest();
|
|
5883
5970
|
const _headers = mergeHeaders(
|
|
@@ -10173,7 +10260,7 @@ var logging;
|
|
|
10173
10260
|
|
|
10174
10261
|
// src/server.ts
|
|
10175
10262
|
var import_types3 = require("@modelcontextprotocol/sdk/types.js");
|
|
10176
|
-
var
|
|
10263
|
+
var import_zod25 = require("zod");
|
|
10177
10264
|
|
|
10178
10265
|
// src/auth.ts
|
|
10179
10266
|
var KEY_RE = /^(sk|ssk|st)_(live|test)_/;
|
|
@@ -10217,8 +10304,8 @@ function warnOnSuboptimalKey(key, log) {
|
|
|
10217
10304
|
|
|
10218
10305
|
// src/build-info.ts
|
|
10219
10306
|
var BUILD_INFO = {
|
|
10220
|
-
mcpServer: true ? "0.
|
|
10221
|
-
sdk: true ? "0.
|
|
10307
|
+
mcpServer: true ? "0.18.0" : "dev",
|
|
10308
|
+
sdk: true ? "0.46.0" : "dev"
|
|
10222
10309
|
};
|
|
10223
10310
|
|
|
10224
10311
|
// src/log.ts
|
|
@@ -10510,7 +10597,7 @@ var inputSchema = {
|
|
|
10510
10597
|
"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.)"
|
|
10511
10598
|
),
|
|
10512
10599
|
limit: import_zod.z.number().int().min(1).max(MCP_MAX_LIMIT).optional().describe(
|
|
10513
|
-
`Max hits per page. Defaults to a low ${MCP_DEFAULT_LIMIT} to protect the agent context window; raise up to ${MCP_MAX_LIMIT} (
|
|
10600
|
+
`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.`
|
|
10514
10601
|
),
|
|
10515
10602
|
offset: import_zod.z.number().int().min(0).max(200).optional().describe("Skip the first N hits \u2014 for pagination (0\u2013200)."),
|
|
10516
10603
|
folderId: import_zod.z.string().optional().describe("Scope to content in this EXACT folder (Vectros folder id)."),
|
|
@@ -11259,52 +11346,61 @@ var recordDelete = ({ client, log }) => ({
|
|
|
11259
11346
|
var record_delete_default = recordDelete;
|
|
11260
11347
|
|
|
11261
11348
|
// src/tools/rag_ask.ts
|
|
11349
|
+
var import_zod10 = require("zod");
|
|
11350
|
+
|
|
11351
|
+
// src/tools/provider-alias.ts
|
|
11262
11352
|
var import_zod9 = require("zod");
|
|
11353
|
+
var providerAliasInput = import_zod9.z.string().min(1, "providerAlias must be non-empty when supplied").optional().describe(
|
|
11354
|
+
"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."
|
|
11355
|
+
);
|
|
11356
|
+
|
|
11357
|
+
// src/tools/rag_ask.ts
|
|
11263
11358
|
var SEARCH_MCP_DEFAULT_LIMIT = 5;
|
|
11264
11359
|
var SEARCH_MCP_MAX_LIMIT = 50;
|
|
11265
11360
|
var inputSchema9 = {
|
|
11266
|
-
query:
|
|
11267
|
-
instructions:
|
|
11361
|
+
query: import_zod10.z.string().min(1, "query must be non-empty").describe("Question to ground against retrieved content."),
|
|
11362
|
+
instructions: import_zod10.z.string().optional().describe(
|
|
11268
11363
|
'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.'
|
|
11269
11364
|
),
|
|
11270
|
-
model:
|
|
11271
|
-
"Inference model alias (e.g. claude-haiku-4-5, claude-sonnet-5, claude-opus-
|
|
11365
|
+
model: import_zod10.z.string().optional().describe(
|
|
11366
|
+
"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."
|
|
11272
11367
|
),
|
|
11273
|
-
|
|
11274
|
-
|
|
11275
|
-
|
|
11276
|
-
|
|
11368
|
+
providerAlias: providerAliasInput,
|
|
11369
|
+
search: import_zod10.z.object({
|
|
11370
|
+
mode: import_zod10.z.enum(["HYBRID", "TEXT", "SEMANTIC"]).optional().describe("Retrieval mode. Default HYBRID."),
|
|
11371
|
+
limit: import_zod10.z.number().int().min(1).max(SEARCH_MCP_MAX_LIMIT).optional().describe(
|
|
11372
|
+
`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.`
|
|
11277
11373
|
),
|
|
11278
11374
|
// Retrieval scoping — parity with hybrid_search so an agent can ground the
|
|
11279
11375
|
// answer on a specific owner / folder / type / metadata subset, not just the
|
|
11280
11376
|
// whole-tenant corpus.
|
|
11281
|
-
userId:
|
|
11282
|
-
scope:
|
|
11377
|
+
userId: import_zod10.z.string().optional().describe("Restrict retrieval to content owned by this user (Vectros UUID)."),
|
|
11378
|
+
scope: import_zod10.z.string().optional().describe(
|
|
11283
11379
|
'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.'
|
|
11284
11380
|
),
|
|
11285
|
-
scopeFilters:
|
|
11381
|
+
scopeFilters: import_zod10.z.array(import_zod10.z.string()).min(1, "scopeFilters must name at least one dimension when supplied").optional().describe(
|
|
11286
11382
|
'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`.'
|
|
11287
11383
|
),
|
|
11288
|
-
folderId:
|
|
11289
|
-
rootFolderId:
|
|
11290
|
-
typeName:
|
|
11291
|
-
contentTypes:
|
|
11292
|
-
filters:
|
|
11384
|
+
folderId: import_zod10.z.string().optional().describe("Restrict retrieval to this exact folder."),
|
|
11385
|
+
rootFolderId: import_zod10.z.string().optional().describe("Restrict retrieval to this folder and all its descendants."),
|
|
11386
|
+
typeName: import_zod10.z.string().optional().describe("Restrict record retrieval to this schema type."),
|
|
11387
|
+
contentTypes: import_zod10.z.array(import_zod10.z.enum(["documents", "records"])).optional().describe('Narrow retrieval to content types. ["documents"] or ["records"]; omit for both.'),
|
|
11388
|
+
filters: import_zod10.z.record(import_zod10.z.unknown()).optional().describe(
|
|
11293
11389
|
'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"}.'
|
|
11294
11390
|
),
|
|
11295
|
-
createdAfter:
|
|
11391
|
+
createdAfter: import_zod10.z.string().optional().describe(
|
|
11296
11392
|
"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."
|
|
11297
11393
|
),
|
|
11298
|
-
createdBefore:
|
|
11299
|
-
requireComplete:
|
|
11394
|
+
createdBefore: import_zod10.z.string().optional().describe("Same creation-time basis as createdAfter, bounding at/before this ISO 8601 UTC value."),
|
|
11395
|
+
requireComplete: import_zod10.z.boolean().optional().describe("Fail closed (503) on a degraded search backend instead of grounding on partial results. Default false.")
|
|
11300
11396
|
}).optional().describe("Retrieval params + scoping. Default mode HYBRID, limit " + SEARCH_MCP_DEFAULT_LIMIT + "."),
|
|
11301
|
-
maxTokens:
|
|
11302
|
-
temperature:
|
|
11397
|
+
maxTokens: import_zod10.z.number().int().min(1).optional().describe("Max output tokens."),
|
|
11398
|
+
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.")
|
|
11303
11399
|
};
|
|
11304
11400
|
var ragAsk = ({ client, log }) => ({
|
|
11305
11401
|
name: "rag_ask",
|
|
11306
11402
|
title: "RAG ask (corpus-wide)",
|
|
11307
|
-
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.
|
|
11403
|
+
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.",
|
|
11308
11404
|
inputSchema: inputSchema9,
|
|
11309
11405
|
// NOT a pure read: this call reserves an atomic hold against the caller's prepaid inference
|
|
11310
11406
|
// balance before generation starts, then debits it on completion — a real financial side
|
|
@@ -11346,6 +11442,7 @@ var ragAsk = ({ client, log }) => ({
|
|
|
11346
11442
|
query: args.query,
|
|
11347
11443
|
instructions: args.instructions,
|
|
11348
11444
|
model: args.model,
|
|
11445
|
+
providerAlias: args.providerAlias,
|
|
11349
11446
|
search,
|
|
11350
11447
|
maxTokens: args.maxTokens,
|
|
11351
11448
|
temperature: args.temperature
|
|
@@ -11400,19 +11497,20 @@ var ragAsk = ({ client, log }) => ({
|
|
|
11400
11497
|
var rag_ask_default = ragAsk;
|
|
11401
11498
|
|
|
11402
11499
|
// src/tools/document_ask.ts
|
|
11403
|
-
var
|
|
11500
|
+
var import_zod11 = require("zod");
|
|
11404
11501
|
var inputSchema10 = {
|
|
11405
|
-
documentId:
|
|
11406
|
-
prompt:
|
|
11407
|
-
model:
|
|
11408
|
-
"Inference model alias. Default = tier-appropriate Haiku. See GET /v1/models for the catalog the calling key can reach."
|
|
11502
|
+
documentId: import_zod11.z.string().min(1, "documentId is required").describe("ID of the document to ask against."),
|
|
11503
|
+
prompt: import_zod11.z.string().min(1, "prompt is required").describe("Question to ask about the document."),
|
|
11504
|
+
model: import_zod11.z.string().optional().describe(
|
|
11505
|
+
"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."
|
|
11409
11506
|
),
|
|
11410
|
-
|
|
11507
|
+
providerAlias: providerAliasInput,
|
|
11508
|
+
maxTokens: import_zod11.z.number().int().min(1).optional().describe("Max output tokens.")
|
|
11411
11509
|
};
|
|
11412
11510
|
var documentAsk = ({ client, log }) => ({
|
|
11413
11511
|
name: "document_ask",
|
|
11414
11512
|
title: "Document ask (single-document)",
|
|
11415
|
-
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`.
|
|
11513
|
+
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.",
|
|
11416
11514
|
inputSchema: inputSchema10,
|
|
11417
11515
|
// NOT a pure read: this call reserves an atomic hold against the caller's prepaid inference
|
|
11418
11516
|
// balance before generation starts, then debits it on completion — a real financial side
|
|
@@ -11429,6 +11527,7 @@ var documentAsk = ({ client, log }) => ({
|
|
|
11429
11527
|
id: args.documentId,
|
|
11430
11528
|
prompt: args.prompt,
|
|
11431
11529
|
model: args.model,
|
|
11530
|
+
providerAlias: args.providerAlias,
|
|
11432
11531
|
maxTokens: args.maxTokens
|
|
11433
11532
|
});
|
|
11434
11533
|
const progressToken = extra._meta?.progressToken;
|
|
@@ -11481,18 +11580,18 @@ var documentAsk = ({ client, log }) => ({
|
|
|
11481
11580
|
var document_ask_default = documentAsk;
|
|
11482
11581
|
|
|
11483
11582
|
// src/tools/list_schemas.ts
|
|
11484
|
-
var
|
|
11583
|
+
var import_zod12 = require("zod");
|
|
11485
11584
|
var inputSchema11 = {
|
|
11486
|
-
userId:
|
|
11585
|
+
userId: import_zod12.z.string().optional().describe(
|
|
11487
11586
|
"Filter to schemas visible to a specific user. Optional; default returns all schemas the credential can see."
|
|
11488
11587
|
),
|
|
11489
|
-
scope:
|
|
11588
|
+
scope: import_zod12.z.string().optional().describe(
|
|
11490
11589
|
'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.'
|
|
11491
11590
|
),
|
|
11492
|
-
surface:
|
|
11591
|
+
surface: import_zod12.z.enum(["record", "document", "user", "entity"]).optional().describe(
|
|
11493
11592
|
"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."
|
|
11494
11593
|
),
|
|
11495
|
-
recordType:
|
|
11594
|
+
recordType: import_zod12.z.string().optional().describe(
|
|
11496
11595
|
'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.'
|
|
11497
11596
|
)
|
|
11498
11597
|
};
|
|
@@ -11528,19 +11627,19 @@ var listSchemas = ({ client, log }) => ({
|
|
|
11528
11627
|
var list_schemas_default = listSchemas;
|
|
11529
11628
|
|
|
11530
11629
|
// src/tools/document_get.ts
|
|
11531
|
-
var
|
|
11630
|
+
var import_zod13 = require("zod");
|
|
11532
11631
|
var MAX_TEXT_CHARS = 32e3;
|
|
11533
11632
|
var inputSchema12 = {
|
|
11534
|
-
documentId:
|
|
11535
|
-
externalId:
|
|
11633
|
+
documentId: import_zod13.z.string().optional().describe("The document ID returned by document_ingest or hybrid_search. Provide this OR externalId+type."),
|
|
11634
|
+
externalId: import_zod13.z.string().optional().describe(
|
|
11536
11635
|
"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."
|
|
11537
11636
|
),
|
|
11538
|
-
type:
|
|
11539
|
-
includeText:
|
|
11637
|
+
type: import_zod13.z.string().optional().describe("Document type \u2014 REQUIRED when selecting by `externalId` (externalId is unique within a type)."),
|
|
11638
|
+
includeText: import_zod13.z.boolean().optional().describe(
|
|
11540
11639
|
"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."
|
|
11541
11640
|
),
|
|
11542
|
-
includeDownloadUrl:
|
|
11543
|
-
"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."
|
|
11641
|
+
includeDownloadUrl: import_zod13.z.boolean().optional().describe(
|
|
11642
|
+
"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."
|
|
11544
11643
|
)
|
|
11545
11644
|
};
|
|
11546
11645
|
function truncateText(text) {
|
|
@@ -11623,28 +11722,28 @@ var documentGet = ({ client, log }) => ({
|
|
|
11623
11722
|
var document_get_default = documentGet;
|
|
11624
11723
|
|
|
11625
11724
|
// src/tools/document_query.ts
|
|
11626
|
-
var
|
|
11725
|
+
var import_zod14 = require("zod");
|
|
11627
11726
|
var MCP_DEFAULT_LIMIT3 = 3;
|
|
11628
11727
|
var MCP_MAX_LIMIT3 = 100;
|
|
11629
11728
|
var inputSchema13 = {
|
|
11630
11729
|
// Lookup-mode args — provide `field` plus EXACTLY ONE of: value | from+to | prefix.
|
|
11631
|
-
field:
|
|
11632
|
-
value:
|
|
11633
|
-
from:
|
|
11634
|
-
to:
|
|
11635
|
-
prefix:
|
|
11636
|
-
order:
|
|
11730
|
+
field: import_zod14.z.string().optional().describe("Lookup mode: name of the lookup-indexed field to query by."),
|
|
11731
|
+
value: import_zod14.z.string().optional().describe("Lookup mode (equality): exact-match value for `field`. Works on sensitive fields too."),
|
|
11732
|
+
from: import_zod14.z.string().optional().describe("Lookup mode (range): inclusive lower bound; requires `to`. Range-enabled, non-sensitive fields only."),
|
|
11733
|
+
to: import_zod14.z.string().optional().describe("Lookup mode (range): inclusive upper bound; requires `from`."),
|
|
11734
|
+
prefix: import_zod14.z.string().optional().describe("Lookup mode (prefix): match values starting with this. Range-enabled string fields only."),
|
|
11735
|
+
order: import_zod14.z.enum(["asc", "desc"]).optional().describe(
|
|
11637
11736
|
"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."
|
|
11638
11737
|
),
|
|
11639
|
-
type:
|
|
11738
|
+
type: import_zod14.z.string().optional().describe("Lookup mode: the document type (the bound schema's type). Required with `field`."),
|
|
11640
11739
|
// List-mode args:
|
|
11641
|
-
folderId:
|
|
11642
|
-
userId:
|
|
11643
|
-
scope:
|
|
11740
|
+
folderId: import_zod14.z.string().optional().describe("List mode: only documents in this folder (Vectros folder id)."),
|
|
11741
|
+
userId: import_zod14.z.string().optional().describe("List mode: scope to documents owned by this user."),
|
|
11742
|
+
scope: import_zod14.z.string().optional().describe(
|
|
11644
11743
|
'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.'
|
|
11645
11744
|
),
|
|
11646
|
-
startFrom:
|
|
11647
|
-
limit:
|
|
11745
|
+
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."),
|
|
11746
|
+
limit: import_zod14.z.number().int().min(1).max(MCP_MAX_LIMIT3).optional().describe(
|
|
11648
11747
|
`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.`
|
|
11649
11748
|
)
|
|
11650
11749
|
};
|
|
@@ -11734,29 +11833,29 @@ var documentQuery = ({ client, log }) => ({
|
|
|
11734
11833
|
var document_query_default = documentQuery;
|
|
11735
11834
|
|
|
11736
11835
|
// src/tools/document_update.ts
|
|
11737
|
-
var
|
|
11836
|
+
var import_zod15 = require("zod");
|
|
11738
11837
|
var inputSchema14 = {
|
|
11739
|
-
documentId:
|
|
11740
|
-
externalId:
|
|
11838
|
+
documentId: import_zod15.z.string().optional().describe("The Vectros document id to update. Provide this OR externalId+type."),
|
|
11839
|
+
externalId: import_zod15.z.string().optional().describe(
|
|
11741
11840
|
"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."
|
|
11742
11841
|
),
|
|
11743
|
-
type:
|
|
11744
|
-
title:
|
|
11745
|
-
fields:
|
|
11842
|
+
type: import_zod15.z.string().optional().describe("Document type \u2014 REQUIRED when selecting by `externalId` (externalId is unique within a type)."),
|
|
11843
|
+
title: import_zod15.z.string().optional().describe("New title. Omit to keep the current title."),
|
|
11844
|
+
fields: import_zod15.z.record(import_zod15.z.string(), import_zod15.z.unknown()).optional().describe(
|
|
11746
11845
|
"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."
|
|
11747
11846
|
),
|
|
11748
|
-
text:
|
|
11847
|
+
text: import_zod15.z.string().optional().describe(
|
|
11749
11848
|
"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."
|
|
11750
11849
|
),
|
|
11751
|
-
folderId:
|
|
11752
|
-
status:
|
|
11850
|
+
folderId: import_zod15.z.string().optional().describe("Move the document into this folder (cannot be cleared once set)."),
|
|
11851
|
+
status: import_zod15.z.enum(["ACTIVE", "ARCHIVED"]).optional().describe(
|
|
11753
11852
|
"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."
|
|
11754
11853
|
),
|
|
11755
|
-
userId:
|
|
11756
|
-
scopes:
|
|
11854
|
+
userId: import_zod15.z.string().optional().describe("Reassign the owning user (Vectros UUID)."),
|
|
11855
|
+
scopes: import_zod15.z.array(import_zod15.z.string()).optional().describe(
|
|
11757
11856
|
'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).'
|
|
11758
11857
|
),
|
|
11759
|
-
expectedVersion:
|
|
11858
|
+
expectedVersion: import_zod15.z.number().int().optional().describe(
|
|
11760
11859
|
"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."
|
|
11761
11860
|
)
|
|
11762
11861
|
};
|
|
@@ -11784,18 +11883,18 @@ var documentUpdate = ({ client, log }) => ({
|
|
|
11784
11883
|
try {
|
|
11785
11884
|
const resolved = await resolveDocumentIdByExternalId(client, { id: documentId, externalId, type });
|
|
11786
11885
|
if ("error" in resolved) return toolError("document_update", new Error(resolved.error));
|
|
11787
|
-
const
|
|
11788
|
-
if (title !== void 0)
|
|
11789
|
-
if (fields !== void 0)
|
|
11790
|
-
if (text !== void 0)
|
|
11791
|
-
if (folderId !== void 0)
|
|
11792
|
-
if (status !== void 0)
|
|
11793
|
-
if (userId !== void 0)
|
|
11794
|
-
if (scopes !== void 0)
|
|
11795
|
-
if (expectedVersion !== void 0)
|
|
11886
|
+
const patch = {};
|
|
11887
|
+
if (title !== void 0) patch.title = title;
|
|
11888
|
+
if (fields !== void 0) patch.payload = fields;
|
|
11889
|
+
if (text !== void 0) patch.text = text;
|
|
11890
|
+
if (folderId !== void 0) patch.folderId = folderId;
|
|
11891
|
+
if (status !== void 0) patch.status = status;
|
|
11892
|
+
if (userId !== void 0) patch.userId = userId;
|
|
11893
|
+
if (scopes !== void 0) patch.scopes = scopes;
|
|
11894
|
+
if (expectedVersion !== void 0) patch.expectedVersion = expectedVersion;
|
|
11796
11895
|
const updated = await client.documents.patchDocument({
|
|
11797
11896
|
id: resolved.id,
|
|
11798
|
-
|
|
11897
|
+
...patch
|
|
11799
11898
|
});
|
|
11800
11899
|
log.debug({ tool: "document_update", documentId: resolved.id, externalId }, "document_update ok");
|
|
11801
11900
|
return { content: [{ type: "text", text: JSON.stringify(updated, null, 2) }] };
|
|
@@ -11808,9 +11907,9 @@ var documentUpdate = ({ client, log }) => ({
|
|
|
11808
11907
|
var document_update_default = documentUpdate;
|
|
11809
11908
|
|
|
11810
11909
|
// src/tools/document_delete.ts
|
|
11811
|
-
var
|
|
11910
|
+
var import_zod16 = require("zod");
|
|
11812
11911
|
var inputSchema15 = {
|
|
11813
|
-
documentId:
|
|
11912
|
+
documentId: import_zod16.z.string().min(1, "documentId is required").describe("The Vectros document id to delete.")
|
|
11814
11913
|
};
|
|
11815
11914
|
var documentDelete = ({ client, log }) => ({
|
|
11816
11915
|
name: "document_delete",
|
|
@@ -11837,18 +11936,18 @@ var documentDelete = ({ client, log }) => ({
|
|
|
11837
11936
|
var document_delete_default = documentDelete;
|
|
11838
11937
|
|
|
11839
11938
|
// src/tools/folder_query.ts
|
|
11840
|
-
var
|
|
11939
|
+
var import_zod17 = require("zod");
|
|
11841
11940
|
var MCP_DEFAULT_LIMIT4 = 10;
|
|
11842
11941
|
var MCP_MAX_LIMIT4 = 100;
|
|
11843
11942
|
var inputSchema16 = {
|
|
11844
|
-
id:
|
|
11845
|
-
parentId:
|
|
11846
|
-
userId:
|
|
11847
|
-
scope:
|
|
11943
|
+
id: import_zod17.z.string().optional().describe("Get mode: fetch this single folder by id."),
|
|
11944
|
+
parentId: import_zod17.z.string().optional().describe("List mode: direct children of this folder (tree navigation). Omit for a flat tenant list."),
|
|
11945
|
+
userId: import_zod17.z.string().optional().describe("List mode: scope to folders owned by this user."),
|
|
11946
|
+
scope: import_zod17.z.string().optional().describe(
|
|
11848
11947
|
'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.'
|
|
11849
11948
|
),
|
|
11850
|
-
startFrom:
|
|
11851
|
-
limit:
|
|
11949
|
+
startFrom: import_zod17.z.string().optional().describe("List mode: pagination cursor \u2014 pass the `nextCursor` from the previous page to fetch the next."),
|
|
11950
|
+
limit: import_zod17.z.number().int().min(1).max(MCP_MAX_LIMIT4).optional().describe(
|
|
11852
11951
|
`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\`.`
|
|
11853
11952
|
)
|
|
11854
11953
|
};
|
|
@@ -11888,16 +11987,16 @@ var folderQuery = ({ client, log }) => ({
|
|
|
11888
11987
|
var folder_query_default = folderQuery;
|
|
11889
11988
|
|
|
11890
11989
|
// src/tools/folder_create.ts
|
|
11891
|
-
var
|
|
11990
|
+
var import_zod18 = require("zod");
|
|
11892
11991
|
var inputSchema17 = {
|
|
11893
|
-
name:
|
|
11894
|
-
description:
|
|
11895
|
-
parentId:
|
|
11896
|
-
slug:
|
|
11992
|
+
name: import_zod18.z.string().min(1, "name is required").describe("Folder display name."),
|
|
11993
|
+
description: import_zod18.z.string().optional().describe("Optional description of the folder's purpose."),
|
|
11994
|
+
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."),
|
|
11995
|
+
slug: import_zod18.z.string().optional().describe(
|
|
11897
11996
|
"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."
|
|
11898
11997
|
),
|
|
11899
|
-
userId:
|
|
11900
|
-
scopes:
|
|
11998
|
+
userId: import_zod18.z.string().optional().describe("Owning user (Vectros UUID)."),
|
|
11999
|
+
scopes: import_zod18.z.array(import_zod18.z.string()).optional().describe(
|
|
11901
12000
|
'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.'
|
|
11902
12001
|
)
|
|
11903
12002
|
};
|
|
@@ -11939,16 +12038,16 @@ var folderCreate = ({ client, log }) => ({
|
|
|
11939
12038
|
var folder_create_default = folderCreate;
|
|
11940
12039
|
|
|
11941
12040
|
// src/tools/folder_update.ts
|
|
11942
|
-
var
|
|
12041
|
+
var import_zod19 = require("zod");
|
|
11943
12042
|
var inputSchema18 = {
|
|
11944
|
-
id:
|
|
11945
|
-
name:
|
|
11946
|
-
description:
|
|
11947
|
-
userId:
|
|
11948
|
-
scopes:
|
|
12043
|
+
id: import_zod19.z.string().min(1, "id is required").describe("The Vectros folder id to update."),
|
|
12044
|
+
name: import_zod19.z.string().optional().describe("New folder name. Omit to keep the current name."),
|
|
12045
|
+
description: import_zod19.z.string().optional().describe("New description. Omit to leave unchanged."),
|
|
12046
|
+
userId: import_zod19.z.string().optional().describe("Reassign the owning user (Vectros UUID)."),
|
|
12047
|
+
scopes: import_zod19.z.array(import_zod19.z.string()).optional().describe(
|
|
11949
12048
|
'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).'
|
|
11950
12049
|
),
|
|
11951
|
-
expectedVersion:
|
|
12050
|
+
expectedVersion: import_zod19.z.number().int().optional().describe(
|
|
11952
12051
|
"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."
|
|
11953
12052
|
)
|
|
11954
12053
|
};
|
|
@@ -11987,9 +12086,9 @@ var folderUpdate = ({ client, log }) => ({
|
|
|
11987
12086
|
var folder_update_default = folderUpdate;
|
|
11988
12087
|
|
|
11989
12088
|
// src/tools/folder_delete.ts
|
|
11990
|
-
var
|
|
12089
|
+
var import_zod20 = require("zod");
|
|
11991
12090
|
var inputSchema19 = {
|
|
11992
|
-
id:
|
|
12091
|
+
id: import_zod20.z.string().min(1, "id is required").describe("The Vectros folder id to delete.")
|
|
11993
12092
|
};
|
|
11994
12093
|
var folderDelete = ({ client, log }) => ({
|
|
11995
12094
|
name: "folder_delete",
|
|
@@ -12039,7 +12138,7 @@ var currentIdentity = ({ log, apiKey, environment }) => ({
|
|
|
12039
12138
|
var current_identity_default = currentIdentity;
|
|
12040
12139
|
|
|
12041
12140
|
// src/tools/document_ingest.ts
|
|
12042
|
-
var
|
|
12141
|
+
var import_zod21 = require("zod");
|
|
12043
12142
|
var import_promises = require("fs/promises");
|
|
12044
12143
|
var import_node_path = require("path");
|
|
12045
12144
|
var IngestPathError = class extends Error {
|
|
@@ -12115,43 +12214,46 @@ function inferMimeType(filePath) {
|
|
|
12115
12214
|
return EXT_TO_MIME[ext] ?? "application/octet-stream";
|
|
12116
12215
|
}
|
|
12117
12216
|
var inputSchema21 = {
|
|
12118
|
-
title:
|
|
12119
|
-
indexMode:
|
|
12217
|
+
title: import_zod21.z.string().min(1, "title is required").describe("Human-readable document title \u2014 appears in search results and the UI."),
|
|
12218
|
+
indexMode: import_zod21.z.enum(["HYBRID", "SEMANTIC", "TEXT", "NONE"]).optional().describe(
|
|
12120
12219
|
"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."
|
|
12121
12220
|
),
|
|
12122
|
-
externalId:
|
|
12123
|
-
'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.'
|
|
12221
|
+
externalId: import_zod21.z.string().optional().describe(
|
|
12222
|
+
'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.'
|
|
12223
|
+
),
|
|
12224
|
+
upsert: import_zod21.z.boolean().optional().describe(
|
|
12225
|
+
"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)."
|
|
12124
12226
|
),
|
|
12125
|
-
|
|
12126
|
-
"
|
|
12227
|
+
schemaId: import_zod21.z.string().optional().describe(
|
|
12228
|
+
"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`)."
|
|
12127
12229
|
),
|
|
12128
|
-
|
|
12129
|
-
"
|
|
12230
|
+
confirmUntyped: import_zod21.z.boolean().optional().describe(
|
|
12231
|
+
"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."
|
|
12130
12232
|
),
|
|
12131
|
-
payload:
|
|
12233
|
+
payload: import_zod21.z.record(import_zod21.z.string(), import_zod21.z.unknown()).optional().describe(
|
|
12132
12234
|
"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."
|
|
12133
12235
|
),
|
|
12134
12236
|
// Inline text mode (mutually exclusive with filePath):
|
|
12135
|
-
text:
|
|
12136
|
-
storeText:
|
|
12237
|
+
text: import_zod21.z.string().min(1).optional().describe("Text body to ingest inline. Mutually exclusive with filePath. Either text or filePath is required."),
|
|
12238
|
+
storeText: import_zod21.z.boolean().optional().describe(
|
|
12137
12239
|
"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."
|
|
12138
12240
|
),
|
|
12139
12241
|
// File upload mode (mutually exclusive with text; stdio-transport-only):
|
|
12140
|
-
filePath:
|
|
12242
|
+
filePath: import_zod21.z.string().min(1).optional().describe(
|
|
12141
12243
|
"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."
|
|
12142
12244
|
),
|
|
12143
|
-
fileType:
|
|
12245
|
+
fileType: import_zod21.z.string().optional().describe('MIME type of the file (e.g. "application/pdf"). Inferred from filePath extension if omitted.'),
|
|
12144
12246
|
// Common (both modes):
|
|
12145
|
-
folderId:
|
|
12146
|
-
userId:
|
|
12147
|
-
scopes:
|
|
12247
|
+
folderId: import_zod21.z.string().optional().describe("Optional folder to ingest into. Default: tenant root."),
|
|
12248
|
+
userId: import_zod21.z.string().optional().describe("Owning user ID. Optional."),
|
|
12249
|
+
scopes: import_zod21.z.array(import_zod21.z.string()).optional().describe(
|
|
12148
12250
|
"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."
|
|
12149
12251
|
)
|
|
12150
12252
|
};
|
|
12151
12253
|
var documentIngest = ({ client, log, transport, ingestRoot }) => ({
|
|
12152
12254
|
name: "document_ingest",
|
|
12153
12255
|
title: "Ingest a new document (text body or file upload)",
|
|
12154
|
-
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
|
|
12256
|
+
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`.",
|
|
12155
12257
|
inputSchema: inputSchema21,
|
|
12156
12258
|
// Creates by default, idempotent ONLY when the caller supplies `externalId` (optional,
|
|
12157
12259
|
// per the doc comment above) — re-ingest then returns the existing document rather than
|
|
@@ -12169,6 +12271,7 @@ var documentIngest = ({ client, log, transport, ingestRoot }) => ({
|
|
|
12169
12271
|
const filePath = args.filePath;
|
|
12170
12272
|
const schemaId = args.schemaId;
|
|
12171
12273
|
const upsert = args.upsert;
|
|
12274
|
+
const confirmUntyped = args.confirmUntyped;
|
|
12172
12275
|
const indexMode = args.indexMode ?? (schemaId ? void 0 : "HYBRID");
|
|
12173
12276
|
if (!text && !filePath) {
|
|
12174
12277
|
return toolError(
|
|
@@ -12217,6 +12320,7 @@ var documentIngest = ({ client, log, transport, ingestRoot }) => ({
|
|
|
12217
12320
|
if (text) {
|
|
12218
12321
|
const result = await client.documents.ingestDocument({
|
|
12219
12322
|
upsert,
|
|
12323
|
+
confirmUntyped,
|
|
12220
12324
|
body: {
|
|
12221
12325
|
title,
|
|
12222
12326
|
text,
|
|
@@ -12257,6 +12361,7 @@ var documentIngest = ({ client, log, transport, ingestRoot }) => ({
|
|
|
12257
12361
|
const storeTextFile = args.storeText ?? true;
|
|
12258
12362
|
const upload = await client.documents.uploadDocument({
|
|
12259
12363
|
upsert,
|
|
12364
|
+
confirmUntyped,
|
|
12260
12365
|
fileName,
|
|
12261
12366
|
fileType,
|
|
12262
12367
|
indexMode,
|
|
@@ -12289,6 +12394,8 @@ var documentIngest = ({ client, log, transport, ingestRoot }) => ({
|
|
|
12289
12394
|
{ tool: "document_ingest", mode: "file", id: docId, fileName, fileType, bytes: bytes.length },
|
|
12290
12395
|
"document_ingest file ok"
|
|
12291
12396
|
);
|
|
12397
|
+
const uploadCreated = upload?.created;
|
|
12398
|
+
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.";
|
|
12292
12399
|
return {
|
|
12293
12400
|
content: [
|
|
12294
12401
|
{
|
|
@@ -12297,7 +12404,7 @@ var documentIngest = ({ client, log, transport, ingestRoot }) => ({
|
|
|
12297
12404
|
{
|
|
12298
12405
|
...upload,
|
|
12299
12406
|
indexStatus: "PENDING_INDEX",
|
|
12300
|
-
_note:
|
|
12407
|
+
_note: note
|
|
12301
12408
|
},
|
|
12302
12409
|
null,
|
|
12303
12410
|
2
|
|
@@ -12321,29 +12428,29 @@ function presignedUploadHeaders(response) {
|
|
|
12321
12428
|
}
|
|
12322
12429
|
|
|
12323
12430
|
// src/tools/lookup_principal.ts
|
|
12324
|
-
var
|
|
12431
|
+
var import_zod22 = require("zod");
|
|
12325
12432
|
var MCP_DEFAULT_LIMIT5 = 10;
|
|
12326
12433
|
var MCP_MAX_LIMIT5 = 100;
|
|
12327
12434
|
var inputSchema22 = {
|
|
12328
|
-
kind:
|
|
12435
|
+
kind: import_zod22.z.string().describe(
|
|
12329
12436
|
'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.'
|
|
12330
12437
|
),
|
|
12331
|
-
externalId:
|
|
12438
|
+
externalId: import_zod22.z.string().optional().describe(
|
|
12332
12439
|
"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."
|
|
12333
12440
|
),
|
|
12334
|
-
contextId:
|
|
12441
|
+
contextId: import_zod22.z.string().optional().describe(
|
|
12335
12442
|
"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."
|
|
12336
12443
|
),
|
|
12337
12444
|
// Lookup-mode args — provide `field` plus EXACTLY ONE of: value | from+to | prefix.
|
|
12338
|
-
type:
|
|
12339
|
-
field:
|
|
12340
|
-
value:
|
|
12341
|
-
from:
|
|
12342
|
-
to:
|
|
12343
|
-
prefix:
|
|
12344
|
-
order:
|
|
12345
|
-
startFrom:
|
|
12346
|
-
limit:
|
|
12445
|
+
type: import_zod22.z.string().optional().describe('Lookup mode: the identity schema\'s record type (e.g. "person_v1"). Required with `field`.'),
|
|
12446
|
+
field: import_zod22.z.string().optional().describe('Lookup mode: name of the schema-declared lookup field to query by (e.g. "email").'),
|
|
12447
|
+
value: import_zod22.z.string().optional().describe("Lookup mode (equality): exact-match value for `field`. Works on sensitive fields."),
|
|
12448
|
+
from: import_zod22.z.string().optional().describe("Lookup mode (range): inclusive lower bound; requires `to`. Non-sensitive fields only."),
|
|
12449
|
+
to: import_zod22.z.string().optional().describe("Lookup mode (range): inclusive upper bound; requires `from`."),
|
|
12450
|
+
prefix: import_zod22.z.string().optional().describe("Lookup mode (prefix): match values starting with this. Range-enabled string fields only."),
|
|
12451
|
+
order: import_zod22.z.enum(["asc", "desc"]).optional().describe("Lookup mode: sort direction by the looked-up field. `asc` (default) or `desc`."),
|
|
12452
|
+
startFrom: import_zod22.z.string().optional().describe("Lookup mode: pagination cursor \u2014 pass the `nextCursor` from the previous page to fetch the next."),
|
|
12453
|
+
limit: import_zod22.z.number().int().min(1).max(MCP_MAX_LIMIT5).optional().describe(
|
|
12347
12454
|
`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\`.`
|
|
12348
12455
|
)
|
|
12349
12456
|
};
|
|
@@ -12427,11 +12534,11 @@ var lookupPrincipal = ({ client, log }) => ({
|
|
|
12427
12534
|
var lookup_principal_default = lookupPrincipal;
|
|
12428
12535
|
|
|
12429
12536
|
// src/tools/version_history.ts
|
|
12430
|
-
var
|
|
12537
|
+
var import_zod23 = require("zod");
|
|
12431
12538
|
var inputSchema23 = {
|
|
12432
|
-
resourceType:
|
|
12433
|
-
id:
|
|
12434
|
-
startFrom:
|
|
12539
|
+
resourceType: import_zod23.z.enum(["record", "document"]).describe("Which kind of entity the id refers to: a record or a document."),
|
|
12540
|
+
id: import_zod23.z.string().min(1, "id is required").describe("The Vectros id of the record or document whose history you want."),
|
|
12541
|
+
startFrom: import_zod23.z.string().optional().describe("Pagination cursor \u2014 pass the `nextCursor` from the previous page to fetch older entries.")
|
|
12435
12542
|
};
|
|
12436
12543
|
var versionHistory = ({ client, log }) => ({
|
|
12437
12544
|
name: "version_history",
|
|
@@ -12555,7 +12662,7 @@ var ALL_RESOURCE_FACTORIES = {
|
|
|
12555
12662
|
};
|
|
12556
12663
|
|
|
12557
12664
|
// src/zod-to-json-schema.ts
|
|
12558
|
-
var
|
|
12665
|
+
var import_zod24 = require("zod");
|
|
12559
12666
|
function zodShapeToJsonSchema(shape) {
|
|
12560
12667
|
const properties = {};
|
|
12561
12668
|
const required = [];
|
|
@@ -12570,40 +12677,40 @@ function zodShapeToJsonSchema(shape) {
|
|
|
12570
12677
|
function zodTypeToJsonSchema(schema) {
|
|
12571
12678
|
const description = schema.description;
|
|
12572
12679
|
let current = schema;
|
|
12573
|
-
while (current instanceof
|
|
12680
|
+
while (current instanceof import_zod24.z.ZodOptional || current instanceof import_zod24.z.ZodDefault || current instanceof import_zod24.z.ZodNullable) {
|
|
12574
12681
|
current = current._def.innerType;
|
|
12575
12682
|
}
|
|
12576
12683
|
const base = description ? { description } : {};
|
|
12577
|
-
if (current instanceof
|
|
12684
|
+
if (current instanceof import_zod24.z.ZodString) {
|
|
12578
12685
|
return { ...base, type: "string" };
|
|
12579
12686
|
}
|
|
12580
|
-
if (current instanceof
|
|
12687
|
+
if (current instanceof import_zod24.z.ZodNumber) {
|
|
12581
12688
|
return { ...base, type: "number" };
|
|
12582
12689
|
}
|
|
12583
|
-
if (current instanceof
|
|
12690
|
+
if (current instanceof import_zod24.z.ZodBoolean) {
|
|
12584
12691
|
return { ...base, type: "boolean" };
|
|
12585
12692
|
}
|
|
12586
|
-
if (current instanceof
|
|
12693
|
+
if (current instanceof import_zod24.z.ZodEnum) {
|
|
12587
12694
|
return {
|
|
12588
12695
|
...base,
|
|
12589
12696
|
type: "string",
|
|
12590
12697
|
enum: current.options
|
|
12591
12698
|
};
|
|
12592
12699
|
}
|
|
12593
|
-
if (current instanceof
|
|
12700
|
+
if (current instanceof import_zod24.z.ZodArray) {
|
|
12594
12701
|
return {
|
|
12595
12702
|
...base,
|
|
12596
12703
|
type: "array",
|
|
12597
12704
|
items: zodTypeToJsonSchema(current.element)
|
|
12598
12705
|
};
|
|
12599
12706
|
}
|
|
12600
|
-
if (current instanceof
|
|
12707
|
+
if (current instanceof import_zod24.z.ZodObject) {
|
|
12601
12708
|
return {
|
|
12602
12709
|
...base,
|
|
12603
12710
|
...zodShapeToJsonSchema(current.shape)
|
|
12604
12711
|
};
|
|
12605
12712
|
}
|
|
12606
|
-
if (current instanceof
|
|
12713
|
+
if (current instanceof import_zod24.z.ZodRecord) {
|
|
12607
12714
|
const valueType = current._def.valueType;
|
|
12608
12715
|
return {
|
|
12609
12716
|
...base,
|
|
@@ -12732,7 +12839,7 @@ var VectrosMCPServer = class {
|
|
|
12732
12839
|
if (!tool) {
|
|
12733
12840
|
result = toolError(req.params.name ?? "unknown", new Error("No such tool."));
|
|
12734
12841
|
} else {
|
|
12735
|
-
const parsed =
|
|
12842
|
+
const parsed = import_zod25.z.object(tool.inputSchema).strict().safeParse(req.params.arguments ?? {});
|
|
12736
12843
|
if (!parsed.success) {
|
|
12737
12844
|
result = toolError(tool.name, new Error(formatArgError(tool, parsed.error)));
|
|
12738
12845
|
} else {
|