@emseepea/server 0.22.1 → 0.23.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -4
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +82 -6
- package/dist/index.js.map +1 -1
- package/dist/resource-inventory.d.ts +43 -0
- package/dist/resource-inventory.d.ts.map +1 -0
- package/dist/resource-inventory.js +157 -0
- package/dist/resource-inventory.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ProtocolError, type ListResourcesResult } from "@modelcontextprotocol/server";
|
|
2
|
+
import type { OperationContext, Principal } from "./index.js";
|
|
3
|
+
export interface ResourceInventoryEntry {
|
|
4
|
+
/** Unique immutable ASCII ordering key, including any tie-breaker. */
|
|
5
|
+
readonly key: string;
|
|
6
|
+
readonly resource: {
|
|
7
|
+
readonly uri: string;
|
|
8
|
+
readonly name: string;
|
|
9
|
+
readonly mimeType: string;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export interface ResourceInventoryPage {
|
|
13
|
+
readonly entries: readonly ResourceInventoryEntry[];
|
|
14
|
+
readonly hasMore: boolean;
|
|
15
|
+
}
|
|
16
|
+
export type ResourceInventoryHandler = (input: {
|
|
17
|
+
readonly after?: string;
|
|
18
|
+
readonly limit: number;
|
|
19
|
+
}, context: OperationContext & {
|
|
20
|
+
readonly principal: Principal;
|
|
21
|
+
}) => ResourceInventoryPage | Promise<ResourceInventoryPage>;
|
|
22
|
+
export interface InventorySource {
|
|
23
|
+
readonly name: string;
|
|
24
|
+
readonly uriTemplate: string;
|
|
25
|
+
readonly requiredScopes: readonly string[];
|
|
26
|
+
readonly matches: (uri: string) => boolean;
|
|
27
|
+
readonly list: ResourceInventoryHandler;
|
|
28
|
+
}
|
|
29
|
+
export declare class ResourceInventoryCursorError extends ProtocolError {
|
|
30
|
+
constructor();
|
|
31
|
+
}
|
|
32
|
+
/** Process-local encrypted cursors; no retained pages, snapshots, or cursor table. */
|
|
33
|
+
export declare function createResourceInventory(options: {
|
|
34
|
+
readonly sources: readonly InventorySource[];
|
|
35
|
+
readonly catalogue: unknown;
|
|
36
|
+
readonly serverInfo: unknown;
|
|
37
|
+
readonly pageSize: number;
|
|
38
|
+
readonly maxPageBytes: number;
|
|
39
|
+
readonly maxBackendBytes: number;
|
|
40
|
+
}): (cursor: string | undefined, staticEntries: readonly Readonly<Record<string, unknown>>[], context: OperationContext & {
|
|
41
|
+
readonly principal: Principal;
|
|
42
|
+
}) => Promise<ListResourcesResult>;
|
|
43
|
+
//# sourceMappingURL=resource-inventory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-inventory.d.ts","sourceRoot":"","sources":["../src/resource-inventory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAqB,KAAK,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAE1G,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE9D,MAAM,WAAW,sBAAsB;IACrC,sEAAsE;IACtE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/F;AACD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,OAAO,EAAE,SAAS,sBAAsB,EAAE,CAAC;IACpD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AACD,MAAM,MAAM,wBAAwB,GAAG,CACrC,KAAK,EAAE;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAC1D,OAAO,EAAE,gBAAgB,GAAG;IAAE,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAA;CAAE,KAC1D,qBAAqB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;AAC5D,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IAC3C,QAAQ,CAAC,IAAI,EAAE,wBAAwB,CAAC;CACzC;AACD,qBAAa,4BAA6B,SAAQ,aAAa;;CAE9D;AAsBD,sFAAsF;AACtF,wBAAgB,uBAAuB,CAAC,OAAO,EAAE;IAC/C,QAAQ,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,CAAC;IAC7C,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC,IA0CG,QAAQ,MAAM,GAAG,SAAS,EAC1B,eAAe,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,EAC3D,SAAS,gBAAgB,GAAG;IAAE,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAA;CAAE,KAC5D,OAAO,CAAC,mBAAmB,CAAC,CA6EhC"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { createCipheriv, createDecipheriv, createHash, randomBytes } from "node:crypto";
|
|
2
|
+
import { ProtocolError, ProtocolErrorCode } from "@modelcontextprotocol/server";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
export class ResourceInventoryCursorError extends ProtocolError {
|
|
5
|
+
constructor() { super(ProtocolErrorCode.InvalidParams, "Invalid pagination cursor; restart listing"); }
|
|
6
|
+
}
|
|
7
|
+
const lifetimeMs = 15 * 60 * 1000;
|
|
8
|
+
const positionSchema = z.strictObject({
|
|
9
|
+
source: z.number().int().nonnegative(),
|
|
10
|
+
offset: z.number().int().nonnegative(),
|
|
11
|
+
after: z.string().regex(/^[\x21-\x7e]{1,256}$/).optional(),
|
|
12
|
+
expires: z.number().int().positive(),
|
|
13
|
+
});
|
|
14
|
+
const pageSchema = z.strictObject({
|
|
15
|
+
entries: z.array(z.strictObject({
|
|
16
|
+
key: z.string().regex(/^[\x21-\x7e]{1,256}$/),
|
|
17
|
+
resource: z.strictObject({
|
|
18
|
+
uri: z.string().min(1).max(2048),
|
|
19
|
+
name: z.string().trim().min(1).max(512),
|
|
20
|
+
// oxlint-disable-next-line no-control-regex -- MIME metadata must not contain control characters.
|
|
21
|
+
mimeType: z.string().min(1).max(128).regex(/^[^\r\n\x00]+\/[^\r\n\x00]+$/),
|
|
22
|
+
}),
|
|
23
|
+
})).max(100),
|
|
24
|
+
hasMore: z.boolean(),
|
|
25
|
+
});
|
|
26
|
+
/** Process-local encrypted cursors; no retained pages, snapshots, or cursor table. */
|
|
27
|
+
export function createResourceInventory(options) {
|
|
28
|
+
if (Buffer.byteLength(JSON.stringify({ resources: [], resultType: "complete", ttlMs: 0,
|
|
29
|
+
cacheScope: "private", _meta: { "io.modelcontextprotocol/serverInfo": options.serverInfo } })) > options.maxPageBytes)
|
|
30
|
+
throw new TypeError("Resource inventory page bounds cannot fit an empty response");
|
|
31
|
+
const key = randomBytes(32);
|
|
32
|
+
const catalogue = createHash("sha256").update(JSON.stringify([
|
|
33
|
+
options.catalogue, options.sources.map(({ name, uriTemplate, requiredScopes }) => [name, uriTemplate, requiredScopes]), options.pageSize, options.maxPageBytes,
|
|
34
|
+
])).digest("hex");
|
|
35
|
+
function binding(principal) {
|
|
36
|
+
return createHash("sha256").update(JSON.stringify([
|
|
37
|
+
catalogue, principal.clientId, principal.subject ?? null, principal.resource ?? null,
|
|
38
|
+
[...principal.permissions].sort(),
|
|
39
|
+
])).digest();
|
|
40
|
+
}
|
|
41
|
+
function encode(position, aad) {
|
|
42
|
+
const nonce = randomBytes(12);
|
|
43
|
+
const cipher = createCipheriv("aes-256-gcm", key, nonce);
|
|
44
|
+
cipher.setAAD(aad);
|
|
45
|
+
const encrypted = Buffer.concat([cipher.update(JSON.stringify(position), "utf8"), cipher.final()]);
|
|
46
|
+
return Buffer.concat([nonce, cipher.getAuthTag(), encrypted]).toString("base64url");
|
|
47
|
+
}
|
|
48
|
+
function decode(cursor, aad, sources) {
|
|
49
|
+
try {
|
|
50
|
+
if (!/^[A-Za-z0-9_-]{1,1024}$/.test(cursor))
|
|
51
|
+
throw new Error();
|
|
52
|
+
const bytes = Buffer.from(cursor, "base64url");
|
|
53
|
+
if (bytes.toString("base64url") !== cursor || bytes.length < 29)
|
|
54
|
+
throw new Error();
|
|
55
|
+
const decipher = createDecipheriv("aes-256-gcm", key, bytes.subarray(0, 12));
|
|
56
|
+
decipher.setAAD(aad);
|
|
57
|
+
decipher.setAuthTag(bytes.subarray(12, 28));
|
|
58
|
+
const position = positionSchema.parse(JSON.parse(Buffer.concat([
|
|
59
|
+
decipher.update(bytes.subarray(28)), decipher.final(),
|
|
60
|
+
]).toString("utf8")));
|
|
61
|
+
if (position.expires <= Date.now() || position.expires > Date.now() + lifetimeMs ||
|
|
62
|
+
position.source >= sources || position.source === 0 && position.after !== undefined ||
|
|
63
|
+
position.source > 0 && position.offset !== 0)
|
|
64
|
+
throw new Error();
|
|
65
|
+
return position;
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
throw new ResourceInventoryCursorError();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return async (cursor, staticEntries, context) => {
|
|
72
|
+
const sources = options.sources.filter((source) => source.requiredScopes.every((scope) => context.principal.permissions.includes(scope)));
|
|
73
|
+
if (sources.length === 0)
|
|
74
|
+
throw new ProtocolError(ProtocolErrorCode.InvalidParams, "Resource inventory unavailable");
|
|
75
|
+
const aad = binding(context.principal);
|
|
76
|
+
let position = cursor === undefined
|
|
77
|
+
? { source: 0, offset: 0, expires: Date.now() + lifetimeMs }
|
|
78
|
+
: decode(cursor, aad, sources.length + 1);
|
|
79
|
+
const resources = [];
|
|
80
|
+
const seen = new Set();
|
|
81
|
+
const output = (next) => ({
|
|
82
|
+
resources,
|
|
83
|
+
...(next ? { nextCursor: encode(next, aad) } : {}),
|
|
84
|
+
});
|
|
85
|
+
const fits = (entry, next) => Buffer.byteLength(JSON.stringify({
|
|
86
|
+
...output(next), resources: [...resources, entry],
|
|
87
|
+
resultType: "complete", ttlMs: 0, cacheScope: "private",
|
|
88
|
+
_meta: { "io.modelcontextprotocol/serverInfo": options.serverInfo },
|
|
89
|
+
}), "utf8") <= options.maxPageBytes;
|
|
90
|
+
const append = (entry, next) => {
|
|
91
|
+
if (!fits(entry, next)) {
|
|
92
|
+
if (resources.length === 0)
|
|
93
|
+
throw new Error("Inventory entry exceeds page bounds");
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
const uri = entry.uri;
|
|
97
|
+
if (seen.has(uri))
|
|
98
|
+
throw new Error("Duplicate inventory URI");
|
|
99
|
+
seen.add(uri);
|
|
100
|
+
resources.push(entry);
|
|
101
|
+
return true;
|
|
102
|
+
};
|
|
103
|
+
while (position.source <= sources.length) {
|
|
104
|
+
context.signal.throwIfAborted();
|
|
105
|
+
if (Date.now() >= context.deadlineMs)
|
|
106
|
+
throw new Error("Inventory deadline exceeded");
|
|
107
|
+
if (position.source === 0) {
|
|
108
|
+
if (position.offset > staticEntries.length)
|
|
109
|
+
throw new Error("Invalid static inventory position");
|
|
110
|
+
while (position.offset < staticEntries.length) {
|
|
111
|
+
const next = { source: 0, offset: position.offset + 1, expires: position.expires };
|
|
112
|
+
if (!append(staticEntries[position.offset], next))
|
|
113
|
+
return output(position);
|
|
114
|
+
position = next;
|
|
115
|
+
if (resources.length === options.pageSize)
|
|
116
|
+
return output(position);
|
|
117
|
+
}
|
|
118
|
+
position = { source: 1, offset: 0, expires: position.expires };
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
const source = sources[position.source - 1];
|
|
122
|
+
const limit = options.pageSize - resources.length;
|
|
123
|
+
const raw = await source.list(Object.freeze({ after: position.after, limit }), context);
|
|
124
|
+
context.signal.throwIfAborted();
|
|
125
|
+
const serialized = JSON.stringify(raw);
|
|
126
|
+
if (serialized === undefined || Buffer.byteLength(serialized) > options.maxBackendBytes)
|
|
127
|
+
throw new Error("Inventory backend result exceeds bounds");
|
|
128
|
+
const page = pageSchema.parse(JSON.parse(serialized));
|
|
129
|
+
if (page.entries.length > limit || page.hasMore && page.entries.length === 0)
|
|
130
|
+
throw new Error("Invalid inventory backend page");
|
|
131
|
+
let previous = position.after;
|
|
132
|
+
const batchUris = new Set();
|
|
133
|
+
for (const entry of page.entries) {
|
|
134
|
+
if (previous !== undefined && entry.key <= previous || !source.matches(entry.resource.uri) ||
|
|
135
|
+
batchUris.has(entry.resource.uri))
|
|
136
|
+
throw new Error("Invalid inventory ordering or URI");
|
|
137
|
+
new URL(entry.resource.uri);
|
|
138
|
+
batchUris.add(entry.resource.uri);
|
|
139
|
+
previous = entry.key;
|
|
140
|
+
}
|
|
141
|
+
for (const [index, entry] of page.entries.entries()) {
|
|
142
|
+
const hasNext = index + 1 < page.entries.length || page.hasMore || position.source < sources.length;
|
|
143
|
+
const next = { source: position.source, offset: 0, after: entry.key, expires: position.expires };
|
|
144
|
+
if (!append(entry.resource, hasNext ? next : undefined))
|
|
145
|
+
return output(position);
|
|
146
|
+
position = next;
|
|
147
|
+
}
|
|
148
|
+
if (page.hasMore)
|
|
149
|
+
return output(position);
|
|
150
|
+
position = { source: position.source + 1, offset: 0, expires: position.expires };
|
|
151
|
+
if (resources.length === options.pageSize)
|
|
152
|
+
return output(position.source <= sources.length ? position : undefined);
|
|
153
|
+
}
|
|
154
|
+
return output();
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=resource-inventory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-inventory.js","sourceRoot":"","sources":["../src/resource-inventory.ts"],"names":[],"mappings":"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"}
|