canli-mcp@0.22.0
CAUTIONPublisher claims: "A full finance desk for your AI agent: 355 tools in one free server with no API key, reading SEC filings, earnings guidance, insider trades, options, rates and macro data from the source, plus quant analytics and backtest validation. The agent sees 5 tools and searches the rest, so it stays light on context." Observed in sandbox: no network, touches nothing outside the project, writes no memory.
Coverage
Server started and answered tools/list.- Tested
- MCP initialize and tools/list · every tool description, for hidden instructions · every file read, file written and host contacted by what ran
- Not tested
- what the tools do when called with real credentials
Before you give it your token
- It will ask for
CANLI_SERVE_TOKENConfiguration, not credentials: ALPACA_PAPER_KEY_ID, CANLI_AS_OF, CANLI_ASK, CANLI_FRONT, CANLI_HOME, CANLI_LAB_NOTES, CANLI_NULL_ZOO, CANLI_OFFLINE, CANLI_PACKS, CANLI_PLUGINS, CANLI_POLICY, CANLI_QUOTE_SECONDS, CANLI_UPSTREAMS- Where it talks to
- canlicapital.com (its own)
- What the honeypot saw
- no credential files read · no network
- What we could not test
- what the tools do when called with real credentials
Connect it with a scoped credential, under the guard. It asks for CANLI_SERVE_TOKEN and talks to canlicapital.com. Give the credential to the guard, not the server: the value never enters the server's environment and only travels to the host you bind.
Never paste a credential into a chat, a ticket or a report, including ours. How the guard holds it.
Is [email protected] safe to install?
KillerSkills ran it in the KillerSkills honeypot sandbox (2 scenarios) on 2026-11-12 and scored it 76/100 (Caution). It is not known to be malicious, but it has behaviour or code a security policy should decide on before install. Notable findings: Hidden zero-width characters detected. Summary: no network, touches nothing outside the project, writes no memory.
Behavior trace
Honeypot run · 25 s · 2 scenariosStatic findings
…rn { checked: false, why: "The Lab is not built on this machine. Build it once (npx -y canli-mcp lab build) and every dated strategy answer is set against about a mil…Fix: Pin versions and sources; vendor anything fetched at install time.…{String(bad[0].error).slice(0, 140)}). On the hosted server, run the local one: npx -y canli-mcp.`); const factors = prices.slice(0, FACTORS.length), own = prices.s…Fix: Pin versions and sources; vendor anything fetched at install time.…19 by a key published at https://canlicapital.com/.well-known/canli-receipt-keys.json.","","id?: string, receipt?: object, include_receipt?: boolean"],["backtest_strategy","validation","validation","Backtest a rule over a parameter grid, v…Fix: Remove the call, or declare the host in frontmatter and explain in the README what is sent and why.if (readOnly) throw new Error("The sentinel watches from your own machine. Run it locally: npx -y canli-mcp");Fix: Pin versions and sources; vendor anything fetched at install time.limits: RED_TEAM_LIMITS + (ctx.hosted ? " Hosted: only this request is counted; run the loop locally with npx -y canli-mcp." : ""),Fix: Pin versions and sources; vendor anything fetched at install time.? { measure: "years the loop never saw", passed: null, why: "The holdout vault keeps a session; run locally (npx -y canli-mcp)." }Fix: Pin versions and sources; vendor anything fetched at install time.const lines = text.replace(/^/, "").split(/\r?\n/).filter((l) => l.trim());Fix: Keep SKILL.md to visible, descriptive text. Remove comments and encoded text that address the agent.…adOnly) throw new Error("The signed log is on your own machine. Run it locally: npx -y canli-mcp"); return signedTrialCount(args, { dir: join(canliHome(), "audit"), k…Fix: Pin versions and sources; vendor anything fetched at install time.…l explains arguments in full). To save tokens: pass long data as {"$file": "path.csv", "column": "close"} instead of pasting numbers; put several calls in one run_tool, using {"$result": i, "path": "field"} to feed one call's output into t…Fix: Remove the call, or declare the host in frontmatter and explain in the README what is sent and why.scope === "request" ? "Hosted: only this request is counted; run the search as one batch, or locally with npx canli-mcp." : "",Fix: Pin versions and sources; vendor anything fetched at install time.…d. Every free source the server reads can feed the lake this way. Needs DuckDB: npx -y canli-mcp lake setup. Local server only.", keywords: "data lake save store …Fix: Pin versions and sources; vendor anything fetched at install time.…er allowed to change things)` : ""}.` + " Any argument can be {\"$file\": \"path.csv\", \"column\": \"close\"} (or \"columns\": [...] / \"all\") instead of pasted numbers. {\"$result\": i, \"path\": \"close\"} passes batch call i's output …Fix: Remove the call, or declare the host in frontmatter and explain in the README what is sent and why.…ount: equity, cash, buying power, positions, open orders, the market clock, the kill switch and the local order log's verified head.","positions holdings balance cas…Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.….json"))) throw new Error(`The Lab is not built on this machine. Build it once: npx -y canli-mcp lab build (downloads Kenneth French's daily files and runs about a mi…Fix: Pin versions and sources; vendor anything fetched at install time.…(dir) { if (!exists(join(dir, "manifest.json"))) return { built: false, how: "npx -y canli-mcp lab build (downloads Kenneth French's daily files from his data libra…Fix: Pin versions and sources; vendor anything fetched at install time.const local = (name) => { allowed(name); if (readOnly) throw new Error(`${name} keeps files on your own machine. Run it locally: npx -y canli-mcp`); };Fix: Pin versions and sources; vendor anything fetched at install time.…new Error(readOnly ? "The Null Zoo is kept on your own machine. Run it locally: npx -y canli-mcp" : "The Null Zoo is off on this server (CANLI_NULL_ZOO=off)."); retur…Fix: Pin versions and sources; vendor anything fetched at install time.… session, and the hosted server keeps nothing between requests. Run it locally: npx -y canli-mcp"); return vault; }; tools.restatement_causes = (args) => { allowed(…Fix: Pin versions and sources; vendor anything fetched at install time.Cost to the agent
Tokens estimated at four characters each. The tool list is re-read by the agent on every turn, so it is the number to compare between servers that do the same job: ranked across the index.
Known vulnerabilities
Vulnerability advisories (OSV) cover npm and PyPI packages; this registry has no advisory database.
What would make this Verified
4 points to 80 · weights: behavior 45%, static 25%, prompt 15%, publisher 15%- Unclaimed publisher≈ +8 on the totalClaim arhancanli: a verified publisher gets +50 on publisher trust. It is free and usually instant with GitHub sign-in.
- Touches files outside the project≈ +7 on the totalKeep reads and writes inside the working directory, or declare the exact paths in `filesystem:` and explain why in the README.
- Hidden zero-width characters detected≈ +4 on the totalKeep SKILL.md to visible, descriptive text. Remove comments and encoded text that address the agent.
- npx invocation of non-well-known package≈ +2 on the totalPin versions and sources; vendor anything fetched at install time.
- File type combined with upload action≈ +2 on the totalRemove the call, or declare the host in frontmatter and explain in the README what is sent and why.
- Process kill command≈ +2 on the totalBuild commands from fixed arguments; do not interpolate untrusted strings into a shell.