@julong/mono-rele2-utils 1.3.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -15
- package/dist/cli.js +28 -13
- package/dist/index.d.ts +80 -1
- package/dist/index.js +208 -14
- package/dist/server.js +28 -13
- package/dist/{mono-rele2-utils → skills/mono-rele2-utils}/skill.md +13 -15
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -36,40 +36,41 @@ Available skills:
|
|
|
36
36
|
|
|
37
37
|
### Skills
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
<!-- SKILLS:START -->
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
#### `cnTool`
|
|
42
|
+
|
|
43
|
+
Merges class names, filtering out falsy values.
|
|
42
44
|
|
|
43
45
|
```sh
|
|
44
|
-
mono-rele2-utils
|
|
46
|
+
mono-rele2-utils cnTool <classes>
|
|
45
47
|
```
|
|
46
48
|
|
|
47
49
|
| arg | type | description |
|
|
48
50
|
|-----|------|-------------|
|
|
49
|
-
| `
|
|
50
|
-
| `to` | `upper` \| `lower` \| `capitalize` \| `camel` \| `snake` \| `kebab` | Target case format |
|
|
51
|
+
| `classes` | JSON string (array) | List of class names to merge |
|
|
51
52
|
|
|
52
53
|
```sh
|
|
53
|
-
mono-rele2-utils
|
|
54
|
-
mono-rele2-utils caseConvertTool "helloWorld" snake # hello_world
|
|
55
|
-
mono-rele2-utils caseConvertTool "hello world" kebab # hello-world
|
|
56
|
-
mono-rele2-utils caseConvertTool "hello world" upper # HELLO WORLD
|
|
54
|
+
mono-rele2-utils cnTool '["btn","active","large"]' # btn active large
|
|
57
55
|
```
|
|
58
56
|
|
|
59
|
-
#### `
|
|
57
|
+
#### `caseConvertTool`
|
|
60
58
|
|
|
61
|
-
|
|
59
|
+
Converts text to the specified case format.
|
|
62
60
|
|
|
63
61
|
```sh
|
|
64
|
-
mono-rele2-utils
|
|
62
|
+
mono-rele2-utils caseConvertTool <input> <to>
|
|
65
63
|
```
|
|
66
64
|
|
|
67
65
|
| arg | type | description |
|
|
68
66
|
|-----|------|-------------|
|
|
69
|
-
| `
|
|
67
|
+
| `input` | string | Text to convert |
|
|
68
|
+
| `to` | `upper` \| `lower` \| `capitalize` \| `camel` \| `snake` \| `kebab` | Target case format |
|
|
70
69
|
|
|
71
70
|
```sh
|
|
72
|
-
mono-rele2-utils
|
|
71
|
+
mono-rele2-utils caseConvertTool "hello world" camel # helloWorld
|
|
72
|
+
mono-rele2-utils caseConvertTool "helloWorld" snake # hello_world
|
|
73
|
+
mono-rele2-utils caseConvertTool "hello world" kebab # hello-world
|
|
73
74
|
```
|
|
74
75
|
|
|
75
76
|
#### `truncateTool`
|
|
@@ -84,13 +85,15 @@ mono-rele2-utils truncateTool <input> <maxLength> [suffix]
|
|
|
84
85
|
|-----|------|-------------|
|
|
85
86
|
| `input` | string | Text to truncate |
|
|
86
87
|
| `maxLength` | number | Maximum character length |
|
|
87
|
-
| `suffix` | string | Suffix to append (default: `...`) |
|
|
88
|
+
| `suffix` | string | Suffix to append when truncated (default: `...`) |
|
|
88
89
|
|
|
89
90
|
```sh
|
|
90
91
|
mono-rele2-utils truncateTool "hello world long text" 10 # hello w...
|
|
91
92
|
mono-rele2-utils truncateTool "hello world" 8 "…" # hello w…
|
|
92
93
|
```
|
|
93
94
|
|
|
95
|
+
<!-- SKILLS:END -->
|
|
96
|
+
|
|
94
97
|
## MCP Server
|
|
95
98
|
|
|
96
99
|
```sh
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
// ../common/
|
|
3
|
+
// ../common/kit/tool.ts
|
|
4
4
|
function toolDef(def) {
|
|
5
5
|
return def;
|
|
6
6
|
}
|
|
@@ -11,11 +11,11 @@ function text(content) {
|
|
|
11
11
|
return { content: [{ type: "text", text: content }] };
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
// ../common/
|
|
14
|
+
// ../common/kit/server.ts
|
|
15
15
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
16
16
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
17
17
|
|
|
18
|
-
// ../common/
|
|
18
|
+
// ../common/kit/cli.ts
|
|
19
19
|
import { z } from "zod";
|
|
20
20
|
function formatSkills(tools2) {
|
|
21
21
|
const sections = Object.entries(tools2).map(([key, tool]) => {
|
|
@@ -66,9 +66,12 @@ function handleCliError(err) {
|
|
|
66
66
|
process.exit(1);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
//
|
|
69
|
+
// ../common/kit/skill.ts
|
|
70
70
|
import { z as z2 } from "zod";
|
|
71
71
|
|
|
72
|
+
// src/tools/text.ts
|
|
73
|
+
import { z as z3 } from "zod";
|
|
74
|
+
|
|
72
75
|
// src/cn.ts
|
|
73
76
|
function cn(...classes) {
|
|
74
77
|
return classes.filter(Boolean).join(" ");
|
|
@@ -80,31 +83,43 @@ var tools = {
|
|
|
80
83
|
name: "cn",
|
|
81
84
|
description: "Merges class names, filtering out falsy values",
|
|
82
85
|
inputSchema: {
|
|
83
|
-
classes:
|
|
86
|
+
classes: z3.array(z3.string()).describe("List of class names to merge")
|
|
84
87
|
},
|
|
85
|
-
handler: async ({ classes }) => text(cn(...classes))
|
|
88
|
+
handler: async ({ classes }) => text(cn(...classes)),
|
|
89
|
+
examples: [
|
|
90
|
+
{ args: [`'["btn","active","large"]'`], result: "btn active large" }
|
|
91
|
+
]
|
|
86
92
|
}),
|
|
87
93
|
caseConvertTool: toolDef({
|
|
88
94
|
name: "case_convert",
|
|
89
95
|
description: "Converts text to the specified case format",
|
|
90
96
|
inputSchema: {
|
|
91
|
-
input:
|
|
92
|
-
to:
|
|
97
|
+
input: z3.string().describe("Text to convert"),
|
|
98
|
+
to: z3.enum(["upper", "lower", "capitalize", "camel", "snake", "kebab"]).describe("Target case format")
|
|
93
99
|
},
|
|
94
|
-
handler: async ({ input, to }) => text(convert(input, to))
|
|
100
|
+
handler: async ({ input, to }) => text(convert(input, to)),
|
|
101
|
+
examples: [
|
|
102
|
+
{ args: [`"hello world"`, "camel"], result: "helloWorld" },
|
|
103
|
+
{ args: [`"helloWorld"`, "snake"], result: "hello_world" },
|
|
104
|
+
{ args: [`"hello world"`, "kebab"], result: "hello-world" }
|
|
105
|
+
]
|
|
95
106
|
}),
|
|
96
107
|
truncateTool: toolDef({
|
|
97
108
|
name: "truncate",
|
|
98
109
|
description: "Truncates text to a maximum length and appends a suffix",
|
|
99
110
|
inputSchema: {
|
|
100
|
-
input:
|
|
101
|
-
maxLength:
|
|
102
|
-
suffix:
|
|
111
|
+
input: z3.string().describe("Text to truncate"),
|
|
112
|
+
maxLength: z3.number().int().positive().describe("Maximum character length"),
|
|
113
|
+
suffix: z3.string().default("...").describe("Suffix to append when truncated")
|
|
103
114
|
},
|
|
104
115
|
handler: async ({ input, maxLength, suffix }) => {
|
|
105
116
|
const result = input.length <= maxLength ? input : input.slice(0, maxLength - suffix.length) + suffix;
|
|
106
117
|
return text(result);
|
|
107
|
-
}
|
|
118
|
+
},
|
|
119
|
+
examples: [
|
|
120
|
+
{ args: [`"hello world long text"`, "10"], result: "hello w..." },
|
|
121
|
+
{ args: [`"hello world"`, "8", `"\u2026"`], result: "hello w\u2026" }
|
|
122
|
+
]
|
|
108
123
|
})
|
|
109
124
|
};
|
|
110
125
|
var cnTool = defineTool(tools.cnTool);
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,86 @@
|
|
|
1
1
|
import * as _modelcontextprotocol_sdk_server_mcp_js from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
|
3
|
+
import { z } from 'zod';
|
|
2
4
|
|
|
3
5
|
declare function cn(...classes: (string | undefined | null | false)[]): string;
|
|
4
6
|
|
|
7
|
+
type ToolResult = CallToolResult;
|
|
8
|
+
type ToolExample = {
|
|
9
|
+
args: string[];
|
|
10
|
+
result: string;
|
|
11
|
+
};
|
|
12
|
+
type AnyToolDef = {
|
|
13
|
+
name: string;
|
|
14
|
+
description: string;
|
|
15
|
+
inputSchema: z.ZodRawShape;
|
|
16
|
+
handler: (args: any) => Promise<ToolResult>;
|
|
17
|
+
examples?: ToolExample[];
|
|
18
|
+
guidelines?: string[];
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
type SkillTools = Record<string, AnyToolDef>;
|
|
22
|
+
declare function generateSkillMarkdown(opts: {
|
|
23
|
+
binName: string;
|
|
24
|
+
description: string;
|
|
25
|
+
tools: SkillTools;
|
|
26
|
+
}): string;
|
|
27
|
+
declare function generateReadmeSkills(opts: {
|
|
28
|
+
binName: string;
|
|
29
|
+
tools: SkillTools;
|
|
30
|
+
}): string;
|
|
31
|
+
|
|
32
|
+
declare const tools: {
|
|
33
|
+
cnTool: {
|
|
34
|
+
name: string;
|
|
35
|
+
description: string;
|
|
36
|
+
inputSchema: {
|
|
37
|
+
readonly classes: z.ZodArray<z.ZodString>;
|
|
38
|
+
};
|
|
39
|
+
handler: (input: {
|
|
40
|
+
classes: string[];
|
|
41
|
+
}) => Promise<ToolResult>;
|
|
42
|
+
examples?: ToolExample[];
|
|
43
|
+
guidelines?: string[];
|
|
44
|
+
};
|
|
45
|
+
caseConvertTool: {
|
|
46
|
+
name: string;
|
|
47
|
+
description: string;
|
|
48
|
+
inputSchema: {
|
|
49
|
+
readonly input: z.ZodString;
|
|
50
|
+
readonly to: z.ZodEnum<{
|
|
51
|
+
upper: "upper";
|
|
52
|
+
lower: "lower";
|
|
53
|
+
capitalize: "capitalize";
|
|
54
|
+
camel: "camel";
|
|
55
|
+
snake: "snake";
|
|
56
|
+
kebab: "kebab";
|
|
57
|
+
}>;
|
|
58
|
+
};
|
|
59
|
+
handler: (input: {
|
|
60
|
+
input: string;
|
|
61
|
+
to: "upper" | "lower" | "capitalize" | "camel" | "snake" | "kebab";
|
|
62
|
+
}) => Promise<ToolResult>;
|
|
63
|
+
examples?: ToolExample[];
|
|
64
|
+
guidelines?: string[];
|
|
65
|
+
};
|
|
66
|
+
truncateTool: {
|
|
67
|
+
name: string;
|
|
68
|
+
description: string;
|
|
69
|
+
inputSchema: {
|
|
70
|
+
readonly input: z.ZodString;
|
|
71
|
+
readonly maxLength: z.ZodNumber;
|
|
72
|
+
readonly suffix: z.ZodDefault<z.ZodString>;
|
|
73
|
+
};
|
|
74
|
+
handler: (input: {
|
|
75
|
+
input: string;
|
|
76
|
+
maxLength: number;
|
|
77
|
+
suffix: string;
|
|
78
|
+
}) => Promise<ToolResult>;
|
|
79
|
+
examples?: ToolExample[];
|
|
80
|
+
guidelines?: string[];
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
|
|
5
84
|
declare function createUtilsServer(): _modelcontextprotocol_sdk_server_mcp_js.McpServer;
|
|
6
85
|
|
|
7
|
-
export { cn, createUtilsServer };
|
|
86
|
+
export { cn, createUtilsServer, generateReadmeSkills, generateSkillMarkdown, tools };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// ../common/
|
|
1
|
+
// ../common/kit/tool.ts
|
|
2
2
|
function toolDef(def) {
|
|
3
3
|
return def;
|
|
4
4
|
}
|
|
@@ -9,7 +9,7 @@ function text(content) {
|
|
|
9
9
|
return { content: [{ type: "text", text: content }] };
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
// ../common/
|
|
12
|
+
// ../common/kit/server.ts
|
|
13
13
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
14
14
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
15
15
|
function createMcpServer(config, tools2) {
|
|
@@ -25,11 +25,190 @@ function createMcpServer(config, tools2) {
|
|
|
25
25
|
return server;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
// ../common/
|
|
28
|
+
// ../common/kit/cli.ts
|
|
29
29
|
import { z } from "zod";
|
|
30
30
|
|
|
31
|
-
//
|
|
31
|
+
// ../common/kit/skill.ts
|
|
32
32
|
import { z as z2 } from "zod";
|
|
33
|
+
function generateSkillMarkdown(opts) {
|
|
34
|
+
const { binName, description, tools: tools2 } = opts;
|
|
35
|
+
return `---
|
|
36
|
+
name: ${binName}
|
|
37
|
+
description: ${description}
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
# ${binName}
|
|
41
|
+
|
|
42
|
+
\`\`\`sh
|
|
43
|
+
${binName} <skillName> [...args]
|
|
44
|
+
\`\`\`
|
|
45
|
+
|
|
46
|
+
## Skills
|
|
47
|
+
|
|
48
|
+
${renderSkills(tools2)}
|
|
49
|
+
|
|
50
|
+
## Examples
|
|
51
|
+
|
|
52
|
+
${renderExamples(binName, tools2)}
|
|
53
|
+
|
|
54
|
+
## Guidelines
|
|
55
|
+
|
|
56
|
+
${renderGuidelines(binName, tools2)}
|
|
57
|
+
`;
|
|
58
|
+
}
|
|
59
|
+
function renderSkills(tools2) {
|
|
60
|
+
return Object.entries(tools2).map(([key, tool]) => {
|
|
61
|
+
const rows = Object.entries(tool.inputSchema).map(([field, schema]) => `| \`${field}\` | ${describeField(schema)} |`).join("\n");
|
|
62
|
+
return `### ${key}
|
|
63
|
+
|
|
64
|
+
${tool.description}
|
|
65
|
+
|
|
66
|
+
| arg | description |
|
|
67
|
+
|-----|-------------|
|
|
68
|
+
${rows}`;
|
|
69
|
+
}).join("\n\n");
|
|
70
|
+
}
|
|
71
|
+
function describeField(schema) {
|
|
72
|
+
const baseDesc = schema.description ?? "";
|
|
73
|
+
let inner = schema;
|
|
74
|
+
let defaultValue;
|
|
75
|
+
let isOptional = false;
|
|
76
|
+
while (inner instanceof z2.ZodOptional || inner instanceof z2.ZodDefault) {
|
|
77
|
+
if (inner instanceof z2.ZodDefault) {
|
|
78
|
+
const raw = inner.def.defaultValue;
|
|
79
|
+
defaultValue = typeof raw === "function" ? raw() : raw;
|
|
80
|
+
}
|
|
81
|
+
if (inner instanceof z2.ZodOptional) isOptional = true;
|
|
82
|
+
inner = inner.unwrap();
|
|
83
|
+
}
|
|
84
|
+
const parts = [];
|
|
85
|
+
if (baseDesc) parts.push(baseDesc);
|
|
86
|
+
if (inner instanceof z2.ZodEnum) {
|
|
87
|
+
const values = inner.options.map((v) => `\`${v}\``).join(" \\| ");
|
|
88
|
+
parts.push(values);
|
|
89
|
+
}
|
|
90
|
+
if (defaultValue !== void 0) parts.push(`default: \`${String(defaultValue)}\``);
|
|
91
|
+
else if (isOptional) parts.push("optional");
|
|
92
|
+
return parts.join(" \u2014 ");
|
|
93
|
+
}
|
|
94
|
+
function renderExamples(binName, tools2) {
|
|
95
|
+
const lines = [];
|
|
96
|
+
for (const [key, tool] of Object.entries(tools2)) {
|
|
97
|
+
if (!tool.examples) continue;
|
|
98
|
+
for (const ex of tool.examples) {
|
|
99
|
+
const cmd = [binName, key, ...ex.args].join(" ");
|
|
100
|
+
lines.push(`- \`${cmd}\` \u2192 \`${ex.result}\``);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return lines.join("\n");
|
|
104
|
+
}
|
|
105
|
+
function renderGuidelines(binName, tools2) {
|
|
106
|
+
const items = [];
|
|
107
|
+
const seen = /* @__PURE__ */ new Set();
|
|
108
|
+
const push = (g) => {
|
|
109
|
+
if (seen.has(g)) return;
|
|
110
|
+
seen.add(g);
|
|
111
|
+
items.push(g);
|
|
112
|
+
};
|
|
113
|
+
push("Arguments are positional \u2014 pass them in the order listed in each skill's table");
|
|
114
|
+
const allSchemas = Object.values(tools2).flatMap((t) => Object.values(t.inputSchema));
|
|
115
|
+
if (allSchemas.some((s) => containsType(s, z2.ZodNumber))) {
|
|
116
|
+
push("Numeric args are auto-parsed \u2014 pass as plain numbers (e.g. `10`)");
|
|
117
|
+
}
|
|
118
|
+
if (allSchemas.some((s) => containsType(s, z2.ZodArray))) {
|
|
119
|
+
push('Array args must be valid JSON \u2014 wrap in single quotes on Unix shells (e.g. `\'["a","b"]\'`)');
|
|
120
|
+
}
|
|
121
|
+
if (allSchemas.some((s) => s instanceof z2.ZodOptional || s instanceof z2.ZodDefault)) {
|
|
122
|
+
push("Optional args with defaults may be omitted");
|
|
123
|
+
}
|
|
124
|
+
for (const tool of Object.values(tools2)) {
|
|
125
|
+
if (!tool.guidelines) continue;
|
|
126
|
+
for (const g of tool.guidelines) push(g);
|
|
127
|
+
}
|
|
128
|
+
push(`Run \`${binName}\` with no args to list all available skills`);
|
|
129
|
+
return items.map((g) => `- ${g}`).join("\n");
|
|
130
|
+
}
|
|
131
|
+
function containsType(schema, ctor) {
|
|
132
|
+
let inner = schema;
|
|
133
|
+
while (inner instanceof z2.ZodOptional || inner instanceof z2.ZodDefault) {
|
|
134
|
+
inner = inner.unwrap();
|
|
135
|
+
}
|
|
136
|
+
return inner instanceof ctor;
|
|
137
|
+
}
|
|
138
|
+
function generateReadmeSkills(opts) {
|
|
139
|
+
const { binName, tools: tools2 } = opts;
|
|
140
|
+
return Object.entries(tools2).map(([key, tool]) => renderReadmeSkill(binName, key, tool)).join("\n\n");
|
|
141
|
+
}
|
|
142
|
+
function renderReadmeSkill(binName, key, tool) {
|
|
143
|
+
const fields = Object.entries(tool.inputSchema);
|
|
144
|
+
const usageArgs = fields.map(([field, schema]) => {
|
|
145
|
+
const isOpt = schema instanceof z2.ZodOptional || schema instanceof z2.ZodDefault;
|
|
146
|
+
return isOpt ? `[${field}]` : `<${field}>`;
|
|
147
|
+
}).join(" ");
|
|
148
|
+
const usage = [binName, key, usageArgs].filter(Boolean).join(" ");
|
|
149
|
+
const rows = fields.map(([field, schema]) => {
|
|
150
|
+
const t = describeReadmeType(schema);
|
|
151
|
+
const d = describeReadmeDesc(schema);
|
|
152
|
+
return `| \`${field}\` | ${t} | ${d} |`;
|
|
153
|
+
}).join("\n");
|
|
154
|
+
const examples = tool.examples ?? [];
|
|
155
|
+
let exampleBlock = "";
|
|
156
|
+
if (examples.length > 0) {
|
|
157
|
+
const cmds = examples.map((ex) => [binName, key, ...ex.args].join(" "));
|
|
158
|
+
const width = Math.max(...cmds.map((c) => c.length));
|
|
159
|
+
const lines = examples.map((ex, i) => `${cmds[i].padEnd(width)} # ${ex.result}`);
|
|
160
|
+
exampleBlock = `
|
|
161
|
+
|
|
162
|
+
\`\`\`sh
|
|
163
|
+
${lines.join("\n")}
|
|
164
|
+
\`\`\``;
|
|
165
|
+
}
|
|
166
|
+
return `#### \`${key}\`
|
|
167
|
+
|
|
168
|
+
${tool.description}.
|
|
169
|
+
|
|
170
|
+
\`\`\`sh
|
|
171
|
+
${usage}
|
|
172
|
+
\`\`\`
|
|
173
|
+
|
|
174
|
+
| arg | type | description |
|
|
175
|
+
|-----|------|-------------|
|
|
176
|
+
${rows}${exampleBlock}`;
|
|
177
|
+
}
|
|
178
|
+
function describeReadmeType(schema) {
|
|
179
|
+
let inner = schema;
|
|
180
|
+
while (inner instanceof z2.ZodOptional || inner instanceof z2.ZodDefault) {
|
|
181
|
+
inner = inner.unwrap();
|
|
182
|
+
}
|
|
183
|
+
if (inner instanceof z2.ZodEnum) {
|
|
184
|
+
return inner.options.map((v) => `\`${v}\``).join(" \\| ");
|
|
185
|
+
}
|
|
186
|
+
if (inner instanceof z2.ZodNumber) return "number";
|
|
187
|
+
if (inner instanceof z2.ZodString) return "string";
|
|
188
|
+
if (inner instanceof z2.ZodBoolean) return "boolean";
|
|
189
|
+
if (inner instanceof z2.ZodArray) return "JSON string (array)";
|
|
190
|
+
return "unknown";
|
|
191
|
+
}
|
|
192
|
+
function describeReadmeDesc(schema) {
|
|
193
|
+
const baseDesc = schema.description ?? "";
|
|
194
|
+
let inner = schema;
|
|
195
|
+
let defaultValue;
|
|
196
|
+
let isOptional = false;
|
|
197
|
+
while (inner instanceof z2.ZodOptional || inner instanceof z2.ZodDefault) {
|
|
198
|
+
if (inner instanceof z2.ZodDefault) {
|
|
199
|
+
const raw = inner.def.defaultValue;
|
|
200
|
+
defaultValue = typeof raw === "function" ? raw() : raw;
|
|
201
|
+
}
|
|
202
|
+
if (inner instanceof z2.ZodOptional) isOptional = true;
|
|
203
|
+
inner = inner.unwrap();
|
|
204
|
+
}
|
|
205
|
+
if (defaultValue !== void 0) return `${baseDesc} (default: \`${String(defaultValue)}\`)`;
|
|
206
|
+
if (isOptional) return `${baseDesc} (optional)`;
|
|
207
|
+
return baseDesc;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// src/tools/text.ts
|
|
211
|
+
import { z as z3 } from "zod";
|
|
33
212
|
|
|
34
213
|
// src/cn.ts
|
|
35
214
|
function cn(...classes) {
|
|
@@ -42,31 +221,43 @@ var tools = {
|
|
|
42
221
|
name: "cn",
|
|
43
222
|
description: "Merges class names, filtering out falsy values",
|
|
44
223
|
inputSchema: {
|
|
45
|
-
classes:
|
|
224
|
+
classes: z3.array(z3.string()).describe("List of class names to merge")
|
|
46
225
|
},
|
|
47
|
-
handler: async ({ classes }) => text(cn(...classes))
|
|
226
|
+
handler: async ({ classes }) => text(cn(...classes)),
|
|
227
|
+
examples: [
|
|
228
|
+
{ args: [`'["btn","active","large"]'`], result: "btn active large" }
|
|
229
|
+
]
|
|
48
230
|
}),
|
|
49
231
|
caseConvertTool: toolDef({
|
|
50
232
|
name: "case_convert",
|
|
51
233
|
description: "Converts text to the specified case format",
|
|
52
234
|
inputSchema: {
|
|
53
|
-
input:
|
|
54
|
-
to:
|
|
235
|
+
input: z3.string().describe("Text to convert"),
|
|
236
|
+
to: z3.enum(["upper", "lower", "capitalize", "camel", "snake", "kebab"]).describe("Target case format")
|
|
55
237
|
},
|
|
56
|
-
handler: async ({ input, to }) => text(convert(input, to))
|
|
238
|
+
handler: async ({ input, to }) => text(convert(input, to)),
|
|
239
|
+
examples: [
|
|
240
|
+
{ args: [`"hello world"`, "camel"], result: "helloWorld" },
|
|
241
|
+
{ args: [`"helloWorld"`, "snake"], result: "hello_world" },
|
|
242
|
+
{ args: [`"hello world"`, "kebab"], result: "hello-world" }
|
|
243
|
+
]
|
|
57
244
|
}),
|
|
58
245
|
truncateTool: toolDef({
|
|
59
246
|
name: "truncate",
|
|
60
247
|
description: "Truncates text to a maximum length and appends a suffix",
|
|
61
248
|
inputSchema: {
|
|
62
|
-
input:
|
|
63
|
-
maxLength:
|
|
64
|
-
suffix:
|
|
249
|
+
input: z3.string().describe("Text to truncate"),
|
|
250
|
+
maxLength: z3.number().int().positive().describe("Maximum character length"),
|
|
251
|
+
suffix: z3.string().default("...").describe("Suffix to append when truncated")
|
|
65
252
|
},
|
|
66
253
|
handler: async ({ input, maxLength, suffix }) => {
|
|
67
254
|
const result = input.length <= maxLength ? input : input.slice(0, maxLength - suffix.length) + suffix;
|
|
68
255
|
return text(result);
|
|
69
|
-
}
|
|
256
|
+
},
|
|
257
|
+
examples: [
|
|
258
|
+
{ args: [`"hello world long text"`, "10"], result: "hello w..." },
|
|
259
|
+
{ args: [`"hello world"`, "8", `"\u2026"`], result: "hello w\u2026" }
|
|
260
|
+
]
|
|
70
261
|
})
|
|
71
262
|
};
|
|
72
263
|
var cnTool = defineTool(tools.cnTool);
|
|
@@ -98,5 +289,8 @@ function createUtilsServer() {
|
|
|
98
289
|
}
|
|
99
290
|
export {
|
|
100
291
|
cn,
|
|
101
|
-
createUtilsServer
|
|
292
|
+
createUtilsServer,
|
|
293
|
+
generateReadmeSkills,
|
|
294
|
+
generateSkillMarkdown,
|
|
295
|
+
tools
|
|
102
296
|
};
|
package/dist/server.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
// ../common/
|
|
3
|
+
// ../common/kit/tool.ts
|
|
4
4
|
function toolDef(def) {
|
|
5
5
|
return def;
|
|
6
6
|
}
|
|
@@ -11,7 +11,7 @@ function text(content) {
|
|
|
11
11
|
return { content: [{ type: "text", text: content }] };
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
// ../common/
|
|
14
|
+
// ../common/kit/server.ts
|
|
15
15
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
16
16
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
17
17
|
function createMcpServer(config, tools2) {
|
|
@@ -31,12 +31,15 @@ async function startServer(server2) {
|
|
|
31
31
|
await server2.connect(transport);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
// ../common/
|
|
34
|
+
// ../common/kit/cli.ts
|
|
35
35
|
import { z } from "zod";
|
|
36
36
|
|
|
37
|
-
//
|
|
37
|
+
// ../common/kit/skill.ts
|
|
38
38
|
import { z as z2 } from "zod";
|
|
39
39
|
|
|
40
|
+
// src/tools/text.ts
|
|
41
|
+
import { z as z3 } from "zod";
|
|
42
|
+
|
|
40
43
|
// src/cn.ts
|
|
41
44
|
function cn(...classes) {
|
|
42
45
|
return classes.filter(Boolean).join(" ");
|
|
@@ -48,31 +51,43 @@ var tools = {
|
|
|
48
51
|
name: "cn",
|
|
49
52
|
description: "Merges class names, filtering out falsy values",
|
|
50
53
|
inputSchema: {
|
|
51
|
-
classes:
|
|
54
|
+
classes: z3.array(z3.string()).describe("List of class names to merge")
|
|
52
55
|
},
|
|
53
|
-
handler: async ({ classes }) => text(cn(...classes))
|
|
56
|
+
handler: async ({ classes }) => text(cn(...classes)),
|
|
57
|
+
examples: [
|
|
58
|
+
{ args: [`'["btn","active","large"]'`], result: "btn active large" }
|
|
59
|
+
]
|
|
54
60
|
}),
|
|
55
61
|
caseConvertTool: toolDef({
|
|
56
62
|
name: "case_convert",
|
|
57
63
|
description: "Converts text to the specified case format",
|
|
58
64
|
inputSchema: {
|
|
59
|
-
input:
|
|
60
|
-
to:
|
|
65
|
+
input: z3.string().describe("Text to convert"),
|
|
66
|
+
to: z3.enum(["upper", "lower", "capitalize", "camel", "snake", "kebab"]).describe("Target case format")
|
|
61
67
|
},
|
|
62
|
-
handler: async ({ input, to }) => text(convert(input, to))
|
|
68
|
+
handler: async ({ input, to }) => text(convert(input, to)),
|
|
69
|
+
examples: [
|
|
70
|
+
{ args: [`"hello world"`, "camel"], result: "helloWorld" },
|
|
71
|
+
{ args: [`"helloWorld"`, "snake"], result: "hello_world" },
|
|
72
|
+
{ args: [`"hello world"`, "kebab"], result: "hello-world" }
|
|
73
|
+
]
|
|
63
74
|
}),
|
|
64
75
|
truncateTool: toolDef({
|
|
65
76
|
name: "truncate",
|
|
66
77
|
description: "Truncates text to a maximum length and appends a suffix",
|
|
67
78
|
inputSchema: {
|
|
68
|
-
input:
|
|
69
|
-
maxLength:
|
|
70
|
-
suffix:
|
|
79
|
+
input: z3.string().describe("Text to truncate"),
|
|
80
|
+
maxLength: z3.number().int().positive().describe("Maximum character length"),
|
|
81
|
+
suffix: z3.string().default("...").describe("Suffix to append when truncated")
|
|
71
82
|
},
|
|
72
83
|
handler: async ({ input, maxLength, suffix }) => {
|
|
73
84
|
const result = input.length <= maxLength ? input : input.slice(0, maxLength - suffix.length) + suffix;
|
|
74
85
|
return text(result);
|
|
75
|
-
}
|
|
86
|
+
},
|
|
87
|
+
examples: [
|
|
88
|
+
{ args: [`"hello world long text"`, "10"], result: "hello w..." },
|
|
89
|
+
{ args: [`"hello world"`, "8", `"\u2026"`], result: "hello w\u2026" }
|
|
90
|
+
]
|
|
76
91
|
})
|
|
77
92
|
};
|
|
78
93
|
var cnTool = defineTool(tools.cnTool);
|
|
@@ -5,54 +5,52 @@ description: Use this skill to invoke text utility functions via the mono-rele2-
|
|
|
5
5
|
|
|
6
6
|
# mono-rele2-utils
|
|
7
7
|
|
|
8
|
-
CLI for running text utility functions from the mono-rele2 package.
|
|
9
|
-
|
|
10
8
|
```sh
|
|
11
9
|
mono-rele2-utils <skillName> [...args]
|
|
12
10
|
```
|
|
13
11
|
|
|
14
12
|
## Skills
|
|
15
13
|
|
|
16
|
-
###
|
|
14
|
+
### cnTool
|
|
17
15
|
|
|
18
|
-
|
|
16
|
+
Merges class names, filtering out falsy values
|
|
19
17
|
|
|
20
18
|
| arg | description |
|
|
21
19
|
|-----|-------------|
|
|
22
|
-
| `
|
|
23
|
-
| `to` | Target format: `upper` \| `lower` \| `capitalize` \| `camel` \| `snake` \| `kebab` |
|
|
20
|
+
| `classes` | List of class names to merge |
|
|
24
21
|
|
|
25
|
-
###
|
|
22
|
+
### caseConvertTool
|
|
26
23
|
|
|
27
|
-
|
|
24
|
+
Converts text to the specified case format
|
|
28
25
|
|
|
29
26
|
| arg | description |
|
|
30
27
|
|-----|-------------|
|
|
31
|
-
| `
|
|
28
|
+
| `input` | Text to convert |
|
|
29
|
+
| `to` | Target case format — `upper` \| `lower` \| `capitalize` \| `camel` \| `snake` \| `kebab` |
|
|
32
30
|
|
|
33
31
|
### truncateTool
|
|
34
32
|
|
|
35
|
-
Truncates text to a maximum length and appends a suffix
|
|
33
|
+
Truncates text to a maximum length and appends a suffix
|
|
36
34
|
|
|
37
35
|
| arg | description |
|
|
38
36
|
|-----|-------------|
|
|
39
37
|
| `input` | Text to truncate |
|
|
40
38
|
| `maxLength` | Maximum character length |
|
|
41
|
-
| `suffix` | Suffix to append when truncated
|
|
39
|
+
| `suffix` | Suffix to append when truncated — default: `...` |
|
|
42
40
|
|
|
43
41
|
## Examples
|
|
44
42
|
|
|
43
|
+
- `mono-rele2-utils cnTool '["btn","active","large"]'` → `btn active large`
|
|
45
44
|
- `mono-rele2-utils caseConvertTool "hello world" camel` → `helloWorld`
|
|
46
45
|
- `mono-rele2-utils caseConvertTool "helloWorld" snake` → `hello_world`
|
|
47
46
|
- `mono-rele2-utils caseConvertTool "hello world" kebab` → `hello-world`
|
|
48
47
|
- `mono-rele2-utils truncateTool "hello world long text" 10` → `hello w...`
|
|
49
48
|
- `mono-rele2-utils truncateTool "hello world" 8 "…"` → `hello w…`
|
|
50
|
-
- `mono-rele2-utils cnTool '["btn","active","large"]'` → `btn active large`
|
|
51
49
|
|
|
52
50
|
## Guidelines
|
|
53
51
|
|
|
54
52
|
- Arguments are positional — pass them in the order listed in each skill's table
|
|
55
|
-
- Numeric args
|
|
56
|
-
- Array args
|
|
57
|
-
- Optional args with defaults
|
|
53
|
+
- Numeric args are auto-parsed — pass as plain numbers (e.g. `10`)
|
|
54
|
+
- Array args must be valid JSON — wrap in single quotes on Unix shells (e.g. `'["a","b"]'`)
|
|
55
|
+
- Optional args with defaults may be omitted
|
|
58
56
|
- Run `mono-rele2-utils` with no args to list all available skills
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@julong/mono-rele2-utils",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
|
+
"description": "Use this skill to invoke text utility functions via the mono-rele2-utils CLI. Handles class name merging, case conversion, and text truncation.",
|
|
4
5
|
"license": "ISC",
|
|
5
6
|
"type": "module",
|
|
6
7
|
"exports": {
|
|
@@ -22,7 +23,8 @@
|
|
|
22
23
|
"scripts": {
|
|
23
24
|
"build": "tsup",
|
|
24
25
|
"typecheck": "tsc --noEmit",
|
|
25
|
-
"clean": "rimraf dist"
|
|
26
|
+
"clean": "rimraf dist",
|
|
27
|
+
"update-readme": "node ../common/build/update-readme.mjs"
|
|
26
28
|
},
|
|
27
29
|
"dependencies": {
|
|
28
30
|
"@modelcontextprotocol/sdk": "^1.29.0",
|