# How is an integration / connector defined?

> API layer & connectors — a good answer covers: Manifest or schema format; code vs config; codegen from OpenAPI; versioning; how many integrations ship.

Canonical page: https://llms-technical-reviews.com/connectors/q/definition/

## Verdict

The two projects define an integration in opposite ways. In [ACI](/p/aci/), an integration is data. Each of the 98 apps is an `app.json` (metadata and security schemes, with secrets as Jinja placeholders) plus a `functions.json`. That file describes each REST endpoint (method, path, server URL) and its parameters as JSON Schema split into header, path, query and body, with a `visible` list that decides what the LLM sees. The CLI commands `upsert-app` and `upsert-functions` validate the definitions, embed them and load them into Postgres. Of the 987 functions, 971 are pure config. The other 16 are routed by name to Python connector classes. Every definition is written by hand; there is no OpenAPI import.

In [Klavis](/p/klavis/), an integration is code. Each of the roughly 100 `mcp_servers/` directories is a separate MCP server in Python, TypeScript or Go, with its own Dockerfile. Tools are declared in `list_tools()` and dispatched by hand in `call_tool()`. There is no shared manifest. Fern generates SDKs, but only for the hosted API.

Choose ACI's model when you want to add many REST endpoints cheaply and the same way each time. Choose Klavis when you want a normal MCP server per service, which you can run alone and which may contain any custom logic.

More projects in this category are being researched.

## Per-project answers

### Klavis-AI/klavis (answered)

Each integration is an MCP server in `mcp_servers/`. **105 servers** ship with the repo. No single manifest format; servers in Python (Airtable: `mcp_servers/airtable/server.py:1-80`), Go (GitHub: `mcp_servers/github/server.go:1-80`), or TypeScript, each with Dockerfile. Code-defined via `app.list_tools()` and `app.call_tool()`. **Strata config** (`open-strata/src/strata/config.py:13-87`): MCPServerConfig dataclass with name, type, url/command, headers, env, auth, enabled. Stored in `~/.config/strata/servers.json`. **OpenAPI codegen** (`fern/generators.yml:1-69`): Fern generates Python and TypeScript SDKs from openapi.json. **Versions**: Fern v3.5.0 (`fern/fern.config.json:1-4`); strata-mcp 1.0.2 (`open-strata/pyproject.toml:3`).

> **Editor's note.** Correction: `mcp_servers/` holds 101 server directories, not 105. The other entries are README and package files, and several directories are benchmark variants (`*_toolathlon`, `*_mcpmark`, `*_atlas`).

Citations: [mcp_servers/airtable/server.py:1-80](https://github.com/Klavis-AI/klavis/blob/45c9f7da83d1cf43f7429b96f9c8e8153542ea1e/mcp_servers/airtable/server.py#L1-L80) · [mcp_servers/github/server.go:1-80](https://github.com/Klavis-AI/klavis/blob/45c9f7da83d1cf43f7429b96f9c8e8153542ea1e/mcp_servers/github/server.go#L1-L80) · [open-strata/src/strata/config.py:13-87](https://github.com/Klavis-AI/klavis/blob/45c9f7da83d1cf43f7429b96f9c8e8153542ea1e/open-strata/src/strata/config.py#L13-L87) · [fern/generators.yml:1-69](https://github.com/Klavis-AI/klavis/blob/45c9f7da83d1cf43f7429b96f9c8e8153542ea1e/fern/generators.yml#L1-L69) · [open-strata/pyproject.toml:1-5](https://github.com/Klavis-AI/klavis/blob/45c9f7da83d1cf43f7429b96f9c8e8153542ea1e/open-strata/pyproject.toml#L1-L5)

### aipotheosis-labs/aci (answered)

An integration (called an **App**) is defined declaratively as two JSON files in `backend/apps/{app_name}/`. The `app.json` file contains metadata: name, display_name, provider, version, description, categories, visibility, active status, security_schemes (with OAuth2 URLs, scopes, and placeholder client_id/client_secret as Jinja2 template variables), and default_security_credentials_by_scheme (apps/github/app.json:1-27). The `functions.json` file is an array of function definitions, each specifying name, description, tags, visibility, active, protocol (`"rest"` or `"connector"`), protocol_data (e.g. `{"method": "GET", "path": "/repos/...", "server_url": "..."}` for REST), and parameters as a JSON Schema (apps/github/functions.json:1-80). Parameters have `visible` and `invisible` properties — invisible params inject security defaults at execution time. The `upsert-app` CLI command (cli/commands/upsert_app.py:44-47) renders templates with environment-specific secrets, validates the JSON via `AppUpsert` Pydantic model, generates an OpenAI embedding for semantic search, and upserts into the `apps` and `functions` tables (upsert_app.py:84-103). There are **98 integrations** in `backend/apps/` (from accredible to zoho_desk). Most REST integrations are pure config; 10 have custom Python connector code in `server/app_connectors/` (base.py, gmail.py, e2b.py, etc.). Versioning is a free-form string field per app; there is no automated OpenAPI codegen — integrations are manually authored.

> **Editor's note.** Correction: `upsert-app` registers the app only. Functions are loaded by a separate `upsert-functions` command.

Citations: [backend/apps/github/app.json:1-27](https://github.com/aipotheosis-labs/aci/blob/3e4a82fa5fd22f1165af2b39fa3de2b0f031242e/backend/apps/github/app.json#L1-L27) · [backend/apps/github/functions.json:1-80](https://github.com/aipotheosis-labs/aci/blob/3e4a82fa5fd22f1165af2b39fa3de2b0f031242e/backend/apps/github/functions.json#L1-L80) · [backend/aci/cli/commands/upsert_app.py:44-103](https://github.com/aipotheosis-labs/aci/blob/3e4a82fa5fd22f1165af2b39fa3de2b0f031242e/backend/aci/cli/commands/upsert_app.py#L44-L103) · [backend/aci/common/schemas/app.py:20-64](https://github.com/aipotheosis-labs/aci/blob/3e4a82fa5fd22f1165af2b39fa3de2b0f031242e/backend/aci/common/schemas/app.py#L20-L64) · [backend/aci/common/schemas/function.py:32-83](https://github.com/aipotheosis-labs/aci/blob/3e4a82fa5fd22f1165af2b39fa3de2b0f031242e/backend/aci/common/schemas/function.py#L32-L83)
