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
1 change: 1 addition & 0 deletions server/mcp_server_openviking_controlplane/.python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.13
134 changes: 134 additions & 0 deletions server/mcp_server_openviking_controlplane/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# OpenViking Control Plane — MCP Server + CLI

MCP server **and** CLI for the OpenViking control plane (topapi) — manage OV
libraries (`Collection`). Both front-ends share one core (`client.py`), so a tool
added once is available from MCP and the CLI alike.

Covers the 6 core control-plane Actions:

| Action | MCP tool | CLI command |
|---|---|---|
| `ListOpenVikingCollections` | `list_collections` | `ov-cp list` |
| `CreateOpenVikingCollection` | `create_collection` ⚠️ | `ov-cp create` |
| `GetOpenVikingCollection` | `get_collection` | `ov-cp get <rid>` |
| `DeleteOpenVikingCollection` | `delete_collection` ⚠️ | `ov-cp delete <rid>` |
| `GetOpenVikingUsage` | `get_usage` | `ov-cp usage <rid>` |
| `GetOpenVikingCollectionUserAccess` | `get_collection_api_key` | `ov-cp api-key <rid>` |

## Endpoint

The control-plane TopAPI is compiled into the OpenViking **data-plane cluster**;
each Action is served by the data-plane gateway at:

```text
{endpoint}/api/openviking/{Action}
# default endpoint: https://api.vikingdb.cn-beijing.volces.com/openviking
# full URL e.g.: https://api.vikingdb.cn-beijing.volces.com/openviking/api/openviking/ListOpenVikingCollections
```

The Action lives in the **path** (no `?Action=&Version=` query). The request body
is the Action's params (e.g. `{"ResourceID": "..."}`).

> The default endpoint points at the **reserved** public data-plane gateway (not
> open to traffic yet). For local testing set `--endpoint` / `VIKING_ENDPOINT` to a
> `kubectl port-forward`, e.g. `http://localhost:18080`.

## Authentication

The only method: an **Ark AgentPlan ApiKey**, sent as an `Authorization: Bearer
<key>` header on every request (the backend's `authorizeControlPlaneByArk` reads
the key only from this header — it does **not** accept `X-API-Key`). Auth is
pluggable (`common/auth.py` → `BearerTokenAuth`); an AK/SK signer can be swapped in
later without touching the rest.

> ⚠️ Write actions like `create` require the account to have **AgentPlan deduction
> activated**, otherwise they return `ProductUnordered`. Read-only actions
> (list/get/usage/delete) are not gated.

### Configuration

| Setting | Env var | CLI flag | Default |
|---|---|---|---|
| Control-plane endpoint (base URL) | `VIKING_ENDPOINT` | `--endpoint` / `-e` | `https://api.vikingdb.cn-beijing.volces.com/openviking` |
| AgentPlan ApiKey | `AGENTPLAN_API_KEY` | `--api-key` / `-k` | — (required) |
| Default project | `OPENVIKING_PROJECT` | `--project` | `default` |

## CLI usage

```bash
uv sync # or: pip install -e .

# set the key once via env, then drop the per-command flag
export AGENTPLAN_API_KEY=ark-xxxxxxxx

# read-only
uv run ov-cp list
uv run ov-cp get <ResourceID>
uv run ov-cp usage <ResourceID>
uv run ov-cp api-key <ResourceID>

# create (consumes paid quota; with source=agentplan only --name is needed —
# model names default, and the model ApiKey falls back to the configured key)
uv run ov-cp create --name my_kb

# delete (irreversible)
uv run ov-cp delete <ResourceID> --yes
```

Flags override env. The endpoint defaults to the public gateway; override it only
for testing (e.g. against a port-forward) with `-e` / `VIKING_ENDPOINT` —
`uv run ov-cp -e http://localhost:18080 list`.
`ov-cp --help` works without any config.

## MCP usage (stdio / uvx)

The server defaults to **stdio** transport, so it can be launched as a subprocess by
any MCP client. Add to `.mcp.json`:

```json
{
"mcpServers": {
"openviking-controlplane": {
"command": "uvx",
"args": [
"--from",
"git+https://github.com/volcengine/mcp-server#subdirectory=server/mcp_server_openviking_controlplane",
"mcp-server-openviking-controlplane"
],
"env": {
"AGENTPLAN_API_KEY": "ark-xxxxxxxx"
}
}
}
}
```

For local development point it at your checkout instead:

```json
{
"mcpServers": {
"openviking-controlplane": {
"command": "uv",
"args": ["run", "--directory", "/abs/path/server/mcp_server_openviking_controlplane",
"mcp-server-openviking-controlplane"],
"env": {
"AGENTPLAN_API_KEY": "ark-xxxxxxxx"
}
}
}
}
```

Run with SSE instead via `mcp-server-openviking-controlplane --transport sse`.

## Agent skill

A Claude Code / agent skill that documents the `ov-cp` workflow lives at
[`skills/openviking-controlplane/SKILL.md`](skills/openviking-controlplane/SKILL.md).
Symlink or copy it into your agent's skills directory (e.g. `~/.claude/skills/`) to
let an agent drive the control plane.

> ⚠️ `create_collection` / `delete_collection` create/destroy **billable** resources and
> are exposed as MCP tools; their descriptions instruct the model to confirm with you
> first. Rely on your client's tool-permission prompt as the final gate.
120 changes: 120 additions & 0 deletions server/mcp_server_openviking_controlplane/README_zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# OpenViking 控制面 — MCP Server + CLI

OpenViking 控制面(topapi)的 MCP Server **与** CLI —— 用于管理 OV 库
(`Collection`)。两个前端共用同一套核心(`client.py`),新增一个能力即可同时被 MCP
和 CLI 使用。

覆盖 6 个核心控制面 Action:

| Action | MCP tool | CLI 命令 |
|---|---|---|
| `ListOpenVikingCollections` | `list_collections` | `ov-cp list` |
| `CreateOpenVikingCollection` | `create_collection` ⚠️ | `ov-cp create` |
| `GetOpenVikingCollection` | `get_collection` | `ov-cp get <rid>` |
| `DeleteOpenVikingCollection` | `delete_collection` ⚠️ | `ov-cp delete <rid>` |
| `GetOpenVikingUsage` | `get_usage` | `ov-cp usage <rid>` |
| `GetOpenVikingCollectionUserAccess` | `get_collection_api_key` | `ov-cp api-key <rid>` |

## 端点

控制面 TopAPI 接口已编译进 OpenViking **数据面集群**,每个 Action 由数据面网关在如下路径提供:

```text
{endpoint}/api/openviking/{Action}
# 默认 endpoint:https://api.vikingdb.cn-beijing.volces.com/openviking
# 完整 URL 例:https://api.vikingdb.cn-beijing.volces.com/openviking/api/openviking/ListOpenVikingCollections
```

Action 在 **path** 里(不走 `?Action=&Version=` query)。请求体是该 Action 的参数(如
`{"ResourceID": "..."}`)。

> 默认 endpoint 指向**预留**的公网数据面网关(尚未对外开放)。本地/联调时用
> `--endpoint` / `VIKING_ENDPOINT` 指向一个 `kubectl port-forward`,例如
> `http://localhost:18080`。

## 鉴权

唯一方式:**Ark AgentPlan ApiKey**,作为 `Authorization: Bearer <key>` 头随每个请求发送
(后端 `authorizeControlPlaneByArk` 只认 Bearer,**不兼容 `X-API-Key`**)。鉴权是可插拔的
(`common/auth.py` → `BearerTokenAuth`),后续要换 AK/SK 签名时只需替换这一处。

> ⚠️ `create` 等写接口要求账号已**开通 AgentPlan 抵扣**,否则返回 `ProductUnordered`;
> 只读接口(list/get/usage/delete)不受此限。

### 配置

| 项 | 环境变量 | CLI 参数 | 默认 |
|---|---|---|---|
| 控制面 endpoint(base URL) | `VIKING_ENDPOINT` | `--endpoint` / `-e` | `https://api.vikingdb.cn-beijing.volces.com/openviking` |
| AgentPlan ApiKey | `AGENTPLAN_API_KEY` | `--api-key` / `-k` | —(必填) |
| 默认 project | `OPENVIKING_PROJECT` | `--project` | `default` |

## CLI 用法

```bash
uv sync # 或:pip install -e .

# 把 key 用环境变量配一次,之后免传参
export AGENTPLAN_API_KEY=ark-xxxxxxxx

# 只读
uv run ov-cp list
uv run ov-cp get <ResourceID>
uv run ov-cp usage <ResourceID>
uv run ov-cp api-key <ResourceID>

# 建库(消耗付费配额;source=agentplan 时只需 --name,
# 模型名取默认、模型 ApiKey 回落到配置的 key)
uv run ov-cp create --name my_kb

# 删库(不可逆)
uv run ov-cp delete <ResourceID> --yes
```

命令行参数优先于环境变量。端点默认指向公网网关;仅在测试时(如指向 port-forward)才用
`-e` / `VIKING_ENDPOINT` 覆盖:`uv run ov-cp -e http://localhost:18080 list`。
`ov-cp --help` 不需要任何配置即可运行。

## MCP 用法(stdio / uvx)

Server 默认 **stdio** 传输,可被任意 MCP 客户端作为子进程拉起。`.mcp.json` 配置:

```json
{
"mcpServers": {
"openviking-controlplane": {
"command": "uvx",
"args": [
"--from",
"git+https://github.com/volcengine/mcp-server#subdirectory=server/mcp_server_openviking_controlplane",
"mcp-server-openviking-controlplane"
],
"env": {
"AGENTPLAN_API_KEY": "ark-xxxxxxxx"
}
}
}
}
```

本地开发可改指向你的代码检出:

```json
{
"mcpServers": {
"openviking-controlplane": {
"command": "uv",
"args": ["run", "--directory", "/abs/path/server/mcp_server_openviking_controlplane",
"mcp-server-openviking-controlplane"],
"env": {
"AGENTPLAN_API_KEY": "ark-xxxxxxxx"
}
}
}
}
```

