Skip to content

Search these docs from your AI tool

  • Antigravity
    {
      "mcpServers": {
        "edisyl-docs": {
          "serverUrl": "https://docs.edisyl.com/mcp"
        }
      }
    }
  • Claude CodeCLI
    claude mcp add edisyl-docs https://docs.edisyl.com/mcp --transport http --scope user
  • CodexCLI
    codex mcp add --url https://docs.edisyl.com/mcp edisyl-docs
  • Cursor
    {
      "mcpServers": {
        "edisyl-docs": {
          "type": "http",
          "url": "https://docs.edisyl.com/mcp"
        }
      }
    }
  • Gemini CLI
    gemini mcp add --transport http edisyl-docs https://docs.edisyl.com/mcp
  • Goose
    {
      "extensions": {
        "edisyl-docs": {
          "enabled": true,
          "name": "edisyl-docs",
          "type": "streamable_http",
          "uri": "https://docs.edisyl.com/mcp",
          "envs": {},
          "env_keys": [],
          "headers": {},
          "description": "",
          "timeout": 300,
          "bundled": null,
          "available_tools": []
        }
      }
    }
  • JetBrains AI Assistant
    {
      "mcpServers": {
        "edisyl-docs": {
          "type": "http",
          "url": "https://docs.edisyl.com/mcp"
        }
      }
    }

    Paste into Settings → Tools → AI Assistant → Model Context Protocol → Add → As JSON. Direct file writing isn’t supported — JetBrains stores this per-version as XML.

  • Junie (JetBrains)
    {
      "mcpServers": {
        "edisyl-docs": {
          "url": "https://docs.edisyl.com/mcp"
        }
      }
    }
  • OpenCode
    {
      "mcp": {
        "edisyl-docs": {
          "type": "remote",
          "url": "https://docs.edisyl.com/mcp"
        }
      }
    }
  • VS CodeCLI
    code --add-mcp '{"name":"edisyl-docs","type":"http","url":"https://docs.edisyl.com/mcp"}'
  • Windsurf
    {
      "mcpServers": {
        "edisyl-docs": {
          "serverUrl": "https://docs.edisyl.com/mcp"
        }
      }
    }

    Supports both stdio and native HTTP connections.

Prerequisites

The chart installs the Edisyl platform into a namespace on a cluster you run. You do not need a copy of the chart repository — the chart is pulled from our OCI registry, and everything below is configured through Helm values.

Kubernetes 1.28 or later
Helm 3.8 or later, for OCI registry support
AWS CLI To obtain a registry token
Docker Only to verify a pull by hand
Ingress NGINX, or Istio with the Gateway API, or routing you write yourself
DNS A zone you control, for one wildcard record
TLS cert-manager, or a certificate you supply yourself
Storage A StorageClass that can actually provision — the LLM gateway always claims a volume, and so does any bundled datastore
PostgreSQL 16: three or four databases, the application’s with pgvector available — bundled, or your own (RDS, Cloud SQL, self-run)
Redis With RediSearch and RedisJSON — bundled, or your own
Object storage Bundled MinIO, AWS S3, or another S3-compatible store (Cloudflare R2 through its S3 endpoint)
Identity provider A SAML 2.0 IdP your users sign in through, with its metadata as an HTTPS URL or an XML file
Email A sender address for the platform’s mail

PostgreSQL, Redis and object storage are covered below: each can be bundled with the chart or supplied by you, and only Redis is bundled by default. PostgreSQL means three or four databases, sized below.

The chart installs everything into the single namespace you pass to helm install -n, and it does not create or label namespaces.

One exception. The bundled Inngest subchart takes its namespace from its own value, which defaults to edisyl. If you install into a namespace with any other name you must override it to match, or Inngest lands somewhere its consumers and their Secrets are not:

inngest:
namespace: { create: false, name: <your-namespace> }

The chart’s own pods — the applications and the install hooks — satisfy the restricted Pod Security Standard: non-root, no privilege escalation, all capabilities dropped, seccompProfile: RuntimeDefault.

The bundled third-party subcharts do not. Their pod specs do not satisfy restricted as shipped. If you enable bundled object storage into a namespace labelled pod-security.kubernetes.io/enforce: restricted, those pods are rejected outright. Label the namespace baseline instead, or exempt the workload through whatever mechanism your cluster provides.

Three things have to line up before anyone can sign in: something to route the traffic, a name that resolves to it, and a certificate for that name.

routing.provider decides what the chart renders for the three public apps, api, auth and edisyl. The configurator asks it on its Ingress tab, and can install NGINX or Istio for you.

nginx, the default. The chart renders an Ingress per public app, all conventionally class nginx. Either NGINX controller works. The auth ingress emits both F5’s nginx.org/rewrites and the community controller’s use-regex and rewrite-target, and each reads its own. On chart versions before 0.26.0 the F5 syntax was the only one, and on the community controller every auth route 404’d with the pod Ready and the Ingress admitted.

istio. The chart renders a Gateway API HTTPRoute per public app instead, attached to the Gateway named by routing.gateway.name and routing.gateway.namespace, and to one listener on it if you set routing.gateway.sectionName. It needs the Gateway API CRDs and a Gateway API Gateway, run by Istio, whose listeners allow routes from the install namespace. Istio’s classic istio-ingressgateway with VirtualServices takes no HTTPRoutes: on such a cluster, use none and write the routing yourself. The configurator can install Istio and a Gateway named edisyl in istio-ingress.

Under Istio, Envoy handles three things differently from NGINX:

  • Request timeouts. The api route sets none, so the long-lived /mcp stream is never cut. The edisyl route limits the whole response to 300 seconds (edisyl.edisyl.ingress.requestTimeout).
  • Idle streams. Envoy closes a stream with no traffic for 5 minutes, its default stream idle timeout. NGINX waits 600 seconds on api.
  • Upload size. NGINX caps request bodies at 100 MB on api and edisyl. The chart’s HTTPRoutes cap none; set a limit at the gateway if you want one.

none. The chart renders no Ingress and no HTTPRoute. Route each host to its Service in the install namespace, with what the chart’s own routes do:

Host Service Port Path Your routing must
edisyl.<domain> edisyl 3000 / allow requests up to 300 s and bodies up to 100 MB
api.<domain> api 8080 / set no request timeout, since /mcp is an unbounded event stream, and allow bodies up to 100 MB
auth.<domain> auth 80 /auth/v1/ strip the prefix to /, and route the bare /auth/v1 too

Every public URL derives from config.domain: api.<domain>, auth.<domain>, and the web application at edisyl.<domain>, not app.<domain>.

One wildcard record pointed at your ingress or gateway load balancer covers all of them:

Type Name Target
CNAME *.<your-domain> your load balancer’s hostname

Two requirements, whoever hosts your zone:

  • No proxy or CDN mode. An internal load balancer resolves to private addresses a proxy cannot reach, and the failure hits every hostname at once and reads like the cluster is down. On Cloudflare that means a grey cloud, not orange.
  • A CNAME to the load balancer’s hostname, not an A record to its addresses. Those addresses are not stable; the hostname is.

Nothing further works until it resolves, so confirm before installing:

Terminal window
dig +short api.<your-domain>

Every app’s Ingress ships annotated for cert-manager, alongside its own tlsSecret name:

cert-manager.io/cluster-issuer: letsencrypt-prod
kubernetes.io/tls-acme: "true"

So out of the box the chart expects cert-manager installed, and a ClusterIssuer named exactly letsencrypt-prod. The name is a value rather than a hardcode — edisyl.<app>.ingress.annotations is yours to override — but an issuer by any other name is never consulted, no certificate is ever requested, and the browser gets a default self-signed certificate on a host that otherwise works.

If your load balancer is internal, the issuer must solve DNS-01, not HTTP-01. Let’s Encrypt cannot reach a private address to answer an HTTP challenge; proving control of the zone works however private the endpoints are.

If you cannot give cert-manager credentials for your DNS at all, skip it: issue a wildcard certificate yourself, load it as a TLS Secret in the install namespace, and point each app’s ingress.tlsSecret at it. You then own renewal.

With Istio, TLS belongs to the Gateway listener, or to a load balancer in front of the Gateway. The chart’s cert-manager annotations and tlsSecret are inert under routing.provider: istio. The configurator’s Istio install annotates its Gateway for cert-manager, which it installs with Gateway API support turned on, and gives the Gateway one HTTPS listener per host, so each host gets its own Let’s Encrypt certificate, with HTTP-01 solved through the Gateway. The alternative it offers is a certificate Secret you supply, covering *.<domain>, which you renew.

TLS is not optional for a production install. The web application marks its session cookies Secure whenever config.appEnv is anything but local, and a browser drops a Secure cookie over plain http — so sign-in completes, lands back on the login screen with no session, and logs nothing.

The platform needs PostgreSQL, a Redis and an S3-compatible object store. Each can be bundled with the chart or supplied by you — and only Redis is bundled by default. Using your own infrastructure has the full settings for each; this is what you need to have decided before you start. The configurator asks each of these decisions in turn and lists the prerequisites your answers imply.

Edisyl runs three or four databases, each with its own role, never sharing one:

Database Used by When
services the API, worker and install jobs (the application database) always
auth the auth service always
inngest the job runner’s run history always, unless you choose SQLite for an evaluation
bifrost the LLM gateway only when the chart runs the gateway (bifrost.enabled)
Option How
Bundled CloudNativePG cnpg.enabled: true and database.source: cnpg: one CloudNativePG cluster per database
Your own PostgreSQL, including AWS RDS or Cloud SQL database.source: managed, with the application database’s URL in secrets.managed.edisyl-database, and a Secret you create for each of the others
Connection Secrets already in the namespace database.source: existing-secret, with each database’s Secret named in values

A managed service is the second row. The chart only needs connection details, so RDS, Cloud SQL and a Postgres on a VM are the same case. The databases can share one server or each have their own.

