Release wordcraft-mcp and gridcraft-mcp 0.3.0: client-neutral skills, Cursor plugins.

This commit is contained in:
Dominic Gundel committed 2026-10-19 23:27:06 +02:00
1 parent debdf92877
commit 4c7e3ff720
26 files changed
+1008 -236

No files matched your search

+197
View File
@@ -0,0 +1,197 @@
# Builds dist\cursor\ from skills\: flat skill copies, mcp snippets, one plugin per skill.
# Usage: scripts\build-cursor.ps1 [-Name <skill-name>]
param([string]$Name)
. (Join-Path $PSScriptRoot 'lib.ps1')
. (Join-Path $PSScriptRoot 'cursor-deeplink.ps1')
$CursorDist = Join-Path $DistDir 'cursor'
$ServerKeys = @{
'wordcraft-mcp' = 'wordcraft'
'gridcraft-mcp' = 'gridcraft'
}
function Get-McpServerKey([string]$SkillName) {
if ($ServerKeys.ContainsKey($SkillName)) { return $ServerKeys[$SkillName] }
# fallback: strip trailing -mcp
if ($SkillName -match '^(.+)-mcp$') { return $Matches[1] }
return $SkillName
}
function Convert-ClaudeArgsToCursor([object[]]$CliArgs) {
$out = New-Object System.Collections.Generic.List[string]
foreach ($a in $CliArgs) {
$s = [string]$a
if ($s -eq '${user_config.author}') { $out.Add('${AUTHOR}'); continue }
if ($s -eq '${user_config.read_root}') { $out.Add('${READ_ROOT}'); continue }
if ($s -eq '${user_config.write_root}') { $out.Add('${WRITE_ROOT}'); continue }
$out.Add($s)
}
return , $out.ToArray()
}
function Convert-ArgsToUserHomeDefaults([object[]]$CliArgs) {
$out = New-Object System.Collections.Generic.List[string]
foreach ($a in $CliArgs) {
$s = [string]$a
if ($s -eq '${user_config.author}' -or $s -eq '${AUTHOR}') { $out.Add('Claude'); continue }
if ($s -eq '${user_config.read_root}' -or $s -eq '${READ_ROOT}') { $out.Add('${userHome}/Documents'); continue }
if ($s -eq '${user_config.write_root}' -or $s -eq '${WRITE_ROOT}') { $out.Add('${userHome}/Documents/Claude'); continue }
$out.Add($s)
}
return , $out.ToArray()
}
function Build-OneSkill([string]$N) {
$dir = Join-Path $SkillsDir $N
if (-not (Test-Path $dir -PathType Container)) {
Write-Host "skills/$N fehlt."
return $false
}
$ver = Get-SkillVersion $dir
if (-not $ver) {
Write-Host "CHANGELOG von $N hat keine Version."
return $false
}
$skillPath = Join-Path $dir 'SKILL.md'
$fm = Get-Frontmatter $skillPath
if ($null -eq $fm) {
Write-Host "${N}: kein Frontmatter."
return $false
}
$fmName = Get-FmValue $fm 'name'
$desc = Get-FmValue $fm 'description'
if ($fmName -cne $N) {
Write-Host "${N}: Frontmatter name '$fmName' != Ordner."
return $false
}
if (-not $desc -or $desc.Length -gt 1024) {
Write-Host "${N}: description fehlt oder > 1024."
return $false
}
# Flat skill copy
$flatDir = Join-Path (Join-Path $CursorDist 'skills') $N
New-Item -ItemType Directory -Force -Path $flatDir | Out-Null
Copy-Item -LiteralPath $skillPath -Destination (Join-Path $flatDir 'SKILL.md') -Force
$extManPath = Join-Path $dir 'extension\manifest.json'
$hasExt = Test-Path $extManPath
$pluginRoot = Join-Path (Join-Path $CursorDist 'plugins') $N
if (Test-Path $pluginRoot) { Remove-Item $pluginRoot -Recurse -Force }
New-Item -ItemType Directory -Force -Path (Join-Path $pluginRoot '.cursor-plugin') | Out-Null
$pluginSkillDir = Join-Path (Join-Path $pluginRoot 'skills') $N
New-Item -ItemType Directory -Force -Path $pluginSkillDir | Out-Null
Copy-Item -LiteralPath $skillPath -Destination (Join-Path $pluginSkillDir 'SKILL.md') -Force
$displayDesc = $desc
$authorName = 'Dominic Gundel'
$pluginVars = $null
$mcpForPlugin = $null
$mcpStandalone = $null
$serverKey = Get-McpServerKey $N
if ($hasExt) {
$man = (Read-Text $extManPath) | ConvertFrom-Json
if ($man.version -cne $ver) {
Write-Host "${N}: manifest version '$($man.version)' != CHANGELOG '$ver'."
return $false
}
$dn = [string]$man.display_name
if ($dn -match ' for Claude$') {
$displayDesc = ($dn -replace ' for Claude$', ' for Cursor') + '. ' + $desc
}
elseif ($man.description) {
$displayDesc = [string]$man.description
}
if ($man.author -and $man.author.name) { $authorName = [string]$man.author.name }
$cmd = [string]$man.server.mcp_config.command
$argsRaw = @($man.server.mcp_config.args)
$argsPlugin = Convert-ClaudeArgsToCursor $argsRaw
$argsHome = Convert-ArgsToUserHomeDefaults $argsRaw
$transportPlugin = @{ command = $cmd; args = @($argsPlugin) }
$transportHome = @{ command = $cmd; args = @($argsHome) }
$mcpForPlugin = @{ mcpServers = @{ $serverKey = $transportPlugin } }
$mcpStandalone = @{ mcpServers = @{ $serverKey = $transportHome } }
if ($man.user_config) {
$props = @{}
$required = @()
if ($man.user_config.read_root) {
$props['READ_ROOT'] = @{
type = 'string'
title = 'Lese-Ordner'
description = 'Weit fassen (Standard: Dokumente).'
default = '${userHome}/Documents'
}
$required += 'READ_ROOT'
}
if ($man.user_config.write_root) {
$props['WRITE_ROOT'] = @{
type = 'string'
title = 'Schreib-Ordner'
description = 'Eng halten (Standard: Dokumente/Claude).'
default = '${userHome}/Documents/Claude'
}
$required += 'WRITE_ROOT'
}
if ($man.user_config.author) {
$props['AUTHOR'] = @{
type = 'string'
title = 'Autorname'
description = 'Name fuer nachverfolgte Aenderungen.'
default = 'Claude'
}
}
if ($props.Count -gt 0) {
$pluginVars = @{
type = 'object'
properties = $props
}
if ($required.Count -gt 0) { $pluginVars['required'] = $required }
}
}
$mcpDir = Join-Path $CursorDist 'mcp'
New-Item -ItemType Directory -Force -Path $mcpDir | Out-Null
$snippetPath = Join-Path $mcpDir "$N.json"
Write-Text $snippetPath (($mcpStandalone | ConvertTo-Json -Depth 20) + "`n")
}
$pluginJson = @{
name = $N
version = $ver
description = $displayDesc
author = @{ name = $authorName }
license = 'MIT'
homepage = 'https://git.gundel.dev/dg/claude-skills'
repository = 'https://git.gundel.dev/dg/claude-skills.git'
}
if ($pluginVars) { $pluginJson['variables'] = $pluginVars }
Write-Text (Join-Path $pluginRoot '.cursor-plugin\plugin.json') (($pluginJson | ConvertTo-Json -Depth 20) + "`n")
if ($mcpForPlugin) {
Write-Text (Join-Path $pluginRoot 'mcp.json') (($mcpForPlugin | ConvertTo-Json -Depth 20) + "`n")
}
# Validate JSON round-trip
$null = (Read-Text (Join-Path $pluginRoot '.cursor-plugin\plugin.json')) | ConvertFrom-Json
if ($mcpForPlugin) {
$null = (Read-Text (Join-Path $pluginRoot 'mcp.json')) | ConvertFrom-Json
}
Write-Host "OK cursor plugin $N $ver"
return $true
}
if ($Name) { $names = @($Name) } else { $names = @(Get-SkillNames) }
New-Item -ItemType Directory -Force -Path $CursorDist | Out-Null
$ok = $true
foreach ($n in $names) {
if (-not (Build-OneSkill $n)) { $ok = $false }
}
if (-not $ok) { exit 1 }
exit 0