@protobase/server 0.53.1 → 0.53.2

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.
@@ -0,0 +1,9 @@
1
+ import { listColumnNames } from "@protobase/schema/internal";
2
+ //#region src/assistant/list-fields.ts
3
+ /**
4
+ * The fields `list_records` returns when it is not told which: the key, then the columns of the resource's table as
5
+ * the caller's view lists them, leaving out the related columns, which are not fields.
6
+ */
7
+ const listFields = (model, view) => [.../* @__PURE__ */ new Set([...model.primaryKey, ...listColumnNames(model, view)])].filter((name) => Object.hasOwn(model.fields, name) && !model.fields[name].writeOnly);
8
+ //#endregion
9
+ export { listFields };
@@ -0,0 +1,13 @@
1
+ import { pickFields } from "../rows.js";
2
+ import { selectedFields } from "../params.js";
3
+ //#region src/assistant/record-fields.ts
4
+ /** `record` with only `fields`, each one of those it holds, which are those the caller may read; all of it without. */
5
+ const recordFields = (model, record, fields) => {
6
+ const readable = Object.fromEntries(Object.keys(record).map((name) => [name, model.fields[name]]));
7
+ return pickFields(record, selectedFields({
8
+ ...model,
9
+ fields: readable
10
+ }, fields));
11
+ };
12
+ //#endregion
13
+ export { recordFields };
@@ -1,5 +1,6 @@
1
1
  import { notFound } from "../problem.js";
2
2
  import { defineTool } from "./tools.js";
3
+ import { listFields } from "./list-fields.js";
3
4
  import { invalidShowDeleted, keyOf, keyParameter, refused, resourceOf, resourceParameter, showDeletedOf, showDeletedParameter } from "./record-tool-args.js";
4
5
  import { countRecordsTool } from "./count-records-tool.js";
5
6
  //#region src/assistant/record-tools.ts
