eacg

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 28, 2026 License: MIT Imports: 15 Imported by: 0

README

EACG

EACG(Enterprise Agent Capability Gateway)是一个面向企业 Agent 的能力网关 Go Module。

当前仓库实现 v0.1.0 HTTP-only MVP:

  • MCP Streamable HTTP;
  • Typed Capability;
  • Bearer Token/JWT;
  • Service Token/API Key 与实际用户复合认证;
  • Tenant、Principal 和 Capability 级 RBAC;
  • 动态 Tool 可见性;
  • 输入输出 JSON Schema;
  • R0/R1 只读能力;
  • HTTP Connector;
  • 输出字段白名单与敏感字段遮盖;
  • 结构化审计;
  • Health、Readiness 和优雅停机。

MVP 不包含 gRPC、Kitex、下游 MCP、STDIO、R2/R3 写操作、Prometheus 和 OpenTelemetry。

环境要求

  • Go 1.25 或更高版本;
  • Make;
  • Docker,可选。

运行测试

make test
make test-race
make vet

启动示例

示例程序会同时启动:

  • EACG:http://127.0.0.1:8080/mcp
  • 演示下游 HTTP 服务:http://127.0.0.1:8090
make run

默认使用 JWT。若要演示企业微信风格的固定 API Key 加用户 Header:

make run-api-key

另开一个终端生成测试 JWT:

make token

默认令牌包含:

  • Tenant:tenant-a
  • User:user-1
  • Role:reader
  • 有效期:1 小时

把令牌配置到 MCP Host 的 Authorization: Bearer <token> 请求头,然后连接:

http://127.0.0.1:8080/mcp

可调用 Tool:

{
  "name": "get_profile",
  "arguments": {
    "user_id": "42"
  }
}

使用 curl 调用 MCP

以下命令已经在本地示例服务上验证。整个会话必须使用同一个 TOKEN 和 SESSION_ID。

先启动服务并生成 JWT:

make run

另开一个终端执行:

TOKEN=$(make -s token)
MCP_URL=http://127.0.0.1:8080/mcp
HEADER_FILE=/tmp/eacg-mcp-headers
1. 初始化 MCP Session
curl -sS -N \
  -D "$HEADER_FILE" \
  -X POST "$MCP_URL" \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  --data '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {
      "protocolVersion": "2025-11-25",
      "capabilities": {},
      "clientInfo": {
        "name": "curl-client",
        "version": "1.0.0"
      }
    }
  }'

响应使用 SSE 格式:

event: message
data: {"jsonrpc":"2.0","id":1,"result":{...}}

从响应头提取 Session ID:

SESSION_ID=$(
  awk 'BEGIN{IGNORECASE=1} /^Mcp-Session-Id:/ {
    gsub("\r", "", $2)
    print $2
  }' "$HEADER_FILE"
)
echo "$SESSION_ID"
2. 发送初始化完成通知
curl -sS -i \
  -X POST "$MCP_URL" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Mcp-Session-Id: $SESSION_ID" \
  -H 'Mcp-Protocol-Version: 2025-11-25' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  --data '{
    "jsonrpc": "2.0",
    "method": "notifications/initialized"
  }'

成功时返回 HTTP 202 Accepted。

3. 查询可用 Tool
curl -sS -N \
  -X POST "$MCP_URL" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Mcp-Session-Id: $SESSION_ID" \
  -H 'Mcp-Protocol-Version: 2025-11-25' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  --data '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/list",
    "params": {}
  }'

返回列表中应包含 get_profile。

4. 调用 get_profile
curl -sS -N \
  -X POST "$MCP_URL" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Mcp-Session-Id: $SESSION_ID" \
  -H 'Mcp-Protocol-Version: 2025-11-25' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  --data '{
    "jsonrpc": "2.0",
    "id": 3,
    "method": "tools/call",
    "params": {
      "name": "get_profile",
      "arguments": {
        "user_id": "42"
      }
    }
  }'

结构化结果示例:

{
  "email": "42@example.com",
  "name": "示例用户",
  "user_id": "42"
}
5. 关闭 MCP Session
curl -sS -i \
  -X DELETE "$MCP_URL" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Mcp-Session-Id: $SESSION_ID" \
  -H 'Mcp-Protocol-Version: 2025-11-25'

成功关闭时返回 HTTP 204 No Content;如果 Session 已关闭或已过期,则可能返回 404。

如果返回内容以 event: message 和 data: 开头,表示服务正在按 MCP Streamable HTTP 规范返回 SSE,而不是普通 JSON。

使用 API Key 和 requester userid 调用

API Key 模式使用两个 Header:

  • X-EACG-API-Key:认证企业微信机器人或其他调用应用;
  • X-EACG-Requester-UserID:标识当前实际提问用户。

先执行 make run-api-key,然后准备调用参数:

API_KEY=0123456789abcdef0123456789abcdef
REQUESTER_USER_ID=zhangsan
MCP_URL=http://127.0.0.1:8080/mcp
HEADER_FILE=/tmp/eacg-api-key-mcp-headers

初始化 MCP Session:

curl -sS -N \
  -D "$HEADER_FILE" \
  -X POST "$MCP_URL" \
  -H "X-EACG-API-Key: $API_KEY" \
  -H "X-EACG-Requester-UserID: $REQUESTER_USER_ID" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  --data '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {
      "protocolVersion": "2025-11-25",
      "capabilities": {},
      "clientInfo": {
        "name": "curl-api-key-client",
        "version": "1.0.0"
      }
    }
  }'

提取 Session ID:

SESSION_ID=$(
  awk 'BEGIN{IGNORECASE=1} /^Mcp-Session-Id:/ {
    gsub("\r", "", $2)
    print $2
  }' "$HEADER_FILE"
)
echo "$SESSION_ID"

发送初始化完成通知:

curl -sS -i \
  -X POST "$MCP_URL" \
  -H "X-EACG-API-Key: $API_KEY" \
  -H "X-EACG-Requester-UserID: $REQUESTER_USER_ID" \
  -H "Mcp-Session-Id: $SESSION_ID" \
  -H 'Mcp-Protocol-Version: 2025-11-25' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  --data '{
    "jsonrpc": "2.0",
    "method": "notifications/initialized"
  }'

查询 Tool:

curl -sS -N \
  -X POST "$MCP_URL" \
  -H "X-EACG-API-Key: $API_KEY" \
  -H "X-EACG-Requester-UserID: $REQUESTER_USER_ID" \
  -H "Mcp-Session-Id: $SESSION_ID" \
  -H 'Mcp-Protocol-Version: 2025-11-25' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  --data '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/list",
    "params": {}
  }'

调用 get_profile:

curl -sS -N \
  -X POST "$MCP_URL" \
  -H "X-EACG-API-Key: $API_KEY" \
  -H "X-EACG-Requester-UserID: $REQUESTER_USER_ID" \
  -H "Mcp-Session-Id: $SESSION_ID" \
  -H 'Mcp-Protocol-Version: 2025-11-25' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  --data '{
    "jsonrpc": "2.0",
    "id": 3,
    "method": "tools/call",
    "params": {
      "name": "get_profile",
      "arguments": {
        "user_id": "42"
      }
    }
  }'

关闭 Session:

curl -sS -i \
  -X DELETE "$MCP_URL" \
  -H "X-EACG-API-Key: $API_KEY" \
  -H "X-EACG-Requester-UserID: $REQUESTER_USER_ID" \
  -H "Mcp-Session-Id: $SESSION_ID" \
  -H 'Mcp-Protocol-Version: 2025-11-25'

同一 Session 的每个请求都必须携带相同 API Key 和 requester userid。更换其中任意一项都会使 Session 身份校验失败。

企业微信插件中应选择 Header,Parameter name 配置为 X-EACG-API-Key。requester userid Header 的实际名称由企业微信接入链路决定,再通过 EACG_REQUESTER_USER_HEADER 告诉 EACG。

Docker

make docker-build
docker run --rm -p 8080:8080 \
  -e EACG_JWT_SECRET=0123456789abcdef0123456789abcdef \
  eacg-example:local

示例默认密钥只适合本地学习,生产环境必须使用企业密钥管理系统。

API Key 模式:

docker run --rm -p 8080:8080 \
  -e EACG_AUTH_MODE=api_key \
  -e EACG_API_KEY=0123456789abcdef0123456789abcdef \
  -e EACG_CREDENTIAL_HEADER=X-EACG-API-Key \
  -e EACG_REQUESTER_USER_HEADER=X-EACG-Requester-UserID \
  eacg-example:local

最小接入示例

type Input struct {
    ID string `json:"id"`
}

type Output struct {
    ID   string `json:"id"`
    Name string `json:"name"`
}

item, err := capability.New(capability.Descriptor{
    ID:            "get_user.v1",
    Name:          "get_user",
    Version:       "v1",
    Description:   "查询用户基础信息",
    RiskLevel:     capability.RiskR1,
    ReadOnly:      true,
    RequiredRoles: []string{"reader"},
}, func(ctx context.Context, request capability.RequestContext, input Input) (Output, error) {
    // 在这里通过 HTTP Connector 调用企业业务服务。
    return Output{ID: input.ID, Name: "示例用户"}, nil
})

文档

Documentation

Overview

Package eacg 提供企业 Agent 能力网关的应用入口。

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type App

type App struct {
	// contains filtered or unexported fields
}

App 负责组装能力、协议和 HTTP 生命周期。

func New

func New(
	config Config,
	authentication HTTPAuthenticationConfig,
	sink audit.Sink,
) (*App, error)

New 使用统一认证配置创建 EACG 应用。

func (*App) Handler

func (a *App) Handler() (http.Handler, error)

Handler 构建可用于测试或外部 Server 的 HTTP Handler。

func (*App) RegisterCapability

func (a *App) RegisterCapability(items ...capability.Capability) error

RegisterCapability 注册一个领域能力。

func (*App) Run

func (a *App) Run(ctx context.Context) error

Run 启动 HTTP Server,并在上下文结束时优雅停机。

func (*App) SetLogger

func (a *App) SetLogger(logger *slog.Logger)

SetLogger 替换应用使用的结构化日志器。

func (*App) Stop

func (a *App) Stop(ctx context.Context) error

Stop 在超时时间内优雅停止 HTTP Server。

type Config

type Config struct {
	Name              string
	Version           string
	Address           string
	ReadHeaderTimeout time.Duration
	ShutdownTimeout   time.Duration
	SessionTimeout    time.Duration
	ExecutionTimeout  time.Duration
	AllowedOrigins    []string
	ResourceMetaURL   string
}

Config 定义 EACG 应用参数。

type HTTPAuthenticationConfig

type HTTPAuthenticationConfig struct {
	Authenticator    identity.Authenticator
	CredentialHeader string
	SubjectHeader    string
	SubjectProvider  string
}

HTTPAuthenticationConfig 定义 MCP HTTP 端点的认证方式。

Directories

Path Synopsis
Package audit 定义能力调用审计接口和默认实现。
Package audit 定义能力调用审计接口和默认实现。
Package capability 定义 EACG 的核心能力模型。
Package capability 定义 EACG 的核心能力模型。
cmd
eacg-example command
Command eacg-example 启动一个可学习和测试的 EACG 服务。
Command eacg-example 启动一个可学习和测试的 EACG 服务。
eacg-token command
Command eacg-token 为本地示例生成短期 JWT。
Command eacg-token 为本地示例生成短期 JWT。
connector
httpconnector
Package httpconnector 提供安全的下游 HTTP 调用能力。
Package httpconnector 提供安全的下游 HTTP 调用能力。
Package execution 实现固定顺序的 MVP 能力执行管线。
Package execution 实现固定顺序的 MVP 能力执行管线。
Package identity 定义调用者身份和令牌校验接口。
Package identity 定义调用者身份和令牌校验接口。
protocol
mcphttp
Package mcphttp 把 EACG 能力适配为 MCP Streamable HTTP。
Package mcphttp 把 EACG 能力适配为 MCP Streamable HTTP。
Package registry 提供线程安全的能力注册表。
Package registry 提供线程安全的能力注册表。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL