This is an automated email from the ASF dual-hosted git repository.

Similarityoung pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/dubbo-go-pixiu.git


The following commit(s) were added to refs/heads/develop by this push:
     new e3031c478 Fix: improve skills for pixiu (#933)
e3031c478 is described below

commit e3031c478cc1ee6fdf57c2c337259fb5f3e0f0e8
Author: wm_03 <[email protected]>
AuthorDate: Wed Jul 22 16:33:12 2026 +0800

    Fix: improve skills for pixiu (#933)
    
    * feat: add Pixiu skills
    
    * fix: harden Pixiu skill validators and docs
    
    * fix: harden Pixiu skill scripts
    
    * fix: add MCP validator dependency preflight
    
    * harden Pixiu validators against helper failures
    
    * fix: write validator failure summaries to stderr
    
    * fix: add license headers to Pixiu skill scripts
    
    * fix: remove check scripts and reference docs
    
    * fix: update Pixiu skills for new Dubbo config style
    
    * fix: improve pixiu skills
    
    * fix: Rename pixiu-mcp-integration to pixiu-mcp-gateway
    
    * fix: add <HARD-GATE>
    
    * fix skills review feedback
    
    * Move Pixiu skills under agents directory
    
    * feat: introduce Pixiu agent plugin
    
    * docs(skills): tighten Pixiu filter and MCP gateway validation
---
 .agents/.claude-plugin/marketplace.json     |  21 ++
 .agents/.claude-plugin/plugin.json          |   8 +
 .agents/.codex-plugin/plugin.json           |   6 +
 .agents/README.md                           | 100 +++++++
 .agents/README_CN.md                        | 100 +++++++
 .agents/plugins/marketplace.json            |  22 ++
 .agents/skills/pixiu-filter-author/SKILL.md |  71 +++++
 .agents/skills/pixiu-http-to-dubbo/SKILL.md | 249 +++++++++++++++++
 .agents/skills/pixiu-llm-gateway/SKILL.md   | 265 ++++++++++++++++++
 .agents/skills/pixiu-mcp-gateway/SKILL.md   | 314 ++++++++++++++++++++++
 skills/pixiu-filter-author/SKILL.md         | 359 -------------------------
 skills/pixiu-http-to-dubbo/SKILL.md         | 399 ----------------------------
 skills/pixiu-llm-gateway/SKILL.md           | 293 --------------------
 skills/pixiu-mcp-integration/SKILL.md       | 231 ----------------
 14 files changed, 1156 insertions(+), 1282 deletions(-)

diff --git a/.agents/.claude-plugin/marketplace.json 
b/.agents/.claude-plugin/marketplace.json
new file mode 100644
index 000000000..3140d6608
--- /dev/null
+++ b/.agents/.claude-plugin/marketplace.json
@@ -0,0 +1,21 @@
+{
+  "$schema": "https://anthropic.com/claude-code/marketplace.schema.json";,
+  "name": "dubbo-go-pixiu-agent-skills",
+  "description": "Agent skills bundled with Apache dubbo-go-pixiu for gateway 
users",
+  "owner": {
+    "name": "Apache Dubbo"
+  },
+  "plugins": [
+    {
+      "name": "dubbo-go-pixiu",
+      "description": "AI skills for Apache dubbo-go-pixiu users — HTTP/Network 
filters, HTTP-to-Dubbo routing, LLM gateway, and MCP gateway configuration.",
+      "category": "development",
+      "source": {
+        "source": "git-subdir",
+        "url": "https://github.com/apache/dubbo-go-pixiu.git";,
+        "path": ".agents"
+      },
+      "homepage": "https://github.com/apache/dubbo-go-pixiu/tree/main/.agents";
+    }
+  ]
+}
diff --git a/.agents/.claude-plugin/plugin.json 
b/.agents/.claude-plugin/plugin.json
new file mode 100644
index 000000000..3bbae87ea
--- /dev/null
+++ b/.agents/.claude-plugin/plugin.json
@@ -0,0 +1,8 @@
+{
+  "name": "dubbo-go-pixiu",
+  "version": "0.1.0",
+  "description": "Agent skills bundled with Apache dubbo-go-pixiu for gateway 
users — HTTP/Network filters, HTTP-to-Dubbo routing, LLM gateway, and MCP 
gateway configuration.",
+  "author": {
+    "name": "Apache dubbo-go-pixiu contributors"
+  }
+}
diff --git a/.agents/.codex-plugin/plugin.json 
b/.agents/.codex-plugin/plugin.json
new file mode 100644
index 000000000..724a4b1d3
--- /dev/null
+++ b/.agents/.codex-plugin/plugin.json
@@ -0,0 +1,6 @@
+{
+  "name": "dubbo-go-pixiu",
+  "version": "0.1.0",
+  "description": "Agent skills bundled with Apache dubbo-go-pixiu for gateway 
users — HTTP/Network filters, HTTP-to-Dubbo routing, LLM gateway, and MCP 
gateway configuration.",
+  "skills": "./skills/"
+}
diff --git a/.agents/README.md b/.agents/README.md
new file mode 100644
index 000000000..78b199d51
--- /dev/null
+++ b/.agents/README.md
@@ -0,0 +1,100 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+# dubbo-go-pixiu Agent Skills
+
+English | [中文](README_CN.md)
+
+AI agent skills maintained alongside [Apache 
dubbo-go-pixiu](https://github.com/apache/dubbo-go-pixiu) — so your coding 
assistant actually knows how to configure the Pixiu gateway.
+
+## What you get
+
+Four skills cover Pixiu's most common gateway tasks: HTTP-to-Dubbo routing, 
custom filters, the LLM gateway, and the MCP gateway. They generate config and 
code against the real fields and SPI conventions, avoiding the "compiles but 
doesn't take effect" pitfalls.
+
+## Installation
+
+The method differs by AI tool: Claude Code / Cursor have a built-in 
marketplace; Codex installs manually.
+
+### Claude Code / Cursor
+
+```bash
+/plugin marketplace add apache/dubbo-go-pixiu
+/plugin install dubbo-go-pixiu@dubbo-go-pixiu-agent-skills
+```
+
+### Codex
+
+```bash
+codex plugin marketplace add apache/dubbo-go-pixiu
+```
+
+Then open `/plugins`, select the `dubbo-go-pixiu` marketplace → Install plugin.
+
+## Skills
+
+### pixiu-filter-author
+
+Create and debug Pixiu HTTP/Network filters: SPI implementation, registration 
in `init()` (`RegisterHttpFilter` / `RegisterNetworkFilterPlugin`), the blank 
import in `registry.go`, aligning `Kind` with `key.go`, and mounting under HCM 
or the filter-chain.
+
+Example triggers:
+
+- "Write a custom HTTP filter for Pixiu"
+- "My filter compiles but doesn't run"
+- "Port this Envoy filter to Pixiu"
+
+### pixiu-http-to-dubbo
+
+Create and debug HTTP-to-Dubbo routes: `api_config.yaml` / `conf.yaml` routes, 
registry/direct mode switching, `mappingParams`, `mapType`, `parameterTypes`, 
`opt.values` / `opt.types`, and POJO handling.
+
+Example triggers:
+
+- "Route /api/v1/users to the Dubbo UserService"
+- "How do I debug a consumer reporting no provider found"
+- "How should I map the parameters of a Dubbo method"
+
+### pixiu-llm-gateway
+
+Create and validate an LLM gateway `conf.yaml` that configures Pixiu as a 
multi-provider HTTP proxy: proxy / tokenizer / kvcache filters, `llm_meta`, 
retry/fallback, vLLM/LMCache, and Nacos LLM discovery.
+
+Example triggers:
+
+- "Set up an LLM gateway using vLLM"
+- "Add retry and fallback to the LLM gateway"
+- "Use Nacos for LLM service discovery"
+
+### pixiu-mcp-gateway
+
+Create and validate an MCP gateway `conf.yaml` that exposes backend HTTP APIs 
as MCP tools: static / Nacos dynamic modes, the MCP server filter, 
tools/resources/prompts, Mcp-Session-Id, OAuth/JWT protection, and Streamable 
HTTP/SSE.
+
+Example triggers:
+
+- "Expose my backend HTTP API as MCP tools"
+- "Set up an MCP gateway with OAuth protection"
+- "Manage MCP tools dynamically with Nacos"
+
+## Contributing
+
+Skill files live at `.agents/skills/<name>/SKILL.md`.
+
+1. Edit or add skills directly.
+2. Keep each skill's frontmatter `description` focused on its trigger 
scenarios — the agent relies on that single line to decide whether to use the 
skill.
+3. Only touch the metadata under `.agents/` when the install path, skill 
names, or supported agents change.
+4. Submit changes through the normal dubbo-go-pixiu contribution process.
+
+## License
+
+Apache License 2.0
diff --git a/.agents/README_CN.md b/.agents/README_CN.md
new file mode 100644
index 000000000..5ac925c3e
--- /dev/null
+++ b/.agents/README_CN.md
@@ -0,0 +1,100 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+# dubbo-go-pixiu Agent Skills
+
+[English](README.md) | 中文
+
+随 [Apache dubbo-go-pixiu](https://github.com/apache/dubbo-go-pixiu) 一起维护的 AI 
Agent Skills——让编码助手真正会配 Pixiu 网关。
+
+## 它能给你什么
+
+四个 skill 覆盖 Pixiu 最常见的网关任务:HTTP→Dubbo 路由、自定义 filter、LLM 网关、MCP 网关。它们按真实字段和 SPI 
约定生成配置与代码,避开"能编译却没生效"这类坑。
+
+## 安装
+
+不同 AI 工具方式不同:Claude Code / Cursor 内置市场,Codex / OpenCode 需手动安装。
+
+### Claude Code / Cursor
+
+```bash
+/plugin marketplace add apache/dubbo-go-pixiu
+/plugin install dubbo-go-pixiu@dubbo-go-pixiu-agent-skills
+```
+
+### Codex
+
+```bash
+codex plugin marketplace add apache/dubbo-go-pixiu
+```
+
+然后打开 `/plugins`,选择 `dubbo-go-pixiu` 市场 → Install plugin。
+
+## Skills
+
+### pixiu-filter-author
+
+创建并调试 Pixiu HTTP/Network 过滤器:SPI 实现、`init()` 注册(`RegisterHttpFilter` / 
`RegisterNetworkFilterPlugin`)、`registry.go` blank import、Kind 对齐 `key.go`、挂载到 
HCM 或 filter-chain。
+
+触发词示例:
+
+- "给 Pixiu 写一个自定义 HTTP filter"
+- "我的 filter 编译过了但没运行"
+- "把这个 Envoy filter 迁移到 Pixiu"
+
+### pixiu-http-to-dubbo
+
+创建并调试 HTTP-to-Dubbo 路由:`api_config.yaml` / `conf.yaml` 
路由、注册中心/直连切换、`mappingParams`、`mapType`、`parameterTypes`、`opt.values` / 
`opt.types`、POJO 处理。
+
+触发词示例:
+
+- "把 /api/v1/users 路由到 Dubbo 的 UserService"
+- "consumer 报 no provider found 怎么排查"
+- "Dubbo 方法的参数该怎么映射"
+
+### pixiu-llm-gateway
+
+创建并校验 LLM 网关 `conf.yaml`,把 Pixiu 配成多提供方 HTTP 代理:proxy / tokenizer / kvcache 
过滤器、`llm_meta`、重试/兜底、vLLM/LMCache、Nacos LLM 服务发现。
+
+触发词示例:
+
+- "配一个用 vLLM 的 LLM 网关"
+- "给 LLM 网关加重试和兜底"
+- "用 Nacos 做 LLM 服务发现"
+
+### pixiu-mcp-gateway
+
+创建并校验 MCP 网关 `conf.yaml`,把后端 HTTP API 暴露成 MCP 工具:静态/Nacos 动态模式、MCP server 
过滤器、tools/resources/prompts、Mcp-Session-Id、OAuth/JWT 保护、Streamable HTTP/SSE。
+
+触发词示例:
+
+- "把我的后端 HTTP API 暴露成 MCP 工具"
+- "配一个带 OAuth 保护的 MCP 网关"
+- "用 Nacos 动态管理 MCP 工具"
+
+## 贡献
+
+Skill 文件位于 `.agents/skills/<name>/SKILL.md`。
+
+1. 直接修改或新增 skill。
+2. 保持 frontmatter 的 `description` 聚焦触发场景——Agent 就是靠这一行决定要不要使用该 skill。
+3. 只有当安装路径、skill 名称或支持的 Agent 发生变化时,才修改 `.agents/` 下的元数据。
+4. 按 dubbo-go-pixiu 正常贡献流程提交修改。
+
+## License
+
+Apache License 2.0
diff --git a/.agents/plugins/marketplace.json b/.agents/plugins/marketplace.json
new file mode 100644
index 000000000..b1cf5800d
--- /dev/null
+++ b/.agents/plugins/marketplace.json
@@ -0,0 +1,22 @@
+{
+  "name": "dubbo-go-pixiu",
+  "interface": {
+    "displayName": "dubbo-go-pixiu"
+  },
+  "plugins": [
+    {
+      "name": "dubbo-go-pixiu",
+      "source": {
+        "source": "git-subdir",
+        "url": "https://github.com/apache/dubbo-go-pixiu.git";,
+        "path": "./.agents",
+        "ref": "main"
+      },
+      "policy": {
+        "installation": "AVAILABLE",
+        "authentication": "ON_INSTALL"
+      },
+      "category": "Development"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/.agents/skills/pixiu-filter-author/SKILL.md 
b/.agents/skills/pixiu-filter-author/SKILL.md
new file mode 100644
index 000000000..96fa3da5b
--- /dev/null
+++ b/.agents/skills/pixiu-filter-author/SKILL.md
@@ -0,0 +1,71 @@
+---
+name: pixiu-filter-author
+description: Creates and debugs dubbo-go-pixiu HTTP/Network filters. Use when 
adding, registering, or wiring Pixiu filters, or when a filter compiles but 
does not run. Do not use for adapter or protocol-listener SPI work.
+---
+
+# pixiu-filter-author
+
+## Purpose
+Build Pixiu HTTP/Network filters that register and run.
+
+## When to use
+- Use when:
+  - Adding, fixing, or wiring Pixiu HTTP/Network filters.
+  - Porting Envoy/Kong/APISIX filters.
+  - Diagnosing filters that compile but do not run.
+
+- Do not use for:
+  - Registry adapter or protocol-listener SPI implementation.
+
+## Inputs
+
+<HARD-GATE>
+Do not generate YAML, write code, create files, or take any implementation 
action until the user has provided all required inputs. This is a first 
principle.
+
+If any required input is missing, this turn must only ask for the missing 
fields in the current input group; do not generate examples, defaults, YAML, 
code, or final output.
+
+Even if configuration information seems inferable, obvious, or implied by 
context, you must still ask the user to confirm it. Do not proceed until the 
user confirms it.
+</HARD-GATE>
+
+- Choose filter type (required):
+  - Required:
+    - `filter_type`: `http` or `network`
+- Common plugin information (required):
+  - Required:
+    - `Kind` constant value, also used as YAML `name`
+- HTTP filter (required when `filter_type: http`):
+  - Required:
+    - Which stages to implement: `Decode`, `Encode`, or both
+    - Processing logic for each stage, in natural language or pseudocode
+  - Optional:
+    - `Config` fields and validation logic
+- Network filter (required when `filter_type: network`):
+  - Required:
+    - Which `NetworkFilter` callbacks to implement, such as `OnData`, 
`OnTripleData`, or `ServeHTTP`
+    - Processing logic for each callback, in natural language or pseudocode
+  - Optional:
+    - `Config` fields and validation logic
+
+## Workflow
+1. Check required Inputs first:
+   1. Read existing code, config, and already provided user information first; 
do not ask again for information already present or stated.
+   2. Ask one `Inputs` group at a time. Each time, output only that group's 
required fields, with a short explanation after each field.
+   3. If the current group's required fields are incomplete, ask only for the 
missing fields and do not move to the next group.
+   4. After the current group's required fields are complete, ask whether to 
fill that group's optional fields; if yes, list those optional fields with 
short explanations.
+   5. After optional fields are skipped or completed, apply that group's 
defaults to complete implementation or mounting snippets; defaults must not 
override existing code, config, or user input.
+2. Read current source before writing code:
+   - `pkg/common/extension/filter/filter.go` for SPI interfaces and 
`pkg/pluginregistry/registry.go` for the current blank-import list.
+   - HTTP filter example: `pkg/filter/cors/cors.go`.
+   - Network filter example: `pkg/filter/network/dubboproxy/`.
+3. Choose package shape by `filter_type`: HTTP filters go under 
`pkg/filter/<name>/` or `pkg/filter/http/<name>/`; Network filters go under 
`pkg/filter/network/<name>/`.
+4. Implement the matching SPI: HTTP defines `Kind`, `Plugin`, `FilterFactory`, 
`Filter`, and `Config`; Network defines `Kind`, `Plugin`, `Filter`, and 
`Config`.
+5. Finish registration and mounting: in the filter package's `init()`, call 
the registration function — `filter.RegisterHttpFilter(&Plugin{})` for an HTTP 
filter, `filter.RegisterNetworkFilterPlugin(&Plugin{})` for a Network filter; 
add a blank import in `pkg/pluginregistry/registry.go`; then mount according to 
filter type under HCM or the listener filter-chain.
+
+## Output format
+- Show the relevant YAML fragment.
+
+## Validation
+- Verify the filter package's `init()` actually calls 
`filter.RegisterHttpFilter(&Plugin{})` (HTTP) or 
`filter.RegisterNetworkFilterPlugin(&Plugin{})` (Network).
+- Verify `pkg/pluginregistry/registry.go` blank-imports the new package.
+- Verify HTTP filters are nested under HCM `http_filters[]`, and Network 
filters are under listener `filter_chains.filters[]`.
+- Verify `PrepareFilterChain` deep-copies `factory.cfg` fields into each 
per-request Filter instance and does not share pointers.
\ No newline at end of file
diff --git a/.agents/skills/pixiu-http-to-dubbo/SKILL.md 
b/.agents/skills/pixiu-http-to-dubbo/SKILL.md
new file mode 100644
index 000000000..afe07f287
--- /dev/null
+++ b/.agents/skills/pixiu-http-to-dubbo/SKILL.md
@@ -0,0 +1,249 @@
+---
+name: pixiu-http-to-dubbo
+description: Creates and debugs dubbo-go-pixiu HTTP-to-Dubbo route YAML. Use 
for api_config.yaml/conf.yaml routes, direct Dubbo URLs, registry-backed Dubbo, 
mappingParams, mapType, parameterTypes, opt.types/opt.values, or generic-invoke 
errors. Do not use for non-Dubbo HTTP proxy routes or new registry adapter 
implementation.
+---
+
+# pixiu-http-to-dubbo
+
+## Purpose
+Generate a complete or embeddable `api_config.yaml`, and add the required 
companion `conf.yaml` fragments.
+
+## When to use
+- Use when:
+  - Creating or modifying HTTP-to-Dubbo routes, including registry/direct mode 
switching, parameter mapping, type conversion, generic-invoke config, or 
debugging errors such as `no provider found`, `ClassNotFound`, empty responses, 
and signature mismatches.
+
+- Do not use for:
+  - New registry adapter implementation or non-Dubbo HTTP proxy routes.
+
+## Inputs
+
+<HARD-GATE>
+Do not generate YAML, write code, create files, or take any implementation 
action until the user has provided all required inputs. This is a first 
principle.
+
+If any required input is missing, this turn must only ask for the missing 
fields in the current input group; do not generate examples, defaults, YAML, 
code, or final output.
+
+Even if configuration information seems inferable, obvious, or implied by 
context, you must still ask the user to confirm it. Do not proceed until the 
user confirms it.
+</HARD-GATE>
+
+- Choose Dubbo provider mode (required):
+  - Required:
+    - `provider_mode`: `registry` or `direct`
+- `listener` (required):
+  - Defaults:
+    - `address.socket_address.address: 0.0.0.0`
+    - `address.socket_address.port: 8888`
+- `route_config` (required):
+  - Defaults:
+    - `routes[].match.prefix: /api/v1`
+    - `routes[].route.cluster: dubbo-route`
+- `dgp.filter.http.apiconfig` (required):
+  - Defaults:
+    - `config.path: configs/api_config.yaml`
+    - `config.dynamic: false`
+- `dgp.filter.http.dubboproxy` (required):
+  - Defaults:
+    - `dubboProxyConfig.timeout_config.connect_timeout: 5s`
+    - `dubboProxyConfig.timeout_config.request_timeout: 5s`
+    - `dubboProxyConfig.load_balance: roundrobin`
+    - `dubboProxyConfig.retries: "3"`
+- `api_config.yaml` resource/method (required):
+  - Required:
+    - `resources[].path`
+    - `methods[].httpVerb`
+    - `integrationRequest.interface`
+    - `integrationRequest.method`
+  - Optional:
+    - `resources[].description`
+    - `integrationRequest.group`
+    - `integrationRequest.version`
+    - `integrationRequest.applicationName`
+    - `integrationRequest.clusterName`
+  - Defaults:
+    - `resources[].type: restful`
+    - `resources[].timeout: 1000ms`
+    - `methods[].enable: true`
+    - `methods[].timeout: 1000ms`
+    - `inboundRequest.requestType: http`
+    - `integrationRequest.requestType: dubbo`
+- Dubbo method parameters (required when the method has parameters):
+  - Required:
+    - `mappingParams[]` using exactly one argument style:
+      - positional mappings: `mappingParams[].mapTo: "0"`, `"1"`, ...
+      - `opt.values` mappings: map request fields to `opt.values`, and map or 
declare Java types separately when needed
+  - Conditionally required:
+    - `opt.types` when using `opt.values` and Java types cannot be inferred or 
must be explicit.
+    - `parameterTypes[]` for direct-mode positional mappings, or whenever Java 
types must override inferred types.
+    - When method parameters contain POJOs, nested objects, or collections, 
provide the corresponding Java class names and field types.
+- Registry provider (required when `provider_mode: registry`; defaults use 
Zookeeper, Nacos can also be chosen, examples below use Zookeeper):
+  - Required:
+    - `dubboProxyConfig.registries.zookeeper.address`
+  - Optional:
+    - `dubboProxyConfig.registries.zookeeper.group`
+    - `dubboProxyConfig.registries.zookeeper.namespace`
+    - `dubboProxyConfig.registries.zookeeper.username`
+    - `dubboProxyConfig.registries.zookeeper.password`
+  - Defaults:
+    - `dubboProxyConfig.registries.zookeeper.protocol: zookeeper`
+    - `dubboProxyConfig.registries.zookeeper.registry_type: interface`
+    - `dubboProxyConfig.registries.zookeeper.timeout: 3s`
+    - `dubboProxyConfig.registries.zookeeper.group: DEFAULT_GROUP`
+- Direct provider (required when `provider_mode: direct`):
+  - Required:
+    - `integrationRequest.url`
+  - Conditionally required:
+    - `integrationRequest.parameterTypes` (use `[]` for no-argument methods; 
required when `opt.types` is not used)
+  - Optional:
+    - `integrationRequest.protocol` (needed when `url` is `host:port`; when 
`url` has a scheme, it must match that scheme)
+  - Defaults:
+    - `integrationRequest.protocol: dubbo`
+    - `integrationRequest.serialization: hessian2`
+
+## Workflow
+1. Check required Inputs first:
+   1. Read existing config and already provided user information first; do not 
ask again for information already present or stated.
+   2. Ask one `Inputs` group at a time. Each time, output only that group's 
required fields, with a short explanation after each field.
+   3. If the current group's required fields are incomplete, ask only for the 
missing fields and do not move to the next group.
+   4. After the current group's required fields are complete, ask whether to 
fill that group's optional fields; if yes, list those optional fields with 
short explanations.
+   5. After optional fields are skipped or completed, apply that group's 
defaults and output default-value information; defaults must not override 
existing config or user input.
+2. Read current source before editing YAML:
+   - `pkg/config/api_config.go`.
+   - `pkg/filter/http/remote/dubbo_handler.go`.
+   - `pkg/client/dubbo/types.go`, `pkg/client/dubbo/typeconv.go`, and 
`pkg/client/dubbo/dubbo.go`.
+3. Choose registry or direct path by `provider_mode`:
+   - Registry uses the registry config in `dgp.filter.http.dubboproxy`.
+   - Direct uses `integrationRequest.url`.
+4. Generate `api_config.yaml`: write `resources[].methods[]` for each HTTP 
API, and use either positional `mappingParams` or `opt.values`/`opt.types` to 
organize Dubbo arguments.
+5. Complete `conf.yaml`: use HCM for route and filters, and ensure 
`dgp.filter.http.apiconfig` is before the Dubbo proxy.
+
+## Output format
+- Show the relevant YAML fragments.
+
+## Validation
+- When using positional mappings, verify `mappingParams[].mapTo` indexes match 
the declared Java type order exactly.
+- Verify positional mappings and `opt.values` are not mixed in the same method.
+- Verify `dgp.filter.http.apiconfig` is ordered before 
`dgp.filter.http.dubboproxy`.
+- Verify `mapType` is supported by `client/dubbo.MapTypes` after normalization 
against `constant.JTypeMapper`: lowercase primitives and supported 
fully-qualified Java type aliases such as 
`java.lang.String`/`java.lang.Integer` are valid; short uppercase aliases such 
as `String`/`Boolean` are not.
+- Verify POJO arguments have a `class` field in the corresponding JSON body, 
such as `{"class":"com.example.User", ...}`.
+
+## Examples
+Direct mode (`api_config.yaml`):
+
+```yaml
+name: pixiu
+description: HTTP facade for Dubbo user service
+resources:
+  - path: /users/:name
+    type: restful
+    timeout: 5s
+    description: User APIs
+    methods:
+      - httpVerb: GET
+        enable: true
+        timeout: 5s
+        inboundRequest:
+          requestType: http
+        integrationRequest:
+          requestType: dubbo
+          url: dubbo://127.0.0.1:20880
+          protocol: dubbo
+          serialization: hessian2
+          interface: com.example.UserService
+          method: getUser
+          group: ""
+          version: "1.0.0"
+          parameterTypes:
+            - java.lang.String
+          mappingParams:
+            - name: uri.name
+              mapTo: "0"
+              mapType: string
+```
+
+Direct mode (`conf.yaml`):
+
+```yaml
+http_filters:
+  - name: dgp.filter.http.apiconfig
+    config:
+      path: configs/api_config.yaml
+      dynamic: false
+  - name: dgp.filter.http.dubboproxy
+    config:
+      dubboProxyConfig:
+        timeout_config:
+          connect_timeout: 5s
+          request_timeout: 5s
+        load_balance: roundrobin
+        retries: "3"
+```
+
+Registry mode (`api_config.yaml`):
+
+```yaml
+integrationRequest:
+  requestType: dubbo
+  interface: com.example.UserService
+  method: getUser
+  group: ""
+  version: "1.0.0"
+  parameterTypes:
+    - java.lang.String
+  mappingParams:
+    - name: uri.name
+      mapTo: "0"
+      mapType: string
+```
+
+Registry mode (`conf.yaml`):
+
+```yaml
+http_filters:
+  - name: dgp.filter.http.apiconfig
+    config:
+      path: configs/api_config.yaml
+      dynamic: false
+  - name: dgp.filter.http.dubboproxy
+    config:
+      dubboProxyConfig:
+        registries:
+          zookeeper:
+            protocol: zookeeper
+            address: 127.0.0.1:2181
+            timeout: 3s
+            group: DEFAULT_GROUP
+            registry_type: interface
+        timeout_config:
+          connect_timeout: 5s
+          request_timeout: 5s
+        load_balance: roundrobin
+        retries: "3"
+```
+
+Minimal positional parameter mapping:
+
+```yaml
+integrationRequest:
+  requestType: dubbo
+  interface: com.example.UserService
+  method: getUser
+  parameterTypes:
+    - java.lang.String
+  mappingParams:
+    - name: uri.name
+      mapTo: "0"
+      mapType: string
+```
+
+Minimal `opt.values` / `opt.types` mapping:
+
+```yaml
+integrationRequest:
+  requestType: dubbo
+  interface: com.example.UserService
+  method: getUser
+  mappingParams:
+    - name: requestBody.values
+      mapTo: opt.values
+    - name: requestBody.types
+      mapTo: opt.types
+```
diff --git a/.agents/skills/pixiu-llm-gateway/SKILL.md 
b/.agents/skills/pixiu-llm-gateway/SKILL.md
new file mode 100644
index 000000000..b2a0c06f2
--- /dev/null
+++ b/.agents/skills/pixiu-llm-gateway/SKILL.md
@@ -0,0 +1,265 @@
+---
+name: pixiu-llm-gateway
+description: Creates and validates dubbo-go-pixiu LLM gateway conf.yaml. Use 
for LLM proxy/tokenizer/kvcache filters, llm_meta, vLLM, LMCache, 
retry/fallback, or Nacos LLM discovery. Do not use for MCP gateway config.
+---
+
+# pixiu-llm-gateway
+
+## Purpose
+Generate a complete or embeddable LLM gateway `conf.yaml` that configures 
Pixiu as a multi-provider HTTP proxy.
+
+## When to use
+- Use when:
+  - Generating or fixing Pixiu LLM gateway `conf.yaml`, including LLM 
proxy/tokenizer/kvcache, `llm_meta`, retry/fallback, vLLM/LMCache, or Nacos LLM 
discovery.
+
+- Do not use for:
+  - MCP gateway, HTTP-to-Dubbo routes, or implementing new LLM-related filters.
+
+## Inputs
+
+<HARD-GATE>
+Do not generate YAML, write code, create files, or take any implementation 
action until the user has provided all required inputs. This is a first 
principle.
+
+If any required input is missing, this turn must only ask for the missing 
fields in the current input group; do not generate examples, defaults, YAML, 
code, or final output.
+
+Even if configuration information seems inferable, obvious, or implied by 
context, you must still ask the user to confirm it. Do not proceed until the 
user confirms it.
+</HARD-GATE>
+
+- Choose upstream mode (required):
+  - Required:
+    - `upstream_mode`: `static` or `registry`
+
+- `listener` (required):
+  - Defaults:
+    - `address.socket_address.address: 0.0.0.0`
+    - `address.socket_address.port: 8888`
+
+- `route_config` (required):
+  - Defaults:
+    - `routes[].match.prefix: /v1`
+    - `routes[].route.cluster: llm`
+
+- `dgp.filter.llm.proxy` (required):
+  - Defaults:
+    - `config.scheme: http` (use `https` when the upstream is an HTTPS 
endpoint)
+    - `config.timeout: 60s`
+    - `config.maxIdleConns: 100`
+    - `config.maxIdleConnsPerHost: 100`
+    - `config.maxConnsPerHost: 100`
+
+- Static upstream (required when `upstream_mode: static`):
+  - Required:
+    - `endpoints[].ID`
+    - `endpoints[].socket_address.address` or 
`endpoints[].socket_address.domains`
+    - `endpoints[].socket_address.port`
+  - Optional:
+    - `endpoints[].llm_meta.provider`
+    - `endpoints[].llm_meta.api_key`
+    - `endpoints[].llm_meta.retry_policy.config`
+  - Defaults:
+    - `clusters[].name: llm`
+    - `clusters[].lb_policy: RoundRobin`
+    - `endpoints[].llm_meta.retry_policy.name: NoRetry`
+    - `endpoints[].llm_meta.fallback: false`
+    - `endpoints[].llm_meta.health_check_interval: 5000`
+
+- Registry upstream (required when `upstream_mode: registry`):
+  - Required:
+    - `registries.nacos.address`
+  - Optional:
+    - `registries.nacos.group`
+    - `registries.nacos.namespace`
+    - `registries.nacos.username`
+    - `registries.nacos.password`
+  - Defaults:
+    - `adapters[].id: llm-registry`
+    - `adapters[].name: dgp.adapter.llmregistrycenter`
+    - `registries.nacos.protocol: nacos`
+    - `registries.nacos.timeout: 5s`
+    - `registries.nacos.group: DEFAULT_GROUP`
+
+- `dgp.filter.llm.tokenizer` (optional):
+  - Defaults:
+    - `config.log_to_console: false`
+
+- `dgp.filter.ai.kvcache` (optional):
+  - Required:
+    - `config.enabled: true` (must be set explicitly when enabling kvcache)
+    - `config.vllm_endpoint`
+    - `config.lmcache_endpoint`
+  - Optional:
+    - `config.default_model`
+    - `config.token_cache`
+    - `config.cache_strategy`
+  - Defaults:
+    - `config.request_timeout: 2s`
+    - `config.lookup_routing_timeout: 50ms`
+    - `config.hot_window: 5m`
+    - `config.hot_max_records: 300`
+    - `config.max_idle_conns: 100`
+    - `config.max_idle_conns_per_host: 100`
+    - `config.max_conns_per_host: 100`
+    - `config.retry.max_attempts: 3`
+    - `config.retry.base_backoff: 100ms`
+    - `config.retry.max_backoff: 2s`
+    - `config.circuit_breaker.failure_threshold: 5`
+    - `config.circuit_breaker.recovery_timeout: 10s`
+    - `config.circuit_breaker.half_open_max_calls: 2`
+
+## Workflow
+1. Check required Inputs first:
+   1. Read existing config and already provided user information first; do not 
ask again for information already present or stated.
+   2. Ask one `Inputs` group at a time. Each time, output only that group's 
required fields, with a short explanation after each field.
+   3. If the current group's required fields are incomplete, ask only for the 
missing fields and do not move to the next group.
+   4. After the current group's required fields are complete, ask whether to 
fill that group's optional fields; if yes, list those optional fields with 
short explanations.
+   5. After optional fields are skipped or completed, apply that group's 
defaults and output default-value information; defaults must not override 
existing config or user input.
+2. Read current source before generating YAML:
+   - `pkg/common/constant/key.go`.
+   - `pkg/filter/llm/proxy/filter.go`.
+   - `pkg/filter/llm/tokenizer/tokenizer.go`.
+   - `pkg/filter/ai/kvcache/config.go` and `pkg/filter/ai/kvcache/handlers.go`.
+   - `pkg/model/llm.go`, `pkg/model/cluster.go`, and `pkg/model/base.go`.
+3. Choose static or registry path by `upstream_mode`: static uses 
`static_resources.clusters[]`; registry uses the LLM registry adapter.
+4. Generate listener, route, and filters: use HCM to carry the LLM route and 
HTTP filters; add `dgp.filter.ai.kvcache`, tokenizer, and 
`dgp.filter.llm.proxy` as needed.
+5. Generate LLM upstream: static endpoints go under `socket_address` and 
`llm_meta`; ensure the LLM cluster does not mix in ordinary HTTP endpoints.
+
+## Output format
+- Show the relevant YAML fragments.
+
+## Validation
+- Verify LLM filter-chain order: `dgp.filter.ai.kvcache` -> 
`dgp.filter.llm.tokenizer` -> `dgp.filter.llm.proxy`; ignore missing filters 
within this order chain.
+- Verify `scheme` is under `dgp.filter.llm.proxy.config`, not under an 
endpoint; `socket_address.domains` contains host names only, such as 
`api.openai.com`, not full URLs or paths.
+- When KV cache is enabled, verify the LMCache-side `instance_id` exactly 
matches the Pixiu endpoint `ID`.
+
+## Examples
+Complete LLM route example (`conf.yaml`):
+
+```yaml
+static_resources:
+  listeners:
+    - name: net/http
+      protocol_type: HTTP
+      address:
+        socket_address:
+          address: 0.0.0.0
+          port: 8888
+      filter_chains:
+        filters:
+          - name: dgp.filter.httpconnectionmanager
+            config:
+              route_config:
+                routes:
+                  - match:
+                      prefix: /v1
+                    route:
+                      cluster: llm
+              http_filters:
+                - name: dgp.filter.ai.kvcache
+                  config:
+                    enabled: true
+                    vllm_endpoint: "http://127.0.0.1:8000";
+                    lmcache_endpoint: "http://127.0.0.1:9000";
+                    default_model: "Qwen2.5-3B-Instruct"
+                    request_timeout: "2s"
+                    lookup_routing_timeout: "50ms"
+                    hot_window: "5m"
+                    hot_max_records: 300
+                    hot_max_keys: 1000
+                    max_idle_conns: 100
+                    max_idle_conns_per_host: 100
+                    max_conns_per_host: 100
+                    token_cache:
+                      enabled: true
+                      max_size: 1024
+                      ttl: "10m"
+                    cache_strategy:
+                      enable_compression: true
+                      enable_pinning: true
+                      enable_eviction: true
+                      memory_threshold: 0.85
+                      hot_content_threshold: 10
+                      load_threshold: 0.7
+                      pin_instance_id: "vllm-instance-1"
+                      pin_location: "LocalCPUBackend"
+                      compress_instance_id: "vllm-instance-1"
+                      compress_location: "LocalCPUBackend"
+                      compress_method: "zstd"
+                      evict_instance_id: "vllm-instance-1"
+                    circuit_breaker:
+                      failure_threshold: 5
+                      recovery_timeout: "10s"
+                      half_open_max_calls: 2
+                    retry:
+                      max_attempts: 3
+                      base_backoff: "100ms"
+                      max_backoff: "2s"
+                - name: dgp.filter.llm.tokenizer
+                  config:
+                    log_to_console: false
+                - name: dgp.filter.llm.proxy
+                  config:
+                    scheme: http
+                    timeout: "60s"
+                    maxIdleConns: 100
+                    maxIdleConnsPerHost: 100
+                    maxConnsPerHost: 100
+  clusters:
+    - name: llm
+      lb_policy: RoundRobin
+      endpoints:
+        - ID: vllm-instance-1
+          socket_address:
+            address: 127.0.0.1
+            port: 8000
+          llm_meta:
+            provider: vllm
+            api_key: "<api-key>"
+            fallback: false
+            health_check_interval: 5000
+            retry_policy:
+              name: ExponentialBackoff
+              config:
+                times: 3
+                initialInterval: "200ms"
+                maxInterval: "5s"
+                multiplier: 2.0
+```
+
+Nacos LLM registry mode example (`conf.yaml`):
+
+```yaml
+static_resources:
+  listeners:
+    - name: net/http
+      protocol_type: HTTP
+      address:
+        socket_address:
+          address: 0.0.0.0
+          port: 8888
+      filter_chains:
+        filters:
+          - name: dgp.filter.httpconnectionmanager
+            config:
+              route_config:
+                routes:
+                  - match:
+                      prefix: /v1
+                    route:
+                      cluster: llm
+              http_filters:
+                - name: dgp.filter.llm.proxy
+                  config:
+                    scheme: http
+                    timeout: "60s"
+  adapters:
+    - id: llm-nacos
+      name: dgp.adapter.llmregistrycenter
+      config:
+        registries:
+          nacos:
+            protocol: nacos
+            address: "127.0.0.1:8848"
+            timeout: "5s"
+            group: DEFAULT_GROUP
+            namespace: public
+```
diff --git a/.agents/skills/pixiu-mcp-gateway/SKILL.md 
b/.agents/skills/pixiu-mcp-gateway/SKILL.md
new file mode 100644
index 000000000..4bf8eb5f4
--- /dev/null
+++ b/.agents/skills/pixiu-mcp-gateway/SKILL.md
@@ -0,0 +1,314 @@
+---
+name: pixiu-mcp-gateway
+description: Creates and validates dubbo-go-pixiu MCP gateway conf.yaml. Use 
for MCP server filters, tools/list, tools/call, Mcp-Session-Id, MCP auth, Nacos 
MCP registry, or exposing backend HTTP APIs as MCP tools. Do not use for LLM 
model proxying.
+---
+
+# pixiu-mcp-gateway
+
+## Purpose
+Generate a complete or embeddable MCP gateway `conf.yaml` that exposes backend 
HTTP APIs as MCP tools.
+
+## When to use
+- Use when:
+  - Exposing backend HTTP APIs as MCP tools through the Pixiu MCP gateway, in 
static or Nacos dynamic mode, or configuring resources/templates/prompts, 
OAuth/JWT protection, or Streamable HTTP/SSE.
+
+- Do not use for:
+  - LLM model proxying or implementing a new MCP-related filter.
+
+## Inputs
+
+<HARD-GATE>
+Do not generate YAML, write code, create files, or take any implementation 
action until the user has provided all required inputs. This is a first 
principle.
+
+If any required input is missing, this turn must only ask for the missing 
fields in the current input group; do not generate examples, defaults, YAML, 
code, or final output.
+
+Even if configuration information seems inferable, obvious, or implied by 
context, you must still ask the user to confirm it. Do not proceed until the 
user confirms it.
+</HARD-GATE>
+
+- Choose tool source (required):
+  - Required:
+    - `tool_mode`: `static` or `registry`
+
+- `listener` (required):
+  - Defaults:
+    - `address.socket_address.address: 0.0.0.0`
+    - `address.socket_address.port: 8888`
+
+- `route_config` (required):
+  - Defaults:
+    - `routes[].match.prefix: /mcp`
+    - `routes[].route.cluster: mcp-route` (route cluster name)
+
+- `dgp.filter.mcp.mcpserver` (required):
+  - Defaults:
+    - `config.endpoint: /mcp`
+    - `config.server_info.name: Pixiu MCP Server`
+    - `config.server_info.version: 1.0.0`
+    - `config.server_info.description: MCP Server powered by Apache 
Dubbo-go-pixiu`
+    - `config.server_info.instructions: Use the provided tools to interact 
with backend services.`
+
+- Static tools (required when `tool_mode: static`):
+  - Required:
+    - `tools[].name`
+    - `tools[].request.path`
+    - Endpoint under `static_resources.clusters[]` for each backend cluster 
referenced by a tool:
+      - `clusters[].endpoints[].socket_address.address`
+      - `clusters[].endpoints[].socket_address.port`
+  - Optional:
+    - `tools[].description`
+    - `tools[].args[]`
+  - Defaults (`tools[].cluster` and `clusters[].name` reference the same name; 
changing one requires changing the other):
+    - `tools[].cluster: mcp-backend`
+    - `clusters[].name: mcp-backend`
+    - `tools[].request.method: GET`
+    - `tools[].request.timeout: 30s`
+    - `tools[].args[].type: string`
+
+- Registry tools (required when `tool_mode: registry`):
+  - Required:
+    - `registries.nacos.address`
+  - Optional:
+    - `registries.nacos.group`
+    - `registries.nacos.namespace`
+    - `registries.nacos.username`
+    - `registries.nacos.password`
+  - Defaults:
+    - `adapters[].id: mcp-nacos`
+    - `adapters[].name: dgp.adapter.mcpserver`
+    - `registries.nacos.protocol: nacos`
+    - `registries.nacos.timeout: 5s`
+    - `registries.nacos.group: DEFAULT_GROUP`
+
+- `resources[]` (optional):
+  - Required:
+    - `resources[].name`
+    - `resources[].uri`
+    - `resources[].source.type`
+  - Conditionally required by `resources[].source.type`:
+    - `resources[].source.content` for `inline`
+    - `resources[].source.path` for `file`
+    - `resources[].source.url` for `url`
+    - `resources[].source.template` for `template`
+  - Optional:
+    - `resources[].description`
+    - `resources[].mime_type`
+
+- `resource_templates[]` (optional):
+  - Required:
+    - `resource_templates[].name`
+    - `resource_templates[].uri_template`
+  - Optional:
+    - `resource_templates[].title`
+    - `resource_templates[].description`
+    - `resource_templates[].mime_type`
+    - `resource_templates[].parameters[]`
+    - `resource_templates[].annotations`
+
+- `prompts[]` (optional):
+  - Required:
+    - `prompts[].name`
+    - `prompts[].messages[].role`
+    - `prompts[].messages[].content`
+  - Optional:
+    - `prompts[].title`
+    - `prompts[].description`
+    - `prompts[].arguments[]`
+
+- `dgp.filter.http.auth.mcp` (optional):
+  - Required:
+    - `resource_metadata.resource`
+    - `resource_metadata.authorization_servers[]`
+    - `providers[].name`
+    - `providers[].issuer`
+    - `providers[].jwks`
+  - Defaults:
+    - `resource_metadata.path: /.well-known/oauth-protected-resource`
+    - `providers[].audience`: defaults to `resource_metadata.resource`
+    - `rules[].cluster`: defaults to `route_config.routes[].route.cluster`
+
+## Workflow
+1. Check required Inputs first:
+   1. Read existing config and already provided user information first; do not 
ask again for information already present or stated.
+   2. Ask one `Inputs` group at a time. Each time, output only that group's 
required fields, with a short explanation after each field.
+   3. If the current group's required fields are incomplete, ask only for the 
missing fields and do not move to the next group.
+   4. After the current group's required fields are complete, ask whether to 
fill that group's optional fields; if yes, list those optional fields with 
short explanations.
+   5. After optional fields are skipped or completed, apply that group's 
defaults and output default-value information; defaults must not override 
existing config or user input.
+2. When field shape or behavior is uncertain, read current source before 
generating YAML:
+   - `pkg/common/constant/key.go`.
+   - `pkg/model/mcpserver.go`.
+   - `pkg/filter/mcp/mcpserver/plugin.go`, `filter.go`, `handlers.go`, and 
`transport/`.
+   - Read `pkg/filter/auth/mcp/config.go` and `filter.go` when auth is 
required.
+   - Read `pkg/adapter/mcpserver/registrycenter.go` and 
`pkg/adapter/mcpserver/registry/nacos/` when Nacos is required.
+3. Choose static or registry path by `tool_mode`: static writes tools into the 
MCP filter; registry uses the MCP server adapter.
+4. Generate listener, route, and filters: route the MCP endpoint to the route 
cluster, and put the auth filter before the MCP server when needed.
+5. Generate tool backend: write static tool backend clusters under 
`static_resources.clusters[]`; map args with `path`, `query`, or `body`.
+
+## Output format
+- Show the relevant YAML fragments.
+
+## Validation
+- Verify `dgp.filter.http.auth.mcp` `rules[].cluster` matches the MCP route 
cluster, such as `mcp-route`, not a tool backend cluster.
+- Verify MCP filter-chain order: `dgp.filter.http.auth.mcp` -> 
`dgp.filter.mcp.mcpserver` -> `dgp.filter.http.httpproxy`; ignore missing 
filters within this order chain.
+- Verify every static tool `cluster` has a same-name cluster declaration under 
`static_resources.clusters[]`.
+- Verify `dgp.filter.mcp.mcpserver.config.endpoint` exactly matches the path 
in the client call URL.
+- When `resources[]` is configured, verify the user has been told about the 
current `resources/read` runtime limitation: it returns placeholder content and 
does not read real data from `source`; do not claim clients can read actual 
content from `source.content/path/url/template`.
+
+## Examples
+Static mode (`conf.yaml`):
+
+```yaml
+static_resources:
+  listeners:
+    - name: net/http
+      protocol_type: HTTP
+      address:
+        socket_address:
+          address: 0.0.0.0
+          port: 8888
+      filter_chains:
+        filters:
+          - name: dgp.filter.httpconnectionmanager
+            config:
+              route_config:
+                routes:
+                  - match:
+                      prefix: /mcp
+                    route:
+                      cluster: mcp-route
+              http_filters:
+                - name: dgp.filter.http.auth.mcp
+                  config:
+                    resource_metadata:
+                      path: /.well-known/oauth-protected-resource
+                      resource: http://localhost:8888/mcp
+                      authorization_servers:
+                        - http://localhost:9000
+                    providers:
+                      - name: local
+                        issuer: http://localhost:9000
+                        jwks: http://localhost:9000/.well-known/jwks.json
+                        audience: http://localhost:8888/mcp
+                    rules:
+                      - cluster: mcp-route
+                - name: dgp.filter.mcp.mcpserver
+                  config:
+                    endpoint: /mcp
+                    server_info:
+                      name: demo-mcp
+                      version: "1.0.0"
+                      description: Demo MCP server for user APIs
+                      instructions: Use the exposed tools to query and create 
users.
+                    tools:
+                      - name: search_users
+                        description: Search users by status
+                        cluster: users
+                        request:
+                          method: GET
+                          path: /users
+                          timeout: 5s
+                        args:
+                          - name: status
+                            type: string
+                            in: query
+                            description: User status filter
+                            required: false
+                            default: active
+                            enum:
+                              - active
+                              - disabled
+                    resources:
+                      - name: service-status
+                        uri: pixiu://service/status
+                        description: Current service status
+                        mime_type: application/json
+                        source:
+                          type: inline
+                          content: '{"status":"ok"}'
+                    resource_templates:
+                      - name: user-profile
+                        uri_template: pixiu://users/{id}
+                        title: User profile
+                        description: User profile by ID
+                        mime_type: application/json
+                        parameters:
+                          - name: id
+                            type: string
+                            description: User ID
+                            required: true
+                        annotations:
+                          audience:
+                            - assistant
+                          priority: 0.7
+                    prompts:
+                      - name: summarize_user
+                        title: Summarize user
+                        description: Summarize a user profile
+                        arguments:
+                          - name: id
+                            description: User ID
+                            required: true
+                        messages:
+                          - role: user
+                            content: "Summarize user {{id}}."
+                - name: dgp.filter.http.httpproxy
+  clusters:
+    - name: mcp-route
+      endpoints:
+        - socket_address:
+            address: 127.0.0.1
+            port: 8080
+    - name: users
+      endpoints:
+        - socket_address:
+            address: 127.0.0.1
+            port: 8080
+```
+
+Registry mode example (`conf.yaml`):
+
+```yaml
+static_resources:
+  listeners:
+    - name: net/http
+      protocol_type: HTTP
+      address:
+        socket_address:
+          address: 0.0.0.0
+          port: 8888
+      filter_chains:
+        filters:
+          - name: dgp.filter.httpconnectionmanager
+            config:
+              route_config:
+                routes:
+                  - match:
+                      prefix: /mcp
+                    route:
+                      cluster: mcp-route
+              http_filters:
+                - name: dgp.filter.mcp.mcpserver
+                  config:
+                    endpoint: /mcp
+                    server_info:
+                      name: demo-mcp
+                      version: "1.0.0"
+                      description: Demo MCP server with Nacos-managed tools
+                      instructions: Tool definitions are loaded from Nacos.
+                - name: dgp.filter.http.httpproxy
+  clusters:
+    - name: mcp-route
+      endpoints:
+        - socket_address:
+            address: 127.0.0.1
+            port: 8080
+  adapters:
+    - id: mcp-nacos
+      name: dgp.adapter.mcpserver
+      config:
+        registries:
+          nacos:
+            protocol: nacos
+            address: "127.0.0.1:8848"
+            timeout: "5s"
+            group: DEFAULT_GROUP
+```
diff --git a/skills/pixiu-filter-author/SKILL.md 
b/skills/pixiu-filter-author/SKILL.md
deleted file mode 100644
index 832201041..000000000
--- a/skills/pixiu-filter-author/SKILL.md
+++ /dev/null
@@ -1,359 +0,0 @@
----
-name: pixiu-filter-author
-description: |
-  Create a new HTTP or Network filter for Apache dubbo-go-pixiu. Use whenever
-  the user wants to add a custom filter, extend gateway per-request behavior,
-  implement a new auth/logging/transformation/proxy filter, or mentions
-  "pixiu filter", "dgp.filter", "http_filters", "filter chain", "custom 
filter",
-  "extend pixiu", or is porting a filter from Envoy/Kong/APISIX to pixiu.
-  Strongly prefer this skill over ad-hoc generation even when the user does
-  not say the word "skill" — getting the SPI registration right is the single
-  biggest source of "my filter does not run" bug reports.
-allowed-tools: [Read, Grep, Glob, Edit, Write, Bash]
-metadata:
-  version: "0.1.2"
-  domain: extension
-  scope: implementation
-  triggers: ["filter", "pixiu filter", "dgp.filter", "http_filters", "filter 
chain", "custom filter", "extend pixiu"]
-  pixiu_min_version: "0.6.0"
-  role: specialist
----
-
-# pixiu-filter-author — Authoring HTTP / Network Filters
-
-dubbo-go-pixiu's extension surface is Envoy-style: every filter is a Go
-package that registers a `Plugin` in `init()`, and a central file
-(`pkg/pluginregistry/registry.go`) blank-imports all such packages to
-activate them. A single missing blank import is the most common reason a
-newly written filter "does nothing" — so this skill treats registration as
-a first-class concern, not an afterthought.
-
-## When to Use
-
-Use this skill when the user wants to:
-- Add a new HTTP filter (auth, logging, header rewriting, rate limiting,
-  request transformation, metric emission, etc.).
-- Add a new Network filter (e.g. a custom connection manager).
-- Port a filter from Envoy / Kong / APISIX onto pixiu.
-- Fix an existing filter that "isn't running" — start at Step 5 (blank
-  import) and Step 3 (phase).
-
-**Do NOT use this skill for:**
-- Editing the yaml that *uses* an existing filter → that is plain config
-  work. Only include a minimal mounting snippet when you create a new
-  filter in this skill.
-- Mounting an already-registered filter such as CORS, JWT, OPA, MCP,
-  LLM proxy, or Dubbo proxy. In that case do not create new filter code;
-  do not touch `pkg/pluginregistry/registry.go`; answer with the
-  smallest `http_filters` snippet and state that the filter already
-  exists.
-  If pressured to add a package anyway, explicitly answer:
-  "this is already-registered; do not create new filter code; do not
-  touch `pkg/pluginregistry/registry.go`."
-- Adding a registry adapter (Nacos, ZK, Consul), a new protocol
-  listener (WebSocket, MQTT), or a custom load-balancing algorithm —
-  these are different SPI hubs and out of scope for this skill. Point
-  the user to the relevant interface file
-  (`pkg/common/extension/adapter/adapter.go`,
-  `pkg/listener/listener.go`, or
-  `pkg/cluster/loadbalancer/`) and let them work directly.
-
-## Prerequisites
-
-- pixiu ≥ 0.6.0. Verify with `grep dubbo-go-pixiu go.mod` in Step 0.
-- The user should be inside a clone of `github.com/apache/dubbo-go-pixiu`
-  (or a fork). If they are not, stop and ask — this skill edits repo files.
-
-## Steps
-
-### Step 0 — Verify Context (ALWAYS FIRST, no exceptions)
-
-Before writing a single line of code, read the current shape of three
-files. pixiu's SPI is stable but not frozen, and your instinct about
-these interfaces can be one minor version stale:
-
-1. `pkg/common/extension/filter/filter.go` — the four interfaces
-   (`HttpFilterPlugin`, `HttpFilterFactory`, `HttpDecodeFilter`,
-   `HttpEncodeFilter`), plus `NetworkFilterPlugin` / `NetworkFilter`.
-   Read signatures, especially `PrepareFilterChain`.
-2. `pkg/pluginregistry/registry.go` — the blank-import list you will
-   extend in Step 5. Note the alphabetical order within groups.
-3. `pkg/filter/cors/cors.go` — the shortest idiomatic HTTP filter in the
-   tree. A single file, all four types (`Plugin`, `FilterFactory`,
-   `Filter`, `Config`) declared together. Note: `cors` ships **without**
-   a `_test.go` — that matches roughly half of the existing filter
-   packages. See Step 7 for the project's actual convention.
-
-Then `ls pkg/filter/` and `ls pkg/filter/http/` to see the existing
-directory conventions. Do not assume — layouts evolve (e.g. `cors` lives
-at `pkg/filter/cors/`, while proxy filters live at
-`pkg/filter/http/httpproxy/`, `pkg/filter/http/dubboproxy/`).
-
-If an interface detail is unclear, stay in the source file instead of
-relying on memory.
-
-### Step 1 — Clarify the Filter Shape (STOP and ask)
-
-Do not write code until the user has answered, in plain words:
-
-1. **Phase**: Decode (request, before upstream), Encode (response, after
-   upstream), or both?
-2. **Kind**: the string that identifies the filter in yaml. It MUST start
-   with `dgp.filter.http.` for HTTP filters or
-   match Pixiu's current Network filter constants, usually
-   `dgp.filter.network.`. The built-in HTTP connection manager is the
-   special network-filter Kind `dgp.filter.httpconnectionmanager`.
-   Suggest a name after checking `pkg/common/constant/key.go`; confirm
-   the user is happy.
-3. **Config fields**: what yaml keys does the user want? (`allow_origin`,
-   `max_request_bytes`, etc.)
-4. **Where to put the package**: the convention is
-   `pkg/filter/<name>/` for ordinary filters and
-   `pkg/filter/http/<name>/` for *proxy-style* filters (the ones that
-   actually call upstream). If unsure, ask — getting this right once
-   beats moving files later.
-
-If the user says "just write something reasonable", pick a minimal
-request-logging filter as the placeholder and be explicit about the
-assumptions in a short summary before coding.
-
-### Step 2 — Create the Package Skeleton
-
-Create the directory and initial files. Two shapes are idiomatic in the
-existing tree:
-
-- **Single file** (cors, csrf, jwt, header, host, tracing): everything
-  lives in `<name>.go`. This is the dominant pattern for non-proxy
-  filters — about 20 of the existing filter packages follow it.
-- **Split files** (network/dubboproxy, mcp/mcpserver, ai/kvcache, etc.):
-  `plugin.go`, `filter.go`, `config.go`. Use this only when the package
-  has more than ~200 LOC or several distinct types worth separating.
-
-Test files (`*_test.go`) are **not** part of either default shape —
-they are added on a per-filter basis when the logic warrants it. See
-Step 7.
-
-Create the initial files directly, using the closest in-tree filter as
-the pattern. Keep the first version minimal: the four interface types,
-`Kind`, `init()` registration, `Config`, and empty `Decode` / `Encode`
-methods as appropriate. The user still owns every Config field.
-
-### Step 3 — Implement the Four Interfaces
-
-The four types for an HTTP filter, in order:
-
-```go
-type Plugin struct{}
-func (p *Plugin) Kind() string { return Kind }
-func (p *Plugin) CreateFilterFactory() (filter.HttpFilterFactory, error) {
-    return &FilterFactory{cfg: &Config{}}, nil
-}
-
-type FilterFactory struct{ cfg *Config }
-func (f *FilterFactory) Config() any { return f.cfg }
-func (f *FilterFactory) Apply() error { /* validate / defaults */ return nil }
-func (f *FilterFactory) PrepareFilterChain(ctx *http.HttpContext, chain 
filter.FilterChain) error {
-    inst := &Filter{cfg: f.cfg.DeepCopy()} // or a shallow copy of the pieces 
you need
-    chain.AppendDecodeFilters(inst)        // or AppendEncodeFilters, or both
-    return nil
-}
-
-type Filter struct{ cfg *Config }
-func (f *Filter) Decode(ctx *http.HttpContext) filter.FilterStatus { return 
filter.Continue }
-// and/or:
-func (f *Filter) Encode(ctx *http.HttpContext) filter.FilterStatus { return 
filter.Continue }
-```
-
-A few subtle rules the interface alone does not enforce:
-
-- **Do not reuse `factory.cfg` directly in the Filter instance.** The
-  factory's config pointer can be hot-reloaded at runtime. Copy the
-  fields you need into the Filter when `PrepareFilterChain` runs. The
-  CORS filter's `factory.cfg.DeepCopy()` pattern is the canonical
-  reference.
-- **Decode vs Encode is about the phase, not the direction.**  Mutating
-  `ctx.TargetResp` (the outbound body) from a Decode filter is a
-  category error — read `pkg/context/http/` before touching response
-  state.
-- **Response-body mutation is an Encode-only checklist.** For redaction,
-  watermarking, compression, or similar response transforms, inspect
-  existing response-transforming filters and their tests.
-  Operate on `ctx.TargetResp` only after confirming the concrete
-  response type. Handle `*client.UnaryResponse` deliberately, pass
-  streaming responses through unless the user explicitly asked for
-  streaming support, gate by `Content-Type` when the behavior is textual,
-  and write table-driven tests for empty body, unsupported content type,
-  configured/default values, and invalid config.
-
-For Network filters, the interface surface is larger
-(`ServeHTTP`, `OnData`, `OnTripleData`, etc.); reuse an existing one
-(`pkg/filter/network/httpconnectionmanager/`) as a template.
-
-### Step 4 — Register in `init()`
-
-```go
-func init() {
-    filter.RegisterHttpFilter(&Plugin{})
-}
-```
-
-For Network filters the call is 
`filter.RegisterNetworkFilterPlugin(&Plugin{})`.
-
-### Step 5 — Add the Blank Import (THIS is where filters die silently)
-
-Edit `pkg/pluginregistry/registry.go` and insert, in alphabetical order
-within the correct grouping:
-
-```go
-_ "github.com/apache/dubbo-go-pixiu/pkg/filter/<name>"
-```
-
-(Or `.../pkg/filter/http/<name>` if the package lives there.)
-
-If this line is missing, the filter compiles fine, `go test` passes, and
-pixiu boots — but the filter never registers, and yaml using its Kind
-fails with `no filter found for name ...`. This is *the* pixiu rite of
-passage.
-
-In answers, spell this out: package-level tests can pass while the
-gateway binary never imports the package, so the plugin `init()` never
-registers. The missing blank import is still required.
-
-Manually check the new package against `pkg/pluginregistry/registry.go`:
-if the package calls `filter.RegisterHttpFilter` or
-`filter.RegisterNetworkFilterPlugin`, it must be blank-imported there.
-Review the existing grouping and alphabetical order before inserting the
-new line.
-
-If the user asked for a "full workflow", do not stop after writing the
-filter package. The final answer must include either the applied
-`registry.go` edit or a precise patch hunk the user can apply.
-
-### Step 6 — Wire Up Config
-
-Add your filter to `configs/conf.yaml` (or whatever bootstrap the user
-is running), under the `http_filters` list of the
-`dgp.filter.httpconnectionmanager` network filter. Order matters: CORS /
-request auth / tracing normally run before proxy-style filters, while
-response-shaping filters must be placed where their Encode phase will
-see the intended response.
-
-```yaml
-- name: dgp.filter.http.<name>
-  config:
-    <field>: <value>
-```
-
-Do NOT put the filter under 
`static_resources.listeners[].filter_chains[].filters[]`
-directly — that's the Network filter level. HTTP filters always live
-inside `dgp.filter.httpconnectionmanager`'s `http_filters`.
-
-### Step 7 — Tests (optional; follow the project's actual convention)
-
-Pixiu does **not** have a "every filter must have tests" policy. Decide
-from the behavior you add, then mirror a nearby filter with comparable
-complexity:
-
-- **Skip the test** when your filter is a thin config-driven header
-  rewriter, an auth check that delegates to a library, a one-line proxy
-  switch, or otherwise mostly setup — matches cors / csrf / jwt /
-  httpproxy.
-- **Add a table-driven test** when your filter has branching logic,
-  state transitions, or response-body transformation — matches
-  sentinel/ratelimit / opa / accesslog.
-
-If you choose to test, copy the style of nearby table-driven tests in
-`pkg/filter/`. If you choose not to test, do not generate an empty stub
-`*_test.go` — empty test files are noise and do not match repo style.
-
-When in doubt, ask the user. Either answer is consistent with the
-project; pick deliberately.
-
-### Step 8 — Verify End-to-End
-
-- `go build ./...` from repo root must succeed.
-- If you wrote tests: `go test ./pkg/filter/<name>/...` must pass.
-- If the user has the gateway binary, `./dubbo-go-pixiu gateway start -c
-  configs/conf.yaml` should log the filter's Kind among the registered
-  filters at boot.
-- A `curl` against the listener port should exhibit the new behavior.
-
-For full-workflow answers, emit a compact delivery checklist:
-
-- Filter package path and the `Kind` string.
-- `pkg/pluginregistry/registry.go` blank-import patch or applied edit.
-- Minimal `http_filters` yaml snippet mounting the new filter.
-- Test decision: either real test files and commands, or a short reason
-  why no `_test.go` is consistent with nearby pixiu filters.
-- Verification commands run or, if not runnable, the exact commands the
-  user should run.
-
-## Cross-Cutting Rules
-
-### Always
-
-- Name the `Kind` constant with the correct prefix. HTTP filters use
-  `dgp.filter.http.*`; Network filters must match the current constants
-  in `pkg/common/constant/key.go` such as `dgp.filter.network.*` or the
-  special `dgp.filter.httpconnectionmanager`. Put it in a `const` at
-  the top of the package.
-- Use the project's logger: `import ".../pkg/logger"` and
-  `logger.Infof(...)`. Never `fmt.Println`, never stdlib `log`.
-- Deep-copy config into the per-request `Filter` instance — the factory
-  config is live and can change under you.
-- Keep imports in three alphabetically ordered groups (stdlib, third
-  party, internal) — this is a project-wide convention and the CI
-  linter enforces it.
-- Match the surrounding package style on testing: look at neighbors of
-  comparable complexity (cors / jwt for simple, opa / sentinel for
-  branching) and follow their pattern.
-- In full-workflow mode, always produce registry and config artifacts.
-  A filter package alone is incomplete even when it compiles.
-
-### Never
-
-- Expose internal error details in HTTP responses. Return generic
-  client-facing errors and log full diagnostics server-side only.
-- Skip the blank import. This is the #1 filter bug. If something does
-  not seem to register, re-check this before anything else.
-- Accept `dgp.filter.networkfilter.*`. That prefix is invalid in current
-  Pixiu; HTTP filters use `dgp.filter.http.*`, and Network filter Kinds
-  must be checked against `pkg/common/constant/key.go`.
-- Mutate `ctx.TargetResp` from a Decode filter. Use Encode.
-- Rewrite response streams unless the user explicitly requested
-  streaming support and you have designed backpressure/lifetime handling.
-- Launch a goroutine inside Decode/Encode without a parent context and
-  timeout — it will outlive the request.
-- Return `nil, error` from `CreateFilterFactory` for a non-fatal config
-  problem — instead return a zero-valued factory and log a warning; this
-  keeps pixiu bootable.
-- Generate an empty stub `*_test.go` "to be filled in later". Either
-  write a real test or omit the file.
-
-## Common Pitfalls
-
-1. **"My filter doesn't run" = missing blank import.** 90% of the time.
-   Check `pkg/pluginregistry/registry.go` first.
-2. **Phase confusion.** Auth → Decode; response shaping → Encode.
-   Filters are invoked Decode forward, Encode reversed — draw it out
-   once and the rest follows.
-3. **`ctx.Abort` vs `ctx.Next`.** `Abort` stops subsequent Decode
-   filters, but Encode filters of already-entered filters still run.
-4. **Per-request state in the factory.** The factory is shared across
-   all requests on a listener; per-request state belongs in the Filter
-   struct created by `PrepareFilterChain`.
-5. **Dubbo-aware filters running too early.** Anything that needs the
-   request's Dubbo parameters parsed must run *after*
-   `dgp.filter.httpconnectionmanager` has done its work — effectively,
-   it must be inside its `http_filters` list.
-6. **Yaml tags omitted on Config struct.** Without
-   `yaml:"field_name" mapstructure:"field_name"`, your field will not
-   bind. Follow CORS's tag pattern exactly.
-
-## Source Files To Read
-
-- `pkg/common/extension/filter/filter.go`
-- `pkg/pluginregistry/registry.go`
-- `pkg/filter/cors/cors.go`
-- Nearby filters under `pkg/filter/` or `pkg/filter/http/` with similar
-  complexity.
diff --git a/skills/pixiu-http-to-dubbo/SKILL.md 
b/skills/pixiu-http-to-dubbo/SKILL.md
deleted file mode 100644
index b7279bb91..000000000
--- a/skills/pixiu-http-to-dubbo/SKILL.md
+++ /dev/null
@@ -1,399 +0,0 @@
----
-name: pixiu-http-to-dubbo
-description: |
-  Map a REST/HTTP endpoint onto a backend Dubbo service through
-  dubbo-go-pixiu. Use whenever the user wants to "expose Dubbo as HTTP",
-  "REST gateway for Dubbo", "Dubbo generic invoke", configure
-  `api_config.yaml`, `integrationRequest`, `mappingParams`, `mapType`,
-  `opt.types` / `opt.values`, group / version, or says "how do I call
-  my Dubbo service from curl".
-  Use this even when the user only asks to tweak an existing yaml route —
-  the combination of conf.yaml + api_config.yaml is where most "500 from
-  pixiu" reports come from, and this skill encodes the invariants.
-allowed-tools: [Read, Grep, Glob, Edit, Write, Bash]
-metadata:
-  version: "0.1.2"
-  domain: config
-  scope: generate-and-validate
-  triggers: ["http to dubbo", "REST to Dubbo", "Dubbo gateway", 
"api_config.yaml", "integrationRequest", "Dubbo generic invoke", 
"mappingParams", "mapType", "opt.types", "expose Dubbo as HTTP"]
-  pixiu_min_version: "0.6.0"
-  role: specialist
----
-
-# pixiu-http-to-dubbo — Wiring HTTP Clients to Dubbo Backends
-
-pixiu's bread and butter is "let a REST client call a Dubbo service". On
-the surface it's two yaml files; underneath, you are configuring a
-generic Dubbo invoke, and most failures come from the three-way mismatch
-between the client request shape, the Dubbo interface signature, and
-the mapping rules in between.
-
-## Two files, two jobs
-
-- **`conf.yaml`** (bootstrap) — wires the HTTP listener, enables the
-  `dgp.filter.httpconnectionmanager` network filter, and loads the
-  Dubbo registry adapter. You almost always keep this close to the
-  sample; changes are listener port, adapter type, and sometimes
-  cluster definitions.
-  In config answers, explicitly use canonical HCM Kind
-  `dgp.filter.httpconnectionmanager` (never
-  `dgp.filter.http.httpconnectionmanager`) and put
-  `dgp.filter.http.apiconfig` before `dgp.filter.http.dubboproxy` or
-  `dgp.filter.http.httpproxy` inside HCM `http_filters`.
-- **`api_config.yaml`** — the per-endpoint mapping. One
-  `resources[].methods[]` entry per HTTP route. Every field except the
-  path comes from the Dubbo side; every mapping rule comes from the
-  HTTP side.
-
-This skill's job is to keep those two in sync.
-
-## When to Use
-
-Use this skill when the user wants to:
-- Expose an existing Dubbo interface through HTTP (GET/POST/PUT/DELETE).
-- Configure `integrationRequest` for an existing route.
-- Fix a 500 / "generic invoke failed" / "no provider found" error that
-  points at a yaml route.
-- Add parameter-name mapping (query → method param, body field → method
-  param, header → method param).
-- Switch an existing HTTP proxy route to Dubbo backend.
-
-**Do NOT use this skill for:**
-- Writing a new filter in the chain → `pixiu-filter-author`.
-- Adding a new registry adapter for a non-standard service registry —
-  out of scope; the user will need to author the adapter directly
-  against `pkg/common/extension/adapter/adapter.go`.
-- Pure yaml audit with no new HTTP-to-Dubbo route — out of scope. This
-  skill only validates the route/config fragments it generates or edits.
-
-## Prerequisites
-
-- pixiu ≥ 0.6.0.
-- A Dubbo provider running somewhere reachable. The user must know the
-  interface FQCN, method name, Java method signature, and the Dubbo
-  `group` / `version`.
-- Registry mode needs ZooKeeper/Nacos config under
-  `dgp.filter.http.dubboproxy.config.dubboProxyConfig.registries`.
-  Direct mode instead uses `integrationRequest.url` in `api_config.yaml`
-  and must also declare `parameterTypes` and `serialization`.
-
-## Steps
-
-### Step 0 — Verify Context
-
-1. Confirm pixiu version: `grep dubbo-go-pixiu go.mod`.
-2. Locate existing config: typically `configs/conf.yaml` and
-   `configs/api_config.yaml` in the pixiu repo, or user-specified
-   paths.
-3. Open `pkg/config/api_config.go` — that's the Go struct the yaml
-   actually binds to. Current `DubboBackendConfig` includes
-   `parameterTypes` and `serialization`; the legacy spelling
-   `paramTypes` is not the current field name.
-4. Open `pkg/filter/http/remote/dubbo_handler.go`,
-   `pkg/client/dubbo/types.go`, `pkg/client/dubbo/typeconv.go`, and
-   `pkg/client/dubbo/dubbo.go` before editing mappings. Do not cite
-   legacy mapping helpers on branches where they no longer exist.
-5. If the user says "Dubbo direct URL, no registry", use the current
-   direct generic contract: `integrationRequest.url` plus explicit
-   `protocol`, `parameterTypes`, and `serialization`.
-
-### Step 1 — Gather the Required Things (STOP and ask)
-
-You cannot write a valid `integrationRequest` without all applicable
-items:
-
-1. **HTTP method + path**: `POST /api/v1/user`, etc.
-2. **Dubbo interface FQCN**: e.g. `com.example.UserProvider`.
-3. **Dubbo method name**: e.g. `createUser`.
-4. **Java method signature**: e.g.
-   `User createUser(com.example.User user)` or
-   `Page<Order> search(String tenant, OrderQuery q)`. Translate each
-   argument into `parameterTypes` and supported pixiu `mapType` values
-   (`string`, `int`, `long`, `double`, `boolean`, `object`, etc.).
-5. **Dubbo `group` and `version`**: empty strings are allowed but must
-   be explicit.
-6. **Where each parameter comes from** on the HTTP side: `queryStrings.
-   <name>`, `requestBody.<path>`, `headers.<name>`, `uri.<name>`.
-7. **Registry/direct mode**: ZK/Nacos registry, or direct URL. Registry
-   settings live in `conf.yaml`; direct provider address lives in
-   `integrationRequest.url`.
-8. **Direct-call extras**: for direct URL mode, the declared protocol,
-   `parameterTypes`, and `serialization`.
-
-For POJO arguments, also ask whether the HTTP JSON body includes the
-Dubbo/Hessian class discriminator the provider expects, usually a
-`class` field such as `"class": "com.example.User"`. Pixiu can map the
-argument as `object`, but it cannot infer every provider-side POJO FQCN
-from a yaml field that the current config struct ignores.
-
-For primitives, collections, and nested POJOs, stay close to
-`DubboHandler`, `typeconv.go`, and existing `api_config.yaml` examples
-before finalizing `mappingParams`.
-
-If the user says "direct URL", "no registry", or gives a provider
-address such as `10.0.0.8:20880`, keep the Dubbo route as
-`integrationRequest.requestType: dubbo` and put the provider address in
-`integrationRequest.url`. Direct generic invoke also requires
-`parameterTypes` and `serialization`; without them Pixiu returns direct
-generic validation errors before invoking the provider.
-
-Do NOT proceed until the required fields are answered. It is fine to propose
-defaults and ask for confirmation — but **every field must be explicit
-in the final yaml**.
-
-### Step 2 — Shape the `api_config.yaml` entry
-
-The template:
-
-```yaml
-name: pixiu
-description: <what this gateway does>
-resources:
-  - path: /api/v1/user
-    type: restful
-    description: create a user
-    methods:
-      - httpVerb: POST
-        enable: true
-        timeout: 1000ms
-        inboundRequest:
-          requestType: http
-          # describe the HTTP shape the client will send:
-          headers:
-            - name: X-Request-Id
-              required: false
-          queryStrings: []
-          requestBody:
-            - contentType: application/json
-              schema: user
-              required: true
-        integrationRequest:
-          requestType: dubbo
-          # Dubbo coordinates:
-          applicationName: pixiu
-          group: ""
-          version: "1.0.0"
-          interface: com.example.UserProvider
-          method: createUser
-          parameterTypes:
-            - com.example.User
-          # How to pull each Dubbo method argument from the HTTP request:
-          mappingParams:
-            - name: requestBody
-              mapTo: "0"
-              mapType: object
-```
-
-Rules the template hides:
-
-- `requestType` **must** be `dubbo` for Dubbo routes. `http` is the
-  pass-through mode; different code path.
-- `requestType: triple` uses the same outbound builder, but direct
-  Triple generic invoke requires the provider to expose generic `$invoke`;
-  IDL-only Triple handlers may return `404 Not Found`.
-- `mapTo` is either the **index** of the Dubbo method parameter
-  (`mapTo: "0"` is the first argument) or one of the supported
-  `opt.*` targets such as `opt.types`, `opt.values`, `opt.group`,
-  `opt.version`, `opt.interface`, or `opt.method`. `opt.application`
-  is deprecated in the current handler.
-- `parameterTypes` is the preferred explicit Java signature. In
-  registry mode, `opt.types` can still provide the signature when
-  `parameterTypes` is omitted. In direct mode, `parameterTypes` is
-  required.
-- `mapType` is the conversion hint consumed by pixiu's Dubbo type
-  conversion path. Supported values come from `constant.JTypeMapper`: `string`,
-  `java.lang.String`, `char`, `short`, `int`, `long`, `float`,
-  `double`, `boolean`, `java.util.Date`, `date`, `object`, and
-  `java.lang.Object`. Use `object` / `java.lang.Object` for POJO or map
-  payloads, and include provider-required class metadata in the body
-  when the Dubbo serializer needs it.
-- `paramTypes` is not the current field name. Use `parameterTypes`.
-- Registry mode gets provider discovery from
-  `dubboProxyConfig.registries`. Direct mode gets the provider address
-  from `integrationRequest.url`; do not model it as a static cluster-only
-  path unless the target branch proves that older direct filter is in use.
-
-For dynamic/default generic routes where the HTTP client explicitly
-sends the type list and value list, map body fields to `opt.types` and
-`opt.values` instead of using top-level yaml fields:
-
-```yaml
-mappingParams:
-  - name: requestBody.types
-    mapTo: opt.types
-  - name: requestBody.values
-    mapTo: opt.values
-```
-
-When the user pastes legacy `paramTypes`, `groupType`, or old
-`types/values` examples, translate the intent into current
-`parameterTypes`, `mappingParams`, and `mapType` rules. Do not preserve
-unknown fields just because the user supplied them; current
-`IntegrationRequest` silently ignores fields not present in
-`pkg/config/api_config.go`.
-
-### Step 3 — Update `conf.yaml` if needed
-
-You usually only touch `conf.yaml` when:
-
-- This is the first registry-backed Dubbo route (need
-  `dgp.filter.http.dubboproxy.config.dubboProxyConfig.registries`, and
-  often the dynamic `dgp.adapter.dubboregistrycenter` if API definitions
-  come from a registry).
-- A new listener port or host is needed.
-- The user wants direct/no-registry Dubbo access. In that case
-  `api_config.yaml` must carry `integrationRequest.url`,
-  `parameterTypes`, and `serialization`; `conf.yaml` still needs the
-  listener/filter chain, but not a static Dubbo cluster endpoint for
-  that direct provider.
-
-The `dgp.filter.http.dubboproxy` registry block (ZK example, inside HCM
-`http_filters`):
-
-```yaml
-- name: dgp.filter.http.dubboproxy
-  config:
-    dubboProxyConfig:
-      registries:
-        zk:
-          protocol: zookeeper
-          timeout: 3s
-          address: 127.0.0.1:2181
-          username: ""
-          password: ""
-      timeout_config:
-        connect_timeout: 5s
-        request_timeout: 5s
-```
-
-Add `dgp.adapter.dubboregistrycenter` only when API definitions are
-dynamically discovered from a Dubbo registry, not for every static
-`api_config.yaml` route.
-
-For direct/no-registry cases, omit the registry adapter and put the
-provider address in `api_config.yaml`:
-
-```yaml
-integrationRequest:
-  requestType: dubbo
-  url: dubbo://10.0.0.8:20880
-  protocol: dubbo
-  serialization: hessian2
-  interface: com.example.UserProvider
-  method: getUser
-  group: ""
-  version: "1.0.0"
-  parameterTypes:
-    - java.lang.String
-  mappingParams:
-    - name: queryStrings.name
-      mapTo: "0"
-      mapType: string
-```
-
-If the URL omits a scheme, `protocol` must still be set so Pixiu can
-construct the direct Dubbo reference.
-
-And the HTTP listener MUST have `dgp.filter.http.apiconfig` in its
-`http_filters` list, followed by `dgp.filter.http.dubboproxy` (or
-`dgp.filter.http.httpproxy` if some routes are pass-through). Filter
-order matters — compare against the current config structs and examples.
-
-### Step 4 — Validate
-
-Before booting Pixiu, inspect the generated config directly:
-
-1. Parse the yaml with an available local parser or by loading it through
-   Pixiu's config path.
-2. Check the current API config structs and examples for required keys,
-   expected types, and the allowed shape of structured API mapping
-   objects. `filter.config` remains intentionally permissive because
-   individual filter plugins own their own config schemas.
-3. For registry mode, check that `dgp.filter.http.dubboproxy` has usable
-   `dubboProxyConfig.registries`. For direct mode, check
-   `integrationRequest.url`, `protocol`, `parameterTypes`, and
-   `serialization`.
-
-If validation fails, fix *before* trying to boot pixiu — boot-time
-errors are more cryptic than config-shape mistakes found by inspection.
-
-### Step 5 — Smoke Test
-
-1. `go run ./cmd/pixiu/... gateway start -c configs/conf.yaml -a 
configs/api_config.yaml`
-   (or the binary equivalent).
-2. `curl -v -X POST http://localhost:<port>/<path> ...`
-3. If you get HTTP 5xx, inspect Pixiu server logs near the request
-   timestamp and match the first error to the config area it references.
-
-## Cross-Cutting Rules
-
-### Always
-
-- Base generated yaml on the current `pkg/config/api_config.go` and
-  `pkg/filter/http/remote/dubbo_handler.go`, not on older examples. Use
-  `parameterTypes`, not legacy `paramTypes`.
-- Use supported `mapType` values exactly as pixiu's `constant.JTypeMapper`
-  defines them. `String` and `bool` are not valid current-source values;
-  use `string` / `java.lang.String` and `boolean`.
-- Keep numeric `mappingParams[].mapTo` values aligned with Java method
-  argument order. `mapTo: "0"` is the first Dubbo argument.
-- Specify `group` and `version` explicitly, even if empty. Empty-string
-  is valid; missing key is not.
-- Put `dgp.filter.http.apiconfig` **before** any proxy filter in
-  `http_filters`.
-- Timeouts: give `methods[].timeout` a value shorter than the
-  listener's `idle_timeout` in `conf.yaml`.
-
-### Never
-
-- Generate top-level `paramTypes`; current pixiu uses `parameterTypes`.
-- Write `String` or `bool` as a `mapType`. Current pixiu accepts
-  `string` / `java.lang.String` and `boolean`.
-- Mix `requestType: http` and Dubbo fields in the same
-  `integrationRequest`. Pick one.
-- Put a registry-backed Dubbo provider address in HTTP backend fields
-  such as `host` or `path`. For direct/no-registry Dubbo calls, use
-  `integrationRequest.url` and also set `parameterTypes` and
-  `serialization`.
-- Put the Dubbo registry configuration in `api_config.yaml`. It lives
-  in `conf.yaml` under `dgp.filter.http.dubboproxy` and, for dynamic API
-  discovery, under `adapters`.
-- Use the literal object from the request body as a single arg when
-  the Dubbo side expects separate primitives. Use
-  `mappingParams[].mapTo` with an index per arg.
-
-## Common Pitfalls
-
-1. **`no provider found`** at boot — registry is up but the adapter
-   cannot resolve the interface. Check `interface`, `group`, `version`
-   spelling; `group` is case-sensitive.
-2. **500 with `generic invoke failed: ClassNotFound`** — type strings
-   came from `parameterTypes`, `opt.types`, or request body `types` and
-   do not match classes visible to the provider. Prefer exact Java
-   class names and provider-required POJO class metadata in the JSON
-   body.
-3. **Response is `{}` / empty** — `mappingParams` is empty or wrong,
-   so the Dubbo method got `null` args and returned its default value.
-4. **Timeout set in the wrong layer** — `methods[].timeout` becomes the
-   Dubbo call deadline; `dubboProxyConfig.timeout_config` controls the
-   Dubbo client side. If the Dubbo call is slow, check the method
-   timeout first, then the proxy timeout config.
-5. **Header/query name case** — `inboundRequest.headers[].name` is
-   case-insensitive on match but case-sensitive in logs; normalize in
-   docs.
-6. **Nacos namespace confusion** — `namespace` vs `namespaceId` vs
-   `group` vs `groupName`. pixiu's Nacos adapter uses `namespace` and
-   `group`; if you are setting up a new adapter from scratch, read
-   the adapter source under `pkg/adapter/` for the actual field
-   names.
-
-## Source Files To Read
-
-- `pkg/config/api_config.go`
-- `pkg/filter/http/remote/dubbo_handler.go`
-- `pkg/client/dubbo/types.go`
-- `pkg/client/dubbo/typeconv.go`
-- `pkg/client/dubbo/dubbo.go`
-- Existing `configs/api_config.yaml` and sample `api_config.yaml`
-  files.
-- Pixiu server logs for the first error near a failing request.
diff --git a/skills/pixiu-llm-gateway/SKILL.md 
b/skills/pixiu-llm-gateway/SKILL.md
deleted file mode 100644
index b1f126d81..000000000
--- a/skills/pixiu-llm-gateway/SKILL.md
+++ /dev/null
@@ -1,293 +0,0 @@
----
-name: pixiu-llm-gateway
-description: |
-  Configure Apache dubbo-go-pixiu as an AI / LLM gateway. Use when the
-  user asks to proxy OpenAI-compatible, Claude-compatible, Gemini, vLLM,
-  DeepSeek, or self-hosted model endpoints; configure `dgp.filter.llm.proxy`,
-  `dgp.filter.llm.tokenizer`, `dgp.filter.ai.kvcache`, LLM retry/fallback,
-  endpoint `llm_meta`, token metrics, LMCache/vLLM cache-aware routing, or
-  Nacos LLM registry discovery. This skill is for Pixiu `conf.yaml`, not
-  `api_config.yaml`.
-allowed-tools: [Read, Grep, Glob, Edit, Write, Bash]
-metadata:
-  version: "0.1.1"
-  domain: ai-gateway
-  scope: generate-and-validate
-  triggers: ["LLM gateway", "AI gateway", "OpenAI proxy", "Claude proxy", 
"vLLM", "DeepSeek", "kvcache", "LMCache", "tokenizer", "token billing", 
"llm_meta", "dgp.filter.llm.proxy"]
-  pixiu_min_version: "0.6.0"
-  experimental: true
-  role: specialist
----
-
-# pixiu-llm-gateway — Configuring Pixiu as an LLM Gateway
-
-Pixiu's LLM path is config-driven. The gateway routes normal HTTP
-requests to LLM-compatible upstreams through `dgp.filter.llm.proxy`,
-optionally records token metrics with `dgp.filter.llm.tokenizer`, and
-optionally hints cache-local routing with `dgp.filter.ai.kvcache`.
-
-This skill writes `conf.yaml` fragments. It does not write
-`api_config.yaml`; HTTP-to-Dubbo API mapping is a different code path.
-
-## When to Use
-
-Use this skill when the user wants to:
-
-- Expose an OpenAI-compatible chat/completions endpoint through Pixiu.
-- Route between multiple LLM providers or self-hosted vLLM instances.
-- Configure endpoint-level API keys, retry policy, fallback, or health
-  cooldown through `llm_meta`.
-- Enable token metrics / token accounting through
-  `dgp.filter.llm.tokenizer`.
-- Enable KV cache-aware routing through `dgp.filter.ai.kvcache`.
-- Discover LLM endpoints dynamically from Nacos via
-  `dgp.adapter.llmregistrycenter`.
-
-Do not use this skill for:
-
-- HTTP to Dubbo routes; use `pixiu-http-to-dubbo`.
-- MCP tool exposure; use `pixiu-mcp-integration`.
-- Authoring a new filter implementation; use `pixiu-filter-author`.
-
-## Step 0 — Verify Current Source First
-
-The LLM module is moving quickly. Before generating yaml, read the
-current repo shape:
-
-1. `pkg/common/constant/key.go` for the exact Kind strings.
-2. `pkg/filter/llm/proxy/filter.go` for proxy config, endpoint
-   selection, API key injection, retry, and fallback behavior.
-3. `pkg/filter/llm/tokenizer/tokenizer.go` for token metric behavior.
-4. `pkg/filter/ai/kvcache/config.go` and `handlers.go` for cache-aware
-   routing and the `endpoint.id` contract.
-5. `pkg/model/llm.go`, `pkg/model/cluster.go`, and `pkg/model/base.go`
-   for `llm_meta`, endpoint, and `socket_address` fields.
-6. `configs/ai_kvcache_config.yaml` and docs under `docs/ai/` if
-   present.
-
-If source disagrees with this skill, trust source and note the
-difference in the final answer.
-
-## Step 1 — Gather the Eight Things
-
-Do not produce a final config until these are explicit:
-
-1. HTTP listener address and route prefix/path, usually `/v1/`.
-2. Upstream mode: static `clusters[]` or Nacos LLM registry.
-3. Provider endpoints: host/domain, scheme (`http` or `https`), and
-   path convention (`/v1/chat/completions`, `/v1/completions`, etc.).
-4. API key handling: per-endpoint `llm_meta.api_key`, injected secret
-   placeholder, or caller-supplied Authorization header.
-5. Retry policy per endpoint: `NoRetry`, `CountBased`, or
-   `ExponentialBackoff`.
-6. Fallback behavior: whether endpoint failure should move to the next
-   endpoint in the same cluster.
-7. Token metrics: whether to add `dgp.filter.llm.tokenizer` and whether
-   console logging is acceptable.
-8. KV cache: whether vLLM `/tokenize` and LMCache controller endpoints
-   exist, and whether LMCache `instance_id` values match Pixiu
-   `endpoint.id`.
-
-It is fine to propose safe defaults, but make assumptions explicit.
-
-## Step 2 — Shape the Static Gateway Config
-
-Minimal static gateway shape:
-
-```yaml
-static_resources:
-  listeners:
-    - name: "net/http"
-      protocol_type: "HTTP"
-      address:
-        socket_address:
-          address: "0.0.0.0"
-          port: 8888
-      filter_chains:
-        filters:
-          - name: dgp.filter.httpconnectionmanager
-            config:
-              route_config:
-                routes:
-                  - match:
-                      prefix: "/v1/"
-                    route:
-                      cluster: "llm_cluster"
-                      cluster_not_found_response_code: 503
-              http_filters:
-                - name: dgp.filter.llm.tokenizer
-                  config:
-                    log_to_console: false
-                - name: dgp.filter.llm.proxy
-                  config:
-                    scheme: "https"
-                    timeout: "60s"
-  clusters:
-    - name: "llm_cluster"
-      lb_policy: "RoundRobin"
-      endpoints:
-        - id: "openai-primary"
-          socket_address:
-            domains:
-              - "api.openai.com"
-          llm_meta:
-            provider: "openai"
-            api_key: "${OPENAI_API_KEY}"
-            fallback: true
-            health_check_interval: 5000
-            retry_policy:
-              name: "ExponentialBackoff"
-              config:
-                times: 3
-                initialInterval: "200ms"
-                maxInterval: "5s"
-                multiplier: 2.0
-```
-
-Notes:
-
-- `dgp.filter.llm.proxy` forwards the original request path and query
-  to the selected endpoint. If the client calls `/v1/chat/completions`,
-  the upstream receives that same path.
-- `socket_address.domains[0]` should be a host, not a full URL and not
-  a path-bearing value. Current `llm.proxy` puts it into `url.URL.Host`;
-  use `api.openai.com`, not `https://api.openai.com` or
-  `api.openai.com/v1`.
-- `dgp.filter.llm.proxy.config.scheme` is filter-level. Every endpoint
-  reached by the same HTTP filter instance uses that one scheme, so do
-  not mix `https` providers and `http` local vLLM endpoints in the same
-  route/filter configuration. Split them by route/listener/cluster
-  arrangement or normalize the upstream scheme.
-- When correcting adversarial configs, explicitly say: `scheme` is
-  filter-level, `socket_address.domains` is host-only, and full URLs
-  such as `https://api.openai.com/v1` do not belong in `domains`.
-- `lb_policy` must be one of `Rand`, `RoundRobin`, `RingHashing`,
-  `MaglevHashing`, or `WeightRandom`; reject `lb` and check
-  `pkg/model/cluster.go` before inventing a policy.
-- Endpoint API keys are injected as `Authorization: Bearer <api_key>`.
-  Do not hard-code production secrets; use placeholders or the user's
-  secret management convention.
-- `dgp.filter.llm.tokenizer` should be before `dgp.filter.llm.proxy` so
-  Decode starts timing before the upstream call. Its Encode phase reads
-  proxy attempt data and token usage from the response.
-- Tokenizer metrics read OpenAI-style `usage` fields for unary responses
-  and SSE `data:` frames for streaming responses. If upstream omits token
-  usage, report partial metrics instead of inventing counts.
-
-## Step 3 — Add KV Cache Only When the Contract Exists
-
-KV cache-aware routing is optional. It only works when LMCache returns
-an `instance_id` that matches a Pixiu endpoint `id`.
-
-```yaml
-http_filters:
-  - name: dgp.filter.ai.kvcache
-    config:
-      enabled: true
-      vllm_endpoint: "http://127.0.0.1:8000";
-      lmcache_endpoint: "http://127.0.0.1:9000";
-      default_model: "Qwen2.5-3B-Instruct"
-      request_timeout: "2s"
-      lookup_routing_timeout: "50ms"
-      hot_window: "5m"
-      hot_max_records: 300
-      token_cache:
-        enabled: true
-        max_size: 1024
-        ttl: "10m"
-      cache_strategy:
-        enable_compression: true
-        enable_pinning: true
-        enable_eviction: true
-        load_threshold: 0.7
-        memory_threshold: 0.85
-        hot_content_threshold: 10
-        pin_instance_id: "vllm-instance-1"
-        pin_location: "LocalCPUBackend"
-        compress_instance_id: "vllm-instance-1"
-        compress_location: "LocalCPUBackend"
-        compress_method: "zstd"
-        evict_instance_id: "vllm-instance-1"
-  - name: dgp.filter.llm.tokenizer
-    config:
-      log_to_console: false
-  - name: dgp.filter.llm.proxy
-    config:
-      scheme: "http"
-      timeout: "60s"
-```
-
-Before generating a kvcache config, read the current
-`pkg/filter/ai/kvcache/` source and any checked-in AI config examples.
-
-## Step 4 — Use Nacos Discovery Only for Dynamic Endpoint Discovery
-
-Static clusters are simpler. Use `dgp.adapter.llmregistrycenter` only
-when LLM services register endpoint metadata into Nacos.
-
-```yaml
-adapters:
-  - id: "llm-nacos"
-    name: dgp.adapter.llmregistrycenter
-    config:
-      registries:
-        nacos:
-          protocol: nacos
-          address: "127.0.0.1:8848"
-          timeout: "5s"
-          group: "test_llm_registry_group"
-          namespace: "public"
-```
-
-The Nacos instance metadata must include `cluster`, `id`, and LLM
-metadata keys such as `llm-meta.api_key`,
-`llm-meta.retry_policy.name`, and `llm-meta.fallback`. Read the current
-LLM registry adapter source before generating Nacos instructions.
-
-## Step 5 — Validate
-
-Before booting Pixiu, inspect `conf.yaml` directly. Check yaml syntax,
-filter order, required LLM cluster fields, `llm_meta` placement,
-kvcache instance-id references, and Nacos adapter basics.
-
-## Cross-Cutting Rules
-
-### Always
-
-- Generate `conf.yaml` fragments, not `api_config.yaml`.
-- Use exact current Kind strings: `dgp.filter.llm.proxy`,
-  `dgp.filter.llm.tokenizer`, `dgp.filter.ai.kvcache`, and
-  `dgp.adapter.llmregistrycenter`.
-- Use singular `llm-meta.api_key` in Nacos metadata. Older docs may say
-  `llm-meta.api_keys`, but current source reads only the singular key.
-- Put `dgp.filter.ai.kvcache` and `dgp.filter.llm.tokenizer` before
-  `dgp.filter.llm.proxy` when enabled.
-- Keep `llm_meta` under each `clusters[].endpoints[]` entry.
-- Use endpoint `id` values that can be matched by kvcache / LMCache
-  instance IDs.
-- Use duration strings with units: `"60s"`, `"200ms"`, `"5m"`.
-
-### Never
-
-- Put LLM provider credentials in `api_config.yaml`.
-- Put `llm_meta` under the cluster instead of endpoints.
-- Put `scheme` under individual endpoints or put full URLs in
-  `socket_address.domains`. The proxy has one filter-level scheme and
-  endpoint domains must be host-only.
-- Use Nacos `llm-meta.api_keys` plural for current source.
-- Use old names such as `dgp.filter.http.llm.proxy` unless Step 0 proves
-  the target branch changed the Kind constants.
-- Enable kvcache without `vllm_endpoint`, `lmcache_endpoint`, and an
-  endpoint-id matching story.
-- Promise cost billing from config alone. Current tokenizer records
-  token metrics; pricing/currency math belongs outside the current
-  filter unless the target branch adds it.
-
-## Source Files To Read
-
-- `pkg/filter/llm/proxy/`
-- `pkg/filter/llm/tokenizer/`
-- `pkg/filter/ai/kvcache/`
-- `pkg/adapter/llmregistry/`
-- `pkg/model/llm.go`, `pkg/model/cluster.go`, and current AI config
-  examples.
diff --git a/skills/pixiu-mcp-integration/SKILL.md 
b/skills/pixiu-mcp-integration/SKILL.md
deleted file mode 100644
index ded4b2ba4..000000000
--- a/skills/pixiu-mcp-integration/SKILL.md
+++ /dev/null
@@ -1,231 +0,0 @@
----
-name: pixiu-mcp-integration
-description: |
-  Use when configuring dubbo-go-pixiu as an MCP gateway:
-  `dgp.filter.mcp.mcpserver`, Streamable HTTP/SSE, `tools/list`,
-  `tools/call`, OAuth/JWT `dgp.filter.http.auth.mcp`, Nacos
-  `dgp.adapter.mcpserver`, or stdio MCP bridge guidance.
-allowed-tools: [Read, Grep, Glob, Edit, Write, Bash]
-metadata:
-  version: "0.1.1"
-  domain: ai-gateway
-  scope: generate-and-validate
-  triggers: ["MCP", "Model Context Protocol", "mcpserver", "tools/list", 
"tools/call", "Mcp-Session-Id", "dgp.filter.mcp.mcpserver", 
"dgp.filter.http.auth.mcp", "mcp gateway", "MCP tool"]
-  pixiu_min_version: "0.6.0"
-  experimental: true
-  role: specialist
----
-
-# pixiu-mcp-integration — Exposing HTTP APIs as MCP Tools
-
-Pixiu's current MCP integration is an HTTP filter that speaks MCP
-Streamable HTTP/SSE to clients and maps `tools/call` to backend HTTP
-clusters. It can also expose resources, resource templates, prompts,
-and optional OAuth/JWT protection.
-
-Important boundary: current Pixiu does not directly spawn or manage
-stdio MCP servers. For a stdio server, put an external bridge in front
-of it, then configure Pixiu to call the bridge as an HTTP backend tool.
-
-## When to Use
-
-Use this skill when the user wants to:
-
-- Expose existing backend HTTP APIs as MCP tools.
-- Configure MCP endpoint metadata, tools, resources, templates, or
-  prompts.
-- Support Streamable HTTP / SSE MCP clients.
-- Protect the MCP endpoint with OAuth 2.0 protected-resource metadata
-  and JWT validation.
-- Load MCP tool definitions dynamically from Nacos.
-- Integrate stdio MCP servers by documenting the required bridge.
-
-Do not use this skill for:
-
-- LLM model proxying; use `pixiu-llm-gateway`.
-- HTTP to Dubbo API mapping; use `pixiu-http-to-dubbo`.
-- Writing a new filter implementation; use `pixiu-filter-author`.
-
-## Step 0 — Verify Current Source First
-
-Read current source before generating config:
-
-1. `pkg/common/constant/key.go` for Kind strings.
-2. `pkg/model/mcpserver.go` for `McpServerConfig`, tool args,
-   resources, templates, and prompts.
-3. `pkg/filter/mcp/mcpserver/plugin.go`, `filter.go`, `handlers.go`,
-   and `transport/` for endpoint matching, Streamable HTTP/SSE, and
-   JSON-RPC handling.
-4. `pkg/filter/auth/mcp/config.go` and `filter.go` for optional auth.
-5. `pkg/adapter/mcpserver/registrycenter.go` and
-   `pkg/adapter/mcpserver/registry/nacos/` for dynamic tool discovery.
-6. `docs/ai/mcp/mcp.md` if present.
-
-If current source disagrees with this skill, trust the source and note
-the difference.
-
-## Step 1 — Gather the Nine Things
-
-Do not generate final config until these are explicit:
-
-1. MCP endpoint path, usually `/mcp`.
-2. Server name, version, description, and instructions.
-3. Static tools or Nacos-managed tools.
-4. For every static tool: name, description, upstream cluster,
-   request method/path/timeout, and argument schema.
-5. Backend clusters for each tool.
-6. Whether resources, resource templates, or prompts should be exposed.
-7. Transport expectation: JSON POST only, SSE GET stream, or both.
-8. Auth requirement: none, or `dgp.filter.http.auth.mcp` with issuer,
-   JWKS URL, resource URI, and protected cluster.
-9. If the user says stdio MCP: which external bridge will expose it as
-   HTTP/SSE. Pixiu itself does not run the stdio process.
-
-## Step 2 — Shape the Static MCP Server Config
-
-Before generating a static tool config, read `pkg/model/mcpserver.go`
-and the current MCP filter source. Keep the generated config compact but
-include these essentials:
-
-- `endpoint` must match the client URL path. Current filter checks
-  `ctx.Request.URL.Path == cfg.Endpoint`.
-- The `mcp-backend` route cluster is a routing anchor for the MCP
-  endpoint. Each tool has its own `cluster` for the actual backend call.
-- Declare every static tool cluster under `static_resources.clusters[]`.
-- Put `dgp.filter.mcp.mcpserver` before `dgp.filter.http.httpproxy`.
-- `tools/list`, `resources/list`, `prompts/list`, `initialize`,
-  `ping`, and `notifications/initialized` are terminal methods handled
-  by the MCP filter.
-- `tools/call` continues through the chain to an HTTP proxy, then
-  Encode converts the backend response into MCP tool-call output.
-- When explaining ordering, spell it out as
-  `dgp.filter.http.auth.mcp` before `dgp.filter.mcp.mcpserver`, and
-  `dgp.filter.mcp.mcpserver` before `dgp.filter.http.httpproxy`.
-  Terminal methods (`initialize`, `tools/list`, `resources/list`,
-  `prompts/list`, `ping`) stop at the MCP filter; `tools/call`
-  continues to `httpproxy`.
-- Current source declares `request.headers`, but `buildBackendRequest`
-  does not apply them yet. Do not rely on static tool headers for
-  runtime behavior; request bodies still get `Content-Type:
-  application/json` automatically.
-
-## Step 3 — Add OAuth/JWT Protection When Required
-
-Place `dgp.filter.http.auth.mcp` before `dgp.filter.mcp.mcpserver`:
-
-```yaml
-http_filters:
-  - name: dgp.filter.http.auth.mcp
-    config:
-      resource_metadata:
-        path: "/.well-known/oauth-protected-resource/mcp"
-        resource: "https://mcp.example.com/mcp";
-        authorization_servers:
-          - "https://auth.example.com";
-      providers:
-        - name: "main"
-          issuer: "https://auth.example.com";
-          jwks: "https://auth.example.com/.well-known/jwks.json";
-          audience: "https://mcp.example.com/mcp";
-      rules:
-        - cluster: "mcp-backend"
-  - name: dgp.filter.mcp.mcpserver
-    config: ...
-```
-
-Auth rules match the route entry's cluster. If `rules[].cluster` does
-not match the MCP route cluster, requests will not be protected.
-On successful validation the current auth filter removes the
-`Authorization` header before forwarding. Do not promise that the
-caller token reaches the tool backend; if the backend needs credentials,
-design an explicit downstream auth strategy instead of relying on the
-validated bearer token being forwarded.
-Safe alternatives are backend-side service auth, an external bridge or
-proxy that injects credentials, mTLS or network policy, or a source
-change that explicitly applies outbound headers.
-
-Before generating auth config, read the current MCP auth filter source.
-
-## Step 4 — Use Nacos Only for Dynamic Tool Definitions
-
-Static tools are easier. Use `dgp.adapter.mcpserver` only when a Nacos
-MCP registry supplies tool definitions.
-
-```yaml
-adapters:
-  - id: "mcp-nacos-adapter"
-    name: dgp.adapter.mcpserver
-    config:
-      registries:
-        nacos:
-          protocol: "nacos"
-          address: "127.0.0.1:8848"
-          timeout: "5s"
-          username: "nacos"
-          password: "nacos"
-          namespace: ""
-          group: "DEFAULT_GROUP"
-```
-
-The listener still needs `dgp.filter.mcp.mcpserver`; the adapter updates
-the in-process tool registry and may register endpoints for tools with
-`backend_url`.
-
-Before generating Nacos instructions, read the current MCP registry
-adapter source.
-
-## Step 5 — Validate and Smoke Test
-
-Before booting Pixiu, inspect `conf.yaml` directly. Check yaml syntax,
-filter order, MCP server config shape, route targets, static tool
-definitions, auth settings, and Nacos adapter basics.
-
-Smoke-test Streamable HTTP:
-
-```sh
-curl -i -X POST http://localhost:8888/mcp \
-  -H 'Content-Type: application/json' \
-  -H 'Accept: application/json, text/event-stream' \
-  -d 
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","clientInfo":{"name":"curl","version":"1.0.0"}}}'
-```
-
-For SSE, the client should call `GET /mcp` with
-`Accept: text/event-stream` and then reuse the returned
-`Mcp-Session-Id` on POST requests.
-
-## Cross-Cutting Rules
-
-### Always
-
-- Use exact current Kinds: `dgp.filter.mcp.mcpserver`,
-  `dgp.filter.http.auth.mcp`, and `dgp.adapter.mcpserver`.
-- Put auth before MCP server when auth is enabled.
-- Keep `endpoint` and route prefix/path aligned.
-- Ensure every tool `cluster` exists in `static_resources.clusters[]`
-  unless it is dynamically supplied by the adapter.
-- Use arg `in` values `path`, `query`, or `body`.
-- Use arg `type` values `string`, `integer`, `number`, or `boolean`.
-
-### Never
-
-- Claim Pixiu can directly run a stdio MCP server. It needs an external
-  HTTP/SSE bridge for stdio-based servers.
-- Put `tools` at top level; they belong under the MCP filter config.
-- Put `dgp.filter.mcp.mcpserver` after `httpproxy`; terminal MCP
-  methods must be handled before proxying.
-- Forget `dgp.filter.http.httpproxy` when `tools/call` needs to reach a
-  backend HTTP service.
-- Configure auth `rules[].cluster` with the tool backend cluster when
-  the MCP route itself uses a different route cluster.
-- Rely on `request.headers` for static tool backend credentials in the
-  current source. The model field exists, but `buildBackendRequest` does
-  not apply it yet; use an external bridge/proxy, backend-side auth, or
-  a source change before promising static header injection.
-
-## Source Files To Read
-
-- `pkg/model/mcpserver.go`
-- `pkg/filter/mcp/mcpserver/`
-- `pkg/filter/auth/mcp/`
-- `pkg/adapter/mcpserver/`
-- `docs/ai/mcp/` if present.

Reply via email to