Metadata-Version: 2.4
Name: softkad-mcp
Version: 0.1.0
Summary: MCP server that consumes the APIDIAN 2026 API (FacturaLatam, DIAN UBL 2.1 e-invoicing)
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: fastmcp>=2.0
Requires-Dist: httpx>=0.27
Requires-Dist: pydantic>=2.5
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"

# APIDIAN MCP

MCP server (Python) that consumes the **APIDIAN 2026** API — FacturaLatam's DIAN e-invoicing service (UBL 2.1, Colombia) — documented in the sibling repository's Postman collection `ApiDianV2.12026.postman_collection.json`.

Independent project living in its own Git repository: it does not live inside the API project.

## Features

- **Configuration** tools: company (create/update, query, delete), digital certificate `.p12` (upload, listing, expiry), software registration (invoice, payroll, support-document, equivalent documents), resolutions.
- **Catalog & Query** tools: documents (list by date/search), customers (list/get/search/register/update), items/products (list/get/create/update), DIAN tables (payment-forms, payment-methods), resolutions by type, PDF templates, taxpayer info (DIAN RUT), document download (XML/PDF).
- **Emission** tools: invoice, credit-note, debit-note, support-document, equivalent document (eqdoc), payroll, invoice-mandate (factoring). Bodies are seeded from real collection examples (`fixtures/`).
- **Status** tools: status by ZIP_KEY, status by CUFE/CUNE, registered events by CUFE.
- **Auxiliary** tools: next consecutive number, WhatsApp config (get/set) and message sending.
- Proper DIAN business handling (Spec S5): the API answers HTTP 200 even when the DIAN rejects a document — the verdict lives inside `ResponseDian`. Accepted documents return their payload; rejected ones raise an error carrying the DIAN rejection messages.

## Requirements

- Python **3.11+**
- An APIDIAN environment (local Laragon instance, staging or production) reachable from the machine running the MCP server.

## Installation

```bash
git clone <this-repo> softkad-mcp
cd softkad-mcp
python -m venv .venv
.venv/Scripts/python -m pip install -e ".[dev]"
```

The `softkad-mcp` console command is registered by `[project.scripts]`.

## Configuration

Copy `docs/env.example` to `.env` (or export the variables) before starting:

```bash
APIDIAN_BASE_URL=http://127.0.0.1/api        # single base URL for every endpoint
APIDIAN_TOKEN=your_api_token_here            # bearer token from company registration
APIDIAN_TIMEOUT=60                            # request timeout in seconds
```

Authentication is token-only:

- Set `APIDIAN_TOKEN` with an `api_token` obtained from company registration.
- If you don't have a token yet, register a company first — the response includes a token that can be used for the session.

Every endpoint requires the bearer token except company registration (which issues its own token on creation).

## Run as an MCP server (stdio)

```bash
.venv/Scripts/softkad-mcp
```

## Run as an MCP server (SSE remote) with stdio bridge

If your MCP client only speaks stdio (Claude Desktop, ChatGPT Desktop, etc.) but you want to connect to a remote SSE server, use the bridge:

```bash
# Token as argument
.venv/Scripts/softkad-mcp-bridge https://softkad-mcp.softkad.co/sse \
    --token 5a7dece2d28dbd066818fc037b7c525ae41e1c91d1ad6e0a895db87d71eb5855

# Or via environment variable
$env:APIDIAN_MCP_TOKEN="5a7dece2d28dbd066818fc037b7c525ae41e1c91d1ad6e0a895db87d71eb5855"
.venv/Scripts/softkad-mcp-bridge https://softkad-mcp.softkad.co/sse
```

The bridge works transparently with any stdio MCP client.

## Claude Desktop config (stdio local or bridge)

```json
{
  "mcpServers": {
    "apidian-colombia": {
      "command": "C:\\laragon\\www\\co-apidian2026-mcp\\.venv\\Scripts\\softkad-mcp.exe",
      "args": [],
      "env": {
        "APIDIAN_BASE_URL": "https://api-diancol.softkad.co/api",
        "APIDIAN_TOKEN": "5a7dece2d28dbd066818fc037b7c525ae41e1c91d1ad6e0a895db87d71eb5855",
        "APIDIAN_VERIFY_SSL": "false"
      }
    }
  }
}
```

Or using the bridge for remote SSE:

```json
{
  "mcpServers": {
    "apidian-colombia": {
      "command": "C:\\laragon\\www\\co-apidian2026-mcp\\.venv\\Scripts\\softkad-mcp-bridge.exe",
      "args": [
        "https://softkad-mcp.softkad.co/sse",
        "--token", "5a7dece2d28dbd066818fc037b7c525ae41e1c91d1ad6e0a895db87d71eb5855"
      ]
    }
  }
}
```

