Blawx MCP Server
by Lexpedite
README.md
# THIS REPOSITORY IS DEPRECATED AS OF BLAWX v2.2.3, June 20, 2026
# OFFICIAL MCP SUPPORT FOR BLAWX IS NOW VIA REMOTE MCP
# SEE DOCUMENTATION AT HTTPS://APP.BLAWX.DEV
# blawx-mcp
A minimal run-local MCP server that calls the Blawx API using a Blawx API key.
## Prereqs
- Python 3.10+
## Install
From this repo root:
```bash
python -m pip install -e .
```
### Example: Windows + Claude Desktop
This is one way to set up the MCP server locally for Claude Desktop on Windows.
1. Clone the repository locally.
```powershell
git clone https://github.com/Lexpedite/blawx_mcp.git
cd blawx_mcp
```
2. Install the package.
```powershell
python -m pip install .
```
3. Generate an API key from the Blawx profile page. In the left navigation bar, click "Profile", then use the "Add API Key" button. Copy the key when it is shown.
4. Add the MCP server to your Claude Desktop configuration file, typically at `%APPDATA%\Claude\claude_desktop_config.json`:
```json
{
"mcpServers": {
"blawx-mcp": {
"command": "python",
"args": ["-m", "blawx_mcp", "--stdio"],
"env": {
"BLAWX_API_KEY": "your API Key Here"
}
}
}
}
```
The MCP server no longer needs `team_slug` or `project_id` at startup. Agents discover teams at runtime with `blawx_teams_list`, choose a team slug, then discover projects with `blawx_projects_list`.
You will need to completely quit Claude Desktop (using the Claude icon in the system tray and selecting "Quit", then restarting) and restart for
the changes to your configuration to take effect.
## Configuration
Set required configuration in your environment:
```bash
export BLAWX_API_KEY="your_key_here"
```
Team and project selection happen at tool-call time instead of startup time.
Use `blawx_teams_list` after connecting the server. If it returns exactly one team, use that team's `slug` as `team_slug`; if it returns multiple teams and the user has not already identified one, ask the user which team to use. Then call `blawx_projects_list` with `team_slug` and pass both `team_slug` and the returned `project_id` to every project-scoped tool.
You can create a Blawx API Key if you have a Pro subscription to Blawx.
Click on "Profile" in the left navigation bar, and find the "Add API
Key" button. When you click the button your API key will be displayed
only once at the top of the screen. Copy and paste it into your
environment settings.
## Run
Run the MCP server from this folder (no install required).
For SSE/HTTP transport:
```bash
./.venv/bin/python -m blawx_mcp
```
Defaults:
- Binds to `127.0.0.1:8765`
- SSE endpoint at `http://127.0.0.1:8765/sse`
Optional server bind overrides:
```bash
export BLAWX_MCP_HOST="127.0.0.1"
export BLAWX_MCP_PORT="8765"
```
For stdio transport, which is useful for local clients such as Claude Desktop:
```bash
./.venv/bin/python -m blawx_mcp --stdio
```
## Connect to Your Coding Agent
Coding agents differ in how they configure MCP servers. This is a typical
tool definition in your `mcp.json` for VS Code.
```
{
"servers": {
"my-blawx-sse-server": {
"url": "http://127.0.0.1:8765/sse",
"type": "http"
}
},
"inputs": []
}
```
## Tools
These tools give your coding agent the following capabilities:
All project-scoped tools require both `team_slug` and `project_id`. Agents should always call `blawx_teams_list` first. If there is only one team, use that team's slug; if there are multiple teams and the user has not already identified one, ask the user which team to use. Then call `blawx_projects_list` with that `team_slug` and pass both `team_slug` and the returned `project_id` to every later ontology, legal-doc, question, fact-scenario, ask/answer, and encoding tool.
Unless noted otherwise, MCP tools return a compact structured response with `status_code`, `ok`, and `body`. Some tools also include `workflow_hint` and `next_recommended_tool`. Request URLs, headers, params, and echoed payloads are intentionally omitted from tool output.
Two tools intentionally return MCP text content blocks instead of structured JSON: `blawx_encoding_guide` and `blawx_legaldocparts_list`.
1. Discover teams and choose a `team_slug`.
2. Discover projects under that team and choose a `project_id`.
3. Discover what the chosen project exposes (declared objects, questions, fact scenarios, ontology).
4. Create, update, and delete LegalDocs, LegalDocParts, and EncodingParts.
5. Ask a question (using either a stored fact scenario or a custom facts payload).
6. Browse answers and drill into explanations (model/attributes/explanation text).
Here's a brief run-down of the available tools.
### Health check
- `blawx_health`: verifies the Blawx app is reachable and returns the compact status/body envelope.
### Discover Project Content
Agents should start by listing teams, then listing projects under the selected team.
- `blawx_teams_list`: lists the teams available to the configured API key.
- `blawx_projects_list`: lists the available projects for a `team_slug`.
Once a team and project are chosen, every project-scoped tool requires explicit `team_slug` and `project_id` arguments.
Agents will then usually list the available questions, fact scenarios, and vocabulary.
- `blawx_declared_objects_list`: lists objects declared across the project's encoding parts as `{"declared_objects": [{"symbol": "...", "legal_doc_part_id": 123}]}`; use before writing fact scenarios, questions, or encodings that refer to entities. When the symbol meaning is unclear, inspect the cited legal doc part text to interpret it.
- `blawx_questions_list`: lists shared questions available in the project.
- `blawx_question_detail`: retrieves a specific question's details (useful when deciding which question id to ask).
- `blawx_fact_scenarios_list`: lists stored fact scenarios (prebuilt sets of facts you can re-use).
- `blawx_fact_scenario_detail`: shows the facts contained in a specific fact scenario.
- `blawx_ontology_list`: primary ontology discovery tool; lists categories, relationships, and relationship parameters with the details needed for encoding.
- `blawx_ontology_category_detail`: focused lookup for one category already present in `blawx_ontology_list`.
- `blawx_ontology_relationship_detail`: focused lookup for one relationship already present in `blawx_ontology_list`, including the same arity/parameter information.
Additional read-write tools are also available for project editing (questions, fact scenarios, ontology categories/relationships/parameters).
Examples:
```json
{
"team_slug": "my-team",
"project_id": 60
}
```
```json
{
"team_slug": "my-team",
"project_id": 60,
"question_id": 123
}
```
For write operations:
- `blawx_encodingpart_update`, `blawx_question_create`, `blawx_question_update`, `blawx_fact_scenario_create`, and `blawx_fact_scenario_update` all use the same payload shape:
```json
{
"payload": {
"blawx_json": {
"...": "..."
}
}
}
```
For question saves specifically, the encoding is expected to include a single outer question block.
- Ontology write tools accept plain JSON objects under `payload`, not `blawx_json` workspaces.
Current API validation requires these minimum shapes:
```json
{
"payload": {
"name": "Contract",
"slug": "contract",
"short_description": "",
"nlg_prefix": "",
"nlg_postfix": "is a contract",
"nlg_pattern": "{1} is a contract"
}
}
```
```json
{
"payload": {
"name": "Estimated Expenditure",
"slug": "estimated_expenditure",
"short_description": "",
"nlg_prefix": "",
"nlg_pattern": "{1}'s estimated expenditure is {2}"
}
}
```
```json
{
"relationship_id": 458,
"payload": {
"order": 1,
"type_id": 466,
"nlg_postfix": ""
}
}
```
Notes:
- Category create/update currently requires `name` and `slug`; `nlg_postfix` must be 50 characters or fewer.
- Relationship create/update currently requires `name` and `slug`.
- `nlg_pattern` on categories and relationships illustrates how statements using that predicate appear in the coding interface and natural language explanations.
- Relationship-parameter create/update currently requires `order` and `type_id`.
- Use `blawx_ontology_list` or `blawx_ontology_category_detail` to discover valid category ids for `type_id`.
Patch-style tools are intentionally not exposed in this MCP server to reduce tool-selection ambiguity.
### Ask Questions
- `blawx_question_ask_with_fact_scenario`: asks a question using a stored fact scenario.
- `blawx_question_ask_with_facts`: asks a question using an explicit facts payload generated by your agent based on your
instructions.
Both ask tools require `team_slug` and `project_id` in addition to `question_id` and their respective payload arguments.
Both ask tools currently require shared questions.
If you call either `blawx_question_ask_with_fact_scenario` or
`blawx_question_ask_with_facts` with a non-shared question id, the Blawx app may return
`Question not available via API.` Use a question from `blawx_questions_list`,
or set `shared: true` on the question first.
**NB**: It's not clear how good agents will be at generating
representations of complicated fact scenarios in complicated
vocabularies. It can be helpful to review how your agent
formulated your fact scenario if you get unexpected results,
and to give it hints on how to do better.
When you pose a question, the answer is saved on the Blawx
server for approximately 30 minutes, and your agent can
review it over that period of time. Once the data expires,
your agent will need to pose the question again to analyse
the responses further. Based on the instructions provided
by the MCP server, it should know to do that when and if
required.
### Review Answers
Blawx's answers can be quite large, and agents have a limited
context window, so the process of reviewing
answers is broken into multiple steps.
1. Get the list of answers to the question.
2. Get the list of explanations for a specific answer.
3. Look at the parts of a specific explanation.
- `blawx_list_answers`: gives the list of answers available,
and the bindings in those answers.
- `blawx_cached_response_meta`: metadata (ttl, created, answer_count) for a cached response.
- `blawx_list_explanations`: gives the list of explanations available for an answer
There are four tools to retrieve specific parts of an
explanation. These tools all allow the agent to select the
entire part, or if it is too long, to select only certain
lines at a time.
- `blawx_get_model_part`: this returns the answer set
- `blawx_get_attributes_part`: this returns the constraints applied to variables in the model and explanations
- `blawx_get_explanation_part`: this is the tree-structured,
human-readable explanation for the answer
- `blawx_get_constraint_satisfaction_part`: this is the portion
of the explanation that shows how global constraints were satisfied. This is often both verbose and unhelpful, so it
is separated out. You may need to ask your agent to seek it
specifically if you know your encoding uses constraints and
you need to know how they are satisfied.
### Visualize Blawx Code
Blawx code (questions, fact scenarios, and encoding parts) is stored as a Blockly
workspace in a `blawx_json` field. To let the user *see* that code as rendered
Blawx blocks instead of raw JSON, use the read-only code viewer.
- `blawx_view_code`: renders an arbitrary `blawx_json` workspace as read-only
Blawx blocks (no toolbox, no editing). It carries MCP App UI metadata, so a host
that supports MCP Apps renders the viewer in-frame. This tool does not call the
Blawx server.
The `blawx_json` argument is the full Blockly workspace object (it has a top-level
`blocks` key). It can be code your agent authored, or — more commonly — the
`blawx_json` value from the `body` of a read tool such as `blawx_question_detail`,
`blawx_fact_scenario_detail`, or `blawx_encodingpart_get`. Optional `title`,
`known_objects_list`, and `known_relationship_dict` arguments are accepted; only
`blawx_json` is required.
```json
{
"blawx_json": { "blocks": { "languageVersion": 0, "blocks": [ "..." ] } },
"title": "Section 4 encoding"
}
```
The viewer is served as a self-contained MCP App resource (`ui://blawx/code-viewer`)
with the Blockly runtime and Blawx block definitions inlined, so it needs no
network access at render time. The bundled block definitions are generated from
the `blawx_saas` repo; see `src/blawx_mcp/ui/VENDOR.md` for how to refresh them.
### Legal Docs + Encoding
The API supports read-write legal documents, legal document parts, and encoding parts, and this MCP server now exposes CRUD tools for all three layers.
- `blawx_legaldocs_list`, `blawx_legaldoc_create`, `blawx_legaldoc_detail`, `blawx_legaldoc_update`, `blawx_legaldoc_delete`
- `blawx_legaldocparts_list`, `blawx_legaldocpart_create`, `blawx_legaldocpart_detail`, `blawx_legaldocpart_update`, `blawx_legaldocpart_delete`
- `blawx_encoding_guide`, `blawx_encodingpart_get`, `blawx_encodingpart_update`, `blawx_encodingpart_delete`
All of these tools require `team_slug` and `project_id`.
Default LegalDocPart granularity rule: preserve the legislative hierarchy. Each heading gets its own part, each section gets its own part for section-level text, a section with no subordinate units is one part, and each subsection, paragraph, or similar subordinate unit gets its own part when it has distinct text. Do not merge separately addressable legislative units into one part just because their logic is related.
For the full LegalDocPart structure guidance, including `parent_id`, `include_parent`, `include_sibling`, and worked examples, read `blawx_encoding_guide` topic `legaldocs`.
**To read legislation text, use this sequence:**
1. `blawx_teams_list` to choose a `team_slug`.
2. `blawx_projects_list` to choose a `project_id`.
3. `blawx_legaldocs_list` (or `blawx_legaldoc_detail`) to identify a `legal_doc_id`.
4. `blawx_legaldocparts_list` to read the Markdown outline for that document. This MCP tool returns the outline as a text content block, not structured data. The outline includes part IDs, optional encoding IDs and markers, hierarchy indentation, index text, and short part text.
5. `blawx_legaldocpart_detail` for each relevant `legal_doc_part_id` when you need full fields, content-in-context, pincite, or `encoding_part_id`. Detail responses do not include `parent_id`, `path`, `depth`, or `numchild`; use the parts outline for hierarchy.
In the parts outline, each item follows `- <legaldocpart_id> [<encodingpart_id> <marker>] <index> <text>`. Marker `!` means the encoding part has content; marker `.` means it exists but is empty. Non-substantive legal document part content is bolded.
**To create or update document structure:**
1. `blawx_encoding_guide` with topic `legaldocs`.
2. `blawx_legaldoc_create` or `blawx_legaldoc_update` with payload:
```json
{
"team_slug": "my-team",
"project_id": 60,
"payload": {
"name": "Financial Administration Act",
"slug": "FAA",
"tag_ids": []
}
}
```
3. `blawx_legaldocpart_create` with payload such as:
```json
{
"team_slug": "my-team",
"project_id": 60,
"legal_doc_id": 78,
"payload": {
"element_type": "Section",
"index_text": "41",
"text_content": "No contract shall be entered into...",
"substantive": true
}
}
```
For part updates, omit `parent_id`. The current Blawx API rejects re-parenting via PUT.
**Use this sequence first**:
1. Call `blawx_encoding_guide` (topic `quickstart`, then `encoding-process`, then `encodingpart`, then `blawx-json`).
Additional available topics include:
- `valid-blawx-json`: concrete valid payload patterns for `blawx_json`
- `blawx-blocks`: quick reference of available block types and required components
- `encoding-process`: step-by-step workflow for creating and updating encoding parts
- `legaldocs`: LegalDoc and LegalDocPart structure, write fields, and project-selection workflow
2. Call `blawx_encodingpart_get` to inspect existing encoding.
3. Call `blawx_encodingpart_update` with payload shape:
```json
{
"payload": {
"blawx_json": {
"...": "..."
}
}
}
```
`blawx_encodingpart_update` accepts only **Blawx JSON blocks** via `payload.blawx_json`. Do not send `content`, `scasp_encoding`, or stringified JSON.
**NB**: The other three parts should be read alongside the
attributes, or relevant information may be missing. This
instruction is provided to the agent, but if it isn't followed
your agent may draw incorrect conclusions. It may be wise to
instruct your agent to check the attributes in addition to
the other parts of an explanation.
## Typical Workflow
1. Start the server with `BLAWX_API_KEY`.
2. Call `blawx_teams_list` and choose a `team_slug`; if only one team is returned, use it.
3. Call `blawx_projects_list` with `team_slug` and choose a `project_id`.
4. Pass that `team_slug` and `project_id` to ontology, fact-scenario, question, ask/answer, legal-doc, legal-doc-part, and encoding-part tools.
## Development
The Blawx server used can be overridden for local development
- `BLAWX_BASE_URL` (default: `https://app.blawx.dev`)
## Embedding as a Library (multi-tenant / hosted use)
`blawx_mcp` can be imported as a library in a hosted multi-tenant server. Use
`settings_context()` to inject per-request `Settings` so concurrent requests from
different users never collide on configuration or cached state.
```python
from blawx_mcp import Settings, settings_context
from blawx_mcp.config import _settings_override
settings = Settings(
base_url="https://app.blawx.dev",
api_key="my-key",
)
token = settings_context(settings)
try:
# ... invoke MCP tools in this async context ...
pass
finally:
_settings_override.reset(token)
```
`settings_context()` uses Python's `contextvars.ContextVar` under the hood, which is
async-safe: each `asyncio` task inherits its own copy of the context so concurrent
requests cannot collide even when running in the same event loop. Team selection is
provided by MCP tool arguments, so hosted consumers should pass `team_slug` through
the team-scoped tool calls rather than injecting it into settings.
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessUnresponsive