Skip to content
Open
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
114 changes: 114 additions & 0 deletions docs/en/how-to/configure-external-mcp.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
---
weight: 10
---

# Configure External MCP Servers

Alauda Hyperflux ships with a built-in MCP server that provides cluster-aware tools.
You can extend the agent's tool set with your own (external) MCP servers — for example an
internal wiki search, a CMDB query service, or any other MCP-compatible endpoint.

External MCP servers are declared in ConfigMaps and registered through the installation form.
At startup, Alauda Hyperflux connects to each server, lists its tools, and makes them available
to the agent alongside the built-in tools.

## Declare the MCP servers in a ConfigMap

Create a ConfigMap **in the namespace where Alauda Hyperflux is installed** (`cpaas-system`).
Every data key with a `.yaml`, `.yml` or `.json` extension is parsed; the content of each file
must be a **list** of server entries:

```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: my-org-mcp-servers
namespace: cpaas-system
data:
servers.yaml: |
- name: corp-wiki
url: https://wiki-mcp.example.com/mcp
transport: streamable_http
headers:
Authorization: "Bearer <your-token>"
- name: cmdb
url: https://cmdb-mcp.example.com/sse
transport: sse
tls_verify: false
```

Fields per server entry:

| Field | Required | Description |
|---|---|---|
| `name` | Yes | Unique server name matching `^[a-z][a-z0-9_-]*$`. The name `acp_mcp_server` is reserved. |
| `url` | Yes | The MCP endpoint URL. |
| `transport` | No | `streamable_http` (default) or `sse`. |
| `headers` | No | Static HTTP headers sent on every request, e.g. for token auth. `${VAR}` placeholders are substituted from the container environment if the variable exists. |
| `tls_verify` | No | Whether to verify the server's TLS certificate. Default `true`. For endpoints using an internal CA, prefer keeping this `true` and adding the CA via **Extra CA ConfigMaps** (see [Configure TLS](./configure-tls.mdx)). |

Invalid entries (bad name, missing url, unknown transport, duplicate name) are skipped with an
ERROR log; they never prevent the other servers or the service itself from starting.

> **NOTE:** ConfigMap values are stored in plain text. Avoid putting long-lived secrets directly
> in `headers`; rotate any token you place there as you would any shared credential.

## Register the ConfigMap

In **Administrator / Marketplace / Cluster Plugins**, install or update the `Alauda Hyperflux`
plugin and add the ConfigMap name under **Extra MCP Servers ConfigMaps**.

Each listed ConfigMap is mounted read-only at `/opt/extra-mcp/<configmap-name>/` and scanned
**once at startup**:

- Adding or removing a ConfigMap name in the form triggers a rolling restart automatically.
- Editing the *content* of an already-registered ConfigMap does **not** — restart manually:

```bash
kubectl -n cpaas-system rollout restart deploy/smart-doc
```

## Tool naming and approval

Tools from an external server are exposed to the agent with the server name as a prefix,
e.g. `corp-wiki__search_pages`, so they can never collide with built-in tool names.

External tools are subject to the same **Tool Approval Strategy** as built-in tools:

- With the default strategy `disabled`, any tool **not** annotated `readOnlyHint: true` by its
MCP server is filtered out of the agent's tool set entirely. Many MCP servers do not annotate
their tools — in that case none of their tools will be visible until you either switch the
strategy to `tool_annotations` (write tools then require interactive approval) or have the
MCP server annotate its read-only tools.
- With `tool_annotations`, read-only tools run freely and all other tools prompt the user for
approval before each call.

## Verify

Check the startup logs:

```bash
kubectl -n cpaas-system logs -l app=smart-doc -c serve | grep -i "extra mcp\|MCP tools"
```

Expected lines:

```
Loading extra MCP servers from file /opt/extra-mcp/my-org-mcp-servers/servers.yaml
Loading extra MCP server name=corp-wiki url=https://wiki-mcp.example.com/mcp transport=streamable_http headers={'Authorization': '<redacted>'}
Extra MCP corp-wiki loaded 3 tools: ['corp-wiki__search_pages', ...]
Loaded 15 MCP tools (acp=12, extra=3)
```

Common failure modes:

| Log message | Cause |
|---|---|
| `Extra MCP <name> timed out after 10.0s; skipped` | The endpoint is unreachable or slow; each server has a 10-second connection budget and is skipped without affecting the others. |
| `Extra MCP <name> failed to load: ...; skipped` | Connection or protocol error — check the URL, transport and TLS trust. |
| `<file> is not valid YAML` / `must be a list` | The ConfigMap file content is malformed. |
| `extra MCP header placeholder ${VAR} not in environment; leaving as-is` | A `${VAR}` header referenced an environment variable that does not exist in the container. |
| `AGENT_APPROVAL_STRATEGY=disabled — filtered out N write/unannotated tools` | Tools without `readOnlyHint: true` were removed under the default approval strategy (see above). |

Sensitive header values (`Authorization`, `X-API-Key`, cookies, and any value longer than
16 characters) are always redacted in logs.
144 changes: 144 additions & 0 deletions docs/en/how-to/configure-redaction.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
---
weight: 50
---

