@julong/mono-rele2-utils 1.30.0 → 1.31.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 CHANGED
@@ -57,32 +57,27 @@ mono-rele2-utils-cli
57
57
  **Signature**
58
58
 
59
59
  ```typescript
60
- function cn(classes: string[]): string
60
+ function cn(classes: string[]): string;
61
61
  ```
62
62
 
63
63
  Merges class names, filtering out falsy values.
64
64
 
65
-
66
65
  **Parameters**
67
66
 
68
- | Name | Type | Description |
69
- |------|------|-------------|
67
+ | Name | Type | Description |
68
+ | --------- | ---------- | ---------------------------- |
70
69
  | `classes` | `string[]` | List of class names to merge |
71
70
 
72
-
73
71
  **Returns**
74
72
 
75
73
  `string` — Merged class name string with falsy values filtered out
76
74
 
77
-
78
75
  **CLI**
79
76
 
80
77
  ```sh
81
78
  mono-rele2-utils-cli cnTool <classes>
82
79
  ```
83
80
 
84
-
85
-
86
81
  **Examples**
87
82
 
88
83
  ```sh
@@ -95,43 +90,43 @@ mono-rele2-utils-cli cnTool '["btn","active","large"]'
95
90
  **Signature**
96
91
 
97
92
  ```typescript
98
- function case_convert(input: string, to: "upper" | "lower" | "capitalize" | "camel" | "snake" | "kebab"): string
93
+ function case_convert(
94
+ input: string,
95
+ to: 'upper' | 'lower' | 'capitalize' | 'camel' | 'snake' | 'kebab',
96
+ ): string;
99
97
  ```
100
98
 
101
99
  Converts text to the specified case format.
102
100
 
103
-
104
101
  **Parameters**
105
102
 
106
- | Name | Type | Description |
107
- |------|------|-------------|
103
+ | Name | Type | Description |
104
+ | ------- | -------- | --------------- | ------------ | ------- | ------- | -------- | ------------------ |
108
105
  | `input` | `string` | Text to convert |
109
- | `to` | `"upper" | "lower" | "capitalize" | "camel" | "snake" | "kebab"` | Target case format |
110
-
106
+ | `to` | `"upper" | "lower" | "capitalize" | "camel" | "snake" | "kebab"` | Target case format |
111
107
 
112
108
  **Returns**
113
109
 
114
110
  `string` — Converted text in the target case format
115
111
 
116
-
117
112
  **CLI**
118
113
 
119
114
  ```sh
120
115
  mono-rele2-utils-cli caseConvertTool <input> <to>
121
116
  ```
122
117
 
123
-
124
-
125
118
  **Examples**
126
119
 
127
120
  ```sh
128
121
  mono-rele2-utils-cli caseConvertTool "hello world" camel
129
122
  # → helloWorld
130
123
  ```
124
+
131
125
  ```sh
132
126
  mono-rele2-utils-cli caseConvertTool "helloWorld" snake
133
127
  # → hello_world
134
128
  ```
129
+
135
130
  ```sh
136
131
  mono-rele2-utils-cli caseConvertTool "hello world" kebab
137
132
  # → hello-world
@@ -142,40 +137,36 @@ mono-rele2-utils-cli caseConvertTool "hello world" kebab
142
137
  **Signature**
143
138
 
144
139
  ```typescript
145
- function truncate(input: string, maxLength: number, suffix?: string): string
140
+ function truncate(input: string, maxLength: number, suffix?: string): string;
146
141
  ```
147
142
 
148
143
  Truncates text to a maximum length and appends a suffix.
149
144
 
150
-
151
145
  **Parameters**
152
146
 
153
- | Name | Type | Description |
154
- |------|------|-------------|
155
- | `input` | `string` | Text to truncate |
156
- | `maxLength` | `number` | Maximum character length |
157
- | `suffix` | `string` | Suffix to append when truncated (default: `...`) |
158
-
147
+ | Name | Type | Description |
148
+ | ----------- | -------- | ------------------------------------------------ |
149
+ | `input` | `string` | Text to truncate |
150
+ | `maxLength` | `number` | Maximum character length |
151
+ | `suffix` | `string` | Suffix to append when truncated (default: `...`) |
159
152
 
160
153
  **Returns**
161
154
 
162
155
  `string` — Truncated text with the configured suffix appended if truncated
163
156
 
164
-
165
157
  **CLI**
166
158
 
167
159
  ```sh
168
160
  mono-rele2-utils-cli truncateTool <input> <maxLength> [suffix]
169
161
  ```
170
162
 
171
-
172
-
173
163
  **Examples**
174
164
 
175
165
  ```sh
176
166
  mono-rele2-utils-cli truncateTool "hello world long text" 10
177
167
  # → hello w...
178
168
  ```
169
+
179
170
  ```sh
180
171
  mono-rele2-utils-cli truncateTool "hello world" 8 "…"
181
172
  # → hello w…
@@ -191,27 +182,22 @@ function object_flatten(json: string \| JSON object): JsonObject
191
182
 
192
183
  Flattens a nested JSON object of any depth into dot-notation key-value pairs. Accepts a JSON string and recursively flattens all levels. Arrays and primitives at any level are treated as leaf values..
193
184
 
194
-
195
185
  **Parameters**
196
186
 
197
- | Name | Type | Description |
198
- |------|------|-------------|
187
+ | Name | Type | Description |
188
+ | ------ | ----------------------- | --------------------------------------------------------- |
199
189
  | `json` | `string \| JSON object` | JSON string or parsed object to flatten (unlimited depth) |
200
190
 
201
-
202
191
  **Returns**
203
192
 
204
193
  `JsonObject` — Flattened object with dot-notation keys — e.g. { "a.b.c": value }
205
194
 
206
-
207
195
  **CLI**
208
196
 
209
197
  ```sh
210
198
  mono-rele2-utils-cli objectFlattenTool <json>
211
199
  ```
212
200
 
213
-
214
-
215
201
  **Examples**
216
202
 
217
203
  ```sh
@@ -223,6 +209,7 @@ mono-rele2-utils-cli objectFlattenTool '{"user":{"name":"Alice","address":{"city
223
209
  "active": true
224
210
  }
225
211
  ```
212
+
226
213
  ```sh
227
214
  mono-rele2-utils-cli objectFlattenTool '{"a":{"b":{"c":{"d":{"e":"deep"}}}}}'
228
215
  # → {
@@ -235,36 +222,32 @@ mono-rele2-utils-cli objectFlattenTool '{"a":{"b":{"c":{"d":{"e":"deep"}}}}}'
235
222
  **Signature**
236
223
 
237
224
  ```typescript
238
- function getUser(user: RandomUser): string
225
+ function getUser(user: RandomUser): string;
239
226
  ```
240
227
 
241
228
  RandomUser API 형식의 사용자 객체를 받아 이름과 거주 도시로 구성된 한글 문장을 반환합니다. JSON 문자열 또는 파싱된 객체를 입력받습니다..
242
229
 
243
-
244
230
  **Parameters**
245
231
 
246
- | Name | Type | Description |
247
- |------|------|-------------|
232
+ | Name | Type | Description |
233
+ | ------ | ------------ | ------------------------------------------------------------------------------------- |
248
234
  | `user` | `RandomUser` | RandomUser 형식의 JSON 문자열 또는 객체 — name.first / name.last / location.city 필수 |
249
235
 
250
-
251
236
  **Returns**
252
237
 
253
238
  `string` — "이름은 {first} {last} 이고 현재 {city} 에 살고 있습니다." 형식의 한글 문장
254
239
 
255
-
256
240
  **CLI**
257
241
 
258
242
  ```sh
259
243
  mono-rele2-utils-cli getUserTool <user>
260
244
  ```
261
245
 
262
-
263
246
  **`user`** type definition
264
247
 
265
248
  ```typescript
266
249
  interface RandomUser {
267
- gender: "male" | "female";
250
+ gender: 'male' | 'female';
268
251
  name: {
269
252
  title: string;
270
253
  first: string;
@@ -308,7 +291,6 @@ interface RandomUser {
308
291
  }
309
292
  ```
310
293
 
311
-
312
294
  **Examples**
313
295
 
314
296
  ```sh
@@ -321,31 +303,27 @@ mono-rele2-utils-cli getUserTool '{"name":{"title":"Mr","first":"Alice","last":"
321
303
  **Signature**
322
304
 
323
305
  ```typescript
324
- function env_get(keys: string[]): Record<string, string>
306
+ function env_get(keys: string[]): Record<string, string>;
325
307
  ```
326
308
 
327
309
  MCP 클라이언트 config의 env 필드를 통해 주입된 환경 변수 값을 조회합니다. 조회 가능한 키는 패키지에서 제공하는 환경 변수로 한정됩니다. 현재 지원: API_KEY..
328
310
 
329
-
330
311
  **Parameters**
331
312
 
332
- | Name | Type | Description |
333
- |------|------|-------------|
313
+ | Name | Type | Description |
314
+ | ------ | ---------- | --------------------------------------------- |
334
315
  | `keys` | `string[]` | 조회할 환경 변수 이름 목록 (유효 키: API_KEY) |
335
316
 
336
-
337
317
  **Returns**
338
318
 
339
319
  `Record<string, string>` — key: 환경 변수 이름, value: 해당 값 (설정되지 않은 변수는 결과에서 제외)
340
320
 
341
-
342
321
  **CLI**
343
322
 
344
323
  ```sh
345
324
  mono-rele2-utils-cli envGetTool <keys>
346
325
  ```
347
326
 
348
-
349
327
  **`keys`** type definition
350
328
 
351
329
  ```typescript
@@ -366,7 +344,6 @@ mono-rele2-utils-cli envGetTool <keys>
366
344
  // }
367
345
  ```
368
346
 
369
-
370
347
  **Examples**
371
348
 
372
349
  ```sh
