Skip to content

Model Context Protocol (MCP)

Sema includes a built-in Model Context Protocol server. This allows LLM clients (such as Claude Desktop, Cursor, or Claude Code) to inspect, compile, format, evaluate, and build Sema code in your host environment, as well as execute user-defined Lisp tools.

The server communicates over standard input/output (stdio) using JSON-RPC 2.0.

bash
sema mcp

Default MCP Tools

When started, the MCP server exposes a set of core developer tools:

Tool NameDescriptionParameters
run_fileRun a .sema or .semac file and get output/return valuefile_path (string), arguments (array of strings, optional)
compileCompile a .sema file to .semac bytecodesource_path (string), output_path (string, optional)
evalEvaluate a single Sema expression string and capture outputcode (string)
docsRetrieve docstring and signature details for any symbolsymbol (string)
fmtFormat a Sema file or code stringfile_path (string, optional), code (string, optional)
disasmDisassemble a .sema or .semac file to VM instructionsfile_path (string)
buildCompile a .sema file into a standalone executablesource_path (string), output_path (string)
infoGet environment and version information about the serverNone

Path Resolution

All file paths passed to these tools are resolved relative to the current working directory (CWD) of the MCP server process. Both absolute and relative paths are supported.


Filepath Mode & Custom Tools

You can expose custom tools defined in your Sema scripts to the LLM client by passing filepaths when starting the server:

bash
sema mcp tools/receipts.sema

When started in filepath mode, the server instantiates the interpreter context, evaluates the specified files, and automatically exposes any tools defined via the deftool special form.

Defining a Custom Tool: PDF Receipt Extractor

Here is a real-world example of an MCP tool that reads a receipt PDF and extracts structured data from it by combining Sema's PDF processing and LLM Structured Extraction:

sema
;; tools/receipts.sema

(deftool extract-receipt
  "Extract structured transaction data (merchant, amount, currency, date, line items) from a PDF invoice/receipt."
  {:pdf-path {:type :string :description "Path to the invoice/receipt PDF file (e.g. invoice.pdf)"}}
  (lambda (pdf-path)
    (if (not (file/exists? pdf-path))
        (error (string-append "Receipt file not found: " pdf-path))
        (begin
          (llm/auto-configure)
          ;; Extract text and clean up whitespace for LLM processing
          (define text (text/clean-whitespace (pdf/extract-text pdf-path)))
          ;; Call structured LLM extraction
          (llm/extract
            {:vendor {:type :string :description "Name of the merchant"}
             :amount {:type :number :description "Total bill amount"}
             :currency {:type :string :description "3-letter currency code (e.g. USD, EUR)"}
             :date {:type :string :description "Date of transaction in YYYY-MM-DD format"}
             :line-items {:type :array
                          :description "List of individual items purchased"
                          :items {:type :object
                                  :properties {:description {:type :string}
                                               :price {:type :number}}}}}
            text)))))

Standalone Binary Mode

Sema's build command compiles scripts into standalone native executables. Every compiled standalone binary has built-in MCP server capabilities out-of-the-box:

bash
# Compile the custom receipt tool
sema build tools/receipts.sema -o receipt-extractor

# Run as a normal CLI tool (from your shell/scripts)
./receipt-extractor --pdf-path invoice.pdf

# Start the stdio MCP server exposing the embedded tools
./receipt-extractor --mcp

When started with --mcp, the executable evaluates its embedded bytecode (which registers the extract-receipt tool definition in the environment) and then transitions to starting the stdio MCP server loop.


Tool Filtering & Visibility

When loading files in filepath mode, you can control which tools are exposed to the LLM:

1. Private Prefix

Any tool whose name begins with an underscore (e.g., _secret-helper) is treated as a private helper and excluded from discovery.

2. Declarative Metadata

You can declare a tool as private by adding :mcp/expose #f or :private #t in its parameters metadata map:

sema
(deftool internal-helper
  "Not visible to MCP clients"
  {:mcp/expose #f}
  (lambda () (println "internal")))

3. Command Line Filters

You can explicitly include or exclude tools using the --include and --exclude flags:

bash
# Only expose the receipt extractor tool
sema mcp tools/receipts.sema --include extract-receipt

# Expose all tools except order-pineapple-pizza (which we probably shouldn't be running automatically)
sema mcp tools/receipts.sema --exclude order-pineapple-pizza

Stateful Notebook Tools

The MCP server exposes a set of stateful notebook management and evaluation tools to allow LLMs to directly read, write, and execute cell-based .sema-nb files.

Tool NameDescriptionParameters
notebook/newCreate a new empty .sema-nb notebookpath (string), title (string, optional), overwrite (boolean, optional — defaults to false; creation fails if a file already exists at path)
notebook/readRead the structure, source, and outputs of a notebookpath (string)
notebook/add_cellAppend or insert a new cell (code or markdown)path (string), type (string: "code"/"markdown"), source (string), after_id (string, optional)
notebook/update_cellUpdate the source/type of an existing cellpath (string), id (string), source (string, optional), type (string, optional)
notebook/delete_cellDelete a cell from a notebookpath (string), id (string)
notebook/eval_cellEvaluate a single code cellpath (string), id (string)
notebook/eval_allEvaluate all code cells in orderpath (string)
notebook/exportExport a notebook to Markdown or a clean .sema scriptpath (string), format (string: "markdown"/"source"), output_path (string, optional)

In-Memory State Caching

To support interactive cell execution (where Cell 2 relies on variables or functions defined in Cell 1), the MCP server maintains an in-memory cache of notebook evaluation engines mapped by their canonical file paths.

When a cell is evaluated, the cached engine runs the code, updates the cell output, saves the updated JSON representation back to disk, and returns the result, ensuring state is preserved across consecutive tool calls.