Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,13 @@ clients/python/src/mr_openapi/models/serving_environment_list.py linguist-genera
clients/python/src/mr_openapi/models/serving_environment_update.py linguist-generated=true
clients/python/src/mr_openapi/models/sort_order.py linguist-generated=true
clients/python/src/mr_openapi/rest.py linguist-generated=true
cmd/catalog-gen/gen_manifests.go linguist-generated=true
cmd/catalog-gen/templates/api/openapi_components.gotmpl linguist-generated=true
cmd/catalog-gen/templates/catalog/loader.gotmpl linguist-generated=true
cmd/catalog-gen/templates/models/artifact.gotmpl linguist-generated=true
cmd/catalog-gen/templates/models/entity.gotmpl linguist-generated=true
cmd/catalog-gen/templates/service/artifact_repository.gotmpl linguist-generated=true
cmd/catalog-gen/templates/service/spec.gotmpl linguist-generated=true
internal/converter/generated/embedmd_openapi_converter.gen.go linguist-generated=true
internal/converter/generated/openapi_converter.gen.go linguist-generated=true
internal/converter/generated/openapi_embedmd_converter.gen.go linguist-generated=true
Expand Down
149 changes: 149 additions & 0 deletions cmd/catalog-gen/add_provider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package main

import (
"fmt"
"path/filepath"
"strings"

"github.com/spf13/cobra"
)

func newAddProviderCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "add-provider <type>",
Short: "Add a new provider type to the catalog",
Long: `Add a new provider type to the catalog configuration.

Supported provider types:
- yaml: File-based provider using YAML catalog files
- http: HTTP-based provider for remote APIs

Example:
catalog-gen add-provider yaml
catalog-gen add-provider http`,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
providerType := args[0]

switch providerType {
case "yaml", "http":
// OK
default:
return fmt.Errorf("unsupported provider type: %s (supported: yaml, http)", providerType)
}

return addProvider(providerType)
},
}

return cmd
}

func addProvider(providerType string) error {
config, err := loadConfig()
if err != nil {
return err
}

// Check if provider already exists
for _, p := range config.Spec.Providers {
if p.Type == providerType {
fmt.Printf("Provider '%s' already exists in catalog.yaml\n", providerType)
return nil
}
}

// Add provider
config.Spec.Providers = append(config.Spec.Providers, ProviderConfig{Type: providerType})

// Save config
if err := saveConfig(config); err != nil {
return err
}

// Generate provider file
if err := generateProviderFile(config.Spec.Entity.Name, providerType); err != nil {
return err
}

fmt.Printf("Added provider '%s' to catalog.yaml\n", providerType)
fmt.Printf("Generated provider file at internal/catalog/providers/%s_provider.go\n", providerType)

return nil
}

func newAddArtifactCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "add-artifact <name>",
Short: "Add a new artifact type to the catalog",
Long: `Add a new artifact type to the catalog configuration.

Example:
catalog-gen add-artifact Tool
catalog-gen add-artifact Resource`,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
artifactName := args[0]
return addArtifact(artifactName)
},
}

return cmd
}

func addArtifact(artifactName string) error {
config, err := loadConfig()
if err != nil {
return err
}

// Check if artifact already exists
for _, a := range config.Spec.Artifacts {
if a.Name == artifactName {
fmt.Printf("Artifact '%s' already exists in catalog.yaml\n", artifactName)
return nil
}
}

// Add artifact
config.Spec.Artifacts = append(config.Spec.Artifacts, ArtifactConfig{
Name: artifactName,
Properties: []PropertyConfig{
{Name: "uri", Type: "string"},
},
})

// Save config
if err := saveConfig(config); err != nil {
return err
}

// Generate artifact model stub file
if err := generateArtifactModelStub(artifactName); err != nil {
return err
}

fmt.Printf("Added artifact '%s' to catalog.yaml\n", artifactName)
fmt.Printf("Generated artifact model at internal/db/models/%s.go\n", strings.ToLower(artifactName))
fmt.Println("\nRun 'catalog-gen generate' to generate the full artifact implementation.")

return nil
}

func generateArtifactModelStub(artifactName string) error {
lowerName := strings.ToLower(artifactName)
data := map[string]any{
"EntityName": "",
"ArtifactName": artifactName,
"LowerEntityName": "",
"LowerArtifactName": lowerName,
"Properties": "\tURI *string\n",
}

modelsDir := filepath.Join("internal", "db", "models")
if err := ensureDir(modelsDir); err != nil {
return fmt.Errorf("failed to create models directory: %w", err)
}

return executeTemplate(TmplModelsArtifact, filepath.Join(modelsDir, fmt.Sprintf("%s.go", lowerName)), data)
}
145 changes: 145 additions & 0 deletions cmd/catalog-gen/docs/skills-and-commands.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# catalog-gen Skills & Commands Reference

This document describes the AI agent skills and slash commands generated by `catalog-gen generate` for each catalog project.

## Overview

When you run `catalog-gen generate`, it creates two directories in the generated catalog:

- `.claude/commands/` - Slash commands that can be invoked directly (e.g., `/run-local`)
- `.claude/skills/` - Detailed skill files with step-by-step instructions

## Generated Commands

### Development Workflow

| Command | File | Description |
|---------|------|-------------|
| `/add-property` | `add-property.md` | Add a new property to the entity. Guides through updating catalog.yaml, regenerating, and updating converters. |
| `/add-artifact` | `add-artifact.md` | Add a new artifact type. Guides through updating catalog.yaml, regenerating, and running /implement-artifacts. |
| `/add-provider` | `add-provider.md` | Add a new data provider (http, grpc, s3, etc.). Creates provider file and registers it. |
| `/regenerate` | `regenerate.md` | Regenerate code from catalog.yaml and fix any resulting build issues. |
| `/implement-artifacts` | `implement-artifacts.md` | Implement missing artifact support after adding artifacts to catalog.yaml. |
| `/fix-build` | `fix-build.md` | Diagnose and fix compilation errors. |

### Testing & Debugging

| Command | File | Description |
|---------|------|-------------|
| `/run-local` | `run-local.md` | Start the catalog server locally for testing. Includes port, base URL, and quick test curl. |
| `/test-api` | `test-api.md` | Generate curl commands to test all API endpoints including pagination and artifacts. |
| `/seed-data` | `seed-data.md` | Populate sample-catalog.yaml and artifacts.yaml with test data. |

## Generated Skills

Skills provide detailed, step-by-step instructions with code snippets customized for the specific catalog.

| Skill File | Purpose |
|------------|---------|
| `README.md` | Master reference listing all commands, workflows, and common scenarios |
| `add-property.md` | Step-by-step guide for adding entity properties with code examples |
| `add-artifact.md` | Step-by-step guide for adding artifact types |
| `add-provider.md` | Step-by-step guide for adding data providers with template code |
| `implement-artifacts.md` | Exact code snippets for implementing artifact support (NewServices, API methods, conversions) |
| `test-api.md` | Curl commands for testing all endpoints (list, get, pagination, artifacts) |
| `seed-data.md` | Sample data templates for entities and artifacts |

## Customization

All generated files are customized with:

- **Entity name** (e.g., `McpServer`)
- **Artifact names** (e.g., `Tool`)
- **Catalog name** (e.g., `mcp-catalog`)
- **API port** (e.g., `8081`)
- **Property names and types**
- **File paths** specific to the catalog

## Common Workflows

### Adding a New Property

```
/add-property version string
```

This guides you through:
1. Updating `catalog.yaml`
2. Running `catalog-gen generate`
3. Updating repository converter
4. Updating OpenAPI service implementation
5. Updating YAML provider

### Adding a New Artifact

```
/add-artifact License
```

This guides you through:
1. Updating `catalog.yaml` with artifact definition
2. Running `catalog-gen generate`
3. Running `/implement-artifacts` to complete integration

### Testing the API

```
/seed-data
/run-local
/test-api
```

### Fixing Build Errors

```
/fix-build
```

Or for artifact-specific errors:

```
/implement-artifacts
```

## File Structure

After running `catalog-gen generate`, the catalog will have:

```
<catalog>/
├── .claude/
│ ├── commands/
│ │ ├── add-property.md
│ │ ├── add-artifact.md
│ │ ├── add-provider.md
│ │ ├── regenerate.md
│ │ ├── implement-artifacts.md
│ │ ├── fix-build.md
│ │ ├── run-local.md
│ │ ├── test-api.md
│ │ └── seed-data.md
│ └── skills/
│ ├── README.md
│ ├── add-property.md
│ ├── add-artifact.md
│ ├── add-provider.md
│ ├── implement-artifacts.md
│ ├── test-api.md
│ └── seed-data.md
├── CLAUDE.md # Main context file for AI agents
└── docs/
└── post-artifact-generation.md
```

## Integration with Claude Code

These files are automatically recognized by Claude Code:

- **CLAUDE.md** - Loaded as project context
- **`.claude/commands/*.md`** - Available as slash commands
- **`.claude/skills/*.md`** - Referenced by commands for detailed instructions

When an AI agent is working in the catalog directory, it can:
1. Read CLAUDE.md for overall project context
2. Use slash commands for common tasks
3. Follow skill files for detailed implementation steps
Loading
Loading