import { z } from 'zod';
/**
* Configuration schema for the MCP server.
* All values are loaded from environment variables.
*/
const configSchema = z.object({
/**
* The agent's Ed25519 private key in base64 format.
* Used for signing outgoing requests.
*/
privateKey: z
.string()
.min(1, 'AGENT_PRIVATE_KEY is required')
.refine(
(val) => {
try {
const decoded = Buffer.from(val, 'base64');
return decoded.length === 32 || decoded.length === 64;
} catch {
return false;
}
},
{ message: 'AGENT_PRIVATE_KEY must be a valid base64-encoded Ed25519 private key (32 or 64 bytes)' }
),
/**
* The agent's origin/domain identifier.
* Example: "agent.example.com" or "did:key:..."
*/
origin: z.string().min(1, 'AGENT_ORIGIN is required'),
/**
* The key ID registered in the agents registry.
* This links the signing key to the registered agent.
*/
pubkeyId: z.string().uuid('AGENT_PUBKEY_ID must be a valid UUID'),
/**
* The base URL of the agents registry API.
* Defaults to the production registry.
*/
registryUrl: z
.string()
.url('REGISTRY_API_URL must be a valid URL')
.default('https://api.agents-registry.com'),
/**
* Request timeout in milliseconds.
*/
requestTimeout: z.coerce.number().positive().default(30000),
/**
* Enable debug logging.
*/
debug: z.coerce.boolean().default(false),
});
export type Config = z.infer<typeof configSchema>;
/**
* Load and validate configuration from environment variables.
* Throws a descriptive error if validation fails.
*/
export function loadConfig(): Config {
const result = configSchema.safeParse({
privateKey: process.env['AGENT_PRIVATE_KEY'],
origin: process.env['AGENT_ORIGIN'],
pubkeyId: process.env['AGENT_PUBKEY_ID'],
registryUrl: process.env['REGISTRY_API_URL'],
requestTimeout: process.env['REQUEST_TIMEOUT'],
debug: process.env['DEBUG'],
});
if (!result.success) {
const errors = result.error.errors
.map((e) => ` - ${e.path.join('.')}: ${e.message}`)
.join('\n');
throw new Error(`Configuration error:\n${errors}`);
}
return result.data;
}
/**
* Create a config object for testing purposes.
*/
export function createTestConfig(overrides: Partial<Config> = {}): Config {
return {
privateKey: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=', // 32 zero bytes
origin: 'test.example.com',
pubkeyId: '00000000-0000-0000-0000-000000000000',
registryUrl: 'http://localhost:3000',
requestTimeout: 5000,
debug: false,
...overrides,
};
}