MCP Chat Integration Plan

Objective

Create an MCP-based integration so natural-language messages from Discord, email-to-text, or other chat channels can create and manage accounting records such as customers and sales invoices.

Primary Use Case

Example operator workflow:

  1. User sends a plain-language message:

    • Create customer Jane Doe, email jane@example.com, phone 780-555-0123

    • Create invoice for Jane Doe: 12 DTF shirts at 15 each, Alberta tax

  2. The chat agent (Hermes/Open Claw/Nemo Claw) calls MCP tools.

  3. MCP server validates and normalizes input.

  4. MCP server calls Inkforje Accounting API endpoints.

  5. MCP server returns structured success/failure output back to chat.

        sequenceDiagram
  participant User as DTF Operator
  participant Chat as Discord/Email-to-Text
  participant Agent as Hermes/Open Claw/Nemo Claw
  participant MCP as MCP Gateway
  participant API as Inkforje API
  participant DB as PostgreSQL

  User->>Chat: "Create invoice for Jane Doe..."
  Chat->>Agent: Inbound message
  Agent->>MCP: create_invoice(tool args)
  MCP->>API: OAuth2 token + POST /api/invoices/
  API->>DB: Persist customer/invoice rows
  DB-->>API: Commit OK
  API-->>MCP: JSON response
  MCP-->>Agent: Typed tool result
  Agent-->>Chat: Confirmation / error details
    

Reference API Endpoints

From current accounting/api_urls.py:

  • POST /api/customers/

  • GET /api/customers/

  • POST /api/invoices/

  • GET /api/invoices/

  • POST /api/invoices/<uuid:uuid>/approve/

  • POST /api/invoices/<uuid:uuid>/pay/

  • POST /oauth/token/

These are sufficient to start with customer + invoice creation flows.

Input Normalization Rules

Apply deterministic normalization before API calls:

  • Resolve customer references by UUID, then by exact name/email match.

  • Parse money/quantity as decimals; reject ambiguous values.

  • Parse jurisdiction strings to known tax preset identifiers.

  • Require explicit currency when not inferable from defaults.

  • Reject incomplete invoice lines (missing qty/rate/description).

Security And Access Model

  1. Use a dedicated OAuth2 confidential client for MCP.

  2. Request only required scopes (minimum privilege).

  3. Restrict ingress by source channel identity and shared secret.

  4. Log request ID, actor/channel, normalized payload, API response status.

  5. Redact PII in long-term logs where feasible.

Important

The referenced .env.production currently contains live-looking credentials and secrets (database, storage, API keys, webhook secret, broker auth, etc.). Rotate all exposed values before production rollout and move secret handling to secure secret storage.

Do not copy raw secret values into documentation, prompts, or MCP tool outputs.

High-Level System Design

Suggested deployment components:

  • mcp-gateway service: receives MCP calls from chat agents and enforces tool schema.

  • nlp-parser module: converts natural language to strict tool arguments.

  • inkforje-api-client module: OAuth token handling + typed API requests to Django backend.

  • audit-log store: immutable event logs for traceability and support.

  • retry/dead-letter queue: handles transient failures and idempotent retries.

        flowchart LR
  A[Discord / Email-to-Text] --> B[Chat Agent]
  B --> C[MCP Gateway]
  C --> D[NLP Parser + Validation]
  D --> E[Inkforje API Client]
  E --> F[/oauth/token/]
  E --> G[/api/customers/]
  E --> H[/api/invoices/]
  G --> I[(PostgreSQL)]
  H --> I
  C --> J[(Audit Log)]
  C --> K[(Retry / Dead-letter Queue)]
    

Implementation Phases

Phase 1: Foundation

  • Provision OAuth client for MCP.

  • Implement create_customer MCP tool.

  • Add integration tests against /api/customers/.

  • Add audit logging and correlation IDs.

Phase 2: Invoice Creation

  • Implement create_invoice MCP tool.

  • Add line-item parsing and tax preset mapping.

  • Validate invoice totals and API response consistency.

  • Add retry/idempotency behavior.

Phase 3: Channel Connectors

  • Add Discord command/message adapter.

  • Add email-to-text webhook adapter.

  • Add sender allowlist and abuse/rate controls.

  • Add operator-friendly error responses.

Phase 4: Hardening

  • Add structured metrics and alerts.

  • Add dead-letter review workflow.

  • Add backup manual review queue for uncertain parses.

  • Run UAT with DTF business scenarios.

Testing Strategy

Required automated tests:

  • Tool schema validation tests.

  • API contract tests for customer/invoice flows.

  • Negative tests (unknown customer, malformed quantity/rate, missing fields).

  • Permission/scope tests.

  • Idempotency tests for duplicate inbound messages.

Operational Guardrails

To reduce risk in chat-driven accounting updates:

  • Confirm before posting financial transactions above a configured threshold.

  • Require explicit customer confirmation when name matching is ambiguous.

  • Store original inbound message alongside normalized command payload.

  • Provide a dry-run mode that returns the would-be API payload.

Sphinx Build

Build HTML documentation:

uv run --with sphinx sphinx-build -b html docs docs/_build/html

Generated entry point:

  • docs/_build/html/index.html

GitHub Actions: Cloudflare Pages Deployment

The repository now includes a workflow to build Sphinx docs and deploy to Cloudflare Pages:

  • .github/workflows/publish-docs-cloudflare-pages.yml

Required GitHub repository secrets:

  • CLOUDFLARE_API_TOKEN

  • CLOUDFLARE_ACCOUNT_ID

  • CLOUDFLARE_PAGES_PROJECT_NAME

Implementation Status (Current Repo)

Initial MCP server implementation is now added:

  • accounting/mcp/server.py: stdio MCP server with initialize, tools/list, and tools/call support.

  • accounting/mcp/client.py: OAuth2 client-credentials API client.

  • accounting/mcp/schemas.py: strict input validation serializers.

  • accounting/management/commands/run_mcp_server.py: command entrypoint.

Current tools:

  • create_customer -> POST /api/customers/

  • create_invoice -> POST /api/invoices/

Run MCP Server (stdio)

Set environment variables:

export MCP_API_BASE_URL="https://accounting.inkforje.com"
export MCP_OAUTH_CLIENT_ID="<oauth-client-id>"
export MCP_OAUTH_CLIENT_SECRET="<oauth-client-secret>"

Run:

uv run python manage.py run_mcp_server