@ankimcp/anki-mcp-server 0.13.0-tunnel.1 → 0.13.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 +53 -5
- package/bin/ankimcp.js +17 -10
- package/dist/anki-config.service.d.ts +11 -0
- package/dist/anki-config.service.js +46 -0
- package/dist/anki-config.service.js.map +1 -0
- package/dist/app.module.d.ts +2 -4
- package/dist/app.module.js +11 -98
- package/dist/app.module.js.map +1 -1
- package/dist/bootstrap.d.ts +1 -6
- package/dist/bootstrap.js +2 -7
- package/dist/bootstrap.js.map +1 -1
- package/dist/cli.d.ts +1 -4
- package/dist/cli.js +18 -23
- package/dist/cli.js.map +1 -1
- package/dist/http/guards/origin-validation.guard.d.ts +0 -1
- package/dist/http/guards/origin-validation.guard.js +3 -5
- package/dist/http/guards/origin-validation.guard.js.map +1 -1
- package/dist/main-http.js +10 -19
- package/dist/main-http.js.map +1 -1
- package/dist/main-stdio.js +31 -7
- package/dist/main-stdio.js.map +1 -1
- package/dist/mcp/clients/anki-connect.client.d.ts +5 -0
- package/dist/mcp/clients/anki-connect.client.js +35 -1
- package/dist/mcp/clients/anki-connect.client.js.map +1 -1
- package/dist/mcp/config/anki-config.interface.d.ts +1 -0
- package/dist/mcp/config/anki-config.interface.js.map +1 -1
- package/dist/mcp/primitives/essential/index.d.ts +4 -9
- package/dist/mcp/primitives/essential/index.js +7 -21
- package/dist/mcp/primitives/essential/index.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/add-note.tool.js +22 -9
- package/dist/mcp/primitives/essential/tools/add-note.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/deckActions/actions/changeDeck.action.d.ts +12 -0
- package/dist/mcp/primitives/essential/tools/deckActions/actions/changeDeck.action.js +24 -0
- package/dist/mcp/primitives/essential/tools/deckActions/actions/changeDeck.action.js.map +1 -0
- package/dist/mcp/primitives/essential/tools/deckActions/actions/createDeck.action.d.ts +15 -0
- package/dist/mcp/primitives/essential/tools/deckActions/actions/createDeck.action.js +44 -0
- package/dist/mcp/primitives/essential/tools/deckActions/actions/createDeck.action.js.map +1 -0
- package/dist/mcp/primitives/essential/tools/{deck-stats/deck-stats.types.d.ts → deckActions/actions/deckStats.action.d.ts} +5 -2
- package/dist/mcp/primitives/essential/tools/deckActions/actions/deckStats.action.js +78 -0
- package/dist/mcp/primitives/essential/tools/deckActions/actions/deckStats.action.js.map +1 -0
- package/dist/mcp/primitives/essential/tools/deckActions/actions/listDecks.action.d.ts +18 -0
- package/dist/mcp/primitives/essential/tools/deckActions/actions/listDecks.action.js +63 -0
- package/dist/mcp/primitives/essential/tools/deckActions/actions/listDecks.action.js.map +1 -0
- package/dist/mcp/primitives/essential/tools/{deck-stats/deck-stats.tool.d.ts → deckActions/deckActions.tool.d.ts} +8 -4
- package/dist/mcp/primitives/essential/tools/deckActions/deckActions.tool.js +138 -0
- package/dist/mcp/primitives/essential/tools/deckActions/deckActions.tool.js.map +1 -0
- package/dist/mcp/primitives/essential/tools/deckActions/index.d.ts +5 -0
- package/dist/mcp/primitives/essential/tools/deckActions/index.js +6 -0
- package/dist/mcp/primitives/essential/tools/deckActions/index.js.map +1 -0
- package/dist/mcp/primitives/gui/index.d.ts +0 -1
- package/dist/mcp/primitives/gui/index.js +1 -8
- package/dist/mcp/primitives/gui/index.js.map +1 -1
- package/dist/services/ngrok.service.d.ts +0 -1
- package/dist/services/ngrok.service.js +3 -5
- package/dist/services/ngrok.service.js.map +1 -1
- package/dist/test-fixtures/mock-data.d.ts +0 -8
- package/dist/test-fixtures/mock-data.js +0 -8
- package/dist/test-fixtures/mock-data.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +24 -27
- package/dist/app-config.service.d.ts +0 -21
- package/dist/app-config.service.js +0 -76
- package/dist/app-config.service.js.map +0 -1
- package/dist/cli/__tests__/cli-output.manual.d.ts +0 -2
- package/dist/cli/__tests__/cli-output.manual.js +0 -13
- package/dist/cli/__tests__/cli-output.manual.js.map +0 -1
- package/dist/cli/cli-output.d.ts +0 -20
- package/dist/cli/cli-output.js +0 -69
- package/dist/cli/cli-output.js.map +0 -1
- package/dist/cli/index.d.ts +0 -1
- package/dist/cli/index.js +0 -18
- package/dist/cli/index.js.map +0 -1
- package/dist/config/config.factory.d.ts +0 -12
- package/dist/config/config.factory.js +0 -29
- package/dist/config/config.factory.js.map +0 -1
- package/dist/config/config.schema.d.ts +0 -32
- package/dist/config/config.schema.js +0 -48
- package/dist/config/config.schema.js.map +0 -1
- package/dist/config/index.d.ts +0 -3
- package/dist/config/index.js +0 -11
- package/dist/config/index.js.map +0 -1
- package/dist/main-tunnel.d.ts +0 -1
- package/dist/main-tunnel.js +0 -26
- package/dist/main-tunnel.js.map +0 -1
- package/dist/mcp/primitives/essential/tools/create-deck.tool.d.ts +0 -105
- package/dist/mcp/primitives/essential/tools/create-deck.tool.js +0 -121
- package/dist/mcp/primitives/essential/tools/create-deck.tool.js.map +0 -1
- package/dist/mcp/primitives/essential/tools/deck-stats/deck-stats.tool.js +0 -165
- package/dist/mcp/primitives/essential/tools/deck-stats/deck-stats.tool.js.map +0 -1
- package/dist/mcp/primitives/essential/tools/deck-stats/deck-stats.types.js +0 -3
- package/dist/mcp/primitives/essential/tools/deck-stats/deck-stats.types.js.map +0 -1
- package/dist/mcp/primitives/essential/tools/deck-stats/index.d.ts +0 -2
- package/dist/mcp/primitives/essential/tools/deck-stats/index.js +0 -6
- package/dist/mcp/primitives/essential/tools/deck-stats/index.js.map +0 -1
- package/dist/mcp/primitives/essential/tools/list-decks.tool.d.ts +0 -105
- package/dist/mcp/primitives/essential/tools/list-decks.tool.js +0 -117
- package/dist/mcp/primitives/essential/tools/list-decks.tool.js.map +0 -1
- package/dist/tunnel/commands/index.d.ts +0 -3
- package/dist/tunnel/commands/index.js +0 -10
- package/dist/tunnel/commands/index.js.map +0 -1
- package/dist/tunnel/commands/login.command.d.ts +0 -1
- package/dist/tunnel/commands/login.command.js +0 -108
- package/dist/tunnel/commands/login.command.js.map +0 -1
- package/dist/tunnel/commands/logout.command.d.ts +0 -1
- package/dist/tunnel/commands/logout.command.js +0 -26
- package/dist/tunnel/commands/logout.command.js.map +0 -1
- package/dist/tunnel/commands/tunnel.command.d.ts +0 -1
- package/dist/tunnel/commands/tunnel.command.js +0 -183
- package/dist/tunnel/commands/tunnel.command.js.map +0 -1
- package/dist/tunnel/credentials.service.d.ts +0 -23
- package/dist/tunnel/credentials.service.js +0 -152
- package/dist/tunnel/credentials.service.js.map +0 -1
- package/dist/tunnel/device-flow.service.d.ts +0 -46
- package/dist/tunnel/device-flow.service.js +0 -237
- package/dist/tunnel/device-flow.service.js.map +0 -1
- package/dist/tunnel/in-memory.transport.d.ts +0 -14
- package/dist/tunnel/in-memory.transport.js +0 -63
- package/dist/tunnel/in-memory.transport.js.map +0 -1
- package/dist/tunnel/index.d.ts +0 -6
- package/dist/tunnel/index.js +0 -31
- package/dist/tunnel/index.js.map +0 -1
- package/dist/tunnel/tunnel-mcp.service.d.ts +0 -15
- package/dist/tunnel/tunnel-mcp.service.js +0 -100
- package/dist/tunnel/tunnel-mcp.service.js.map +0 -1
- package/dist/tunnel/tunnel.client.d.ts +0 -60
- package/dist/tunnel/tunnel.client.js +0 -381
- package/dist/tunnel/tunnel.client.js.map +0 -1
- package/dist/tunnel/tunnel.protocol.d.ts +0 -67
- package/dist/tunnel/tunnel.protocol.js +0 -25
- package/dist/tunnel/tunnel.protocol.js.map +0 -1
- package/dist/version.d.ts +0 -2
- package/dist/version.js +0 -21
- package/dist/version.js.map +0 -1
package/README.md
CHANGED
|
@@ -41,8 +41,11 @@ For comprehensive guides, real-world examples, and step-by-step tutorials on usi
|
|
|
41
41
|
- `rate_card` - Rate card performance
|
|
42
42
|
|
|
43
43
|
### Deck Management
|
|
44
|
-
- `
|
|
45
|
-
- `
|
|
44
|
+
- `deckActions` - Unified deck operations:
|
|
45
|
+
- `listDecks` - List all decks with optional statistics
|
|
46
|
+
- `createDeck` - Create new decks (max 2 levels: "Parent::Child")
|
|
47
|
+
- `deckStats` - Get comprehensive deck statistics
|
|
48
|
+
- `changeDeck` - Move cards to a different deck
|
|
46
49
|
|
|
47
50
|
### Note Management
|
|
48
51
|
- `addNote` - Create new notes
|
|
@@ -216,6 +219,7 @@ Options:
|
|
|
216
219
|
-h, --host <host> Host to bind to (HTTP mode, default: 127.0.0.1)
|
|
217
220
|
-a, --anki-connect <url> AnkiConnect URL (default: http://localhost:8765)
|
|
218
221
|
--ngrok Start ngrok tunnel (requires global ngrok installation)
|
|
222
|
+
--read-only Run in read-only mode (blocks all write operations)
|
|
219
223
|
--help Show help message
|
|
220
224
|
|
|
221
225
|
Usage with npx (no installation needed):
|
|
@@ -223,6 +227,7 @@ Usage with npx (no installation needed):
|
|
|
223
227
|
npx @ankimcp/anki-mcp-server --port 8080 # Custom port
|
|
224
228
|
npx @ankimcp/anki-mcp-server --stdio # STDIO mode
|
|
225
229
|
npx @ankimcp/anki-mcp-server --ngrok # HTTP mode with ngrok tunnel
|
|
230
|
+
npx @ankimcp/anki-mcp-server --read-only # Read-only mode
|
|
226
231
|
|
|
227
232
|
Usage with global installation:
|
|
228
233
|
npm install -g @ankimcp/anki-mcp-server # Install once
|
|
@@ -230,6 +235,46 @@ Usage with global installation:
|
|
|
230
235
|
ankimcp --port 8080 # Custom port
|
|
231
236
|
ankimcp --stdio # STDIO mode
|
|
232
237
|
ankimcp --ngrok # HTTP mode with ngrok tunnel
|
|
238
|
+
ankimcp --read-only # Read-only mode
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
**Read-Only Mode:**
|
|
242
|
+
|
|
243
|
+
The `--read-only` flag prevents any modifications to your Anki collection. When enabled:
|
|
244
|
+
- All read operations work normally (browsing decks, viewing cards, searching notes)
|
|
245
|
+
- Review operations are allowed (sync, answerCards, suspend/unsuspend)
|
|
246
|
+
- Content modifications are blocked (addNote, deleteNotes, createDeck, updateNoteFields, etc.)
|
|
247
|
+
- Useful for safely exploring Anki data without risk of accidental changes
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
# HTTP mode with read-only
|
|
251
|
+
ankimcp --read-only
|
|
252
|
+
|
|
253
|
+
# STDIO mode with read-only
|
|
254
|
+
ankimcp --stdio --read-only
|
|
255
|
+
|
|
256
|
+
# Can combine with other flags
|
|
257
|
+
ankimcp --ngrok --read-only
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
You can also enable read-only mode via environment variable:
|
|
261
|
+
```bash
|
|
262
|
+
READ_ONLY=true ankimcp
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Or in MCP client configuration:
|
|
266
|
+
```json
|
|
267
|
+
{
|
|
268
|
+
"mcpServers": {
|
|
269
|
+
"anki-mcp": {
|
|
270
|
+
"command": "npx",
|
|
271
|
+
"args": ["-y", "@ankimcp/anki-mcp-server", "--stdio", "--read-only"],
|
|
272
|
+
"env": {
|
|
273
|
+
"ANKI_CONNECT_URL": "http://localhost:8765"
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
233
278
|
```
|
|
234
279
|
|
|
235
280
|
**Using with ngrok:**
|
|
@@ -321,6 +366,7 @@ For more details, see the [official MCP documentation](https://modelcontextproto
|
|
|
321
366
|
| `ANKI_CONNECT_API_VERSION` | API version | `6` |
|
|
322
367
|
| `ANKI_CONNECT_API_KEY` | API key if configured in AnkiConnect | - |
|
|
323
368
|
| `ANKI_CONNECT_TIMEOUT` | Request timeout in ms | `5000` |
|
|
369
|
+
| `READ_ONLY` | Enable read-only mode (`true` or `1`) | `false` |
|
|
324
370
|
|
|
325
371
|
## Usage Examples
|
|
326
372
|
|
|
@@ -398,14 +444,16 @@ If you see an error like:
|
|
|
398
444
|
Error [ERR_REQUIRE_ESM]: require() of ES Module not supported
|
|
399
445
|
```
|
|
400
446
|
|
|
401
|
-
This means your Node.js version is
|
|
447
|
+
This means your Node.js version is not supported. The server requires **Node.js 20.19.0+ or 22.12.0+**.
|
|
448
|
+
|
|
449
|
+
> **Note:** Node.js 21.x is not supported. The `require(esm)` feature was added in Node 22 and backported to Node 20.17+, but was never available in Node 21. See [#16](https://github.com/ankimcp/anki-mcp-server/issues/16) for details.
|
|
402
450
|
|
|
403
451
|
**Check your version:**
|
|
404
452
|
```bash
|
|
405
453
|
node --version
|
|
406
454
|
```
|
|
407
455
|
|
|
408
|
-
**Solution:** Update Node.js to version 20.19.0 or
|
|
456
|
+
**Solution:** Update Node.js to version 20.19.0+ or 22.12.0+. You can download it from [nodejs.org](https://nodejs.org/) or use a version manager like [nvm](https://github.com/nvm-sh/nvm).
|
|
409
457
|
|
|
410
458
|
## Development
|
|
411
459
|
|
|
@@ -798,4 +846,4 @@ For complete license terms, see the [LICENSE](LICENSE) file.
|
|
|
798
846
|
|
|
799
847
|
- **Model Context Protocol (MCP)** is an open standard by Anthropic. The MCP logo is from the official [MCP documentation repository](https://github.com/modelcontextprotocol/docs) and is used under the MIT License. For more information about MCP, visit [https://modelcontextprotocol.io](https://modelcontextprotocol.io).
|
|
800
848
|
|
|
801
|
-
- This is an independent project that bridges Anki and MCP technologies. All trademarks, service marks, trade names, product names, and logos are the property of their respective owners.
|
|
849
|
+
- This is an independent project that bridges Anki and MCP technologies. All trademarks, service marks, trade names, product names, and logos are the property of their respective owners.
|
package/bin/ankimcp.js
CHANGED
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
//
|
|
3
|
+
// Runtime Node.js version check (require(esm) needs Node 20.19+ or 22.12+)
|
|
4
|
+
const [major, minor] = process.versions.node.split('.').map(Number);
|
|
5
|
+
if (
|
|
6
|
+
(major < 20) ||
|
|
7
|
+
(major === 21) ||
|
|
8
|
+
(major === 20 && minor < 19) ||
|
|
9
|
+
(major === 22 && minor < 12)
|
|
10
|
+
) {
|
|
11
|
+
console.error(
|
|
12
|
+
`Error: Node.js ${process.versions.node} is not supported.\n` +
|
|
13
|
+
'This package requires Node.js 20.19.0+ or 22.12.0+ (Node 21.x is not supported).\n' +
|
|
14
|
+
'Download: https://nodejs.org/'
|
|
15
|
+
);
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Check if --stdio flag is present
|
|
4
20
|
const isStdioMode = process.argv.includes('--stdio');
|
|
5
|
-
const isTunnelMode = process.argv.some(arg =>
|
|
6
|
-
arg === '--tunnel' ||
|
|
7
|
-
arg.startsWith('--tunnel=') ||
|
|
8
|
-
arg === '--login' ||
|
|
9
|
-
arg === '--logout'
|
|
10
|
-
);
|
|
11
21
|
|
|
12
22
|
if (isStdioMode) {
|
|
13
23
|
// STDIO mode - for MCP clients like Cursor, Cline, Zed, etc.
|
|
14
24
|
require('../dist/main-stdio.js');
|
|
15
|
-
} else if (isTunnelMode) {
|
|
16
|
-
// Tunnel mode - for remote MCP access via tunnel service
|
|
17
|
-
require('../dist/main-tunnel.js');
|
|
18
25
|
} else {
|
|
19
26
|
// HTTP mode (default) - for web-based AI assistants
|
|
20
27
|
require('../dist/main-http.js');
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ConfigService } from "@nestjs/config";
|
|
2
|
+
import { IAnkiConfig } from "./mcp/config/anki-config.interface";
|
|
3
|
+
export declare class AnkiConfigService implements IAnkiConfig {
|
|
4
|
+
private configService;
|
|
5
|
+
constructor(configService: ConfigService);
|
|
6
|
+
get ankiConnectUrl(): string;
|
|
7
|
+
get ankiConnectApiVersion(): number;
|
|
8
|
+
get ankiConnectApiKey(): string | undefined;
|
|
9
|
+
get ankiConnectTimeout(): number;
|
|
10
|
+
get readOnly(): boolean;
|
|
11
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.AnkiConfigService = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const config_1 = require("@nestjs/config");
|
|
15
|
+
const mcpb_workarounds_1 = require("./mcp/utils/mcpb-workarounds");
|
|
16
|
+
let AnkiConfigService = class AnkiConfigService {
|
|
17
|
+
configService;
|
|
18
|
+
constructor(configService) {
|
|
19
|
+
this.configService = configService;
|
|
20
|
+
}
|
|
21
|
+
get ankiConnectUrl() {
|
|
22
|
+
return this.configService.get("ANKI_CONNECT_URL", "http://localhost:8765");
|
|
23
|
+
}
|
|
24
|
+
get ankiConnectApiVersion() {
|
|
25
|
+
const version = this.configService.get("ANKI_CONNECT_API_VERSION", "6");
|
|
26
|
+
return parseInt(version, 10);
|
|
27
|
+
}
|
|
28
|
+
get ankiConnectApiKey() {
|
|
29
|
+
const apiKey = this.configService.get("ANKI_CONNECT_API_KEY");
|
|
30
|
+
return (0, mcpb_workarounds_1.sanitizeMcpbConfigValue)(apiKey);
|
|
31
|
+
}
|
|
32
|
+
get ankiConnectTimeout() {
|
|
33
|
+
const timeout = this.configService.get("ANKI_CONNECT_TIMEOUT", "5000");
|
|
34
|
+
return parseInt(timeout, 10);
|
|
35
|
+
}
|
|
36
|
+
get readOnly() {
|
|
37
|
+
const readOnly = this.configService.get("READ_ONLY", "false");
|
|
38
|
+
return readOnly === "true" || readOnly === "1";
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
exports.AnkiConfigService = AnkiConfigService;
|
|
42
|
+
exports.AnkiConfigService = AnkiConfigService = __decorate([
|
|
43
|
+
(0, common_1.Injectable)(),
|
|
44
|
+
__metadata("design:paramtypes", [config_1.ConfigService])
|
|
45
|
+
], AnkiConfigService);
|
|
46
|
+
//# sourceMappingURL=anki-config.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anki-config.service.js","sourceRoot":"","sources":["../src/anki-config.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,2CAA+C;AAE/C,mEAAuE;AAMhE,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;IACR;IAApB,YAAoB,aAA4B;QAA5B,kBAAa,GAAb,aAAa,CAAe;IAAG,CAAC;IAEpD,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,CAC3B,kBAAkB,EAClB,uBAAuB,CACxB,CAAC;IACJ,CAAC;IAED,IAAI,qBAAqB;QACvB,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CACpC,0BAA0B,EAC1B,GAAG,CACJ,CAAC;QACF,OAAO,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,iBAAiB;QACnB,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAS,sBAAsB,CAAC,CAAC;QACtE,OAAO,IAAA,0CAAuB,EAAC,MAAM,CAAC,CAAC;IACzC,CAAC;IAED,IAAI,kBAAkB;QACpB,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CACpC,sBAAsB,EACtB,MAAM,CACP,CAAC;QACF,OAAO,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,QAAQ;QACV,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAS,WAAW,EAAE,OAAO,CAAC,CAAC;QACtE,OAAO,QAAQ,KAAK,MAAM,IAAI,QAAQ,KAAK,GAAG,CAAC;IACjD,CAAC;CACF,CAAA;AAnCY,8CAAiB;4BAAjB,iBAAiB;IAD7B,IAAA,mBAAU,GAAE;qCAEwB,sBAAa;GADrC,iBAAiB,CAmC7B"}
|
package/dist/app.module.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { DynamicModule } from "@nestjs/common";
|
|
2
|
-
import { ConfigInput, CliOverrides } from "@/config";
|
|
3
2
|
export declare class AppModule {
|
|
4
|
-
static forStdio(
|
|
5
|
-
static forHttp(
|
|
6
|
-
static forTunnel(cliOverrides?: CliOverrides): DynamicModule;
|
|
3
|
+
static forStdio(): DynamicModule;
|
|
4
|
+
static forHttp(): DynamicModule;
|
|
7
5
|
}
|
package/dist/app.module.js
CHANGED
|
@@ -13,19 +13,16 @@ const config_1 = require("@nestjs/config");
|
|
|
13
13
|
const mcp_nest_1 = require("@rekog/mcp-nest");
|
|
14
14
|
const essential_1 = require("./mcp/primitives/essential");
|
|
15
15
|
const gui_1 = require("./mcp/primitives/gui");
|
|
16
|
-
const
|
|
17
|
-
const config_2 = require("./config");
|
|
18
|
-
const tunnel_mcp_service_1 = require("./tunnel/tunnel-mcp.service");
|
|
16
|
+
const anki_config_service_1 = require("./anki-config.service");
|
|
19
17
|
let AppModule = AppModule_1 = class AppModule {
|
|
20
|
-
static forStdio(
|
|
21
|
-
const validatedConfig = config_2.configSchema.parse((0, config_2.transformEnvToConfig)(configInput));
|
|
18
|
+
static forStdio() {
|
|
22
19
|
return {
|
|
23
20
|
module: AppModule_1,
|
|
24
21
|
imports: [
|
|
25
22
|
config_1.ConfigModule.forRoot({
|
|
26
23
|
isGlobal: true,
|
|
27
24
|
cache: true,
|
|
28
|
-
|
|
25
|
+
envFilePath: [".env.local", ".env"],
|
|
29
26
|
}),
|
|
30
27
|
mcp_nest_1.McpModule.forRoot({
|
|
31
28
|
name: process.env.MCP_SERVER_NAME || "anki-mcp-server",
|
|
@@ -35,45 +32,27 @@ let AppModule = AppModule_1 = class AppModule {
|
|
|
35
32
|
essential_1.McpPrimitivesAnkiEssentialModule.forRoot({
|
|
36
33
|
ankiConfigProvider: {
|
|
37
34
|
provide: essential_1.ANKI_CONFIG,
|
|
38
|
-
useClass:
|
|
39
|
-
},
|
|
40
|
-
appConfigProvider: {
|
|
41
|
-
provide: config_2.APP_CONFIG,
|
|
42
|
-
useValue: validatedConfig,
|
|
35
|
+
useClass: anki_config_service_1.AnkiConfigService,
|
|
43
36
|
},
|
|
44
37
|
}),
|
|
45
38
|
gui_1.McpPrimitivesAnkiGuiModule.forRoot({
|
|
46
39
|
ankiConfigProvider: {
|
|
47
40
|
provide: essential_1.ANKI_CONFIG,
|
|
48
|
-
useClass:
|
|
49
|
-
},
|
|
50
|
-
appConfigProvider: {
|
|
51
|
-
provide: config_2.APP_CONFIG,
|
|
52
|
-
useValue: validatedConfig,
|
|
41
|
+
useClass: anki_config_service_1.AnkiConfigService,
|
|
53
42
|
},
|
|
54
43
|
}),
|
|
55
44
|
],
|
|
56
|
-
providers: [
|
|
57
|
-
{
|
|
58
|
-
provide: config_2.APP_CONFIG,
|
|
59
|
-
useValue: validatedConfig,
|
|
60
|
-
},
|
|
61
|
-
app_config_service_1.AppConfigService,
|
|
62
|
-
...essential_1.ESSENTIAL_MCP_TOOLS,
|
|
63
|
-
...gui_1.GUI_MCP_TOOLS,
|
|
64
|
-
],
|
|
65
|
-
exports: [config_2.APP_CONFIG, app_config_service_1.AppConfigService],
|
|
45
|
+
providers: [anki_config_service_1.AnkiConfigService, ...essential_1.ESSENTIAL_MCP_TOOLS, ...gui_1.GUI_MCP_TOOLS],
|
|
66
46
|
};
|
|
67
47
|
}
|
|
68
|
-
static forHttp(
|
|
69
|
-
const validatedConfig = config_2.configSchema.parse((0, config_2.transformEnvToConfig)(configInput));
|
|
48
|
+
static forHttp() {
|
|
70
49
|
return {
|
|
71
50
|
module: AppModule_1,
|
|
72
51
|
imports: [
|
|
73
52
|
config_1.ConfigModule.forRoot({
|
|
74
53
|
isGlobal: true,
|
|
75
54
|
cache: true,
|
|
76
|
-
|
|
55
|
+
envFilePath: [".env.local", ".env"],
|
|
77
56
|
}),
|
|
78
57
|
mcp_nest_1.McpModule.forRoot({
|
|
79
58
|
name: process.env.MCP_SERVER_NAME || "anki-mcp-server",
|
|
@@ -84,83 +63,17 @@ let AppModule = AppModule_1 = class AppModule {
|
|
|
84
63
|
essential_1.McpPrimitivesAnkiEssentialModule.forRoot({
|
|
85
64
|
ankiConfigProvider: {
|
|
86
65
|
provide: essential_1.ANKI_CONFIG,
|
|
87
|
-
useClass:
|
|
88
|
-
},
|
|
89
|
-
appConfigProvider: {
|
|
90
|
-
provide: config_2.APP_CONFIG,
|
|
91
|
-
useValue: validatedConfig,
|
|
66
|
+
useClass: anki_config_service_1.AnkiConfigService,
|
|
92
67
|
},
|
|
93
68
|
}),
|
|
94
69
|
gui_1.McpPrimitivesAnkiGuiModule.forRoot({
|
|
95
70
|
ankiConfigProvider: {
|
|
96
71
|
provide: essential_1.ANKI_CONFIG,
|
|
97
|
-
useClass:
|
|
98
|
-
},
|
|
99
|
-
appConfigProvider: {
|
|
100
|
-
provide: config_2.APP_CONFIG,
|
|
101
|
-
useValue: validatedConfig,
|
|
72
|
+
useClass: anki_config_service_1.AnkiConfigService,
|
|
102
73
|
},
|
|
103
74
|
}),
|
|
104
75
|
],
|
|
105
|
-
providers: [
|
|
106
|
-
{
|
|
107
|
-
provide: config_2.APP_CONFIG,
|
|
108
|
-
useValue: validatedConfig,
|
|
109
|
-
},
|
|
110
|
-
app_config_service_1.AppConfigService,
|
|
111
|
-
...essential_1.ESSENTIAL_MCP_TOOLS,
|
|
112
|
-
...gui_1.GUI_MCP_TOOLS,
|
|
113
|
-
],
|
|
114
|
-
exports: [config_2.APP_CONFIG, app_config_service_1.AppConfigService],
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
static forTunnel(cliOverrides) {
|
|
118
|
-
const validatedConfig = (0, config_2.loadValidatedConfig)(cliOverrides);
|
|
119
|
-
return {
|
|
120
|
-
module: AppModule_1,
|
|
121
|
-
imports: [
|
|
122
|
-
config_1.ConfigModule.forRoot({
|
|
123
|
-
isGlobal: true,
|
|
124
|
-
cache: true,
|
|
125
|
-
load: [() => validatedConfig],
|
|
126
|
-
}),
|
|
127
|
-
mcp_nest_1.McpModule.forRoot({
|
|
128
|
-
name: process.env.MCP_SERVER_NAME || "anki-mcp-server",
|
|
129
|
-
version: process.env.MCP_SERVER_VERSION || "1.0.0",
|
|
130
|
-
transport: [],
|
|
131
|
-
}),
|
|
132
|
-
essential_1.McpPrimitivesAnkiEssentialModule.forRoot({
|
|
133
|
-
ankiConfigProvider: {
|
|
134
|
-
provide: essential_1.ANKI_CONFIG,
|
|
135
|
-
useClass: app_config_service_1.AppConfigService,
|
|
136
|
-
},
|
|
137
|
-
appConfigProvider: {
|
|
138
|
-
provide: config_2.APP_CONFIG,
|
|
139
|
-
useValue: validatedConfig,
|
|
140
|
-
},
|
|
141
|
-
}),
|
|
142
|
-
gui_1.McpPrimitivesAnkiGuiModule.forRoot({
|
|
143
|
-
ankiConfigProvider: {
|
|
144
|
-
provide: essential_1.ANKI_CONFIG,
|
|
145
|
-
useClass: app_config_service_1.AppConfigService,
|
|
146
|
-
},
|
|
147
|
-
appConfigProvider: {
|
|
148
|
-
provide: config_2.APP_CONFIG,
|
|
149
|
-
useValue: validatedConfig,
|
|
150
|
-
},
|
|
151
|
-
}),
|
|
152
|
-
],
|
|
153
|
-
providers: [
|
|
154
|
-
{
|
|
155
|
-
provide: config_2.APP_CONFIG,
|
|
156
|
-
useValue: validatedConfig,
|
|
157
|
-
},
|
|
158
|
-
app_config_service_1.AppConfigService,
|
|
159
|
-
tunnel_mcp_service_1.TunnelMcpService,
|
|
160
|
-
...essential_1.ESSENTIAL_MCP_TOOLS,
|
|
161
|
-
...gui_1.GUI_MCP_TOOLS,
|
|
162
|
-
],
|
|
163
|
-
exports: [config_2.APP_CONFIG, app_config_service_1.AppConfigService, tunnel_mcp_service_1.TunnelMcpService],
|
|
76
|
+
providers: [anki_config_service_1.AnkiConfigService, ...essential_1.ESSENTIAL_MCP_TOOLS, ...gui_1.GUI_MCP_TOOLS],
|
|
164
77
|
};
|
|
165
78
|
}
|
|
166
79
|
};
|
package/dist/app.module.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.module.js","sourceRoot":"","sources":["../src/app.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAuD;AACvD,2CAA8C;AAC9C,8CAA8D;AAC9D,0DAIoC;AACpC,8CAG8B;AAC9B
|
|
1
|
+
{"version":3,"file":"app.module.js","sourceRoot":"","sources":["../src/app.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAuD;AACvD,2CAA8C;AAC9C,8CAA8D;AAC9D,0DAIoC;AACpC,8CAG8B;AAC9B,+DAA0D;AAGnD,IAAM,SAAS,iBAAf,MAAM,SAAS;IAIpB,MAAM,CAAC,QAAQ;QACb,OAAO;YACL,MAAM,EAAE,WAAS;YACjB,OAAO,EAAE;gBAEP,qBAAY,CAAC,OAAO,CAAC;oBACnB,QAAQ,EAAE,IAAI;oBACd,KAAK,EAAE,IAAI;oBACX,WAAW,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC;iBACpC,CAAC;gBAGF,oBAAS,CAAC,OAAO,CAAC;oBAChB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,iBAAiB;oBACtD,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,OAAO;oBAClD,SAAS,EAAE,2BAAgB,CAAC,KAAK;iBAClC,CAAC;gBAGF,4CAAgC,CAAC,OAAO,CAAC;oBACvC,kBAAkB,EAAE;wBAClB,OAAO,EAAE,uBAAW;wBACpB,QAAQ,EAAE,uCAAiB;qBAC5B;iBACF,CAAC;gBAGF,gCAA0B,CAAC,OAAO,CAAC;oBACjC,kBAAkB,EAAE;wBAClB,OAAO,EAAE,uBAAW;wBACpB,QAAQ,EAAE,uCAAiB;qBAC5B;iBACF,CAAC;aACH;YAED,SAAS,EAAE,CAAC,uCAAiB,EAAE,GAAG,+BAAmB,EAAE,GAAG,mBAAa,CAAC;SACzE,CAAC;IACJ,CAAC;IAKD,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,MAAM,EAAE,WAAS;YACjB,OAAO,EAAE;gBAEP,qBAAY,CAAC,OAAO,CAAC;oBACnB,QAAQ,EAAE,IAAI;oBACd,KAAK,EAAE,IAAI;oBACX,WAAW,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC;iBACpC,CAAC;gBAGF,oBAAS,CAAC,OAAO,CAAC;oBAChB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,iBAAiB;oBACtD,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,OAAO;oBAClD,SAAS,EAAE,2BAAgB,CAAC,eAAe;oBAC3C,WAAW,EAAE,GAAG;iBACjB,CAAC;gBAGF,4CAAgC,CAAC,OAAO,CAAC;oBACvC,kBAAkB,EAAE;wBAClB,OAAO,EAAE,uBAAW;wBACpB,QAAQ,EAAE,uCAAiB;qBAC5B;iBACF,CAAC;gBAGF,gCAA0B,CAAC,OAAO,CAAC;oBACjC,kBAAkB,EAAE;wBAClB,OAAO,EAAE,uBAAW;wBACpB,QAAQ,EAAE,uCAAiB;qBAC5B;iBACF,CAAC;aACH;YAED,SAAS,EAAE,CAAC,uCAAiB,EAAE,GAAG,+BAAmB,EAAE,GAAG,mBAAa,CAAC;SACzE,CAAC;IACJ,CAAC;CACF,CAAA;AArFY,8BAAS;oBAAT,SAAS;IADrB,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,SAAS,CAqFrB"}
|
package/dist/bootstrap.d.ts
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
1
|
import { LoggerService } from "@nestjs/common";
|
|
2
|
-
export declare
|
|
3
|
-
readonly STDOUT: 1;
|
|
4
|
-
readonly STDERR: 2;
|
|
5
|
-
};
|
|
6
|
-
export type LogDestination = (typeof LOG_DESTINATION)[keyof typeof LOG_DESTINATION];
|
|
7
|
-
export declare function createPinoLogger(destination: LogDestination, logLevel?: string): import("pino").Logger<never, boolean>;
|
|
2
|
+
export declare function createPinoLogger(destination: 1 | 2): import("pino").Logger<never, boolean>;
|
|
8
3
|
export declare function createLoggerService(pinoLogger: any): LoggerService;
|
package/dist/bootstrap.js
CHANGED
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.LOG_DESTINATION = void 0;
|
|
4
3
|
exports.createPinoLogger = createPinoLogger;
|
|
5
4
|
exports.createLoggerService = createLoggerService;
|
|
6
5
|
const pino_1 = require("pino");
|
|
7
|
-
|
|
8
|
-
STDOUT: 1,
|
|
9
|
-
STDERR: 2,
|
|
10
|
-
};
|
|
11
|
-
function createPinoLogger(destination, logLevel = "info") {
|
|
6
|
+
function createPinoLogger(destination) {
|
|
12
7
|
return (0, pino_1.pino)({
|
|
13
|
-
level:
|
|
8
|
+
level: process.env.LOG_LEVEL || "info",
|
|
14
9
|
transport: {
|
|
15
10
|
target: "pino-pretty",
|
|
16
11
|
options: {
|
package/dist/bootstrap.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":";;AASA,4CAaC;AAQD,kDAkBC;AA/CD,+BAA4B;AAQ5B,SAAgB,gBAAgB,CAAC,WAAkB;IACjD,OAAO,IAAA,WAAI,EAAC;QACV,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,MAAM;QACtC,SAAS,EAAE;YACT,MAAM,EAAE,aAAa;YACrB,OAAO,EAAE;gBACP,WAAW;gBACX,QAAQ,EAAE,IAAI;gBACd,aAAa,EAAE,YAAY;gBAC3B,MAAM,EAAE,cAAc;aACvB;SACF;KACF,CAAC,CAAC;AACL,CAAC;AAQD,SAAgB,mBAAmB,CAAC,UAAe;IACjD,OAAO;QACL,GAAG,EAAE,CAAC,OAAY,EAAE,OAAgB,EAAE,EAAE;YACtC,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;QACxC,CAAC;QACD,KAAK,EAAE,CAAC,OAAY,EAAE,KAAc,EAAE,OAAgB,EAAE,EAAE;YACxD,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;QAChD,CAAC;QACD,IAAI,EAAE,CAAC,OAAY,EAAE,OAAgB,EAAE,EAAE;YACvC,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;QACxC,CAAC;QACD,KAAK,EAAE,CAAC,OAAY,EAAE,OAAgB,EAAE,EAAE;YACxC,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;QACzC,CAAC;QACD,OAAO,EAAE,CAAC,OAAY,EAAE,OAAgB,EAAE,EAAE;YAC1C,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;QACzC,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/cli.d.ts
CHANGED
|
@@ -3,10 +3,7 @@ export interface CliOptions {
|
|
|
3
3
|
host: string;
|
|
4
4
|
ankiConnect: string;
|
|
5
5
|
ngrok: boolean;
|
|
6
|
-
|
|
7
|
-
logout: boolean;
|
|
8
|
-
tunnel: string | boolean;
|
|
9
|
-
debug: boolean;
|
|
6
|
+
readOnly: boolean;
|
|
10
7
|
}
|
|
11
8
|
export declare function checkForUpdates(): void;
|
|
12
9
|
export declare function parseCliArgs(): CliOptions;
|
package/dist/cli.js
CHANGED
|
@@ -10,8 +10,6 @@ const commander_1 = require("commander");
|
|
|
10
10
|
const fs_1 = require("fs");
|
|
11
11
|
const path_1 = require("path");
|
|
12
12
|
const update_notifier_1 = __importDefault(require("update-notifier"));
|
|
13
|
-
const cli_output_1 = require("./cli/cli-output");
|
|
14
|
-
const version_1 = require("./version");
|
|
15
13
|
function getPackageJson() {
|
|
16
14
|
try {
|
|
17
15
|
return JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname, "../package.json"), "utf-8"));
|
|
@@ -20,6 +18,9 @@ function getPackageJson() {
|
|
|
20
18
|
return { version: "0.0.0", name: "ankimcp" };
|
|
21
19
|
}
|
|
22
20
|
}
|
|
21
|
+
function getVersion() {
|
|
22
|
+
return getPackageJson().version;
|
|
23
|
+
}
|
|
23
24
|
function checkForUpdates() {
|
|
24
25
|
(0, update_notifier_1.default)({ pkg: getPackageJson() }).notify();
|
|
25
26
|
}
|
|
@@ -28,16 +29,13 @@ function parseCliArgs() {
|
|
|
28
29
|
program
|
|
29
30
|
.name("ankimcp")
|
|
30
31
|
.description("AnkiMCP Server - Model Context Protocol server for Anki")
|
|
31
|
-
.version(
|
|
32
|
+
.version(getVersion())
|
|
32
33
|
.option("--stdio", "Run in STDIO mode (for MCP clients like Cursor, Cline, Zed)")
|
|
33
34
|
.option("-p, --port <number>", "Port to listen on (HTTP mode)", "3000")
|
|
34
35
|
.option("-h, --host <address>", "Host to bind to (HTTP mode)", "127.0.0.1")
|
|
35
36
|
.option("-a, --anki-connect <url>", "AnkiConnect URL", "http://localhost:8765")
|
|
36
37
|
.option("--ngrok", "Start ngrok tunnel (requires global ngrok installation)")
|
|
37
|
-
.option("--
|
|
38
|
-
.option("--logout", "Clear tunnel credentials")
|
|
39
|
-
.option("--tunnel [url]", "Connect to tunnel server (default: ws://localhost:3004/tunnel)")
|
|
40
|
-
.option("-d, --debug", "Enable debug logging (shows stack traces)")
|
|
38
|
+
.option("--read-only", "Run in read-only mode (blocks all write operations)")
|
|
41
39
|
.addHelpText("after", `
|
|
42
40
|
Transport Modes:
|
|
43
41
|
HTTP Mode (default): For web-based AI assistants (ChatGPT, Claude.ai)
|
|
@@ -67,18 +65,15 @@ Examples - STDIO Mode:
|
|
|
67
65
|
}
|
|
68
66
|
}
|
|
69
67
|
|
|
68
|
+
Examples - Read-Only Mode:
|
|
69
|
+
$ ankimcp --read-only # HTTP mode, read-only
|
|
70
|
+
$ ankimcp --stdio --read-only # STDIO mode, read-only
|
|
71
|
+
|
|
70
72
|
Ngrok Setup (one-time):
|
|
71
73
|
1. Install: npm install -g ngrok
|
|
72
74
|
2. Get auth token from: https://dashboard.ngrok.com/get-started/your-authtoken
|
|
73
75
|
3. Setup: ngrok config add-authtoken <your-token>
|
|
74
76
|
4. Run: ankimcp --ngrok
|
|
75
|
-
|
|
76
|
-
Tunnel Mode:
|
|
77
|
-
$ ankimcp --login # Login to default tunnel service
|
|
78
|
-
$ ankimcp --login wss://custom.server.com/tunnel # Login to custom server
|
|
79
|
-
$ ankimcp --logout # Clear saved credentials
|
|
80
|
-
$ ankimcp --tunnel # Connect to localhost:3004
|
|
81
|
-
$ ankimcp --tunnel wss://tunnel.ankimcp.ai/tunnel # Production tunnel
|
|
82
77
|
`);
|
|
83
78
|
program.parse();
|
|
84
79
|
const options = program.opts();
|
|
@@ -87,30 +82,30 @@ Tunnel Mode:
|
|
|
87
82
|
host: options.host,
|
|
88
83
|
ankiConnect: options.ankiConnect,
|
|
89
84
|
ngrok: options.ngrok || false,
|
|
90
|
-
|
|
91
|
-
logout: options.logout || false,
|
|
92
|
-
tunnel: options.tunnel ?? false,
|
|
93
|
-
debug: options.debug || false,
|
|
85
|
+
readOnly: options.readOnly || false,
|
|
94
86
|
};
|
|
95
87
|
}
|
|
96
88
|
function displayStartupBanner(options, ngrokUrl) {
|
|
97
|
-
const version =
|
|
89
|
+
const version = getVersion();
|
|
98
90
|
const title = `AnkiMCP HTTP Server v${version}`;
|
|
99
91
|
const padding = Math.floor((64 - title.length) / 2);
|
|
100
92
|
const paddedTitle = " ".repeat(padding) + title + " ".repeat(64 - padding - title.length);
|
|
101
|
-
|
|
93
|
+
const readOnlyWarning = options.readOnly
|
|
94
|
+
? "\n\n** READ-ONLY MODE ENABLED **\nContent modifications (addNote, deleteNotes, createDeck, etc.) are blocked.\nReview operations (sync, answerCards, suspend) remain available."
|
|
95
|
+
: "";
|
|
96
|
+
console.log(`
|
|
102
97
|
╔════════════════════════════════════════════════════════════════╗
|
|
103
98
|
║${paddedTitle}║
|
|
104
|
-
|
|
99
|
+
╚════════════════════════════════════════════════════════════════╝${readOnlyWarning}
|
|
105
100
|
|
|
106
101
|
🚀 Server running on: http://${options.host}:${options.port}
|
|
107
|
-
🔌 AnkiConnect URL: ${options.ankiConnect}${ngrokUrl ? `\n🌐 Ngrok tunnel: ${ngrokUrl}` : ""}
|
|
102
|
+
🔌 AnkiConnect URL: ${options.ankiConnect}${ngrokUrl ? `\n🌐 Ngrok tunnel: ${ngrokUrl}` : ""}${options.readOnly ? "\n🔒 Mode: Read-only" : ""}
|
|
108
103
|
|
|
109
104
|
Configuration:
|
|
110
105
|
• Port: ${options.port} (override: --port 8080)
|
|
111
106
|
• Host: ${options.host} (override: --host 0.0.0.0)
|
|
112
107
|
• AnkiConnect: ${options.ankiConnect}
|
|
113
|
-
(override: --anki-connect http://localhost:8765)${ngrokUrl ? `\n • Ngrok tunnel: ${ngrokUrl}\n • Ngrok dashboard: http://localhost:4040` : ""}
|
|
108
|
+
(override: --anki-connect http://localhost:8765)${options.readOnly ? "\n • Read-only: Yes (write operations blocked)" : ""}${ngrokUrl ? `\n • Ngrok tunnel: ${ngrokUrl}\n • Ngrok dashboard: http://localhost:4040` : ""}
|
|
114
109
|
${!ngrokUrl
|
|
115
110
|
? `
|
|
116
111
|
Usage with ngrok:
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,12 +8,10 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
8
8
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
9
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
10
|
};
|
|
11
|
-
var OriginValidationGuard_1;
|
|
12
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
12
|
exports.OriginValidationGuard = void 0;
|
|
14
13
|
const common_1 = require("@nestjs/common");
|
|
15
|
-
let OriginValidationGuard =
|
|
16
|
-
logger = new common_1.Logger(OriginValidationGuard_1.name);
|
|
14
|
+
let OriginValidationGuard = class OriginValidationGuard {
|
|
17
15
|
allowedOrigins;
|
|
18
16
|
constructor() {
|
|
19
17
|
const defaultOrigins = "http://localhost:*,http://127.0.0.1:*,https://localhost:*,https://127.0.0.1:*";
|
|
@@ -28,7 +26,7 @@ let OriginValidationGuard = OriginValidationGuard_1 = class OriginValidationGuar
|
|
|
28
26
|
}
|
|
29
27
|
const isAllowed = this.allowedOrigins.some((allowedOrigin) => this.matchesPattern(origin, allowedOrigin));
|
|
30
28
|
if (!isAllowed) {
|
|
31
|
-
|
|
29
|
+
console.warn(`[OriginValidationGuard] Rejected request from unauthorized origin: ${origin}`);
|
|
32
30
|
}
|
|
33
31
|
return isAllowed;
|
|
34
32
|
}
|
|
@@ -47,7 +45,7 @@ let OriginValidationGuard = OriginValidationGuard_1 = class OriginValidationGuar
|
|
|
47
45
|
}
|
|
48
46
|
};
|
|
49
47
|
exports.OriginValidationGuard = OriginValidationGuard;
|
|
50
|
-
exports.OriginValidationGuard = OriginValidationGuard =
|
|
48
|
+
exports.OriginValidationGuard = OriginValidationGuard = __decorate([
|
|
51
49
|
(0, common_1.Injectable)(),
|
|
52
50
|
__metadata("design:paramtypes", [])
|
|
53
51
|
], OriginValidationGuard);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"origin-validation.guard.js","sourceRoot":"","sources":["../../../src/http/guards/origin-validation.guard.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"origin-validation.guard.js","sourceRoot":"","sources":["../../../src/http/guards/origin-validation.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA2E;AAiBpE,IAAM,qBAAqB,GAA3B,MAAM,qBAAqB;IACf,cAAc,CAAW;IAE1C;QACE,MAAM,cAAc,GAClB,+EAA+E,CAAC;QAClF,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,cAAc,CAAC;QACjE,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,WAAW,CAAC,OAAyB;QACnC,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAW,CAAC;QAC7D,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;QAGjE,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC;QACd,CAAC;QAGD,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,EAAE,CAC3D,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,aAAa,CAAC,CAC3C,CAAC;QAEF,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CACV,sEAAsE,MAAM,EAAE,CAC/E,CAAC;QACJ,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IASO,cAAc,CAAC,MAAc,EAAE,OAAe;QAEpD,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QAGD,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,MAAM,YAAY,GAAG,OAAO;iBACzB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;iBACrB,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YACxB,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,IAAI,YAAY,GAAG,CAAC,CAAC;YAC9C,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;CACF,CAAA;AAzDY,sDAAqB;gCAArB,qBAAqB;IADjC,IAAA,mBAAU,GAAE;;GACA,qBAAqB,CAyDjC"}
|