Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions packages/xmcp/src/compiler/config/__tests__/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
getResolvedTypescriptConfig,
getResolvedExperimentalConfig,
getResolvedCorsConfig,
getResolvedObservabilityConfig,
} from "../utils";
import {
injectHttpVariables,
Expand All @@ -18,6 +19,7 @@ import {
injectAdapterVariables,
injectStdioVariables,
injectServerInfoVariables,
injectObservabilityVariables,
} from "../injection";
import { configSchema } from "../index";

Expand Down Expand Up @@ -75,6 +77,14 @@ describe("Config System - Zod Defaults", () => {
assert.equal(corsConfig.maxAge, 86400);
}
});

it("should apply observability defaults", () => {
const parsed = configSchema.parse({ observability: {} });
const resolved = getResolvedObservabilityConfig(parsed);

assert.equal(resolved.enabled, false);
assert.equal(resolved.includeInput, true);
});
});

describe("Config System - Boolean Transformations", () => {
Expand Down Expand Up @@ -314,6 +324,21 @@ describe("Config System - Injection Functions", () => {
assert.equal(typeof serverInfo.version, "string");
assert.notEqual(serverInfo.version, "");
});

it("should inject observability variables", () => {
const config = configSchema.parse({
observability: {
enabled: true,
includeInput: false,
},
});
const variables = injectObservabilityVariables(config);

assert.notEqual(variables.OBSERVABILITY_CONFIG, undefined);
const observability = JSON.parse(variables.OBSERVABILITY_CONFIG);
assert.equal(observability.enabled, true);
assert.equal(observability.includeInput, false);
});
});

describe("Config System - Edge Cases", () => {
Expand Down
4 changes: 4 additions & 0 deletions packages/xmcp/src/compiler/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
templateConfigSchema,
typescriptConfigSchema,
bundlerConfigSchema,
observabilityConfigSchema,
} from "./schemas";
import type { RspackOptions } from "@rspack/core";

Expand All @@ -21,6 +22,7 @@ export const configSchema = z.object({
bundler: bundlerConfigSchema.optional(),
template: templateConfigSchema.optional(),
typescript: typescriptConfigSchema.optional(),
observability: observabilityConfigSchema.optional(),
});

type BundlerConfigType = { bundler?: (config: RspackOptions) => RspackOptions };
Expand All @@ -44,6 +46,7 @@ export type {
ResolvedStdioConfig,
ResolvedPathsConfig,
ResolvedExperimentalConfig,
ResolvedObservabilityConfig,
} from "./utils";

// Template, TypeScript, and CORS configs don't need resolved types
Expand All @@ -59,4 +62,5 @@ export type {
BundlerConfig,
TemplateConfig,
TypescriptConfig,
ObservabilityConfig,
} from "./schemas";
18 changes: 17 additions & 1 deletion packages/xmcp/src/compiler/config/injection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
getResolvedTemplateConfig,
getResolvedExperimentalConfig,
getResolvedTypescriptConfig,
getResolvedObservabilityConfig,
} from "./utils";
import type { ResolvedHttpConfig, XmcpConfigOutputSchema } from "./index";
import type { HttpTransportConfig } from "./schemas/transport/http";
Expand Down Expand Up @@ -198,6 +199,20 @@ export function injectTypescriptVariables(userConfig: XmcpConfigOutputSchema) {

export type TypescriptVariables = ReturnType<typeof injectTypescriptVariables>;

export function injectObservabilityVariables(
userConfig: XmcpConfigOutputSchema
) {
const observabilityConfig = getResolvedObservabilityConfig(userConfig);

return {
OBSERVABILITY_CONFIG: JSON.stringify(observabilityConfig),
};
}

export type ObservabilityVariables = ReturnType<
typeof injectObservabilityVariables
>;

export type InjectedVariables =
| HttpVariables
| CorsVariables
Expand All @@ -206,4 +221,5 @@ export type InjectedVariables =
| TemplateVariables
| ServerInfoVariables
| AdapterVariables
| TypescriptVariables;
| TypescriptVariables
| ObservabilityVariables;
4 changes: 4 additions & 0 deletions packages/xmcp/src/compiler/config/schemas/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,7 @@ export { pathsConfigSchema, type PathsConfig, DEFAULT_PATHS } from "./paths";
export { bundlerConfigSchema, type BundlerConfig } from "./bundler";
export { templateConfigSchema, type TemplateConfig } from "./template";
export { typescriptConfigSchema, type TypescriptConfig } from "./typescript";
export {
observabilityConfigSchema,
type ObservabilityConfig,
} from "./observability";
24 changes: 24 additions & 0 deletions packages/xmcp/src/compiler/config/schemas/observability.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { z } from "zod/v3";

const observabilityConfigBaseSchema = z.object({
/** Enables execution logs for tools, prompts, and resources */
enabled: z.boolean().default(false),
/** Includes the incoming input payload in start logs */
includeInput: z.boolean().default(true),
});

export const observabilityConfigSchema = observabilityConfigBaseSchema
.partial()
.transform((val) => {
const defaults = observabilityConfigBaseSchema.parse({});
const provided = Object.fromEntries(
Object.entries(val).filter(([_, value]) => value !== undefined)
);

return {
...defaults,
...provided,
};
});

export type ObservabilityConfig = z.infer<typeof observabilityConfigSchema>;
12 changes: 12 additions & 0 deletions packages/xmcp/src/compiler/config/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
typescriptConfigSchema,
corsConfigSchema,
experimentalConfigSchema,
observabilityConfigSchema,
DEFAULT_PATHS,
} from "./schemas";
import type { z } from "zod/v3";
Expand Down Expand Up @@ -166,3 +167,14 @@ export function getResolvedTypescriptConfig(
const typescript = userConfig?.typescript;
return typescriptConfigSchema.parse(typescript ?? {});
}

export type ResolvedObservabilityConfig = z.output<
typeof observabilityConfigSchema
>;

export function getResolvedObservabilityConfig(
userConfig: XmcpConfigOutputSchema
): ResolvedObservabilityConfig {
const observability = userConfig?.observability;
return observabilityConfigSchema.parse(observability ?? {});
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
injectServerInfoVariables,
injectAdapterVariables,
injectTypescriptVariables,
injectObservabilityVariables,
} from "../config/injection";
import { getResolvedHttpConfig } from "../config/utils";

Expand All @@ -32,6 +33,7 @@ export function getInjectedVariables(
const serverInfoVariables = injectServerInfoVariables(xmcpConfig);
const adapterVariables = injectAdapterVariables(xmcpConfig);
const typescriptVariables = injectTypescriptVariables(xmcpConfig);
const observabilityVariables = injectObservabilityVariables(xmcpConfig);

return {
...httpVariables,
Expand All @@ -42,5 +44,6 @@ export function getInjectedVariables(
...serverInfoVariables,
...adapterVariables,
...typescriptVariables,
...observabilityVariables,
};
}
Loading