@telepath-computer/autofile 0.0.0-stage → 0.4.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.
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Registers and checks Autofile's JSON Schemas with the explicitly selected
3
+ * 2020-12 dialect. The registry is process-global, so schemas are addressed by
4
+ * content and compiled once even when several store instances read them.
5
+ */
6
+ import "@hyperjump/json-schema/formats";
7
+ import { type JsonObject, type JsonValue } from "./json.js";
8
+ /** A compiled schema that returns all readable validation problems. */
9
+ export interface PreparedSchema {
10
+ validate(value: JsonValue): Promise<string[]>;
11
+ formatFields(value: JsonValue, format: "uri" | "blob"): FormatField[];
12
+ }
13
+ /** One instance value reached by a schema's `format` annotation. */
14
+ export interface FormatField {
15
+ pointer: string;
16
+ location: string;
17
+ value: JsonValue;
18
+ }
19
+ /** Checks that a declaration schema is safe, valid 2020-12 JSON Schema. */
20
+ export declare function prepareSchema(schema: JsonObject): Promise<PreparedSchema>;
21
+ /** A user-correctable problem in a proposed schema declaration. */
22
+ export declare class SchemaRefusal extends Error {
23
+ readonly messages: string[];
24
+ constructor(messages: string[]);
25
+ }
package/dist/schema.js ADDED
@@ -0,0 +1,241 @@
1
+ /**
2
+ * Registers and checks Autofile's JSON Schemas with the explicitly selected
3
+ * 2020-12 dialect. The registry is process-global, so schemas are addressed by
4
+ * content and compiled once even when several store instances read them.
5
+ */
6
+ import { createHash } from "node:crypto";
7
+ import "@hyperjump/json-schema/formats";
8
+ import { InvalidSchemaError, registerSchema, setMetaSchemaOutputFormat, setShouldValidateFormat, unregisterSchema, validate, } from "@hyperjump/json-schema/draft-2020-12";
9
+ import { addFormat, setFormatHandler } from "@hyperjump/json-schema/experimental";
10
+ import { annotate } from "@hyperjump/json-schema/annotations/experimental";
11
+ import { annotatedWith, annotation, value as instanceValue, } from "@hyperjump/json-schema/annotated-instance/experimental";
12
+ import { JSE } from "@hyperjump/json-schema-errors";
13
+ import { BLOB_URI_PATTERN } from "./blobs.js";
14
+ import { jsonObjectProblem } from "./json.js";
15
+ const DIALECT = "https://json-schema.org/draft/2020-12/schema";
16
+ const FORMAT_KEYWORD = "https://json-schema.org/keyword/draft-2020-12/format";
17
+ const BLOB_FORMAT = "https://autofile.dev/formats/blob";
18
+ const knownFormats = new Set([
19
+ "date-time",
20
+ "date",
21
+ "time",
22
+ "duration",
23
+ "email",
24
+ "idn-email",
25
+ "hostname",
26
+ "idn-hostname",
27
+ "ipv4",
28
+ "ipv6",
29
+ "uri",
30
+ "uri-reference",
31
+ "iri",
32
+ "iri-reference",
33
+ "uuid",
34
+ "uri-template",
35
+ "json-pointer",
36
+ "relative-json-pointer",
37
+ "regex",
38
+ "blob",
39
+ ]);
40
+ const schemaMapKeywords = ["$defs", "properties", "patternProperties", "dependentSchemas"];
41
+ const schemaArrayKeywords = ["allOf", "anyOf", "oneOf", "prefixItems"];
42
+ const schemaKeywords = [
43
+ "items",
44
+ "contains",
45
+ "additionalProperties",
46
+ "unevaluatedItems",
47
+ "unevaluatedProperties",
48
+ "propertyNames",
49
+ "if",
50
+ "then",
51
+ "else",
52
+ "not",
53
+ "contentSchema",
54
+ ];
55
+ const preparedSchemas = new Map();
56
+ setShouldValidateFormat(true);
57
+ // json-schema-errors augments the package root's TypeScript declarations, but
58
+ // the draft-specific entry point does not expose that augmentation.
59
+ setMetaSchemaOutputFormat(JSE);
60
+ addFormat({
61
+ id: BLOB_FORMAT,
62
+ // JSON Schema formats ignore other instance types. Autofile's separate
63
+ // annotation check gives URI and blob values their stricter string rule.
64
+ handler: (value) => typeof value !== "string" || BLOB_URI_PATTERN.test(value),
65
+ });
66
+ setFormatHandler(FORMAT_KEYWORD, "blob", BLOB_FORMAT);
67
+ /** Checks that a declaration schema is safe, valid 2020-12 JSON Schema. */
68
+ export async function prepareSchema(schema) {
69
+ // Parsed files can contain overflowing numbers or negative zero too. Check
70
+ // every schema before serialization can change its constants or cache key.
71
+ const problem = jsonObjectProblem(schema);
72
+ if (problem !== undefined)
73
+ throw new SchemaRefusal([`schema: ${problem}`]);
74
+ const inspectionErrors = inspectSchema(schema);
75
+ if (inspectionErrors.length > 0)
76
+ throw new SchemaRefusal(inspectionErrors);
77
+ const serialized = JSON.stringify(schema);
78
+ const digest = createHash("sha256").update(serialized).digest("hex");
79
+ const schemaUri = `https://autofile.dev/schemas/${digest}`;
80
+ let prepared = preparedSchemas.get(schemaUri);
81
+ if (prepared === undefined) {
82
+ prepared = compileSchema(schema, schemaUri);
83
+ preparedSchemas.set(schemaUri, prepared);
84
+ prepared.catch(() => preparedSchemas.delete(schemaUri));
85
+ }
86
+ return prepared;
87
+ }
88
+ /** A user-correctable problem in a proposed schema declaration. */
89
+ export class SchemaRefusal extends Error {
90
+ messages;
91
+ constructor(messages) {
92
+ super(messages.join("; "));
93
+ this.name = "SchemaRefusal";
94
+ this.messages = messages;
95
+ }
96
+ }
97
+ async function compileSchema(schema, schemaUri) {
98
+ let registered = false;
99
+ try {
100
+ registerSchema(schema, schemaUri, DIALECT);
101
+ registered = true;
102
+ const validator = await validate(schemaUri);
103
+ const annotator = await annotate(schemaUri);
104
+ return {
105
+ validate: (value) => validateValue(validator, annotator, value),
106
+ formatFields: (value, format) => findFormatFields(annotator, value, format),
107
+ };
108
+ }
109
+ catch (error) {
110
+ if (registered)
111
+ unregisterSchema(schemaUri);
112
+ if (error instanceof InvalidSchemaError) {
113
+ const output = error.output;
114
+ throw new SchemaRefusal(formatErrors(output.valid ? [] : output.errors, "schema"));
115
+ }
116
+ throw new SchemaRefusal([
117
+ error instanceof Error ? `schema: ${error.message}` : `schema: ${String(error)}`,
118
+ ]);
119
+ }
120
+ }
121
+ function findFormatFields(annotator, value, format) {
122
+ const fields = [];
123
+ const annotated = annotator(value);
124
+ for (const node of annotatedWith(annotated, "format", DIALECT)) {
125
+ if (!annotation(node, "format", DIALECT).includes(format))
126
+ continue;
127
+ const pointer = node.pointer;
128
+ fields.push({
129
+ pointer,
130
+ location: formatInstancePointer(pointer),
131
+ value: instanceValue(node),
132
+ });
133
+ }
134
+ return fields;
135
+ }
136
+ async function validateValue(validator, annotator, value) {
137
+ const output = validator(value, {
138
+ outputFormat: JSE,
139
+ });
140
+ if (!output.valid)
141
+ return formatErrors(output.errors, "");
142
+ // JSON Schema deliberately ignores `format` for non-strings. Autofile's
143
+ // field model is stricter: anything annotated as a URI or blob is a string.
144
+ const annotated = annotator(value);
145
+ const errors = [];
146
+ for (const node of annotatedWith(annotated, "format", DIALECT)) {
147
+ const formats = annotation(node, "format", DIALECT);
148
+ if (formats.some((format) => format === "uri" || format === "blob")
149
+ && typeof instanceValue(node) !== "string") {
150
+ const location = formatInstancePointer(node.pointer);
151
+ errors.push(location === "" ? "must be a string" : `${location}: must be a string`);
152
+ }
153
+ }
154
+ return errors;
155
+ }
156
+ function inspectSchema(schema) {
157
+ const errors = [];
158
+ inspectSubschema(schema, "schema", errors, true, new WeakSet());
159
+ return errors;
160
+ }
161
+ function inspectSubschema(schema, location, errors, isRoot, inspected) {
162
+ if (!isObject(schema))
163
+ return;
164
+ if (inspected.has(schema))
165
+ return;
166
+ inspected.add(schema);
167
+ if (schema.$schema !== undefined) {
168
+ if (!isRoot)
169
+ errors.push(`${location}.$schema: is only allowed at the schema root`);
170
+ else if (schema.$schema !== DIALECT) {
171
+ errors.push(`${location}.$schema: must name ${DIALECT}`);
172
+ }
173
+ }
174
+ if (typeof schema.format === "string" && !knownFormats.has(schema.format)) {
175
+ errors.push(`${location}.format: unknown format ${JSON.stringify(schema.format)}`);
176
+ }
177
+ for (const keyword of ["$ref", "$dynamicRef"]) {
178
+ const reference = schema[keyword];
179
+ if (typeof reference === "string"
180
+ && reference !== ""
181
+ && !reference.startsWith("#")) {
182
+ errors.push(`${location}.${keyword}: must point within this schema`);
183
+ }
184
+ }
185
+ for (const keyword of schemaMapKeywords) {
186
+ const schemas = schema[keyword];
187
+ if (!isObject(schemas))
188
+ continue;
189
+ for (const [name, subschema] of Object.entries(schemas)) {
190
+ inspectSubschema(subschema, `${location}.${keyword}.${name}`, errors, false, inspected);
191
+ }
192
+ }
193
+ for (const keyword of schemaArrayKeywords) {
194
+ const schemas = schema[keyword];
195
+ if (!Array.isArray(schemas))
196
+ continue;
197
+ schemas.forEach((subschema, index) => {
198
+ inspectSubschema(subschema, `${location}.${keyword}.${String(index)}`, errors, false, inspected);
199
+ });
200
+ }
201
+ for (const keyword of schemaKeywords) {
202
+ if (schema[keyword] !== undefined) {
203
+ inspectSubschema(schema[keyword], `${location}.${keyword}`, errors, false, inspected);
204
+ }
205
+ }
206
+ }
207
+ function formatErrors(errors, prefix) {
208
+ return errors.map((error) => {
209
+ const location = formatInstanceLocation(error.instanceLocation);
210
+ const path = [prefix, location].filter((part) => part !== "").join(".");
211
+ const message = error.message.length === 0
212
+ ? "does not match the schema"
213
+ : `${error.message[0]?.toLowerCase() ?? ""}${error.message.slice(1)}`;
214
+ return path === "" ? message : `${path}: ${message}`;
215
+ });
216
+ }
217
+ function formatInstanceLocation(location) {
218
+ const hash = location.indexOf("#");
219
+ const fragment = hash === -1 ? location : location.slice(hash + 1);
220
+ if (fragment === "" || fragment === "/")
221
+ return "";
222
+ const pointer = decodeURIComponent(fragment).replace(/^\//u, "");
223
+ return pointer
224
+ .split("/")
225
+ .map((part) => part.replaceAll("~1", "/").replaceAll("~0", "~"))
226
+ .join(".");
227
+ }
228
+ function formatInstancePointer(pointer) {
229
+ if (pointer === "")
230
+ return "";
231
+ const parts = pointer.slice(1).split("/");
232
+ if (parts.some((part) => part === ""))
233
+ return pointer;
234
+ return parts
235
+ .map((part) => part.replaceAll("~1", "/").replaceAll("~0", "~"))
236
+ .join(".");
237
+ }
238
+ function isObject(value) {
239
+ return typeof value === "object" && value !== null && !Array.isArray(value);
240
+ }
241
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Builds Autofile's transport-independent MCP server. The store owns all
3
+ * persistence semantics; this module only describes the protocol surface and
4
+ * translates plain store values into MCP results.
5
+ */
6
+ import { McpServer } from "@modelcontextprotocol/server";
7
+ import type { Autofile } from "./index.js";
8
+ /** Builds one MCP server around a store, without choosing its transport. */
9
+ export declare function buildServer(autofile: Autofile): Promise<McpServer>;
package/dist/server.js ADDED
@@ -0,0 +1,257 @@
1
+ /**
2
+ * Builds Autofile's transport-independent MCP server. The store owns all
3
+ * persistence semantics; this module only describes the protocol surface and
4
+ * translates plain store values into MCP results.
5
+ */
6
+ import { createRequire } from "node:module";
7
+ import { fromJsonSchema, McpServer, ProtocolError, ProtocolErrorCode, ResourceNotFoundError, } from "@modelcontextprotocol/server";
8
+ import { buildTools, } from "./mcp-tools.js";
9
+ import { buildResources, isResourceUri } from "./mcp-resources.js";
10
+ const SERVER_DESCRIPTION = "Typed records that agents file and retrieve.";
11
+ const BASE_INSTRUCTIONS = "Autofile is where the user keeps durable information, as typed records. When information should outlive the current task, file it here. Call `list_types` to see the types and what belongs in each, and `get_type` for the schema of one. Search with `find_records` before creating a record, so the same thing is not filed twice. If no type fits, propose a new type to the user and create it only once they agree.";
12
+ const RESOURCE_PAGE_SIZE = 100;
13
+ const packageJson = createRequire(import.meta.url)("../package.json");
14
+ const findRecordsSchema = fromJsonSchema({
15
+ type: "object",
16
+ properties: {
17
+ type: {
18
+ type: ["string", "array"],
19
+ items: { type: "string" },
20
+ description: "The type or types to search. All types when absent.",
21
+ },
22
+ q: {
23
+ type: "string",
24
+ description: "Words that must all appear, ignoring case, in the string values of a record at any depth.",
25
+ },
26
+ where: {
27
+ type: "object",
28
+ description: "Fields to match by value using MongoDB query syntax. An array field matches when any item equals the value, and `null` also matches a missing field. Keys starting with `$`, and the keys `__proto__`, `constructor` and `prototype`, are not supported at any depth or in dotted paths.",
29
+ },
30
+ limit: {
31
+ type: "integer",
32
+ minimum: 1,
33
+ maximum: 200,
34
+ default: 50,
35
+ description: "The most results the page returns, counting records and entries in `errors`. From 1 to 200; defaults to 50.",
36
+ },
37
+ fields: {
38
+ type: "array",
39
+ items: { type: "string", minLength: 1 },
40
+ description: "Top-level fields to return in `value`. All fields are returned when absent; matching still uses the whole record.",
41
+ },
42
+ cursor: {
43
+ type: "string",
44
+ description: "An opaque cursor returned by the previous page. The next page starts after the last record that page considered, even if that record was deleted.",
45
+ },
46
+ },
47
+ additionalProperties: false,
48
+ });
49
+ const getRecordSchema = fromJsonSchema({
50
+ type: "object",
51
+ properties: { uri: { type: "string", description: "The URI of the record." } },
52
+ required: ["uri"],
53
+ additionalProperties: false,
54
+ });
55
+ const createRecordSchema = fromJsonSchema({
56
+ type: "object",
57
+ properties: {
58
+ type: { type: "string", description: "The type of the record." },
59
+ key: {
60
+ type: "string",
61
+ description: "The key of the new record: lowercase letters, digits and hyphens, starting with a letter or digit. Generated when absent.",
62
+ },
63
+ record: {
64
+ type: "object",
65
+ description: "The full record, which must match the schema of its type. Blob fields hold existing blob URIs returned by `upload_blob`; the same URI may be used by multiple records.",
66
+ },
67
+ },
68
+ required: ["type", "record"],
69
+ additionalProperties: false,
70
+ });
71
+ const updateRecordSchema = fromJsonSchema({
72
+ type: "object",
73
+ properties: {
74
+ uri: { type: "string", description: "The URI of the record." },
75
+ patch: {
76
+ type: "object",
77
+ description: "A [JSON Merge Patch](https://www.rfc-editor.org/rfc/rfc7396): fields in the patch are set, a field set to `null` is removed, nested objects are merged, and arrays are replaced whole. Blob fields hold existing blob URIs returned by `upload_blob`; the same URI may be used by multiple records.",
78
+ },
79
+ },
80
+ required: ["uri", "patch"],
81
+ additionalProperties: false,
82
+ });
83
+ const uploadBlobSchema = fromJsonSchema({
84
+ type: "object",
85
+ properties: {
86
+ base64: { type: "string", description: "Canonical base64 contents. Requires mediaType; cannot be combined with path." },
87
+ path: { type: "string", description: "An absolute local file path, accepted only over stdio. Cannot be combined with base64." },
88
+ mediaType: { type: "string", description: "The media type of the contents. Required for base64; inferred from the file extension for a path when absent, falling back to application/octet-stream." },
89
+ },
90
+ additionalProperties: false,
91
+ });
92
+ const deleteRecordSchema = fromJsonSchema({
93
+ type: "object",
94
+ properties: { uri: { type: "string", description: "The URI of the record." } },
95
+ required: ["uri"],
96
+ additionalProperties: false,
97
+ });
98
+ const listTypesSchema = fromJsonSchema({
99
+ type: "object",
100
+ properties: {},
101
+ additionalProperties: false,
102
+ });
103
+ const getTypeSchema = fromJsonSchema({
104
+ type: "object",
105
+ properties: { type: { type: "string", description: "The name of the type." } },
106
+ required: ["type"],
107
+ additionalProperties: false,
108
+ });
109
+ const createTypeSchema = fromJsonSchema({
110
+ type: "object",
111
+ properties: {
112
+ type: { type: "string", description: "The name of the type." },
113
+ description: { type: "string", description: "What belongs in the type." },
114
+ schema: { type: "object", description: "The JSON Schema for records of the type." },
115
+ titleField: {
116
+ type: "string",
117
+ description: "A top-level field of the record whose string value is shown as its title.",
118
+ },
119
+ title: {
120
+ type: "string",
121
+ description: "The name of the type in words, in the singular, such as \"Journal entry\", shown to people in place of the type name.",
122
+ },
123
+ },
124
+ required: ["type", "description", "schema"],
125
+ additionalProperties: false,
126
+ });
127
+ const updateTypeSchema = fromJsonSchema({
128
+ type: "object",
129
+ properties: {
130
+ type: { type: "string", description: "The name of the type." },
131
+ description: { type: "string", description: "The new description." },
132
+ schema: { type: "object", description: "The new JSON Schema." },
133
+ titleField: {
134
+ type: ["string", "null"],
135
+ description: "The new title field; `null` removes it.",
136
+ },
137
+ title: {
138
+ type: ["string", "null"],
139
+ description: "The new title; `null` removes it.",
140
+ },
141
+ },
142
+ required: ["type"],
143
+ additionalProperties: false,
144
+ });
145
+ const deleteTypeSchema = fromJsonSchema({
146
+ type: "object",
147
+ properties: { type: { type: "string", description: "The name of the type." } },
148
+ required: ["type"],
149
+ additionalProperties: false,
150
+ });
151
+ /** Builds one MCP server around a store, without choosing its transport. */
152
+ export async function buildServer(autofile) {
153
+ const tools = buildTools(autofile);
154
+ const resources = buildResources(autofile);
155
+ const { types } = await tools.listTypes({});
156
+ const typeNames = types.map(({ type }) => type).sort();
157
+ const typeSummary = typeNames.length === 0 ? "none yet" : typeNames.join(", ");
158
+ const server = new McpServer({
159
+ name: "autofile",
160
+ version: packageJson.version,
161
+ description: SERVER_DESCRIPTION,
162
+ }, {
163
+ instructions: `${BASE_INSTRUCTIONS}\n\nTypes: ${typeSummary}. This list was taken when the session began; call \`list_types\` for types created since.`,
164
+ });
165
+ server.registerTool("find_records", {
166
+ description: "Searches records and returns matching records in URI order. It skips nonmatching records until the page has `limit` results, reaches 64 KB of JSON, or no records remain; the size cap never prevents the first result. `fields` selects top-level fields to return, while matching uses the whole record. A schema-invalid record is listed in `errors` only when it matches the search; a record that cannot be read is always listed. Autofile is where the user keeps durable information.",
167
+ inputSchema: findRecordsSchema,
168
+ }, async (input) => toolResult(await tools.findRecords(input)));
169
+ server.registerTool("get_record", {
170
+ description: "Returns one record by URI: its `uri`, optional `title`, `createdAt` and `updatedAt` times, and `value`. A record that does not match its type is still returned, with what must change in `error`.",
171
+ inputSchema: getRecordSchema,
172
+ }, async (input) => toolResult(await tools.getRecord(input)));
173
+ server.registerTool("create_record", {
174
+ description: "Creates a record and returns its URI. `record` is the full record and must match the schema of its type, which `get_type` returns. `key` is optional and generated when absent. Autofile is where the user keeps durable information.",
175
+ inputSchema: createRecordSchema,
176
+ }, async (input) => toolResult(await tools.createRecord(input)));
177
+ server.registerTool("update_record", { description: "Changes a record and returns its URI.", inputSchema: updateRecordSchema }, async (input) => toolResult(await tools.updateRecord(input)));
178
+ server.registerTool("upload_blob", {
179
+ description: "Uploads bytes and returns their blob URI for use in records. Supply canonical base64 and a media type, or an absolute local path over stdio. The maximum size is 7 MiB.",
180
+ inputSchema: uploadBlobSchema,
181
+ }, async (input, context) => toolResult(await tools.uploadBlob(input, { allowLocalPaths: context.http === undefined })));
182
+ server.registerTool("delete_record", {
183
+ description: "Deletes a record, removes the links to it from other records, and returns its URI.",
184
+ inputSchema: deleteRecordSchema,
185
+ }, async (input) => toolResult(await tools.deleteRecord(input)));
186
+ server.registerTool("list_types", {
187
+ description: "Returns every type, ordered by name, with the URI of its declaration, its description, and its `title` when it has one.",
188
+ inputSchema: listTypesSchema,
189
+ }, async (input) => toolResult(await tools.listTypes(input)));
190
+ server.registerTool("get_type", { description: "Returns the declaration of a type with its URI added.", inputSchema: getTypeSchema }, async (input) => toolResult(await tools.getType(input)));
191
+ server.registerTool("create_type", { description: "Declares a type and returns the URI of its declaration.", inputSchema: createTypeSchema }, async (input) => toolResult(await tools.createType(input)));
192
+ server.registerTool("update_type", {
193
+ description: "Replaces the description, schema, title field or title of a type, or any of them.",
194
+ inputSchema: updateTypeSchema,
195
+ }, async (input) => toolResult(await tools.updateType(input)));
196
+ server.registerTool("delete_type", { description: "Deletes a type and returns its URI.", inputSchema: deleteTypeSchema }, async (input) => toolResult(await tools.deleteType(input)));
197
+ // The high-level resource API returns every resource at once. These
198
+ // handlers stay at the low-level boundary where cursors remain explicit;
199
+ // the process-level watcher supplies the advertised change notices.
200
+ server.server.registerCapabilities({ resources: { subscribe: true, listChanged: true } });
201
+ server.server.setRequestHandler("resources/list", async (request) => {
202
+ const listed = await resources.listResources();
203
+ const cursor = request.params?.cursor;
204
+ let start = 0;
205
+ if (cursor !== undefined) {
206
+ const previousUri = decodeCursor(cursor);
207
+ if (previousUri === undefined) {
208
+ throw new ProtocolError(ProtocolErrorCode.InvalidParams, "Invalid resource cursor");
209
+ }
210
+ const nextIndex = listed.findIndex(({ uri }) => uri > previousUri);
211
+ start = nextIndex < 0 ? listed.length : nextIndex;
212
+ }
213
+ const page = listed.slice(start, start + RESOURCE_PAGE_SIZE);
214
+ const last = page.at(-1);
215
+ return {
216
+ resources: page,
217
+ ...(last !== undefined && start + page.length < listed.length
218
+ ? { nextCursor: encodeCursor(last.uri) }
219
+ : {}),
220
+ ttlMs: 0,
221
+ cacheScope: "private",
222
+ };
223
+ });
224
+ server.server.setRequestHandler("resources/read", async (request) => {
225
+ const contents = await resources.readResource(request.params.uri);
226
+ if (contents === undefined)
227
+ throw new ResourceNotFoundError(request.params.uri);
228
+ return { contents: [contents], ttlMs: 0, cacheScope: "private" };
229
+ });
230
+ return server;
231
+ }
232
+ function toolResult(result) {
233
+ const body = result;
234
+ return {
235
+ content: [{ type: "text", text: JSON.stringify(body) }],
236
+ structuredContent: body,
237
+ ...("errors" in body && !("uri" in body) && !("records" in body) ? { isError: true } : {}),
238
+ };
239
+ }
240
+ function encodeCursor(uri) {
241
+ return Buffer.from(uri, "utf8").toString("base64url");
242
+ }
243
+ function decodeCursor(cursor) {
244
+ if (!/^[A-Za-z0-9_-]+$/u.test(cursor))
245
+ return undefined;
246
+ const bytes = Buffer.from(cursor, "base64url");
247
+ if (bytes.toString("base64url") !== cursor)
248
+ return undefined;
249
+ try {
250
+ const uri = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
251
+ return isResourceUri(uri) ? uri : undefined;
252
+ }
253
+ catch {
254
+ return undefined;
255
+ }
256
+ }
257
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}