@knitli/openapi-mcp 0.0.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/LICENSE-APACHE +202 -0
- package/LICENSE-MIT +21 -0
- package/README.md +362 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +249 -0
- package/dist/compile.d.ts +14 -0
- package/dist/compile.js +132 -0
- package/dist/compiler.d.ts +13 -0
- package/dist/compiler.js +7 -0
- package/dist/conformance/fixtures.d.ts +24 -0
- package/dist/conformance/fixtures.js +119 -0
- package/dist/conformance/index.d.ts +2 -0
- package/dist/conformance/index.js +2 -0
- package/dist/conformance/runtime-suite.d.ts +31 -0
- package/dist/conformance/runtime-suite.js +343 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/load.d.ts +31 -0
- package/dist/load.js +20 -0
- package/dist/operations.d.ts +27 -0
- package/dist/operations.js +231 -0
- package/dist/permissions.d.ts +31 -0
- package/dist/permissions.js +89 -0
- package/dist/release/compile-release.d.ts +33 -0
- package/dist/release/compile-release.js +1620 -0
- package/dist/release/load-v4.d.ts +29 -0
- package/dist/release/load-v4.js +297 -0
- package/dist/release/manifest-builder.d.ts +19 -0
- package/dist/release/manifest-builder.js +28 -0
- package/dist/release/publish.d.ts +45 -0
- package/dist/release/publish.js +346 -0
- package/dist/release/reference-map.d.ts +53 -0
- package/dist/release/reference-map.js +347 -0
- package/dist/release/schema-v4.d.ts +5 -0
- package/dist/release/schema-v4.js +91 -0
- package/dist/runtime/action-permit.d.ts +11 -0
- package/dist/runtime/action-permit.js +1 -0
- package/dist/runtime/classify.d.ts +16 -0
- package/dist/runtime/classify.js +279 -0
- package/dist/runtime/credential-binding.d.ts +3 -0
- package/dist/runtime/credential-binding.js +101 -0
- package/dist/runtime/digest.d.ts +8 -0
- package/dist/runtime/digest.js +80 -0
- package/dist/runtime/errors.d.ts +14 -0
- package/dist/runtime/errors.js +15 -0
- package/dist/runtime/index.d.ts +20 -0
- package/dist/runtime/index.js +14 -0
- package/dist/runtime/manifest.d.ts +33 -0
- package/dist/runtime/manifest.js +489 -0
- package/dist/runtime/prepared-call.d.ts +39 -0
- package/dist/runtime/prepared-call.js +566 -0
- package/dist/runtime/references.d.ts +7 -0
- package/dist/runtime/references.js +197 -0
- package/dist/runtime/runtime.d.ts +25 -0
- package/dist/runtime/runtime.js +1272 -0
- package/dist/runtime/schema-keywords.d.ts +2 -0
- package/dist/runtime/schema-keywords.js +30 -0
- package/dist/runtime/schema-resolver.d.ts +10 -0
- package/dist/runtime/schema-resolver.js +237 -0
- package/dist/runtime/serialize.d.ts +12 -0
- package/dist/runtime/serialize.js +877 -0
- package/dist/runtime/store.d.ts +52 -0
- package/dist/runtime/store.js +582 -0
- package/dist/runtime/strict-json.d.ts +19 -0
- package/dist/runtime/strict-json.js +539 -0
- package/dist/runtime/types.d.ts +457 -0
- package/dist/runtime/types.js +1 -0
- package/dist/runtime/verify-record.d.ts +6 -0
- package/dist/runtime/verify-record.js +492 -0
- package/dist/runtime/versions.d.ts +63 -0
- package/dist/runtime/versions.js +86 -0
- package/dist/safety.d.ts +28 -0
- package/dist/safety.js +60 -0
- package/dist/schema.d.ts +5 -0
- package/dist/schema.js +52 -0
- package/dist/schemas.d.ts +9 -0
- package/dist/schemas.js +16 -0
- package/dist/sign.d.ts +20 -0
- package/dist/sign.js +55 -0
- package/dist/sqlite/auth.d.ts +33 -0
- package/dist/sqlite/auth.js +973 -0
- package/dist/sqlite/catalog-store.d.ts +20 -0
- package/dist/sqlite/catalog-store.js +370 -0
- package/dist/sqlite/destination-guard.d.ts +24 -0
- package/dist/sqlite/destination-guard.js +140 -0
- package/dist/sqlite/generation-store.d.ts +12 -0
- package/dist/sqlite/generation-store.js +721 -0
- package/dist/sqlite/guarded-fetch.d.ts +24 -0
- package/dist/sqlite/guarded-fetch.js +626 -0
- package/dist/sqlite/index.d.ts +5 -0
- package/dist/sqlite/index.js +5 -0
- package/dist/sqlite/oauth-resource.d.ts +2 -0
- package/dist/sqlite/oauth-resource.js +15 -0
- package/dist/sqlite/release-completion.d.ts +5 -0
- package/dist/sqlite/release-completion.js +80 -0
- package/dist/stdio/action-broker.d.ts +15 -0
- package/dist/stdio/action-broker.js +136 -0
- package/dist/stdio/authorizer.d.ts +30 -0
- package/dist/stdio/authorizer.js +484 -0
- package/dist/stdio/config.d.ts +77 -0
- package/dist/stdio/config.js +144 -0
- package/dist/stdio/exact-policy.d.ts +41 -0
- package/dist/stdio/exact-policy.js +361 -0
- package/dist/stdio/index.d.ts +6 -0
- package/dist/stdio/index.js +148 -0
- package/dist/stdio/render.d.ts +8 -0
- package/dist/stdio/render.js +253 -0
- package/dist/stdio/request-state.d.ts +18 -0
- package/dist/stdio/request-state.js +79 -0
- package/dist/stdio/search.d.ts +10 -0
- package/dist/stdio/search.js +76 -0
- package/dist/stdio/server.d.ts +29 -0
- package/dist/stdio/server.js +309 -0
- package/dist/types.d.ts +32 -0
- package/dist/types.js +1 -0
- package/package.json +131 -0
package/dist/safety.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
const READ_METHODS = new Set(["GET", "HEAD"]);
|
|
2
|
+
/**
|
|
3
|
+
* Operation-id suffixes that are POSTs by protocol but reads by semantics,
|
|
4
|
+
* keyed by the API they were derived from. Scoping is load-bearing, not
|
|
5
|
+
* tidiness: `preview` and `query` are generic enough that another mounted API
|
|
6
|
+
* will have a genuinely mutating `POST .../query`, and a global list would
|
|
7
|
+
* classify it `read` — reachable through the no-approval read tool. An API
|
|
8
|
+
* with no entry here gets no overrides, so mutating methods stay `write`.
|
|
9
|
+
*
|
|
10
|
+
* This table is engine code, not artifact data: the server recomputes safety
|
|
11
|
+
* at load and honours a stored `read` on a mutating method only if the same
|
|
12
|
+
* `(api, suffix)` pair appears here.
|
|
13
|
+
*/
|
|
14
|
+
export const READ_OVERRIDES = {
|
|
15
|
+
graph: [
|
|
16
|
+
"getByIds",
|
|
17
|
+
"getMemberGroups",
|
|
18
|
+
"getMemberObjects",
|
|
19
|
+
"checkMemberGroups",
|
|
20
|
+
"checkMemberObjects",
|
|
21
|
+
"getAvailableExtensionProperties",
|
|
22
|
+
"findMeetingTimes",
|
|
23
|
+
"getSchedule",
|
|
24
|
+
"translateExchangeIds",
|
|
25
|
+
"preview",
|
|
26
|
+
"query",
|
|
27
|
+
],
|
|
28
|
+
};
|
|
29
|
+
/** A batch endpoint bundles arbitrary sub-request methods, so it is never a read. */
|
|
30
|
+
export function isBatch(path) {
|
|
31
|
+
return path === "/$batch" || path.endsWith("/$batch");
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Classifies an operation as read or write. Method is the default; the
|
|
35
|
+
* API's own override list corrects semantically-read POSTs. `$batch` always
|
|
36
|
+
* wins, and an unrecognised API never gets an override.
|
|
37
|
+
*/
|
|
38
|
+
export function classifySafety(method, path, operationId, api) {
|
|
39
|
+
if (isBatch(path))
|
|
40
|
+
return "write";
|
|
41
|
+
if (READ_METHODS.has(method.toUpperCase()))
|
|
42
|
+
return "read";
|
|
43
|
+
const tail = operationId.split(".").pop() ?? "";
|
|
44
|
+
const overrides = READ_OVERRIDES[api] ?? [];
|
|
45
|
+
return overrides.some((s) => s === tail) ? "read" : "write";
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Risk tier drives which write tool an operation is reachable through.
|
|
49
|
+
* Unknown privilege is treated as high: 22% of Graph has no permission
|
|
50
|
+
* mapping, and unmapped must not silently mean "safe".
|
|
51
|
+
*/
|
|
52
|
+
export function riskFor(safety, privilegeLevel, path) {
|
|
53
|
+
if (isBatch(path))
|
|
54
|
+
return "high";
|
|
55
|
+
if (safety === "read")
|
|
56
|
+
return "routine";
|
|
57
|
+
if (privilegeLevel === null)
|
|
58
|
+
return "high";
|
|
59
|
+
return privilegeLevel >= 4 ? "high" : "routine";
|
|
60
|
+
}
|
package/dist/schema.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { DatabaseSync } from "node:sqlite";
|
|
2
|
+
/** Bumped when the artifact layout changes incompatibly. Servers refuse unknown versions. */
|
|
3
|
+
export declare const LEGACY_FORMAT_VERSION = 3;
|
|
4
|
+
/** Creates every table, index, and virtual table the artifact needs. */
|
|
5
|
+
export declare function createSchema(db: DatabaseSync): void;
|
package/dist/schema.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/** Bumped when the artifact layout changes incompatibly. Servers refuse unknown versions. */
|
|
2
|
+
export const LEGACY_FORMAT_VERSION = 3;
|
|
3
|
+
// `fts5` MUST be lower-case: D1 rejects `FTS5` as "not authorized".
|
|
4
|
+
const DDL = `
|
|
5
|
+
CREATE TABLE operations (
|
|
6
|
+
qualified_id TEXT PRIMARY KEY,
|
|
7
|
+
api TEXT NOT NULL,
|
|
8
|
+
operation_id TEXT NOT NULL,
|
|
9
|
+
method TEXT NOT NULL,
|
|
10
|
+
path TEXT NOT NULL,
|
|
11
|
+
safety TEXT NOT NULL CHECK (safety IN ('read','write')),
|
|
12
|
+
risk TEXT NOT NULL CHECK (risk IN ('routine','high')),
|
|
13
|
+
operation_type TEXT,
|
|
14
|
+
pageable INTEGER NOT NULL DEFAULT 0,
|
|
15
|
+
deprecated INTEGER NOT NULL DEFAULT 0,
|
|
16
|
+
permissions TEXT,
|
|
17
|
+
perm_confidence TEXT,
|
|
18
|
+
privilege_level INTEGER,
|
|
19
|
+
summary TEXT,
|
|
20
|
+
tags TEXT,
|
|
21
|
+
params_json TEXT NOT NULL,
|
|
22
|
+
search_text TEXT NOT NULL,
|
|
23
|
+
body_ref TEXT,
|
|
24
|
+
body_schema TEXT,
|
|
25
|
+
body_media_type TEXT,
|
|
26
|
+
server_url TEXT NOT NULL
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
CREATE INDEX operations_api ON operations (api);
|
|
30
|
+
CREATE INDEX operations_safety ON operations (api, safety, risk);
|
|
31
|
+
|
|
32
|
+
CREATE VIRTUAL TABLE operations_fts USING fts5(
|
|
33
|
+
qualified_id, operation_id, summary, path, tags, api, search_text,
|
|
34
|
+
content='operations', content_rowid='rowid'
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
CREATE TABLE schemas (
|
|
38
|
+
api TEXT NOT NULL,
|
|
39
|
+
name TEXT NOT NULL,
|
|
40
|
+
json TEXT NOT NULL,
|
|
41
|
+
PRIMARY KEY (api, name)
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
CREATE TABLE meta (
|
|
45
|
+
key TEXT PRIMARY KEY,
|
|
46
|
+
value TEXT NOT NULL
|
|
47
|
+
);
|
|
48
|
+
`;
|
|
49
|
+
/** Creates every table, index, and virtual table the artifact needs. */
|
|
50
|
+
export function createSchema(db) {
|
|
51
|
+
db.exec(DDL);
|
|
52
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { OpenApiDoc } from "./load.ts";
|
|
2
|
+
import type { SchemaRecord } from "./types.ts";
|
|
3
|
+
/**
|
|
4
|
+
* Stores each component schema exactly as written, with `$ref`s intact.
|
|
5
|
+
* Resolution happens at request time against one operation's closure;
|
|
6
|
+
* eager dereferencing of Microsoft Graph exceeds 342 MB and, resolved per
|
|
7
|
+
* `$ref` hop rather than per nesting level, does not terminate at all.
|
|
8
|
+
*/
|
|
9
|
+
export declare function extractSchemas(doc: OpenApiDoc, api: string): SchemaRecord[];
|
package/dist/schemas.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stores each component schema exactly as written, with `$ref`s intact.
|
|
3
|
+
* Resolution happens at request time against one operation's closure;
|
|
4
|
+
* eager dereferencing of Microsoft Graph exceeds 342 MB and, resolved per
|
|
5
|
+
* `$ref` hop rather than per nesting level, does not terminate at all.
|
|
6
|
+
*/
|
|
7
|
+
export function extractSchemas(doc, api) {
|
|
8
|
+
const schemas = doc.components?.schemas;
|
|
9
|
+
if (!schemas)
|
|
10
|
+
return [];
|
|
11
|
+
return Object.entries(schemas).map(([name, value]) => ({
|
|
12
|
+
api,
|
|
13
|
+
name: `#/components/schemas/${name}`,
|
|
14
|
+
json: JSON.stringify(value),
|
|
15
|
+
}));
|
|
16
|
+
}
|
package/dist/sign.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ManifestSignature, ReleaseManifestV4 } from "./runtime/types.ts";
|
|
2
|
+
/** Ed25519 keypair, PEM encoded. The public key ships in plugin source. */
|
|
3
|
+
export declare function generateKeypair(): {
|
|
4
|
+
publicKeyPem: string;
|
|
5
|
+
privateKeyPem: string;
|
|
6
|
+
};
|
|
7
|
+
/** Signs the artifact's exact bytes. Returns a base64 signature. */
|
|
8
|
+
export declare function signArtifact(path: string, privateKeyPem: string): Promise<string>;
|
|
9
|
+
/**
|
|
10
|
+
* Verifies an artifact against a public key. Returns false rather than
|
|
11
|
+
* throwing on malformed input — callers treat any failure identically.
|
|
12
|
+
*/
|
|
13
|
+
export declare function verifyArtifact(path: string, signatureB64: string, publicKeyPem: string): Promise<boolean>;
|
|
14
|
+
/** Sign canonical v4/v5 manifest JSON under its versioned domain separator. */
|
|
15
|
+
export declare function signReleaseManifestV4(manifest: ReleaseManifestV4, keyId: string, privateKeyPem: string): {
|
|
16
|
+
manifestJson: string;
|
|
17
|
+
signature: ManifestSignature;
|
|
18
|
+
};
|
|
19
|
+
/** Derive the unpadded base64url SPKI used by the Worker-safe trust contract. */
|
|
20
|
+
export declare function deriveReleasePublicKeyV4(privateKeyPem: string): string;
|
package/dist/sign.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { createPrivateKey, createPublicKey, generateKeyPairSync, sign, verify, } from "node:crypto";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { canonicalJson } from "./runtime/strict-json.js";
|
|
4
|
+
function manifestSignatureDomain(format) {
|
|
5
|
+
return `knitli.openapi-mcp.release-manifest.v${format}\0`;
|
|
6
|
+
}
|
|
7
|
+
/** Ed25519 keypair, PEM encoded. The public key ships in plugin source. */
|
|
8
|
+
export function generateKeypair() {
|
|
9
|
+
const { publicKey, privateKey } = generateKeyPairSync("ed25519");
|
|
10
|
+
return {
|
|
11
|
+
publicKeyPem: publicKey.export({ type: "spki", format: "pem" }).toString(),
|
|
12
|
+
privateKeyPem: privateKey
|
|
13
|
+
.export({ type: "pkcs8", format: "pem" })
|
|
14
|
+
.toString(),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/** Signs the artifact's exact bytes. Returns a base64 signature. */
|
|
18
|
+
export async function signArtifact(path, privateKeyPem) {
|
|
19
|
+
const bytes = await readFile(path);
|
|
20
|
+
const key = createPrivateKey(privateKeyPem);
|
|
21
|
+
return sign(null, bytes, key).toString("base64");
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Verifies an artifact against a public key. Returns false rather than
|
|
25
|
+
* throwing on malformed input — callers treat any failure identically.
|
|
26
|
+
*/
|
|
27
|
+
export async function verifyArtifact(path, signatureB64, publicKeyPem) {
|
|
28
|
+
try {
|
|
29
|
+
const bytes = await readFile(path);
|
|
30
|
+
const key = createPublicKey(publicKeyPem);
|
|
31
|
+
return verify(null, bytes, key, Buffer.from(signatureB64, "base64"));
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** Sign canonical v4/v5 manifest JSON under its versioned domain separator. */
|
|
38
|
+
export function signReleaseManifestV4(manifest, keyId, privateKeyPem) {
|
|
39
|
+
const manifestJson = canonicalJson(manifest);
|
|
40
|
+
const payload = Buffer.concat([
|
|
41
|
+
Buffer.from(manifestSignatureDomain(manifest.format), "utf8"),
|
|
42
|
+
Buffer.from(manifestJson, "utf8"),
|
|
43
|
+
]);
|
|
44
|
+
const signature = sign(null, payload, createPrivateKey(privateKeyPem)).toString("base64url");
|
|
45
|
+
return {
|
|
46
|
+
manifestJson,
|
|
47
|
+
signature: { algorithm: "Ed25519", keyId, signature },
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/** Derive the unpadded base64url SPKI used by the Worker-safe trust contract. */
|
|
51
|
+
export function deriveReleasePublicKeyV4(privateKeyPem) {
|
|
52
|
+
return createPublicKey(createPrivateKey(privateKeyPem))
|
|
53
|
+
.export({ type: "spki", format: "der" })
|
|
54
|
+
.toString("base64url");
|
|
55
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { CredentialBindingResolver, CredentialProvider, LocalAuthProfile, SecretStore, Sha256 } from "../runtime/types.ts";
|
|
2
|
+
/** @internal Dependency seams exist only for deterministic local adapter tests. */
|
|
3
|
+
export interface CredentialProviderOptions {
|
|
4
|
+
readonly manifestOrigins: readonly string[];
|
|
5
|
+
readonly secretStore?: SecretStore;
|
|
6
|
+
readonly environment?: Readonly<Record<string, string | undefined>>;
|
|
7
|
+
readonly fetch?: typeof globalThis.fetch;
|
|
8
|
+
readonly now?: () => number;
|
|
9
|
+
readonly randomBytes?: (size: number) => Uint8Array;
|
|
10
|
+
readonly authorizationDeadlineMs?: number;
|
|
11
|
+
readonly tokenDeadlineMs?: number;
|
|
12
|
+
readonly maxTokenResponseBytes?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface LocalCredentialProvider extends CredentialProvider {
|
|
15
|
+
readonly bindingResolver: CredentialBindingResolver;
|
|
16
|
+
/**
|
|
17
|
+
* Clears process-local credentials only. To invalidate the upstream grant,
|
|
18
|
+
* use the provider account's documented revocation procedure; v1 does not
|
|
19
|
+
* invent or call a provider revocation endpoint.
|
|
20
|
+
*/
|
|
21
|
+
forget(): Promise<void>;
|
|
22
|
+
close(): Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
export declare class MemorySecretStore implements SecretStore {
|
|
25
|
+
#private;
|
|
26
|
+
get(key: string): Promise<string | null>;
|
|
27
|
+
set(key: string, value: string): Promise<void>;
|
|
28
|
+
delete(key: string): Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
/** Validate local profile semantics without resolving credentials or performing I/O. */
|
|
31
|
+
export declare function validateLocalAuthProfile(profile: LocalAuthProfile): LocalAuthProfile;
|
|
32
|
+
export declare function digestCredentialProfile(profile: LocalAuthProfile): Promise<Sha256>;
|
|
33
|
+
export declare function createCredentialProvider(rawProfile: LocalAuthProfile, options: CredentialProviderOptions): Promise<LocalCredentialProvider>;
|