pgvector is required on the application database. The first migration runs CREATE EXTENSION vector, so the extension must be available on the server. The chart cannot check this, and a server without it fails minutes into the install rather than at render time. The bundled operand image carries it.

Inngest keeps its run history in Postgres by default. SQLite on the pod’s scratch volume (inngest.database.source: sqlite) is for evaluation only: every restart, upgrade or reschedule of the Inngest pod loses the history.

Using your own infrastructure has the Secret each database is read from, and the configurator prints the commands that create them.

From Edisyl’s own production, over a week of normal load. Start here and watch storage and CPU; the application database is the one that grows.

Database RDS or Cloud SQL Storage Bundled cluster (chart defaults, per instance)
services db.r6g.large (2 vCPU, 16 GB) minimum; db.r6g.xlarge for heavy use 100–200 GB, with storage autoscaling on 2 instances, 1 CPU, 8Gi memory, 100Gi data + 20Gi WAL
inngest db.t4g.medium (2 vCPU, 4 GB) 50–100 GB 2 instances, 500m CPU, 2Gi memory, 50Gi data + 10Gi WAL
auth db.t4g.small (2 vCPU, 2 GB) 20 GB 2 instances, 250m CPU, 1Gi memory, 20Gi data + 5Gi WAL
bifrost db.t4g.small (2 vCPU, 2 GB) 20 GB 2 instances, 250m CPU, 1Gi memory, 20Gi data + 5Gi WAL

Run them Multi-AZ, or with two instances in-cluster: a primary and a hot standby. All four bundled clusters at the defaults claim 460Gi of volumes and request 24Gi of memory. CloudNativePG can grow a volume when the StorageClass allows expansion, but it never does so on its own, so size for growth. Raise a cluster’s memory and its shared_buffers and effective_cache_size together, under cnpg.clusters.<database>.

The following apply only if you enable the bundled clusters.

The CloudNativePG operator must already be installed

Section titled “The CloudNativePG operator must already be installed”

The chart renders one Cluster custom resource per database; it does not install the CloudNativePG operator that acts on them. Install the operator first, or the resources are created and nothing ever reconciles them.

cnpg.imageName defaults to CloudNativePG’s own public, multi-arch ghcr.io/cloudnative-pg/postgresql:16-standard-bookworm, which carries the pgvector extension the platform’s first migration needs. Every cluster runs it. Override it only if you mirror images internally; whatever you point at must include pgvector.

Option How
Bundled Redis redis.enabled: true — this one is on by default
Your own redis.enabled: false, with the connection details supplied

RediSearch and RedisJSON are both required, so a plain managed Redis will not work. Check that your provider actually offers both modules before choosing it; Redis Cloud does, and the bundled server runs Redis 8, which ships both. This is the requirement most likely to rule out a managed Redis you already run.

Redis always has a password. Bundled Redis gets one the chart generates on the first install and reads back on every upgrade. Your own Redis is named by host, port, user and TLS setting under config.redis*, with its password as a credential; a single REDIS_URL is refused, and the API refuses to start on a blank password.

ElastiCache IAM authentication is not supported. The API and the job runner authenticate with a static password, and neither can mint IAM tokens. On ElastiCache, create a user with a password (RBAC user groups) and use that, or run the bundled Redis. A Redis behind Sentinel works, with limits on the job runner’s connection — see Using your own infrastructure.

Option config.objectStorageProvider
Bundled MinIO — (minio.enabled: true)
AWS S3 s3
Another S3-compatible store — MinIO you run yourself, Ceph, Wasabi, or Cloudflare R2 through its S3 endpoint s3compatible

s3 means real AWS. Using it for anything else is the mistake that produces storage which renders cleanly, starts healthy and writes nowhere. For a non-AWS store use s3compatible, which requires config.objectStorageUrl and both access keys — there is no instance-role fallback outside AWS. For R2 the URL is https://<account-id>.r2.cloudflarestorage.com; the provider value r2 was removed in chart 0.42.0 and is refused.

Whichever you choose, config.objectStorageBucket is required.

Credentials for any of these belong in your gitignored values file or a secret manager — see Secrets and signing keys.

A SAML identity provider. SAML through your IdP is the only way anyone signs in — Okta, Entra ID, Google Workspace or any SAML 2.0 IdP. You declare it in values before the install: its metadata, as an HTTPS URL or the XML document, and the email domains that sign in through it. Create the SAML application in your IdP first, with the auth service’s entity ID and ACS URL, and an assertion that carries the user’s email address. A metadata URL is fetched from inside the cluster, so the cluster needs egress to the IdP’s host. See Authentication.

A sender address, if the deployment sends email. config.emailFrom is an identity verified in SES. Leave it blank to run without email; invitations then show a link to share. See Configuration.

Registry access is granted per customer. Once you have sent us the IAM principal that will pull, you receive a client ID, a role ARN built from it, an external ID, and the list of repositories your role can read. If you have not, contact us before going further — nothing below works without it. Registry access has the whole exchange.

Report incorrect code

Please provide a detailed description of the incorrect code.