Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 34 additions & 58 deletions src/documentation/user_guides/publishing/mcp_agents.malloynb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ npx @malloy-publisher/server --server_root /path/to/your/packages

The AI sees all packages under your `server_root` directory. The MCP server starts automatically at `http://localhost:4040/mcp`.

The endpoint does not require authentication, and Publisher binds `0.0.0.0` by default, so anyone who can reach port 4040 on your network can run `malloy_executeQuery` against the databases your models connect to. The surface is not read-only either: `malloy_reloadPackage` mutates server state, and for a package that carries an install location a reload re-fetches it, overwriting on-disk edits. The same effects are already reachable through the equivalent REST endpoints, so this is a reason to gate the deployment rather than a reason to avoid the tools. Bind it to loopback with `--host 127.0.0.1` for local-only use, and put an authenticating gateway in front before exposing it more widely.

For other deployment options (Docker, git clone), see [Publish Your Models](publishing.malloynb).

### 2. Configure Your MCP Client
Expand All @@ -40,99 +42,73 @@ Once connected, try prompts like:

---

## Stdio Bridge (VS Code, Claude Desktop, etc.)

Some MCP clients (VS Code, Claude Desktop) require stdio-based commands instead of HTTP. Use the bridge script to translate between protocols.

### Prerequisites

- Python 3.x installed
- Malloy Publisher MCP Server running on `localhost:4040/mcp`

### 1. Download the Bridge

