Skip to main content
Glama
petri-net-sim

pns-server MCP Server

README.md
# pns-server

Backend service that converts natural language descriptions of production and queueing systems into Petri net models exported in PNML format (compatible with TINA, PetriObjModel, CPN Tools).

**Web UI**: [pns-ui-web](https://github.com/petri-net-sim/pns-ui-web)

---

## Stack

| Layer | Technology |
|---|---|
| Runtime | Python 3.13 |
| Web framework | FastAPI + Uvicorn |
| AI agent | LangGraph + LangChain |
| LLM providers | OpenAI, Anthropic, Ollama |
| Database | PostgreSQL (async via SQLAlchemy + asyncpg) |
| Session cache | Redis |
| Protocol | OpenAI-compatible REST + MCP (Model Context Protocol) |
| Migrations | Alembic |

---

## Quick start (Docker)

### Local — single command, auto-generated secrets

Runs PostgreSQL + backend. No Redis. Every user provides their own LLM API key via the Settings page.

```bash
docker compose -f docker-compose.local.yml up -d

# View auto-generated secrets on first start
docker compose -f docker-compose.local.yml logs app | grep -A 10 "AUTO-GENERATED"

# Health check
curl http://localhost:8000/health
```

### Production — with Redis, PostgreSQL, Nginx

```bash
cp .env.example .env
# Fill in all required values in .env

docker compose -f docker-compose.prod.yml up -d
docker compose -f docker-compose.prod.yml ps
```

**Nginx reverse proxy config:**

```nginx
server {
    listen 80;
    server_name your-domain.com;

    location /api/   { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }
    location /health { proxy_pass http://127.0.0.1:8000; }
    location /mcp {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_read_timeout 3600s;
        proxy_buffering off;
        proxy_cache off;
        chunked_transfer_encoding on;
    }
}
```

**Scale workers (default: 2):**

```bash
UVICORN_WORKERS=4 docker compose -f docker-compose.prod.yml up -d backend
```

---

## Local development

```bash
# Install dependencies (uv package manager)
uv sync --extra dev

# Start dependencies
docker compose up -d

# Apply migrations
uv run alembic upgrade head

# Start server with hot reload
uv run uvicorn main:app --reload --host 0.0.0.0 --port 8000

# Run tests
uv run pytest -v
```

---

## API

### OpenAI-compatible

| Method | Path | Description |
|--------|------|-------------|
| POST | `/api/v1/chat/completions` | Chat completion (stream/non-stream) |
| GET | `/api/v1/models` | List available models |
| GET | `/api/v1/files/{file_id}` | Download generated PNML file |

Auth: `Authorization: Bearer sk-...`

### Auth & API Keys

| Method | Path | Description |
|--------|------|-------------|
| POST | `/api/v1/auth/signup` | Register |
| POST | `/api/v1/auth/login` | Log in, returns JWT pair |
| POST | `/api/v1/auth/refresh` | Refresh tokens |
| GET | `/api/v1/auth/me` | Current user |
| POST | `/api/v1/auth/api-keys` | Create API key |
| GET | `/api/v1/auth/api-keys` | List API keys |
| DELETE | `/api/v1/auth/api-keys/{id}` | Revoke API key |

### LLM Credentials (BYOK)

| Method | Path | Description |
|--------|------|-------------|
| POST | `/api/v1/llm-credentials` | Store encrypted LLM API key |
| GET | `/api/v1/llm-credentials` | List profiles |
| PATCH | `/api/v1/llm-credentials/{id}` | Update profile |
| DELETE | `/api/v1/llm-credentials/{id}` | Delete profile |
| POST | `/api/v1/llm-credentials/{id}/test` | Verify connectivity |

### Sessions & Simulation

| Method | Path | Description |
|--------|------|-------------|
| GET | `/api/v1/sessions` | List user sessions |
| GET | `/api/v1/sessions/{id}` | Get session |
| POST | `/api/v1/sessions/{id}/simulate` | Run simulation (SSE stream) |
| GET | `/api/v1/sessions/{id}/snapshots` | List net snapshots |

### Health

| Method | Path | Description |
|--------|------|-------------|
| GET | `/health` | Liveness probe |
| GET | `/health/ready` | Readiness probe (checks DB + Redis) |

---

## MCP Server (Model Context Protocol)

The MCP server is mounted at `/mcp` on the main port and also available standalone.

| Mode | Command | Endpoint |
|------|---------|----------|
| Unified (default) | `uvicorn main:app` | `http://host:8000/mcp` |
| Standalone HTTP | `uv run python mcp_server.py` | `http://host:8001/mcp` |
| Standalone stdio | `uv run python mcp_server.py --stdio` | — |

The MCP server exposes 50+ tools for Petri net construction, simulation, and export directly to MCP-compatible clients.

---

## Architecture

```
src/
├── api/              # Common API infrastructure (health, versioning, middleware)
├── openai_api/       # OpenAI-compatible protocol (chat completions, models, files)
├── core/             # Config, DI, logging, lifecycle
├── domain/           # Pure domain logic
│   ├── models/       # PetriNet, Place, Transition, Arc
│   ├── patterns/     # 29 reusable Petri net building blocks
│   └── layout/       # Sugiyama hierarchical layout algorithm
├── infrastructure/   # PostgreSQL (SQLAlchemy) + Redis
├── mcp/              # MCP server — tools, resources, prompts
└── services/
    ├── agent/        # LangGraph workflow (graph, nodes, tools)
    ├── chat/         # Chat orchestration, session management
    ├── petri/        # Builder, Optimizer, PNML exporter
    ├── simulation/   # Discrete-event Petri net simulator
    ├── llm/          # Per-credentials LLM factory (OpenAI / Anthropic / Ollama)
    ├── crypto/       # Fernet encryption for stored API keys
    ├── usage/        # Free-tier Redis counters
    └── auth/         # JWT, API keys, OAuth
```

### Petri net patterns (29 total)

Core: Generator, Machine, Controller, Assembly, Router, Terminator, Buffer, BoundedQueue

Flow control: PriorityChoice, ThresholdActivation, Merge, Duplicate

Advanced: QualityCheck, FeedbackLoop, Conveyor, ConveyorWorkstation, TransportAgent

Batching: Batch, Unbatch, TimedBatch

Reliability: Breakdown, ScheduledAvailability, PreemptiveMachine, SetupMachine

Queueing: RenegingQueue, BalkingQueue, MultiResource, ServerVacation, NonstationaryGenerator

---

## Key environment variables

| Variable | Default | Description |
|----------|---------|-------------|
| `APP_ENV` | `local` | Environment (`local` / `stage` / `prod`) |
| `AGENT_LLM_PROVIDER` | `openai` | LLM provider (`openai` / `anthropic` / `ollama`) |
| `AGENT_LLM_MODEL` | `gpt-4o` | Model name |
| `OPENAI_API_KEY` | — | OpenAI API key |
| `ANTHROPIC_API_KEY` | — | Anthropic API key |
| `DB_HOST` / `DB_PORT` / `DB_NAME` | — | PostgreSQL connection |
| `REDIS_HOST` / `REDIS_PORT` | — | Redis connection |
| `REDIS_ENABLED` | `true` | Enable Redis |
| `AUTH_JWT_SECRET_KEY` | — | JWT signing key (min 32 chars) |
| `LLM_BYOK_REQUIRED` | `true` | Require user-provided LLM credentials |
| `CREDENTIALS_CIPHER` | `fernet` | Encryption mode (`fernet` / `noop`) |
| `CREDENTIALS_MASTER_KEY` | — | 32-byte base64 key for Fernet |
| `SIMULATION_REMOTE_URL` | — | Optional external simulation backend |

See `.env.example` for the full reference.

---

## CI/CD

Push to `main` → GitHub Actions builds Docker image → pushes to `ghcr.io` → deploys via SSH.

Required GitHub secrets: `SERVER_HOST`, `SERVER_USER`, `SERVER_SSH_KEY`, `DEPLOY_PATH`.

---

## License

MIT

TDQS

B3.2/5.0

Scored across 66 tools

Disambiguation4/5

Most tools have clearly distinct purposes, with detailed descriptions that differentiate similar patterns (e.g., add_queue variants, add_conveyor vs add_conveyor_line). A few pairs like add_batch and add_timed_batch could cause minor confusion but are well-documented.

Naming Consistency5/5

The naming is fully consistent, using snake_case throughout with a clear verb_noun pattern (add_*, connect_*, modify_*, remove_*, etc.). All tool names follow predictable conventions without mixing styles.

Tool Count4/5

66 tools is high, but justified for a comprehensive Petri net modeling tool. The count reflects the many pattern variants and low-level operations needed. However, some users might find it overwhelming, so it's slightly above ideal.

Completeness5/5

The tool set is exceptionally complete, covering creation, modification, connection, layout, simulation, validation, and export. It includes a wide range of high-level patterns and low-level primitives, leaving no obvious gaps in the modeling workflow.

Maintenance

ActivityMaintained
ResponsivenessSyncing