package/dist/cli.cjs ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ "use strict";function r(e){return{content:[{type:"text",text:e}]}}var O=require("@modelcontextprotocol/sdk/server/mcp.js"),A=require("@modelcontextprotocol/sdk/server/stdio.js");var y=require("zod");async function j(e){let[,,n,...t]=process.argv;(!n||!(n in e))&&(n&&console.error(`Unknown skill: "${n}"
3
+ `),process.exit(n?1:0));let o=e[n],s=Object.keys(o.inputSchema),c={};for(let i=0;i<s.length;i++){let g=t[i];if(g!==void 0)try{c[s[i]]=JSON.parse(g)}catch{c[s[i]]=g}}let f=y.z.object(o.inputSchema).parse(c),m=await o.handler(f);for(let i of m.content)i.type==="text"&&console.log(i.text)}function Z(e){e instanceof y.z.ZodError?console.error("Validation error:",e.issues.map(n=>`${n.path.join(".")}: ${n.message}`).join(", ")):console.error("Error:",e instanceof Error?e.message:String(e)),process.exit(1)}var k=require("zod");var a=require("zod");function w(...e){return e.filter(Boolean).join(" ")}var d={cnTool:{name:"cn",description:"Merges class names, filtering out falsy values",inputSchema:{classes:a.z.array(a.z.string()).describe("List of class names to merge")},typeLabels:{classes:"string[]"},returnType:"string",returnDescription:"Merged class name string with falsy values filtered out",handler:async({classes:e})=>r(w(...e)),examples:[{args:[`'["btn","active","large"]'`],result:"btn active large"}]},caseConvertTool:{name:"case_convert",description:"Converts text to the specified case format",inputSchema:{input:a.z.string().describe("Text to convert"),to:a.z.enum(["upper","lower","capitalize","camel","snake","kebab"]).describe("Target case format")},typeLabels:{input:"string",to:'"upper" | "lower" | "capitalize" | "camel" | "snake" | "kebab"'},returnType:"string",returnDescription:"Converted text in the target case format",handler:async({input:e,to:n})=>r(N(e,n)),examples:[{args:['"hello world"',"camel"],result:"helloWorld"},{args:['"helloWorld"',"snake"],result:"hello_world"},{args:['"hello world"',"kebab"],result:"hello-world"}]},truncateTool:{name:"truncate",description:"Truncates text to a maximum length and appends a suffix",inputSchema:{input:a.z.string().describe("Text to truncate"),maxLength:a.z.number().int().positive().describe("Maximum character length"),suffix:a.z.string().default("...").describe("Suffix to append when truncated")},typeLabels:{input:"string",maxLength:"number",suffix:"string"},returnType:"string",returnDescription:"Truncated text with the configured suffix appended if truncated",handler:async({input:e,maxLength:n,suffix:t})=>{let o=e.length<=n?e:e.slice(0,n-t.length)+t;return r(o)},examples:[{args:['"hello world long text"',"10"],result:"hello w..."},{args:['"hello world"',"8",'"\u2026"'],result:"hello w\u2026"}]}},z=d.cnTool,D=d.caseConvertTool,R=d.truncateTool;function N(e,n){switch(n){case"upper":return e.toUpperCase();case"lower":return e.toLowerCase();case"capitalize":return e.charAt(0).toUpperCase()+e.slice(1).toLowerCase();case"camel":return e.replace(/[-_\s]+(.)/g,(t,o)=>o.toUpperCase()).replace(/^(.)/,t=>t.toLowerCase());case"snake":return e.replace(/([A-Z])/g,"_$1").replace(/[-\s]+/g,"_").toLowerCase().replace(/^_/,"");case"kebab":return e.replace(/([A-Z])/g,"-$1").replace(/[_\s]+/g,"-").toLowerCase().replace(/^-/,"")}}var p=require("zod");function E(e){let n=typeof e=="string"?JSON.parse(e):e,t={};function o(s,c){if(s===null||typeof s!="object"||Array.isArray(s)){t[c]=s;return}for(let[f,m]of Object.entries(s)){let i=c?`${c}.${f}`:f;o(m,i)}}return o(n,""),t}var b={objectFlattenTool:{name:"object_flatten",description:"Flattens a nested JSON object of any depth into dot-notation key-value pairs. Accepts a JSON string and recursively flattens all levels. Arrays and primitives at any level are treated as leaf values.",inputSchema:{json:p.z.union([p.z.string(),p.z.record(p.z.string(),p.z.any())]).describe("JSON string or parsed object to flatten (unlimited depth)")},handler:async({json:e})=>{try{let t=E(e);return r(JSON.stringify(t,null,2))}catch(n){return n instanceof SyntaxError?r("Error: invalid JSON string \u2014 unable to parse input"):r(`Error: failed to flatten object \u2014 ${n.message}`)}},examples:[{args:[`'{"user":{"name":"Alice","address":{"city":"Seoul","zip":"12345"}},"active":true}'`],result:JSON.stringify({"user.name":"Alice","user.address.city":"Seoul","user.address.zip":"12345",active:!0},null,2)},{args:[`'{"a":{"b":{"c":{"d":{"e":"deep"}}}}}'`],result:JSON.stringify({"a.b.c.d.e":"deep"},null,2)}],returnType:"JsonObject",returnDescription:'Flattened object with dot-notation keys \u2014 e.g. { "a.b.c": value }',guidelines:["Arrays and primitives at any level are always treated as leaf values \u2014 they are never traversed.","The result is always a flat JSON object with dot-notation keys.","There is no depth limit \u2014 objects of any nesting level are fully flattened.","Input is accepted as a JSON string (MCP/CLI) and parsed internally."]}},J=b.objectFlattenTool;var u=require("zod");function C(e){let n=typeof e=="string"?JSON.parse(e):e,{first:t,last:o}=n.name,s=n.location.city;return`\uC774\uB984\uC740 ${t} ${o} \uC774\uACE0 \uD604\uC7AC ${s} \uC5D0 \uC0B4\uACE0 \uC788\uC2B5\uB2C8\uB2E4.`}var x={getUserTool:{name:"getUser",description:"RandomUser API \uD615\uC2DD\uC758 \uC0AC\uC6A9\uC790 \uAC1D\uCCB4\uB97C \uBC1B\uC544 \uC774\uB984\uACFC \uAC70\uC8FC \uB3C4\uC2DC\uB85C \uAD6C\uC131\uB41C \uD55C\uAE00 \uBB38\uC7A5\uC744 \uBC18\uD658\uD569\uB2C8\uB2E4. JSON \uBB38\uC790\uC5F4 \uB610\uB294 \uD30C\uC2F1\uB41C \uAC1D\uCCB4\uB97C \uC785\uB825\uBC1B\uC2B5\uB2C8\uB2E4.",inputSchema:{user:u.z.union([u.z.string(),u.z.record(u.z.string(),u.z.any())]).describe("RandomUser \uD615\uC2DD\uC758 JSON \uBB38\uC790\uC5F4 \uB610\uB294 \uAC1D\uCCB4 \u2014 name.first / name.last / location.city \uD544\uC218")},typeLabels:{user:"RandomUser"},typeDefs:{user:["interface RandomUser {",' gender: "male" | "female";'," name: {"," title: string;"," first: string;"," last: string;"," };"," location: {"," street: {"," number: number;"," name: string;"," };"," city: string;"," state: string;"," country: string;"," postcode: string | number;"," coordinates: {"," latitude: string;"," longitude: string;"," };"," timezone: {"," offset: string;"," description: string;"," };"," };"," email: string;"," login: {"," uuid: string;"," username: string;"," };"," dob: {"," date: string;"," age: number;"," };"," phone: string;"," cell: string;"," picture: {"," large: string;"," medium: string;"," thumbnail: string;"," };"," nat: string;","}"].join(`
4
+ `)},returnType:"string",returnDescription:'"\uC774\uB984\uC740 {first} {last} \uC774\uACE0 \uD604\uC7AC {city} \uC5D0 \uC0B4\uACE0 \uC788\uC2B5\uB2C8\uB2E4." \uD615\uC2DD\uC758 \uD55C\uAE00 \uBB38\uC7A5',handler:async({user:e})=>{try{let t=C(e);return r(t)}catch(n){return n instanceof SyntaxError?r("Error: invalid JSON string \u2014 unable to parse input"):r(`Error: failed to process user data \u2014 ${n.message}
5
+
6
+ Input must include \`name.first\`, \`name.last\`, and \`location.city\`.`)}},examples:[{args:[`'{"name":{"title":"Mr","first":"Alice","last":"Kim"},"location":{"city":"Seoul"},"gender":"female","email":"alice@example.com","nat":"KR"}'`],result:"\uC774\uB984\uC740 Alice Kim \uC774\uACE0 \uD604\uC7AC Seoul \uC5D0 \uC0B4\uACE0 \uC788\uC2B5\uB2C8\uB2E4."}],guidelines:["\uC785\uB825\uC740 RandomUser API \uC2A4\uD399\uC744 \uB530\uB985\uB2C8\uB2E4. \uCD5C\uC18C\uD55C name.first, name.last, location.city \uD544\uB4DC\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.","JSON \uBB38\uC790\uC5F4(string)\uACFC \uD30C\uC2F1\uB41C \uAC1D\uCCB4 \uBAA8\uB450 \uD5C8\uC6A9\uB429\uB2C8\uB2E4 (CLI / MCP \uBAA8\uB450 \uB3D9\uC791).","\uACB0\uACFC\uB294 \uD56D\uC0C1 '\uC774\uB984\uC740 {first} {last} \uC774\uACE0 \uD604\uC7AC {city} \uC5D0 \uC0B4\uACE0 \uC788\uC2B5\uB2C8\uB2E4.' \uD615\uC2DD\uC758 \uD55C\uAE00 \uBB38\uC7A5\uC785\uB2C8\uB2E4."]}},U=x.getUserTool;var S=require("zod"),l=["API_KEY"];function L(e){let n=e.filter(o=>!l.includes(o));if(n.length>0)throw new Error(`Invalid env key(s): ${n.join(", ")}. Allowed keys: ${l.join(", ")}`);let t={};for(let o of e){let s=process.env[o];s!==void 0&&(t[o]=s)}return t}var $={envGetTool:{name:"env_get",description:`MCP \uD074\uB77C\uC774\uC5B8\uD2B8 config\uC758 env \uD544\uB4DC\uB97C \uD1B5\uD574 \uC8FC\uC785\uB41C \uD658\uACBD \uBCC0\uC218 \uAC12\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4. \uC870\uD68C \uAC00\uB2A5\uD55C \uD0A4\uB294 \uD328\uD0A4\uC9C0\uC5D0\uC11C \uC81C\uACF5\uD558\uB294 \uD658\uACBD \uBCC0\uC218\uB85C \uD55C\uC815\uB429\uB2C8\uB2E4. \uD604\uC7AC \uC9C0\uC6D0: ${l.join(", ")}.`,inputSchema:{keys:S.z.array(S.z.string()).nonempty().describe(`\uC870\uD68C\uD560 \uD658\uACBD \uBCC0\uC218 \uC774\uB984 \uBAA9\uB85D (\uC720\uD6A8 \uD0A4: ${l.join(", ")})`)},typeLabels:{keys:"string[]"},typeDefs:{keys:["// @julong/mono-rele2-utils \uD658\uACBD \uBCC0\uC218 \uD0A4 \uBAA9\uB85D",...l.map(e=>`// "${e}"`),"","// MCP client config \uC608\uC2DC:","// {",'// "mcpServers": {','// "@julong/mono-rele2-utils": {','// "command": "npx",','// "args": ["-y", "@julong/mono-rele2-utils"],','// "env": {',...l.map(e=>`// "${e}": "<value>"`),"// }","// }","// }","// }"].join(`
7
+ `)},returnType:"Record<string, string>",returnDescription:"key: \uD658\uACBD \uBCC0\uC218 \uC774\uB984, value: \uD574\uB2F9 \uAC12 (\uC124\uC815\uB418\uC9C0 \uC54A\uC740 \uBCC0\uC218\uB294 \uACB0\uACFC\uC5D0\uC11C \uC81C\uC678)",handler:async({keys:e})=>{try{let n=L(e);return Object.keys(n).length===0?r("(no matching environment variables found)"):r(JSON.stringify(n,null,2))}catch(n){return r(`Error: ${n.message}`)}},examples:[{args:[`'["API_KEY"]'`],result:JSON.stringify({API_KEY:"<value>"},null,2)}],guidelines:[`\uC870\uD68C \uAC00\uB2A5\uD55C \uD0A4: ${l.join(", ")}`,"MCP client config.json\uC758 env \uD544\uB4DC\uC5D0 \uC704 \uD0A4\uB4E4\uB9CC \uC124\uC815\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.","\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uD0A4\uB97C \uC694\uCCAD\uD558\uBA74 \uC5D0\uB7EC \uBA54\uC2DC\uC9C0\uC5D0 \uD5C8\uC6A9\uB41C \uD0A4 \uBAA9\uB85D\uC774 \uD45C\uC2DC\uB429\uB2C8\uB2E4.","\uC124\uC815\uB418\uC9C0 \uC54A\uC740 \uD658\uACBD \uBCC0\uC218\uB294 \uACB0\uACFC \uAC1D\uCCB4\uC5D0\uC11C \uC81C\uC678\uB429\uB2C8\uB2E4."]}},_=$.envGetTool;var v={...d,...b,...x,...$};j(v).catch(Z);
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- function r(e){return{content:[{type:"text",text:e}]}}import{McpServer as _}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as I}from"@modelcontextprotocol/sdk/server/stdio.js";import{z as S}from"zod";async function $(e){let[,,n,...t]=process.argv;(!n||!(n in e))&&(n&&console.error(`Unknown skill: "${n}"
3
- `),process.exit(n?1:0));let o=e[n],s=Object.keys(o.inputSchema),l={};for(let i=0;i<s.length;i++){let g=t[i];if(g!==void 0)try{l[s[i]]=JSON.parse(g)}catch{l[s[i]]=g}}let f=S.object(o.inputSchema).parse(l),m=await o.handler(f);for(let i of m.content)i.type==="text"&&console.log(i.text)}function j(e){e instanceof S.ZodError?console.error("Validation error:",e.issues.map(n=>`${n.path.join(".")}: ${n.message}`).join(", ")):console.error("Error:",e instanceof Error?e.message:String(e)),process.exit(1)}import{z as G}from"zod";import{z as c}from"zod";function Z(...e){return e.filter(Boolean).join(" ")}var p={cnTool:{name:"cn",description:"Merges class names, filtering out falsy values",inputSchema:{classes:c.array(c.string()).describe("List of class names to merge")},typeLabels:{classes:"string[]"},returnType:"string",returnDescription:"Merged class name string with falsy values filtered out",handler:async({classes:e})=>r(Z(...e)),examples:[{args:[`'["btn","active","large"]'`],result:"btn active large"}]},caseConvertTool:{name:"case_convert",description:"Converts text to the specified case format",inputSchema:{input:c.string().describe("Text to convert"),to:c.enum(["upper","lower","capitalize","camel","snake","kebab"]).describe("Target case format")},typeLabels:{input:"string",to:'"upper" | "lower" | "capitalize" | "camel" | "snake" | "kebab"'},returnType:"string",returnDescription:"Converted text in the target case format",handler:async({input:e,to:n})=>r(z(e,n)),examples:[{args:['"hello world"',"camel"],result:"helloWorld"},{args:['"helloWorld"',"snake"],result:"hello_world"},{args:['"hello world"',"kebab"],result:"hello-world"}]},truncateTool:{name:"truncate",description:"Truncates text to a maximum length and appends a suffix",inputSchema:{input:c.string().describe("Text to truncate"),maxLength:c.number().int().positive().describe("Maximum character length"),suffix:c.string().default("...").describe("Suffix to append when truncated")},typeLabels:{input:"string",maxLength:"number",suffix:"string"},returnType:"string",returnDescription:"Truncated text with the configured suffix appended if truncated",handler:async({input:e,maxLength:n,suffix:t})=>{let o=e.length<=n?e:e.slice(0,n-t.length)+t;return r(o)},examples:[{args:['"hello world long text"',"10"],result:"hello w..."},{args:['"hello world"',"8",'"\u2026"'],result:"hello w\u2026"}]}},O=p.cnTool,A=p.caseConvertTool,k=p.truncateTool;function z(e,n){switch(n){case"upper":return e.toUpperCase();case"lower":return e.toLowerCase();case"capitalize":return e.charAt(0).toUpperCase()+e.slice(1).toLowerCase();case"camel":return e.replace(/[-_\s]+(.)/g,(t,o)=>o.toUpperCase()).replace(/^(.)/,t=>t.toLowerCase());case"snake":return e.replace(/([A-Z])/g,"_$1").replace(/[-\s]+/g,"_").toLowerCase().replace(/^_/,"");case"kebab":return e.replace(/([A-Z])/g,"-$1").replace(/[_\s]+/g,"-").toLowerCase().replace(/^-/,"")}}import{z as u}from"zod";function D(e){let n=typeof e=="string"?JSON.parse(e):e,t={};function o(s,l){if(s===null||typeof s!="object"||Array.isArray(s)){t[l]=s;return}for(let[f,m]of Object.entries(s)){let i=l?`${l}.${f}`:f;o(m,i)}}return o(n,""),t}var h={objectFlattenTool:{name:"object_flatten",description:"Flattens a nested JSON object of any depth into dot-notation key-value pairs. Accepts a JSON string and recursively flattens all levels. Arrays and primitives at any level are treated as leaf values.",inputSchema:{json:u.union([u.string(),u.record(u.string(),u.any())]).describe("JSON string or parsed object to flatten (unlimited depth)")},handler:async({json:e})=>{try{let t=D(e);return r(JSON.stringify(t,null,2))}catch(n){return n instanceof SyntaxError?r("Error: invalid JSON string \u2014 unable to parse input"):r(`Error: failed to flatten object \u2014 ${n.message}`)}},examples:[{args:[`'{"user":{"name":"Alice","address":{"city":"Seoul","zip":"12345"}},"active":true}'`],result:JSON.stringify({"user.name":"Alice","user.address.city":"Seoul","user.address.zip":"12345",active:!0},null,2)},{args:[`'{"a":{"b":{"c":{"d":{"e":"deep"}}}}}'`],result:JSON.stringify({"a.b.c.d.e":"deep"},null,2)}],returnType:"JsonObject",returnDescription:'Flattened object with dot-notation keys \u2014 e.g. { "a.b.c": value }',guidelines:["Arrays and primitives at any level are always treated as leaf values \u2014 they are never traversed.","The result is always a flat JSON object with dot-notation keys.","There is no depth limit \u2014 objects of any nesting level are fully flattened.","Input is accepted as a JSON string (MCP/CLI) and parsed internally."]}},R=h.objectFlattenTool;import{z as d}from"zod";function E(e){let n=typeof e=="string"?JSON.parse(e):e,{first:t,last:o}=n.name,s=n.location.city;return`\uC774\uB984\uC740 ${t} ${o} \uC774\uACE0 \uD604\uC7AC ${s} \uC5D0 \uC0B4\uACE0 \uC788\uC2B5\uB2C8\uB2E4.`}var b={getUserTool:{name:"getUser",description:"RandomUser API \uD615\uC2DD\uC758 \uC0AC\uC6A9\uC790 \uAC1D\uCCB4\uB97C \uBC1B\uC544 \uC774\uB984\uACFC \uAC70\uC8FC \uB3C4\uC2DC\uB85C \uAD6C\uC131\uB41C \uD55C\uAE00 \uBB38\uC7A5\uC744 \uBC18\uD658\uD569\uB2C8\uB2E4. JSON \uBB38\uC790\uC5F4 \uB610\uB294 \uD30C\uC2F1\uB41C \uAC1D\uCCB4\uB97C \uC785\uB825\uBC1B\uC2B5\uB2C8\uB2E4.",inputSchema:{user:d.union([d.string(),d.record(d.string(),d.any())]).describe("RandomUser \uD615\uC2DD\uC758 JSON \uBB38\uC790\uC5F4 \uB610\uB294 \uAC1D\uCCB4 \u2014 name.first / name.last / location.city \uD544\uC218")},typeLabels:{user:"RandomUser"},typeDefs:{user:["interface RandomUser {",' gender: "male" | "female";'," name: {"," title: string;"," first: string;"," last: string;"," };"," location: {"," street: {"," number: number;"," name: string;"," };"," city: string;"," state: string;"," country: string;"," postcode: string | number;"," coordinates: {"," latitude: string;"," longitude: string;"," };"," timezone: {"," offset: string;"," description: string;"," };"," };"," email: string;"," login: {"," uuid: string;"," username: string;"," };"," dob: {"," date: string;"," age: number;"," };"," phone: string;"," cell: string;"," picture: {"," large: string;"," medium: string;"," thumbnail: string;"," };"," nat: string;","}"].join(`
4
- `)},returnType:"string",returnDescription:'"\uC774\uB984\uC740 {first} {last} \uC774\uACE0 \uD604\uC7AC {city} \uC5D0 \uC0B4\uACE0 \uC788\uC2B5\uB2C8\uB2E4." \uD615\uC2DD\uC758 \uD55C\uAE00 \uBB38\uC7A5',handler:async({user:e})=>{try{let t=E(e);return r(t)}catch(n){return n instanceof SyntaxError?r("Error: invalid JSON string \u2014 unable to parse input"):r(`Error: failed to process user data \u2014 ${n.message}
2
+ function r(e){return{content:[{type:"text",text:e}]}}import{McpServer as M}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as I}from"@modelcontextprotocol/sdk/server/stdio.js";import{z as S}from"zod";async function $(e){let[,,n,...t]=process.argv;(!n||!(n in e))&&(n&&console.error(`Unknown skill: "${n}"
3
+ `),process.exit(n?1:0));let o=e[n],s=Object.keys(o.inputSchema),l={};for(let i=0;i<s.length;i++){let g=t[i];if(g!==void 0)try{l[s[i]]=JSON.parse(g)}catch{l[s[i]]=g}}let f=S.object(o.inputSchema).parse(l),m=await o.handler(f);for(let i of m.content)i.type==="text"&&console.log(i.text)}function j(e){e instanceof S.ZodError?console.error("Validation error:",e.issues.map(n=>`${n.path.join(".")}: ${n.message}`).join(", ")):console.error("Error:",e instanceof Error?e.message:String(e)),process.exit(1)}import{z as G}from"zod";import{z as c}from"zod";function Z(...e){return e.filter(Boolean).join(" ")}var p={cnTool:{name:"cn",description:"Merges class names, filtering out falsy values",inputSchema:{classes:c.array(c.string()).describe("List of class names to merge")},typeLabels:{classes:"string[]"},returnType:"string",returnDescription:"Merged class name string with falsy values filtered out",handler:async({classes:e})=>r(Z(...e)),examples:[{args:[`'["btn","active","large"]'`],result:"btn active large"}]},caseConvertTool:{name:"case_convert",description:"Converts text to the specified case format",inputSchema:{input:c.string().describe("Text to convert"),to:c.enum(["upper","lower","capitalize","camel","snake","kebab"]).describe("Target case format")},typeLabels:{input:"string",to:'"upper" | "lower" | "capitalize" | "camel" | "snake" | "kebab"'},returnType:"string",returnDescription:"Converted text in the target case format",handler:async({input:e,to:n})=>r(z(e,n)),examples:[{args:['"hello world"',"camel"],result:"helloWorld"},{args:['"helloWorld"',"snake"],result:"hello_world"},{args:['"hello world"',"kebab"],result:"hello-world"}]},truncateTool:{name:"truncate",description:"Truncates text to a maximum length and appends a suffix",inputSchema:{input:c.string().describe("Text to truncate"),maxLength:c.number().int().positive().describe("Maximum character length"),suffix:c.string().default("...").describe("Suffix to append when truncated")},typeLabels:{input:"string",maxLength:"number",suffix:"string"},returnType:"string",returnDescription:"Truncated text with the configured suffix appended if truncated",handler:async({input:e,maxLength:n,suffix:t})=>{let o=e.length<=n?e:e.slice(0,n-t.length)+t;return r(o)},examples:[{args:['"hello world long text"',"10"],result:"hello w..."},{args:['"hello world"',"8",'"\u2026"'],result:"hello w\u2026"}]}},O=p.cnTool,A=p.caseConvertTool,k=p.truncateTool;function z(e,n){switch(n){case"upper":return e.toUpperCase();case"lower":return e.toLowerCase();case"capitalize":return e.charAt(0).toUpperCase()+e.slice(1).toLowerCase();case"camel":return e.replace(/[-_\s]+(.)/g,(t,o)=>o.toUpperCase()).replace(/^(.)/,t=>t.toLowerCase());case"snake":return e.replace(/([A-Z])/g,"_$1").replace(/[-\s]+/g,"_").toLowerCase().replace(/^_/,"");case"kebab":return e.replace(/([A-Z])/g,"-$1").replace(/[_\s]+/g,"-").toLowerCase().replace(/^-/,"")}}import{z as u}from"zod";function D(e){let n=typeof e=="string"?JSON.parse(e):e,t={};function o(s,l){if(s===null||typeof s!="object"||Array.isArray(s)){t[l]=s;return}for(let[f,m]of Object.entries(s)){let i=l?`${l}.${f}`:f;o(m,i)}}return o(n,""),t}var h={objectFlattenTool:{name:"object_flatten",description:"Flattens a nested JSON object of any depth into dot-notation key-value pairs. Accepts a JSON string and recursively flattens all levels. Arrays and primitives at any level are treated as leaf values.",inputSchema:{json:u.union([u.string(),u.record(u.string(),u.any())]).describe("JSON string or parsed object to flatten (unlimited depth)")},handler:async({json:e})=>{try{let t=D(e);return r(JSON.stringify(t,null,2))}catch(n){return n instanceof SyntaxError?r("Error: invalid JSON string \u2014 unable to parse input"):r(`Error: failed to flatten object \u2014 ${n.message}`)}},examples:[{args:[`'{"user":{"name":"Alice","address":{"city":"Seoul","zip":"12345"}},"active":true}'`],result:JSON.stringify({"user.name":"Alice","user.address.city":"Seoul","user.address.zip":"12345",active:!0},null,2)},{args:[`'{"a":{"b":{"c":{"d":{"e":"deep"}}}}}'`],result:JSON.stringify({"a.b.c.d.e":"deep"},null,2)}],returnType:"JsonObject",returnDescription:'Flattened object with dot-notation keys \u2014 e.g. { "a.b.c": value }',guidelines:["Arrays and primitives at any level are always treated as leaf values \u2014 they are never traversed.","The result is always a flat JSON object with dot-notation keys.","There is no depth limit \u2014 objects of any nesting level are fully flattened.","Input is accepted as a JSON string (MCP/CLI) and parsed internally."]}},R=h.objectFlattenTool;import{z as d}from"zod";function N(e){let n=typeof e=="string"?JSON.parse(e):e,{first:t,last:o}=n.name,s=n.location.city;return`\uC774\uB984\uC740 ${t} ${o} \uC774\uACE0 \uD604\uC7AC ${s} \uC5D0 \uC0B4\uACE0 \uC788\uC2B5\uB2C8\uB2E4.`}var b={getUserTool:{name:"getUser",description:"RandomUser API \uD615\uC2DD\uC758 \uC0AC\uC6A9\uC790 \uAC1D\uCCB4\uB97C \uBC1B\uC544 \uC774\uB984\uACFC \uAC70\uC8FC \uB3C4\uC2DC\uB85C \uAD6C\uC131\uB41C \uD55C\uAE00 \uBB38\uC7A5\uC744 \uBC18\uD658\uD569\uB2C8\uB2E4. JSON \uBB38\uC790\uC5F4 \uB610\uB294 \uD30C\uC2F1\uB41C \uAC1D\uCCB4\uB97C \uC785\uB825\uBC1B\uC2B5\uB2C8\uB2E4.",inputSchema:{user:d.union([d.string(),d.record(d.string(),d.any())]).describe("RandomUser \uD615\uC2DD\uC758 JSON \uBB38\uC790\uC5F4 \uB610\uB294 \uAC1D\uCCB4 \u2014 name.first / name.last / location.city \uD544\uC218")},typeLabels:{user:"RandomUser"},typeDefs:{user:["interface RandomUser {",' gender: "male" | "female";'," name: {"," title: string;"," first: string;"," last: string;"," };"," location: {"," street: {"," number: number;"," name: string;"," };"," city: string;"," state: string;"," country: string;"," postcode: string | number;"," coordinates: {"," latitude: string;"," longitude: string;"," };"," timezone: {"," offset: string;"," description: string;"," };"," };"," email: string;"," login: {"," uuid: string;"," username: string;"," };"," dob: {"," date: string;"," age: number;"," };"," phone: string;"," cell: string;"," picture: {"," large: string;"," medium: string;"," thumbnail: string;"," };"," nat: string;","}"].join(`
4
+ `)},returnType:"string",returnDescription:'"\uC774\uB984\uC740 {first} {last} \uC774\uACE0 \uD604\uC7AC {city} \uC5D0 \uC0B4\uACE0 \uC788\uC2B5\uB2C8\uB2E4." \uD615\uC2DD\uC758 \uD55C\uAE00 \uBB38\uC7A5',handler:async({user:e})=>{try{let t=N(e);return r(t)}catch(n){return n instanceof SyntaxError?r("Error: invalid JSON string \u2014 unable to parse input"):r(`Error: failed to process user data \u2014 ${n.message}
5
5
 
6
- Input must include \`name.first\`, \`name.last\`, and \`location.city\`.`)}},examples:[{args:[`'{"name":{"title":"Mr","first":"Alice","last":"Kim"},"location":{"city":"Seoul"},"gender":"female","email":"alice@example.com","nat":"KR"}'`],result:"\uC774\uB984\uC740 Alice Kim \uC774\uACE0 \uD604\uC7AC Seoul \uC5D0 \uC0B4\uACE0 \uC788\uC2B5\uB2C8\uB2E4."}],guidelines:["\uC785\uB825\uC740 RandomUser API \uC2A4\uD399\uC744 \uB530\uB985\uB2C8\uB2E4. \uCD5C\uC18C\uD55C name.first, name.last, location.city \uD544\uB4DC\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.","JSON \uBB38\uC790\uC5F4(string)\uACFC \uD30C\uC2F1\uB41C \uAC1D\uCCB4 \uBAA8\uB450 \uD5C8\uC6A9\uB429\uB2C8\uB2E4 (CLI / MCP \uBAA8\uB450 \uB3D9\uC791).","\uACB0\uACFC\uB294 \uD56D\uC0C1 '\uC774\uB984\uC740 {first} {last} \uC774\uACE0 \uD604\uC7AC {city} \uC5D0 \uC0B4\uACE0 \uC788\uC2B5\uB2C8\uB2E4.' \uD615\uC2DD\uC758 \uD55C\uAE00 \uBB38\uC7A5\uC785\uB2C8\uB2E4."]}},N=b.getUserTool;import{z as w}from"zod";var a=["API_KEY"];function J(e){let n=e.filter(o=>!a.includes(o));if(n.length>0)throw new Error(`Invalid env key(s): ${n.join(", ")}. Allowed keys: ${a.join(", ")}`);let t={};for(let o of e){let s=process.env[o];s!==void 0&&(t[o]=s)}return t}var x={envGetTool:{name:"env_get",description:`MCP \uD074\uB77C\uC774\uC5B8\uD2B8 config\uC758 env \uD544\uB4DC\uB97C \uD1B5\uD574 \uC8FC\uC785\uB41C \uD658\uACBD \uBCC0\uC218 \uAC12\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4. \uC870\uD68C \uAC00\uB2A5\uD55C \uD0A4\uB294 \uD328\uD0A4\uC9C0\uC5D0\uC11C \uC81C\uACF5\uD558\uB294 \uD658\uACBD \uBCC0\uC218\uB85C \uD55C\uC815\uB429\uB2C8\uB2E4. \uD604\uC7AC \uC9C0\uC6D0: ${a.join(", ")}.`,inputSchema:{keys:w.array(w.string()).nonempty().describe(`\uC870\uD68C\uD560 \uD658\uACBD \uBCC0\uC218 \uC774\uB984 \uBAA9\uB85D (\uC720\uD6A8 \uD0A4: ${a.join(", ")})`)},typeLabels:{keys:"string[]"},typeDefs:{keys:["// @julong/mono-rele2-utils \uD658\uACBD \uBCC0\uC218 \uD0A4 \uBAA9\uB85D",...a.map(e=>`// "${e}"`),"","// MCP client config \uC608\uC2DC:","// {",'// "mcpServers": {','// "@julong/mono-rele2-utils": {','// "command": "npx",','// "args": ["-y", "@julong/mono-rele2-utils"],','// "env": {',...a.map(e=>`// "${e}": "<value>"`),"// }","// }","// }","// }"].join(`
6
+ Input must include \`name.first\`, \`name.last\`, and \`location.city\`.`)}},examples:[{args:[`'{"name":{"title":"Mr","first":"Alice","last":"Kim"},"location":{"city":"Seoul"},"gender":"female","email":"alice@example.com","nat":"KR"}'`],result:"\uC774\uB984\uC740 Alice Kim \uC774\uACE0 \uD604\uC7AC Seoul \uC5D0 \uC0B4\uACE0 \uC788\uC2B5\uB2C8\uB2E4."}],guidelines:["\uC785\uB825\uC740 RandomUser API \uC2A4\uD399\uC744 \uB530\uB985\uB2C8\uB2E4. \uCD5C\uC18C\uD55C name.first, name.last, location.city \uD544\uB4DC\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.","JSON \uBB38\uC790\uC5F4(string)\uACFC \uD30C\uC2F1\uB41C \uAC1D\uCCB4 \uBAA8\uB450 \uD5C8\uC6A9\uB429\uB2C8\uB2E4 (CLI / MCP \uBAA8\uB450 \uB3D9\uC791).","\uACB0\uACFC\uB294 \uD56D\uC0C1 '\uC774\uB984\uC740 {first} {last} \uC774\uACE0 \uD604\uC7AC {city} \uC5D0 \uC0B4\uACE0 \uC788\uC2B5\uB2C8\uB2E4.' \uD615\uC2DD\uC758 \uD55C\uAE00 \uBB38\uC7A5\uC785\uB2C8\uB2E4."]}},E=b.getUserTool;import{z as w}from"zod";var a=["API_KEY"];function J(e){let n=e.filter(o=>!a.includes(o));if(n.length>0)throw new Error(`Invalid env key(s): ${n.join(", ")}. Allowed keys: ${a.join(", ")}`);let t={};for(let o of e){let s=process.env[o];s!==void 0&&(t[o]=s)}return t}var x={envGetTool:{name:"env_get",description:`MCP \uD074\uB77C\uC774\uC5B8\uD2B8 config\uC758 env \uD544\uB4DC\uB97C \uD1B5\uD574 \uC8FC\uC785\uB41C \uD658\uACBD \uBCC0\uC218 \uAC12\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4. \uC870\uD68C \uAC00\uB2A5\uD55C \uD0A4\uB294 \uD328\uD0A4\uC9C0\uC5D0\uC11C \uC81C\uACF5\uD558\uB294 \uD658\uACBD \uBCC0\uC218\uB85C \uD55C\uC815\uB429\uB2C8\uB2E4. \uD604\uC7AC \uC9C0\uC6D0: ${a.join(", ")}.`,inputSchema:{keys:w.array(w.string()).nonempty().describe(`\uC870\uD68C\uD560 \uD658\uACBD \uBCC0\uC218 \uC774\uB984 \uBAA9\uB85D (\uC720\uD6A8 \uD0A4: ${a.join(", ")})`)},typeLabels:{keys:"string[]"},typeDefs:{keys:["// @julong/mono-rele2-utils \uD658\uACBD \uBCC0\uC218 \uD0A4 \uBAA9\uB85D",...a.map(e=>`// "${e}"`),"","// MCP client config \uC608\uC2DC:","// {",'// "mcpServers": {','// "@julong/mono-rele2-utils": {','// "command": "npx",','// "args": ["-y", "@julong/mono-rele2-utils"],','// "env": {',...a.map(e=>`// "${e}": "<value>"`),"// }","// }","// }","// }"].join(`
7
7
  `)},returnType:"Record<string, string>",returnDescription:"key: \uD658\uACBD \uBCC0\uC218 \uC774\uB984, value: \uD574\uB2F9 \uAC12 (\uC124\uC815\uB418\uC9C0 \uC54A\uC740 \uBCC0\uC218\uB294 \uACB0\uACFC\uC5D0\uC11C \uC81C\uC678)",handler:async({keys:e})=>{try{let n=J(e);return Object.keys(n).length===0?r("(no matching environment variables found)"):r(JSON.stringify(n,null,2))}catch(n){return r(`Error: ${n.message}`)}},examples:[{args:[`'["API_KEY"]'`],result:JSON.stringify({API_KEY:"<value>"},null,2)}],guidelines:[`\uC870\uD68C \uAC00\uB2A5\uD55C \uD0A4: ${a.join(", ")}`,"MCP client config.json\uC758 env \uD544\uB4DC\uC5D0 \uC704 \uD0A4\uB4E4\uB9CC \uC124\uC815\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.","\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uD0A4\uB97C \uC694\uCCAD\uD558\uBA74 \uC5D0\uB7EC \uBA54\uC2DC\uC9C0\uC5D0 \uD5C8\uC6A9\uB41C \uD0A4 \uBAA9\uB85D\uC774 \uD45C\uC2DC\uB429\uB2C8\uB2E4.","\uC124\uC815\uB418\uC9C0 \uC54A\uC740 \uD658\uACBD \uBCC0\uC218\uB294 \uACB0\uACFC \uAC1D\uCCB4\uC5D0\uC11C \uC81C\uC678\uB429\uB2C8\uB2E4."]}},C=x.envGetTool;var v={...p,...h,...b,...x};$(v).catch(j);
