umlforge 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- umlforge-0.1.0/.claude/settings.json +19 -0
- umlforge-0.1.0/.env.example +57 -0
- umlforge-0.1.0/.github/workflows/ci.yml +56 -0
- umlforge-0.1.0/.gitignore +64 -0
- umlforge-0.1.0/.mcp.json +9 -0
- umlforge-0.1.0/.railway/README.md +98 -0
- umlforge-0.1.0/PKG-INFO +76 -0
- umlforge-0.1.0/README.md +151 -0
- umlforge-0.1.0/alembic/README +1 -0
- umlforge-0.1.0/alembic/env.py +85 -0
- umlforge-0.1.0/alembic/script.py.mako +28 -0
- umlforge-0.1.0/alembic/versions/000_create_base_schema.py +122 -0
- umlforge-0.1.0/alembic/versions/001_add_dashboard_auth_fields.py +35 -0
- umlforge-0.1.0/alembic/versions/002_rename_socratic_to_guided.py +24 -0
- umlforge-0.1.0/alembic/versions/003_add_key_lookup_hash.py +33 -0
- umlforge-0.1.0/alembic.ini +44 -0
- umlforge-0.1.0/all-commits.patch +3100 -0
- umlforge-0.1.0/api/__init__.py +0 -0
- umlforge-0.1.0/api/_rate_limiter.py +5 -0
- umlforge-0.1.0/api/auth.py +221 -0
- umlforge-0.1.0/api/auth_routes.py +545 -0
- umlforge-0.1.0/api/billing.py +321 -0
- umlforge-0.1.0/api/billing_routes.py +159 -0
- umlforge-0.1.0/api/config.py +248 -0
- umlforge-0.1.0/api/db.py +166 -0
- umlforge-0.1.0/api/email.py +256 -0
- umlforge-0.1.0/api/free_tier_budget.py +61 -0
- umlforge-0.1.0/api/limiter.py +191 -0
- umlforge-0.1.0/api/main.py +443 -0
- umlforge-0.1.0/api/models/__init__.py +9 -0
- umlforge-0.1.0/api/models/inputs.py +37 -0
- umlforge-0.1.0/api/models/orm.py +309 -0
- umlforge-0.1.0/api/models/responses.py +50 -0
- umlforge-0.1.0/api/prompts/__init__.py +45 -0
- umlforge-0.1.0/api/prompts/base.py +406 -0
- umlforge-0.1.0/api/prompts/p01_reverse_engineer.py +296 -0
- umlforge-0.1.0/api/prompts/p02_stakeholder_arch.py +90 -0
- umlforge-0.1.0/api/prompts/p03_api_sequence.py +82 -0
- umlforge-0.1.0/api/prompts/p04_state_machine.py +101 -0
- umlforge-0.1.0/api/prompts/p05_living_docs.py +98 -0
- umlforge-0.1.0/api/prompts/p06_erd_schema.py +103 -0
- umlforge-0.1.0/api/prompts/p07_threat_model.py +200 -0
- umlforge-0.1.0/api/prompts/p08_frontend_components.py +105 -0
- umlforge-0.1.0/api/prompts/p09_event_driven.py +106 -0
- umlforge-0.1.0/api/prompts/p10_onboarding.py +106 -0
- umlforge-0.1.0/api/prompts/p11_ai_agent.py +114 -0
- umlforge-0.1.0/api/prompts/p12_deployment.py +112 -0
- umlforge-0.1.0/api/prompts/suggest.py +136 -0
- umlforge-0.1.0/api/providers/__init__.py +18 -0
- umlforge-0.1.0/api/providers/anthropic_provider.py +73 -0
- umlforge-0.1.0/api/providers/base.py +38 -0
- umlforge-0.1.0/api/providers/factory.py +72 -0
- umlforge-0.1.0/api/providers/google_provider.py +81 -0
- umlforge-0.1.0/api/providers/ollama_provider.py +100 -0
- umlforge-0.1.0/api/providers/openai_provider.py +93 -0
- umlforge-0.1.0/api/router.py +83 -0
- umlforge-0.1.0/api/usage.py +188 -0
- umlforge-0.1.0/api/validator.py +208 -0
- umlforge-0.1.0/connector/README.md +54 -0
- umlforge-0.1.0/connector/__init__.py +0 -0
- umlforge-0.1.0/connector/__main__.py +10 -0
- umlforge-0.1.0/connector/api_client.py +154 -0
- umlforge-0.1.0/connector/config.py +94 -0
- umlforge-0.1.0/connector/requirements.txt +12 -0
- umlforge-0.1.0/connector/server.py +33 -0
- umlforge-0.1.0/connector/tools.py +568 -0
- umlforge-0.1.0/dashboard/.env.example +20 -0
- umlforge-0.1.0/dashboard/DEPLOY.md +115 -0
- umlforge-0.1.0/dashboard/app/billing/page.tsx +267 -0
- umlforge-0.1.0/dashboard/app/dashboard/page.tsx +283 -0
- umlforge-0.1.0/dashboard/app/docs/getting-started/page.tsx +272 -0
- umlforge-0.1.0/dashboard/app/docs/how-to/page.tsx +366 -0
- umlforge-0.1.0/dashboard/app/docs/page.tsx +123 -0
- umlforge-0.1.0/dashboard/app/forgot-password/page.tsx +90 -0
- umlforge-0.1.0/dashboard/app/globals.css +9 -0
- umlforge-0.1.0/dashboard/app/layout.tsx +28 -0
- umlforge-0.1.0/dashboard/app/login/page.tsx +100 -0
- umlforge-0.1.0/dashboard/app/page.tsx +244 -0
- umlforge-0.1.0/dashboard/app/reset-password/page.tsx +133 -0
- umlforge-0.1.0/dashboard/app/signup/page.tsx +161 -0
- umlforge-0.1.0/dashboard/app/verify/page.tsx +67 -0
- umlforge-0.1.0/dashboard/components/CreateKeyModal.tsx +151 -0
- umlforge-0.1.0/dashboard/lib/api.ts +91 -0
- umlforge-0.1.0/dashboard/next-env.d.ts +6 -0
- umlforge-0.1.0/dashboard/next.config.js +9 -0
- umlforge-0.1.0/dashboard/package-lock.json +2210 -0
- umlforge-0.1.0/dashboard/package.json +26 -0
- umlforge-0.1.0/dashboard/postcss.config.js +6 -0
- umlforge-0.1.0/dashboard/tailwind.config.js +22 -0
- umlforge-0.1.0/dashboard/tsconfig.json +41 -0
- umlforge-0.1.0/dashboard/tsconfig.tsbuildinfo +1 -0
- umlforge-0.1.0/dashboard/vercel.json +25 -0
- umlforge-0.1.0/dashboard/wrangler.toml +5 -0
- umlforge-0.1.0/infra/db/schema.sql +88 -0
- umlforge-0.1.0/pyproject.toml +41 -0
- umlforge-0.1.0/pytest.ini +5 -0
- umlforge-0.1.0/railway.toml +11 -0
- umlforge-0.1.0/requirements-dev.txt +17 -0
- umlforge-0.1.0/requirements.txt +45 -0
- umlforge-0.1.0/ruff.toml +31 -0
- umlforge-0.1.0/scripts/setup_paystack_plans.py +115 -0
- umlforge-0.1.0/test_phase3_app.py +259 -0
- umlforge-0.1.0/tests/conftest.py +18 -0
- umlforge-0.1.0/tests/test_integration.py +722 -0
- umlforge-0.1.0/tests/test_phase10_connector.py +351 -0
- umlforge-0.1.0/tests/test_phase11_auth_routes.py +511 -0
- umlforge-0.1.0/tests/test_phase12_billing_routes.py +281 -0
- umlforge-0.1.0/tests/test_phase14_deployment.py +238 -0
- umlforge-0.1.0/tests/test_phase15_vercel.py +192 -0
- umlforge-0.1.0/tests/test_phase16_providers.py +639 -0
- umlforge-0.1.0/tests/test_phase1_database.py +308 -0
- umlforge-0.1.0/tests/test_phase2_auth.py +511 -0
- umlforge-0.1.0/tests/test_phase3_app.py +274 -0
- umlforge-0.1.0/tests/test_phase4_prompts.py +381 -0
- umlforge-0.1.0/tests/test_phase5_threat_model.py +583 -0
- umlforge-0.1.0/tests/test_phase6_validator.py +409 -0
- umlforge-0.1.0/tests/test_phase7_all_prompts.py +268 -0
- umlforge-0.1.0/tests/test_phase8_billing.py +461 -0
- umlforge-0.1.0/tests/test_phase9_usage.py +395 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"mcp__umlforge__umlforge_threat_model",
|
|
5
|
+
"mcp__umlforge__umlforge_suggest",
|
|
6
|
+
"mcp__umlforge__umlforge_reverse_engineer",
|
|
7
|
+
"mcp__umlforge__umlforge_stakeholder_arch",
|
|
8
|
+
"mcp__umlforge__umlforge_api_sequence",
|
|
9
|
+
"mcp__umlforge__umlforge_state_machine",
|
|
10
|
+
"mcp__umlforge__umlforge_erd_schema",
|
|
11
|
+
"mcp__umlforge__umlforge_frontend_components",
|
|
12
|
+
"mcp__umlforge__umlforge_event_driven",
|
|
13
|
+
"mcp__umlforge__umlforge_ai_agent",
|
|
14
|
+
"mcp__umlforge__umlforge_deployment",
|
|
15
|
+
"mcp__umlforge__umlforge_living_docs",
|
|
16
|
+
"mcp__umlforge__umlforge_onboarding"
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# UML Forge — Environment Variables
|
|
2
|
+
# Copy this file to .env and fill in your values
|
|
3
|
+
# NEVER commit .env to version control
|
|
4
|
+
|
|
5
|
+
# ── LLM Provider ───────────────────────────────────────
|
|
6
|
+
# Choose one provider. Default is Anthropic (claude-sonnet-4-6).
|
|
7
|
+
LLM_PROVIDER=anthropic # anthropic | openai | google | ollama
|
|
8
|
+
LLM_MODEL=claude-sonnet-4-6 # model ID for the chosen provider
|
|
9
|
+
|
|
10
|
+
# Anthropic (required when LLM_PROVIDER=anthropic)
|
|
11
|
+
ANTHROPIC_API_KEY=sk-ant-...
|
|
12
|
+
|
|
13
|
+
# OpenAI (required when LLM_PROVIDER=openai)
|
|
14
|
+
# Models: gpt-4o | gpt-4o-mini | o1 | o1-mini | o3-mini
|
|
15
|
+
# OPENAI_API_KEY=sk-...
|
|
16
|
+
|
|
17
|
+
# Google Gemini (required when LLM_PROVIDER=google)
|
|
18
|
+
# Models: gemini-2.0-flash | gemini-2.5-pro | gemini-1.5-flash
|
|
19
|
+
# GOOGLE_API_KEY=AIza...
|
|
20
|
+
|
|
21
|
+
# Ollama — local provider, no API key needed
|
|
22
|
+
# Pull a model first: ollama pull llama3.2
|
|
23
|
+
# Models: llama3.2 | mistral | codellama | qwen2.5-coder | phi4
|
|
24
|
+
# LLM_PROVIDER=ollama
|
|
25
|
+
# LLM_MODEL=llama3.2
|
|
26
|
+
# OLLAMA_BASE_URL=http://localhost:11434 # change if Ollama runs on another host
|
|
27
|
+
|
|
28
|
+
# ── Database (Neon PostgreSQL) ─────────────────────────
|
|
29
|
+
# Use the POOLED connection string from Neon → Connection Details → Pooled.
|
|
30
|
+
# IMPORTANT: asyncpg uses ?ssl=require — NOT ?sslmode=require (that's psycopg2 syntax).
|
|
31
|
+
DATABASE_URL=postgresql+asyncpg://user:password@ep-xxx.pooler.neon.tech/neondb?ssl=require
|
|
32
|
+
|
|
33
|
+
# ── Paystack ───────────────────────────────────────────
|
|
34
|
+
PAYSTACK_SECRET_KEY=sk_live_...
|
|
35
|
+
PAYSTACK_WEBHOOK_SECRET=your_webhook_secret_here
|
|
36
|
+
|
|
37
|
+
# ── Security ───────────────────────────────────────────
|
|
38
|
+
# Generate with: python -c "import secrets; print(secrets.token_hex(32))"
|
|
39
|
+
API_SECRET_SALT=your_random_32_char_hex_string_here
|
|
40
|
+
JWT_SECRET_KEY=your_random_32_char_hex_string_here
|
|
41
|
+
|
|
42
|
+
# ── App Config ─────────────────────────────────────────
|
|
43
|
+
ENVIRONMENT=development # development | production
|
|
44
|
+
API_VERSION=1.0.0
|
|
45
|
+
DASHBOARD_URL=http://localhost:3000
|
|
46
|
+
ALLOWED_ORIGINS=http://localhost:3000,http://localhost:5173
|
|
47
|
+
|
|
48
|
+
# ── Email (Resend) ─────────────────────────────────────
|
|
49
|
+
# Create account at resend.com — free tier: 3,000 emails/month, 100/day
|
|
50
|
+
# Add and verify the umlforge.dev domain in Resend dashboard first.
|
|
51
|
+
# Leave blank in development — verification links print to the console instead.
|
|
52
|
+
RESEND_API_KEY=re_...
|
|
53
|
+
RESEND_FROM_EMAIL=UML Forge <noreply@umlforge.dev>
|
|
54
|
+
|
|
55
|
+
# ── Rate Limiting ──────────────────────────────────────
|
|
56
|
+
FREE_TIER_MONTHLY_LIMIT=5
|
|
57
|
+
ABUSE_RATE_LIMIT_PER_HOUR=100
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
api-tests:
|
|
11
|
+
name: API tests (Python 3.12)
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: "3.12"
|
|
20
|
+
cache: pip
|
|
21
|
+
|
|
22
|
+
- name: Install dependencies
|
|
23
|
+
run: |
|
|
24
|
+
pip install -r requirements.txt -r requirements-dev.txt
|
|
25
|
+
|
|
26
|
+
- name: Run tests
|
|
27
|
+
run: pytest tests/ -q --tb=short
|
|
28
|
+
env:
|
|
29
|
+
PYTHONPATH: ${{ github.workspace }}
|
|
30
|
+
DATABASE_URL: "sqlite+aiosqlite:///:memory:"
|
|
31
|
+
JWT_SECRET_KEY: "ci-test-secret-key-at-least-32-chars-long"
|
|
32
|
+
ANTHROPIC_API_KEY: "sk-ant-ci-placeholder"
|
|
33
|
+
ALLOWED_ORIGINS: "http://localhost:3000"
|
|
34
|
+
DASHBOARD_URL: "http://localhost:3000"
|
|
35
|
+
|
|
36
|
+
dashboard-typecheck:
|
|
37
|
+
name: Dashboard typecheck (Node 22)
|
|
38
|
+
runs-on: ubuntu-latest
|
|
39
|
+
defaults:
|
|
40
|
+
run:
|
|
41
|
+
working-directory: dashboard
|
|
42
|
+
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/checkout@v4
|
|
45
|
+
|
|
46
|
+
- uses: actions/setup-node@v4
|
|
47
|
+
with:
|
|
48
|
+
node-version: "22"
|
|
49
|
+
cache: npm
|
|
50
|
+
cache-dependency-path: dashboard/package-lock.json
|
|
51
|
+
|
|
52
|
+
- name: Install dependencies
|
|
53
|
+
run: npm ci
|
|
54
|
+
|
|
55
|
+
- name: Type-check
|
|
56
|
+
run: npx tsc --noEmit
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# UML Forge — Git Ignore
|
|
2
|
+
|
|
3
|
+
# ── Environment & Secrets ──────────────────────────────
|
|
4
|
+
.env
|
|
5
|
+
.env.local
|
|
6
|
+
.env.production
|
|
7
|
+
*.pem
|
|
8
|
+
*.key
|
|
9
|
+
|
|
10
|
+
# ── Python ─────────────────────────────────────────────
|
|
11
|
+
__pycache__/
|
|
12
|
+
*.py[cod]
|
|
13
|
+
*$py.class
|
|
14
|
+
*.so
|
|
15
|
+
.Python
|
|
16
|
+
.venv/
|
|
17
|
+
venv/
|
|
18
|
+
env/
|
|
19
|
+
ENV/
|
|
20
|
+
*.egg-info/
|
|
21
|
+
dist/
|
|
22
|
+
build/
|
|
23
|
+
.eggs/
|
|
24
|
+
*.egg
|
|
25
|
+
|
|
26
|
+
# ── Testing & Coverage ─────────────────────────────────
|
|
27
|
+
.pytest_cache/
|
|
28
|
+
.coverage
|
|
29
|
+
coverage.xml
|
|
30
|
+
htmlcov/
|
|
31
|
+
.mypy_cache/
|
|
32
|
+
.ruff_cache/
|
|
33
|
+
|
|
34
|
+
# ── Node / Dashboard ───────────────────────────────────
|
|
35
|
+
node_modules/
|
|
36
|
+
.next/
|
|
37
|
+
out/
|
|
38
|
+
dashboard/.env.local
|
|
39
|
+
dashboard/.env.production
|
|
40
|
+
|
|
41
|
+
# ── IDE ────────────────────────────────────────────────
|
|
42
|
+
.vscode/
|
|
43
|
+
.idea/
|
|
44
|
+
*.swp
|
|
45
|
+
*.swo
|
|
46
|
+
.DS_Store
|
|
47
|
+
|
|
48
|
+
# ── Logs ───────────────────────────────────────────────
|
|
49
|
+
*.log
|
|
50
|
+
logs/
|
|
51
|
+
|
|
52
|
+
# ── Alembic ────────────────────────────────────────────
|
|
53
|
+
# Keep alembic/versions/ tracked — migrations are version controlled
|
|
54
|
+
|
|
55
|
+
# ── Internal Business Docs ─────────────────────────────
|
|
56
|
+
# Strategy, roadmap, IP, and architecture docs — never public
|
|
57
|
+
/docs/
|
|
58
|
+
|
|
59
|
+
# ── Sample Diagram Outputs ─────────────────────────────
|
|
60
|
+
# Generated during local testing — not project source
|
|
61
|
+
diagram_*.mmd
|
|
62
|
+
diagram_*.png
|
|
63
|
+
diagram_*.svg
|
|
64
|
+
umlforge_backup_*.txt
|
umlforge-0.1.0/.mcp.json
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# UML Forge — Railway Deployment
|
|
2
|
+
|
|
3
|
+
## Required Environment Variables
|
|
4
|
+
|
|
5
|
+
Set ALL of the following in the Railway dashboard before deploying.
|
|
6
|
+
**Never commit secrets to the repository.**
|
|
7
|
+
|
|
8
|
+
### Anthropic
|
|
9
|
+
|
|
10
|
+
| Variable | Description | Example |
|
|
11
|
+
|---|---|---|
|
|
12
|
+
| `ANTHROPIC_API_KEY` | Anthropic API key for diagram generation | `sk-ant-api03-...` |
|
|
13
|
+
|
|
14
|
+
### Database (Neon)
|
|
15
|
+
|
|
16
|
+
| Variable | Description | Example |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| `DATABASE_URL` | **Pooled** Neon connection string — use the pooled endpoint for production | `postgresql+asyncpg://user:pass@ep-xxx.pooler.neon.tech/neondb?sslmode=require` |
|
|
19
|
+
|
|
20
|
+
> ⚠️ Use the **pooled** connection string (endpoint contains `.pooler.neon.tech`), not
|
|
21
|
+
> the direct connection. Railway containers spin up/down frequently; pooled connections
|
|
22
|
+
> avoid exhausting Neon's connection limit.
|
|
23
|
+
|
|
24
|
+
### Paystack Billing
|
|
25
|
+
|
|
26
|
+
| Variable | Description | Example |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| `PAYSTACK_SECRET_KEY` | Live secret key from Paystack dashboard | `sk_live_...` |
|
|
29
|
+
| `PAYSTACK_WEBHOOK_SECRET` | Webhook signature secret from Paystack | (random 32+ char string) |
|
|
30
|
+
|
|
31
|
+
> After deploy, update the webhook URL in Paystack dashboard to:
|
|
32
|
+
> `https://api.umlforge.dev/webhooks/paystack`
|
|
33
|
+
|
|
34
|
+
### Security
|
|
35
|
+
|
|
36
|
+
| Variable | Description | Example |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| `API_SECRET_SALT` | Random 32+ char string for key generation entropy | `openssl rand -hex 32` |
|
|
39
|
+
| `JWT_SECRET_KEY` | Random 32+ char string for dashboard session tokens | `openssl rand -hex 32` |
|
|
40
|
+
|
|
41
|
+
### Application
|
|
42
|
+
|
|
43
|
+
| Variable | Description | Value |
|
|
44
|
+
|---|---|---|
|
|
45
|
+
| `ENVIRONMENT` | Must be `production` to lock down API docs + CORS | `production` |
|
|
46
|
+
| `API_VERSION` | Shown in /health response | `1.0.0` |
|
|
47
|
+
| `DASHBOARD_URL` | Used in email verification links and Paystack callback | `https://umlforge.dev` |
|
|
48
|
+
| `ALLOWED_ORIGINS` | Comma-separated CORS origins | `https://umlforge.dev,https://www.umlforge.dev` |
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Deploy Steps
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# 1. Install Railway CLI
|
|
56
|
+
npm install -g @railway/cli
|
|
57
|
+
|
|
58
|
+
# 2. Authenticate
|
|
59
|
+
railway login
|
|
60
|
+
|
|
61
|
+
# 3. Link to your Railway project
|
|
62
|
+
railway link
|
|
63
|
+
|
|
64
|
+
# 4. Deploy
|
|
65
|
+
railway up
|
|
66
|
+
|
|
67
|
+
# 5. Watch startup logs
|
|
68
|
+
railway logs --follow
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Post-Deploy Verification
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# Health check — must return {"status": "ok", "version": "1.0.0"}
|
|
75
|
+
curl https://api.umlforge.dev/health
|
|
76
|
+
|
|
77
|
+
# Docs must be disabled in production
|
|
78
|
+
curl -s -o /dev/null -w "%{http_code}" https://api.umlforge.dev/docs
|
|
79
|
+
# Expected: 404
|
|
80
|
+
|
|
81
|
+
# Test webhook signature (should return 401 — tampered)
|
|
82
|
+
curl -X POST https://api.umlforge.dev/webhooks/paystack \
|
|
83
|
+
-H "Content-Type: application/json" \
|
|
84
|
+
-d '{"event":"test"}' \
|
|
85
|
+
-w "\nHTTP %{http_code}\n"
|
|
86
|
+
# Expected: 401
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Production Security Checklist
|
|
90
|
+
|
|
91
|
+
- [ ] `ENVIRONMENT=production` — disables /docs, /redoc, /openapi.json
|
|
92
|
+
- [ ] All secrets set as Railway env vars, none in code
|
|
93
|
+
- [ ] `DATABASE_URL` uses Neon **pooled** connection string
|
|
94
|
+
- [ ] `PAYSTACK_WEBHOOK_SECRET` matches value in Paystack dashboard
|
|
95
|
+
- [ ] `ALLOWED_ORIGINS` contains only production dashboard domains
|
|
96
|
+
- [ ] Paystack webhook URL updated to `https://api.umlforge.dev/webhooks/paystack`
|
|
97
|
+
- [ ] `DASHBOARD_URL=https://umlforge.dev` (HTTPS, not localhost)
|
|
98
|
+
- [ ] JWT and salt secrets are 32+ chars and randomly generated
|
umlforge-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: umlforge
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: UML Forge MCP connector — AI-powered UML diagram generation for coding agents
|
|
5
|
+
Project-URL: Homepage, https://umlforge.dev
|
|
6
|
+
Project-URL: Documentation, https://umlforge.dev/docs
|
|
7
|
+
License: Proprietary
|
|
8
|
+
Keywords: ai,architecture,class-diagram,claude,cursor,diagram,mcp,sequence-diagram,uml
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Topic :: Software Development :: Documentation
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Requires-Python: >=3.11
|
|
18
|
+
Requires-Dist: httpx<1.0.0,>=0.27.0
|
|
19
|
+
Requires-Dist: mcp[cli]<2.0.0,>=1.27.0
|
|
20
|
+
Requires-Dist: pydantic<3.0.0,>=2.7.0
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
|
|
23
|
+
# UML Forge MCP Connector
|
|
24
|
+
|
|
25
|
+
**AI-powered UML diagram generation for coding agents.**
|
|
26
|
+
|
|
27
|
+
[UML Forge](https://umlforge.dev) gives Claude Code, Cursor, Windsurf, and any
|
|
28
|
+
MCP-compatible coding agent a suite of 13 specialised tools for producing
|
|
29
|
+
professional UML diagrams from your codebase, schema, or architecture
|
|
30
|
+
descriptions.
|
|
31
|
+
|
|
32
|
+
## Quick start
|
|
33
|
+
|
|
34
|
+
**Claude Code:**
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"mcpServers": {
|
|
38
|
+
"umlforge": {
|
|
39
|
+
"command": "uvx",
|
|
40
|
+
"args": ["umlforge"],
|
|
41
|
+
"env": { "UMLFORGE_API_KEY": "your-api-key" }
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Cursor / Windsurf** — add the same block to your MCP settings.
|
|
48
|
+
|
|
49
|
+
Get your API key at [umlforge.dev](https://umlforge.dev).
|
|
50
|
+
|
|
51
|
+
## Tools included
|
|
52
|
+
|
|
53
|
+
| Tool | Description |
|
|
54
|
+
|------|-------------|
|
|
55
|
+
| `umlforge_reverse_engineer` | Class, sequence, and state diagrams from a codebase or GitHub URL |
|
|
56
|
+
| `umlforge_api_sequence` | Sequence diagrams from OpenAPI / REST endpoints |
|
|
57
|
+
| `umlforge_erd_schema` | Entity-relationship diagrams from SQL schema or ORM models |
|
|
58
|
+
| `umlforge_state_machine` | State diagrams from business rules or UI flows |
|
|
59
|
+
| `umlforge_frontend_components` | Component hierarchy and data-flow diagrams |
|
|
60
|
+
| `umlforge_deployment` | Infrastructure and deployment diagrams |
|
|
61
|
+
| `umlforge_threat_model` | STRIDE threat model + attack surface diagram |
|
|
62
|
+
| `umlforge_event_driven` | Event flow and pub/sub architecture diagrams |
|
|
63
|
+
| `umlforge_ai_agent` | Agent topology and tool-call flow diagrams |
|
|
64
|
+
| `umlforge_stakeholder_arch` | C4 context diagrams for stakeholder communication |
|
|
65
|
+
| `umlforge_living_docs` | Living documentation diagrams synced to code |
|
|
66
|
+
| `umlforge_onboarding` | Onboarding maps for new team members |
|
|
67
|
+
| `umlforge_suggest` | Recommends the best diagram type for a description |
|
|
68
|
+
|
|
69
|
+
## Requirements
|
|
70
|
+
|
|
71
|
+
- Python 3.11+
|
|
72
|
+
- An API key from [umlforge.dev](https://umlforge.dev) (free tier available)
|
|
73
|
+
|
|
74
|
+
## License
|
|
75
|
+
|
|
76
|
+
Proprietary. The connector is open to install and use with a UML Forge account.
|
umlforge-0.1.0/README.md
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# UML Forge
|
|
2
|
+
|
|
3
|
+
> AI-powered UML diagram generation inside your coding environment.
|
|
4
|
+
> Exposes 12 specialised prompt tools as an MCP server — works natively
|
|
5
|
+
> in Claude Code, Cursor, Windsurf, Cline, and Continue.dev.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## What It Does
|
|
10
|
+
|
|
11
|
+
UML Forge generates professional, valid Mermaid diagrams directly inside
|
|
12
|
+
your coding agent. Call a tool, get a diagram. No context switching,
|
|
13
|
+
no diagramming tools, no stale documentation.
|
|
14
|
+
|
|
15
|
+
**12 built-in tools:**
|
|
16
|
+
- Reverse-engineer codebase to class/sequence diagrams
|
|
17
|
+
- Stakeholder architecture (C4 + UML hybrid)
|
|
18
|
+
- API and microservices sequence diagrams
|
|
19
|
+
- State machine design for domain entities
|
|
20
|
+
- Living documentation maintainer (sprint/PR workflow)
|
|
21
|
+
- Database ERD and schema narrative
|
|
22
|
+
- Security threat model with STRIDE analysis
|
|
23
|
+
- Frontend component architecture
|
|
24
|
+
- Event-driven and async system design
|
|
25
|
+
- Team onboarding and knowledge transfer package
|
|
26
|
+
- AI agent and orchestration pipeline design
|
|
27
|
+
- Deployment and DevOps topology
|
|
28
|
+
|
|
29
|
+
**Pro tier:** Socratic mode — the tool asks you 3–5 targeted clarifying
|
|
30
|
+
questions before generating, producing significantly richer diagrams.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Quick Start
|
|
35
|
+
|
|
36
|
+
### 1. Get an API key
|
|
37
|
+
|
|
38
|
+
Sign up at [umlforge.dev](https://umlforge.dev) — free tier, no credit card.
|
|
39
|
+
|
|
40
|
+
### 2. Install the connector
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install umlforge-connector
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 3. Configure
|
|
47
|
+
|
|
48
|
+
```toml
|
|
49
|
+
# ~/.umlforge/config.toml
|
|
50
|
+
api_key = "uf_live_your_key_here"
|
|
51
|
+
socratic_mode = false # set true for Pro users
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 4. Add to your coding agent
|
|
55
|
+
|
|
56
|
+
**Claude Code** (`.mcp.json`):
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"mcpServers": {
|
|
60
|
+
"umlforge": {
|
|
61
|
+
"command": "python",
|
|
62
|
+
"args": ["-m", "umlforge_connector"]
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Cursor** (MCP Settings):
|
|
69
|
+
```json
|
|
70
|
+
{
|
|
71
|
+
"umlforge": {
|
|
72
|
+
"command": "python",
|
|
73
|
+
"args": ["-m", "umlforge_connector"]
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 5. Generate your first diagram
|
|
79
|
+
|
|
80
|
+
In your coding agent:
|
|
81
|
+
```
|
|
82
|
+
Generate a threat model for my FastAPI authentication service
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Development Setup
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
# Clone
|
|
91
|
+
git clone https://github.com/yourname/uml-forge
|
|
92
|
+
cd uml-forge
|
|
93
|
+
|
|
94
|
+
# Virtual environment
|
|
95
|
+
python3.12 -m venv .venv
|
|
96
|
+
source .venv/bin/activate
|
|
97
|
+
|
|
98
|
+
# Install dependencies
|
|
99
|
+
pip install -r requirements.txt
|
|
100
|
+
pip install -r requirements-dev.txt
|
|
101
|
+
|
|
102
|
+
# Configure environment
|
|
103
|
+
cp .env.example .env
|
|
104
|
+
# Edit .env with your keys
|
|
105
|
+
|
|
106
|
+
# Run locally
|
|
107
|
+
uvicorn api.main:app --reload --port 8000
|
|
108
|
+
|
|
109
|
+
# Health check
|
|
110
|
+
curl http://localhost:8000/health
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Project Structure
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
uml-forge/
|
|
119
|
+
├── api/ # Hosted API (Railway) — PRIVATE
|
|
120
|
+
│ ├── prompts/ # 12 prompt modules — never distributed
|
|
121
|
+
│ ├── models/ # Pydantic input/output models
|
|
122
|
+
│ ├── config.py # Environment configuration
|
|
123
|
+
│ ├── main.py # FastAPI application
|
|
124
|
+
│ ├── auth.py # API key validation
|
|
125
|
+
│ ├── db.py # Database connection
|
|
126
|
+
│ └── ...
|
|
127
|
+
├── connector/ # Thin MCP connector — PUBLIC
|
|
128
|
+
│ ├── server.py # FastMCP stdio server
|
|
129
|
+
│ └── tools.py # 13 MCP tool definitions
|
|
130
|
+
├── infra/db/ # Database schema
|
|
131
|
+
├── railway.toml # Production deployment config
|
|
132
|
+
└── requirements.txt # Pinned, verified dependencies
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Tech Stack
|
|
138
|
+
|
|
139
|
+
- **Python 3.12** | **FastAPI 0.136** | **Pydantic v2**
|
|
140
|
+
- **SQLAlchemy 2.0 async** + **asyncpg** + **Alembic**
|
|
141
|
+
- **Neon** (serverless PostgreSQL)
|
|
142
|
+
- **MCP SDK 1.27** (FastMCP built-in)
|
|
143
|
+
- **Anthropic claude-sonnet-4-6**
|
|
144
|
+
- **Paystack** (billing) | **Vercel** (dashboard)
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## License
|
|
149
|
+
|
|
150
|
+
Proprietary. All prompt engineering and server-side logic is closed source.
|
|
151
|
+
The MCP connector (`connector/`) is MIT licensed.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Generic single-database configuration.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# alembic/env.py
|
|
2
|
+
"""
|
|
3
|
+
UML Forge — Alembic Migration Environment
|
|
4
|
+
Configured for async SQLAlchemy 2.0 + asyncpg + Neon PostgreSQL.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
from logging.config import fileConfig
|
|
9
|
+
|
|
10
|
+
from sqlalchemy import pool
|
|
11
|
+
from sqlalchemy.engine import Connection
|
|
12
|
+
from sqlalchemy.ext.asyncio import async_engine_from_config
|
|
13
|
+
|
|
14
|
+
from alembic import context
|
|
15
|
+
|
|
16
|
+
# ── Load app config ───────────────────────────────────────────────────────────
|
|
17
|
+
# Import Base and all models so Alembic can detect schema changes
|
|
18
|
+
from api.db import Base
|
|
19
|
+
import api.models.orm # noqa: F401 — registers all models with Base.metadata
|
|
20
|
+
|
|
21
|
+
# ── Alembic config ────────────────────────────────────────────────────────────
|
|
22
|
+
config = context.config
|
|
23
|
+
|
|
24
|
+
if config.config_file_name is not None:
|
|
25
|
+
fileConfig(config.config_file_name)
|
|
26
|
+
|
|
27
|
+
target_metadata = Base.metadata
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def get_url() -> str:
|
|
31
|
+
"""Load DATABASE_URL from environment via app settings."""
|
|
32
|
+
from api.config import get_settings
|
|
33
|
+
return get_settings().database_url
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# ── Offline migrations (generate SQL scripts) ─────────────────────────────────
|
|
37
|
+
def run_migrations_offline() -> None:
|
|
38
|
+
url = get_url()
|
|
39
|
+
context.configure(
|
|
40
|
+
url=url,
|
|
41
|
+
target_metadata=target_metadata,
|
|
42
|
+
literal_binds=True,
|
|
43
|
+
dialect_opts={"paramstyle": "named"},
|
|
44
|
+
compare_type=True,
|
|
45
|
+
)
|
|
46
|
+
with context.begin_transaction():
|
|
47
|
+
context.run_migrations()
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# ── Online migrations (run against live DB) ───────────────────────────────────
|
|
51
|
+
def do_run_migrations(connection: Connection) -> None:
|
|
52
|
+
context.configure(
|
|
53
|
+
connection=connection,
|
|
54
|
+
target_metadata=target_metadata,
|
|
55
|
+
compare_type=True,
|
|
56
|
+
)
|
|
57
|
+
with context.begin_transaction():
|
|
58
|
+
context.run_migrations()
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
async def run_async_migrations() -> None:
|
|
62
|
+
configuration = config.get_section(config.config_ini_section, {})
|
|
63
|
+
configuration["sqlalchemy.url"] = get_url()
|
|
64
|
+
|
|
65
|
+
connectable = async_engine_from_config(
|
|
66
|
+
configuration,
|
|
67
|
+
prefix="sqlalchemy.",
|
|
68
|
+
poolclass=pool.NullPool, # NullPool for migrations — no connection reuse
|
|
69
|
+
connect_args={"ssl": "require"}, # Neon requires SSL; asyncpg uses 'ssl' not 'sslmode'
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
async with connectable.connect() as connection:
|
|
73
|
+
await connection.run_sync(do_run_migrations)
|
|
74
|
+
|
|
75
|
+
await connectable.dispose()
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def run_migrations_online() -> None:
|
|
79
|
+
asyncio.run(run_async_migrations())
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
if context.is_offline_mode():
|
|
83
|
+
run_migrations_offline()
|
|
84
|
+
else:
|
|
85
|
+
run_migrations_online()
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""${message}
|
|
2
|
+
|
|
3
|
+
Revision ID: ${up_revision}
|
|
4
|
+
Revises: ${down_revision | comma,n}
|
|
5
|
+
Create Date: ${create_date}
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
from typing import Sequence, Union
|
|
9
|
+
|
|
10
|
+
from alembic import op
|
|
11
|
+
import sqlalchemy as sa
|
|
12
|
+
${imports if imports else ""}
|
|
13
|
+
|
|
14
|
+
# revision identifiers, used by Alembic.
|
|
15
|
+
revision: str = ${repr(up_revision)}
|
|
16
|
+
down_revision: Union[str, Sequence[str], None] = ${repr(down_revision)}
|
|
17
|
+
branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)}
|
|
18
|
+
depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def upgrade() -> None:
|
|
22
|
+
"""Upgrade schema."""
|
|
23
|
+
${upgrades if upgrades else "pass"}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def downgrade() -> None:
|
|
27
|
+
"""Downgrade schema."""
|
|
28
|
+
${downgrades if downgrades else "pass"}
|