mcp-texttools 1.0.5 → 1.1.1
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 +49 -0
- package/index.js +140 -1
- package/package.json +8 -3
package/README.md
CHANGED
|
@@ -1,4 +1,45 @@
|
|
|
1
|
+
# mcp-texttools
|
|
1
2
|
|
|
3
|
+
MCP server with **15 text transformation tools** for Claude Desktop, Cursor, and any MCP-compatible AI assistant.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```json
|
|
8
|
+
{
|
|
9
|
+
"mcpServers": {
|
|
10
|
+
"texttools": {
|
|
11
|
+
"command": "npx",
|
|
12
|
+
"args": ["-y", "mcp-texttools"]
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Tools
|
|
19
|
+
|
|
20
|
+
| Tool | Description |
|
|
21
|
+
|------|-------------|
|
|
22
|
+
| `case_convert` | Convert between camelCase, snake_case, kebab-case, PascalCase, CONSTANT_CASE, Title Case, dot.case |
|
|
23
|
+
| `slugify` | Convert text to a URL-friendly slug |
|
|
24
|
+
| `word_count` | Count words, characters, sentences, paragraphs, estimate reading time |
|
|
25
|
+
| `lorem_ipsum` | Generate lorem ipsum placeholder text (words, sentences, paragraphs) |
|
|
26
|
+
| `truncate` | Truncate text at character, word, or sentence boundary with custom suffix |
|
|
27
|
+
| `regex_replace` | Find and replace using regular expressions with capture groups |
|
|
28
|
+
| `markdown_strip` | Strip markdown formatting to get plain text |
|
|
29
|
+
| `text_reverse` | Reverse text by characters, words, or lines |
|
|
30
|
+
| `line_sort` | Sort lines alphabetically, numerically, by length, or randomly; deduplicate |
|
|
31
|
+
| `text_diff` | Compare two texts and show line-by-line differences |
|
|
32
|
+
| `extract_emails` | Extract all email addresses from text |
|
|
33
|
+
| `extract_urls` | Extract all URLs from text |
|
|
34
|
+
| `text_pad` | Pad text to fixed width — left, right, or center aligned |
|
|
35
|
+
| `text_wrap` | Wrap text to specified line width at word boundaries |
|
|
36
|
+
| `string_repeat` | Repeat a string N times with optional separator |
|
|
37
|
+
|
|
38
|
+
## Why use this?
|
|
39
|
+
|
|
40
|
+
- **Zero config** — `npx` and go, no API keys needed
|
|
41
|
+
- **15 tools** — covers the most common text transformation tasks
|
|
42
|
+
- **Works everywhere** — Claude Desktop, Cursor, Windsurf, any MCP client
|
|
2
43
|
|
|
3
44
|
## Support
|
|
4
45
|
|
|
@@ -6,3 +47,11 @@ If this tool saves you time, consider supporting development:
|
|
|
6
47
|
|
|
7
48
|
- [Buy me a coffee](https://buymeacoffee.com/gl89tu25lp)
|
|
8
49
|
- [Tip via Stripe ($3)](https://buy.stripe.com/dRm8wP8R295Z9VyeN59Zm00)
|
|
50
|
+
|
|
51
|
+
## Like this? Try mcp-devutils
|
|
52
|
+
|
|
53
|
+
**[mcp-devutils](https://www.npmjs.com/package/mcp-devutils)** — 44 developer tools in one MCP server. UUID, hash, JWT, JSON diff, AES encryption, and more. 15 free, [unlock all 44 for $5](https://buy.stripe.com/bJe00jgjugyr5Fi5cv9Zm05).
|
|
54
|
+
|
|
55
|
+
## License
|
|
56
|
+
|
|
57
|
+
MIT
|
package/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
4
4
|
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
5
5
|
|
|
6
6
|
const server = new Server(
|
|
7
|
-
{ name: "mcp-texttools", version: "1.
|
|
7
|
+
{ name: "mcp-texttools", version: "1.1.0" },
|
|
8
8
|
{ capabilities: { tools: {} } }
|
|
9
9
|
);
|
|
10
10
|
|
|
@@ -152,6 +152,69 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
152
152
|
},
|
|
153
153
|
required: ["text1", "text2"]
|
|
154
154
|
}
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
name: "extract_emails",
|
|
158
|
+
description: "Extract all email addresses from text, with optional deduplication",
|
|
159
|
+
inputSchema: {
|
|
160
|
+
type: "object",
|
|
161
|
+
properties: {
|
|
162
|
+
text: { type: "string", description: "Text to extract emails from" },
|
|
163
|
+
unique: { type: "boolean", description: "Return only unique emails (default: true)" }
|
|
164
|
+
},
|
|
165
|
+
required: ["text"]
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
name: "extract_urls",
|
|
170
|
+
description: "Extract all URLs (http/https) from text, with optional deduplication",
|
|
171
|
+
inputSchema: {
|
|
172
|
+
type: "object",
|
|
173
|
+
properties: {
|
|
174
|
+
text: { type: "string", description: "Text to extract URLs from" },
|
|
175
|
+
unique: { type: "boolean", description: "Return only unique URLs (default: true)" }
|
|
176
|
+
},
|
|
177
|
+
required: ["text"]
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
name: "text_pad",
|
|
182
|
+
description: "Pad text to a fixed width — left, right, or center aligned",
|
|
183
|
+
inputSchema: {
|
|
184
|
+
type: "object",
|
|
185
|
+
properties: {
|
|
186
|
+
text: { type: "string", description: "Text to pad" },
|
|
187
|
+
width: { type: "number", description: "Target width in characters" },
|
|
188
|
+
align: { type: "string", enum: ["left", "right", "center"], description: "Alignment (default: right)" },
|
|
189
|
+
char: { type: "string", description: "Padding character (default: space)" }
|
|
190
|
+
},
|
|
191
|
+
required: ["text", "width"]
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
name: "text_wrap",
|
|
196
|
+
description: "Wrap text to a specified line width, breaking at word boundaries",
|
|
197
|
+
inputSchema: {
|
|
198
|
+
type: "object",
|
|
199
|
+
properties: {
|
|
200
|
+
text: { type: "string", description: "Text to wrap" },
|
|
201
|
+
width: { type: "number", description: "Maximum line width (default: 80)" }
|
|
202
|
+
},
|
|
203
|
+
required: ["text"]
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
name: "string_repeat",
|
|
208
|
+
description: "Repeat a string N times with an optional separator",
|
|
209
|
+
inputSchema: {
|
|
210
|
+
type: "object",
|
|
211
|
+
properties: {
|
|
212
|
+
text: { type: "string", description: "Text to repeat" },
|
|
213
|
+
count: { type: "number", description: "Number of repetitions (1-1000, default: 2)" },
|
|
214
|
+
separator: { type: "string", description: "Separator between repetitions (default: empty)" }
|
|
215
|
+
},
|
|
216
|
+
required: ["text"]
|
|
217
|
+
}
|
|
155
218
|
}
|
|
156
219
|
]
|
|
157
220
|
};
|
|
@@ -447,6 +510,82 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
447
510
|
return { content: [{ type: "text", text: output.join("\n") + summary }] };
|
|
448
511
|
}
|
|
449
512
|
|
|
513
|
+
case "extract_emails": {
|
|
514
|
+
const { text, unique = true } = args;
|
|
515
|
+
const emailRegex = /[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}/g;
|
|
516
|
+
let emails = text.match(emailRegex) || [];
|
|
517
|
+
if (unique) emails = [...new Set(emails.map(e => e.toLowerCase()))];
|
|
518
|
+
if (emails.length === 0) {
|
|
519
|
+
return { content: [{ type: "text", text: "No email addresses found." }] };
|
|
520
|
+
}
|
|
521
|
+
return { content: [{ type: "text", text: `Found ${emails.length} email(s):\n\n${emails.join("\n")}` }] };
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
case "extract_urls": {
|
|
525
|
+
const { text, unique = true } = args;
|
|
526
|
+
const urlRegex = /https?:\/\/[^\s<>\"')\]]+/g;
|
|
527
|
+
let urls = text.match(urlRegex) || [];
|
|
528
|
+
if (unique) urls = [...new Set(urls)];
|
|
529
|
+
if (urls.length === 0) {
|
|
530
|
+
return { content: [{ type: "text", text: "No URLs found." }] };
|
|
531
|
+
}
|
|
532
|
+
return { content: [{ type: "text", text: `Found ${urls.length} URL(s):\n\n${urls.join("\n")}` }] };
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
case "text_pad": {
|
|
536
|
+
const { text, width, align = "right", char = " " } = args;
|
|
537
|
+
const padChar = char.charAt(0) || " ";
|
|
538
|
+
const lines = text.split("\n");
|
|
539
|
+
const padded = lines.map(line => {
|
|
540
|
+
if (line.length >= width) return line;
|
|
541
|
+
const diff = width - line.length;
|
|
542
|
+
switch (align) {
|
|
543
|
+
case "left":
|
|
544
|
+
return line + padChar.repeat(diff);
|
|
545
|
+
case "center": {
|
|
546
|
+
const left = Math.floor(diff / 2);
|
|
547
|
+
const right = diff - left;
|
|
548
|
+
return padChar.repeat(left) + line + padChar.repeat(right);
|
|
549
|
+
}
|
|
550
|
+
case "right":
|
|
551
|
+
default:
|
|
552
|
+
return padChar.repeat(diff) + line;
|
|
553
|
+
}
|
|
554
|
+
});
|
|
555
|
+
return { content: [{ type: "text", text: padded.join("\n") }] };
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
case "text_wrap": {
|
|
559
|
+
const { text, width = 80 } = args;
|
|
560
|
+
const paragraphs = text.split("\n");
|
|
561
|
+
const wrapped = paragraphs.map(para => {
|
|
562
|
+
if (para.trim() === "") return "";
|
|
563
|
+
const words = para.split(/\s+/);
|
|
564
|
+
const lines = [];
|
|
565
|
+
let current = "";
|
|
566
|
+
for (const word of words) {
|
|
567
|
+
if (current.length === 0) {
|
|
568
|
+
current = word;
|
|
569
|
+
} else if (current.length + 1 + word.length <= width) {
|
|
570
|
+
current += " " + word;
|
|
571
|
+
} else {
|
|
572
|
+
lines.push(current);
|
|
573
|
+
current = word;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
if (current) lines.push(current);
|
|
577
|
+
return lines.join("\n");
|
|
578
|
+
});
|
|
579
|
+
return { content: [{ type: "text", text: wrapped.join("\n") }] };
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
case "string_repeat": {
|
|
583
|
+
const { text, count = 2, separator = "" } = args;
|
|
584
|
+
const n = Math.max(1, Math.min(1000, count));
|
|
585
|
+
const result = Array(n).fill(text).join(separator);
|
|
586
|
+
return { content: [{ type: "text", text: result }] };
|
|
587
|
+
}
|
|
588
|
+
|
|
450
589
|
default:
|
|
451
590
|
throw new Error(`Unknown tool: ${name}`);
|
|
452
591
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-texttools",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "MCP server with
|
|
3
|
+
"version": "1.1.1",
|
|
4
|
+
"description": "MCP server with 15 text transformation tools — case conversion, slug, word count, lorem ipsum, truncate, regex replace, markdown strip, reverse, line sort, text diff, extract emails, extract URLs, text pad, text wrap, string repeat",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"bin": {
|
|
@@ -24,7 +24,12 @@
|
|
|
24
24
|
"claude",
|
|
25
25
|
"cursor",
|
|
26
26
|
"ai-tools",
|
|
27
|
-
"string-utils"
|
|
27
|
+
"string-utils",
|
|
28
|
+
"extract-email",
|
|
29
|
+
"extract-url",
|
|
30
|
+
"text-wrap",
|
|
31
|
+
"string-repeat",
|
|
32
|
+
"text-padding"
|
|
28
33
|
],
|
|
29
34
|
"author": "Hong Teoh",
|
|
30
35
|
"license": "MIT",
|