diff --git a/docs/extensions/api-key-extensions.md b/docs/extensions/api-key-extensions.md index c81dd6b..aa8ede6 100644 --- a/docs/extensions/api-key-extensions.md +++ b/docs/extensions/api-key-extensions.md @@ -1,5 +1,5 @@ --- -sidebar_position: 3 +sidebar_position: 4 --- # API-Key Extensions diff --git a/docs/extensions/building-extensions.md b/docs/extensions/building-extensions.md index 6681847..dcc798b 100644 --- a/docs/extensions/building-extensions.md +++ b/docs/extensions/building-extensions.md @@ -1,5 +1,5 @@ --- -sidebar_position: 2 +sidebar_position: 3 --- # Build Your First Extension @@ -8,6 +8,14 @@ This guide builds a complete NeatContext extension from scratch: a stdio MCP ser in Node.js (built-ins only) that exposes one tool. By the end you'll understand the manifest, the JSON-RPC framing, and the three methods every extension implements. +:::tip[No code needed for simple HTTP connectors] +This is the **write-it-yourself** path — full control, any logic. If your tool +is "call one JSON HTTP endpoint," the in-app builder generates the whole +extension in four steps: see +[Create an Extension in the UI](./create-extension-ui.md). You can start there +and hand-edit the generated code afterwards. +::: + We'll build a connector called **Status Board** with a single tool, `board_get_service_status`, that returns a service's current status from an HTTP endpoint. The same skeleton scales to as many tools as you need — the diff --git a/docs/extensions/create-extension-ui.md b/docs/extensions/create-extension-ui.md new file mode 100644 index 0000000..6777359 --- /dev/null +++ b/docs/extensions/create-extension-ui.md @@ -0,0 +1,141 @@ +--- +sidebar_position: 2 +--- + +# Create an Extension in the UI + +The fastest way to build an extension is the guided **Create** builder: four +steps in the app, no code, and the result is a working, read-only connector for +any JSON HTTP API. This page walks every step and every field. (Prefer to write +the connector yourself? See +[Build Your First Extension](./building-extensions.md) — the two ways are +compared in the [overview](./overview.md#two-ways-to-create-an-extension).) + +Every field in the builder has a **?** next to its label — click it for a +detailed explanation with examples, right in the app. This page follows the +same order. + +## The worked example + +We'll build a connector for the public GitHub REST API that looks up a user +profile, so you can follow along and test with real responses — no key +required: + +- **API**: `https://api.github.com` +- **Endpoint**: `GET /users/{username}` (e.g. `/users/torvalds`) +- **Tool**: `github_get_user` — the model passes a `username`, gets JSON back. + +The same steps apply unchanged to an internal CMDB, a status page, a deploy +tracker, or any other JSON-over-HTTP service. + +## Open the builder + +On the **Extensions** page (top bar → Extensions), click **Create**. The +builder opens with a step indicator: **Basics → Auth → Data → Review**. Each +step validates when you click **Next**, so mistakes surface next to the field +that caused them — the same checks the app applies when it generates the +extension. + +## Step 1 — Basics + +![Step 1: Basics, with the Base URL help open](/img/extensions/builder-basics.png) + +| Field | What to enter | +|---|---| +| **Extension name** | A display name, e.g. `GitHub Users`. Shown on the Extensions page and in the chat activity trace; also becomes the generated folder's name (`github-users`). No effect on API calls. | +| **Base URL** | The address of the API: scheme + host, plus an optional path prefix — `https://api.github.com`, or e.g. `https://api.example.com/v2`. Every tool call requests **Base URL + Endpoint path** (Step 3). Must be http(s); a trailing slash is removed for you. | +| **Description** | Optional. A short note shown on the extension's card, e.g. `Look up GitHub user profiles`. | + +For our example: name `GitHub Users`, base URL `https://api.github.com`, +description `Look up GitHub user profiles`. Click **Next**. + +## Step 2 — Auth + +Choose how the API authenticates requests. Whatever you pick, secrets are +**never written into the generated files** — they're entered later on the +extension card, encrypted with your OS secure storage, and handed to the +connector only when a tool runs. + +- **No auth** — the API is reachable without credentials (a public API like + our example, or an internal service already protected by the network). + Nothing else to fill in. +- **API key** — you'll paste a token that is sent as an HTTP header on every + request. +- **OAuth2 PKCE** — the service supports browser sign-in for public clients. + +Our GitHub example uses **No auth** — pick it and skip to Step 3. The two +authenticated modes look like this: + +### If you pick API key + +![Step 2: the API key fields](/img/extensions/builder-auth-api-key.png) + +| Field | What to enter | +|---|---| +| **Field key** | An internal identifier for the secret, e.g. `apiKey`. The header template references it as `{{apiKey}}`. Users never see it. | +| **Field label** | The label on the Connect form, e.g. `API key` or `Service token` — use the provider's own name for the credential. | +| **Header name** | The header that carries the key, from the API docs — commonly `Authorization` or `X-API-Key`. | +| **Header value** | How the header value wraps your key: `Bearer {{apiKey}}` sends `Authorization: Bearer `; plain `{{apiKey}}` sends the key alone. Check which shape the API expects. | + +The defaults (`apiKey` / `Authorization` / `Bearer {{apiKey}}`) fit most +bearer-token APIs — often you only need to confirm them. + +### If you pick OAuth2 PKCE + +| Field | What to enter | +|---|---| +| **Authorize URL** | The provider's browser authorization endpoint, from its OAuth docs. | +| **Token URL** | The provider's token endpoint; used locally to exchange and refresh tokens. | +| **Client ID** | The id of an OAuth app you register with the provider as a **public / PKCE** client — no client secret is needed or stored. | +| **Scopes** | Permissions to request, space- or comma-separated. Prefer the narrowest read-only scopes. | +| **Redirect port** | A free local port for the one-time sign-in callback. In the provider's OAuth app, register the redirect URL `http://127.0.0.1:/oauth//callback`, where `` is your extension name lowercased with dashes (`GitHub Users` → `github-users`). | + +## Step 3 — Data + +Define the one read-only operation the tool performs. + +![Step 3: the Data step](/img/extensions/builder-data.png) + +| Field | What to enter | +|---|---| +| **Tool name** | The function name the model calls: `github_get_user`. Lowercase letters, numbers, underscores; start with a letter. (`neatcontext_*` is reserved for built-ins.) | +| **Method** | `GET` for reading (recommended). `POST` only if the API requires it — the input is then sent as a JSON body. | +| **Endpoint path** | The path under the base URL, starting with `/`. Put the input into the URL with a placeholder that **exactly matches the input name**: `/users/{username}`. With no placeholder, a GET sends the input as `?username=...` and a POST puts it in the body. | +| **Input name** | The single argument the model fills in: `username`. Must match the `{placeholder}` if the path uses one. | +| **Tool description** | Tell the model when to use the tool and what it returns: `Get a GitHub user's profile: name, company, location, repo and follower counts.` The model picks tools by this text — be specific. | +| **Input description** | What values are valid: `A GitHub login, like "torvalds" — not the display name.` | + +:::tip[The two descriptions do the heavy lifting] +The model decides *whether* to call your tool from the **tool description**, +and *what to pass* from the **input description**. Vague text here is the most +common reason a working connector never gets called. +::: + +## Step 4 — Review and generate + +![Step 4: Review](/img/extensions/builder-review.png) + +Check the summary — name, base URL, auth, tool, method, endpoint — then click +**Generate extension**. NeatContext writes a complete extension folder (a +manifest, an `http-connector.json` describing your endpoint, and a `server.cjs` +MCP server), installs it, and returns you to the Extensions page with the new +card enabled. + +## Try it + +1. If the extension needs credentials, fill the **Connect** form (API key) or + click **Connect** (OAuth) on its card. +2. Ask something in chat that needs the tool: + + > What company does the GitHub user torvalds work for? + + The activity trace shows `github_get_user` running, and the answer comes + from the live API response. + +## Growing beyond the builder + +The generated folder is a normal extension — click the **folder icon** on the +card to open it. `server.cjs` is a single readable file: a natural starting +point when you outgrow one tool per extension or need custom logic. From +there, continue with [Build Your First Extension](./building-extensions.md) +and the [manifest reference](./manifest-reference.md). diff --git a/docs/extensions/manifest-reference.md b/docs/extensions/manifest-reference.md index 861eabf..9591939 100644 --- a/docs/extensions/manifest-reference.md +++ b/docs/extensions/manifest-reference.md @@ -1,5 +1,5 @@ --- -sidebar_position: 5 +sidebar_position: 6 --- # Manifest Reference diff --git a/docs/extensions/oauth-extensions.md b/docs/extensions/oauth-extensions.md index 1806af8..a1e6259 100644 --- a/docs/extensions/oauth-extensions.md +++ b/docs/extensions/oauth-extensions.md @@ -1,5 +1,5 @@ --- -sidebar_position: 4 +sidebar_position: 5 --- # OAuth Extensions diff --git a/docs/extensions/overview.md b/docs/extensions/overview.md index 4f09ff4..f46f291 100644 --- a/docs/extensions/overview.md +++ b/docs/extensions/overview.md @@ -6,14 +6,26 @@ sidebar_position: 1 An **extension** gives the model **tools** for your systems — read an incident, search logs, list deployments, open a ticket, and so on. This section is for -**building** extensions; for installing, connecting, and managing them as a user -— including the no-code **Create extension** builder — see -[Using Extensions](../features/using-extensions.md). - -This page explains the extension architecture; the next pages walk through -[building one](./building-extensions.md), adding -[API-key](./api-key-extensions.md) or [OAuth](./oauth-extensions.md) -authentication, and the [manifest reference](./manifest-reference.md). +**creating** extensions; for installing, connecting, and managing them as a +user, see [Using Extensions](../features/using-extensions.md). + +## Two ways to create an extension + +1. **The UI builder (no code)** — the **Create** button on the Extensions page + generates a working, read-only connector for any JSON HTTP API in four + guided steps. Start here for straightforward "call this endpoint" tools: + [Create an Extension in the UI](./create-extension-ui.md). +2. **Write it yourself (code)** — a single Node script speaking MCP over + stdio gives you full control: multiple tools, custom logic, non-HTTP + backends, exotic auth. Start with + [Build Your First Extension](./building-extensions.md). + +Both produce the same thing — an extension folder with a manifest and an MCP +server — so you can begin in the builder and hand-edit the generated code +later. The rest of this page explains the architecture behind both; the next +pages cover [API-key](./api-key-extensions.md) and +[OAuth](./oauth-extensions.md) authentication and the +[manifest reference](./manifest-reference.md). ## What an extension is @@ -160,6 +172,8 @@ folder and read the source. They are the best starting templates. ## Next +- **[Create an Extension in the UI](./create-extension-ui.md)** — the four-step + no-code builder, field by field. - **[Build Your First Extension](./building-extensions.md)** — a complete, annotated stdio MCP connector with no authentication. - **[API-Key Extensions](./api-key-extensions.md)** — add a credentials form diff --git a/docs/features/using-extensions.md b/docs/features/using-extensions.md index 3fe7856..7875393 100644 --- a/docs/features/using-extensions.md +++ b/docs/features/using-extensions.md @@ -80,23 +80,30 @@ If you ask a question that needs a not-yet-connected extension, the answer will say so and offer a **Connect** button right in the chat — you don't have to remember to set things up in advance. -## Create an extension without writing code +## Create your own extension -The **Create** button opens a guided builder that generates a working, read-only -connector for any JSON HTTP API — no code required: +There are **two ways** to create an extension: -![The 4-step extension builder](/img/features/extension-builder.png) +1. **The Create builder (no code)** — the **Create** button opens a guided, + four-step builder that generates a working, read-only connector for any + JSON HTTP API: -1. **Basics** — name the connector and give the API's base URL. -2. **Auth** — none, an API-key header, or OAuth. -3. **Data** — define the endpoint path (e.g. `/api/services/{serviceName}`) and - the tool's input. -4. **Review** — check the result, then **Generate extension**. + ![The 4-step extension builder](/img/features/extension-builder.png) -The generated extension is installed like any other: it appears on the Extensions -page, its folder is openable (and a nice starting point to grow from if you later -want to hand-edit it), and secrets go through the normal encrypted connection -flow, never into the generated files. + **Basics** (name + base URL) → **Auth** (none, API-key header, or OAuth) → + **Data** (endpoint path + tool input) → **Review** → **Generate extension**. + Every field has a **?** next to its label with a detailed explanation and + examples. For a full field-by-field walkthrough with a real API, see + [Create an Extension in the UI](../extensions/create-extension-ui.md). + +2. **Write one yourself (code)** — a single Node script speaking MCP gives you + multiple tools and custom logic. See + [Building Extensions](../extensions/overview.md). + +Either way the result installs like any other extension: it appears on the +Extensions page, its folder is openable (a generated one is a nice starting +point if you later want to hand-edit it), and secrets go through the normal +encrypted connection flow, never into the generated files. ## Extensions in chat diff --git a/static/img/extensions/builder-auth-api-key.png b/static/img/extensions/builder-auth-api-key.png new file mode 100644 index 0000000..9542d6c Binary files /dev/null and b/static/img/extensions/builder-auth-api-key.png differ diff --git a/static/img/extensions/builder-basics.png b/static/img/extensions/builder-basics.png new file mode 100644 index 0000000..6ed1007 Binary files /dev/null and b/static/img/extensions/builder-basics.png differ diff --git a/static/img/extensions/builder-data.png b/static/img/extensions/builder-data.png new file mode 100644 index 0000000..e0dd0b2 Binary files /dev/null and b/static/img/extensions/builder-data.png differ diff --git a/static/img/extensions/builder-review.png b/static/img/extensions/builder-review.png new file mode 100644 index 0000000..9f9e3bf Binary files /dev/null and b/static/img/extensions/builder-review.png differ