idiolect-mcp 0.1.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 +32 -0
- package/package.json +17 -0
- package/server.mjs +88 -0
package/README.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# idiolect-mcp
|
|
2
|
+
|
|
3
|
+
MCP server that makes any MCP-compatible AI (Claude Desktop, Claude Code, …)
|
|
4
|
+
write in **your** voice, using your [Idiolect](https://idiolect.lol) Voice Card.
|
|
5
|
+
|
|
6
|
+
## Setup
|
|
7
|
+
|
|
8
|
+
1. Get your voice at **https://idiolect.lol** — note the slug in your result URL
|
|
9
|
+
(`idiolect.lol/v/<slug>`).
|
|
10
|
+
2. Add to your MCP config:
|
|
11
|
+
|
|
12
|
+
```json
|
|
13
|
+
{
|
|
14
|
+
"mcpServers": {
|
|
15
|
+
"idiolect": {
|
|
16
|
+
"command": "npx",
|
|
17
|
+
"args": ["-y", "idiolect-mcp"],
|
|
18
|
+
"env": { "IDIOLECT_SLUG": "your-slug" }
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Tool
|
|
25
|
+
|
|
26
|
+
- **`get_my_voice`** — returns your Voice Card. The model calls it before writing
|
|
27
|
+
on your behalf, then writes as you. Pass `slug` per-call or set `IDIOLECT_SLUG`.
|
|
28
|
+
|
|
29
|
+
Set `IDIOLECT_BASE` to point at a self-hosted instance (defaults to
|
|
30
|
+
`https://idiolect.lol`).
|
|
31
|
+
|
|
32
|
+
MIT licensed.
|
package/package.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "idiolect-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"bin": { "idiolect-mcp": "server.mjs" },
|
|
6
|
+
"description": "MCP server that gives any MCP-compatible AI (Claude, etc.) your Idiolect voice — make AI write as you. https://idiolect.lol",
|
|
7
|
+
"keywords": ["mcp", "model-context-protocol", "claude", "ai", "writing", "voice", "idiolect"],
|
|
8
|
+
"homepage": "https://idiolect.lol",
|
|
9
|
+
"repository": { "type": "git", "url": "https://github.com/111mihir/idiolect.git", "directory": "mcp" },
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"files": ["server.mjs", "README.md"],
|
|
12
|
+
"engines": { "node": ">=18" },
|
|
13
|
+
"publishConfig": { "access": "public" },
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@modelcontextprotocol/sdk": "^1.0.4"
|
|
16
|
+
}
|
|
17
|
+
}
|
package/server.mjs
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Idiolect MCP server — gives any MCP-compatible AI (Claude Desktop, Claude
|
|
3
|
+
// Code, etc.) your personal voice. Configure with your Voice Card slug:
|
|
4
|
+
//
|
|
5
|
+
// {
|
|
6
|
+
// "mcpServers": {
|
|
7
|
+
// "idiolect": {
|
|
8
|
+
// "command": "node",
|
|
9
|
+
// "args": ["/path/to/idiolect/mcp/server.mjs"],
|
|
10
|
+
// "env": { "IDIOLECT_SLUG": "your-slug", "IDIOLECT_BASE": "https://idiolect.lol" }
|
|
11
|
+
// }
|
|
12
|
+
// }
|
|
13
|
+
// }
|
|
14
|
+
|
|
15
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
16
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
17
|
+
import {
|
|
18
|
+
CallToolRequestSchema,
|
|
19
|
+
ListToolsRequestSchema,
|
|
20
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
21
|
+
|
|
22
|
+
const BASE = process.env.IDIOLECT_BASE || "https://idiolect.lol";
|
|
23
|
+
const DEFAULT_SLUG = process.env.IDIOLECT_SLUG || "";
|
|
24
|
+
|
|
25
|
+
async function fetchVoice(slug) {
|
|
26
|
+
const res = await fetch(`${BASE}/api/voice/${encodeURIComponent(slug)}`);
|
|
27
|
+
if (!res.ok) throw new Error(`Idiolect: voice "${slug}" not found (${res.status})`);
|
|
28
|
+
return res.json();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const server = new Server(
|
|
32
|
+
{ name: "idiolect", version: "0.1.0" },
|
|
33
|
+
{ capabilities: { tools: {} } },
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
37
|
+
tools: [
|
|
38
|
+
{
|
|
39
|
+
name: "get_my_voice",
|
|
40
|
+
description:
|
|
41
|
+
"Load the user's Idiolect Voice Card. Call this BEFORE writing anything on the user's behalf (emails, posts, messages, docs) and then write strictly in the returned voice. Returns a style guide describing how the user actually writes.",
|
|
42
|
+
inputSchema: {
|
|
43
|
+
type: "object",
|
|
44
|
+
properties: {
|
|
45
|
+
slug: {
|
|
46
|
+
type: "string",
|
|
47
|
+
description:
|
|
48
|
+
"Idiolect voice slug. Optional if IDIOLECT_SLUG is set in the server env.",
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
}));
|
|
55
|
+
|
|
56
|
+
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
57
|
+
if (req.params.name !== "get_my_voice") {
|
|
58
|
+
throw new Error(`Unknown tool: ${req.params.name}`);
|
|
59
|
+
}
|
|
60
|
+
const slug = req.params.arguments?.slug || DEFAULT_SLUG;
|
|
61
|
+
if (!slug) {
|
|
62
|
+
return {
|
|
63
|
+
content: [
|
|
64
|
+
{
|
|
65
|
+
type: "text",
|
|
66
|
+
text: "No Idiolect slug provided. Pass `slug` or set IDIOLECT_SLUG. Get yours at https://idiolect.lol",
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
isError: true,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
const v = await fetchVoice(slug);
|
|
74
|
+
return {
|
|
75
|
+
content: [
|
|
76
|
+
{
|
|
77
|
+
type: "text",
|
|
78
|
+
text: `${v.voiceCard}\n\n---\n(Idiolect voice #${slug} · genericness ${v.genericnessScore}/100. Write everything as this person from now on.)`,
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
};
|
|
82
|
+
} catch (e) {
|
|
83
|
+
return { content: [{ type: "text", text: String(e) }], isError: true };
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const transport = new StdioServerTransport();
|
|
88
|
+
await server.connect(transport);
|