需要 SSE 时:`mcp-server-openviking-controlplane --transport sse`。

> ⚠️ `create_collection` / `delete_collection` 会创建/销毁**付费**资源,且已暴露为 MCP
> tool;其描述会要求模型先与你确认。最终拦截依赖客户端的工具授权弹窗。
20 changes: 20 additions & 0 deletions server/mcp_server_openviking_controlplane/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[project]
name = "mcp-server-openviking-controlplane"
version = "0.1.0"
description = "MCP server and CLI for the OpenViking control plane (topapi) collection management"
readme = "README.md"
requires-python = ">=3.10"
license = {text = "MIT"}
dependencies = [
"mcp[cli]>=1.5.0",
"requests>=2.31.0",
"typer>=0.12.0",
]

[project.scripts]
mcp-server-openviking-controlplane = "mcp_server_openviking_controlplane.server:main"
ov-cp = "mcp_server_openviking_controlplane.cli:main"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
name: openviking-controlplane
description: Manage OpenViking collections (OV libraries) from the command line with `ov-cp` — list / create / get / usage / get the data-plane API key / delete. Use when the user wants to provision or inspect an OpenViking library, fetch a library's data-plane API key, do the create→get-key cold-start, or otherwise drive the OpenViking control plane (topapi). Authenticates with an Ark AgentPlan ApiKey.
---

# OpenViking Control Plane (`ov-cp`)

`ov-cp` is the CLI for the OpenViking control plane (topapi). It manages OV
**collections** (libraries) and shares its core with the
`mcp-server-openviking-controlplane` MCP server, so behavior is identical.

## Setup

Install once (from the package dir): `uv sync` (or `pip install -e .`).

Configure via env vars (CLI flags `-k` / `-e` / `--project` override them):

| Env var | Meaning | Default |
|---|---|---|
| `AGENTPLAN_API_KEY` | Ark AgentPlan ApiKey (sent as `Authorization: Bearer`) | — (required) |
| `VIKING_ENDPOINT` | Control-plane base URL | `https://api.vikingdb.cn-beijing.volces.com/openviking` |
| `OPENVIKING_PROJECT` | Default project | `default` |

```bash
export AGENTPLAN_API_KEY=ark-xxxxxxxx
# VIKING_ENDPOINT defaults to the public gateway — leave it unset for normal use.
```

> The default endpoint is the **reserved** public gateway (not open yet). Override
> `VIKING_ENDPOINT` (or `-e`) only for testing — e.g. point it at a `kubectl
> port-forward` of the data-plane service. The full request URL is
> `{endpoint}/api/openviking/{Action}`.

## Commands

```bash
ov-cp list # list collections (optionally --project X)
ov-cp get <ResourceID> # collection info (Status, models, version, ...)
ov-cp usage <ResourceID> # file counts / estimated cost
ov-cp api-key <ResourceID> # plaintext data-plane key {UserID, Role, ApiKey}
ov-cp create --name my_kb # create a collection (see below)
ov-cp delete <ResourceID> --yes # delete (irreversible; uninstalls the Helm release)
```

Output is JSON. Errors print `Error [Code]: Message` to stderr with exit code 1.
`ov-cp --help` and `ov-cp <cmd> --help` work without any config.

## Creating a collection

⚠️ **Billable + requires the account to have AgentPlan deduction activated** (else
`ProductUnordered`). Confirm with the user before creating. Max 20 libraries/account.

For `--source agentplan` (default) you only need `--name`: the VLM/Embedding model
names default to `doubao-seed-2.0-lite` / `doubao-embedding-vision`, and the model
ApiKey falls back to the configured AgentPlan key.

```bash
ov-cp create --name my_kb
# other sources need explicit model creds:
ov-cp create --name my_kb --source volcengine \
--vlm-api-key-id <id> --vlm-endpoint-id <ep> \
--emb-api-key-id <id> --emb-endpoint-id <ep>
```

## Cold-start chain (create → use the library)

```bash
RID=$(ov-cp create --name my_kb | python3 -c 'import sys,json;print(json.load(sys.stdin)["ResourceID"])')
# Poll until provisioned; api-key times out while Status is INIT.
ov-cp get "$RID" # wait for "Status": "READY"
ov-cp api-key "$RID" # -> the plaintext data-plane key for the library
```

The returned `ApiKey` is the library's **data-plane** key. Use it as
`Authorization: Bearer <key>` against the library's data-plane (e.g.
`GET {endpoint}/health`, `GET {endpoint}/api/v1/system/status`,
`GET {endpoint}/api/v1/fs/ls?uri=viking://`).

## Notes

- Only `Authorization: Bearer` is accepted (no `X-API-Key`).
- Read-only actions (list/get/usage/delete) are not gated by AgentPlan; create and
api-key are.
- `get`/`usage`/`api-key`/`delete` take a `ResourceID` (e.g. `ov-xxxxxxxx`).
Loading
Loading