MCP Server¶
Audience: Developers who want to give an AI assistant (Claude Desktop, Claude Code, Cursor, or any other MCP-capable client) the ability to inspect, complete, and diagnose ExpresZo expressions.
ExpresZo ships an MCP (Model Context Protocol) server that wraps the language service and exposes it over stdio. Once it is wired into your MCP client, the model can ask the server for completions, hover information, syntax highlighting, and diagnostics for any ExpresZo expression — making it dramatically easier for an assistant to author or debug expressions without guessing at the supported functions and syntax.
What it does¶
The MCP server registers four tools, each a thin wrapper around the matching language-service API:
| Tool | Purpose |
|---|---|
expreszo_get_completions |
Completion items (functions, constants, keywords, user variables) at a cursor position |
expreszo_get_hover |
Hover info — signature, documentation, and variable value preview at a position |
expreszo_get_highlighting |
Token-by-token syntax highlighting for an expression |
expreszo_get_diagnostics |
Parse errors and function-arity errors, returned as LSP Diagnostic objects |
All tools return the raw language-service payload as JSON, so the model sees the same data an IDE would consume.
Installation¶
The server ships with @pro-fa/expreszo but its runtime dependencies (@modelcontextprotocol/sdk and zod) are declared as optionalDependencies, so they are only installed when npm is allowed to pull optionals (the default).
If your environment disables optional dependencies (npm install --no-optional or equivalent), install them explicitly:
After install, the expreszo-mcp executable is available via npx expreszo-mcp or as a direct bin entry in node_modules/.bin/.
Wiring it up¶
The server speaks MCP over stdio. Configure your client to spawn it as a subprocess.
Claude Desktop¶
Edit claude_desktop_config.json (Settings → Developer → Edit Config) and add an entry under mcpServers:
{
"mcpServers": {
"expreszo": {
"command": "npx",
"args": ["-y", "@pro-fa/expreszo", "expreszo-mcp"]
}
}
}
Restart Claude Desktop. The four expreszo_* tools will appear in the tool picker.
Claude Code¶
Register the server with the claude mcp CLI:
Or add it manually to your MCP settings file:
{
"mcpServers": {
"expreszo": {
"command": "npx",
"args": ["-y", "@pro-fa/expreszo", "expreszo-mcp"]
}
}
}
VS Code (GitHub Copilot Chat agent mode)¶
VS Code 1.102+ supports MCP servers natively for Copilot Chat in agent mode. You can add the server in a few ways.
Workspace-scoped (recommended — commit it alongside the repo):
Create .vscode/mcp.json at the root of your workspace:
{
"servers": {
"expreszo": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@pro-fa/expreszo", "expreszo-mcp"]
}
}
}
VS Code will prompt you to trust the server the first time it starts. Anyone else who opens the workspace gets the same prompt.
User-scoped (available in every workspace):
Open the command palette (Ctrl+Shift+P / Cmd+Shift+P) and run MCP: Add Server. Pick Command (stdio), enter:
- Command:
npx - Args:
-y @pro-fa/expreszo expreszo-mcp - Name:
expreszo - Scope: User (stores the entry in your user
settings.json)
Once installed, open Copilot Chat, switch to Agent mode, and click the tools icon — the four expreszo_* tools appear under the expreszo server and can be toggled on/off per chat.
Use MCP: List Servers from the command palette to start, stop, restart, or view the output log of a running server.
Cursor, Zed, and other MCP clients¶
Any MCP client that can spawn a stdio server will work. Use the same command (npx -y @pro-fa/expreszo expreszo-mcp) in whatever configuration format the client expects.
Running from a local checkout¶
If you cloned the repo and want to run the built server directly:
{
"mcpServers": {
"expreszo": {
"command": "node",
"args": ["/absolute/path/to/expreszo-typescript/dist/bin/mcp-server.mjs"]
}
}
}
Run npm run build once in the checkout to generate dist/bin/mcp-server.mjs.
Using it from a chat¶
Once the server is wired up you don't call the tools directly — you ask the assistant a question in natural language and it decides which tools to invoke. The point of the MCP server is that the model can look up the real list of supported functions, constants, and arity rules instead of guessing.
Example prompt¶
I'm using ExpresZo to evaluate formulas entered by end users. Given the variables
price(number),discount(number between 0 and 1),taxRate(number), andisMember(boolean), help me write an expression that computes the final total: apply the discount to the price, add tax on the discounted amount, and give members an extra 5% off the final total. Use theexpreszoMCP server to check that every function you use actually exists and that the expression has no diagnostics before you give me the final answer.
With the server connected, a capable agent will typically:
- Call
expreszo_get_completionswith a partial expression like"if"to discover that the conditional is spelledif(cond, then, else)(or that a ternary is available), rather than assuming a JavaScript-style? :. - Draft a candidate expression, for example:
- Call
expreszo_get_diagnosticson the draft. If anything comes back (wrong arity, unknown identifier, parse error), revise and re-check. - Optionally call
expreszo_get_hoveron individual identifiers likeifto confirm the signature and documentation. - Return only the validated expression to you, along with a brief explanation.
Other things you can ask¶
- "What string functions does ExpresZo support? Use the MCP server to enumerate them." — the agent calls
expreszo_get_completionson an empty expression and filters the result. - "Here's an expression one of my users wrote:
sum(x, y— what's wrong with it?" — the agent callsexpreszo_get_diagnosticsand reports the parse error with position. - "Rewrite
a > 0 ? a : -aas a valid ExpresZo expression." — the agent discoversabsvia completions/hover and returnsabs(a).
The general pattern: ask for help with an expression, and explicitly mention "use the expreszo MCP server to verify" so the agent commits to checking its answer instead of hallucinating function names.
Tool reference¶
All tools take a required expression (the ExpresZo source text) and an optional uri (used purely to label the virtual document — defaults to expreszo://inline).
Tools that need a cursor position accept either an offset (0-based index into the expression string, friendliest for single-line expressions) or an LSP { line, character } pair (both 0-based).
expreszo_get_completions¶
Returns an array of LSP CompletionItem objects.
position—{ offset }or{ line, character }. Required.variables— optional map of variable names to runtime values. When supplied, completions include the variable names and their type.
expreszo_get_hover¶
Returns a single LSP Hover object (with contents.value as markdown).
positionandvariableshave the same shape asexpreszo_get_completions.
expreszo_get_highlighting¶
Returns an array of highlight tokens: { type, start, end, value? } where type is one of number, string, name, keyword, operator, function, punctuation, constant.
expreszo_get_diagnostics¶
Returns an array of LSP Diagnostic objects. An empty array means the expression parses cleanly and all function calls have valid arity.
produces a diagnostic explaining that pow requires two arguments.
Programmatic use¶
If you want to embed the MCP server inside a larger Node application (for example, a custom transport or a test harness), import createMcpServer from the mcp-server subpath export:
import { createMcpServer } from '@pro-fa/expreszo/mcp-server';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
const server = createMcpServer({
// Optional: limit which operators the language service exposes
operators: { conditional: true, 'in': false }
});
await server.connect(new StdioServerTransport());
createMcpServer accepts the same operators filter as createLanguageService, plus optional name and version strings for the MCP serverInfo.
Local development and debugging¶
From a clone of the repo:
# Run the server against the source (no build needed)
npm run mcp:dev
# Open the official MCP Inspector — lists all 4 tools and lets you
# invoke them interactively with JSON input
npm run mcp:inspect
To smoke-test manually against the built artifact, pipe JSON-RPC directly into the binary:
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"smoke","version":"0.0.0"}}}' \
'{"jsonrpc":"2.0","method":"notifications/initialized","params":{}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' \
| node dist/bin/mcp-server.mjs
You should see the server respond with its serverInfo followed by the list of four expreszo_* tools.