This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This is a Go-based MCP (Model Context Protocol) server that provides AI assistants with programmatic access to Linkwarden instances. The server implements a modular toolset system for managing bookmark collections, links, tags, searching, and accessing public collections.
# Build the project
make build
# Run tests
make test
# Run linter (requires golangci-lint)
make lint
# Format code
make fmt
# Generate SDK from OpenAPI specification
make generate-sdk
# Install dependencies
make install-deps
# Development workflow
make dev # Clean, generate SDK, and build# Run all tests
make test
# Run unit tests only
make test-unit
# Run integration tests
make test-integration# Build binary
make build
# Clean build artifacts
make clean
# Build and install to GOPATH
make install-
MCP Server (
cmd/linkwarden-mcp-server/main.go)- Entry point with Cobra CLI
- Configuration management using Viper
- Stdio transport implementation
- Signal handling and graceful shutdown
-
Toolset System (
pkg/toolsets/)- Modular organization of functionality
- Read/write separation for safety
- Selective toolset enabling
- Global read-only mode support
-
Tool Implementation (
pkg/linkwardenmcp/)- Individual MCP tools with validation
- Type-safe parameter handling
- Linkwarden API integration
- Comprehensive error handling
-
API Client (
pkg/linkwarden/)- Auto-generated from OpenAPI spec
- Type-safe HTTP client
- Authentication handling
- Toolset Registration: Tools are organized into toolsets (
search,collection,link,tags) that can be selectively enabled - Parameter Validation: Comprehensive validation system in
tools_param.gowith type safety - Read/Write Separation: Each toolset supports read-only mode for production safety
- Configuration Flexibility: Supports command-line flags, environment variables, and config files
- Observability: Structured logging with context-aware logging
--base-url/LINKWARDEN_BASE_URL: Linkwarden instance URL--token/LINKWARDEN_TOKEN: API token
--toolsets/TOOLSETS: Comma-separated toolsets to enable--read-only/READ_ONLY: Enable read-only mode--log-file/LOG_FILE: Path to log file
- Default values
- Environment variables
- Command line flags (highest priority)
Read Tools:
get_all_collections: List all collectionsget_collection_by_id: Get collection by IDget_public_collections_links: Get links from public collectionsget_public_collections_tags: Get tags from public collectionsget_public_collection_by_id: Get public collection by ID
Write Tools:
create_collection: Create new collectiondelete_collection_by_id: Delete collection
Read Tools:
get_all_links: Retrieve all links with filtering and paginationget_link_by_id: Get specific link details
Write Tools:
create_link: Create new links with metadata and tagsdelete_link_by_id: Delete existing linksdelete_links: Delete multiple links by IDsarchive_link: Archive links by ID
Read Tools:
get_all_tags: Retrieve all tags
Write Tools:
delete_tag_by_id: Delete tag by ID
search_links: Search links with filtering and pagination
- Create Tool Implementation in
pkg/linkwardenmcp/ - Use Validation System from
tools_param.go - Register in Toolset in
tools.go - Update Documentation in
docs/tools-reference.md
func NewTool(obs *observability.Observability, client *linkwarden.ClientWithResponses) mcpgo.Tool {
params := []mcpgo.ToolParameter{
mcpgo.WithString("name", mcpgo.Description("Parameter description")),
}
handler := func(ctx context.Context, req mcpgo.CallToolRequest) (*mcpgo.ToolResult, error) {
args := make(map[string]interface{})
validator := NewValidator(&req)
validator.ValidateAndAddRequiredString(args, "name")
if result, err := validator.HandleErrorsIfAny(); result != nil {
return result, err
}
// API call logic
resp, err := client.SomeApiCallWithResponse(ctx, args["name"].(string))
if err != nil {
return mcpgo.NewToolResultError("API call failed: " + err.Error()), nil
}
return mcpgo.NewToolResultJSON(resp.JSON200), nil
}
return mcpgo.NewTool("tool_name", "Tool description", params, handler)
}The Linkwarden API client is auto-generated from OpenAPI specification:
# Generate SDK
make generate-sdk
# The generation uses oapi-codegen with configuration in:
# - linkwarden.codegen.yaml
# - api/linkwarden.openapi.yaml- Prerequisites: Go 1.23+, Make, Linkwarden instance
- Setup:
make install-deps - Configuration: Copy
.env.exampleand configure your instance - Development:
make dev
- Unit Tests: Test individual tool functions with mocks
- Integration Tests: Test against real Linkwarden instance (requires
TEST_BASE_URL) - Parameter Validation: Comprehensive validation testing
- Error Handling: Test error scenarios and edge cases
- Formatting: Use
make fmtfor consistent formatting - Linting: Use
make lint(requires golangci-lint) - Testing: Maintain high test coverage
- Documentation: Update documentation for new features
The server uses stdio transport for MCP communication. Common deployment patterns:
- Claude Desktop: Configure in
claude_desktop_config.json - Development: Run with
make run - Production: Use read-only mode and proper logging
- Token Security: Never commit API tokens, use environment variables
- Read-Only Mode: Enable in production for safety
- Input Validation: All parameters are validated before API calls
- Error Handling: Sensitive information is not exposed in error messages