package/dist/index.cjs ADDED
@@ -0,0 +1,67 @@
1
+ "use strict";var $=Object.defineProperty;var C=Object.getOwnPropertyDescriptor;var U=Object.getOwnPropertyNames;var L=Object.prototype.hasOwnProperty;var M=(n,t)=>{for(var e in t)$(n,e,{get:t[e],enumerable:!0})},_=(n,t,e,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of U(t))!L.call(n,r)&&r!==e&&$(n,r,{get:()=>t[r],enumerable:!(o=C(t,r))||o.enumerable});return n};var P=n=>_($({},"__esModule",{value:!0}),n);var ae={};M(ae,{cn:()=>h,generateReadmeSkills:()=>D,generateSkillMarkdown:()=>z,tools:()=>N});module.exports=P(ae);function h(...n){return n.filter(Boolean).join(" ")}function l(n){return{content:[{type:"text",text:n}]}}var I=require("@modelcontextprotocol/sdk/server/mcp.js"),V=require("@modelcontextprotocol/sdk/server/stdio.js");var K=require("zod");var i=require("zod");function z(n){let{binName:t,description:e,tools:o}=n;return`---
2
+ name: ${t}
3
+ description: ${e}
4
+ ---
5
+
6
+ # ${t}
7
+
8
+ \`\`\`sh
9
+ ${t} <toolName> [...args]
10
+ \`\`\`
11
+
12
+ ## Skills
13
+
14
+ ${B(o)}
15
+
16
+ ## Examples
17
+
18
+ ${G(t,o)}
19
+
20
+ ## Guidelines
21
+
22
+ ${Y(t,o)}
23
+ `}function B(n){return Object.entries(n).map(([t,e])=>{let o=Object.entries(e.inputSchema).map(([a,s])=>{let c=e.typeLabels?.[a];return`| \`${a}\` | ${F(s,c)} |`}).join(`
24
+ `),r=e.typeDefs?Object.entries(e.typeDefs).map(([a,s])=>`
25
+
26
+ **\`${a}\`** type definition:
27
+ \`\`\`typescript
28
+ ${s}
29
+ \`\`\``).join(""):"";return`### ${t}
30
+
31
+ ${e.description}
32
+
33
+ | arg | description |
34
+ |-----|-------------|
35
+ ${o}${r}`}).join(`
36
+
37
+ `)}function F(n,t){let e=n.description??"",o=n,r,a=!1;for(;o instanceof i.z.ZodOptional||o instanceof i.z.ZodDefault;){if(o instanceof i.z.ZodDefault){let c=o.def.defaultValue;r=typeof c=="function"?c():c}o instanceof i.z.ZodOptional&&(a=!0),o=o.unwrap()}let s=[];if(t&&s.push(`Type: ${t}`),e&&s.push(e),o instanceof i.z.ZodEnum){let c=o.options.map(g=>`\`${g}\``).join(" \\| ");s.push(c)}return r!==void 0?s.push(`default: \`${String(r)}\``):a&&s.push("optional"),s.join(" \u2014 ")}function G(n,t){let e=[];for(let[o,r]of Object.entries(t))if(r.examples)for(let a of r.examples){let s=[n,o,...a.args].join(" ");e.push(`- \`${s}\` => \`${a.result}\``)}return e.join(`
38
+ `)}function Y(n,t){let e=[],o=new Set,r=s=>{o.has(s)||(o.add(s),e.push(s))};r("Arguments are positional \u2014 pass them in the order listed in each skill's table");let a=Object.values(t).flatMap(s=>Object.values(s.inputSchema));a.some(s=>k(s,i.z.ZodNumber))&&r("Numeric args are auto-parsed \u2014 pass as plain numbers (e.g. `10`)"),a.some(s=>k(s,i.z.ZodArray))&&r('Array args must be valid JSON \u2014 wrap in single quotes on Unix shells (e.g. `\'["a","b"]\'`)'),a.some(s=>s instanceof i.z.ZodOptional||s instanceof i.z.ZodDefault)&&r("Optional args with defaults may be omitted");for(let s of Object.values(t))if(s.guidelines)for(let c of s.guidelines)r(c);return r(`Run \`${n}\` with no args to list all available skills`),e.map(s=>`- ${s}`).join(`
39
+ `)}function k(n,t){let e=n;for(;e instanceof i.z.ZodOptional||e instanceof i.z.ZodDefault;)e=e.unwrap();return e instanceof t}function D(n){let{binName:t,tools:e}=n;return Object.entries(e).map(([o,r])=>W(t,o,r)).join(`
40
+
41
+ `)}function W(n,t,e){let o=Object.entries(e.inputSchema),r=o.map(([p,u])=>u instanceof i.z.ZodOptional||u instanceof i.z.ZodDefault?`[${p}]`:`<${p}>`).join(" "),a=[n,t,r].filter(Boolean).join(" "),s=o.map(([p,u])=>{let x=e.typeLabels?.[p],m=R(u,x),S=q(u);return`| \`${p}\` | ${m} | ${S} |`}).join(`
42
+ `),c=e.examples??[],g="";if(c.length>0){let p=c.map(m=>[n,t,...m.args].join(" ")),u=Math.max(...p.map(m=>m.length));g=`
43
+
44
+ \`\`\`sh
45
+ ${c.map((m,S)=>`${p[S].padEnd(u)} # ${m.result}`).join(`
46
+ `)}
47
+ \`\`\``}let E=e.typeDefs?Object.entries(e.typeDefs).map(([p,u])=>`
48
+
49
+ **\`${p}\`** type definition:
50
+
51
+ \`\`\`typescript
52
+ ${u}
53
+ \`\`\``).join(""):"",J=s?`
54
+
55
+ | arg | type | description |
56
+ |-----|------|-------------|
57
+ ${s}`:"";return`#### \`${t}\`
58
+
59
+ ${e.description}.
60
+
61
+ \`\`\`sh
62
+ ${a}
63
+ \`\`\`${J}${E}${g}`}function R(n,t){if(t)return t;let e=n;for(;e instanceof i.z.ZodOptional||e instanceof i.z.ZodDefault;)e=e.unwrap();return e instanceof i.z.ZodEnum?e.options.map(o=>`\`${o}\``).join(" \\| "):e instanceof i.z.ZodNumber?"number":e instanceof i.z.ZodString?"string":e instanceof i.z.ZodBoolean?"boolean":e instanceof i.z.ZodArray?"JSON string (array)":e instanceof i.z.ZodUnion?e.options.map(r=>R(r)).join(" \\| "):e instanceof i.z.ZodRecord?"JSON object":"unknown"}function q(n){let t=n.description??"",e=n,o,r=!1;for(;e instanceof i.z.ZodOptional||e instanceof i.z.ZodDefault;){if(e instanceof i.z.ZodDefault){let a=e.def.defaultValue;o=typeof a=="function"?a():a}e instanceof i.z.ZodOptional&&(r=!0),e=e.unwrap()}return o!==void 0?`${t} (default: \`${String(o)}\`)`:r?`${t} (optional)`:t}var d=require("zod");var b={cnTool:{name:"cn",description:"Merges class names, filtering out falsy values",inputSchema:{classes:d.z.array(d.z.string()).describe("List of class names to merge")},typeLabels:{classes:"string[]"},returnType:"string",returnDescription:"Merged class name string with falsy values filtered out",handler:async({classes:n})=>l(h(...n)),examples:[{args:[`'["btn","active","large"]'`],result:"btn active large"}]},caseConvertTool:{name:"case_convert",description:"Converts text to the specified case format",inputSchema:{input:d.z.string().describe("Text to convert"),to:d.z.enum(["upper","lower","capitalize","camel","snake","kebab"]).describe("Target case format")},typeLabels:{input:"string",to:'"upper" | "lower" | "capitalize" | "camel" | "snake" | "kebab"'},returnType:"string",returnDescription:"Converted text in the target case format",handler:async({input:n,to:t})=>l(ee(n,t)),examples:[{args:['"hello world"',"camel"],result:"helloWorld"},{args:['"helloWorld"',"snake"],result:"hello_world"},{args:['"hello world"',"kebab"],result:"hello-world"}]},truncateTool:{name:"truncate",description:"Truncates text to a maximum length and appends a suffix",inputSchema:{input:d.z.string().describe("Text to truncate"),maxLength:d.z.number().int().positive().describe("Maximum character length"),suffix:d.z.string().default("...").describe("Suffix to append when truncated")},typeLabels:{input:"string",maxLength:"number",suffix:"string"},returnType:"string",returnDescription:"Truncated text with the configured suffix appended if truncated",handler:async({input:n,maxLength:t,suffix:e})=>{let o=n.length<=t?n:n.slice(0,t-e.length)+e;return l(o)},examples:[{args:['"hello world long text"',"10"],result:"hello w..."},{args:['"hello world"',"8",'"\u2026"'],result:"hello w\u2026"}]}},H=b.cnTool,Q=b.caseConvertTool,X=b.truncateTool;function ee(n,t){switch(t){case"upper":return n.toUpperCase();case"lower":return n.toLowerCase();case"capitalize":return n.charAt(0).toUpperCase()+n.slice(1).toLowerCase();case"camel":return n.replace(/[-_\s]+(.)/g,(e,o)=>o.toUpperCase()).replace(/^(.)/,e=>e.toLowerCase());case"snake":return n.replace(/([A-Z])/g,"_$1").replace(/[-\s]+/g,"_").toLowerCase().replace(/^_/,"");case"kebab":return n.replace(/([A-Z])/g,"-$1").replace(/[_\s]+/g,"-").toLowerCase().replace(/^-/,"")}}var y=require("zod");function ne(n){let t=typeof n=="string"?JSON.parse(n):n,e={};function o(r,a){if(r===null||typeof r!="object"||Array.isArray(r)){e[a]=r;return}for(let[s,c]of Object.entries(r)){let g=a?`${a}.${s}`:s;o(c,g)}}return o(t,""),e}var w={objectFlattenTool:{name:"object_flatten",description:"Flattens a nested JSON object of any depth into dot-notation key-value pairs. Accepts a JSON string and recursively flattens all levels. Arrays and primitives at any level are treated as leaf values.",inputSchema:{json:y.z.union([y.z.string(),y.z.record(y.z.string(),y.z.any())]).describe("JSON string or parsed object to flatten (unlimited depth)")},handler:async({json:n})=>{try{let e=ne(n);return l(JSON.stringify(e,null,2))}catch(t){return t instanceof SyntaxError?l("Error: invalid JSON string \u2014 unable to parse input"):l(`Error: failed to flatten object \u2014 ${t.message}`)}},examples:[{args:[`'{"user":{"name":"Alice","address":{"city":"Seoul","zip":"12345"}},"active":true}'`],result:JSON.stringify({"user.name":"Alice","user.address.city":"Seoul","user.address.zip":"12345",active:!0},null,2)},{args:[`'{"a":{"b":{"c":{"d":{"e":"deep"}}}}}'`],result:JSON.stringify({"a.b.c.d.e":"deep"},null,2)}],returnType:"JsonObject",returnDescription:'Flattened object with dot-notation keys \u2014 e.g. { "a.b.c": value }',guidelines:["Arrays and primitives at any level are always treated as leaf values \u2014 they are never traversed.","The result is always a flat JSON object with dot-notation keys.","There is no depth limit \u2014 objects of any nesting level are fully flattened.","Input is accepted as a JSON string (MCP/CLI) and parsed internally."]}},te=w.objectFlattenTool;var T=require("zod");function oe(n){let t=typeof n=="string"?JSON.parse(n):n,{first:e,last:o}=t.name,r=t.location.city;return`\uC774\uB984\uC740 ${e} ${o} \uC774\uACE0 \uD604\uC7AC ${r} \uC5D0 \uC0B4\uACE0 \uC788\uC2B5\uB2C8\uB2E4.`}var v={getUserTool:{name:"getUser",description:"RandomUser API \uD615\uC2DD\uC758 \uC0AC\uC6A9\uC790 \uAC1D\uCCB4\uB97C \uBC1B\uC544 \uC774\uB984\uACFC \uAC70\uC8FC \uB3C4\uC2DC\uB85C \uAD6C\uC131\uB41C \uD55C\uAE00 \uBB38\uC7A5\uC744 \uBC18\uD658\uD569\uB2C8\uB2E4. JSON \uBB38\uC790\uC5F4 \uB610\uB294 \uD30C\uC2F1\uB41C \uAC1D\uCCB4\uB97C \uC785\uB825\uBC1B\uC2B5\uB2C8\uB2E4.",inputSchema:{user:T.z.union([T.z.string(),T.z.record(T.z.string(),T.z.any())]).describe("RandomUser \uD615\uC2DD\uC758 JSON \uBB38\uC790\uC5F4 \uB610\uB294 \uAC1D\uCCB4 \u2014 name.first / name.last / location.city \uD544\uC218")},typeLabels:{user:"RandomUser"},typeDefs:{user:["interface RandomUser {",' gender: "male" | "female";'," name: {"," title: string;"," first: string;"," last: string;"," };"," location: {"," street: {"," number: number;"," name: string;"," };"," city: string;"," state: string;"," country: string;"," postcode: string | number;"," coordinates: {"," latitude: string;"," longitude: string;"," };"," timezone: {"," offset: string;"," description: string;"," };"," };"," email: string;"," login: {"," uuid: string;"," username: string;"," };"," dob: {"," date: string;"," age: number;"," };"," phone: string;"," cell: string;"," picture: {"," large: string;"," medium: string;"," thumbnail: string;"," };"," nat: string;","}"].join(`
64
+ `)},returnType:"string",returnDescription:'"\uC774\uB984\uC740 {first} {last} \uC774\uACE0 \uD604\uC7AC {city} \uC5D0 \uC0B4\uACE0 \uC788\uC2B5\uB2C8\uB2E4." \uD615\uC2DD\uC758 \uD55C\uAE00 \uBB38\uC7A5',handler:async({user:n})=>{try{let e=oe(n);return l(e)}catch(t){return t instanceof SyntaxError?l("Error: invalid JSON string \u2014 unable to parse input"):l(`Error: failed to process user data \u2014 ${t.message}
65
+
66
+ Input must include \`name.first\`, \`name.last\`, and \`location.city\`.`)}},examples:[{args:[`'{"name":{"title":"Mr","first":"Alice","last":"Kim"},"location":{"city":"Seoul"},"gender":"female","email":"alice@example.com","nat":"KR"}'`],result:"\uC774\uB984\uC740 Alice Kim \uC774\uACE0 \uD604\uC7AC Seoul \uC5D0 \uC0B4\uACE0 \uC788\uC2B5\uB2C8\uB2E4."}],guidelines:["\uC785\uB825\uC740 RandomUser API \uC2A4\uD399\uC744 \uB530\uB985\uB2C8\uB2E4. \uCD5C\uC18C\uD55C name.first, name.last, location.city \uD544\uB4DC\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.","JSON \uBB38\uC790\uC5F4(string)\uACFC \uD30C\uC2F1\uB41C \uAC1D\uCCB4 \uBAA8\uB450 \uD5C8\uC6A9\uB429\uB2C8\uB2E4 (CLI / MCP \uBAA8\uB450 \uB3D9\uC791).","\uACB0\uACFC\uB294 \uD56D\uC0C1 '\uC774\uB984\uC740 {first} {last} \uC774\uACE0 \uD604\uC7AC {city} \uC5D0 \uC0B4\uACE0 \uC788\uC2B5\uB2C8\uB2E4.' \uD615\uC2DD\uC758 \uD55C\uAE00 \uBB38\uC7A5\uC785\uB2C8\uB2E4."]}},re=v.getUserTool;var O=require("zod"),f=["API_KEY"];function se(n){let t=n.filter(o=>!f.includes(o));if(t.length>0)throw new Error(`Invalid env key(s): ${t.join(", ")}. Allowed keys: ${f.join(", ")}`);let e={};for(let o of n){let r=process.env[o];r!==void 0&&(e[o]=r)}return e}var A={envGetTool:{name:"env_get",description:`MCP \uD074\uB77C\uC774\uC5B8\uD2B8 config\uC758 env \uD544\uB4DC\uB97C \uD1B5\uD574 \uC8FC\uC785\uB41C \uD658\uACBD \uBCC0\uC218 \uAC12\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4. \uC870\uD68C \uAC00\uB2A5\uD55C \uD0A4\uB294 \uD328\uD0A4\uC9C0\uC5D0\uC11C \uC81C\uACF5\uD558\uB294 \uD658\uACBD \uBCC0\uC218\uB85C \uD55C\uC815\uB429\uB2C8\uB2E4. \uD604\uC7AC \uC9C0\uC6D0: ${f.join(", ")}.`,inputSchema:{keys:O.z.array(O.z.string()).nonempty().describe(`\uC870\uD68C\uD560 \uD658\uACBD \uBCC0\uC218 \uC774\uB984 \uBAA9\uB85D (\uC720\uD6A8 \uD0A4: ${f.join(", ")})`)},typeLabels:{keys:"string[]"},typeDefs:{keys:["// @julong/mono-rele2-utils \uD658\uACBD \uBCC0\uC218 \uD0A4 \uBAA9\uB85D",...f.map(n=>`// "${n}"`),"","// MCP client config \uC608\uC2DC:","// {",'// "mcpServers": {','// "@julong/mono-rele2-utils": {','// "command": "npx",','// "args": ["-y", "@julong/mono-rele2-utils"],','// "env": {',...f.map(n=>`// "${n}": "<value>"`),"// }","// }","// }","// }"].join(`
67
+ `)},returnType:"Record<string, string>",returnDescription:"key: \uD658\uACBD \uBCC0\uC218 \uC774\uB984, value: \uD574\uB2F9 \uAC12 (\uC124\uC815\uB418\uC9C0 \uC54A\uC740 \uBCC0\uC218\uB294 \uACB0\uACFC\uC5D0\uC11C \uC81C\uC678)",handler:async({keys:n})=>{try{let t=se(n);return Object.keys(t).length===0?l("(no matching environment variables found)"):l(JSON.stringify(t,null,2))}catch(t){return l(`Error: ${t.message}`)}},examples:[{args:[`'["API_KEY"]'`],result:JSON.stringify({API_KEY:"<value>"},null,2)}],guidelines:[`\uC870\uD68C \uAC00\uB2A5\uD55C \uD0A4: ${f.join(", ")}`,"MCP client config.json\uC758 env \uD544\uB4DC\uC5D0 \uC704 \uD0A4\uB4E4\uB9CC \uC124\uC815\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.","\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uD0A4\uB97C \uC694\uCCAD\uD558\uBA74 \uC5D0\uB7EC \uBA54\uC2DC\uC9C0\uC5D0 \uD5C8\uC6A9\uB41C \uD0A4 \uBAA9\uB85D\uC774 \uD45C\uC2DC\uB429\uB2C8\uB2E4.","\uC124\uC815\uB418\uC9C0 \uC54A\uC740 \uD658\uACBD \uBCC0\uC218\uB294 \uACB0\uACFC \uAC1D\uCCB4\uC5D0\uC11C \uC81C\uC678\uB429\uB2C8\uB2E4."]}},ie=A.envGetTool;var N={...b,...w,...v,...A};0&&(module.exports={cn,generateReadmeSkills,generateSkillMarkdown,tools});
@@ -0,0 +1,178 @@
1
+ import { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
2
+ import * as zod from 'zod';
3
+ import { z } from 'zod';
4
+
5
+ declare function cn(...classes: (string | undefined | null | false)[]): string;
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
+ typeLabels?: Record<string, string>;
20
+ typeDefs?: Record<string, string>;
21
+ returnType?: string;
22
+ returnDescription?: string;
23
+ };
24
+
25
+ type SkillTools = Record<string, AnyToolDef>;
26
+ declare function generateSkillMarkdown(opts: {
27
+ binName: string;
28
+ description: string;
29
+ tools: SkillTools;
30
+ }): string;
31
+ declare function generateReadmeSkills(opts: {
32
+ binName: string;
33
+ tools: SkillTools;
34
+ }): string;
35
+
36
+ declare const tools: {
37
+ envGetTool: {
38
+ name: string;
39
+ description: string;
40
+ inputSchema: {
41
+ readonly keys: zod.ZodArray<zod.ZodString>;
42
+ };
43
+ handler: (input: {
44
+ keys: string[];
45
+ }) => Promise<ToolResult>;
46
+ examples?: ToolExample[];
47
+ guidelines?: string[];
48
+ typeLabels?: {
49
+ readonly keys?: string | undefined;
50
+ } | undefined;
51
+ typeDefs?: {
52
+ readonly keys?: string | undefined;
53
+ } | undefined;
54
+ returnType?: string;
55
+ returnDescription?: string;
56
+ };
57
+ getUserTool: {
58
+ name: string;
59
+ description: string;
60
+ inputSchema: {
61
+ readonly user: zod.ZodUnion<readonly [zod.ZodString, zod.ZodRecord<zod.ZodString, zod.ZodAny>]>;
62
+ };
63
+ handler: (input: {
64
+ user: string | Record<string, any>;
65
+ }) => Promise<ToolResult>;
66
+ examples?: ToolExample[];
67
+ guidelines?: string[];
68
+ typeLabels?: {
69
+ readonly user?: string | undefined;
70
+ } | undefined;
71
+ typeDefs?: {
72
+ readonly user?: string | undefined;
73
+ } | undefined;
74
+ returnType?: string;
75
+ returnDescription?: string;
76
+ };
77
+ objectFlattenTool: {
78
+ name: string;
79
+ description: string;
80
+ inputSchema: {
81
+ readonly json: zod.ZodUnion<readonly [zod.ZodString, zod.ZodRecord<zod.ZodString, zod.ZodAny>]>;
82
+ };
83
+ handler: (input: {
84
+ json: string | Record<string, any>;
85
+ }) => Promise<ToolResult>;
86
+ examples?: ToolExample[];
87
+ guidelines?: string[];
88
+ typeLabels?: {
89
+ readonly json?: string | undefined;
90
+ } | undefined;
91
+ typeDefs?: {
92
+ readonly json?: string | undefined;
93
+ } | undefined;
94
+ returnType?: string;
95
+ returnDescription?: string;
96
+ };
97
+ cnTool: {
98
+ name: string;
99
+ description: string;
100
+ inputSchema: {
101
+ readonly classes: zod.ZodArray<zod.ZodString>;
102
+ };
103
+ handler: (input: {
104
+ classes: string[];
105
+ }) => Promise<ToolResult>;
106
+ examples?: ToolExample[];
107
+ guidelines?: string[];
108
+ typeLabels?: {
109
+ readonly classes?: string | undefined;
110
+ } | undefined;
111
+ typeDefs?: {
112
+ readonly classes?: string | undefined;
113
+ } | undefined;
114
+ returnType?: string;
115
+ returnDescription?: string;
116
+ };
117
+ caseConvertTool: {
118
+ name: string;
119
+ description: string;
120
+ inputSchema: {
121
+ readonly input: zod.ZodString;
122
+ readonly to: zod.ZodEnum<{
123
+ upper: "upper";
124
+ lower: "lower";
125
+ capitalize: "capitalize";
126
+ camel: "camel";
127
+ snake: "snake";
128
+ kebab: "kebab";
129
+ }>;
130
+ };
131
+ handler: (input: {
132
+ input: string;
133
+ to: "upper" | "lower" | "capitalize" | "camel" | "snake" | "kebab";
134
+ }) => Promise<ToolResult>;
135
+ examples?: ToolExample[];
136
+ guidelines?: string[];
137
+ typeLabels?: {
138
+ readonly input?: string | undefined;
139
+ readonly to?: string | undefined;
140
+ } | undefined;
141
+ typeDefs?: {
142
+ readonly input?: string | undefined;
143
+ readonly to?: string | undefined;
144
+ } | undefined;
145
+ returnType?: string;
146
+ returnDescription?: string;
147
+ };
148
+ truncateTool: {
149
+ name: string;
150
+ description: string;
151
+ inputSchema: {
152
+ readonly input: zod.ZodString;
153
+ readonly maxLength: zod.ZodNumber;
154
+ readonly suffix: zod.ZodDefault<zod.ZodString>;
155
+ };
156
+ handler: (input: {
157
+ input: string;
158
+ maxLength: number;
159
+ suffix: string;
160
+ }) => Promise<ToolResult>;
161
+ examples?: ToolExample[];
162
+ guidelines?: string[];
163
+ typeLabels?: {
164
+ readonly input?: string | undefined;
165
+ readonly maxLength?: string | undefined;
166
+ readonly suffix?: string | undefined;
167
+ } | undefined;
168
+ typeDefs?: {
169
+ readonly input?: string | undefined;
170
+ readonly maxLength?: string | undefined;
171
+ readonly suffix?: string | undefined;
172
+ } | undefined;
173
+ returnType?: string;
174
+ returnDescription?: string;
175
+ };
176
+ };
177
+
178
+ export { cn, generateReadmeSkills, generateSkillMarkdown, tools };
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ "use strict";function r(e){return{content:[{type:"text",text:e}]}}var Z=require("@modelcontextprotocol/sdk/server/mcp.js"),w=require("@modelcontextprotocol/sdk/server/stdio.js");function O(e,n){let t=new Z.McpServer(e);for(let o of n)t.registerTool(o.name,{description:o.description,inputSchema:o.inputSchema},o.handler);return t}async function A(e){let n=new w.StdioServerTransport;await e.connect(n)}var R=require("zod");var N=require("zod");var i=require("zod");function k(...e){return e.filter(Boolean).join(" ")}var p={cnTool:{name:"cn",description:"Merges class names, filtering out falsy values",inputSchema:{classes:i.z.array(i.z.string()).describe("List of class names to merge")},typeLabels:{classes:"string[]"},returnType:"string",returnDescription:"Merged class name string with falsy values filtered out",handler:async({classes:e})=>r(k(...e)),examples:[{args:[`'["btn","active","large"]'`],result:"btn active large"}]},caseConvertTool:{name:"case_convert",description:"Converts text to the specified case format",inputSchema:{input:i.z.string().describe("Text to convert"),to:i.z.enum(["upper","lower","capitalize","camel","snake","kebab"]).describe("Target case format")},typeLabels:{input:"string",to:'"upper" | "lower" | "capitalize" | "camel" | "snake" | "kebab"'},returnType:"string",returnDescription:"Converted text in the target case format",handler:async({input:e,to:n})=>r(E(e,n)),examples:[{args:['"hello world"',"camel"],result:"helloWorld"},{args:['"helloWorld"',"snake"],result:"hello_world"},{args:['"hello world"',"kebab"],result:"hello-world"}]},truncateTool:{name:"truncate",description:"Truncates text to a maximum length and appends a suffix",inputSchema:{input:i.z.string().describe("Text to truncate"),maxLength:i.z.number().int().positive().describe("Maximum character length"),suffix:i.z.string().default("...").describe("Suffix to append when truncated")},typeLabels:{input:"string",maxLength:"number",suffix:"string"},returnType:"string",returnDescription:"Truncated text with the configured suffix appended if truncated",handler:async({input:e,maxLength:n,suffix:t})=>{let o=e.length<=n?e:e.slice(0,n-t.length)+t;return r(o)},examples:[{args:['"hello world long text"',"10"],result:"hello w..."},{args:['"hello world"',"8",'"\u2026"'],result:"hello w\u2026"}]}},m=p.cnTool,g=p.caseConvertTool,y=p.truncateTool;function E(e,n){switch(n){case"upper":return e.toUpperCase();case"lower":return e.toLowerCase();case"capitalize":return e.charAt(0).toUpperCase()+e.slice(1).toLowerCase();case"camel":return e.replace(/[-_\s]+(.)/g,(t,o)=>o.toUpperCase()).replace(/^(.)/,t=>t.toLowerCase());case"snake":return e.replace(/([A-Z])/g,"_$1").replace(/[-\s]+/g,"_").toLowerCase().replace(/^_/,"");case"kebab":return e.replace(/([A-Z])/g,"-$1").replace(/[_\s]+/g,"-").toLowerCase().replace(/^-/,"")}}var l=require("zod");function J(e){let n=typeof e=="string"?JSON.parse(e):e,t={};function o(s,u){if(s===null||typeof s!="object"||Array.isArray(s)){t[u]=s;return}for(let[v,z]of Object.entries(s)){let D=u?`${u}.${v}`:v;o(z,D)}}return o(n,""),t}var T={objectFlattenTool:{name:"object_flatten",description:"Flattens a nested JSON object of any depth into dot-notation key-value pairs. Accepts a JSON string and recursively flattens all levels. Arrays and primitives at any level are treated as leaf values.",inputSchema:{json:l.z.union([l.z.string(),l.z.record(l.z.string(),l.z.any())]).describe("JSON string or parsed object to flatten (unlimited depth)")},handler:async({json:e})=>{try{let t=J(e);return r(JSON.stringify(t,null,2))}catch(n){return n instanceof SyntaxError?r("Error: invalid JSON string \u2014 unable to parse input"):r(`Error: failed to flatten object \u2014 ${n.message}`)}},examples:[{args:[`'{"user":{"name":"Alice","address":{"city":"Seoul","zip":"12345"}},"active":true}'`],result:JSON.stringify({"user.name":"Alice","user.address.city":"Seoul","user.address.zip":"12345",active:!0},null,2)},{args:[`'{"a":{"b":{"c":{"d":{"e":"deep"}}}}}'`],result:JSON.stringify({"a.b.c.d.e":"deep"},null,2)}],returnType:"JsonObject",returnDescription:'Flattened object with dot-notation keys \u2014 e.g. { "a.b.c": value }',guidelines:["Arrays and primitives at any level are always treated as leaf values \u2014 they are never traversed.","The result is always a flat JSON object with dot-notation keys.","There is no depth limit \u2014 objects of any nesting level are fully flattened.","Input is accepted as a JSON string (MCP/CLI) and parsed internally."]}},b=T.objectFlattenTool;var c=require("zod");function C(e){let n=typeof e=="string"?JSON.parse(e):e,{first:t,last:o}=n.name,s=n.location.city;return`\uC774\uB984\uC740 ${t} ${o} \uC774\uACE0 \uD604\uC7AC ${s} \uC5D0 \uC0B4\uACE0 \uC788\uC2B5\uB2C8\uB2E4.`}var h={getUserTool:{name:"getUser",description:"RandomUser API \uD615\uC2DD\uC758 \uC0AC\uC6A9\uC790 \uAC1D\uCCB4\uB97C \uBC1B\uC544 \uC774\uB984\uACFC \uAC70\uC8FC \uB3C4\uC2DC\uB85C \uAD6C\uC131\uB41C \uD55C\uAE00 \uBB38\uC7A5\uC744 \uBC18\uD658\uD569\uB2C8\uB2E4. JSON \uBB38\uC790\uC5F4 \uB610\uB294 \uD30C\uC2F1\uB41C \uAC1D\uCCB4\uB97C \uC785\uB825\uBC1B\uC2B5\uB2C8\uB2E4.",inputSchema:{user:c.z.union([c.z.string(),c.z.record(c.z.string(),c.z.any())]).describe("RandomUser \uD615\uC2DD\uC758 JSON \uBB38\uC790\uC5F4 \uB610\uB294 \uAC1D\uCCB4 \u2014 name.first / name.last / location.city \uD544\uC218")},typeLabels:{user:"RandomUser"},typeDefs:{user:["interface RandomUser {",' gender: "male" | "female";'," name: {"," title: string;"," first: string;"," last: string;"," };"," location: {"," street: {"," number: number;"," name: string;"," };"," city: string;"," state: string;"," country: string;"," postcode: string | number;"," coordinates: {"," latitude: string;"," longitude: string;"," };"," timezone: {"," offset: string;"," description: string;"," };"," };"," email: string;"," login: {"," uuid: string;"," username: string;"," };"," dob: {"," date: string;"," age: number;"," };"," phone: string;"," cell: string;"," picture: {"," large: string;"," medium: string;"," thumbnail: string;"," };"," nat: string;","}"].join(`
3
+ `)},returnType:"string",returnDescription:'"\uC774\uB984\uC740 {first} {last} \uC774\uACE0 \uD604\uC7AC {city} \uC5D0 \uC0B4\uACE0 \uC788\uC2B5\uB2C8\uB2E4." \uD615\uC2DD\uC758 \uD55C\uAE00 \uBB38\uC7A5',handler:async({user:e})=>{try{let t=C(e);return r(t)}catch(n){return n instanceof SyntaxError?r("Error: invalid JSON string \u2014 unable to parse input"):r(`Error: failed to process user data \u2014 ${n.message}
4
+
5
+ Input must include \`name.first\`, \`name.last\`, and \`location.city\`.`)}},examples:[{args:[`'{"name":{"title":"Mr","first":"Alice","last":"Kim"},"location":{"city":"Seoul"},"gender":"female","email":"alice@example.com","nat":"KR"}'`],result:"\uC774\uB984\uC740 Alice Kim \uC774\uACE0 \uD604\uC7AC Seoul \uC5D0 \uC0B4\uACE0 \uC788\uC2B5\uB2C8\uB2E4."}],guidelines:["\uC785\uB825\uC740 RandomUser API \uC2A4\uD399\uC744 \uB530\uB985\uB2C8\uB2E4. \uCD5C\uC18C\uD55C name.first, name.last, location.city \uD544\uB4DC\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.","JSON \uBB38\uC790\uC5F4(string)\uACFC \uD30C\uC2F1\uB41C \uAC1D\uCCB4 \uBAA8\uB450 \uD5C8\uC6A9\uB429\uB2C8\uB2E4 (CLI / MCP \uBAA8\uB450 \uB3D9\uC791).","\uACB0\uACFC\uB294 \uD56D\uC0C1 '\uC774\uB984\uC740 {first} {last} \uC774\uACE0 \uD604\uC7AC {city} \uC5D0 \uC0B4\uACE0 \uC788\uC2B5\uB2C8\uB2E4.' \uD615\uC2DD\uC758 \uD55C\uAE00 \uBB38\uC7A5\uC785\uB2C8\uB2E4."]}},x=h.getUserTool;var S=require("zod"),a=["API_KEY"];function U(e){let n=e.filter(o=>!a.includes(o));if(n.length>0)throw new Error(`Invalid env key(s): ${n.join(", ")}. Allowed keys: ${a.join(", ")}`);let t={};for(let o of e){let s=process.env[o];s!==void 0&&(t[o]=s)}return t}var $={envGetTool:{name:"env_get",description:`MCP \uD074\uB77C\uC774\uC5B8\uD2B8 config\uC758 env \uD544\uB4DC\uB97C \uD1B5\uD574 \uC8FC\uC785\uB41C \uD658\uACBD \uBCC0\uC218 \uAC12\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4. \uC870\uD68C \uAC00\uB2A5\uD55C \uD0A4\uB294 \uD328\uD0A4\uC9C0\uC5D0\uC11C \uC81C\uACF5\uD558\uB294 \uD658\uACBD \uBCC0\uC218\uB85C \uD55C\uC815\uB429\uB2C8\uB2E4. \uD604\uC7AC \uC9C0\uC6D0: ${a.join(", ")}.`,inputSchema:{keys:S.z.array(S.z.string()).nonempty().describe(`\uC870\uD68C\uD560 \uD658\uACBD \uBCC0\uC218 \uC774\uB984 \uBAA9\uB85D (\uC720\uD6A8 \uD0A4: ${a.join(", ")})`)},typeLabels:{keys:"string[]"},typeDefs:{keys:["// @julong/mono-rele2-utils \uD658\uACBD \uBCC0\uC218 \uD0A4 \uBAA9\uB85D",...a.map(e=>`// "${e}"`),"","// MCP client config \uC608\uC2DC:","// {",'// "mcpServers": {','// "@julong/mono-rele2-utils": {','// "command": "npx",','// "args": ["-y", "@julong/mono-rele2-utils"],','// "env": {',...a.map(e=>`// "${e}": "<value>"`),"// }","// }","// }","// }"].join(`
6
+ `)},returnType:"Record<string, string>",returnDescription:"key: \uD658\uACBD \uBCC0\uC218 \uC774\uB984, value: \uD574\uB2F9 \uAC12 (\uC124\uC815\uB418\uC9C0 \uC54A\uC740 \uBCC0\uC218\uB294 \uACB0\uACFC\uC5D0\uC11C \uC81C\uC678)",handler:async({keys:e})=>{try{let n=U(e);return Object.keys(n).length===0?r("(no matching environment variables found)"):r(JSON.stringify(n,null,2))}catch(n){return r(`Error: ${n.message}`)}},examples:[{args:[`'["API_KEY"]'`],result:JSON.stringify({API_KEY:"<value>"},null,2)}],guidelines:[`\uC870\uD68C \uAC00\uB2A5\uD55C \uD0A4: ${a.join(", ")}`,"MCP client config.json\uC758 env \uD544\uB4DC\uC5D0 \uC704 \uD0A4\uB4E4\uB9CC \uC124\uC815\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.","\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uD0A4\uB97C \uC694\uCCAD\uD558\uBA74 \uC5D0\uB7EC \uBA54\uC2DC\uC9C0\uC5D0 \uD5C8\uC6A9\uB41C \uD0A4 \uBAA9\uB85D\uC774 \uD45C\uC2DC\uB429\uB2C8\uB2E4.","\uC124\uC815\uB418\uC9C0 \uC54A\uC740 \uD658\uACBD \uBCC0\uC218\uB294 \uACB0\uACFC \uAC1D\uCCB4\uC5D0\uC11C \uC81C\uC678\uB429\uB2C8\uB2E4."]}},j=$.envGetTool;var fe={...p,...T,...h,...$};var L=O({name:"mono-rele2-utils",version:"1.0.0"},[m,g,y,b,x,j]);A(L).catch(e=>{console.error("[utils] server error:",e),process.exit(1)});
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "@julong/mono-rele2-utils",
3
- "version": "1.30.0",
3
+ "version": "1.31.0",
4
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.",
5
5
  "license": "ISC",
6
6
  "type": "module",
7
7
  "exports": {
8
8
  ".": {
9
+ "types": "./dist/index.d.ts",
9
10
  "import": "./dist/index.js",
10
- "types": "./dist/index.d.ts"
11
+ "require": "./dist/index.cjs"
11
12
  }
12
13
  },
13
14
  "bin": {
@@ -22,8 +23,12 @@
22
23
  },
23
24
  "scripts": {
24
25
  "build": "tsup",
26
+ "dev": "tsup --watch",
25
27
  "typecheck": "tsc --noEmit",
26
28
  "clean": "rimraf dist",
29
+ "lint": "rslint --config ../../rslint.config.ts .",
30
+ "format": "prettier --write src/ --write '*.{ts,json,js}'",
31
+ "format:check": "prettier --check src/ --check '*.{ts,json,js}'",
27
32
  "readme": "bun ../common/build/update-readme.mjs"
28
33
  },
29
34
  "dependencies": {