forked from zereight/gitlab-mcp
-
Notifications
You must be signed in to change notification settings - Fork 1
feat: Profiles infrastructure - base support for named configuration profiles #54
Copy link
Copy link
Closed
Description
Summary
Add support for named configuration profiles and presets that enable multi-GitLab workflows and role-based access patterns.
Architecture: Profiles vs Presets
SECURITY CRITICAL: Built-in configurations must NEVER contain host or authentication to prevent accidental requests to wrong GitLab instances during testing.
Profile (User-defined only)
Full configuration including connection settings:
- Location:
~/.config/gitlab-mcp/profiles.yaml - Contains: host, auth, TLS, features, restrictions
- Purpose: Multi-instance access (work, personal, client)
Preset (Built-in, safe for testing)
Settings/restrictions only, NO connection:
- Location:
src/profiles/builtin/(embedded in package) - Contains: features, read_only, denied_tools_regex, denied_actions
- NO host, NO auth - uses environment variables
- Purpose: Role-based tool restrictions (readonly, developer, admin)
Profile Format
Location: ~/.config/gitlab-mcp/profiles.yaml
profiles:
work:
host: gitlab.company.com
auth:
type: pat
token_env: GITLAB_WORK_TOKEN # Reference to env var
read_only: false
features:
wiki: true
pipelines: true
timeout_ms: 30000
client-acme:
host: gitlab.acme-corp.com
auth:
type: oauth
client_id_env: ACME_OAUTH_CLIENT_ID
read_only: true
denied_tools_regex: "^manage_"
default_profile: workPreset Format
Location: src/profiles/builtin/*.yaml
# readonly.yaml - NO host/auth, safe for testing
description: "Read-only access - blocks all write operations"
read_only: true
denied_tools_regex: "^manage_|^create_"
features:
wiki: true
variables: false # Variables often contain secrets
webhooks: false # Admin-levelProfile Selection
Priority order:
- CLI argument:
--profile <name>(tries profile, then preset) - Environment variable:
GITLAB_PROFILE=<name> default_profilefrom user config- Fallback to env vars (current behavior)
Profile Schema
// Full profile with connection (user-defined only)
interface Profile {
// Connection
host: string;
api_url?: string;
// Authentication
auth: {
type: "pat" | "oauth" | "cookie";
token_env?: string;
client_id_env?: string;
cookie_path?: string;
};
// Settings (same as Preset)
read_only?: boolean;
denied_tools_regex?: string;
allowed_tools?: string[];
denied_actions?: string[];
features?: FeatureFlags;
timeout_ms?: number;
// TLS
skip_tls_verify?: boolean;
ssl_cert_path?: string;
ca_cert_path?: string;
}
// Preset without connection (built-in safe)
interface Preset {
description?: string;
read_only?: boolean;
denied_tools_regex?: string;
allowed_tools?: string[];
denied_actions?: string[];
features?: FeatureFlags;
timeout_ms?: number;
// NO host, NO auth
}Implementation
1. Types and schemas
src/profiles/types.ts- Zod schemas for Profile, Preset, ProfilesConfig
2. Profile/Preset loader
// src/profiles/loader.ts
export class ProfileLoader {
async loadProfile(name: string): Promise<Profile>; // User profiles only
async loadPreset(name: string): Promise<Preset>; // Built-in presets only
async loadAny(name: string): Promise<{ type: "profile" | "preset"; data: Profile | Preset }>;
async listProfiles(): Promise<ProfileInfo[]>;
}3. Profile/Preset application
// src/profiles/applicator.ts
export function applyProfile(profile: Profile): void;
export function applyPreset(preset: Preset): void;
export async function loadAndApplyProfile(name: string): Promise<ApplyProfileResult>;Built-in Presets
src/profiles/builtin/
├── readonly.yaml # Browse only, no modifications
├── developer.yaml # Standard dev workflow
└── admin.yaml # Full access
See #55 for extended role-based presets.
Tasks
- Define Profile/Preset TypeScript interfaces
- Create Zod schemas for validation
- Implement ProfileLoader class
- Implement applyProfile()/applyPreset() functions
- Add
--profileCLI argument to entry points - Support
GITLAB_PROFILEenvironment variable - Create built-in presets directory (readonly, developer, admin)
- Write unit tests for profile/preset loading
- Write integration tests for application
- Run full test suite
Acceptance Criteria
- Profiles load from
~/.config/gitlab-mcp/profiles.yaml - Presets load from built-in package directory
- Built-in presets contain NO host/auth (security)
-
--profileargument works -
GITLAB_PROFILEenv var works - Profile validation catches invalid configurations
- Graceful fallback when no profile specified
- Tokens read from env vars (never stored in yaml)
Priority
HIGH - Foundation for role-based presets and multi-instance workflows
Dependencies
None (foundation issue)
Related
- feat: Built-in role-based profiles (junior-dev, senior-dev, devops, team-lead, pm, admin, ci, readonly) #55 - Built-in role-based presets
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels