@vectros-ai/mcp-server 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -26,7 +26,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
26
26
  // src/server.ts
27
27
  var import_server = require("@modelcontextprotocol/sdk/server/index.js");
28
28
 
29
- // ../../node_modules/@vectros-ai/sdk/dist/index.mjs
29
+ // node_modules/@vectros-ai/sdk/dist/index.mjs
30
30
  var __defProp2 = Object.defineProperty;
31
31
  var __export = (target, all) => {
32
32
  for (var name in all)
@@ -4636,7 +4636,7 @@ var DocumentsClient = class {
4636
4636
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/documents");
4637
4637
  }
4638
4638
  /**
4639
- * 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.
4639
+ * 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.
4640
4640
  *
4641
4641
  * @param {Vectros.IngestDocumentRequest} request
4642
4642
  * @param {DocumentsClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -4962,25 +4962,29 @@ var DocumentsClient = class {
4962
4962
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "PATCH", "/v1/documents/{id}");
4963
4963
  }
4964
4964
  /**
4965
- * Finds documents of a given type by field value. Supported fields: `externalId` (the document's first-class external identifier — no schema declaration required) and any field declared as a lookup field on the bound schema. A lookup on a sensitive field is rejected here because the value would appear in the URL query string; use POST /v1/documents/lookup (the request-body variant) for a sensitive field instead. Results are paginated: set `limit` for the page size and feed the returned `nextCursor` back as `startFrom` to fetch the next page. The response is a `{data, nextCursor}` envelope. Requires the `documents:r` scope.
4965
+ * Finds documents of a given type by field value. Supported fields: `externalId` (the document's first-class external identifier — no schema declaration required) and any field declared as a lookup field on the bound schema. A lookup on a sensitive field is rejected here because the value would appear in the URL query string; use POST /v1/documents/lookup (the request-body variant) for a sensitive field instead. `type`'s schema resolves with basedOn-aware shadowing: your own `userId`- or `scope`-owned variant if you have one, otherwise the shared base — for a scoped credential the owner is always your own token identity; `userId`/`scope` here only apply as an explicit owner selector for a root API key. Results are paginated: set `limit` for the page size and feed the returned `nextCursor` back as `startFrom` to fetch the next page. The response is a `{data, nextCursor}` envelope. Requires the `documents:r` scope.
4966
4966
  *
4967
4967
  * @param {Vectros.LookupDocumentsRequest} request
4968
4968
  * @param {DocumentsClient.RequestOptions} requestOptions - Request-specific configuration.
4969
4969
  *
4970
+ * @throws {@link Vectros.BadRequestError}
4971
+ *
4970
4972
  * @example
4971
4973
  * await client.documents.lookupDocuments({
4972
4974
  * type: "invoice",
4973
4975
  * field: "po_number",
4974
4976
  * value: "PO-1001",
4975
4977
  * prefix: "PO-2024",
4976
- * startFrom: "550e8400-e29b-41d4-a716-446655440000"
4978
+ * startFrom: "550e8400-e29b-41d4-a716-446655440000",
4979
+ * userId: "550e8400-e29b-41d4-a716-446655440000",
4980
+ * scope: "org:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
4977
4981
  * })
4978
4982
  */
4979
4983
  lookupDocuments(request, requestOptions) {
4980
4984
  return HttpResponsePromise.fromPromise(this.__lookupDocuments(request, requestOptions));
4981
4985
  }
4982
4986
  async __lookupDocuments(request, requestOptions) {
4983
- const { type: type_, field, value, from: from_, to, prefix, startFrom, limit, order } = request;
4987
+ const { type: type_, field, value, from: from_, to, prefix, startFrom, limit, order, userId, scope } = request;
4984
4988
  const _queryParams = {
4985
4989
  type: type_,
4986
4990
  field,
@@ -4990,7 +4994,9 @@ var DocumentsClient = class {
4990
4994
  prefix,
4991
4995
  startFrom,
4992
4996
  limit,
4993
- order: order != null ? order : void 0
4997
+ order: order != null ? order : void 0,
4998
+ userId,
4999
+ scope
4994
5000
  };
4995
5001
  const _authRequest = await this._options.authProvider.getAuthRequest();
4996
5002
  const _headers = mergeHeaders(
@@ -5016,11 +5022,16 @@ var DocumentsClient = class {
5016
5022
  return { data: _response.body, rawResponse: _response.rawResponse };
5017
5023
  }
5018
5024
  if (_response.error.reason === "status-code") {
5019
- throw new VectrosError({
5020
- statusCode: _response.error.statusCode,
5021
- body: _response.error.body,
5022
- rawResponse: _response.rawResponse
5023
- });
5025
+ switch (_response.error.statusCode) {
5026
+ case 400:
5027
+ throw new BadRequestError(_response.error.body, _response.rawResponse);
5028
+ default:
5029
+ throw new VectrosError({
5030
+ statusCode: _response.error.statusCode,
5031
+ body: _response.error.body,
5032
+ rawResponse: _response.rawResponse
5033
+ });
5034
+ }
5024
5035
  }
5025
5036
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/documents/lookup");
5026
5037
  }
@@ -5388,7 +5399,7 @@ var FoldersClient = class {
5388
5399
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/folders");
5389
5400
  }
5390
5401
  /**
5391
- * Creates a folder to organize your documents and records. If `parentFolderId` is omitted, the folder is created under your context's default root folder. Folder creation is idempotent by (slug + parent): if a folder with the same slug already exists under the same parent, that existing folder 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 folder was returned) tells the two apart. To overwrite an existing folder's mutable fields instead of returning it unchanged, set `?upsert=true` (this also requires the `folders:u` scope). Requires the `folders:c` scope.
5402
+ * Creates a folder to organize your documents and records. If `parentFolderId` is omitted, the folder is created under your context's default root folder. Folder creation is idempotent by (slug + parent): if a folder with the same slug already exists under the same parent, that existing folder 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 folder was returned) tells the two apart. To overwrite an existing folder's mutable fields instead of returning it unchanged, set `?upsert=true` (this also requires the `folders:u` scope). Requires the `folders:c` scope to create. Being returned the existing folder on a collision is a read of that folder's data and additionally requires the `folders:r` scope — a credential holding `folders:c` alone receives a `400` ("already exists") on collision instead of the folder.
5392
5403
  *
5393
5404
  * @param {Vectros.CreateFolderRequest} request
5394
5405
  * @param {FoldersClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -5846,7 +5857,7 @@ var IdentityClient = class {
5846
5857
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/entities/{namespace}");
5847
5858
  }
5848
5859
  /**
5849
- * Creates a new entity in the given namespace. This call is idempotent on `externalId` within the namespace: if an entity with the same `externalId` already exists, the existing record is returned instead of creating a duplicate (`created: false`, HTTP 200). To overwrite an existing entity's content instead of returning it unchanged, set `?upsert=true` (also requires the `entities:u:<namespace>` scope). The namespace must be entity-backed (`org`/`client`, or registered via `POST /v1/namespaces`). Requires the `entities:c:<namespace>` scope.
5860
+ * Creates a new entity in the given namespace. This call is idempotent on `externalId` within the namespace: if an entity with the same `externalId` already exists, the existing record is returned instead of creating a duplicate (`created: false`, HTTP 200). To overwrite an existing entity's content instead of returning it unchanged, set `?upsert=true` (also requires the `entities:u:<namespace>` scope). The namespace must be entity-backed (`org`/`client`, or registered via `POST /v1/namespaces`). Requires the `entities:c:<namespace>` scope to create. Being returned the existing entity on a collision is a read of that entity's data and additionally requires the `entities:r:<namespace>` scope — a credential holding `entities:c:<namespace>` alone receives a `400` ("already in use") on collision instead of the entity.
5850
5861
  *
5851
5862
  * @param {Vectros.CreateEntityRequest} request
5852
5863
  * @param {IdentityClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -6290,7 +6301,7 @@ var IdentityClient = class {
6290
6301
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/namespaces/{namespace}");
6291
6302
  }
6292
6303
  /**
6293
- * Updates the mutable fields (`entityBacked`, `defaultSchemaId`) of a registered namespace. The namespace name itself is immutable. Requires a root API key. The reserved built-ins cannot be updated.
6304
+ * Updates the mutable fields (`entityBacked`, `defaultSchemaId`, `specificityRank`) of a registered namespace. The namespace name itself is immutable. Requires a root API key. The reserved built-ins cannot be updated.
6294
6305
  *
6295
6306
  * @param {Vectros.UpdateNamespaceRequest} request
6296
6307
  * @param {IdentityClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -6303,7 +6314,8 @@ var IdentityClient = class {
6303
6314
  * await client.identity.updateNamespace({
6304
6315
  * namespace: "team",
6305
6316
  * body: {
6306
- * namespace: "team"
6317
+ * namespace: "team",
6318
+ * specificityRank: 1500
6307
6319
  * }
6308
6320
  * })
6309
6321
  */
@@ -6468,7 +6480,7 @@ var IdentityClient = class {
6468
6480
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/namespaces");
6469
6481
  }
6470
6482
  /**
6471
- * Registers a new scope namespace and declares whether its values resolve to identity entities (`entityBacked`). Requires a root API key. The reserved names `org` and `client` are built in and cannot be registered.
6483
+ * Registers a new scope namespace and declares whether its values resolve to identity entities (`entityBacked`). Also requires `specificityRank`, an explicit, account-unique position in the specificity order used to break recordType schema-resolution ties. Requires a root API key. The reserved names `org` and `client` are built in and cannot be registered.
6472
6484
  *
6473
6485
  * @param {Vectros.NamespaceRequest} request
6474
6486
  * @param {IdentityClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -6479,7 +6491,8 @@ var IdentityClient = class {
6479
6491
  *
6480
6492
  * @example
6481
6493
  * await client.identity.registerNamespace({
6482
- * namespace: "team"
6494
+ * namespace: "team",
6495
+ * specificityRank: 1500
6483
6496
  * })
6484
6497
  */
6485
6498
  registerNamespace(request, requestOptions) {
@@ -6596,7 +6609,7 @@ var IdentityClient = class {
6596
6609
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/users");
6597
6610
  }
6598
6611
  /**
6599
- * Creates a user identity in your account. The operation is idempotent on `externalId`: if a user with the same `externalId` already exists, the existing record is returned instead of creating a duplicate. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing user was returned) tells the two apart. To overwrite an existing user's mutable fields (email, status, payload, schema binding) instead of returning it unchanged, set `?upsert=true` (this also requires the `users:u` scope). Requires the `users:c` scope.
6612
+ * Creates a user identity in your account. The operation is idempotent on `externalId`: if a user with the same `externalId` already exists, the existing record is returned instead of creating a duplicate. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing user was returned) tells the two apart. To overwrite an existing user's mutable fields (email, status, payload, schema binding) instead of returning it unchanged, set `?upsert=true` (this also requires the `users:u` scope). Requires the `users:c` scope to create. Being returned the existing user on a collision is a read of that user's data and additionally requires the `users:r` scope — a credential holding `users:c` alone receives a `400` ("already exists") on collision instead of the user.
6600
6613
  *
6601
6614
  * @param {Vectros.CreateUserRequest} request
6602
6615
  * @param {IdentityClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -7467,7 +7480,7 @@ var RecordsClient = class {
7467
7480
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/records");
7468
7481
  }
7469
7482
  /**
7470
- * Creates a new record of a given type. The `payload` is validated against that type's schema before the record is stored. Identify the type by sending `typeName`, `schemaId`, or both (they must agree); if you send only `schemaId`, the type is taken from that schema. Optionally supply an `externalId` to make the create idempotent — if a record with the same `externalId` already exists in your context, that existing record 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 record was returned) tells the two apart. To overwrite an existing record's content instead of returning it unchanged, set `?upsert=true` (this also requires the `records:u:<type>` scope). Requires the `records:c:<type>` scope.
7483
+ * Creates a new record of a given type. The `payload` is validated against that type's schema before the record is stored. Identify the type by sending `typeName`, `schemaId`, or both (they must agree); if you send only `schemaId`, the type is taken from that schema. Optionally supply an `externalId` to make the create idempotent — if a record with the same `externalId` already exists in your context, that existing record 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 record was returned) tells the two apart. To overwrite an existing record's content instead of returning it unchanged, set `?upsert=true` (this also requires the `records:u:<type>` scope). Requires the `records:c:<type>` scope to create. Being returned the existing record on a collision is a read of that record's data and additionally requires the `records:r:<type>` scope — a credential holding `records:c:<type>` alone receives a `400` ("already exists") on collision instead of the record.
7471
7484
  *
7472
7485
  * @param {Vectros.CreateRecordRequest} request
7473
7486
  * @param {RecordsClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -8058,6 +8071,8 @@ var SchemasClient = class {
8058
8071
  * @param {Vectros.ListSchemasRequest} request
8059
8072
  * @param {SchemasClient.RequestOptions} requestOptions - Request-specific configuration.
8060
8073
  *
8074
+ * @throws {@link Vectros.BadRequestError}
8075
+ *
8061
8076
  * @example
8062
8077
  * await client.schemas.listSchemas({
8063
8078
  * userId: "550e8400-e29b-41d4-a716-446655440000",
@@ -8104,16 +8119,21 @@ var SchemasClient = class {
8104
8119
  return { data: _response.body, rawResponse: _response.rawResponse };
8105
8120
  }
8106
8121
  if (_response.error.reason === "status-code") {
8107
- throw new VectrosError({
8108
- statusCode: _response.error.statusCode,
8109
- body: _response.error.body,
8110
- rawResponse: _response.rawResponse
8111
- });
8122
+ switch (_response.error.statusCode) {
8123
+ case 400:
8124
+ throw new BadRequestError(_response.error.body, _response.rawResponse);
8125
+ default:
8126
+ throw new VectrosError({
8127
+ statusCode: _response.error.statusCode,
8128
+ body: _response.error.body,
8129
+ rawResponse: _response.rawResponse
8130
+ });
8131
+ }
8112
8132
  }
8113
8133
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/schemas");
8114
8134
  }
8115
8135
  /**
8116
- * Defines a new record type with optional field definitions, validation rules, and lookup indexes. Idempotent by `typeName` within the same ownership scope: re-creating an existing `typeName` returns the existing schema rather than failing. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing schema was returned) tells the two apart. To reconcile an existing schema to the submitted shape instead of returning it unchanged, set `?upsert=true` (this also requires the `schemas:w` scope; only legal schema changes are applied — migration-locked changes are rejected). Requires the `schemas:w` scope.
8136
+ * Defines a new record type with optional field definitions, validation rules, and lookup indexes. Idempotent by `typeName` within the same ownership scope: re-creating an existing `typeName` returns the existing schema rather than failing. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing schema was returned) tells the two apart. To reconcile an existing schema to the submitted shape instead of returning it unchanged, set `?upsert=true` (this also requires the `schemas:u` scope; only legal schema changes are applied — migration-locked changes are rejected). Requires the `schemas:c` scope to create. Being returned the existing schema on a collision is a read of that schema's data and additionally requires the `schemas:r` scope — a credential holding `schemas:c` alone receives a `400` ("already in use") on collision instead of the schema.
8117
8137
  *
8118
8138
  * @param {Vectros.CreateSchemaRequest} request
8119
8139
  * @param {SchemasClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -8257,7 +8277,7 @@ var SchemasClient = class {
8257
8277
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/schemas/{id}");
8258
8278
  }
8259
8279
  /**
8260
- * Updates a record schema. Fields you omit are preserved; `typeName` is immutable and cannot be changed. Collection fields (`fields`, `lookupFields`, `renderHints`, `capabilities`) are replaced in full when supplied. Requires the `schemas:w` scope.
8280
+ * Updates a record schema. Fields you omit are preserved; `typeName` is immutable and cannot be changed. Collection fields (`fields`, `lookupFields`, `renderHints`, `capabilities`) are replaced in full when supplied. Requires the `schemas:u` scope.
8261
8281
  *
8262
8282
  * @param {Vectros.UpdateSchemaRequest} request
8263
8283
  * @param {SchemasClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -8326,7 +8346,7 @@ var SchemasClient = class {
8326
8346
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "PUT", "/v1/schemas/{id}");
8327
8347
  }
8328
8348
  /**
8329
- * Permanently deletes a record schema. The request is refused with 409 if records of this type still exist — delete those records first, since every record must reference a live schema. Requires the `schemas:w` scope.
8349
+ * Permanently deletes a record schema. The request is refused with 409 if records of this type still exist — delete those records first, since every record must reference a live schema. A lineage base (a schema other schemas declare `basedOn`) also cannot be deleted while any such variant still exists — delete the variant schema(s) first. Requires the `schemas:d` scope.
8330
8350
  *
8331
8351
  * @param {Vectros.DeleteSchemaRequest} request
8332
8352
  * @param {SchemasClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -8623,8 +8643,8 @@ function warnOnSuboptimalKey(key, log) {
8623
8643
 
8624
8644
  // src/build-info.ts
8625
8645
  var BUILD_INFO = {
8626
- mcpServer: true ? "0.11.0" : "dev",
8627
- sdk: true ? "0.36.0" : "dev"
8646
+ mcpServer: true ? "0.12.0" : "dev",
8647
+ sdk: true ? "0.37.0" : "dev"
8628
8648
  };
8629
8649
  function formatBuildInfo() {
8630
8650
  return `vectros-mcp-server ${BUILD_INFO.mcpServer} (sdk ${BUILD_INFO.sdk})`;
@@ -9139,14 +9159,14 @@ var record_query_default = recordQuery;
9139
9159
  var import_zod3 = require("zod");
9140
9160
 
9141
9161
  // src/tools/resolve-external-id.ts
9142
- function validateSelector(sel, entity) {
9162
+ function validateSelector(sel, entity, fieldName) {
9143
9163
  const hasId = sel.id !== void 0 && sel.id !== "";
9144
9164
  const hasExt = sel.externalId !== void 0 && sel.externalId !== "";
9145
9165
  if (hasId && hasExt) {
9146
- return `Provide either id or externalId (not both) to identify the ${entity}.`;
9166
+ return `Provide either ${fieldName} or externalId (not both) to identify the ${entity}.`;
9147
9167
  }
9148
9168
  if (!hasId && !hasExt) {
9149
- return `Provide id, or externalId + type, to identify the ${entity}.`;
9169
+ return `Provide ${fieldName}, or externalId + type, to identify the ${entity}.`;
9150
9170
  }
9151
9171
  if (hasExt && (sel.type === void 0 || sel.type === "")) {
9152
9172
  return "type is required when selecting by externalId (externalId is unique within a type).";
@@ -9154,7 +9174,7 @@ function validateSelector(sel, entity) {
9154
9174
  return void 0;
9155
9175
  }
9156
9176
  async function resolveRecordIdByExternalId(client, sel) {
9157
- const err = validateSelector(sel, "record");
9177
+ const err = validateSelector(sel, "record", "id");
9158
9178
  if (err) return { error: err };
9159
9179
  if (sel.id) return { id: sel.id };
9160
9180
  const page = await client.records.lookupRecordsByBody({
@@ -9170,7 +9190,7 @@ async function resolveRecordIdByExternalId(client, sel) {
9170
9190
  return { id: items[0].id };
9171
9191
  }
9172
9192
  async function resolveDocumentIdByExternalId(client, sel) {
9173
- const err = validateSelector(sel, "document");
9193
+ const err = validateSelector(sel, "document", "documentId");
9174
9194
  if (err) return { error: err };
9175
9195
  if (sel.id) return { id: sel.id };
9176
9196
  const page = await client.documents.lookupDocumentsByBody({