Reference
Configuration
One config file holds the model, the tool registry, where your actions live, and how much mdlang says while it runs.
mdlang.config.ts
import { defineConfig } from "mdlang/config";import { ChatOpenAI } from "@langchain/openai";import { tool } from "@langchain/core/tools";import bcrypt from "bcrypt";import { z } from "zod"; export default defineConfig({ model: new ChatOpenAI({ model: "gpt-4o-mini" }), tools: { mcpServers: { Postgres: { command: "npx", args: ["-y", "some-postgres-mcp-server"], env: { DATABASE_URL: process.env.DATABASE_URL ?? "" }, }, }, custom: { hashPassword: tool(async ({ raw }) => bcrypt.hash(raw, 10), { name: "hashPassword", description: "Hashes a plaintext password with bcrypt.", schema: z.object({ raw: z.string() }), }), }, }, actions: { dir: "actions", generatedDir: "actions/generated", }, logging: { level: "warn", },});Fields
| Field | Purpose |
|---|---|
model | The LangChain BaseChatModel used for every action. Swap providers freely — actions don't change. |
tools.mcpServers | External MCP server definitions, passed through to @langchain/mcp-adapters. |
tools.custom | Registry of in-process tool() instances, keyed by name. |
actions | Where action files live (dir) and where the generated client is written (generatedDir). |
logging | Verbosity, transcript logging, and optional cost estimation. |
Action frontmatter opts in to specific tools by name: mcpTools references entries under tools.mcpServers, and customTools references keys under tools.custom. See Action file format.
The system prompt
MDLANG.mdsits next to your config and is prepended to every action. Keep it short and focused on overall behaviour — per-action instructions belong in the action’s own body.
Logging
logging: { level: "info", // debug | info | warn | error | silent — default "warn" logAgentSteps: true, // model decisions and tool calls logMcpCalls: true, // which MCP tools were loaded per action logCustomTools: true, // which custom tools were loaded per action jsonlFile: "runs.jsonl" // append every completed run as an OpenAI-format transcript // Your model's prices, USD per million tokens. Omit and mdlang logs token // counts only — it will not guess prices for a model it didn't choose. pricing: { inputPerMTok: 0.15, cachedInputPerMTok: 0.075, outputPerMTok: 0.6 },}- The default is
level: "warn". mdlang runs inside your process and stays quiet unless something goes wrong. - The per-category booleans can only narrow what
levelalready permits. They never re-enable output the level has silenced. level: "debug"additionally logs tool inputs and outputs.pricingis opt-in. Without it you get token counts and no cost estimate — mdlang will not guess prices for a model it didn’t choose.