@datorama/mci-mcp-sdk
v0.1.1
Published
Local stdio MCP server for Marketing Cloud Intelligence (MCI). Owns the OAuth2 token lifecycle and pass-through-proxies MCP JSON-RPC to an MCI dato /api/mcp endpoint.
Downloads
284
Readme
@datorama/mci-mcp-sdk
A tiny, local stdio MCP server for Marketing Cloud Intelligence (MCI). You launch it via npx
from your MCP client's config; it owns the entire OAuth2 token lifecycle (mint from your
service-account key, cache, refresh on demand) and pass-through-proxies MCP JSON-RPC to an MCI
dato /api/mcp endpoint.
There is nothing to paste and nothing that expires on you: no more copying a bearer header that dies every hour. You give the SDK a key file and a URL; it does the rest.
What it is (and isn't)
- It is a pure relay + a token manager. Every MCP message —
initialize,tools/list,tools/call, and anything added later — is forwarded verbatim to your MCI endpoint with a freshAuthorization: Bearer …injected. It defines no tools of its own; the tool list you see comes from the server. New server-side tools appear automatically with no SDK update. - It isn't where any business logic lives. All validation, data access, and authorization happen server-side; the SDK is treated as untrusted and the server re-validates every call.
Setup
Add this to your MCP client's server config (e.g. Claude Code / Cursor mcpServers):
{
"mcpServers": {
"mci-mcp": {
"command": "npx",
"args": ["-y", "@datorama/mci-mcp-sdk"],
"env": {
"PRIVATE_KEY_PATH": "<path to the step-1 service-account JSON>",
"HOST": "https://<your dato env>/api/mcp"
}
}
}
}PRIVATE_KEY_PATH— path to the service-account artifact JSON you were issued (it containsserviceAccountId,discoveryEndpoint, andprivateKey). The SDK derives the IdP/token URL from this file; you don't configure an IdP URL. The key is read in-memory only — never logged, never put on the command line, never written to disk.HOST— your MCI dato MCP endpoint (…/api/mcp).
Reload your client. The mci_* tools appear with no pasted header. As you keep working, the SDK
transparently re-mints the bearer when it nears expiry — you never notice.
Optional env
| Var | Default | Purpose |
|---|---|---|
| MCI_INSECURE_TLS | off | Allow a self-signed cert. Honored only for dev hosts (localhost, 127.0.0.1, *.dev.datorama.io); ignored for production. |
| MCI_TIMEOUT_MS | 30000 | Per-request timeout to HOST. |
| DATO_MCI_STATE_DIR | OS state dir | Override the token-cache directory (tests/power users). |
Local development
npm install
npm run build # tsc → dist/
npm test # vitest (unit + proxy relay)
# Smoke-test the built binary against a live endpoint:
PRIVATE_KEY_PATH=/path/to/sa.json HOST=https://127.0.0.1:8081/api/mcp MCI_INSECURE_TLS=1 \
node scripts/stdio-smoke.mjs mci_list_workspacesLocal gotcha: use
127.0.0.1, notlocalhost, for a locally-run dato — Node resolveslocalhostto IPv6::1, but a local Jetty typically binds IPv4 only (ECONNREFUSED ::1).
Security
- Private key: in-memory only. Never logged, never on argv, never persisted.
- Token cache: only the short-lived bearer, written atomically at mode
0600in a0700state dir. stdoutis reserved for the MCP protocol stream; all diagnostics go tostderr.- Tokens are masked and IdP error bodies redacted in any human-readable output.
- The server is the security boundary — it enforces per-user authorization on the service-account identity regardless of what the client (or a tampered SDK) sends.