# Configure Data Redaction

Alauda Hyperflux can redact sensitive values — internal IPs, tokens, passwords — before they
leave the service or get persisted. Redaction is opt-in and has three parts:

- **Value rules** (`queryRedactionFilters`): regex rules applied to the user's question and
attachments, and to agent tool results, *before* the text is sent to the LLM and *before* it
is written to the conversation history.
- **Key-name redaction** (`toolArgRedactKeys`): tool-call arguments whose key name looks like a
credential (`password`, `token`, `api_key`, ...) are masked on approval cards and in the
approval audit records.
- **Redaction audit**: every rule hit is recorded (rule name and hit count — never the value
itself) and is queryable by platform administrators.

> **NOTE:** Redaction is an input-side filter with the precision of your regex rules. A value
> that no rule matches still flows to the LLM and may appear in answers. Do not treat it as a
> guaranteed output filter.

Both settings are **not** in the installation form. They are applied by patching the plugin
configuration (`ModuleInfo`), and take effect after the pods restart (the platform rolls them
automatically after a patch).

## Value rules (`queryRedactionFilters`)

Each rule is an object:

| Field | Required | Description |
|---|---|---|
| `name` | Yes | Rule label; shows up in logs and the audit records. |
| `pattern` | Yes | Regular expression (Python `re` syntax). |
| `mode` | No | `redact` (default) — replace the match with `replace_with`; or `tokenize` — replace the match with an opaque per-request token that is substituted back only when the value is passed to an actual tool execution, so the LLM never sees it but tools still receive the real value. |
| `replace_with` | For `redact` | Literal replacement text, e.g. `[REDACTED_IP]`. |
| `applies_to` | No | Surfaces the rule runs on: `query` (the user's question and attachments — the default) and/or `tool_result` (agent tool outputs before they are fed back to the LLM). |

Example rule set:

```json
[
{
"name": "internal_ip",
"pattern": "\\b(?:10|127)\\.(?:\\d{1,3}\\.){2}\\d{1,3}\\b",
"replace_with": "[REDACTED_IP]",
"applies_to": ["query"]
},
{
"name": "jwt",
"pattern": "eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+",
"replace_with": "[REDACTED_JWT]",
"applies_to": ["query", "tool_result"]
}
]
```

Apply it (the value is the JSON array as a **string**):

```bash
MI=$(kubectl get moduleinfo -o jsonpath='{.items[?(@.spec.module=="alauda-hyperflux")].metadata.name}')
kubectl patch moduleinfo "$MI" --type=merge -p '{
"spec": {"config": {"smartdoc": {
"queryRedactionFilters": "[{\"name\":\"internal_ip\",\"pattern\":\"\\\\b(?:10|127)\\\\.(?:\\\\d{1,3}\\\\.){2}\\\\d{1,3}\\\\b\",\"replace_with\":\"[REDACTED_IP]\",\"applies_to\":[\"query\"]}]"
}}}
}'
```

Validation is strict: a malformed JSON string fails the deployment render, and an invalid
individual rule (missing `name`/`pattern`, unknown `mode` or `applies_to`, uncompilable regex)
prevents the service from starting. Redaction itself is fail-closed — if applying the rules to
a request errors out, the turn is aborted rather than letting the raw text through.

Writing rules well:

- Rules run **sequentially in list order** on every request; an earlier rule's replacement text
is visible to later rules. Put broad rules last.
- Keep patterns narrow and anchored. Regex syntax is validated at startup, but catastrophic
backtracking is not — avoid nested quantifiers.
- Over-broad rules silently degrade answer quality (the LLM sees `[REDACTED_...]` instead of
the real value), which is why the feature ships empty by default.

## Key-name redaction (`toolArgRedactKeys`)

Independent of the value rules, tool-call arguments shown on approval cards and stored in the
approval audit are masked when the argument's key name contains one of the configured
substrings (case-insensitive). The tool itself still receives the real value.

When unset, a built-in safe set applies:

```
password, passwd, secret, token, api_key, apikey, api-key,
authorization, credential, private_key, access_key, secret_key
```

Setting `toolArgRedactKeys` (comma-separated substrings) **replaces** this set — include the
defaults you want to keep. Setting it to an empty string does not disable the feature; the
default set applies again.

## Redaction audit

As soon as either setting above is configured, every rule hit is recorded in the
`redaction_audit` table of the conversation-history database: request id, session, username,
surface (`query` / `attachment` / `tool_result` / `tool_args`), rule name, mode, and hit count.
**The matched value is never stored.**

Platform administrators (see **Admin Users** in the installation form) can query the records:

```
GET https://<platform-address>/smart-doc/api/admin/redaction_audit
```

Supported query parameters (all optional, ANDed): `username`, `session_id`, `request_id`,
`surface`, `rule_name`, `from`, `to`, plus `limit` (default 100, max 1000) and `offset`.
Non-admin callers receive 403.

Two operational notes:

- Audit writes are best-effort: a failed write is logged and dropped, never failing the user's
request. Do not treat the table as a guaranteed-complete compliance ledger.
- There is no automatic retention/cleanup for `redaction_audit` — prune it externally if your
deployment handles large volumes.

## Verify

Send a question containing a value your rule matches, then check the logs:

```bash
kubectl -n cpaas-system logs -l app=smart-doc -c serve | grep 'redaction hits'
```

Expected (rule names and counts only, never values):

```
query redaction hits: {'internal_ip': 2}
tool-result redaction hits: {'jwt': 1}
```

And query the audit as an admin:

```bash
curl -sk "https://<platform-address>/smart-doc/api/admin/redaction_audit?rule_name=internal_ip" \
-H "Authorization: Bearer <admin-acp-token>"
```
99 changes: 99 additions & 0 deletions docs/en/how-to/configure-tls.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
---
weight: 30
---

# Configure TLS

This guide covers the TLS-related configuration of Alauda Hyperflux for its outbound
connections: the LLM service, the reranker, MCP servers and PostgreSQL.

The most common need — trusting an LLM or MCP endpoint that uses an internal or self-signed
certificate — is solved with **Extra CA ConfigMaps**, available directly in the installation
form. For test environments, certificate verification for LLM calls can also be skipped
entirely (see the last section).

## Trust an internal / self-signed CA (Extra CA ConfigMaps)

If your LLM, reranker or MCP endpoint presents a certificate signed by an internal CA, requests
fail with `CERTIFICATE_VERIFY_FAILED`. Add the CA certificate to the trust bundle:

1. Create a ConfigMap holding the CA certificate (PEM) **in the namespace where Alauda
Hyperflux is installed** (`cpaas-system`). CA certificates are public, so a ConfigMap — not
a Secret — is appropriate. One ConfigMap can hold multiple `*.pem` keys:

```bash
kubectl create configmap my-org-internal-ca -n cpaas-system \
--from-file=ca.pem=/path/to/internal-ca.pem
```

2. In **Administrator / Marketplace / Cluster Plugins**, install or update the
`Alauda Hyperflux` plugin and add the ConfigMap name under **Extra CA ConfigMaps**.
The service restarts automatically.

Each listed ConfigMap is mounted read-only at `/opt/extra-ca/<configmap-name>/`. At startup the
certificates are merged with the default CA bundle and the merged bundle is applied
process-wide, so it covers **LLM, reranker and MCP** connections.

> **NOTE:** PostgreSQL is the exception — it does not use this bundle. TLS to an external
> PostgreSQL is configured separately via the `pgSSLMode` / `pgSSLRootCert` values of the
> plugin configuration.

Updating the *content* of an already-registered ConfigMap (e.g. rotating the CA) requires a
manual restart:

```bash
kubectl -n cpaas-system rollout restart deploy/smart-doc
```

### Verify

```bash
# The mounted CA and the merged bundle
kubectl -n cpaas-system exec deploy/smart-doc -c serve -- ls /opt/extra-ca/my-org-internal-ca/
kubectl -n cpaas-system exec deploy/smart-doc -c serve -- grep -c 'BEGIN CERTIFICATE' /tmp/smart-doc-ca.pem

# The startup log line
kubectl -n cpaas-system logs -l app=smart-doc -c serve | grep extra_ca
```

Expected log line:

```
extra_ca: merged 1/1 CA file(s) into /tmp/smart-doc-ca.pem
```

Then ask a question in the chat panel — requests to the endpoint that previously failed with
`CERTIFICATE_VERIFY_FAILED` should now succeed.

## Skip TLS certificate verification (not recommended)

For test or development environments where importing the CA is not practical, TLS certificate
verification for **LLM calls** can be switched off entirely with `llmSkipSslVerify`.

> **WARNING:** This exposes the LLM connection to man-in-the-middle attacks, and it overrides
> both the TLS profile and any extra CA trust — which is why it is deliberately not offered in
> the installation form. The production-safe path for internal certificates is
> **Extra CA ConfigMaps** above. The setting affects LLM calls only; reranker, MCP and
> PostgreSQL connections are not touched.

Apply it by patching the plugin configuration (`ModuleInfo`) directly:

```bash
# Find the ModuleInfo of the Hyperflux plugin (cluster-scoped, name like global-<hash>)
MI=$(kubectl get moduleinfo -o jsonpath='{.items[?(@.spec.module=="alauda-hyperflux")].metadata.name}')

kubectl patch moduleinfo "$MI" --type=merge -p \
'{"spec":{"config":{"smartdoc":{"llmSkipSslVerify":true}}}}'
```

The platform reconciles the change and rolls the pods automatically. When enabled, every
startup logs a warning:

```
LLM_SKIP_SSL_VERIFY=true — LLM TLS certificate verification is DISABLED (verify=False)
```

To revert, patch the value back to `false`.

For external MCP servers there is an equivalent per-server `tls_verify: false` field — see
[Configure External MCP Servers](./configure-external-mcp.mdx), with the same caveat.
Loading