Imported from bivex/ZenTaoMcp (
AGENTS.md). Install upstream withnpx skills add bivex/ZenTaoMcp. Copyright stays with the author.
Agent Guide for ZenTao MCP Server
This document helps AI agents work effectively with this ZenTao MCP Server codebase.
Project Overview
This is a Go-based Model Context Protocol (MCP) server that provides integration between LLM applications and the ZenTao project management system. The server communicates via stdio and exposes MCP tools and resources for managing products, projects, stories, tasks, bugs, test cases, and more.
- Language: Go 1.23.2
- Core Library:
github.com/mark3labs/mcp-gov0.4.0 - Communication: stdio (MCP protocol)
- Purpose: Bridge LLMs to ZenTao REST API
Essential Commands
Build and Run
# From project root
cd src
go mod download # Download dependencies
go build # Build the binary
./mcp-server # Run the server
Environment Variables
ZENTAO_BASE_URL(optional): Default ishttp://localhost:8080
Current Build Issues
IMPORTANT: The codebase has build errors with the current MCP library version (v0.4.0). The errors indicate API incompatibilities:
mcp.NewResourceis undefinedmcp.WithResourceDescriptionandmcp.WithMIMETypeare undefineds.AddResourcefails - MCPServer is a pointer to interface, not interfacemcp.TextResourceContentsstruct cannot be used asmcp.ResourceContentsvaluemcp.NewToolis undefined in tools/
These suggest the MCP library API has changed. Check the library documentation for the correct API before attempting to fix.
Project Structure
/Volumes/External/Code/ZenTaoMcp
├── src/
│ ├── main.go # Entry point - server initialization
│ ├── client/
│ │ └── client.go # ZenTao HTTP client with auth
│ ├── tools/ # MCP tools (one file per entity)
│ │ ├── auth.go # Authentication tools
│ │ ├── products.go # Product CRUD tools
│ │ ├── projects.go # Project and execution tools
│ │ ├── stories.go # User story tools
│ │ ├── tasks.go # Task tools
│ │ ├── bugs.go # Bug tracking tools
│ │ ├── testcases.go # Test case tools
│ │ ├── plans.go # Release planning tools
│ │ ├── builds.go # Build/release tools
│ │ ├── users.go # User management tools
│ │ ├── feedbacks.go # Customer feedback tools
│ │ └── tickets.go # Ticket management tools
│ ├── resources/ # MCP resources (data access)
│ │ ├── entities.go # Resource URI helper
│ │ ├── products.go # Product resources
│ │ └── (other resources)
│ ├── go.mod
│ └── go.sum
├── api_doc.txt # Complete ZenTao API documentation
├── README.md # User-facing documentation
└── LICENSE.md # MIT License
Code Conventions and Patterns
Copyright Header
Every source file MUST include this copyright header:
// Copyright (c) 2026 Bivex
//
// Author: Bivex
// Contact: support@b-b.top
//
// For up-to-date contact information:
// https://github.com/bivex
//
//
// Licensed under the MIT License.
// Commercial licensing available upon request.
Note: Some files have slight variations ("Licensed under MIT License" vs "Licensed under the MIT License"), but maintain the pattern.
Tool Registration Pattern
Tools are organized by entity type. Each file has a Register[Entity]Tools function:
func RegisterProductTools(s *server.MCPServer, client *client.ZenTaoClient) {
createProductTool := mcp.NewTool("create_product",
mcp.WithDescription("Create a new product in ZenTao"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Product name"),
),
// ... more parameters
)
s.AddTool(createProductTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
args := request.GetArguments()
// Process arguments
resp, err := client.Post("/products", body)
if err != nil {
return mcp.NewToolResultError(fmt.Sprintf("Failed to create product: %v", err)), nil
}
return mcp.NewToolResultText(string(resp)), nil
})
}
Tool Parameter Handling
All parameters from MCP come as map[string]interface{}. Types need explicit conversion:
args := request.GetArguments()
// String parameter
name := args["name"].(string)
// Number parameter (MCP sends numbers as float64)
id := int(args["id"].(float64))
// Optional parameters - check existence
if v, ok := args["program"]; ok && v != nil {
body["program"] = int(v.(float64))
}
Resource Registration Pattern
Resources expose data via URIs. Each has a URI pattern and handler:
func RegisterProductResources(s *server.MCPServer, client *client.ZenTaoClient) {
productListResource := mcp.NewResource(
"zentao://products",
"ZenTao Product List",
mcp.WithResourceDescription("List of all products in ZenTao"),
mcp.WithMIMEType("application/json"),
)
s.AddResource(productListResource, func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
resp, err := client.Get("/products")
if err != nil {
return nil, fmt.Errorf("failed to get products: %w", err)
}
return []mcp.ResourceContents{
mcp.TextResourceContents{
Uri: "zentao://products",
MimeType: "application/json",
Text: string(resp),
},
}, nil
})
}
URI Pattern Extraction
Resources use {id} placeholders. The extractIDFromURI helper in resources/entities.go extracts IDs:
func extractIDFromURI(uri, resourceType string) string {
re := regexp.MustCompile(fmt.Sprintf("%s/([^/]+)", resourceType))
matches := re.FindStringSubmatch(uri)
if len(matches) > 1 {
return matches[1]
}
return ""
}
Usage:
id := extractIDFromURI(request.Params.Uri, "products")
resp, err := client.Get(fmt.Sprintf("/products/%s", id))
Client API Usage
The ZenTaoClient in client/client.go handles HTTP requests with automatic token injection:
// Authentication
token, err := client.GetToken(account, password)
// GET request
resp, err := client.Get("/products")
// POST request
resp, err := client.Post("/products", body)
// PUT request
resp, err := client.Put(fmt.Sprintf("/product/%d", id), body)
// DELETE request
resp, err := client.Delete(fmt.Sprintf("/product/%d", id))
All requests automatically include the Token header if authenticated.
ZenTao API Integration
API Documentation
The complete ZenTao REST API is documented in api_doc.txt. This contains:
- 82 API endpoints
- All request/response schemas
- Required vs optional parameters
- Example requests
Refer to this file when adding new tools or resources.
Authentication Flow
- Client calls
/tokensendpoint with account/password - Response contains a token
- Token is stored in
ZenTaoClient.Token - All subsequent requests include
Tokenheader
Common API Patterns
- Lists:
GET /{entity}- Returns array - Details:
GET /{entity}/{id}- Returns single object - Create:
POST /{entity}- Body with fields - Update:
PUT /{entity}/{id}- Partial updates accepted - Delete:
DELETE /{entity}/{id}
Adding New Features
Adding a New Tool
- Create or edit file in
tools/directory - Follow naming:
Register[Entity]Tools(s, client) - Define tool with
mcp.NewTool(), parameters withmcp.WithString/Number/etc. - Add handler function that:
- Extracts arguments
- Builds request body
- Calls
client.Get/Post/Put/Delete() - Returns
mcp.NewToolResultText()ormcp.NewToolResultError()
- Register in
main.goinregisterTools()function
Adding a New Resource
- Create or edit file in
resources/directory - Follow naming:
Register[Entity]Resources(s, client) - Define resource with
mcp.NewResource(uri, name, options) - Add handler that:
- Extracts ID from URI if needed
- Calls
client.Get() - Returns
[]mcp.ResourceContentswithmcp.TextResourceContents
- Register in
main.goinregisterResources()function
API Endpoints to Consider
Based on api_doc.txt, potential additions include:
- Programs (project sets)
- Test tasks
- Releases
- More query parameters for filtering
Important Gotchas
- Type Conversions: MCP always sends numbers as
float64. Always cast tointfor IDs. - Optional Parameters: Use pattern
if v, ok := args["param"]; ok && v != nilto check optional params. - URI IDs: String IDs from URIs need to be used as strings in API paths (
/products/%s), not integers. - Response Formatting: All responses are returned as string via
mcp.NewToolResultText(string(resp)). - Error Handling: Use
fmt.Errorf("failed to X: %w", err)for resource errors, andmcp.NewToolResultError(fmt.Sprintf("Failed to X: %v", err))for tool errors. - Enum Values: Use
mcp.Enum("value1", "value2")to restrict parameter values. - Array Parameters: Use
mcp.WithArray()for array-type parameters. - Resource URIs: Follow pattern
zentao://{entity}/{id}orzentao://{entity}/{id}/{subentity}. - Build Errors: Current code doesn't build due to MCP library API changes. Don't attempt to run tests without fixing the build first.
Testing
Note: No test files (*_test.go) exist in the codebase. No CI configuration found.
When adding tests:
- Place test files next to source (e.g.,
tools/products_test.go) - Use Go's
testingpackage - Mock the
ZenTaoClientfor HTTP calls
Dependencies
From go.mod:
github.com/mark3labs/mcp-gov0.4.0 - MCP protocol implementation- Standard library only for everything else (net/http, encoding/json, fmt, etc.)
No third-party HTTP libraries - uses net/http directly.
File Organization Summary
| Directory | Purpose |
|---|---|
src/client/ |
HTTP client with automatic auth token management |
src/tools/ |
MCP tools (one file per domain entity) |
src/resources/ |
MCP resources (data access via URIs) |
src/main.go |
Server initialization, tool/resource registration |
api_doc.txt |
ZenTao REST API reference (82 endpoints) |
README.md |
User documentation |
Common Workflows
Adding CRUD for New Entity
- Check
api_doc.txtfor endpoint details - Create
src/tools/newentity.gowithRegisterNewEntityTools() - Create
src/resources/newentity.gowithRegisterNewEntityResources() - Add both registrations in
src/main.go - Add documentation in
src/README.md
Fixing Build Errors
- Check MCP library version and documentation
- Identify changed APIs (likely
NewTool,NewResource,AddResource,AddTool) - Update all tool and resource definitions to match new API
- Test build with
go build
Debugging
Since server communicates via stdio, debugging requires:
- Add logging to see what's happening
- Use MCP client to send requests
- Check responses in stderr/stdout
- Ensure ZenTao instance is running and accessible
License
MIT License. Commercial licensing available upon request.