mcp-agent-app
by Nelev
README.md
# mcp-agent-app
A TypeScript service that converts **GeoJSON geometries into 3D triangulated meshes** using a local LLM (Ollama). It exposes an MCP tool (`generate_mesh`) and an HTTP API, making mesh generation accessible both to MCP-compatible clients and standard REST consumers.
```
POST /generate-mesh
│
▼
Express API (src/api/index.ts)
│
▼
generateMeshAgent (src/agents/generate_mesh_agent.ts)
│
▼
Ollama LLM ──────────────────────────────────────────> MeshData
(llama3.2 @ localhost:11434) { vertices, indices, metadata }
MCP server (src/server.ts) exposes the same agent as an MCP tool over stdio
```
## Stack
| Layer | Technology |
|---|---|
| Language | TypeScript 5 (strict, ES2022, ESM) |
| Runtime | Node.js 18+ with `tsx` for development |
| Web framework | Express 4 |
| MCP SDK | `@modelcontextprotocol/sdk` v1.29, `@modelcontextprotocol/server` v2.0 alpha |
| Schema validation | Zod |
| Local LLM | Ollama (`llama3.2` at `http://localhost:11434`) |
> **Note:** The MCP server and HTTP API use Ollama for inference — no Anthropic API key is required for the core mesh generation. `ANTHROPIC_API_KEY` is only needed if you extend the agent loop with Claude tool-use.
## Project structure
```
src/
├── server.ts # MCP server — registers and runs the generate_mesh tool
├── agents/
│ └── generate_mesh_agent.ts # Core logic: GeoJSON → Ollama → MeshData
└── api/
└── index.ts # Express HTTP API wrapping the agent
```
## Prerequisites
1. **Node.js 18+**
2. **Ollama** running locally with the `llama3.2` model pulled:
```bash
ollama pull llama3.2
ollama serve # must be running on http://localhost:11434
```
## Setup
```bash
npm install
```
## Run (dev, no build step)
```bash
npm run dev # starts the Express API on port 3000 (default)
```
In another terminal:
```bash
curl -X POST http://localhost:3000/generate-mesh \
-H "Content-Type: application/json" \
-d '{"geometry": "{\"type\":\"Polygon\",\"coordinates\":[[[0,0],[1,0],[1,1],[0,1],[0,0]]]}"}'
```
The `geometry` field accepts either a **JSON string** or a **parsed GeoJSON object** (Geometry or Feature).
Expected response shape:
```json
{
"vertices": [0, 0, 0, 1, 0, 0, ...],
"indices": [0, 1, 2, ...],
"metadata": {
"featureType": "Polygon",
"vertexCount": 8,
"triangleCount": 4
}
}
```
### Mesh conventions
| Geometry type | Mesh output |
|---|---|
| Polygon / MultiPolygon | Flat base (z=0) + extruded top (z=10) + side walls |
| LineString | Ribbon mesh, width 0.0001° |
| Point | Small pyramid |
Coordinates map as: longitude → x, latitude → y, elevation → z.
## Build & run (production)
```bash
npm run build
npm start
```
## Run the MCP server standalone
```bash
npm run mcp
# or inspect it interactively:
npx @modelcontextprotocol/inspector npx tsx src/server.ts
```
The MCP server exposes one tool — `generate_mesh` — that accepts a GeoJSON geometry or Feature as a JSON string and returns the same `MeshData` structure as the HTTP API.
## NPM scripts
| Script | Description |
|---|---|
| `npm run dev` | Start API in watch mode via `tsx` |
| `npm start` | Run compiled `dist/api/index.js` |
| `npm run build` | Compile TypeScript to `dist/` |
| `npm run mcp` | Run the MCP server standalone |
## Environment variables
| Variable | Default | Description |
|---|---|---|
| `PORT` | `3000` | Express server port |
| `CORS_ORIGINS` | `http://localhost:5173` | Comma-separated list of allowed CORS origins |
## Notes
- The MCP server logs to **stderr**, never stdout — stdout is the stdio protocol channel.
- Ollama responses are validated with a Zod schema; a regex fallback handles markdown-wrapped JSON output.
- The HTTP API allows requests with no `Origin` header (server-to-server calls) in addition to the CORS allowlist.
- For production: TLS at a reverse proxy, auth + rate limiting in front of `/generate-mesh`, and request timeouts via `AbortController`.
- To swap in a remote MCP server, replace `StdioClientTransport` with `StreamableHTTPClientTransport` in the MCP manager.
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues