Skip to content

feat: Built-in role-based profiles (junior-dev, senior-dev, devops, team-lead, pm, admin, ci, readonly) #55

@polaz

Description

@polaz

Summary

Create 9 built-in role-based presets that provide optimized tool sets for different user personas. Each preset minimizes LLM context usage while providing sufficient tools for the role.

IMPORTANT: These are PRESETS, not profiles. Presets contain only settings/restrictions, NO host or auth. Connection settings come from environment variables (GITLAB_API_URL, GITLAB_TOKEN).

Motivation

Based on GitLab Personas and typical workflow patterns, different roles need different tool subsets:

  • Junior developers don't need pipeline management
  • PMs don't need code operations
  • DevOps don't need issue tracking
  • CI bots need minimal tools
  • gitlab.com users need rate-limit friendly defaults

Reducing tool count improves LLM performance and reduces token usage.

Preset Format

Location: src/profiles/builtin/*.yaml

SECURITY: Presets NEVER contain host or auth to prevent accidental requests to wrong GitLab instances during testing.

# Example preset structure
description: "Role description"
read_only: false

features:
  wiki: true
  pipelines: false
  variables: false

# Tool restrictions
denied_tools_regex: "^manage_webhook"
denied_actions:
  - "manage_repository:delete"

Preset Definitions

1. readonly.yaml (implemented)

Persona: Auditor, observer
Focus: All browse_* tools, no manage_*

description: "Read-only access - blocks all write operations"
read_only: true
denied_tools_regex: "^manage_|^create_"

features:
  wiki: true
  milestones: true
  pipelines: true
  labels: true
  mrs: true
  files: true
  variables: false  # Variables often contain secrets
  workitems: true
  webhooks: false   # Admin-level
  snippets: true
  integrations: false  # Admin-level

2. developer.yaml (implemented)

Persona: Standard developer
Focus: Code, MRs, issues - standard workflow

description: "Standard developer workflow"
read_only: false

features:
  wiki: true
  milestones: false
  pipelines: true
  labels: true
  mrs: true
  files: true
  variables: false
  workitems: true
  webhooks: false
  snippets: true
  integrations: false

3. admin.yaml (implemented)

Persona: Admin / Full access

description: "Full admin access - all features enabled"
read_only: false

features:
  wiki: true
  milestones: true
  pipelines: true
  labels: true
  mrs: true
  files: true
  variables: true
  workitems: true
  webhooks: true
  snippets: true
  integrations: true

4. junior-dev.yaml

Persona: Junior/Middle Developer
Focus: Code, MRs, issues - day-to-day development

description: "Junior/Middle Developer - code, MRs, basic issue tracking"
read_only: false

features:
  wiki: false
  milestones: false
  pipelines: false
  labels: true
  mrs: true
  files: true
  variables: false
  workitems: true
  webhooks: false
  snippets: true
  integrations: false

denied_tools_regex: "^manage_pipeline|^manage_variable|^manage_webhook"

5. senior-dev.yaml

Persona: Senior Developer / Code Reviewer
Focus: Code + review + pipeline monitoring

description: "Senior Developer - code review, discussions, pipeline monitoring"
read_only: false

features:
  wiki: true
  milestones: false
  pipelines: true
  labels: true
  mrs: true
  files: true
  variables: false
  workitems: true
  webhooks: false
  snippets: true
  integrations: false

denied_actions:
  - "manage_pipeline:cancel"
  - "manage_pipeline:retry"
  - "manage_webhook:create"
  - "manage_webhook:delete"

6. devops.yaml

Persona: DevOps Engineer
Focus: CI/CD, pipelines, variables, infrastructure

description: "DevOps Engineer - CI/CD pipelines, variables, infrastructure"
read_only: false

features:
  wiki: false
  milestones: false
  pipelines: true
  labels: false
  mrs: false
  files: true
  variables: true
  workitems: false
  webhooks: true
  snippets: false
  integrations: true

7. team-lead.yaml

Persona: Development Team Lead
Focus: Planning + oversight + review

description: "Team Lead - planning, milestones, team oversight, code review"
read_only: false

features:
  wiki: true
  milestones: true
  pipelines: true
  labels: true
  mrs: true
  files: true
  variables: false
  workitems: true
  webhooks: false
  snippets: true
  integrations: false

denied_actions:
  - "manage_variable:create"
  - "manage_variable:update"
  - "manage_variable:delete"
  - "manage_webhook:create"
  - "manage_webhook:delete"

8. pm.yaml

Persona: Product/Project Manager
Focus: Planning, tracking, NO code operations

description: "Project Manager - planning, tracking, documentation (no code ops)"
read_only: false

features:
  wiki: true
  milestones: true
  pipelines: false
  labels: true
  mrs: true   # Read MR status
  files: false
  variables: false
  workitems: true
  webhooks: false
  snippets: false
  integrations: false

denied_tools_regex: "^manage_files|^manage_pipeline|^manage_variable"

9. ci.yaml

Persona: CI/CD automation, bots
Focus: Minimal for automation

description: "CI/CD Bot - minimal tools for automation"
read_only: false

features:
  wiki: false
  milestones: false
  pipelines: true
  labels: false
  mrs: false
  files: true
  variables: true
  workitems: false
  webhooks: false
  snippets: false
  integrations: false

# Only pipeline and file operations
denied_tools_regex: "^manage_work_item|^manage_mr|^manage_label|^manage_milestone|^manage_wiki"

10. gitlab-com.yaml (NEW)

Persona: gitlab.com public users
Focus: Rate-limit friendly, safe defaults for public GitLab

description: "Optimized for gitlab.com - respects rate limits, safe defaults"
read_only: false

features:
  wiki: true
  milestones: true
  pipelines: true
  labels: true
  mrs: true
  files: true
  variables: false     # Often restricted on public projects
  workitems: true
  webhooks: false      # Requires maintainer+ access
  snippets: true
  integrations: false  # Requires admin access

# Rate-limit friendly restrictions
denied_actions:
  # Pagination-heavy operations
  - "browse_commits:list"      # Use specific SHA instead
  - "browse_pipelines:list"    # Use recent pipelines only

  # Operations that can trigger many API calls
  - "manage_pipeline:retry"    # Can cascade

Summary Table

Preset Focus Key Restrictions
readonly Observation All manage_* blocked
developer Standard dev No admin features
admin Everything None
junior-dev Code, MRs, issues No pipelines, variables, webhooks
senior-dev + Review, pipelines No pipeline control, no webhooks
devops CI/CD, infrastructure No MRs, issues, wiki
team-lead Planning, oversight No variables, webhooks
pm Planning, docs No code ops
ci Automation Only pipelines, files, variables
gitlab-com Public GitLab Rate-limit friendly

Implementation

File structure

src/profiles/builtin/
├── readonly.yaml     # Done
├── developer.yaml    # Done
├── admin.yaml        # Done
├── junior-dev.yaml
├── senior-dev.yaml
├── devops.yaml
├── team-lead.yaml
├── pm.yaml
├── ci.yaml
└── gitlab-com.yaml   # NEW

Validate preset tool names

function validatePresetRestrictions(preset: Preset, availableTools: string[]): ValidationResult {
  // Validate denied_tools_regex compiles
  // Validate denied_actions reference valid tools
}

Tasks

  • Create admin.yaml preset
  • Create developer.yaml preset
  • Create readonly.yaml preset
  • Create junior-dev.yaml preset
  • Create senior-dev.yaml preset
  • Create devops.yaml preset
  • Create team-lead.yaml preset
  • Create pm.yaml preset
  • Create ci.yaml preset
  • Create gitlab-com.yaml preset (NEW)
  • Bundle yaml files in npm package
  • Write tests for each preset validation
  • Document gitlab.com usage in README

Testing

IMPORTANT: Preset tests do NOT require GitLab connection:

describe('presets', () => {
  // Unit tests - YAML validation only
  it('validates readonly preset schema', () => {
    const preset = loadPresetYaml('readonly.yaml');
    expect(PresetSchema.safeParse(preset).success).toBe(true);
    expect(preset.host).toBeUndefined(); // CRITICAL: no host
    expect(preset.auth).toBeUndefined(); // CRITICAL: no auth
  });

  it('validates denied_tools_regex compiles', () => {
    const preset = loadPresetYaml('junior-dev.yaml');
    expect(() => new RegExp(preset.denied_tools_regex)).not.toThrow();
  });

  it('validates denied_actions reference valid tools', () => {
    const preset = loadPresetYaml('senior-dev.yaml');
    const validTools = getAllToolNames();
    for (const action of preset.denied_actions || []) {
      const [tool] = action.split(':');
      expect(validTools).toContain(tool);
    }
  });
});

Documentation

Add to README:

### Built-in Presets

| Preset | Best For | Restrictions |
|--------|----------|--------------|
| `readonly` | Auditors, observers | All write ops blocked |
| `developer` | Standard developers | No admin features |
| `admin` | Administrators | Full access |
| `junior-dev` | Junior developers | No pipelines, variables |
| `senior-dev` | Senior developers | Read-only pipelines |
| `devops` | DevOps engineers | CI/CD focused |
| `team-lead` | Team leads | Planning + oversight |
| `pm` | Project managers | No code operations |
| `ci` | CI/CD bots | Minimal automation |
| `gitlab-com` | gitlab.com users | Rate-limit friendly |

Use with: `--preset readonly` or `GITLAB_PRESET=developer`

Note: Presets apply to your existing GitLab connection (from GITLAB_API_URL/GITLAB_TOKEN).

### Using with gitlab.com

```bash
export GITLAB_API_URL=https://gitlab.com
export GITLAB_TOKEN=glpat-xxxxxxxxxxxx

# Recommended preset for gitlab.com
gitlab-mcp stdio --preset gitlab-com

## Acceptance Criteria

- [ ] All 10 presets created as yaml files
- [ ] Presets contain NO host/auth (security requirement)
- [ ] `yarn list-tools --preset <name>` shows correct tools
- [ ] Presets validate against current tool list
- [ ] gitlab-com preset documented for public GitLab users

## Priority

**MEDIUM** - Requires #54 (profiles infrastructure) first

## Dependencies

- #54 - Profiles infrastructure (base support)

## Related

- #61 - Project-level configs (can use `extends` to inherit from these)
- #56 - list-tools --preset (inspection)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions