Skip to content

External API and MCP boundary

Target design · 21 September 2026. The public API and MCP server described here are not implemented yet. Today Legal Core accepts only short-lived internal workload JWTs issued for Kesita workloads. This page fixes the intended boundary before public contracts are introduced.

Open the interactive architecture diagram · Diagram source.

Section titled “One authoritative legal service, two external protocols”

External consumers do not connect directly to the Legal Core network endpoint, legal PostgreSQL or corpus blobs. They enter through a Kesita-owned public integration boundary. That boundary authenticates the external principal, resolves tenant and entitlement, applies scopes, content policy, quotas and idempotency, and records a bounded usage/policy receipt. It then exchanges that authority for a short-lived workload JWT accepted by Legal Core.

The Public API is the canonical application contract. The MCP server is an adapter over the same application services and policies; it must not become a second legal API or carry corpus credentials. ComproCausa and other Kesita-owned products use the same versioned server-to-server contract offered to partners, with their own client identity and entitlements.

flowchart LR
  subgraph Consumers[External consumers]
    Partner[Partner backend]
    Compro[ComproCausa backend]
    Host[MCP host]
  end

  subgraph PublicBoundary[Kesita public integration boundary]
    MCP[Kesita MCP server]
    API[Public Legal API<br/>api.kesita.ai/v1/legal]
    Policy[Identity, scopes, entitlements<br/>content policy and quotas]
    Meter[(Audit and usage receipts)]
  end

  subgraph PrivatePlane[Private legal data plane]
    Core[Legal Core API]
    Legal[(Legal PostgreSQL)]
    Blobs[(Corpus originals)]
  end

  Partner -->|HTTPS + client grant| API
  Compro -->|HTTPS + service identity| API
  Host -->|MCP over HTTPS| MCP
  MCP -->|Typed application calls| API
  Policy -->|Principal + allowed capability| API
  API -->|Short-lived workload JWT| Core
  API -->|Decision + usage receipt| Meter
  Core -->|Scoped read SQL| Legal
  Core -->|Checksum-verified read| Blobs

The private Legal Core address is reachable only from approved Kesita workloads. Network isolation reduces exposure but does not replace application authorization: Legal Core still verifies issuer, audience, key ID, lifetime, service identity, organization, optional user, scopes and content policy on every request.

The external credential terminates at the public boundary and is never forwarded to Legal Core. The gateway builds a narrower internal authority envelope. Public response schemas remain stable even when corpus tables, retrieval engines or internal Legal Core routes change.

sequenceDiagram
  autonumber
  participant C as External backend
  participant I as Authorization service
  participant G as Kesita Public API
  participant L as Legal Core API
  participant D as Legal data stores

  C->>I: OAuth client-credentials grant
  I-->>C: Short-lived access token
  C->>G: POST /v1/legal/search + Bearer token + idempotency key
  G->>G: Resolve client, tenant, scopes, entitlement, quota and content policy
  G->>L: Search + short-lived workload JWT
  L->>L: Verify audience, service, scope and content policy
  L->>D: Scoped retrieval against active corpus generations
  D-->>L: Pinned versions and citation coordinates
  L-->>G: Internal typed retrieval result
  G->>G: Minimize fields, meter usage and record policy receipt
  G-->>C: Versioned public response + request ID

Initial public capabilities should remain narrow:

CapabilityPublic behaviorInternal authority
Legal searchFiltered ranked results with stable citations and explicit degradationlegal:search plus metadata or snippet content policy
Pinned source metadataImmutable version identity, provenance, hash and availabilitylegal:source:read plus metadata
Source passageBounded citation context, never an unbounded corpus dumplegal:source:read plus snippet
Original downloadSeparate entitlement, attachment disposition and audit eventlegal:original:read plus explicitly permitted full-content policy

Legal Core currently serves full text to internal callers and rejects lower-content policy values at runtime. Metadata/snippet projection is therefore an implementation prerequisite, not merely a gateway filter: data that is not permitted must not cross the Legal Core boundary in the first place.

The remote MCP endpoint exposes task-oriented, bounded tools such as legal search, source inspection and pinned-original retrieval. Tool schemas map to the Public API contract. Arbitrary SQL, arbitrary URLs, raw internal route selection and caller-supplied authorization context are never tools.

sequenceDiagram
  autonumber
  actor U as User
  participant H as MCP host
  participant M as Kesita MCP server
  participant I as Authorization service
  participant G as Kesita Public API
  participant L as Legal Core API

  U->>H: Connect Kesita tools
  H->>I: OAuth authorization with PKCE
  I-->>H: User-delegated token with MCP scopes
  H->>M: tools/call legal_search
  M->>M: Validate tool input and delegated scope
  M->>G: Typed legal-search request with delegated principal
  G->>L: Narrow request + short-lived workload JWT
  L-->>G: Pinned legal evidence
  G-->>M: Public contract response
  M-->>H: Bounded MCP tool result with citations
  H-->>U: Assistant-visible result

MCP authorization is user-delegated; unattended product integrations use client credentials. Both paths resolve to a Kesita principal with explicit tenant, scopes and content policy. The authorization-server choice and consent UX require a separate implementation decision, but static shared secrets in source code and direct reuse of Legal Core signing credentials are excluded.

Tokens are audience-bound to either the Public API or MCP endpoint and are never forwarded across that boundary. The MCP server must reject caller-supplied tenant IDs, scopes and downstream tokens, derive authority from the verified principal, and defend against confused-deputy use by binding every tool call to the active authorization grant. Non-human credentials require rotation and immediate disablement; authorization-code, refresh-token and client-grant revocation must prevent new gateway exchanges within the ratified revocation objective.

ComproCausa currently opens a read-only PostgreSQL pool with LEGAL_DB_URL and queries canonical.* tables to enrich reports. That makes its runtime depend on Kesita’s physical schema, connection limits, database network access and full-text layout. The target removes that dependency.

flowchart TB
  subgraph Current[Current coupling]
    C1[ComproCausa report service] -->|LEGAL_DB_URL + SQL| DB1[(Shared legal PostgreSQL)]
    C1 -->|Knows canonical tables and columns| DB1
  end

  subgraph Target[Target integration]
    C2[ComproCausa Kesita client] -->|Versioned HTTPS contract| API[Kesita Public Legal API]
    API -->|Policy-bound workload JWT| Core[Legal Core API]
    Core --> DB2[(Legal PostgreSQL + corpus originals)]
  end

  Current -. Replace direct database access .-> Target

The migration unit is the use case, not a table wrapper. For example, the existing batch lookup of canonical judgments becomes a batch pinned-source endpoint with typed metadata and an explicit optional content tier. ComproCausa retains its case workflow and report composition; Kesita becomes authoritative for legal identity, versioning, retrieval, provenance and source delivery.

  1. Inventory ComproCausa legal queries and group them into search, batch source resolution, passages and originals.
  2. Define those application operations in a separate public OpenAPI contract; do not expose the internal platform-api.yaml unchanged.
  3. Issue a dedicated non-human ComproCausa client identity with least-privilege scopes, quotas and environment separation.
  4. Add a typed Kesita client in ComproCausa and run contract tests against staging fixtures.
  5. Cut each use case from direct SQL to the API, then remove LEGAL_DB_URL, database firewall access and canonical-schema knowledge from ComproCausa.

No dual-running compatibility layer is required after a use case passes acceptance: both products are pre-ship and the clean end state is one authoritative API.

  • A new public OpenAPI source belongs in packages/contracts; it is versioned independently from the internal Legal Core contract and generates supported client types/SDKs.
  • Public resource IDs identify immutable legal source versions. They must not encode table names, blob keys, storage URLs or retrieval-engine coordinates.
  • Requests carry a stable request ID; mutations or billable operations also carry idempotency keys. Retry and rate-limit responses use stable public error codes and Retry-After where applicable.
  • Public endpoints enforce bounded pagination, query complexity, response size and content tiers. Bulk corpus export is a separate product/security decision, not an accidental large page size.
  • The gateway propagates W3C trace context and a request ID to Legal Core. Logs, traces and metrics contain opaque IDs and aggregate quantities, never queries, source text, credentials, prompts or completions by default.
  • Legal Core remains the only runtime reader of legal PostgreSQL and corpus originals. Public API, MCP and consumers never receive database credentials or storage credentials.
  • Public API availability, SDK support, pricing, retention and legal-data licensing claims require explicit acceptance evidence before publication.

Before any external client is admitted, prove cross-tenant and cross-client denial; audience, issuer, expiry and scope rejection; revoked client/user denial; content-tier non-disclosure; quota and complexity enforcement; idempotent replay; original-download authorization before and after blob I/O; MCP consent and confused-deputy resistance; request/trace correlation without content leakage; and absence of public routes to Legal Core, PostgreSQL or blob storage. Exercise key rotation and authorization-service outage behavior without a fail-open path.

  1. Implement metadata/snippet enforcement inside Legal Core and generalize its workload trust policy to allow only registered Kesita gateway identities.
  2. Add the public contract, authorization/entitlement boundary, quotas, metering and audit receipts.
  3. Add the MCP adapter over the accepted public application operations.
  4. Migrate ComproCausa use cases and revoke its direct database access.
  5. Open partner access only after isolation, revocation, abuse, licensing, load and source-delivery tests pass.

See Kesita architecture for the core system and Deployment for runtime placement and network boundaries.