mdlang
Documentation

Reference

Programmatic API

Most of the time you want the generated action() wrapper. These are the pieces underneath it, for when you need to assemble the run yourself.

import { executeAction, runAction, loadConfig, defineConfig } from "mdlang";

Which one to use

ExportUse it when
action()Almost always. The generated wrapper — typed, bundler-safe, no filesystem access.
executeAction()You want to run a compiled action with everything passed in explicitly. No filesystem or transpilation work.
runAction()Scripts and one-off dispatch where the action name is only known at runtime. Needs a real filesystem.
loadConfig()You need the resolved config and system prompt from a directory.
defineConfig()Writing mdlang.config.ts. Also exported from mdlang/config.

executeAction

Runs a compiled action with the action module, runtime, system prompt, and arguments all supplied by you. This is what the generated action() wrapper calls — it does no filesystem or transpilation work, so it is safe anywhere.

const result = await executeAction({  action,  runtime,  systemPrompt,  args,});

runAction

Resolves the config and the generated action from disk by name. Convenient in scripts and for dispatching an action name only known at runtime.

const result = await runAction("create-user", { email }, { cwd });

Using it in an HTTP handler

isActionName is generated alongside action() and narrows an arbitrary string to a known action name, which is what makes this safe to drive from a URL parameter.

server.ts
import express from "express";import { action, isActionName } from "./actions/generated/index.js"; const app = express();app.use(express.json()); app.post("/actions/:name", async (req, res) => {  if (!isActionName(req.params.name)) {    return res.status(404).json({ error: "Unknown action" });  }  try {    const result = await action(req.params.name, req.body);    res.json(result);  } catch (err) {    res.status(400).json({ error: (err as Error).message });  }}); app.listen(3000);
  • An unknown action name is a 404 before any work starts.
  • A malformed body is rejected by the input schema, so it never reaches the model.
  • Every call constructs a fresh agent and connects to the MCP servers that action declares, then tears them down. For high-traffic services you’ll want your own caching layer in front.

Generated exports

ExportWhat it is
action(name, args)The typed entry point. Return type is inferred from the action's output schema.
isActionName(value)Type guard narrowing a string to ActionName.
ActionNameUnion of every generated action key.
ActionMapMap from action name to its argument and result types.

For what runs inside a call, see How it works.