## Configure an MCP client

MCP stdio servers are declared in the client's `mcpServers` block. Example for Claude Desktop / compatible clients:

```json
{
  "mcpServers": {
    "apidian": {
      "command": "C:\\laragon\\www\\co-apidian2026-mcp\\.venv\\Scripts\\softkad-mcp.exe",
      "args": [],
      "env": {
        "APIDIAN_BASE_URL": "http://127.0.0.1/api",
        "APIDIAN_TOKEN": "your_api_token_here"
      }
    }
  }
}
```

Adjust the `command` path and `env` to your installation. Pointers:

- On Windows the entry point is `.venv\Scripts\softkad-mcp.exe`; on Linux/macOS `.venv/bin/softkad-mcp`.
- Never commit real credentials: use environment variables or the client's secret store.
- The server is stateless across restarts: per-session tokens die with the process.

## Tools

### Health & diagnostics
| Tool | Purpose |
| --- | --- |
| `apidian_health` | Server status: base URL, authenticated flag, auth hint |

### Configuration
| Tool | Purpose |
| --- | --- |
| `apidian_company` | Register / update a company (returns token on creation) |
| `apidian_company_get` | Query a company by NIT |
| `apidian_company_delete` | Delete a company |
| `apidian_certificate_upload` | Upload digital certificate `.p12` |
| `apidian_certificates_list` | List certificates for a NIT |
| `apidian_certificate_expiry` | Query certificate expiry date |
| `apidian_register_software` | Register billing software (invoice / payroll / support-document / eqdocs) |
| `apidian_create_resolution` | Create a resolution |
| `apidian_resolutions_list` | List resolutions for a NIT |

### Catalog & Query
| Tool | Purpose |
| --- | --- |
| `apidian_documents_list` | List documents by date/search/page |
| `apidian_customers_list` | List customers |
| `apidian_customer_get` | Get a customer by ID |
| `apidian_customer_search` | Search customer by NIT + identification number |
| `apidian_customer_register` | Register / update a customer |
| `apidian_customer_update` | Update a customer by ID |
| `apidian_items_list` | List products / services |
| `apidian_item_get` | Get an item by ID |
| `apidian_item_create` | Create a product / service |
| `apidian_item_update` | Update a product / service |
| `apidian_payment_forms` | DIAN payment forms table |
| `apidian_payment_methods` | DIAN payment methods table |
| `apidian_resolutions_by_type` | List resolutions by document type and/or NIT |
| `apidian_templates` | List available PDF templates |
| `apidian_information` | Query DIAN taxpayer info (RUT) for a NIT |
| `apidian_download` | Download a document file (XML / PDF) by NIT + filename |

### Emission
| Tool | Purpose |
| --- | --- |
| `apidian_invoice` | Emit a sales invoice |
| `apidian_credit_note` | Emit a credit note |
| `apidian_debit_note` | Emit a debit note |
| `apidian_support_document` | Emit a support document (documento soporte) |
| `apidian_eqdoc` | Emit an equivalent document (POS / eqdoc) |
| `apidian_payroll` | Emit a payroll document (nómina) |
| `apidian_invoice_mandate` | Emit an invoice with mandate (factoring) |

### Status
| Tool | Purpose |
| --- | --- |
| `apidian_status_zip` | Query DIAN status by ZIP_KEY |
| `apidian_status_document` | Query DIAN status by CUFE/CUNE |
| `apidian_events_document` | List registered events for a document |

### Auxiliary
| Tool | Purpose |
| --- | --- |
| `apidian_next_consecutive` | Get the next consecutive number for a resolution |
| `apidian_whatsapp_get_config` | Get WhatsApp integration config |
| `apidian_whatsapp_set_config` | Set / update WhatsApp integration config |
| `apidian_whatsapp_send` | Send a text message via WhatsApp |

Each emission tool accepts a full `body` or an `example` name (see `fixtures/index.json`) to seed it.

## Docs and data

- `fixtures/` — request examples and saved responses extracted from the Postman collection via `scripts/extract_fixtures.py` (Spec S6 oracles).
- `odd/tasks/softkad-mcp.md` — feature document with specs, tasks, and log.

## Tests

```bash
.venv/Scripts/python -m pytest -q
```

The suite is HTTP-free: it stubs the client transport and asserts the exact method, path, body, and DIAN envelope handling.
