Token导航 LogoToken导航TokenDH.com
Go Contextforge logo
办公协作未说明官方级别未说明来源级核验

Go Contextforge

MCP Server

一个Go语言的SDK,用于IBM ContextForge MCP网关,提供丰富的API管理功能,包括工具、资源、网关、服务器、提示、代理和团队的管理。

工具数

0

提示词数

0

GitHub Stars

2

资源数

0
GoCursor多协议支持Cursor

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

作者 / 组织

leefowlercu

提供方

leefowlercu

最后核验

2026/5/17 20:19

快速接入

先看主来源和安装命令,再打开仓库或文档;下面只保留这个条目的关键接入事实。

详细介绍

go contextforge

](https://golang.org/) ![License: MIT](https://opensource.org/licenses/MIT)

Go SDK IBM ContextForge MCP网关 -一个功能丰富的网关、代理和MCP注册表,用于联合MCP和REST服务。

目录

- 兼容性

- 客户端配置 - 指针助手和标签 - 管理工具 - 管理资源 - 管理网关 - 管理服务器 - 管理提示 - 管理代理 - 管理团队 - 分页 - 错误处理

- 工具服务 - 资源服务 - 网关服务 - 服务器服务 - 提示服务 - 代理服务 - 团队服务

概述

ContextForge是人工智能客户端的统一端点,整合了发现、身份验证、速率限制、可观察性和虚拟服务器管理。它是一个完全兼容的MCP服务器,支持具有Redis支持的联盟的多集群Kubernetes环境。

此Go SDK为ContextForge API提供了一个惯用接口,允许您:

  • 管理工具 具有创建、更新、删除和切换操作
  • 管理资源 具有基于URI的访问和模板支持
  • 管理网关 用于MCP服务器联合和代理
  • 管理服务器 具有CRUD操作和工具、资源和提示的关联端点
  • 管理提示 具有基于模板的AI交互和论证支持
  • 管理代理 具有代理到代理(A2A)协议支持、调用和性能跟踪
  • 处理分页 使用基于光标或基于偏移(跳过/限制)的导航
  • 跟踪速率限制 并优雅地处理API错误
  • 验证 使用承载令牌(JWT)身份验证

MCP(模型上下文协议)

模型上下文协议(MCP)是一种开放协议,规范了人工智能系统访问外部数据源、工具和资源的方式。MCP使AI模型能够通过统一的接口与数据库、API、文件系统和其他服务安全地交互,从而更容易构建上下文感知的AI应用程序。

ContextForge将MCP协议实现为兼容的MCP服务器和联邦网关。它将多个MCP服务器和REST服务整合到一个端点中,提供集中身份验证、速率限制、可观察性和资源管理。这使人工智能客户端能够通过单个统一的API发现和访问来自多个来源的工具、资源和提示。

有关MCP协议的更多信息,请参阅 官方文件.

A2A协议

A2A(代理到代理)协议是一个开放标准,它实现了独立AI代理系统之间的通信和互操作性。虽然MCP专注于将AI模型与工具和资源连接起来,但A2A使代理能够发现、调用和与其他代理协作,而不管其底层框架或实现如何。

通过ContextForge,代理使用代理卡(JSON格式的功能描述)宣传他们的功能,允许其他代理发现并调用特定任务的最佳代理。A2A代理可以接收带有参数的调用,返回结构化响应,并跨交互跟踪性能指标。

SDK提供了对A2A代理的全面管理,包括创建、配置、端点注册、调用和性能指标跟踪。这使得构建多代理系统成为可能,在这些系统中,专门的代理可以通过标准化的协议进行协作。

有关A2A协议的更多信息,请参阅 官方规范项目网站.

兼容性

此SDK经过测试 ContextForge v1.0.0-RC1 (PyPI: mcp-contextforge-gateway==1.0.0rc1).

安装

go get github.com/leefowlercu/go-contextforge

要求: 转到1.25.3或更高版本

快速开始

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/leefowlercu/go-contextforge/contextforge"
)

func main() {
    // Create a client with address and bearer token
    client, err := contextforge.NewClient(nil, "http://localhost:8000/", "your-jwt-token")
    if err != nil {
        log.Fatal(err)
    }
    ctx := context.Background()

    // List tools
    tools, _, err := client.Tools.List(ctx, &contextforge.ToolListOptions{
        ListOptions: contextforge.ListOptions{Limit: 10},
    })
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Found %d tools:\n", len(tools))
    for _, tool := range tools {
        desc := contextforge.StringValue(tool.Description) // Safe nil handling
        fmt.Printf("- %s: %s\n", tool.Name, desc)
    }

    // Get a specific tool
    tool, _, err := client.Tools.Get(ctx, "tool-id")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("\nTool details: %s (Enabled: %v)\n", tool.Name, tool.Enabled)
}

使用指南

客户端配置

import (
    "net/http"
    "time"
    "github.com/leefowlercu/go-contextforge/contextforge"
)

// Create a client with locally hosted ContextForge instance
client, err := contextforge.NewClient(nil, "http://localhost:8000/", "your-jwt-token")
if err != nil {
    log.Fatal(err)
}

// Create a client with remote ContextForge instance
client, err := contextforge.NewClient(nil, "https://contextforge.example.com/", "your-jwt-token")
if err != nil {
    log.Fatal(err)
}

// Custom HTTP client with timeout
httpClient := &http.Client{
    Timeout: 60 * time.Second,
}
client, err = contextforge.NewClient(httpClient, "https://contextforge.example.com/", "your-jwt-token")
if err != nil {
    log.Fatal(err)
}

// Note: NewClient automatically adds trailing slash if missing

指针助手和标签

SDK使用指针和切片来区分可选字段的三种状态:

  1. -未设置字段(API请求中省略)
  2. 指向零值或空切片的指针 -字段已明确清除
  3. 指向值或填充切片的指针 -字段设置为该值

这种模式(由google/go-github、hashicorp/go-tfe、AWS SDK使用)允许部分更新,其中只有更改的字段被发送到API。

辅助功能:

// Creating pointers (for setting values)
name := contextforge.String("my-tool")
limit := contextforge.Int(10)
enabled := contextforge.Bool(true)
timeout := contextforge.Int64(3000)
weight := contextforge.Float64(0.95)
timestamp := contextforge.Time(time.Now())

// Extracting values (with zero-value fallback for nil)
nameStr := contextforge.StringValue(name)      // "my-tool"
limitInt := contextforge.IntValue(nil)         // 0
enabledBool := contextforge.BoolValue(enabled) // true

部分更新示例:

// Update only the name (other fields unchanged)
update := &contextforge.ResourceUpdate{
    Name: contextforge.String("new-name"),
    // Description, Tags, etc. are nil and won't be sent
}

// Clear the description (set to empty string)
update := &contextforge.ResourceUpdate{
    Description: contextforge.String(""),
}

// Don't update tags vs clear all tags
update1 := &contextforge.ResourceUpdate{
    Tags: nil,        // Tags field omitted - existing tags unchanged
}
update2 := &contextforge.ResourceUpdate{
    Tags: []string{}, // Empty array sent - clears all tags
}
update3 := &contextforge.ResourceUpdate{
    Tags: []string{"new-tag"}, // Sets new tags
}

标签类型处理:

由于v1.0.0中API响应格式的变化,标签的输入和输出类型不同:

  • 创建/更新类型 使用 []string 用于输入(例如。, ResourceCreate.Tags, PromptCreate.Tags)
  • 读取类型 返回 []Tag 结构体 IDLabel 字段(例如。, Tool.Tags, Prompt.Tags)

转换辅助函数:

// Convert strings to Tag structs (for update operations on read types)
tags := contextforge.NewTags([]string{"tag1", "tag2"})

// Extract tag names from Tag structs
names := contextforge.TagNames(tool.Tags) // Returns []string{"tag1", "tag2"}

管理工具

ctx := context.Background()

// List tools with filtering
opts := &contextforge.ToolListOptions{
    IncludeInactive: false,
    Tags: "automation,api",
    Visibility: "public",
    ListOptions: contextforge.ListOptions{
        Limit: 20,
    },
}
tools, resp, err := client.Tools.List(ctx, opts)

// Get tool by ID
tool, _, err := client.Tools.Get(ctx, "tool-id")

// Create a new tool
newTool := &contextforge.Tool{
    Name: "my-tool",
    Description: contextforge.String("A custom tool"),
    InputSchema: map[string]any{
        "type": "object",
        "properties": map[string]any{
            "input": map[string]any{"type": "string"},
        },
    },
    Enabled: true,
}

// Create with optional team/visibility settings
createOpts := &contextforge.ToolCreateOptions{
    TeamID:     contextforge.String("team-123"),
    Visibility: contextforge.String("public"),
}
created, _, err := client.Tools.Create(ctx, newTool, createOpts)

// Create without options
created, _, err = client.Tools.Create(ctx, newTool, nil)

// Update tool
tool.Description = contextforge.String("Updated description")
updated, _, err := client.Tools.Update(ctx, "tool-id", tool)

// Toggle tool status
toggled, _, err := client.Tools.Toggle(ctx, "tool-id", true) // activate

// Delete tool
_, err = client.Tools.Delete(ctx, "tool-id")

管理资源

由于API字段命名约定,资源对于不同的操作具有不同的类型:

  • 资源创建:用于创建资源(使用snake_case: mime_type)
  • 资源:阅读资源(使用camelCase: mimeType)
  • 资源更新:用于更新资源(使用camelCase: mimeType)
ctx := context.Background()

// List resources
resources, _, err := client.Resources.List(ctx, nil)

// Create a resource
newResource := &contextforge.ResourceCreate{
    URI:         "file:///path/to/resource",
    Name:        "my-resource",
    Content:     "Resource content here",
    Description: contextforge.String("A custom resource"),
    MimeType:    contextforge.String("text/plain"), // Note: snake_case for Create
    Tags:        []string{"documentation", "example"},
}

// Create with optional team/visibility settings
createOpts := &contextforge.ResourceCreateOptions{
    TeamID:     contextforge.String("team-123"),
    Visibility: contextforge.String("public"),
}
created, _, err := client.Resources.Create(ctx, newResource, createOpts)

// Create without options
created, _, err = client.Resources.Create(ctx, newResource, nil)

// Get resource content (hybrid REST endpoint returns MCP-compatible format)
content, _, err := client.Resources.Get(ctx, "resource-id")
if err == nil {
    fmt.Printf("Resource type: %s\n", content.Type)
    fmt.Printf("URI: %s\n", content.URI)
    if content.Text != nil {
        fmt.Printf("Text content: %s\n", *content.Text)
    }
    if content.Blob != nil {
        fmt.Printf("Blob content (base64): %s\n", *content.Blob)
    }
}

// Update resource (uses camelCase fields)
update := &contextforge.ResourceUpdate{
    Description: contextforge.String("Updated description"),
    MimeType:    contextforge.String("text/markdown"), // Note: camelCase for Update
    Tags:        []string{"updated", "documentation"},
}
updated, _, err := client.Resources.Update(ctx, "resource-id", update)

// Toggle resource status
toggled, _, err := client.Resources.Toggle(ctx, "resource-id", false) // deactivate

// List available templates
templates, _, err := client.Resources.ListTemplates(ctx)
for _, template := range templates.Templates {
    fmt.Printf("Template: %s\n", template.Name)
}

// Delete resource
_, err = client.Resources.Delete(ctx, "resource-id")

管理网关

网关支持MCP服务器的联合和代理:

ctx := context.Background()

// List gateways
gateways, _, err := client.Gateways.List(ctx, nil)

// Create a gateway
newGateway := &contextforge.Gateway{
    Name:        "my-gateway",
    URL:         "http://mcp-server.example.com",
    Description: contextforge.String("Proxy to external MCP server"),
    Transport:   "STREAMABLEHTTP",
    AuthType:    contextforge.String("bearer"),
    AuthToken:   contextforge.String("server-token"),
}

// Create with optional team/visibility settings
createOpts := &contextforge.GatewayCreateOptions{
    TeamID:     contextforge.String("team-123"),
    Visibility: contextforge.String("public"),
}
created, _, err := client.Gateways.Create(ctx, newGateway, createOpts)

// Create without options
created, _, err = client.Gateways.Create(ctx, newGateway, nil)

// Get gateway by ID
gateway, _, err := client.Gateways.Get(ctx, "gateway-id")

// Update gateway
gateway.Description = contextforge.String("Updated gateway description")
updated, _, err := client.Gateways.Update(ctx, "gateway-id", gateway)

// Toggle gateway status
toggled, _, err := client.Gateways.Toggle(ctx, "gateway-id", true) // activate

// Delete gateway
_, err = client.Gateways.Delete(ctx, "gateway-id")

管理服务器

服务器代表由ContextForge管理的MCP服务器实例:

ctx := context.Background()

// List servers
servers, _, err := client.Servers.List(ctx, nil)

// Create a server
newServer := &contextforge.ServerCreate{
    Name:        "my-server",
    Description: contextforge.String("Custom MCP server"),
    Icon:        contextforge.String("server"),
    Tags:        []string{"mcp", "production"},

    // Optional: Associate with existing resources
    AssociatedTools:     []string{"tool-id-1", "tool-id-2"},
    AssociatedResources: []string{"resource-id-1"},
    AssociatedPrompts:   []string{"prompt-id-1"},
    AssociatedA2aAgents: []string{"agent-id-1"},
}

// Create with optional team/visibility settings
createOpts := &contextforge.ServerCreateOptions{
    TeamID:     contextforge.String("team-123"),
    Visibility: contextforge.String("public"),
}
created, _, err := client.Servers.Create(ctx, newServer, createOpts)

// Create without options
created, _, err = client.Servers.Create(ctx, newServer, nil)

// Get server by ID
server, _, err := client.Servers.Get(ctx, "server-id")

// Update server
update := &contextforge.ServerUpdate{
    Description:         contextforge.String("Updated server description"),
    Tags:                []string{"mcp", "production", "updated"},
    AssociatedTools:     []string{"tool-id-3"}, // Replace associations
}
updated, _, err := client.Servers.Update(ctx, "server-id", update)

// Toggle server status
toggled, _, err := client.Servers.Toggle(ctx, "server-id", true) // activate

// List server's tools
tools, _, err := client.Servers.ListTools(ctx, "server-id", nil)

// List server's resources
resources, _, err := client.Servers.ListResources(ctx, "server-id", nil)

// List server's prompts
prompts, _, err := client.Servers.ListPrompts(ctx, "server-id", nil)

// Delete server
_, err = client.Servers.Delete(ctx, "server-id")

注: ServersService不包括MCP协议通信端点(GET /servers/{id}/ssePOST /servers/{id}/message).这些用于MCP协议通信,而不是REST API管理。

管理提示

提示为AI模型提供模板化交互:

ctx := context.Background()

// List prompts
prompts, _, err := client.Prompts.List(ctx, nil)

// List with filtering
opts := &contextforge.PromptListOptions{
    IncludeInactive: true,
    Tags:            "ai,code-review",
    TeamID:          "team-123",
}
prompts, _, err = client.Prompts.List(ctx, opts)

// Create a prompt
newPrompt := &contextforge.PromptCreate{
    Name:        "code-review",
    Description: contextforge.String("Code review prompt template"),
    Template:    "Please review this {{language}} code:\n\n{{code}}",
    Arguments: []contextforge.PromptArgument{
        {Name: "language", Description: contextforge.String("Programming language"), Required: true},
        {Name: "code", Description: contextforge.String("Code to review"), Required: true},
    },
    Tags: []string{"ai", "code-review"},
}

// Create with optional team/visibility settings
createOpts := &contextforge.PromptCreateOptions{
    TeamID:     contextforge.String("team-123"),
    Visibility: contextforge.String("public"),
}
created, _, err := client.Prompts.Create(ctx, newPrompt, createOpts)

// Get rendered prompt with arguments (hybrid REST endpoint)
args := map[string]string{
    "language": "Go",
    "code":     "func main() { fmt.Println(\"Hello\") }",
}
result, _, err := client.Prompts.Get(ctx, "code-review", args)
if err == nil {
    fmt.Printf("Description: %s\n", *result.Description)
    for _, msg := range result.Messages {
        fmt.Printf("Role: %s, Content: %s\n", msg.Role, *msg.Content.Text)
    }
}

// Get prompt without arguments
result, _, err = client.Prompts.GetNoArgs(ctx, "simple-prompt")

// Update prompt (promptID is a string)
update := &contextforge.PromptUpdate{
    Description: contextforge.String("Updated description"),
    Template:    contextforge.String("Updated template: {{new_arg}}"),
}
updated, _, err := client.Prompts.Update(ctx, "prompt-id", update)

// Toggle prompt status
toggled, _, err := client.Prompts.Toggle(ctx, "prompt-id", true) // activate
toggled, _, err = client.Prompts.Toggle(ctx, "prompt-id", false) // deactivate

// Delete prompt
_, err = client.Prompts.Delete(ctx, "prompt-id")

管理代理

A2A(代理到代理)代理通过ContextForge实现跨年龄通信。由于API字段命名约定,代理对于不同的操作具有不同的类型:

  • 代理创建:用于创建代理(使用snake_case: endpoint_url, agent_type)
  • 代理:用于阅读代理(使用camelCase: endpointUrl, agentType)
  • 代理更新:用于更新代理(使用camelCase: endpointUrl, agentType)
ctx := context.Background()

// List agents with skip/limit pagination (not cursor-based)
agents, _, err := client.Agents.List(ctx, &contextforge.AgentListOptions{
    Skip:  0,
    Limit: 20,
})

// List with filtering
opts := &contextforge.AgentListOptions{
    Skip:            10,
    Limit:           50,
    IncludeInactive: true,
    Tags:            "automation,integration",
    TeamID:          "team-123",
    Visibility:      "public",
}
agents, _, err = client.Agents.List(ctx, opts)

// Get agent by ID
agent, _, err := client.Agents.Get(ctx, "agent-id")

// Create a new agent
newAgent := &contextforge.AgentCreate{
    Name:            "data-processor",
    EndpointURL:     "https://agent.example.com/a2a",
    Description:     contextforge.String("Processes data records"),
    AgentType:       "generic",        // Note: snake_case for Create
    ProtocolVersion: "1.0",
    Capabilities: map[string]any{
        "streaming": true,
        "batch":     true,
    },
    Config: map[string]any{
        "timeout": 30,
        "retries": 3,
    },
    AuthType:  contextforge.String("bearer"),
    AuthValue: contextforge.String("secret-token"), // Encrypted by API
    Tags:      []string{"data", "processing"},
}

// Create with optional team/visibility settings
createOpts := &contextforge.AgentCreateOptions{
    TeamID:     contextforge.String("team-123"),
    Visibility: contextforge.String("public"),
}
created, _, err := client.Agents.Create(ctx, newAgent, createOpts)

// Create without options
created, _, err = client.Agents.Create(ctx, newAgent, nil)

// Update agent (uses camelCase fields)
update := &contextforge.AgentUpdate{
    Description:     contextforge.String("Updated description"),
    AgentType:       contextforge.String("specialized"), // Note: camelCase for Update
    ProtocolVersion: contextforge.String("2.0"),
    Tags:            []string{"updated", "enhanced"},
}
updated, _, err := client.Agents.Update(ctx, "agent-id", update)

// Toggle agent status
toggled, _, err := client.Agents.Toggle(ctx, "agent-id", true) // enable
toggled, _, err = client.Agents.Toggle(ctx, "agent-id", false) // disable

// Invoke an agent by name (not ID!)
invokeReq := &contextforge.AgentInvokeRequest{
    Parameters: map[string]any{
        "input": "data to process",
        "options": map[string]any{
            "format":   "json",
            "validate": true,
        },
    },
    InteractionType: "query", // default: "query"
}
result, _, err := client.Agents.Invoke(ctx, created.Name, invokeReq)
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Result: %v\n", result)

// Delete agent
_, err = client.Agents.Delete(ctx, "agent-id")

重要提示:

  • 分页:代理使用跳过/限制(基于偏移量)分页,而不是其他服务使用的基于光标的分页
  • 调用端点:使用代理名称(不是ID)作为标识符
  • 字段命名:AgentCreate使用snake_case,而AgentUpdate使用camelCase
  • 认证:The AuthValue 字段在存储时由API加密
  • 双重状态:代理商两者都有 Enabled (用户控制)和 Reachable (系统状态)状态
  • 性能指标:代理跟踪执行指标,包括成功/失败率和响应时间

管理团队

团队支持协作资源管理和访问控制。团队运营支持成员管理、邀请和团队发现:

ctx := context.Background()

// List teams with skip/limit pagination (not cursor-based)
teams, _, err := client.Teams.List(ctx, &contextforge.TeamListOptions{
    Skip:  0,
    Limit: 20,
})

// Get team by ID
team, _, err := client.Teams.Get(ctx, "team-id")

// Create a basic team
newTeam := &contextforge.TeamCreate{
    Name:        "engineering",
    Description: contextforge.String("Engineering team for product development"),
}
created, _, err := client.Teams.Create(ctx, newTeam)

// Create a team with all options
completeTeam := &contextforge.TeamCreate{
    Name:        "design",
    Slug:        contextforge.String("design-team"), // Always auto-generated from name (API ignores user value)
    Description: contextforge.String("Design team for UI/UX"),
    Visibility:  contextforge.String("public"),      // "private" (default) | "public"
    MaxMembers:  contextforge.Int(50),
}
created, _, err = client.Teams.Create(ctx, completeTeam)

// Update team
update := &contextforge.TeamUpdate{
    Description: contextforge.String("Updated description"),
    Visibility:  contextforge.String("public"),
    MaxMembers:  contextforge.Int(100),
}
updated, _, err := client.Teams.Update(ctx, "team-id", update)

// Delete team
_, err = client.Teams.Delete(ctx, "team-id")

// List team members
members, _, err := client.Teams.ListMembers(ctx, "team-id")

// Add a direct member
member, _, err := client.Teams.AddMember(ctx, "team-id", &contextforge.TeamMemberAdd{
    Email: "user@example.com",
    Role:  "member",
})

// Update member role (uses email as identifier)
memberUpdate := &contextforge.TeamMemberUpdate{
    Role: "owner", // "owner" | "member"
}
member, _, err := client.Teams.UpdateMember(ctx, "team-id", "user@example.com", memberUpdate)

// Remove member (uses email as identifier)
_, err = client.Teams.RemoveMember(ctx, "team-id", "user@example.com")

// Invite a new member
invite := &contextforge.TeamInvite{
    Email: "newuser@example.com",
    Role:  contextforge.String("member"), // Optional, defaults to "member"
}
invitation, _, err := client.Teams.InviteMember(ctx, "team-id", invite)

// List team invitations
invitations, _, err := client.Teams.ListInvitations(ctx, "team-id")

// Accept invitation (using token)
member, _, err := client.Teams.AcceptInvitation(ctx, "invitation-token")

// Cancel invitation
_, err = client.Teams.CancelInvitation(ctx, "invitation-id")

// Discover public teams
discoveredTeams, _, err := client.Teams.Discover(ctx, &contextforge.TeamDiscoverOptions{
    Limit: 10,
})

// Request to join a public team
joinRequest, _, err := client.Teams.Join(ctx, "team-id", &contextforge.TeamJoinRequest{
    Message: contextforge.String("I'd like to contribute to this team"),
})

// Leave a team
_, err = client.Teams.Leave(ctx, "team-id")

// List join requests (owners only)
joinRequests, _, err := client.Teams.ListJoinRequests(ctx, "team-id")

// Approve join request
member, _, err = client.Teams.ApproveJoinRequest(ctx, "team-id", "request-id")

// Reject join request
_, err = client.Teams.RejectJoinRequest(ctx, "team-id", "request-id")

重要提示:

  • 分页:团队使用跳过/限制(基于偏移)分页,如代理
  • 列表响应:返回结构化响应 {teams: [], total: N} 不仅仅是数组
  • 无请求包装:与工具/资源不同,团队创建/更新没有包装
  • 蛞蝓生成:如果未提供,则根据团队名称自动生成
  • 会员身份:成员端点使用电子邮件(不是ID)作为标识符
  • 邀请令牌:接受邀请时使用过期的一次性令牌
  • 个人团队:不能删除或保留;有特殊限制
  • 最后所有者保护:如果是最后一个所有者,则不能离开或降级

分页

ContextForge支持两种分页模式:

基于光标的分页 (工具、资源、网关、服务器、提示):

opts := &contextforge.ToolListOptions{
    ListOptions: contextforge.ListOptions{Limit: 50},
}

for {
    tools, resp, err := client.Tools.List(ctx, opts)
    if err != nil {
        break
    }

    // Process tools
    for _, tool := range tools {
        fmt.Printf("Tool: %s\n", tool.Name)
    }

    // Check for more pages
    if resp.NextCursor == "" {
        break
    }
    opts.Cursor = resp.NextCursor
}

跳过/限制(基于偏移量)分页 (代理人、团队):

opts := &contextforge.AgentListOptions{
    Limit: 50,
}

for skip := 0; ; skip += opts.Limit {
    opts.Skip = skip
    agents, _, err := client.Agents.List(ctx, opts)
    if err != nil {
        break
    }

    // Process agents
    for _, agent := range agents {
        fmt.Printf("Agent: %s\n", agent.Name)
    }

    // Check if we've reached the end
    if len(agents)  0 {
    fmt.Printf("Rate limit: %d/%d remaining\n", resp.Rate.Remaining, resp.Rate.Limit)
}

API方法参考

工具服务

方法说明
List(ctx, opts)具有分页和筛选功能的列表工具
Get(ctx, toolID)按ID获取工具
Create(ctx, tool, opts)使用可选设置创建新工具
Update(ctx, toolID, tool)更新工具
Delete(ctx, toolID)删除工具
Toggle(ctx, toolID, activate)切换工具启用状态

资源服务

方法说明
List(ctx, opts)列出具有分页和筛选功能的资源
Get(ctx, resourceID)获取资源内容(返回MCP兼容 ResourceContent)
Create(ctx, resource, opts)使用可选设置创建新资源
Update(ctx, resourceID, resource)更新资源
Delete(ctx, resourceID)删除资源
Toggle(ctx, resourceID, activate)切换资源活动状态
ListTemplates(ctx)列出可用的资源模板

网关服务

方法说明
List(ctx, opts)列出具有分页和过滤功能的网关
Get(ctx, gatewayID)按ID获取网关
Create(ctx, gateway, opts)使用可选设置创建新网关
Update(ctx, gatewayID, gateway)更新网关
Delete(ctx, gatewayID)删除网关
Toggle(ctx, gatewayID, activate)切换网关活动状态

服务器服务

方法说明
List(ctx, opts)列出具有分页和筛选功能的服务器
Get(ctx, serverID)按ID获取服务器
Create(ctx, server, opts)使用可选设置创建新服务器
Update(ctx, serverID, server)更新服务器
Delete(ctx, serverID)删除服务器
Toggle(ctx, serverID, activate)切换服务器启用状态
ListTools(ctx, serverID, opts)列出与服务器关联的工具
ListResources(ctx, serverID, opts)列出与服务器关联的资源
ListPrompts(ctx, serverID, opts)列出与服务器关联的提示

提示服务

方法说明
List(ctx, opts)带有分页和筛选功能的列表提示
Get(ctx, promptID, args)获取带有参数的呈现提示(返回MCP兼容 PromptResult)
GetNoArgs(ctx, promptID)获取不带参数的呈现提示符(返回MCP兼容 PromptResult)
Create(ctx, prompt, opts)使用可选设置创建新提示
Update(ctx, promptID, prompt)更新提示
Delete(ctx, promptID)删除提示
Toggle(ctx, promptID, activate)切换提示活动状态

代理服务

方法说明
List(ctx, opts)列出具有跳过/限制分页和过滤功能的代理
Get(ctx, agentID)按ID获取代理
Create(ctx, agent, opts)使用可选设置创建新代理
Update(ctx, agentID, agent)更新代理
Delete(ctx, agentID)删除代理
Toggle(ctx, agentID, activate)切换代理启用状态
Invoke(ctx, agentName, req)按名称和参数调用代理

注: 代理使用跳过/限制(基于偏移量)分页,而不是基于光标的分页。Invoke方法使用代理名称(而不是ID)作为标识符。

团队服务

方法说明
List(ctx, opts)列出具有跳过/限制分页的团队
Get(ctx, teamID)按ID获取团队
Create(ctx, team)创建新团队
Update(ctx, teamID, team)更新团队
Delete(ctx, teamID)删除团队
ListMembers(ctx, teamID)列出团队成员
AddMember(ctx, teamID, add)通过电子邮件直接添加成员
UpdateMember(ctx, teamID, email, update)更新成员角色(使用电子邮件)
RemoveMember(ctx, teamID, email)删除成员(使用电子邮件)
InviteMember(ctx, teamID, invite)邀请用户加入团队
ListInvitations(ctx, teamID)列出团队邀请
AcceptInvitation(ctx, token)接受邀请(使用令牌)
CancelInvitation(ctx, invitationID)取消邀请
Discover(ctx, opts)发现公共团队
Join(ctx, teamID, req)申请加入公共团队
Leave(ctx, teamID)离开团队
ListJoinRequests(ctx, teamID)列出加入请求(仅限所有者)
ApproveJoinRequest(ctx, teamID, reqID)批准加入请求
RejectJoinRequest(ctx, teamID, reqID)拒绝加入请求

注: 团队使用跳过/限制(基于偏移)分页,就像代理一样。列表返回结构化响应 {teams: [], total: N}。成员操作使用电子邮件作为标识符,而不是ID。

例子

SDK包括演示所有服务功能的工作示例程序:

每个示例都包含一个模拟HTTP服务器,并演示了:

  • 身份验证流程
  • CRUD操作
  • 分页模式(光标或跳过/限制)
  • 过滤和查询
  • 错误处理
  • 服务特定功能

运行任何示例:

go run examples/tools/main.go
go run examples/agents/main.go

发展

运行测试

# Unit tests
make test
# or
go test ./...

# Unit tests with coverage
make test-cover

# Integration tests (requires ContextForge running)
make integration-test-setup  # Start ContextForge gateway
make integration-test        # Run integration tests
make integration-test-teardown  # Stop gateway

# Full integration test cycle
make integration-test-all

# Run both unit and integration tests
make test-all

# Generate HTML coverage report
make coverage

集成测试配置

集成测试需要环境变量:

# Required to enable integration tests
export INTEGRATION_TESTS=true

# Optional configuration (defaults shown)
export CONTEXTFORGE_ADDR="http://localhost:8000/"
export CONTEXTFORGE_ADMIN_EMAIL="admin@test.local"
export CONTEXTFORGE_ADMIN_PASSWORD="testpassword123"

建筑

# Build all packages
make build

# Build with formatting and linting
make check

# Format code
make fmt

# Lint
make vet

# Full CI pipeline
make ci

可用生成目标

发展:

  • make deps -下载依赖项
  • make fmt -使用gofmt格式化代码
  • make vet -快跑兽医
  • make lint -格式和审查
  • make test -运行单元测试
  • make test-verbose -运行具有详细输出的单元测试
  • make test-cover -运行覆盖率的单元测试
  • make build -构建所有包
  • make clean -清理构建工件
  • make coverage -生成HTML覆盖率报告
  • make ci -完整的CI管道(拆卸、拆卸、测试、构建)

测试:

  • make integration-test-setup -启动ContextForge网关
  • make integration-test -运行集成测试
  • make integration-test-teardown -停止网关
  • make integration-test-all -完整的集成测试周期
  • make test-all -运行单元和集成测试

释放:

  • make goreleaser-check -验证GoRelease配置
  • make goreleaser-snapshot -本地测试发布,不发布
  • make release-check -验证发布先决条件
  • make release-patch -准备补丁发布(自动增量补丁版本)
  • make release-minor -准备次要版本(自动递增次要版本)
  • make release-major -准备主要版本(自动递增主要版本)
  • make release-prep VERSION=vX.Y.Z -准备发布特定版本
  • make release -完整的发布准备工作流程

代理审查管道

该存储库包括一个上游形状的、CI辅助的采用 代理审查管道。它在以下位置安装提示资产 agents/,手册 操作员入口点 commands/review_pr.md,仅stdlib下的辅助脚本 scripts/,以及两个用于记分簿记录和 反映循环建议PR。

手动入口点

使用 commands/review_pr.md 作为人为操作的合同 /review_pr 命令。当前的集成首先是手动的:它标准化了工件名称 例如 coordinator-report.mdverify-feedback.json,但还没有 包括一个自动PR审查执行器。

工作流和权限

存储库现在包括:

  • .github/workflows/record-run.yml
  • .github/workflows/reflect-and-propose.yml

所需的工作流权限:

  • contents: write
  • pull-requests: write
  • models: read

record-run.yml 设计严格:它只附加到 data/pipeline-runs.jsonl 当一个真实 coordinator-report.md 人工制品是 可用。在手动或自动审查执行器上传这些工件之前, 记分簿工作流将完全跳过,反射循环将保持不变 休眠的。

可选存储库引导

如果需要调整存储库操作设置,请使用 scripts/configure_actions_permissions.py 带有repo管理令牌。这是一个 可选的引导助手,不是正常开发或发布流程的一部分。

释放

该项目使用语义版本控制,并包括自动发布工具来简化发布过程。

先决条件:

  go install github.com/goreleaser/goreleaser/v2@latest
  • GitHub代币 -设置 GITHUB_TOKEN GitHub发布创建的环境变量

- 在以下位置创建令牌:https://github.com/settings/tokens/new - 所需范围: repo (完全访问存储库) - 添加到您的shell配置文件: export GITHUB_TOKEN=your_token_here

语义版本碰撞

发布工作流支持自动语义版本跳转:

# Patch release (0.1.0 → 0.1.1) - bug fixes, no API changes
make release-patch

# Minor release (0.1.0 → 0.2.0) - new features, backward compatible
make release-minor

# Major release (0.1.0 → 1.0.0) - breaking changes
make release-major

手动版本覆盖

您还可以手动指定版本:

make release-prep VERSION=v0.2.5

发布工作流

每个释放命令执行以下步骤:

  1. 先决条件检查:确保git工作目录干净,并且安装了goreleaser
  2. 版本计算:根据中的当前版本确定新版本 contextforge/version.go
  3. 更新版本常量:更新 contextforge/version.go 使用新版本
  4. 创建提交:提交版本更改并显示消息 release: prepare vX.Y.Z
  5. 创建标签:为发布创建带注释的git标签
  6. 运行GoRelease:执行 goreleaser release --clean 其中:

- 从常规提交更新CHANGELOG.md - 创建带有发布说明的GitHub发布草案

  1. 人工审核:在GitHub上查看发布草案,并在本地更改CHANGELOG.md
  2. 发布:准备就绪后,推送commit和标签,然后在GitHub上发布发布草稿

注: GoReleaser在发布之前创建一个草稿版本供审查。更改日志是使用传统提交格式从提交消息中自动生成的。

推动发布

运行release命令后,按下更改:

# Push commit and tag
git push && git push --tags

# Then create a GitHub release at:
# https://github.com/leefowlercu/go-contextforge/releases/new?tag=vX.Y.Z

版本管理

  • SDK版本:定义见 contextforge/version.go 作为 Version 恒定
  • 用户代理:自动包含SDK版本(go-contextforge/vX.Y.Z)
  • 更新日志:使用GoReleaser从常规提交中自动生成,如下所示 保存变更日志 格式
  • Git标签:使用格式 vX.Y.Z (语义版本控制 v 前缀)
  • 提交格式:所有提交都应该使用 常规承诺 格式(例如。, feat:, fix:, docs:)

变更日志生成

该项目使用 GoRelease 根据提交消息自动生成更改日志。Changelog的生成在发布工作流程中自动进行,并在Changelog.md和GitHub发布说明中创建条目。

测试GoRelease配置:

# Validate GoReleaser configuration
make goreleaser-check

# Test release locally without publishing
make goreleaser-snapshot

配置 (.goreleaser.yaml):

  • 使用GitHub的原生变更日志生成
  • 按常规提交类型进行组提交
  • 不包括合并提交和发布准备提交
  • 创建GitHub发布草案以供手动审查

提交类型映射到变更日志部分:

  • feat: → Added
  • fix:, bug: → Fixed
  • refactor: → 改变
  • docs: → 文档
  • build:, chore: → Build
  • test:, style: → Tests

撤消发布准备

如果需要撤消发布准备(在按下之前):

# Remove the tag
git tag -d vX.Y.Z

# Reset the commit
git reset --hard HEAD~1

建筑

此SDK遵循由 ,将API端点组织到逻辑服务组中:

  • 客户 -HTTP客户端管理和JWT身份验证的主要入口点
  • 工具服务 -所有与工具相关的操作
  • 资源服务 -所有与资源相关的操作
  • 网关服务 -所有与网关相关的操作
  • 服务器服务 -所有与服务器相关的操作和关联
  • Prompts服务 -所有及时的管理操作
  • 代理服务 -所有A2A代理操作、调用和性能跟踪
  • 团队服务 -团队管理、成员、邀请和发现
  • 取消服务 -请求取消飞行和取消状态检查

自定义类型

  • 灵活ID -处理API不一致,其中ID可能以整数或字符串形式返回
  • 时间戳 -不带时区信息的API响应的自定义时间戳解析
  • 标签 -使用以下方式处理标记对象 IDLabel 领域;自定义JSON封送/解封送以实现API兼容性
  • 指针助手 - String(), Int(), Bool(), Time() 用于处理可选字段
  • 标签助手 - NewTags(), NewTag(), TagNames() 用于转换 []string[]Tag

链接

  • ContextForge存储库: https://github.com/IBM/mcp-context-forge
  • MCP协议: https://modelcontextprotocol.io/
  • A2A协议规范: https://a2a-protocol.org/latest/specification/
  • A2A协议网站: https://a2aprotocol.ai/

已知问题

上游ContextForge API Bug

SDK集成测试目前记录了几个上游ContextForge API错误。这些bug存在于上游API中,而不是SDK实现中。跳过受影响的测试,一旦上游修复成功,将重新启用;请参阅链接的报告,了解每个问题的最新验证版本。

CONTEXTFORGE-001:切换端点返回停滞状态POST /prompts/{id}/togglePOST /resources/{id}/toggle 端点返回陈旧 isActive 尽管正确更新了数据库,但仍处于状态。看 docs/upstream-bugs/contextforge-001-prompt-toggle.md.

CONTEXTFORGE-002:提示API接受空模板字段POST /prompts 终结点接受无需 template 字段,允许语义无效的提示。看 docs/upstream-bugs/contextforge-002-prompt-validation-missing-template.md.

CONTEXTFORGE-005:Teams API忽略用户提供的Slug字段POST /teams 端点忽略 slug 字段,并始终根据团队名称自动生成。看 docs/upstream-bugs/contextforge-005-teams-slug-ignored.md.

CONTEXTFORGE-008:代理承载身份字段名称不匹配 A2A代理API仍然期望 auth_token 用于承载身份验证,而不是SDK auth_value 现场。看 docs/upstream-bugs/contextforge-008-agent-auth-field-name.md.

CONTEXTFORGE-010:团队ID筛选器返回权限错误 工具列表API仍然返回 403 对于一些应该成功的团队范围的过滤器组合。看 docs/upstream-bugs/contextforge-010-team-id-filter-permission-error.md.

在当前RC1验证中已解决: CONTEXTFORGE-004 团队端点身份验证失败不再重现。历史和已解决的报告仍在 docs/upstream-bugs/.

所有错误报告都包括根本原因分析、建议的解决方案和变通方法。

许可证

MIT许可证-请参阅 许可证 文件以获取详细信息。

目录标签

目录标签

GoCursor多协议支持AI接口管理本地部署资源管理代理通信团队协作

支持客户端

Cursor

接入字段

传输方式(transport,传输协议)

未说明

鉴权方式(authType,认证方式)

token

工具数量(toolCount,工具数)

0

资源数量(resourceCount,资源数)

0

提示词数量(promptCount,提示词数)

0

权限和风险

未说明token部署方式未说明

接入前请确认传输方式、认证方式和部署位置,并根据实际工具能力限制访问范围。

安装前确认

不要直接授予不必要的文件、网络或账号权限;先核对安装命令和配置内容。

仍需确认:installCommand

来源信息

继续浏览同类 MCP