Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/extensions/api-key-extensions.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 3
sidebar_position: 4
---

# API-Key Extensions
Expand Down
10 changes: 9 additions & 1 deletion docs/extensions/building-extensions.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 2
sidebar_position: 3
---

# Build Your First Extension
Expand All @@ -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
Expand Down
141 changes: 141 additions & 0 deletions docs/extensions/create-extension-ui.md
Original file line number Diff line number Diff line change
@@ -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 <key>`; 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:<port>/oauth/<extension-id>/callback`, where `<extension-id>` 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).
2 changes: 1 addition & 1 deletion docs/extensions/manifest-reference.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 5
sidebar_position: 6
---

# Manifest Reference
Expand Down
2 changes: 1 addition & 1 deletion docs/extensions/oauth-extensions.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 4
sidebar_position: 5
---

# OAuth Extensions
Expand Down
30 changes: 22 additions & 8 deletions docs/extensions/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down
33 changes: 20 additions & 13 deletions docs/features/using-extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Binary file added static/img/extensions/builder-auth-api-key.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/img/extensions/builder-basics.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/img/extensions/builder-data.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/img/extensions/builder-review.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading