idiolect-mcp 0.5.1 → 0.5.2
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 +10 -4
- package/package.json +1 -1
- package/progressive-catalog.json +21 -9
- package/server.mjs +20 -0
package/README.md
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# idiolect-mcp
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
Idiolect AI creates and revises writing through MCP-compatible AI tools. A Writing Profile
|
|
4
|
+
personalizes the result using writing samples, stated preferences, and learned patterns.
|
|
5
|
+
Writing requests do not need a brand mention or an existing profile.
|
|
5
6
|
|
|
6
7
|
## Setup
|
|
7
8
|
|
|
@@ -46,8 +47,8 @@ Remote OAuth and account-mode stdio advertise the same user-facing tools.
|
|
|
46
47
|
Setup state, evidence approval, retries, and idempotency stay inside the server;
|
|
47
48
|
clients receive one `next` action and never coordinate workflow versions or locks.
|
|
48
49
|
|
|
49
|
-
- **`write`** —
|
|
50
|
-
- **`rewrite`** —
|
|
50
|
+
- **`write`** — drafts writing from requests, facts, notes, or outlines.
|
|
51
|
+
- **`rewrite`** — corrects, summarizes, expands, simplifies, paraphrases, or repurposes existing text.
|
|
51
52
|
- **`refine_writing`** — changes returned writing, applies a template, or records its outcome.
|
|
52
53
|
- **`view_writing_profile`** — lists Writing Profiles and shows the selected or current profile.
|
|
53
54
|
- **`list_writing_samples`** — lists the writing behind one profile.
|
|
@@ -61,6 +62,11 @@ clients receive one `next` action and never coordinate workflow versions or lock
|
|
|
61
62
|
- **`remove_writing_sample`** — revokes one ready or waiting sample.
|
|
62
63
|
- **`delete_writing_profile`** — deletes a selected profile.
|
|
63
64
|
|
|
65
|
+
Profile creation, approved samples, and lasting preferences can be part of writing and
|
|
66
|
+
revision workflows. They do not require a separate profile-management request. Inferred
|
|
67
|
+
patterns can contribute approved authored examples; they must not become user-stated rules.
|
|
68
|
+
See [the MCP content standard](../docs/MCP-CONTENT-STANDARD.md) for writing and review rules.
|
|
69
|
+
|
|
64
70
|
Cached account-mode tool names remain callable but are not advertised. Slug mode keeps its
|
|
65
71
|
legacy local-samples catalogue; locally configured samples are used only for stateless scoring
|
|
66
72
|
and are not stored.
|
package/package.json
CHANGED
package/progressive-catalog.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"instructions": "Idiolect AI
|
|
2
|
+
"instructions": "Idiolect AI creates and revises writing for the user. A Writing Profile personalizes the result using writing samples, stated preferences, and learned patterns. The profile tools support continued personalization throughout writing and revision.\n\nUse Idiolect AI for requested writing tasks, including the writing portion of a larger workflow. These span personal, professional, technical, academic, and creative content. Examples include messages, reports, applications, speeches, product copy, and articles. These are examples, not required formats. The user does not need to name Idiolect AI or request a Writing Profile.\n\nFor new writing from requests, facts, notes, or outlines, call `write`. For existing text, call `rewrite`. Changes include corrections, summarization, expansion, simplification, paraphrasing, restructuring, and changes of tone, style, audience, or format. Preserve requests such as 'make this sound like me' or 'make this less AI-written' in `instructions`. An existing Writing Profile is not required to start. Call the writing tool without first checking profile state.\n\nWhen `write` or `rewrite` returns `needs_setup`, keep the task unchanged. Follow `next.action`. For `choose_setup`, follow these steps. Show all five `setupOptions` in the supplied order, numbered 1–5. Keep each label and one-line description. Open with \"How should Idiolect AI write this?\" and lead with the write-now option. End with: Reply with a number, a name, or just write it. Your request is saved; you don't need to repeat it. Then wait for the user to answer. An answer in the chat is enough. Map a number to the option you actually displayed in this conversation, including an older or reordered menu. Map a template name directly. If no template is named, ask which template. Map 'whatever', 'just write it', and 'skip' to `plain`. Do not ask for confirmation. If the user does not want a Writing Profile or a template, select `plain`. If the user explicitly wants a template for all their writing, add `alwaysUse` true to that template; otherwise leave it unset. If they abandon profile setup for plain or a named template, complete the same held request with that choice immediately. Then call the same writing tool with the selected option. For `check_context` or `ask_user`, follow the returned message instead of the setup menu. Set a persistent default only when the user requests one.\n\nWhen a result returns `needs_evidence`, offer pasted writing or short questions. If host rules permit another source, the user can approve access to that source. Before sending material, show the exact excerpts or answers and obtain the required approval. Reuse approval already given for that exact material and purpose. Send only approved material. Set `source` and `userApproved` accurately. Exclude AI text, prompts, templates, signatures, quotations, and forwarded text from learning evidence. If the user declines, finish the held request with plain style or their selected template.\n\nWhen the user requests a change to returned writing, call `refine_writing` with its reference. The user does not need to name Idiolect AI again. Record an outcome only after the user reports it. Send `finalText` only when their exact final wording is known. Do not request a rating.\n\nDevelop personalization during writing and revision workflows, within the user's permission for that material and purpose. When approved authored examples are available, call `add_writing_samples`. If no Writing Profile exists, use `create_writing_profile` instead. A separate profile-management request is not required. When the user states a lasting writing preference, call `add_writing_rule`. Keep their words and stated scope. A rule without `profile` applies to all profiles. For an inferred pattern, contribute its approved authored examples rather than recording an inference as a user-stated rule. Directions for one piece belong to that writing task, not a lasting rule.\n\nWhen profile details are needed for the user's request, call `view_writing_profile`. Use `list_writing_samples` when the supporting writing is needed. Use profile actions to complete authorized writing or personalization workflows. Describe a persistent settings change before calling its tool. The host's destructive-action confirmation is sufficient; do not add another confirmation. Profile tools support writing workflows; they do not themselves generate the requested draft.\n\nPreserve supplied facts and protected wording unless the user requests changes. Keep the source narrator unless the user requests a change. Ask only for necessary facts, required permission, or unresolved ambiguity. Never invent facts, positions, experiences, or opinions. Writing tools return text; they do not send messages or publish content. Respect the user's tool choice and the host's permissions.\n\nHost context boundary: use the current request and data already stored in Idiolect AI. For another source, follow the host's rules and obtain the required approval before access. Show the exact excerpts before sending them. Send only approved, task-relevant material. If the host's source rules are unknown, use only the current request and stored Idiolect AI data. The connector never directs another plugin or connector to gather material.",
|
|
3
3
|
"tools": [
|
|
4
4
|
{
|
|
5
5
|
"name": "write",
|
|
6
6
|
"title": "Write",
|
|
7
|
-
"description": "Use this when the user
|
|
7
|
+
"description": "Use this when the user needs new writing from a request, facts, notes, or an outline. It returns a draft for the requested purpose, audience, and format. A Writing Profile personalizes the draft when available. If the tool returns a setup step, follow that step.",
|
|
8
8
|
"inputSchema": {
|
|
9
9
|
"type": "object",
|
|
10
10
|
"properties": {
|
|
@@ -37,6 +37,12 @@
|
|
|
37
37
|
"maxLength": 8000,
|
|
38
38
|
"description": "The user's exact directions about tone, length, structure, or exclusions. Omit when none were given. Put content in `request` and a named output form in `format`."
|
|
39
39
|
},
|
|
40
|
+
"language": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"minLength": 1,
|
|
43
|
+
"maxLength": 100,
|
|
44
|
+
"description": "The language for the finished writing, in plain words (for example 'French'). Set it only when the user asked for a specific language. Omit it to follow the request's language, or the source text's language for a rewrite."
|
|
45
|
+
},
|
|
40
46
|
"effects": {
|
|
41
47
|
"type": "array",
|
|
42
48
|
"maxItems": 20,
|
|
@@ -1184,7 +1190,7 @@
|
|
|
1184
1190
|
{
|
|
1185
1191
|
"name": "rewrite",
|
|
1186
1192
|
"title": "Rewrite",
|
|
1187
|
-
"description": "Use this when the user
|
|
1193
|
+
"description": "Use this when the user wants existing text changed, from a small correction to a complete rewrite. Changes include grammar, clarity, length, structure, tone, style, audience, and format. It can shorten, summarize, expand, simplify, paraphrase, or repurpose the supplied text. Requests include 'make this sound like me' and 'make this less AI-written'. A Writing Profile personalizes the result when available. Preserve supplied facts and protected wording unless the user requests changes.",
|
|
1188
1194
|
"inputSchema": {
|
|
1189
1195
|
"type": "object",
|
|
1190
1196
|
"properties": {
|
|
@@ -1215,6 +1221,12 @@
|
|
|
1215
1221
|
"maxLength": 8000,
|
|
1216
1222
|
"description": "The user's exact change request. Keep it separate from the prose. Use `changeScope` for the amount of change. Do not replace their words with an effect label."
|
|
1217
1223
|
},
|
|
1224
|
+
"language": {
|
|
1225
|
+
"type": "string",
|
|
1226
|
+
"minLength": 1,
|
|
1227
|
+
"maxLength": 100,
|
|
1228
|
+
"description": "The language for the finished writing, in plain words (for example 'French'). Set it only when the user asked for a specific language. Omit it to follow the request's language, or the source text's language for a rewrite."
|
|
1229
|
+
},
|
|
1218
1230
|
"changeScope": {
|
|
1219
1231
|
"type": "string",
|
|
1220
1232
|
"enum": [
|
|
@@ -2371,7 +2383,7 @@
|
|
|
2371
2383
|
{
|
|
2372
2384
|
"name": "refine_writing",
|
|
2373
2385
|
"title": "Refine writing",
|
|
2374
|
-
"description": "Use this when the user
|
|
2386
|
+
"description": "Use this when the user requests changes to an identified piece that Idiolect AI returned. It continues the writing task through further revisions or a selected template. It can also record the user's reported outcome or exact final wording. Use the returned writing reference.",
|
|
2375
2387
|
"inputSchema": {
|
|
2376
2388
|
"type": "object",
|
|
2377
2389
|
"properties": {
|
|
@@ -2641,7 +2653,7 @@
|
|
|
2641
2653
|
{
|
|
2642
2654
|
"name": "view_writing_profile",
|
|
2643
2655
|
"title": "View writing profile",
|
|
2644
|
-
"description": "Use this when the user
|
|
2656
|
+
"description": "Use this when profile details are needed to answer the user or resolve a writing or personalization task. Without `profile`, it lists all profiles and shows the current one in full.",
|
|
2645
2657
|
"inputSchema": {
|
|
2646
2658
|
"type": "object",
|
|
2647
2659
|
"properties": {
|
|
@@ -2979,7 +2991,7 @@
|
|
|
2979
2991
|
{
|
|
2980
2992
|
"name": "list_writing_samples",
|
|
2981
2993
|
"title": "List writing samples",
|
|
2982
|
-
"description": "Use this when the
|
|
2994
|
+
"description": "Use this when the writing behind a profile is needed for inspection or an authorized personalization workflow.",
|
|
2983
2995
|
"inputSchema": {
|
|
2984
2996
|
"type": "object",
|
|
2985
2997
|
"properties": {
|
|
@@ -3321,7 +3333,7 @@
|
|
|
3321
3333
|
{
|
|
3322
3334
|
"name": "create_writing_profile",
|
|
3323
3335
|
"title": "Create writing profile",
|
|
3324
|
-
"description": "Use this when
|
|
3336
|
+
"description": "Use this when personalization requires a new Writing Profile and approved writing samples or answers are available. It can continue a writing task that is waiting for a profile. It never changes an existing profile.",
|
|
3325
3337
|
"inputSchema": {
|
|
3326
3338
|
"type": "object",
|
|
3327
3339
|
"properties": {
|
|
@@ -3747,7 +3759,7 @@
|
|
|
3747
3759
|
{
|
|
3748
3760
|
"name": "add_writing_samples",
|
|
3749
3761
|
"title": "Add writing samples",
|
|
3750
|
-
"description": "Use this when the user
|
|
3762
|
+
"description": "Use this when additional approved examples of the user's writing are available for an existing Writing Profile. This includes examples supplied during writing and revision workflows.",
|
|
3751
3763
|
"inputSchema": {
|
|
3752
3764
|
"type": "object",
|
|
3753
3765
|
"properties": {
|
|
@@ -5172,7 +5184,7 @@
|
|
|
5172
5184
|
{
|
|
5173
5185
|
"name": "add_writing_rule",
|
|
5174
5186
|
"title": "Add writing rule",
|
|
5175
|
-
"description": "Use this when the user states a lasting writing
|
|
5187
|
+
"description": "Use this when the user states a lasting writing preference, including during a writing task. Save the preference in their words with its stated scope.",
|
|
5176
5188
|
"inputSchema": {
|
|
5177
5189
|
"not": {
|
|
5178
5190
|
"required": [
|
package/server.mjs
CHANGED
|
@@ -1061,6 +1061,12 @@ const accountToolDefinitions = [
|
|
|
1061
1061
|
description:
|
|
1062
1062
|
"The user's actual change request — length, tone, audience, what to cut or keep, make it sound less AI-written, roughen it up, or make it sound like I am talking. Kept separate from `text`: put the request here, never inside the prose to rewrite. `changeScope` carries magnitude; `instructions` carries the requested change.",
|
|
1063
1063
|
},
|
|
1064
|
+
language: {
|
|
1065
|
+
type: "string",
|
|
1066
|
+
minLength: 1,
|
|
1067
|
+
maxLength: 100,
|
|
1068
|
+
description: "The language for the finished writing, in plain words (for example 'French'). Set it only when the user asked for a specific language. Omit it to follow the request's language, or the source text's language for a rewrite.",
|
|
1069
|
+
},
|
|
1064
1070
|
changeScope: CHANGE_SCOPE_SCHEMA,
|
|
1065
1071
|
effects: EFFECTS_SCHEMA,
|
|
1066
1072
|
sourceAuthor: SOURCE_AUTHOR_SCHEMA,
|
|
@@ -1101,6 +1107,12 @@ const accountToolDefinitions = [
|
|
|
1101
1107
|
description:
|
|
1102
1108
|
"`instructions` is the user's actual direction: how to write the piece — tone, length, format, structure, and what to leave out. Optional; omit it when the user gave none. Never paste directions into `brief`, which carries the material, and never put material here. A named output shape goes in `format`.",
|
|
1103
1109
|
},
|
|
1110
|
+
language: {
|
|
1111
|
+
type: "string",
|
|
1112
|
+
minLength: 1,
|
|
1113
|
+
maxLength: 100,
|
|
1114
|
+
description: "The language for the finished writing, in plain words (for example 'French'). Set it only when the user asked for a specific language. Omit it to follow the request's language, or the source text's language for a rewrite.",
|
|
1115
|
+
},
|
|
1104
1116
|
effects: EFFECTS_SCHEMA,
|
|
1105
1117
|
briefAuthor: BRIEF_AUTHOR_SCHEMA,
|
|
1106
1118
|
calibration: CALIBRATION_SCHEMA,
|
|
@@ -1625,6 +1637,9 @@ export async function handleToolRequest(req) {
|
|
|
1625
1637
|
const instructions = typeof args.instructions === "string" && args.instructions.trim()
|
|
1626
1638
|
? args.instructions.trim()
|
|
1627
1639
|
: undefined;
|
|
1640
|
+
const language = typeof args.language === "string" && args.language.trim()
|
|
1641
|
+
? args.language.trim()
|
|
1642
|
+
: undefined;
|
|
1628
1643
|
const invalidChangeRequest = changeRequestError(args, "rewrite_in_voice");
|
|
1629
1644
|
if (invalidChangeRequest) return invalidChangeRequest;
|
|
1630
1645
|
const invalidSourceAuthor = authorProvenanceError(args, "rewrite_in_voice", "sourceAuthor");
|
|
@@ -1655,6 +1670,7 @@ export async function handleToolRequest(req) {
|
|
|
1655
1670
|
...(profileId !== undefined ? { voice: profileId } : {}),
|
|
1656
1671
|
...(targetRegister ? { targetRegister } : {}),
|
|
1657
1672
|
...(instructions ? { instructions } : {}),
|
|
1673
|
+
...(language ? { language } : {}),
|
|
1658
1674
|
...(changeScope !== undefined ? { changeScope } : {}),
|
|
1659
1675
|
...(effects !== undefined ? { effects } : {}),
|
|
1660
1676
|
...(sourceAuthor !== undefined ? { sourceAuthor } : {}),
|
|
@@ -1686,6 +1702,9 @@ export async function handleToolRequest(req) {
|
|
|
1686
1702
|
const instructions = typeof args.instructions === "string" && args.instructions.trim()
|
|
1687
1703
|
? args.instructions.trim()
|
|
1688
1704
|
: undefined;
|
|
1705
|
+
const language = typeof args.language === "string" && args.language.trim()
|
|
1706
|
+
? args.language.trim()
|
|
1707
|
+
: undefined;
|
|
1689
1708
|
const formats = new Set(["linkedin", "x_post", "x_thread", "newsletter", "generic"]);
|
|
1690
1709
|
const invalidChangeRequest = changeRequestError(args, "draft_in_voice");
|
|
1691
1710
|
if (invalidChangeRequest) return invalidChangeRequest;
|
|
@@ -1717,6 +1736,7 @@ export async function handleToolRequest(req) {
|
|
|
1717
1736
|
...(profileId !== undefined ? { voice: profileId } : {}),
|
|
1718
1737
|
...(format ? { format } : {}),
|
|
1719
1738
|
...(instructions ? { instructions } : {}),
|
|
1739
|
+
...(language ? { language } : {}),
|
|
1720
1740
|
...(changeScope !== undefined ? { changeScope } : {}),
|
|
1721
1741
|
...(effects !== undefined ? { effects } : {}),
|
|
1722
1742
|
...(briefAuthor !== undefined ? { briefAuthor } : {}),
|