@cryptoapis-io/mcp-aml 0.1.0 → 0.2.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 +24 -2
- package/dist/cli.js +5 -12
- package/dist/cli.js.map +1 -1
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +12 -32
- package/dist/server.js.map +1 -1
- package/package.json +2 -6
- package/server.json +5 -3
package/README.md
CHANGED
|
@@ -32,7 +32,7 @@ npx @cryptoapis-io/mcp-aml --api-key YOUR_API_KEY
|
|
|
32
32
|
export CRYPTOAPIS_API_KEY=YOUR_API_KEY
|
|
33
33
|
npx @cryptoapis-io/mcp-aml
|
|
34
34
|
|
|
35
|
-
# HTTP transport
|
|
35
|
+
# HTTP transport (listens on 127.0.0.1; see "Exposing the server beyond localhost")
|
|
36
36
|
npx @cryptoapis-io/mcp-aml --transport http --port 3000 --api-key YOUR_API_KEY
|
|
37
37
|
```
|
|
38
38
|
|
|
@@ -87,6 +87,8 @@ npx @modelcontextprotocol/inspector npx @cryptoapis-io/mcp-aml --api-key YOUR_AP
|
|
|
87
87
|
2. In your n8n workflow, add an **AI Agent** node
|
|
88
88
|
3. Under **Tools**, add an **MCP Client Tool** and set the URL to `http://localhost:3000/mcp`
|
|
89
89
|
|
|
90
|
+
> **n8n in Docker:** `localhost` inside the container is not your machine. Start the server with `--host 0.0.0.0` and `MCP_AUTH_TOKEN` set (see [Exposing the server beyond localhost](#exposing-the-server-beyond-localhost)), use `http://host.docker.internal:3000/mcp` as the URL, and add an `Authorization: Bearer <token>` header to the MCP Client Tool credential.
|
|
91
|
+
|
|
90
92
|
> All servers default to port 3000. Use `--port` to assign different ports when running multiple servers.
|
|
91
93
|
|
|
92
94
|
## Available Tools
|
|
@@ -108,7 +110,9 @@ npx @modelcontextprotocol/inspector npx @cryptoapis-io/mcp-aml --api-key YOUR_AP
|
|
|
108
110
|
|----------|-------------|---------|
|
|
109
111
|
| `--api-key` | Crypto APIs API key | `CRYPTOAPIS_API_KEY` env var |
|
|
110
112
|
| `--transport` | Transport type: `stdio` or `http` | `stdio` |
|
|
111
|
-
| `--host` | HTTP host
|
|
113
|
+
| `--host` | HTTP host (use `0.0.0.0` to accept remote connections — requires an auth token with `--api-key`) | `127.0.0.1` |
|
|
114
|
+
| `--auth-token` | Bearer token callers must send (`Authorization: Bearer <token>`); prefer the `MCP_AUTH_TOKEN` env var | `MCP_AUTH_TOKEN` env var |
|
|
115
|
+
| `--allowed-hosts` | Comma-separated `Host` header allowlist for non-loopback binds | — |
|
|
112
116
|
| `--port` | HTTP port | `3000` |
|
|
113
117
|
| `--path` | HTTP path | `/mcp` |
|
|
114
118
|
| `--stateless` | Enable stateless HTTP mode | `false` |
|
|
@@ -126,6 +130,24 @@ npx @cryptoapis-io/mcp-aml --transport http --port 3000
|
|
|
126
130
|
# Clients send x-api-key header with each request
|
|
127
131
|
```
|
|
128
132
|
|
|
133
|
+
### Exposing the server beyond localhost
|
|
134
|
+
|
|
135
|
+
HTTP mode listens on `127.0.0.1` by default, so only processes on the same machine can reach it.
|
|
136
|
+
To accept connections from other machines or containers, bind explicitly and protect the port:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
# Startup-key mode: callers must present the token (the server refuses to start without one)
|
|
140
|
+
export MCP_AUTH_TOKEN=$(openssl rand -hex 32)
|
|
141
|
+
npx @cryptoapis-io/mcp-aml --transport http --host 0.0.0.0 --port 3000 --api-key YOUR_API_KEY \
|
|
142
|
+
--allowed-hosts mcp.internal.example
|
|
143
|
+
# Clients send: Authorization: Bearer $MCP_AUTH_TOKEN
|
|
144
|
+
|
|
145
|
+
# Per-request key mode: no startup key, every request must carry the caller's own x-api-key
|
|
146
|
+
npx @cryptoapis-io/mcp-aml --transport http --host 0.0.0.0 --port 3000
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
`--allowed-hosts` restricts the `Host` header (DNS rebinding protection) when not bound to loopback. Prefer `MCP_AUTH_TOKEN` over `--auth-token`: command-line arguments are visible in the process list.
|
|
150
|
+
|
|
129
151
|
> Stdio transport always requires an API key at startup.
|
|
130
152
|
|
|
131
153
|
## Important: API Key Required
|
package/dist/cli.js
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
|
+
import { parseHttpCliOptions } from "@cryptoapis-io/mcp-shared";
|
|
1
2
|
import { startAmlServer } from "./server.js";
|
|
2
3
|
function getArg(name) {
|
|
3
4
|
const idx = process.argv.indexOf(`--${name}`);
|
|
4
|
-
|
|
5
|
-
return undefined;
|
|
6
|
-
return process.argv[idx + 1];
|
|
7
|
-
}
|
|
8
|
-
function hasFlag(name) {
|
|
9
|
-
return process.argv.includes(`--${name}`);
|
|
5
|
+
return idx === -1 ? undefined : process.argv[idx + 1];
|
|
10
6
|
}
|
|
11
7
|
async function main() {
|
|
12
8
|
const transport = (getArg("transport") ?? "stdio");
|
|
@@ -15,14 +11,11 @@ async function main() {
|
|
|
15
11
|
await startAmlServer({ transport: "stdio", apiKey });
|
|
16
12
|
return;
|
|
17
13
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const path = getArg("path") ?? "/mcp";
|
|
21
|
-
const stateless = hasFlag("stateless");
|
|
22
|
-
await startAmlServer({ transport: "http", host, port, path, stateless, apiKey });
|
|
14
|
+
// --host (default 127.0.0.1), --port, --path, --stateless, --auth-token / MCP_AUTH_TOKEN, --allowed-hosts
|
|
15
|
+
await startAmlServer({ transport: "http", apiKey, ...parseHttpCliOptions() });
|
|
23
16
|
}
|
|
24
17
|
main().catch((err) => {
|
|
25
|
-
console.error(err);
|
|
18
|
+
console.error(err instanceof Error ? err.message : err);
|
|
26
19
|
process.exit(1);
|
|
27
20
|
});
|
|
28
21
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,SAAS,MAAM,CAAC,IAAY;IACxB,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;IAC9C,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,SAAS,MAAM,CAAC,IAAY;IACxB,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;IAC9C,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED,KAAK,UAAU,IAAI;IACf,MAAM,SAAS,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,OAAO,CAAqB,CAAC;IACvE,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;IACjC,IAAI,SAAS,KAAK,OAAO,EAAE,CAAC;QACxB,MAAM,cAAc,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACrD,OAAO;IACX,CAAC;IACD,0GAA0G;IAC1G,MAAM,cAAc,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,mBAAmB,EAAE,EAAE,CAAC,CAAC;AAClF,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACjB,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC,CAAC,CAAC"}
|
package/dist/server.d.ts
CHANGED
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAuDA,MAAM,MAAM,YAAY,GAClB;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACvC;IACI,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B,CAAC;AAER,wBAAsB,cAAc,CAAC,IAAI,EAAE,YAAY,iBAuBtD"}
|
package/dist/server.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import { randomUUID } from "node:crypto";
|
|
2
|
-
import express from "express";
|
|
3
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
2
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
-
import {
|
|
6
|
-
import { CryptoApisHttpClient, formatCreditsForDescription, loadSharedConfig, McpLogger, runWithApiKey, } from "@cryptoapis-io/mcp-shared";
|
|
3
|
+
import { CryptoApisHttpClient, formatCreditsForDescription, loadSharedConfig, McpLogger, startHttpServer } from "@cryptoapis-io/mcp-shared";
|
|
7
4
|
import { tools } from "./tools/index.js";
|
|
8
5
|
import { registerResources } from "./resources/index.js";
|
|
9
6
|
import { registerPrompts } from "./prompts/index.js";
|
|
@@ -52,40 +49,23 @@ export async function startAmlServer(opts) {
|
|
|
52
49
|
const isHttp = opts.transport === "http";
|
|
53
50
|
const cfg = loadSharedConfig({ apiKey: opts.apiKey, allowMissingApiKey: isHttp });
|
|
54
51
|
const client = new CryptoApisHttpClient(cfg);
|
|
55
|
-
const { server, logger } = buildServer(client);
|
|
56
52
|
if (opts.transport === "stdio") {
|
|
53
|
+
const { server, logger } = buildServer(client);
|
|
57
54
|
const transport = new StdioServerTransport();
|
|
58
55
|
await server.connect(transport);
|
|
59
56
|
logger.logInfo("cryptoapis-aml MCP running (stdio)");
|
|
60
57
|
return;
|
|
61
58
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
app.all(path, (req, res) => {
|
|
73
|
-
const headerApiKey = req.headers["x-api-key"];
|
|
74
|
-
if (headerApiKey && !cfg.apiKey) {
|
|
75
|
-
return runWithApiKey(headerApiKey, () => transport.handleRequest(req, res, req.body));
|
|
76
|
-
}
|
|
77
|
-
return transport.handleRequest(req, res, req.body);
|
|
78
|
-
});
|
|
79
|
-
app.get("/health", (_req, res) => res.status(200).json({ ok: true }));
|
|
80
|
-
app.listen(port, host, () => {
|
|
81
|
-
logger.logInfo(`cryptoapis-aml MCP running (http) at http://${host}:${port}${path}`);
|
|
82
|
-
logger.logInfo(`mode: ${stateless ? "stateless" : "stateful"}`);
|
|
83
|
-
if (cfg.apiKey) {
|
|
84
|
-
logger.logInfo("API key: provided at startup — x-api-key request headers will be ignored");
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
87
|
-
logger.logInfo("API key: not provided — each request must include x-api-key header");
|
|
88
|
-
}
|
|
59
|
+
await startHttpServer({
|
|
60
|
+
name: CRYPTOAPIS_SERVER_INFO.name,
|
|
61
|
+
createServer: () => buildServer(client).server,
|
|
62
|
+
startupApiKey: cfg.apiKey,
|
|
63
|
+
host: opts.host,
|
|
64
|
+
port: opts.port,
|
|
65
|
+
path: opts.path,
|
|
66
|
+
stateless: opts.stateless,
|
|
67
|
+
authToken: opts.authToken,
|
|
68
|
+
allowedHosts: opts.allowedHosts,
|
|
89
69
|
});
|
|
90
70
|
}
|
|
91
71
|
//# sourceMappingURL=server.js.map
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cryptoapis-io/mcp-aml",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "MCP server for AML address verification and transaction screening via Crypto APIs",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Crypto APIs, Inc.",
|
|
@@ -33,12 +33,8 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
36
|
-
"express": "^4.22.1",
|
|
37
36
|
"zod": "^3.25.0",
|
|
38
|
-
"@cryptoapis-io/mcp-shared": "0.
|
|
39
|
-
},
|
|
40
|
-
"devDependencies": {
|
|
41
|
-
"@types/express": "^5.0.6"
|
|
37
|
+
"@cryptoapis-io/mcp-shared": "0.4.0"
|
|
42
38
|
},
|
|
43
39
|
"scripts": {
|
|
44
40
|
"dev": "tsx watch src/cli.ts",
|
package/server.json
CHANGED
|
@@ -6,13 +6,15 @@
|
|
|
6
6
|
"url": "https://github.com/CryptoAPIs-io/cryptoapis-mcp-aml",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.2.0",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"identifier": "@cryptoapis-io/mcp-aml",
|
|
14
|
-
"version": "0.
|
|
15
|
-
"transport": {
|
|
14
|
+
"version": "0.2.0",
|
|
15
|
+
"transport": {
|
|
16
|
+
"type": "stdio"
|
|
17
|
+
},
|
|
16
18
|
"environmentVariables": [
|
|
17
19
|
{
|
|
18
20
|
"description": "Crypto APIs API key",
|