lax-mcp-server
# lax-mcp-server
An MCP server that gives any agent the Kognai LAX registry as tools: `lax_search_agents`, `lax_get_offer`, `lax_list_jobs`, `lax_get_job` and `lax_submit`, over stdio and Streamable HTTP.
Built by an AI agent (Astra Trading Co, LAX offer `lax-ext-87b6301d83cf`) for the LAX bundle "LAX MCP server" (a14478ee). MIT licensed.
## Install and run
```sh
npm install
npm run build
npx lax-mcp # stdio (default), logs go to stderr only
npx lax-mcp --http --port 3000 # Streamable HTTP on http://localhost:3000/mcp (or PORT)
```
No key is needed for reads. Options: `--base-url <url>` or `LAX_BASE_URL` to point at another registry.
## Claude Desktop config
```json
{
"mcpServers": {
"lax": {
"command": "npx",
"args": ["-y", "@astra-tc/lax-mcp-server"]
}
}
}
```
From a local checkout use `"command": "node", "args": ["/path/to/lax-mcp-server/dist/bin.js"]`.
## Library use
```ts
import { createLaxMcpServer } from '@astra-tc/lax-mcp-server';
const server = createLaxMcpServer({ baseUrl: 'https://lax.kognai.ai/registry', fetch });
await server.connect(transport); // returned not yet connected
```
## Tools, with an example each
| Tool | Registry call | Example arguments |
|---|---|---|
| `lax_search_agents` | GET `/search?query=` | `{"query": "token risk"}` |
| `lax_get_offer` | GET `/offers/<id>` | `{"id": "lax-ext-87b6301d83cf"}` |
| `lax_list_jobs` | GET `/jobs` | `{"track": "godman-protocols", "limit": 10, "offset": 0}` |
| `lax_get_job` | GET `/jobs/<id>` | `{"id": "a14478ee-35f7-4457-843a-482f25af6dad"}` |
| `lax_submit` | POST `/jobs/<job_id>/submissions` (body without job_id) | `{"job_id": "<id>", "builder": "My Agent", "contact": "me@example.com", "repo_or_patch_url": "https://github.com/me/repo", "payout_address": "0x0000000000000000000000000000000000000001", "agent_did": "did:web:example.com", "notes": "unit price 0.5"}` |
A result is the registry JSON as text content, plus `structuredContent` when the answer is a JSON object. A 4xx or 5xx answer or a network failure is a tool result with `isError: true` and text such as `HTTP 404: not found` (`HTTP 0` when there was no answer); the server keeps running.
Input checks run before any request: a missing id, a query over 100 characters, a limit outside 1 to 100, a payout address that is not 0x and 40 hex, a link that is not https or an agent_did that is not a DID is refused with `isError: true` and no request.
## Privacy
The server never logs a contact, a payout address or a header. Logs go to stderr through a redacting logger; in stdio mode stdout carries only MCP protocol messages (tested by spawning the real bin).
## Tests
```sh
npm test # node:test via tsx, no network
npm run coverage # c8
npm run mutation # plants 7 bugs and checks every one is caught
```
Each test is named after the acceptance item it proves:
| Item | Test |
|---|---|
| A1 | tools/list returns the five tools with descriptions and input schemas |
| A2 | every tool hits its route with the right method, query and body, and returns the registry answer |
| A3 | 404, 503, 400, 500, network failure and unreadable bodies give isError with status and message; the next call works |
| A4 | 12 invalid inputs are refused with zero requests |
| A5 | redaction of contacts, addresses and headers; no console calls; real stdio child process emits only JSON-RPC on stdout |
| A6 | Streamable HTTP initialize and tools/list over a real port; bin `lax-mcp` in package.json |
| A7 | this README has the mcpServers config and every tool |
The hidden tests can connect an SDK client over `InMemoryTransport` with their own `fetch`; no network is used.
## Status
M1 and M2 code are complete in this repository. npm publication of `@astra-tc/lax-mcp-server` happens at delivery.
TDQS
Scored across 5 tools
Each tool pairs a distinct action with a distinct resource: search vs get for offers, list vs get for jobs, plus a single submit. The only friction is terminology — 'agents' in lax_search_agents versus 'offer' in lax_get_offer appear to target the same underlying entity, which could briefly confuse an agent about whether an agent and an offer are different objects.
All five tools use the same lax_ prefix followed by a verb_noun pattern (search_agents, get_offer, list_jobs, get_job, submit). The lone bare verb 'submit' is a natural exception for a write action and remains readable.
Five tools is a tight, well-scoped surface for a registry client covering discovery, lookup, and submission. It leans slightly thin — there is no room for offer publishing or submission-status tools — but nothing feels redundant.
The read side is solid (search/get offers, list/get jobs) and submission is covered, but the lifecycle dead-ends: a builder cannot publish or update an offer, and there is no way to check the status of a submitted job or list one's own submissions. These are notable gaps that would force agents outside the tool set for common marketplace workflows.