@@ -36,6 +37,7 @@ const resourceSummary = (model, view) => ({
36
37
  const resourceDetail = (model, view) => ({
37
38
  ...resourceSummary(model, view),
38
39
  ...view?.help && { help: view.help },
40
+ list_fields: listFields(model, view),
39
41
  fields: Object.values(model.fields).map((field) => fieldEntry(field, view))
40
42
  });
41
43
  const viewOf = ({ views }, model) => views.find((view) => view.resource === model.name);
@@ -56,7 +58,7 @@ const listResourcesTool = () => defineTool({
56
58
  /** Describes one resource the caller may read, with its fields, their labels, help and values, and which fields filters and sorts take. */
57
59
  const describeResourceTool = () => defineTool({
58
60
  name: "describe_resource",
59
- description: "Describes one resource you may read, as JSON: its name, label, help, key fields, whether it soft deletes (soft_delete) and fields (name, type, label, help, enum values, the resource a relation links to, and whether it is optional, read-only, filterable and sortable). Filters and order_by in list_records take only fields marked filterable or sortable.",
61
+ description: "Describes one resource you may read, as JSON: its name, label, help, key fields, whether it soft deletes (soft_delete) and fields (name, type, label, help, enum values, the resource a relation links to, and whether it is optional, read-only, filterable and sortable), and list_fields, the fields list_records returns when not told which. Filters and order_by in list_records take only fields marked filterable or sortable.",
60
62
  parameters: {
61
63
  type: "object",
62
64
  properties: { resource: resourceParameter },
@@ -72,14 +74,42 @@ const describeResourceTool = () => defineTool({
72
74
  return JSON.stringify(resourceDetail(model, viewOf(resources, model)));
73
75
  }
74
76
  });
77
+ const fieldsParameter = (what) => ({
78
+ type: "array",
79
+ items: { type: "string" },
80
+ minItems: 1,
81
+ description: `The fields to return, such as ["id", "status"], or ["*"] for every field; ${what}.`
82
+ });
83
+ /** The fields named, `*` when they ask for every field, or `undefined` when none are. */
84
+ const fieldsOf = (value) => {
85
+ if (!Array.isArray(value) || value.length === 0 || !value.every((name) => typeof name === "string")) return void 0;
86
+ return value.includes("*") ? "*" : value;
87
+ };
88
+ /** Without `fields`, the resource's list fields, the page naming the others in `omitted_fields`; `*` asks for all. */
89
+ const listedFields = async (resource, value, context) => {
90
+ const named = fieldsOf(value);
91
+ if (named === "*") return {};
92
+ if (named) return { fields: named };
93
+ const readable = await context.resources();
94
+ const model = readable.models.find((each) => each.name === resource);
95
+ if (!model) return {};
96
+ const fields = listFields(model, viewOf(readable, model));
97
+ const omitted = Object.keys(model.fields).filter((name) => !fields.includes(name));
98
+ if (omitted.length === 0) return {};
99
+ return {
100
+ fields,
101
+ omitted
102
+ };
103
+ };
75
104
  /** Finds records of a resource with the REST API's filters, sorting and pages, under the caller's access rules. */
76
105
  const listRecordsTool = () => defineTool({
77
106
  name: "list_records",
78
- description: `Finds records of a resource and returns a page of them as JSON ({ items, next_page_token, total_size_estimate }). filter uses AIP-160 syntax, such as status = "open" AND amount > 10, and order_by a comma-separated list of fields, each optionally followed by desc. Pass next_page_token back as page_token for the next page; it is empty on the last. show_deleted: true also returns soft-deleted records.`,
107
+ description: `Finds records of a resource and returns a page of them as JSON ({ items, next_page_token, total_size_estimate }). Name the fields you need in fields, such as ["id", "status"]; without it each record has its resource's list_fields, the columns of its table in the app, and the page names the others in omitted_fields: pass ["*"] for every field. filter uses AIP-160 syntax on filterable fields, such as status = "open" AND amount > 10, and order_by a comma-separated list of sortable fields, each optionally followed by desc. total_size_estimate is an estimate, not an exact count. Keep page_size small and pass next_page_token back as page_token for the next page; it is empty on the last. show_deleted: true also returns soft-deleted records.`,
79
108
  parameters: {
80
109
  type: "object",
81
110
  properties: {
82
111
  resource: resourceParameter,
112
+ fields: fieldsParameter("without it, the list_fields describe_resource names"),
83
113
  filter: {
84
114
  type: "string",
85
115
  description: "An AIP-160 filter on filterable fields, such as status = \"open\" AND amount > 10."
@@ -108,25 +138,31 @@ const listRecordsTool = () => defineTool({
108
138
  if (!resource) return "Pass the resource as { \"resource\": \"<name>\" }.";
109
139
  const showDeleted = showDeletedOf(args);
110
140
  if (showDeleted === void 0) return invalidShowDeleted;
141
+ const { fields, omitted } = await listedFields(resource, args.fields, context);
111
142
  const params = {
112
143
  ...typeof args.filter === "string" && { filter: args.filter },
113
144
  ...typeof args.order_by === "string" && { order_by: args.order_by },
114
145
  ...typeof args.page_token === "string" && { page_token: args.page_token },
146
+ ...fields && { fields },
115
147
  page_size: typeof args.page_size === "number" ? Math.min(args.page_size, maxPageSize) : defaultPageSize,
116
148
  ...showDeleted && { show_deleted: true }
117
149
  };
118
- return context.records.list(resource, params).then((page) => JSON.stringify(page), refused);
150
+ return context.records.list(resource, params).then((page) => JSON.stringify({
151
+ ...page,
152
+ ...omitted && { omitted_fields: omitted }
153
+ }), refused);
119
154
  }
120
155
  });
121
156
  /** Reads one record by its key, under the caller's access rules. */
122
157
  const getRecordTool = () => defineTool({
123
158
  name: "get_record",
124
- description: "Reads one record of a resource by its key and returns it as JSON ({ record, etag }). show_deleted: true also finds a soft-deleted record.",
159
+ description: "Reads one record of a resource by its key and returns it as JSON ({ record, etag }). Name the fields you need in fields, such as [\"id\", \"status\"]; without it, or with [\"*\"], the record has every field, long texts included. show_deleted: true also finds a soft-deleted record.",
125
160
  parameters: {
126
161
  type: "object",
127
162
  properties: {
128
163
  resource: resourceParameter,
129
164
  key: keyParameter,
165
+ fields: fieldsParameter("without it, every field"),
130
166
  show_deleted: showDeletedParameter
131
167
  },
132
168
  required: ["resource", "key"]
@@ -138,7 +174,11 @@ const getRecordTool = () => defineTool({
138
174
  if (!resource || key === void 0) return "Pass the resource and key as { \"resource\": \"<name>\", \"key\": \"<key>\" }.";
139
175
  const showDeleted = showDeletedOf(args);
140
176
  if (showDeleted === void 0) return invalidShowDeleted;
141
- return context.records.get(resource, key, { show_deleted: showDeleted }).then((record) => JSON.stringify(record), refused);
177
+ const fields = fieldsOf(args.fields);
178
+ return context.records.get(resource, key, {
179
+ show_deleted: showDeleted,
180
+ ...Array.isArray(fields) && { fields }
181
+ }).then((record) => JSON.stringify(record), refused);
142
182
  }
143
183
  });
144
184
  /**
@@ -61,9 +61,13 @@ export type ToolRecords = {
61
61
  list: (resource: string, params?: ListParams) => Promise<RecordPage>;
62
62
  /** Counts per value of a field, as `GET /{resource}:aggregate` does, under the same access rules as `list`. */
63
63
  aggregate: (resource: string, params: AggregateParams) => Promise<RecordGroups>;
64
- /** With `show_deleted`, also finds a soft-deleted record, as the REST API's `show_deleted` does. */
64
+ /**
65
+ * With `show_deleted`, also finds a soft-deleted record, as the REST API's `show_deleted` does. With `fields`, the
66
+ * record holds those fields only, each checked against the fields the caller may read.
67
+ */
65
68
  get: (resource: string, key: RecordKeyInput, options?: {
66
69
  show_deleted?: boolean;
70
+ fields?: string[];
67
71
  }) => Promise<ToolRecord>;
68
72
  create: (resource: string, data: Row) => Promise<ToolRecord>;
69
73
  /** With `etag`, fails with 412 when the record changed since it was read; without, it updates any version. */
@@ -5,6 +5,7 @@ import { decodeKeyText } from "../key.js";
5
5
  import { runBatch } from "../batch/run-batch.js";
6
6
  import { listRecords } from "../list-service.js";
7
7
  import { readRecord } from "../read-service.js";
8
+ import { recordFields } from "./record-fields.js";
8
9
  import { encodeKey } from "@protobase/schema/internal";
9
10
  //#region src/assistant/records.ts
10
11
  const filterLength = 2e5;
@@ -29,11 +30,11 @@ const assistantRecords = (deps, session) => {
29
30
  return {
30
31
  list: async (resource, params = {}) => (await listRecords(deps, entryOf(resource), session, params, filterLength)).body,
31
32
  aggregate: async (resource, params) => (await aggregate(deps, entryOf(resource), session, params)).body,
32
- get: async (resource, input, { show_deleted } = {}) => {
33
+ get: async (resource, input, { show_deleted, fields } = {}) => {
33
34
  const { entry, key } = keyOf(resource, input);
34
35
  const { record, etag } = await readRecord(deps, entry, session, key, show_deleted);
35
36
  return {
36
- record,
37
+ record: recordFields(entry.model, record, fields),
37
38
  etag
38
39
  };
39
40
  },
package/dist/index.d.ts CHANGED
@@ -130,6 +130,7 @@ import { CommentToolsInput, addCommentTool, commentTools, listCommentsTool } fro
130
130
  import { McpApprovals, mcpApprovals } from "./mcp/mcp-approval-store.js";
131
131
  import { McpServerInput, mcpServer } from "./mcp/mcp-server.js";
132
132
  import { mcpIcons } from "./web-app/mcp-icons.js";
133
+ import { mcpInstructions } from "./mcp/mcp-instructions.js";
133
134
  import { McpToolsInput, mcpTools } from "./mcp/mcp-tools.js";
134
135
  import { McpGateInput, mcpGate, sessionOf } from "./mcp/mcp-gate.js";
135
136
  import { McpHandlerInput, mcpHandler } from "./mcp/mcp-handler.js";
@@ -170,4 +171,4 @@ import { MobileRelease, ReleaseFile, ServedReleaseFile, composeRelease, releaseM
170
171
  import { MobileReleaseAppInput, OfferedRelease, mobileReleaseApp } from "./mobile-release/release-app.js";
171
172
  import { mobileSigningKeyVariable, readSigningKey } from "./mobile-release/signing-key.js";
172
173
  import { AdminAuth, CreateAuthOptions, UserCreatedHook, normalizeRoles } from "./better-auth/create-auth.js";
173
- export { type Admin, type AdminAuth, type AdminOptions, type AggregateParams, type ApiFunction, type ApiKeys, type ApiKeysOptions, type ApnsEnvironment, type AppIcons, type AppIdentity, type AppPoolConfig, type ApplyOptions, type ApplyResult, type ApprovalAnswer, type ApprovalRequest, type ArgumentsPayload, type AssistantBackend, type AssistantOptions, type AssistantSettings, type AssistantTool, type AuditEvent, type AuditQueue, type AuthHooks, type AuthSettings, type AuthenticateSettings, type Authenticator, type BatchOperation, type BatchResult, type BetterAuthAuthenticator, type BetterAuthAuthenticatorOptions, type Caller, type CallerOptions, type CapturedRow, type CascadingKey, type ChatMessage, type ChatTextPart, type CheckAiInput, type CleanupEntry, type CleanupReport, type CleanupSchedule, type CoalescedChange, type CommentItem, type CommentToolsInput, type CommentUsers, type Completion, type CompletionOptions, ConnectionsBusy, type Conversation, type ConversationRecord, type ConversationStore, type ConversationsOptions, type CorsOptions, type CorsOrigins, type CreateAdminInput, type CreateAuthOptions, type Device, type DeviceColumn, type DeviceKind, type DeviceStore, DeviceStoreError, type DrainResult, type EmailComponent, type EmailOptions, type EmailTemplate, type EncryptionStatus, type EncryptionTools, type EncryptionToolsInput, type EnqueueJob, type EnqueueOptions, type ErrorReporter, type ErrorReportingOptions, type ErrorReportingSettings, type EventData, type EventsOptions, FatalJobError, type FieldApplied, type FieldStatus, type FileCleanupInput, type FileLimits, type FileObject, type FileProvider, type FileProviderSettings, type FileRef, type FileStore, type FileVariantObject, type FilesOptions, type FunctionApp, type FunctionCaller, type FunctionContext, type FunctionEnv, type FunctionHandler, type FunctionOptions, type FunctionRecords, type FunctionSocket, type FunctionSource, type HistoryColumn, type HistoryOptions, type HistoryPosition, type HistoryStore, HistoryStoreError, type HookContext, HttpProblem, type IssueTokenOptions, type JobContext, type JobDeclaration, type JobDefinition, type JobName, type JobOptions, type JobPayload, type JobRun, type JobsRuntime, type JsonObject, type JsonValue, type JwtOptions, type JwtVerifyOptions, type KeyFunctionContext, type LinkedAccount, type ListParams, type LocalFilesOptions, type MailMessage, type Mailer, type MapLayer, type MapOptions, type MapSettings, type McpApprovals, type McpGateInput, type McpHandlerInput, type McpRoutesInput, type McpServerInput, type McpToolsInput, type McpWrites, type MemberInput, type Membership, MissingCredentials, type MobileConfig, type MobileRelease, type MobileReleaseAppInput, ModelError, type ModelSettings, type NewDevice, type NewNotification, type NewOrganization, type NewUser, type NotificationRecipients, NotificationSendError, type NotificationsOptions, type OfferedRelease, type OperatorProvider, type OrganizationRole, type OrganizationsOptions, type PgModule, type PipelineHook, type PlatformSignIn, type PluginOption, type PluginRef, type PngIcon, type ProtectedFunctionOptions, type PublicFunctionContext, type PublicFunctionEnv, type PublicFunctionHandler, type PublicFunctionOptions, type PushAnswer, type PushMessage, PushMessageError, type PushSender, type QueryOptions, type QueryResult, type ReadableResources, type RealtimeOptions, type ReasoningDetail, type ReasoningEffort, type RebindOption, type RecordGroups, type RecordKeyInput, type RecordPage, type ReleaseFile, type RenderedEmail, type ResourceChange, type ResourceSource, type RoleDefinition, type RolesInput, type RunContext, type RuntimeOptions, type S3Bucket, type S3FilesOptions, type S3ListPage, type S3Object, type ScanGuardMode, type ScheduledDelete, type SendNotification, type ServedReleaseFile, type Session, type SessionOrganization, type Sharp, type SignInPolicy, type SignInRule, type SignatureOptions, type SocketEvents, type SourceOption, type SourceRef, type StaffAccessRule, type StaffSignIn, type StandardSchema, type StandardWebhookOptions, type StartJobsOptions, type StoreFileInput, type StoredMember, type StoredNotification, type StoredObject, type StoredOrganization, type StoredUser, type StrayValues, type SubscriptionDefinition, type SubscriptionEvent, type SubscriptionOptions, type TenantValue, type ToolAnnotations, type ToolCall, type ToolComment, type ToolCommentPage, type ToolComments, type ToolContext, type ToolRecord, type ToolRecords, type ToolSpec, type TrustedApp, type TurnOptions, type UnreadableEntry, type Urgency, type User, type UserCreatedHook, type VapidSettings, type ViewSource, type WebPushFields, type WebPushOptions, type WebhooksOptions, type WidgetOptions, type WriteEvent, type WriteOperation, type WriteRecordToolsInput, addAppRoleToOwners, addCommentTool, addMember, apiKeyCaller, apiKeySettings, apiKeyVariables, appNameOver, aspectRatio, assistantProtocolRoutes, assistantRoles, assistantSettings, assistantVariables, authSchemaDrift, authSchemaMigration, authStoreTables, backgroundSettled, badRequest, batchWriteTool, beforeSignInPluginsVariable, betterAuthTokens, capSocketMessages, changesMigration, checkAi, checkAuthSchema, checkChanges, checkComments, checkComputed, checkJobsSchema, checkNotificationsSchema, checkQueryRunner, checkRealtimeRelay, checkResourcesOutsideAuthStore, checkSourceNames, checkViewQueries, checkWebhooksSchema, coalesce, commentTools, commentsMigration, composeRelease, computedMigration, configExports, consoleAuditQueue, conversationKey, countRecordsTool, createAdmin, createConversations, createEncryptionTools, createFileCleanup, createOrganization, createRecordTool, createUser, defaultAppName, defaultHistoryPage, defaultSignInPolicy, defineEmail, defineFunction, defineJob, defineTool, deleteRecordTool, deleteUser, describeResourceTool, deviceIdParam, deviceStore, devicesPath, enqueueJob, errorReportingSettings, errorReportingVariable, eventMatcher, fileConversationStore, fileSize, fileType, forbidden, formatUri, functionApp, generateVapidKeys, getRecordTool, goTruePath, handleDroppedConnections, hasUsers, historyIdParam, historyIdPattern, historyLimits, historyPath, historyStore, honorSocketMessageCaps, imageSize, isBackgroundWork, isCaptured, isJobDefinition, isOAuthWellKnownPath, isSchedule, issueToken, jobDefinitions, jobsDrainApp, jobsSchema, jobsSchemaMigration, jwtAuthenticator, jwtVerifier, limitedFileStore, listCommentsTool, listOrganizations, listRecordsTool, listResourcesTool, listUsers, localFileStore, longQueryTimeoutMs, mapSettings, mapStyleUrl, mapStyleVariable, maxDevicesPerUser, maxHistoryPage, maxMessageBytes, maxRecipients, maxTokenTtlSeconds, maxTtlSeconds, maxUnreadCount, maxWidgetPropsBytes, mcpApprovals, mcpGate, mcpHandler, mcpIcons, mcpRoutes, mcpServer, mcpToolContext, mcpTools, migrationCommand, mobileReleaseApp, mobileSigningKeyVariable, newWebhookSecret, normalizeRoles, notFound, notificationSenders, notificationsMigration, oauthWellKnownPaths, objectKey, parseColumns, parseRoles, passwordLength, pluginOptions, pluginsBeforeSignIn, pluginsFor, pluginsVariable, pngIcons, poolWaitMs, postgresDeviceStore, postgresHistoryStore, processor, pushMessage, queryRunnerMigration, readDbConnections, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readRecordTools, readSigningKey, readVapidSettings, readWriteQueryTool, readableResources, realtimeLimits, realtimeRelayMigration, recordOf, relayed, releaseManifest, removeDevicesWithUsers, removeHistoryWithUsers, removeMember, renderVariant, requestApproval, requireEnv, resourceChange, roleChoices, runInBackground, runReadOnlyQuery, runReadWriteQuery, runTurn, runtimeUrl, runtimeVariable, s3FileStore, seesAssistant, seesRuntime, sendNotification, sessionOf, setMemberRoles, setUserBanned, setUserRole, shownAppName, signInPolicyMethods, socketMessageCapOf, sourceOptions, sourcesFor, sourcesVariable, startErrorReporting, startJobs, storageCleanupSchedule, storageProvider, storeFile, storeUsage, streamChatCompletion, subscription, supabasePath, thumbHash, unauthorized, updateRecordTool, urgencies, vapidPrivateKeyVariable, vapidPublicKeyVariable, vapidSubjectVariable, variantPath, verifySignature, verifyStandardWebhook, waitUntil, wantsLongQueries, webManifestPath, webPushSender, webauthnPath, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps, writeRecordTools };
174
+ export { type Admin, type AdminAuth, type AdminOptions, type AggregateParams, type ApiFunction, type ApiKeys, type ApiKeysOptions, type ApnsEnvironment, type AppIcons, type AppIdentity, type AppPoolConfig, type ApplyOptions, type ApplyResult, type ApprovalAnswer, type ApprovalRequest, type ArgumentsPayload, type AssistantBackend, type AssistantOptions, type AssistantSettings, type AssistantTool, type AuditEvent, type AuditQueue, type AuthHooks, type AuthSettings, type AuthenticateSettings, type Authenticator, type BatchOperation, type BatchResult, type BetterAuthAuthenticator, type BetterAuthAuthenticatorOptions, type Caller, type CallerOptions, type CapturedRow, type CascadingKey, type ChatMessage, type ChatTextPart, type CheckAiInput, type CleanupEntry, type CleanupReport, type CleanupSchedule, type CoalescedChange, type CommentItem, type CommentToolsInput, type CommentUsers, type Completion, type CompletionOptions, ConnectionsBusy, type Conversation, type ConversationRecord, type ConversationStore, type ConversationsOptions, type CorsOptions, type CorsOrigins, type CreateAdminInput, type CreateAuthOptions, type Device, type DeviceColumn, type DeviceKind, type DeviceStore, DeviceStoreError, type DrainResult, type EmailComponent, type EmailOptions, type EmailTemplate, type EncryptionStatus, type EncryptionTools, type EncryptionToolsInput, type EnqueueJob, type EnqueueOptions, type ErrorReporter, type ErrorReportingOptions, type ErrorReportingSettings, type EventData, type EventsOptions, FatalJobError, type FieldApplied, type FieldStatus, type FileCleanupInput, type FileLimits, type FileObject, type FileProvider, type FileProviderSettings, type FileRef, type FileStore, type FileVariantObject, type FilesOptions, type FunctionApp, type FunctionCaller, type FunctionContext, type FunctionEnv, type FunctionHandler, type FunctionOptions, type FunctionRecords, type FunctionSocket, type FunctionSource, type HistoryColumn, type HistoryOptions, type HistoryPosition, type HistoryStore, HistoryStoreError, type HookContext, HttpProblem, type IssueTokenOptions, type JobContext, type JobDeclaration, type JobDefinition, type JobName, type JobOptions, type JobPayload, type JobRun, type JobsRuntime, type JsonObject, type JsonValue, type JwtOptions, type JwtVerifyOptions, type KeyFunctionContext, type LinkedAccount, type ListParams, type LocalFilesOptions, type MailMessage, type Mailer, type MapLayer, type MapOptions, type MapSettings, type McpApprovals, type McpGateInput, type McpHandlerInput, type McpRoutesInput, type McpServerInput, type McpToolsInput, type McpWrites, type MemberInput, type Membership, MissingCredentials, type MobileConfig, type MobileRelease, type MobileReleaseAppInput, ModelError, type ModelSettings, type NewDevice, type NewNotification, type NewOrganization, type NewUser, type NotificationRecipients, NotificationSendError, type NotificationsOptions, type OfferedRelease, type OperatorProvider, type OrganizationRole, type OrganizationsOptions, type PgModule, type PipelineHook, type PlatformSignIn, type PluginOption, type PluginRef, type PngIcon, type ProtectedFunctionOptions, type PublicFunctionContext, type PublicFunctionEnv, type PublicFunctionHandler, type PublicFunctionOptions, type PushAnswer, type PushMessage, PushMessageError, type PushSender, type QueryOptions, type QueryResult, type ReadableResources, type RealtimeOptions, type ReasoningDetail, type ReasoningEffort, type RebindOption, type RecordGroups, type RecordKeyInput, type RecordPage, type ReleaseFile, type RenderedEmail, type ResourceChange, type ResourceSource, type RoleDefinition, type RolesInput, type RunContext, type RuntimeOptions, type S3Bucket, type S3FilesOptions, type S3ListPage, type S3Object, type ScanGuardMode, type ScheduledDelete, type SendNotification, type ServedReleaseFile, type Session, type SessionOrganization, type Sharp, type SignInPolicy, type SignInRule, type SignatureOptions, type SocketEvents, type SourceOption, type SourceRef, type StaffAccessRule, type StaffSignIn, type StandardSchema, type StandardWebhookOptions, type StartJobsOptions, type StoreFileInput, type StoredMember, type StoredNotification, type StoredObject, type StoredOrganization, type StoredUser, type StrayValues, type SubscriptionDefinition, type SubscriptionEvent, type SubscriptionOptions, type TenantValue, type ToolAnnotations, type ToolCall, type ToolComment, type ToolCommentPage, type ToolComments, type ToolContext, type ToolRecord, type ToolRecords, type ToolSpec, type TrustedApp, type TurnOptions, type UnreadableEntry, type Urgency, type User, type UserCreatedHook, type VapidSettings, type ViewSource, type WebPushFields, type WebPushOptions, type WebhooksOptions, type WidgetOptions, type WriteEvent, type WriteOperation, type WriteRecordToolsInput, addAppRoleToOwners, addCommentTool, addMember, apiKeyCaller, apiKeySettings, apiKeyVariables, appNameOver, aspectRatio, assistantProtocolRoutes, assistantRoles, assistantSettings, assistantVariables, authSchemaDrift, authSchemaMigration, authStoreTables, backgroundSettled, badRequest, batchWriteTool, beforeSignInPluginsVariable, betterAuthTokens, capSocketMessages, changesMigration, checkAi, checkAuthSchema, checkChanges, checkComments, checkComputed, checkJobsSchema, checkNotificationsSchema, checkQueryRunner, checkRealtimeRelay, checkResourcesOutsideAuthStore, checkSourceNames, checkViewQueries, checkWebhooksSchema, coalesce, commentTools, commentsMigration, composeRelease, computedMigration, configExports, consoleAuditQueue, conversationKey, countRecordsTool, createAdmin, createConversations, createEncryptionTools, createFileCleanup, createOrganization, createRecordTool, createUser, defaultAppName, defaultHistoryPage, defaultSignInPolicy, defineEmail, defineFunction, defineJob, defineTool, deleteRecordTool, deleteUser, describeResourceTool, deviceIdParam, deviceStore, devicesPath, enqueueJob, errorReportingSettings, errorReportingVariable, eventMatcher, fileConversationStore, fileSize, fileType, forbidden, formatUri, functionApp, generateVapidKeys, getRecordTool, goTruePath, handleDroppedConnections, hasUsers, historyIdParam, historyIdPattern, historyLimits, historyPath, historyStore, honorSocketMessageCaps, imageSize, isBackgroundWork, isCaptured, isJobDefinition, isOAuthWellKnownPath, isSchedule, issueToken, jobDefinitions, jobsDrainApp, jobsSchema, jobsSchemaMigration, jwtAuthenticator, jwtVerifier, limitedFileStore, listCommentsTool, listOrganizations, listRecordsTool, listResourcesTool, listUsers, localFileStore, longQueryTimeoutMs, mapSettings, mapStyleUrl, mapStyleVariable, maxDevicesPerUser, maxHistoryPage, maxMessageBytes, maxRecipients, maxTokenTtlSeconds, maxTtlSeconds, maxUnreadCount, maxWidgetPropsBytes, mcpApprovals, mcpGate, mcpHandler, mcpIcons, mcpInstructions, mcpRoutes, mcpServer, mcpToolContext, mcpTools, migrationCommand, mobileReleaseApp, mobileSigningKeyVariable, newWebhookSecret, normalizeRoles, notFound, notificationSenders, notificationsMigration, oauthWellKnownPaths, objectKey, parseColumns, parseRoles, passwordLength, pluginOptions, pluginsBeforeSignIn, pluginsFor, pluginsVariable, pngIcons, poolWaitMs, postgresDeviceStore, postgresHistoryStore, processor, pushMessage, queryRunnerMigration, readDbConnections, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readRecordTools, readSigningKey, readVapidSettings, readWriteQueryTool, readableResources, realtimeLimits, realtimeRelayMigration, recordOf, relayed, releaseManifest, removeDevicesWithUsers, removeHistoryWithUsers, removeMember, renderVariant, requestApproval, requireEnv, resourceChange, roleChoices, runInBackground, runReadOnlyQuery, runReadWriteQuery, runTurn, runtimeUrl, runtimeVariable, s3FileStore, seesAssistant, seesRuntime, sendNotification, sessionOf, setMemberRoles, setUserBanned, setUserRole, shownAppName, signInPolicyMethods, socketMessageCapOf, sourceOptions, sourcesFor, sourcesVariable, startErrorReporting, startJobs, storageCleanupSchedule, storageProvider, storeFile, storeUsage, streamChatCompletion, subscription, supabasePath, thumbHash, unauthorized, updateRecordTool, urgencies, vapidPrivateKeyVariable, vapidPublicKeyVariable, vapidSubjectVariable, variantPath, verifySignature, verifyStandardWebhook, waitUntil, wantsLongQueries, webManifestPath, webPushSender, webauthnPath, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps, writeRecordTools };
package/dist/index.js CHANGED
@@ -44,6 +44,7 @@ import { mcpToolContext } from "./mcp/mcp-context.js";
44
44
  import { mcpGate, sessionOf } from "./mcp/mcp-gate.js";
45
45
  import { mcpHandler } from "./mcp/mcp-handler.js";
46
46
  import { mcpRoutes } from "./mcp/mcp-routes.js";
47
+ import { mcpInstructions } from "./mcp/mcp-instructions.js";
47
48
  import { mcpServer } from "./mcp/mcp-server.js";
48
49
  import { countRecordsTool } from "./assistant/count-records-tool.js";
49
50
  import { describeResourceTool, getRecordTool, listRecordsTool, listResourcesTool, readRecordTools } from "./assistant/record-tools.js";
@@ -128,4 +129,4 @@ import { jobsDrainApp } from "./jobs/drain-route.js";
128
129
  import { composeRelease, releaseManifest } from "./mobile-release/release.js";
129
130
  import { mobileReleaseApp } from "./mobile-release/release-app.js";
130
131
  import { mobileSigningKeyVariable, readSigningKey } from "./mobile-release/signing-key.js";
131
- export { ConnectionsBusy, DeviceStoreError, FatalJobError, HistoryStoreError, HttpProblem, MissingCredentials, ModelError, NotificationSendError, PushMessageError, addAppRoleToOwners, addCommentTool, addMember, apiKeyCaller, apiKeySettings, apiKeyVariables, appNameOver, aspectRatio, assistantProtocolRoutes, assistantRoles, assistantSettings, assistantVariables, authSchemaDrift, authSchemaMigration, authStoreTables, backgroundSettled, badRequest, batchWriteTool, beforeSignInPluginsVariable, betterAuthTokens, capSocketMessages, changesMigration, checkAi, checkAuthSchema, checkChanges, checkComments, checkComputed, checkJobsSchema, checkNotificationsSchema, checkQueryRunner, checkRealtimeRelay, checkResourcesOutsideAuthStore, checkSourceNames, checkViewQueries, checkWebhooksSchema, coalesce, commentTools, commentsMigration, composeRelease, computedMigration, configExports, consoleAuditQueue, conversationKey, countRecordsTool, createAdmin, createConversations, createEncryptionTools, createFileCleanup, createOrganization, createRecordTool, createUser, defaultAppName, defaultHistoryPage, defaultSignInPolicy, defineEmail, defineFunction, defineJob, defineTool, deleteRecordTool, deleteUser, describeResourceTool, deviceIdParam, deviceStore, devicesPath, enqueueJob, errorReportingSettings, errorReportingVariable, eventMatcher, fileConversationStore, fileSize, fileType, forbidden, formatUri, functionApp, generateVapidKeys, getRecordTool, goTruePath, handleDroppedConnections, hasUsers, historyIdParam, historyIdPattern, historyLimits, historyPath, historyStore, honorSocketMessageCaps, imageSize, isBackgroundWork, isCaptured, isJobDefinition, isOAuthWellKnownPath, isSchedule, issueToken, jobDefinitions, jobsDrainApp, jobsSchema, jobsSchemaMigration, jwtAuthenticator, jwtVerifier, limitedFileStore, listCommentsTool, listOrganizations, listRecordsTool, listResourcesTool, listUsers, localFileStore, longQueryTimeoutMs, mapSettings, mapStyleUrl, mapStyleVariable, maxDevicesPerUser, maxHistoryPage, maxMessageBytes, maxRecipients, maxTokenTtlSeconds, maxTtlSeconds, maxUnreadCount, maxWidgetPropsBytes, mcpApprovals, mcpGate, mcpHandler, mcpIcons, mcpRoutes, mcpServer, mcpToolContext, mcpTools, migrationCommand, mobileReleaseApp, mobileSigningKeyVariable, newWebhookSecret, normalizeRoles, notFound, notificationSenders, notificationsMigration, oauthWellKnownPaths, objectKey, parseColumns, parseRoles, passwordLength, pluginOptions, pluginsBeforeSignIn, pluginsFor, pluginsVariable, pngIcons, poolWaitMs, postgresDeviceStore, postgresHistoryStore, processor, pushMessage, queryRunnerMigration, readDbConnections, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readRecordTools, readSigningKey, readVapidSettings, readWriteQueryTool, readableResources, realtimeLimits, realtimeRelayMigration, recordOf, relayed, releaseManifest, removeDevicesWithUsers, removeHistoryWithUsers, removeMember, renderVariant, requestApproval, requireEnv, resourceChange, roleChoices, runInBackground, runReadOnlyQuery, runReadWriteQuery, runTurn, runtimeUrl, runtimeVariable, s3FileStore, seesAssistant, seesRuntime, sendNotification, sessionOf, setMemberRoles, setUserBanned, setUserRole, shownAppName, signInPolicyMethods, socketMessageCapOf, sourceOptions, sourcesFor, sourcesVariable, startErrorReporting, startJobs, storageCleanupSchedule, storageProvider, storeFile, storeUsage, streamChatCompletion, subscription, supabasePath, thumbHash, unauthorized, updateRecordTool, urgencies, vapidPrivateKeyVariable, vapidPublicKeyVariable, vapidSubjectVariable, variantPath, verifySignature, verifyStandardWebhook, waitUntil, wantsLongQueries, webManifestPath, webPushSender, webauthnPath, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps, writeRecordTools };
132
+ export { ConnectionsBusy, DeviceStoreError, FatalJobError, HistoryStoreError, HttpProblem, MissingCredentials, ModelError, NotificationSendError, PushMessageError, addAppRoleToOwners, addCommentTool, addMember, apiKeyCaller, apiKeySettings, apiKeyVariables, appNameOver, aspectRatio, assistantProtocolRoutes, assistantRoles, assistantSettings, assistantVariables, authSchemaDrift, authSchemaMigration, authStoreTables, backgroundSettled, badRequest, batchWriteTool, beforeSignInPluginsVariable, betterAuthTokens, capSocketMessages, changesMigration, checkAi, checkAuthSchema, checkChanges, checkComments, checkComputed, checkJobsSchema, checkNotificationsSchema, checkQueryRunner, checkRealtimeRelay, checkResourcesOutsideAuthStore, checkSourceNames, checkViewQueries, checkWebhooksSchema, coalesce, commentTools, commentsMigration, composeRelease, computedMigration, configExports, consoleAuditQueue, conversationKey, countRecordsTool, createAdmin, createConversations, createEncryptionTools, createFileCleanup, createOrganization, createRecordTool, createUser, defaultAppName, defaultHistoryPage, defaultSignInPolicy, defineEmail, defineFunction, defineJob, defineTool, deleteRecordTool, deleteUser, describeResourceTool, deviceIdParam, deviceStore, devicesPath, enqueueJob, errorReportingSettings, errorReportingVariable, eventMatcher, fileConversationStore, fileSize, fileType, forbidden, formatUri, functionApp, generateVapidKeys, getRecordTool, goTruePath, handleDroppedConnections, hasUsers, historyIdParam, historyIdPattern, historyLimits, historyPath, historyStore, honorSocketMessageCaps, imageSize, isBackgroundWork, isCaptured, isJobDefinition, isOAuthWellKnownPath, isSchedule, issueToken, jobDefinitions, jobsDrainApp, jobsSchema, jobsSchemaMigration, jwtAuthenticator, jwtVerifier, limitedFileStore, listCommentsTool, listOrganizations, listRecordsTool, listResourcesTool, listUsers, localFileStore, longQueryTimeoutMs, mapSettings, mapStyleUrl, mapStyleVariable, maxDevicesPerUser, maxHistoryPage, maxMessageBytes, maxRecipients, maxTokenTtlSeconds, maxTtlSeconds, maxUnreadCount, maxWidgetPropsBytes, mcpApprovals, mcpGate, mcpHandler, mcpIcons, mcpInstructions, mcpRoutes, mcpServer, mcpToolContext, mcpTools, migrationCommand, mobileReleaseApp, mobileSigningKeyVariable, newWebhookSecret, normalizeRoles, notFound, notificationSenders, notificationsMigration, oauthWellKnownPaths, objectKey, parseColumns, parseRoles, passwordLength, pluginOptions, pluginsBeforeSignIn, pluginsFor, pluginsVariable, pngIcons, poolWaitMs, postgresDeviceStore, postgresHistoryStore, processor, pushMessage, queryRunnerMigration, readDbConnections, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readRecordTools, readSigningKey, readVapidSettings, readWriteQueryTool, readableResources, realtimeLimits, realtimeRelayMigration, recordOf, relayed, releaseManifest, removeDevicesWithUsers, removeHistoryWithUsers, removeMember, renderVariant, requestApproval, requireEnv, resourceChange, roleChoices, runInBackground, runReadOnlyQuery, runReadWriteQuery, runTurn, runtimeUrl, runtimeVariable, s3FileStore, seesAssistant, seesRuntime, sendNotification, sessionOf, setMemberRoles, setUserBanned, setUserRole, shownAppName, signInPolicyMethods, socketMessageCapOf, sourceOptions, sourcesFor, sourcesVariable, startErrorReporting, startJobs, storageCleanupSchedule, storageProvider, storeFile, storeUsage, streamChatCompletion, subscription, supabasePath, thumbHash, unauthorized, updateRecordTool, urgencies, vapidPrivateKeyVariable, vapidPublicKeyVariable, vapidSubjectVariable, variantPath, verifySignature, verifyStandardWebhook, waitUntil, wantsLongQueries, webManifestPath, webPushSender, webauthnPath, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps, writeRecordTools };
@@ -0,0 +1,4 @@
1
+ //#region src/mcp/mcp-instructions.d.ts
2
+ /** What `mcpServer` tells a client when it connects: how to read the app's records without pulling more than it needs. */
3
+ export declare const mcpInstructions: string;
4
+ //#endregion
@@ -0,0 +1,10 @@
1
+ //#region src/mcp/mcp-instructions.ts
2
+ /** What `mcpServer` tells a client when it connects: how to read the app's records without pulling more than it needs. */
3
+ const mcpInstructions = [
4
+ "Call list_resources first to find the resources, then describe_resource for one: it names the resource's fields, which ones filters and sorts take, and its list_fields.",
5
+ "Name the fields you need in fields, such as [\"id\", \"status\"], on list_records and get_record: a record can hold long texts. Without fields, list_records returns the list_fields, the columns of the resource's table in the app, and names the others in omitted_fields; [\"*\"] asks for every field. get_record returns every field unless told which.",
6
+ "Filter on fields marked filterable, the indexed ones, rather than reading pages to search them, and keep page_size small: follow next_page_token only when you need more. total_size_estimate is an estimate, not an exact count: count_records counts.",
7
+ "For example, the open tasks, newest first, ten at a time: list_records { \"resource\": \"tasks\", \"fields\": [\"id\", \"status\", \"title\"], \"filter\": \"status = \\\"open\\\"\", \"order_by\": \"created_at desc\", \"page_size\": 10 }, then get_record { \"resource\": \"tasks\", \"key\": \"42\", \"fields\": [\"brief\"] } for one long text."
8
+ ].join("\n");
9
+ //#endregion
10
+ export { mcpInstructions };
@@ -10,6 +10,8 @@ export type McpServerInput = {
10
10
  title?: string;
11
11
  icons?: Icon[];
12
12
  };
13
+ /** What the server tells clients about using it when they connect; `mcpInstructions`, on reading records, by default. */
14
+ instructions?: string;
13
15
  tools: AssistantTool[];
14
16
  /** What each tool gets as its context, for the caller of the request; `approve` comes from each call's own answers. */
15
17
  context: Omit<ToolContext, 'approve'>;
@@ -26,5 +28,5 @@ export type McpServerInput = {
26
28
  * counts only for the call it was asked for, once, while it lasts; for a user holding one of `rolesWithoutApproval` it
27
29
  * is approved at once, and the client is never asked.
28
30
  */
29
- export declare const mcpServer: ({ info, tools, context, report, rolesWithoutApproval, approvals }: McpServerInput) => McpServer;
31
+ export declare const mcpServer: ({ info, instructions, tools, context, report, rolesWithoutApproval, approvals }: McpServerInput) => McpServer;
30
32
  //#endregion
@@ -2,6 +2,7 @@ import { isStatementTimeout } from "../statement-timeout.js";
2
2
  import { checkedTools } from "../assistant/checked-tools.js";
3
3
  import { ApprovalNeeded, approvalAsked, approvedUnasked, mcpApproval, writesUnasked } from "./mcp-approval.js";
4
4
  import { callHash, callScope, scopeHash } from "./mcp-call-hash.js";
5
+ import { mcpInstructions } from "./mcp-instructions.js";
5
6
  import { CLIENT_CAPABILITIES_META_KEY, McpServer, fromJsonSchema } from "@modelcontextprotocol/server";
6
7
  //#region src/mcp/mcp-server.ts
7
8
  const capabilitiesOf = (envelope) => envelope?.[CLIENT_CAPABILITIES_META_KEY];
@@ -33,8 +34,8 @@ const stopped = (tool) => ({
33
34
  * counts only for the call it was asked for, once, while it lasts; for a user holding one of `rolesWithoutApproval` it
34
35
  * is approved at once, and the client is never asked.
35
36
  */
36
- const mcpServer = ({ info, tools, context, report, rolesWithoutApproval = [], approvals }) => {
37
- const server = new McpServer(info);
37
+ const mcpServer = ({ info, instructions = mcpInstructions, tools, context, report, rolesWithoutApproval = [], approvals }) => {
38
+ const server = new McpServer(info, { instructions });
38
39
  const unasked = writesUnasked(rolesWithoutApproval, context.session.user.roles);
39
40
  for (const tool of checkedTools(tools)) {
40
41
  const config = {
package/dist/package.js CHANGED
@@ -1,4 +1,4 @@
1
1
  //#region package.json
2
- var version = "0.53.1";
2
+ var version = "0.53.2";
3
3
  //#endregion
4
4
  export { version };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@protobase/server",
3
- "version": "0.53.1",
3
+ "version": "0.53.2",
4
4
  "description": "The Protobase REST API as a Hono app, with Better Auth sign-in.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -40,9 +40,9 @@
40
40
  "@better-auth/passkey": "^1.7.12",
41
41
  "@better-auth/sso": "^1.7.12",
42
42
  "@modelcontextprotocol/server": "^2.3.1",
43
- "@protobase/layout": "0.53.1",
44
- "@protobase/query": "0.53.1",
45
- "@protobase/schema": "0.53.1",
43
+ "@protobase/layout": "0.53.2",
44
+ "@protobase/query": "0.53.2",
45
+ "@protobase/schema": "0.53.2",
46
46
  "@react-email/render": "^2.1.0",
47
47
  "@scalar/hono-api-reference": "^0.12.10",
48
48
  "@sentry/core": "^11.7.0",