[Download malloy_bridge.py](https://github.com/malloydata/publisher/blob/main/packages/server/dxt/malloy_bridge.py)

Save it somewhere accessible, for example: `~/malloy_bridge.py`

### 2. Configure Your MCP Client
## Stdio-only Clients (older Claude Desktop, etc.)

Example configuration for VS Code (`settings.json` or `.vscode/mcp.json`):
Some MCP clients speak only stdio, not HTTP. Bridge them to the HTTP endpoint with [`mcp-remote`](https://www.npmjs.com/package/mcp-remote), which needs no extra script. In the client's MCP config add:

```json
{
"mcp": {
"servers": {
"malloy": {
"command": "python3",
"args": ["/full/path/to/malloy_bridge.py"]
}
"mcpServers": {
"malloy": {
"command": "npx",
"args": ["-y", "mcp-remote", "http://localhost:4040/mcp", "--allow-http"]
}
}
}
```

Replace `/full/path/to/malloy_bridge.py` with the actual path where you saved the bridge script.

### Testing the Bridge

Test the bridge script:

```bash
echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | python3 /path/to/malloy_bridge.py
```

Check `/tmp/malloy_bridge.log` for debugging information.
`--allow-http` is required because the endpoint is plain HTTP on localhost. For Claude Desktop the config lives under Settings > Developer > Edit Config.

---

## MCP Tools

Publisher exposes these tools to AI agents:
Publisher serves these tools from the single MCP endpoint, alongside the bundled agent skills as prompts.

### Discovery

`malloy_getContext` is the entry point. Every parameter is optional, so an agent can start with nothing and narrow down as it learns the names.

| Tool | Parameters | Description |
|------|------------|-------------|
| `malloy_projectList` | — | List all available projects |
| `malloy_packageList` | `projectName` | List packages in a project |
| `malloy_packageGet` | `projectName`, `packageName` | Get models in a package |
| `malloy_modelGetText` | `projectName`, `packageName`, `modelPath` | Get raw model source code |
| `malloy_getContext` | all optional: `environmentName`, `packageName`, `query`, `sourceName`, `limit` | Progressively discover what is on the server, and the model entities most relevant to a plain-English question. |

Call it with no arguments to list the environments and the packages in each, with an `environmentName` to list that environment's packages, with `environmentName` plus `packageName` to list that package's sources, and with `environmentName` plus `packageName` plus a plain-English `query` to get the sources, views, named queries, and dimension/measure fields most relevant to it, each with its model path and `#(doc)` description. Add `sourceName` alongside a `query` to focus retrieval on a single source.

Each step needs the ones before it: `packageName` without `environmentName` is ignored, and you get the environment list back rather than an error.

The `environmentName`, `packageName`, and `modelPath` it returns map directly onto `malloy_executeQuery`, so an agent can go from a question to a grounded query without guessing names.

### Query Execution

| Tool | Parameters | Description |
|------|------------|-------------|
| `malloy_executeQuery` | `projectName`, `packageName`, `modelPath`, `query` | Run a Malloy query, returns JSON results |
| `malloy_executeQuery` | required: `environmentName`, `packageName`, `modelPath`, and then either `query` or `queryName` plus `sourceName`. Optional: `filterParams`, `givens` | Run a Malloy query: ad hoc with `query`, or a named query or view with `queryName` plus the `sourceName` it belongs to. Exactly one of `query` and `queryName` is required. Returns JSON results. |

---
### Authoring

## Agent Retrieval Tools and Skills
These two close the edit-and-run loop, so an agent can change a model and query the result without restarting the server.

Alongside the core MCP server on `:4040`, Publisher runs a second MCP server for agents on `:4041` (set by `AGENT_MCP_PORT`). It serves two read-only retrieval tools plus the bundled agent skills, configured the same way as the core server but on the agent endpoint:
| Tool | Parameters | Description |
|------|------------|-------------|
| `malloy_compile` | required: `environmentName`, `packageName`, `modelPath`, `source`. Optional: `includeSql`, `givens` | Compile-check Malloy source against a model and get structured diagnostics back, without running a query. The source is appended to `modelPath`, so that model's imports, sources, and queries are in scope. |
| `malloy_reloadPackage` | required: `environmentName`, `packageName` | Recompile a package from its on-disk model files, so a source or view added after boot becomes resolvable by name. Returns the mode it used, `in-place` or `reinstalled`. |

```json
{
"mcpServers": {
"malloy-publisher-agent": {
"url": "http://localhost:4041/mcp"
}
}
}
```
Publisher compiles each configured package at boot and serves that cached model, so a source you add afterwards is not queryable by name until the package is reloaded. `malloy_compile` does not need a reload: it validates against the model as it is on disk.

Compiling before reloading is a speed-up, not a safety measure. A reload that fails to compile leaves your files alone and keeps serving the previously compiled model, returning the compile errors, so nothing breaks either way. `malloy_compile` is simply the faster way to see diagnostics.

### Retrieval tools
One caveat worth knowing: a package whose stored metadata carries an install location is re-fetched from that source on reload, which overwrites on-disk edits. Check the returned mode if you had edits you did not save elsewhere.

### Documentation Search

| Tool | Parameters | Description |
|------|------------|-------------|
| `malloy_getContext` | `environmentName`, `packageName`, `query`, `sourceName` (optional), `limit` (optional) | Given a plain-English question, returns the model entities (sources, views, named queries, and dimension/measure fields) most relevant to it, each with its model path and `#(doc)` description. |
| `malloy_searchDocs` | `query`, `limit` (optional) | Keyword search over a bundled index of the Malloy documentation, returning matching pages with a short excerpt and a link. |

Use `malloy_getContext` in two phases: call it once with just a `query` to discover the most relevant sources and views, then optionally call it again with `sourceName` set to focus on the fields within one source. The `environmentName`, `packageName`, and `modelPath` it returns map directly onto `malloy_executeQuery`, so an agent can go from a question to a grounded query without guessing field names.
| `malloy_searchDocs` | required: `query`. Optional: `limit` | Keyword search over a bundled index of the Malloy documentation, returning matching pages with a short excerpt and a link. |

### Skills as MCP prompts

Publisher also ships a set of agent **skills**: short guides that teach an agent how to write Malloy, choose charts, and verify results. Skill-aware hosts (such as Claude Code and Claude Desktop) load the skill files directly. For hosts that only ingest MCP, the agent server also exposes each skill as an MCP prompt, so the same guidance is available either way: list them with `prompts/list` on the agent endpoint and fetch one with `prompts/get`.
Publisher also ships a set of agent **skills**: short guides that teach an agent how to write Malloy, choose charts, and verify results. Skill-aware hosts (such as Claude Code and Claude Desktop) load the skill files directly. For hosts that only ingest MCP, the server also exposes each skill as an MCP prompt, so the same guidance is available either way: list them with `prompts/list` and fetch one with `prompts/get`.

## Example Prompts

Expand Down
Loading