feat: use latest MCPB schema for BUILD manifest validation
Update manifest type usage in config and packaging to strictly enforce the latest schema version (0.3) instead of accepting any version. Changes: - src/shared/config.ts: Use McpbManifestLatest instead of McpbManifest - src/types.ts: Add McpbManifestLatest type export - test/config.test.ts: Update tests to use McpbManifestLatest This ensures BUILD manifests are validated against the latest schema only during packaging, preventing use of older schema versions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
11d1397ee8
commit
ddad8064ef
3 changed files with 36 additions and 20 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
import type {
|
import type {
|
||||||
Logger,
|
Logger,
|
||||||
McpbManifest,
|
McpbManifestLatest,
|
||||||
McpbUserConfigValues,
|
McpbUserConfigValues,
|
||||||
McpServerConfig,
|
McpServerConfig,
|
||||||
} from "../types.js";
|
} from "../types.js";
|
||||||
|
|
@ -85,7 +85,7 @@ export function replaceVariables(
|
||||||
}
|
}
|
||||||
|
|
||||||
interface GetMcpConfigForManifestOptions {
|
interface GetMcpConfigForManifestOptions {
|
||||||
manifest: McpbManifest;
|
manifest: McpbManifestLatest;
|
||||||
extensionPath: string;
|
extensionPath: string;
|
||||||
systemDirs: Record<string, string>;
|
systemDirs: Record<string, string>;
|
||||||
userConfig: McpbUserConfigValues;
|
userConfig: McpbUserConfigValues;
|
||||||
|
|
@ -179,7 +179,7 @@ export async function getMcpConfigForManifest(
|
||||||
}
|
}
|
||||||
|
|
||||||
interface HasRequiredConfigMissingOptions {
|
interface HasRequiredConfigMissingOptions {
|
||||||
manifest: McpbManifest;
|
manifest: McpbManifestLatest;
|
||||||
userConfig?: McpbUserConfigValues;
|
userConfig?: McpbUserConfigValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
18
src/types.ts
18
src/types.ts
|
|
@ -15,6 +15,7 @@ import type {
|
||||||
McpbUserConfigValuesSchema,
|
McpbUserConfigValuesSchema,
|
||||||
McpServerConfigSchema,
|
McpServerConfigSchema,
|
||||||
} from "./schemas/latest.js";
|
} from "./schemas/latest.js";
|
||||||
|
import type { McpbManifestSchema as McpbManifestSchemaAny } from "./schemas/any.js";
|
||||||
|
|
||||||
export type McpServerConfig = z.infer<typeof McpServerConfigSchema>;
|
export type McpServerConfig = z.infer<typeof McpServerConfigSchema>;
|
||||||
|
|
||||||
|
|
@ -46,7 +47,22 @@ export type McpbUserConfigurationOption = z.infer<
|
||||||
|
|
||||||
export type McpbUserConfigValues = z.infer<typeof McpbUserConfigValuesSchema>;
|
export type McpbUserConfigValues = z.infer<typeof McpbUserConfigValuesSchema>;
|
||||||
|
|
||||||
export type McpbManifest = z.infer<typeof McpbManifestSchema>;
|
/**
|
||||||
|
* McpbManifest type that accepts any supported manifest version (0.1, 0.2, 0.3).
|
||||||
|
* This is the default manifest type that should be used for maximum compatibility.
|
||||||
|
*/
|
||||||
|
export type McpbManifest = z.infer<typeof McpbManifestSchemaAny>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use McpbManifest instead. This alias is kept for backward compatibility.
|
||||||
|
*/
|
||||||
|
export type McpbManifestAny = z.infer<typeof McpbManifestSchemaAny>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* McpbManifest type for the latest manifest version only (0.3).
|
||||||
|
* Use this when you specifically need the latest version.
|
||||||
|
*/
|
||||||
|
export type McpbManifestLatest = z.infer<typeof McpbManifestSchema>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Information about a MCPB package signature
|
* Information about a MCPB package signature
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import {
|
||||||
hasRequiredConfigMissing,
|
hasRequiredConfigMissing,
|
||||||
replaceVariables,
|
replaceVariables,
|
||||||
} from "../src/shared/config";
|
} from "../src/shared/config";
|
||||||
import type { Logger, McpbManifest } from "../src/types";
|
import type { Logger, McpbManifestLatest } from "../src/types";
|
||||||
|
|
||||||
describe("replaceVariables", () => {
|
describe("replaceVariables", () => {
|
||||||
it("should replace variables in strings", () => {
|
it("should replace variables in strings", () => {
|
||||||
|
|
@ -89,7 +89,7 @@ describe("getMcpConfigForManifest", () => {
|
||||||
data: "/data",
|
data: "/data",
|
||||||
};
|
};
|
||||||
|
|
||||||
const baseManifest: McpbManifest = {
|
const baseManifest: McpbManifestLatest = {
|
||||||
manifest_version: "0.3",
|
manifest_version: "0.3",
|
||||||
name: "test-extension",
|
name: "test-extension",
|
||||||
version: "1.0.0",
|
version: "1.0.0",
|
||||||
|
|
@ -114,7 +114,7 @@ describe("getMcpConfigForManifest", () => {
|
||||||
const manifest = {
|
const manifest = {
|
||||||
...baseManifest,
|
...baseManifest,
|
||||||
server: undefined,
|
server: undefined,
|
||||||
} as unknown as McpbManifest;
|
} as unknown as McpbManifestLatest;
|
||||||
|
|
||||||
const result = await getMcpConfigForManifest({
|
const result = await getMcpConfigForManifest({
|
||||||
manifest,
|
manifest,
|
||||||
|
|
@ -129,7 +129,7 @@ describe("getMcpConfigForManifest", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return undefined when required config is missing", async () => {
|
it("should return undefined when required config is missing", async () => {
|
||||||
const manifest: McpbManifest = {
|
const manifest: McpbManifestLatest = {
|
||||||
...baseManifest,
|
...baseManifest,
|
||||||
user_config: {
|
user_config: {
|
||||||
apiKey: {
|
apiKey: {
|
||||||
|
|
@ -171,7 +171,7 @@ describe("getMcpConfigForManifest", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should apply platform overrides", async () => {
|
it("should apply platform overrides", async () => {
|
||||||
const manifest: McpbManifest = {
|
const manifest: McpbManifestLatest = {
|
||||||
...baseManifest,
|
...baseManifest,
|
||||||
server: {
|
server: {
|
||||||
type: "node",
|
type: "node",
|
||||||
|
|
@ -203,7 +203,7 @@ describe("getMcpConfigForManifest", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should handle user config variable replacement with defaults", async () => {
|
it("should handle user config variable replacement with defaults", async () => {
|
||||||
const manifest: McpbManifest = {
|
const manifest: McpbManifestLatest = {
|
||||||
...baseManifest,
|
...baseManifest,
|
||||||
user_config: {
|
user_config: {
|
||||||
port: {
|
port: {
|
||||||
|
|
@ -236,7 +236,7 @@ describe("getMcpConfigForManifest", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should handle user config variable replacement with user values", async () => {
|
it("should handle user config variable replacement with user values", async () => {
|
||||||
const manifest: McpbManifest = {
|
const manifest: McpbManifestLatest = {
|
||||||
...baseManifest,
|
...baseManifest,
|
||||||
user_config: {
|
user_config: {
|
||||||
paths: {
|
paths: {
|
||||||
|
|
@ -270,7 +270,7 @@ describe("getMcpConfigForManifest", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should convert boolean user config values to strings", async () => {
|
it("should convert boolean user config values to strings", async () => {
|
||||||
const manifest: McpbManifest = {
|
const manifest: McpbManifestLatest = {
|
||||||
...baseManifest,
|
...baseManifest,
|
||||||
user_config: {
|
user_config: {
|
||||||
verbose: {
|
verbose: {
|
||||||
|
|
@ -304,7 +304,7 @@ describe("getMcpConfigForManifest", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("hasRequiredConfigMissing", () => {
|
describe("hasRequiredConfigMissing", () => {
|
||||||
const baseManifest: McpbManifest = {
|
const baseManifest: McpbManifestLatest = {
|
||||||
manifest_version: "0.3",
|
manifest_version: "0.3",
|
||||||
name: "test-extension",
|
name: "test-extension",
|
||||||
version: "1.0.0",
|
version: "1.0.0",
|
||||||
|
|
@ -329,7 +329,7 @@ describe("hasRequiredConfigMissing", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return false when no config fields are required", () => {
|
it("should return false when no config fields are required", () => {
|
||||||
const manifest: McpbManifest = {
|
const manifest: McpbManifestLatest = {
|
||||||
...baseManifest,
|
...baseManifest,
|
||||||
user_config: {
|
user_config: {
|
||||||
port: {
|
port: {
|
||||||
|
|
@ -349,7 +349,7 @@ describe("hasRequiredConfigMissing", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return false when required config is provided", () => {
|
it("should return false when required config is provided", () => {
|
||||||
const manifest: McpbManifest = {
|
const manifest: McpbManifestLatest = {
|
||||||
...baseManifest,
|
...baseManifest,
|
||||||
user_config: {
|
user_config: {
|
||||||
apiKey: {
|
apiKey: {
|
||||||
|
|
@ -369,7 +369,7 @@ describe("hasRequiredConfigMissing", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return true when required config is undefined", () => {
|
it("should return true when required config is undefined", () => {
|
||||||
const manifest: McpbManifest = {
|
const manifest: McpbManifestLatest = {
|
||||||
...baseManifest,
|
...baseManifest,
|
||||||
user_config: {
|
user_config: {
|
||||||
apiKey: {
|
apiKey: {
|
||||||
|
|
@ -389,7 +389,7 @@ describe("hasRequiredConfigMissing", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return true when required config is empty string", () => {
|
it("should return true when required config is empty string", () => {
|
||||||
const manifest: McpbManifest = {
|
const manifest: McpbManifestLatest = {
|
||||||
...baseManifest,
|
...baseManifest,
|
||||||
user_config: {
|
user_config: {
|
||||||
apiKey: {
|
apiKey: {
|
||||||
|
|
@ -409,7 +409,7 @@ describe("hasRequiredConfigMissing", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return true when required config is array with invalid values", () => {
|
it("should return true when required config is array with invalid values", () => {
|
||||||
const manifest: McpbManifest = {
|
const manifest: McpbManifestLatest = {
|
||||||
...baseManifest,
|
...baseManifest,
|
||||||
user_config: {
|
user_config: {
|
||||||
paths: {
|
paths: {
|
||||||
|
|
@ -430,7 +430,7 @@ describe("hasRequiredConfigMissing", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return true when required config is empty array", () => {
|
it("should return true when required config is empty array", () => {
|
||||||
const manifest: McpbManifest = {
|
const manifest: McpbManifestLatest = {
|
||||||
...baseManifest,
|
...baseManifest,
|
||||||
user_config: {
|
user_config: {
|
||||||
paths: {
|
paths: {
|
||||||
|
|
@ -459,7 +459,7 @@ describe("hasRequiredConfigMissing", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should handle multiple required config fields", () => {
|
it("should handle multiple required config fields", () => {
|
||||||
const manifest: McpbManifest = {
|
const manifest: McpbManifestLatest = {
|
||||||
...baseManifest,
|
...baseManifest,
|
||||||
user_config: {
|
user_config: {
|
||||||
apiKey: {
|
apiKey: {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue