equisense-research-mcp 0.1.0 → 0.1.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 +82 -43
- package/index.js +18 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# equisense-research MCP server
|
|
2
2
|
|
|
3
|
-
Thin Node.js wrapper that exposes the EquiSense AI equity-research
|
|
3
|
+
Thin Node.js MCP wrapper that exposes the EquiSense AI equity-research engine as a single tool:
|
|
4
4
|
|
|
5
5
|
| Tool | Endpoint | What it does |
|
|
6
6
|
|---|---|---|
|
|
@@ -8,35 +8,25 @@ Thin Node.js wrapper that exposes the EquiSense AI equity-research endpoint as a
|
|
|
8
8
|
|
|
9
9
|
Same brain the WhatsApp chat uses, just over MCP instead of WhatsApp.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
The Java app (Spring Boot 3.1) is too old for the Spring AI MCP server starter (needs 3.4+). All research logic, LLM routing, and feature metering stay server-side in Java; this wrapper just speaks MCP.
|
|
14
|
-
|
|
15
|
-
## Setup
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
cd mcp-server/equisense-research
|
|
19
|
-
npm install
|
|
20
|
-
```
|
|
11
|
+
Published on npm: [`equisense-research-mcp`](https://www.npmjs.com/package/equisense-research-mcp)
|
|
21
12
|
|
|
22
|
-
|
|
13
|
+
---
|
|
23
14
|
|
|
24
|
-
|
|
25
|
-
|---|---|---|
|
|
26
|
-
| `EQUISENSE_BASE_URL` | `http://localhost:8080` | Spring Boot app root |
|
|
27
|
-
| `EQUISENSE_TIMEOUT_MS` | `90000` | Per-request timeout (research queries can take 30–90s) |
|
|
28
|
-
| `EQUISENSE_MCP_TOKEN` | **required** | HMAC bearer token. Treat like a password. |
|
|
15
|
+
## Quick start
|
|
29
16
|
|
|
30
|
-
###
|
|
17
|
+
### 1. Mint a token
|
|
31
18
|
|
|
32
|
-
The
|
|
19
|
+
The MCP authenticates via a 90-day HMAC bearer token, byte-identical to a logged-in `ES_AUTH` session cookie. Mint it via the admin endpoint (admin-IP-restricted in prod via nginx; reachable on localhost in dev):
|
|
33
20
|
|
|
34
21
|
```bash
|
|
22
|
+
# Prod (must be on an admin-allowlisted IP)
|
|
23
|
+
curl -X POST "https://equisense.ai/api/v1/admin/auth/mint-mcp-token?phoneNumber=9876543210"
|
|
24
|
+
|
|
25
|
+
# Dev
|
|
35
26
|
curl -X POST "http://localhost:8080/api/v1/admin/auth/mint-mcp-token?phoneNumber=9876543210"
|
|
36
27
|
```
|
|
37
28
|
|
|
38
29
|
Response:
|
|
39
|
-
|
|
40
30
|
```json
|
|
41
31
|
{
|
|
42
32
|
"token": "<payload>.<sig>",
|
|
@@ -47,22 +37,30 @@ Response:
|
|
|
47
37
|
}
|
|
48
38
|
```
|
|
49
39
|
|
|
50
|
-
|
|
40
|
+
Copy the `token`. Treat it like a password.
|
|
51
41
|
|
|
52
|
-
|
|
53
|
-
- There is no per-token denylist in v1 — the only way to revoke is to wait 90 days or rotate the global `auth.token.secret` (which logs everyone out). Don't paste this token anywhere you wouldn't paste your account password.
|
|
54
|
-
- Never commit the token. Never log it. Never paste it into chat.
|
|
42
|
+
### 2. Register the MCP with Claude Code
|
|
55
43
|
|
|
56
|
-
|
|
44
|
+
**Recommended (npx, no install):**
|
|
57
45
|
|
|
58
46
|
```bash
|
|
59
47
|
claude mcp add equisense-research --scope local \
|
|
60
|
-
--env EQUISENSE_BASE_URL=
|
|
61
|
-
--env EQUISENSE_MCP_TOKEN='<token from
|
|
62
|
-
--
|
|
48
|
+
--env EQUISENSE_BASE_URL=https://equisense.ai \
|
|
49
|
+
--env EQUISENSE_MCP_TOKEN='<token from step 1>' \
|
|
50
|
+
-- npx -y equisense-research-mcp
|
|
63
51
|
```
|
|
64
52
|
|
|
65
|
-
|
|
53
|
+
**Alternative (global install):**
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npm install -g equisense-research-mcp
|
|
57
|
+
claude mcp add equisense-research --scope local \
|
|
58
|
+
--env EQUISENSE_BASE_URL=https://equisense.ai \
|
|
59
|
+
--env EQUISENSE_MCP_TOKEN='<token>' \
|
|
60
|
+
-- equisense-research-mcp
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 3. Verify
|
|
66
64
|
|
|
67
65
|
```bash
|
|
68
66
|
claude mcp list
|
|
@@ -70,32 +68,73 @@ claude mcp list
|
|
|
70
68
|
|
|
71
69
|
Should show `equisense-research - ✓ Connected`.
|
|
72
70
|
|
|
73
|
-
|
|
71
|
+
### 4. Try it
|
|
72
|
+
|
|
73
|
+
In any Claude Code session:
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
2. Mint a token for your test user (see above).
|
|
77
|
-
3. Register the MCP with the minted token in the env.
|
|
78
|
-
4. In Claude Code, ask: *"Use ask_research: bull case for OLAELEC."*
|
|
79
|
-
5. Confirm a structured response with `answer`, `companyName`, `followUpQuestions` comes back.
|
|
80
|
-
6. Confirm one `AI_EQUITY_RESEARCH` event lands in the user's metering ledger (the call is metered, same as the UI path).
|
|
75
|
+
> Use ask_research: bull case for OLAELEC
|
|
81
76
|
|
|
82
|
-
|
|
77
|
+
You should get back `{ answer, companyName, isin, detectedIntent, followUpQuestions, responseTimeMs }`.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Environment variables
|
|
82
|
+
|
|
83
|
+
| Var | Default | Purpose |
|
|
84
|
+
|---|---|---|
|
|
85
|
+
| `EQUISENSE_BASE_URL` | `http://localhost:8080` | Backend root URL |
|
|
86
|
+
| `EQUISENSE_TIMEOUT_MS` | `90000` | Per-request timeout (research queries can take 30–90s) |
|
|
87
|
+
| `EQUISENSE_MCP_TOKEN` | **required** | HMAC bearer token. Treat like a password. |
|
|
88
|
+
|
|
89
|
+
## Security notes
|
|
90
|
+
|
|
91
|
+
- The minted token grants **full session access** for 90 days, scope-equivalent to a logged-in browser session for that user. Not scoped to research-only.
|
|
92
|
+
- There is no per-token revocation in v1. The only way to invalidate a token early is to rotate the global `auth.token.secret` (which logs out every user).
|
|
93
|
+
- Never commit the token. Never log it. Never paste it into chat.
|
|
94
|
+
- Each `ask_research` call counts against the represented user's `AI_EQUITY_RESEARCH` daily quota — same metering as the web UI.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Contributing / running from source
|
|
83
99
|
|
|
84
100
|
```bash
|
|
101
|
+
git clone git@github.com:shivanshu-dixit/equity-sense.git
|
|
102
|
+
cd equity-sense/mcp-server/equisense-research
|
|
103
|
+
npm install
|
|
85
104
|
npm test
|
|
86
105
|
```
|
|
87
106
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
- `test/unit.test.js` — TOOLS shape, fetch body shape, HTTP error mapping (401/402/403/429/5xx)
|
|
107
|
+
Tests:
|
|
108
|
+
- `test/unit.test.js` — TOOLS shape, fetch body, HTTP error mapping (401/402/403/429/5xx)
|
|
91
109
|
- `test/integration.test.js` — fail-fast on missing env, stdio handshake + `tools/list` RPC
|
|
92
110
|
|
|
111
|
+
Local registration against from-source code (instead of npm):
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
claude mcp add equisense-research --scope local \
|
|
115
|
+
--env EQUISENSE_BASE_URL=http://localhost:8080 \
|
|
116
|
+
--env EQUISENSE_MCP_TOKEN='<token>' \
|
|
117
|
+
-- node /absolute/path/to/equity-sense/mcp-server/equisense-research/index.js
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Why Node?
|
|
121
|
+
|
|
122
|
+
The Java app (Spring Boot 3.1) is too old for the Spring AI MCP server starter (needs 3.4+). All research logic, LLM routing, and feature metering stay server-side in Java; this wrapper just speaks MCP.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
93
126
|
## Troubleshooting
|
|
94
127
|
|
|
95
128
|
| Symptom | Likely cause | Fix |
|
|
96
129
|
|---|---|---|
|
|
97
|
-
| `FATAL: EQUISENSE_MCP_TOKEN env var is required` on startup |
|
|
98
|
-
| `Auth failed (HTTP 401) ...
|
|
130
|
+
| `FATAL: EQUISENSE_MCP_TOKEN env var is required` on startup | Env var unset or empty | Pass `--env EQUISENSE_MCP_TOKEN=...` to `claude mcp add` |
|
|
131
|
+
| `Auth failed (HTTP 401) ... re-mint via /api/v1/admin/auth/mint-mcp-token` | Token > 90 days old OR `auth.token.secret` rotated | Re-mint and update the env |
|
|
99
132
|
| `AI_EQUITY_RESEARCH quota exhausted (HTTP 402)` | Daily quota hit | Wait until tomorrow OR upgrade the user's plan |
|
|
133
|
+
| `Rate limited (HTTP 429)` | Transient | Retry in a few seconds |
|
|
100
134
|
| `Forbidden (HTTP 403)` | User doesn't have `AI_EQUITY_RESEARCH` feature | Check the user's license/plan |
|
|
101
|
-
| Hangs > 90s with no response | Backend research query timed out | Bump `EQUISENSE_TIMEOUT_MS`; check
|
|
135
|
+
| Hangs > 90s with no response | Backend research query timed out | Bump `EQUISENSE_TIMEOUT_MS`; check backend logs |
|
|
136
|
+
| `403` minting in prod | Your IP isn't admin-allowlisted | SSH to prod box and mint from there, or have an admin mint for you |
|
|
137
|
+
|
|
138
|
+
## License
|
|
139
|
+
|
|
140
|
+
MIT
|
package/index.js
CHANGED
|
@@ -200,11 +200,24 @@ function createServer() {
|
|
|
200
200
|
return server;
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
-
// Only start the server when this file is the entrypoint.
|
|
204
|
-
//
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
203
|
+
// Only start the server when this file is the entrypoint. Resolve symlinks on
|
|
204
|
+
// both sides so the check survives npx, global bin installs, and pnpm shims.
|
|
205
|
+
// Without realpath, a `bin` entry symlinked to index.js shows up in argv[1] as
|
|
206
|
+
// `<cache>/.bin/equisense-research-mcp` — not ending in index.js — and the
|
|
207
|
+
// server silently never starts.
|
|
208
|
+
import { realpathSync } from "node:fs";
|
|
209
|
+
import { fileURLToPath } from "node:url";
|
|
210
|
+
|
|
211
|
+
const isEntrypoint = (() => {
|
|
212
|
+
try {
|
|
213
|
+
if (!process.argv[1]) return false;
|
|
214
|
+
const thisFile = realpathSync(fileURLToPath(import.meta.url));
|
|
215
|
+
const argvFile = realpathSync(process.argv[1]);
|
|
216
|
+
return thisFile === argvFile;
|
|
217
|
+
} catch {
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
})();
|
|
208
221
|
|
|
209
222
|
if (isEntrypoint) {
|
|
210
223
|
const server = createServer();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "equisense-research-mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "MCP server wrapper for the EquiSense AI equity-research API. Exposes a single ask_research tool that proxies POST /api/v1/research/ask, authenticated via a minted ES_AUTH bearer token.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|