anki-mcp-http 0.19.2 → 0.20.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 +7 -1
- package/dist/mcp/clients/anki-connect.client.d.ts +1 -0
- package/dist/mcp/clients/anki-connect.client.js +36 -11
- package/dist/mcp/clients/anki-connect.client.js.map +1 -1
- package/dist/mcp/primitives/essential/index.d.ts +13 -1
- package/dist/mcp/primitives/essential/index.js +25 -1
- package/dist/mcp/primitives/essential/index.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/add-model-field.tool.d.ts +113 -0
- package/dist/mcp/primitives/essential/tools/add-model-field.tool.js +150 -0
- package/dist/mcp/primitives/essential/tools/add-model-field.tool.js.map +1 -0
- package/dist/mcp/primitives/essential/tools/add-note.tool.js +1 -1
- package/dist/mcp/primitives/essential/tools/add-note.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/add-notes.tool.js +1 -1
- package/dist/mcp/primitives/essential/tools/add-notes.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/model-templates.tool.d.ts +116 -0
- package/dist/mcp/primitives/essential/tools/model-templates.tool.js +95 -0
- package/dist/mcp/primitives/essential/tools/model-templates.tool.js.map +1 -0
- package/dist/mcp/primitives/essential/tools/remove-model-field.tool.d.ts +112 -0
- package/dist/mcp/primitives/essential/tools/remove-model-field.tool.js +107 -0
- package/dist/mcp/primitives/essential/tools/remove-model-field.tool.js.map +1 -0
- package/dist/mcp/primitives/essential/tools/rename-model-field.tool.d.ts +114 -0
- package/dist/mcp/primitives/essential/tools/rename-model-field.tool.js +156 -0
- package/dist/mcp/primitives/essential/tools/rename-model-field.tool.js.map +1 -0
- package/dist/mcp/primitives/essential/tools/reposition-model-field.tool.d.ts +113 -0
- package/dist/mcp/primitives/essential/tools/reposition-model-field.tool.js +137 -0
- package/dist/mcp/primitives/essential/tools/reposition-model-field.tool.js.map +1 -0
- package/dist/mcp/primitives/essential/tools/update-model-templates.tool.d.ts +115 -0
- package/dist/mcp/primitives/essential/tools/update-model-templates.tool.js +140 -0
- package/dist/mcp/primitives/essential/tools/update-model-templates.tool.js.map +1 -0
- package/package.json +12 -11
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var RenameModelFieldTool_1;
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.RenameModelFieldTool = void 0;
|
|
14
|
+
const common_1 = require("@nestjs/common");
|
|
15
|
+
const mcp_nest_1 = require("@rekog/mcp-nest");
|
|
16
|
+
const zod_1 = require("zod");
|
|
17
|
+
const anki_connect_client_1 = require("../../../clients/anki-connect.client");
|
|
18
|
+
const anki_utils_1 = require("../../../utils/anki.utils");
|
|
19
|
+
let RenameModelFieldTool = RenameModelFieldTool_1 = class RenameModelFieldTool {
|
|
20
|
+
ankiClient;
|
|
21
|
+
logger = new common_1.Logger(RenameModelFieldTool_1.name);
|
|
22
|
+
constructor(ankiClient) {
|
|
23
|
+
this.ankiClient = ankiClient;
|
|
24
|
+
}
|
|
25
|
+
async renameModelField({ modelName, oldFieldName, newFieldName, }) {
|
|
26
|
+
try {
|
|
27
|
+
this.logger.log(`Renaming field "${oldFieldName}" → "${newFieldName}" in model "${modelName}"`);
|
|
28
|
+
if (oldFieldName === newFieldName) {
|
|
29
|
+
return (0, anki_utils_1.createErrorResponse)(new Error(`Old and new field names are identical ("${oldFieldName}") — nothing to rename`), {
|
|
30
|
+
modelName,
|
|
31
|
+
oldFieldName,
|
|
32
|
+
newFieldName,
|
|
33
|
+
hint: "Provide a new field name that differs from the current one.",
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
const fields = await this.ankiClient.invoke("modelFieldNames", {
|
|
37
|
+
modelName,
|
|
38
|
+
});
|
|
39
|
+
if (!fields || fields.length === 0) {
|
|
40
|
+
return (0, anki_utils_1.createErrorResponse)(new Error(`Model "${modelName}" has no fields or does not exist`), {
|
|
41
|
+
modelName,
|
|
42
|
+
oldFieldName,
|
|
43
|
+
newFieldName,
|
|
44
|
+
hint: "Model not found. Use modelNames tool to see available models.",
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
if (!fields.includes(oldFieldName)) {
|
|
48
|
+
return (0, anki_utils_1.createErrorResponse)(new Error(`Field "${oldFieldName}" does not exist in model "${modelName}"`), {
|
|
49
|
+
modelName,
|
|
50
|
+
oldFieldName,
|
|
51
|
+
newFieldName,
|
|
52
|
+
hint: "Field names are case-sensitive. Use modelFieldNames to see the current field names.",
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
if (fields.includes(newFieldName)) {
|
|
56
|
+
return (0, anki_utils_1.createErrorResponse)(new Error(`A field named "${newFieldName}" already exists in model "${modelName}". ` +
|
|
57
|
+
'AnkiConnect would silently mangle the name with a "+" suffix instead of erroring.'), {
|
|
58
|
+
modelName,
|
|
59
|
+
oldFieldName,
|
|
60
|
+
newFieldName,
|
|
61
|
+
hint: `A field named "${newFieldName}" already exists in this model.`,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
const caseVariant = fields.find((f) => f !== oldFieldName && f.toLowerCase() === newFieldName.toLowerCase());
|
|
65
|
+
if (caseVariant) {
|
|
66
|
+
return (0, anki_utils_1.createErrorResponse)(new Error(`Field "${newFieldName}" collides with existing field "${caseVariant}" ` +
|
|
67
|
+
`in model "${modelName}" (names differ only in case)`), {
|
|
68
|
+
modelName,
|
|
69
|
+
oldFieldName,
|
|
70
|
+
newFieldName,
|
|
71
|
+
hint: `Field names are case-sensitive, but "${newFieldName}" differs from existing field "${caseVariant}" only in case. Pick a distinct name.`,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
await this.ankiClient.invoke("modelFieldRename", {
|
|
75
|
+
modelName,
|
|
76
|
+
oldFieldName,
|
|
77
|
+
newFieldName,
|
|
78
|
+
});
|
|
79
|
+
this.logger.log(`Successfully renamed field "${oldFieldName}" to "${newFieldName}" in model "${modelName}"`);
|
|
80
|
+
return {
|
|
81
|
+
success: true,
|
|
82
|
+
modelName,
|
|
83
|
+
oldFieldName,
|
|
84
|
+
newFieldName,
|
|
85
|
+
message: `Successfully renamed field "${oldFieldName}" to "${newFieldName}" in model "${modelName}"`,
|
|
86
|
+
warning: `Card templates referencing "{{${oldFieldName}}}" must be updated manually ` +
|
|
87
|
+
`to "{{${newFieldName}}}" using the updateModelTemplates tool.`,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
this.logger.error(`Failed to rename field "${oldFieldName}" in model "${modelName}"`, error);
|
|
92
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
93
|
+
if (errorMessage.includes("not found") ||
|
|
94
|
+
errorMessage.includes("does not exist")) {
|
|
95
|
+
return (0, anki_utils_1.createErrorResponse)(error, {
|
|
96
|
+
modelName,
|
|
97
|
+
oldFieldName,
|
|
98
|
+
newFieldName,
|
|
99
|
+
hint: "Model or field not found. Use modelNames and modelFieldNames tools to verify names.",
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return (0, anki_utils_1.createErrorResponse)(error, {
|
|
103
|
+
modelName,
|
|
104
|
+
oldFieldName,
|
|
105
|
+
newFieldName,
|
|
106
|
+
hint: "Make sure Anki is running and the model and field names are correct.",
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
exports.RenameModelFieldTool = RenameModelFieldTool;
|
|
112
|
+
__decorate([
|
|
113
|
+
(0, mcp_nest_1.Tool)({
|
|
114
|
+
name: "renameModelField",
|
|
115
|
+
description: "Rename a field in an existing Anki note type (model). " +
|
|
116
|
+
"Card templates that reference the old field name (e.g., {{OldName}}) will need to be " +
|
|
117
|
+
"updated separately using updateModelTemplates — they are not updated automatically. " +
|
|
118
|
+
"Use modelFieldNames to confirm the current field name before renaming.",
|
|
119
|
+
parameters: zod_1.z.object({
|
|
120
|
+
modelName: zod_1.z
|
|
121
|
+
.string()
|
|
122
|
+
.min(1)
|
|
123
|
+
.describe('Name of the note type to modify (e.g., "Basic", "Latin Vocabulary")'),
|
|
124
|
+
oldFieldName: zod_1.z
|
|
125
|
+
.string()
|
|
126
|
+
.min(1)
|
|
127
|
+
.describe('Current name of the field to rename (e.g., "Notes")'),
|
|
128
|
+
newFieldName: zod_1.z
|
|
129
|
+
.string()
|
|
130
|
+
.min(1)
|
|
131
|
+
.describe('New name for the field (e.g., "Grammar Notes")'),
|
|
132
|
+
}),
|
|
133
|
+
outputSchema: zod_1.z.object({
|
|
134
|
+
success: zod_1.z.boolean(),
|
|
135
|
+
modelName: zod_1.z.string(),
|
|
136
|
+
oldFieldName: zod_1.z.string(),
|
|
137
|
+
newFieldName: zod_1.z.string(),
|
|
138
|
+
message: zod_1.z.string(),
|
|
139
|
+
warning: zod_1.z.string().optional(),
|
|
140
|
+
}),
|
|
141
|
+
annotations: {
|
|
142
|
+
title: "Rename Field in Note Type",
|
|
143
|
+
readOnlyHint: false,
|
|
144
|
+
destructiveHint: false,
|
|
145
|
+
idempotentHint: false,
|
|
146
|
+
},
|
|
147
|
+
}),
|
|
148
|
+
__metadata("design:type", Function),
|
|
149
|
+
__metadata("design:paramtypes", [Object]),
|
|
150
|
+
__metadata("design:returntype", Promise)
|
|
151
|
+
], RenameModelFieldTool.prototype, "renameModelField", null);
|
|
152
|
+
exports.RenameModelFieldTool = RenameModelFieldTool = RenameModelFieldTool_1 = __decorate([
|
|
153
|
+
(0, common_1.Injectable)(),
|
|
154
|
+
__metadata("design:paramtypes", [anki_connect_client_1.AnkiConnectClient])
|
|
155
|
+
], RenameModelFieldTool);
|
|
156
|
+
//# sourceMappingURL=rename-model-field.tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rename-model-field.tool.js","sourceRoot":"","sources":["../../../../../src/mcp/primitives/essential/tools/rename-model-field.tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { AnkiConnectClient } from "../../../clients/anki-connect.client";
|
|
2
|
+
export declare class RepositionModelFieldTool {
|
|
3
|
+
private readonly ankiClient;
|
|
4
|
+
private readonly logger;
|
|
5
|
+
constructor(ankiClient: AnkiConnectClient);
|
|
6
|
+
repositionModelField({ modelName, fieldName, index, }: {
|
|
7
|
+
modelName: string;
|
|
8
|
+
fieldName: string;
|
|
9
|
+
index: number;
|
|
10
|
+
}): Promise<{
|
|
11
|
+
[x: string]: unknown;
|
|
12
|
+
content: ({
|
|
13
|
+
type: "text";
|
|
14
|
+
text: string;
|
|
15
|
+
annotations?: {
|
|
16
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
17
|
+
priority?: number | undefined;
|
|
18
|
+
lastModified?: string | undefined;
|
|
19
|
+
} | undefined;
|
|
20
|
+
_meta?: {
|
|
21
|
+
[x: string]: unknown;
|
|
22
|
+
} | undefined;
|
|
23
|
+
} | {
|
|
24
|
+
type: "image";
|
|
25
|
+
data: string;
|
|
26
|
+
mimeType: string;
|
|
27
|
+
annotations?: {
|
|
28
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
29
|
+
priority?: number | undefined;
|
|
30
|
+
lastModified?: string | undefined;
|
|
31
|
+
} | undefined;
|
|
32
|
+
_meta?: {
|
|
33
|
+
[x: string]: unknown;
|
|
34
|
+
} | undefined;
|
|
35
|
+
} | {
|
|
36
|
+
type: "audio";
|
|
37
|
+
data: string;
|
|
38
|
+
mimeType: string;
|
|
39
|
+
annotations?: {
|
|
40
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
41
|
+
priority?: number | undefined;
|
|
42
|
+
lastModified?: string | undefined;
|
|
43
|
+
} | undefined;
|
|
44
|
+
_meta?: {
|
|
45
|
+
[x: string]: unknown;
|
|
46
|
+
} | undefined;
|
|
47
|
+
} | {
|
|
48
|
+
uri: string;
|
|
49
|
+
name: string;
|
|
50
|
+
type: "resource_link";
|
|
51
|
+
description?: string | undefined;
|
|
52
|
+
mimeType?: string | undefined;
|
|
53
|
+
size?: number | undefined;
|
|
54
|
+
annotations?: {
|
|
55
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
56
|
+
priority?: number | undefined;
|
|
57
|
+
lastModified?: string | undefined;
|
|
58
|
+
} | undefined;
|
|
59
|
+
_meta?: {
|
|
60
|
+
[x: string]: unknown;
|
|
61
|
+
} | undefined;
|
|
62
|
+
icons?: {
|
|
63
|
+
src: string;
|
|
64
|
+
mimeType?: string | undefined;
|
|
65
|
+
sizes?: string[] | undefined;
|
|
66
|
+
theme?: "light" | "dark" | undefined;
|
|
67
|
+
}[] | undefined;
|
|
68
|
+
title?: string | undefined;
|
|
69
|
+
} | {
|
|
70
|
+
type: "resource";
|
|
71
|
+
resource: {
|
|
72
|
+
uri: string;
|
|
73
|
+
text: string;
|
|
74
|
+
mimeType?: string | undefined;
|
|
75
|
+
_meta?: {
|
|
76
|
+
[x: string]: unknown;
|
|
77
|
+
} | undefined;
|
|
78
|
+
} | {
|
|
79
|
+
uri: string;
|
|
80
|
+
blob: string;
|
|
81
|
+
mimeType?: string | undefined;
|
|
82
|
+
_meta?: {
|
|
83
|
+
[x: string]: unknown;
|
|
84
|
+
} | undefined;
|
|
85
|
+
};
|
|
86
|
+
annotations?: {
|
|
87
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
88
|
+
priority?: number | undefined;
|
|
89
|
+
lastModified?: string | undefined;
|
|
90
|
+
} | undefined;
|
|
91
|
+
_meta?: {
|
|
92
|
+
[x: string]: unknown;
|
|
93
|
+
} | undefined;
|
|
94
|
+
})[];
|
|
95
|
+
_meta?: {
|
|
96
|
+
[x: string]: unknown;
|
|
97
|
+
progressToken?: string | number | undefined;
|
|
98
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
99
|
+
taskId: string;
|
|
100
|
+
} | undefined;
|
|
101
|
+
} | undefined;
|
|
102
|
+
structuredContent?: {
|
|
103
|
+
[x: string]: unknown;
|
|
104
|
+
} | undefined;
|
|
105
|
+
isError?: boolean | undefined;
|
|
106
|
+
} | {
|
|
107
|
+
success: boolean;
|
|
108
|
+
modelName: string;
|
|
109
|
+
fieldName: string;
|
|
110
|
+
newIndex: number;
|
|
111
|
+
message: string;
|
|
112
|
+
}>;
|
|
113
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var RepositionModelFieldTool_1;
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.RepositionModelFieldTool = void 0;
|
|
14
|
+
const common_1 = require("@nestjs/common");
|
|
15
|
+
const mcp_nest_1 = require("@rekog/mcp-nest");
|
|
16
|
+
const zod_1 = require("zod");
|
|
17
|
+
const anki_connect_client_1 = require("../../../clients/anki-connect.client");
|
|
18
|
+
const anki_utils_1 = require("../../../utils/anki.utils");
|
|
19
|
+
let RepositionModelFieldTool = RepositionModelFieldTool_1 = class RepositionModelFieldTool {
|
|
20
|
+
ankiClient;
|
|
21
|
+
logger = new common_1.Logger(RepositionModelFieldTool_1.name);
|
|
22
|
+
constructor(ankiClient) {
|
|
23
|
+
this.ankiClient = ankiClient;
|
|
24
|
+
}
|
|
25
|
+
async repositionModelField({ modelName, fieldName, index, }) {
|
|
26
|
+
try {
|
|
27
|
+
this.logger.log(`Repositioning field "${fieldName}" to index ${index} in model "${modelName}"`);
|
|
28
|
+
const fields = await this.ankiClient.invoke("modelFieldNames", {
|
|
29
|
+
modelName,
|
|
30
|
+
});
|
|
31
|
+
if (!fields || fields.length === 0) {
|
|
32
|
+
return (0, anki_utils_1.createErrorResponse)(new Error(`Model "${modelName}" has no fields or does not exist`), {
|
|
33
|
+
modelName,
|
|
34
|
+
fieldName,
|
|
35
|
+
index,
|
|
36
|
+
hint: "Model not found. Use modelNames tool to see available models.",
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
if (!fields.includes(fieldName)) {
|
|
40
|
+
return (0, anki_utils_1.createErrorResponse)(new Error(`Field "${fieldName}" does not exist in model "${modelName}"`), {
|
|
41
|
+
modelName,
|
|
42
|
+
fieldName,
|
|
43
|
+
index,
|
|
44
|
+
hint: "Field names are case-sensitive. Use modelFieldNames to see the current field names.",
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
if (index < 0 || index > fields.length - 1) {
|
|
48
|
+
return (0, anki_utils_1.createErrorResponse)(new Error(`Index ${index} is out of range for model "${modelName}". ` +
|
|
49
|
+
`Valid range is 0-${fields.length - 1} (the model has ${fields.length} fields). ` +
|
|
50
|
+
"AnkiConnect would silently clamp the index instead of erroring."), {
|
|
51
|
+
modelName,
|
|
52
|
+
fieldName,
|
|
53
|
+
index,
|
|
54
|
+
hint: "Index out of range. Use modelFieldNames to see how many fields exist.",
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
await this.ankiClient.invoke("modelFieldReposition", {
|
|
58
|
+
modelName,
|
|
59
|
+
fieldName,
|
|
60
|
+
index,
|
|
61
|
+
});
|
|
62
|
+
this.logger.log(`Successfully repositioned field "${fieldName}" to index ${index} in model "${modelName}"`);
|
|
63
|
+
return {
|
|
64
|
+
success: true,
|
|
65
|
+
modelName,
|
|
66
|
+
fieldName,
|
|
67
|
+
newIndex: index,
|
|
68
|
+
message: `Successfully moved field "${fieldName}" to position ${index} in model "${modelName}"`,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
this.logger.error(`Failed to reposition field "${fieldName}" in model "${modelName}"`, error);
|
|
73
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
74
|
+
if (errorMessage.includes("not found") ||
|
|
75
|
+
errorMessage.includes("does not exist")) {
|
|
76
|
+
return (0, anki_utils_1.createErrorResponse)(error, {
|
|
77
|
+
modelName,
|
|
78
|
+
fieldName,
|
|
79
|
+
index,
|
|
80
|
+
hint: "Model or field not found. Use modelNames and modelFieldNames tools to verify names.",
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return (0, anki_utils_1.createErrorResponse)(error, {
|
|
84
|
+
modelName,
|
|
85
|
+
fieldName,
|
|
86
|
+
index,
|
|
87
|
+
hint: "Make sure Anki is running and the model and field names are correct.",
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
exports.RepositionModelFieldTool = RepositionModelFieldTool;
|
|
93
|
+
__decorate([
|
|
94
|
+
(0, mcp_nest_1.Tool)({
|
|
95
|
+
name: "repositionModelField",
|
|
96
|
+
description: "Change the position of a field within an Anki note type (model). " +
|
|
97
|
+
"Fields are ordered 0-based: index 0 is the first field. " +
|
|
98
|
+
"(Which field is the sort field is a separate model setting and is not changed by repositioning.) " +
|
|
99
|
+
"Use modelFieldNames to see the current field order before repositioning.",
|
|
100
|
+
parameters: zod_1.z.object({
|
|
101
|
+
modelName: zod_1.z
|
|
102
|
+
.string()
|
|
103
|
+
.min(1)
|
|
104
|
+
.describe('Name of the note type to modify (e.g., "Basic", "Latin Vocabulary")'),
|
|
105
|
+
fieldName: zod_1.z
|
|
106
|
+
.string()
|
|
107
|
+
.min(1)
|
|
108
|
+
.describe('Name of the field to reposition (e.g., "Grammar")'),
|
|
109
|
+
index: zod_1.z
|
|
110
|
+
.number()
|
|
111
|
+
.int()
|
|
112
|
+
.min(0)
|
|
113
|
+
.describe("New 0-based position for the field (0 = first field)."),
|
|
114
|
+
}),
|
|
115
|
+
outputSchema: zod_1.z.object({
|
|
116
|
+
success: zod_1.z.boolean(),
|
|
117
|
+
modelName: zod_1.z.string(),
|
|
118
|
+
fieldName: zod_1.z.string(),
|
|
119
|
+
newIndex: zod_1.z.number(),
|
|
120
|
+
message: zod_1.z.string(),
|
|
121
|
+
}),
|
|
122
|
+
annotations: {
|
|
123
|
+
title: "Reposition Field in Note Type",
|
|
124
|
+
readOnlyHint: false,
|
|
125
|
+
destructiveHint: false,
|
|
126
|
+
idempotentHint: true,
|
|
127
|
+
},
|
|
128
|
+
}),
|
|
129
|
+
__metadata("design:type", Function),
|
|
130
|
+
__metadata("design:paramtypes", [Object]),
|
|
131
|
+
__metadata("design:returntype", Promise)
|
|
132
|
+
], RepositionModelFieldTool.prototype, "repositionModelField", null);
|
|
133
|
+
exports.RepositionModelFieldTool = RepositionModelFieldTool = RepositionModelFieldTool_1 = __decorate([
|
|
134
|
+
(0, common_1.Injectable)(),
|
|
135
|
+
__metadata("design:paramtypes", [anki_connect_client_1.AnkiConnectClient])
|
|
136
|
+
], RepositionModelFieldTool);
|
|
137
|
+
//# sourceMappingURL=reposition-model-field.tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reposition-model-field.tool.js","sourceRoot":"","sources":["../../../../../src/mcp/primitives/essential/tools/reposition-model-field.tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { AnkiConnectClient } from "../../../clients/anki-connect.client";
|
|
2
|
+
export declare class UpdateModelTemplatesTool {
|
|
3
|
+
private readonly ankiClient;
|
|
4
|
+
private readonly logger;
|
|
5
|
+
constructor(ankiClient: AnkiConnectClient);
|
|
6
|
+
updateModelTemplates({ modelName, templates, }: {
|
|
7
|
+
modelName: string;
|
|
8
|
+
templates: Record<string, {
|
|
9
|
+
Front: string;
|
|
10
|
+
Back: string;
|
|
11
|
+
}>;
|
|
12
|
+
}): Promise<{
|
|
13
|
+
[x: string]: unknown;
|
|
14
|
+
content: ({
|
|
15
|
+
type: "text";
|
|
16
|
+
text: string;
|
|
17
|
+
annotations?: {
|
|
18
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
19
|
+
priority?: number | undefined;
|
|
20
|
+
lastModified?: string | undefined;
|
|
21
|
+
} | undefined;
|
|
22
|
+
_meta?: {
|
|
23
|
+
[x: string]: unknown;
|
|
24
|
+
} | undefined;
|
|
25
|
+
} | {
|
|
26
|
+
type: "image";
|
|
27
|
+
data: string;
|
|
28
|
+
mimeType: string;
|
|
29
|
+
annotations?: {
|
|
30
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
31
|
+
priority?: number | undefined;
|
|
32
|
+
lastModified?: string | undefined;
|
|
33
|
+
} | undefined;
|
|
34
|
+
_meta?: {
|
|
35
|
+
[x: string]: unknown;
|
|
36
|
+
} | undefined;
|
|
37
|
+
} | {
|
|
38
|
+
type: "audio";
|
|
39
|
+
data: string;
|
|
40
|
+
mimeType: string;
|
|
41
|
+
annotations?: {
|
|
42
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
43
|
+
priority?: number | undefined;
|
|
44
|
+
lastModified?: string | undefined;
|
|
45
|
+
} | undefined;
|
|
46
|
+
_meta?: {
|
|
47
|
+
[x: string]: unknown;
|
|
48
|
+
} | undefined;
|
|
49
|
+
} | {
|
|
50
|
+
uri: string;
|
|
51
|
+
name: string;
|
|
52
|
+
type: "resource_link";
|
|
53
|
+
description?: string | undefined;
|
|
54
|
+
mimeType?: string | undefined;
|
|
55
|
+
size?: number | undefined;
|
|
56
|
+
annotations?: {
|
|
57
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
58
|
+
priority?: number | undefined;
|
|
59
|
+
lastModified?: string | undefined;
|
|
60
|
+
} | undefined;
|
|
61
|
+
_meta?: {
|
|
62
|
+
[x: string]: unknown;
|
|
63
|
+
} | undefined;
|
|
64
|
+
icons?: {
|
|
65
|
+
src: string;
|
|
66
|
+
mimeType?: string | undefined;
|
|
67
|
+
sizes?: string[] | undefined;
|
|
68
|
+
theme?: "light" | "dark" | undefined;
|
|
69
|
+
}[] | undefined;
|
|
70
|
+
title?: string | undefined;
|
|
71
|
+
} | {
|
|
72
|
+
type: "resource";
|
|
73
|
+
resource: {
|
|
74
|
+
uri: string;
|
|
75
|
+
text: string;
|
|
76
|
+
mimeType?: string | undefined;
|
|
77
|
+
_meta?: {
|
|
78
|
+
[x: string]: unknown;
|
|
79
|
+
} | undefined;
|
|
80
|
+
} | {
|
|
81
|
+
uri: string;
|
|
82
|
+
blob: string;
|
|
83
|
+
mimeType?: string | undefined;
|
|
84
|
+
_meta?: {
|
|
85
|
+
[x: string]: unknown;
|
|
86
|
+
} | undefined;
|
|
87
|
+
};
|
|
88
|
+
annotations?: {
|
|
89
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
90
|
+
priority?: number | undefined;
|
|
91
|
+
lastModified?: string | undefined;
|
|
92
|
+
} | undefined;
|
|
93
|
+
_meta?: {
|
|
94
|
+
[x: string]: unknown;
|
|
95
|
+
} | undefined;
|
|
96
|
+
})[];
|
|
97
|
+
_meta?: {
|
|
98
|
+
[x: string]: unknown;
|
|
99
|
+
progressToken?: string | number | undefined;
|
|
100
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
101
|
+
taskId: string;
|
|
102
|
+
} | undefined;
|
|
103
|
+
} | undefined;
|
|
104
|
+
structuredContent?: {
|
|
105
|
+
[x: string]: unknown;
|
|
106
|
+
} | undefined;
|
|
107
|
+
isError?: boolean | undefined;
|
|
108
|
+
} | {
|
|
109
|
+
success: boolean;
|
|
110
|
+
modelName: string;
|
|
111
|
+
templateCount: number;
|
|
112
|
+
message: string;
|
|
113
|
+
hint: string;
|
|
114
|
+
}>;
|
|
115
|
+
}
|