@meertrack/mcp 1.0.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/LICENSE +21 -0
- package/README.md +313 -0
- package/dist/auth.d.ts +75 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +109 -0
- package/dist/auth.js.map +1 -0
- package/dist/client.d.ts +84 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +178 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +27 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +68 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +77 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +48 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +46 -0
- package/dist/logger.js.map +1 -0
- package/dist/prompts/competitor_deep_dive.d.ts +5 -0
- package/dist/prompts/competitor_deep_dive.d.ts.map +1 -0
- package/dist/prompts/competitor_deep_dive.js +48 -0
- package/dist/prompts/competitor_deep_dive.js.map +1 -0
- package/dist/prompts/index.d.ts +13 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +20 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/weekly_recap.d.ts +5 -0
- package/dist/prompts/weekly_recap.d.ts.map +1 -0
- package/dist/prompts/weekly_recap.js +28 -0
- package/dist/prompts/weekly_recap.js.map +1 -0
- package/dist/prompts/whats_new.d.ts +5 -0
- package/dist/prompts/whats_new.d.ts.map +1 -0
- package/dist/prompts/whats_new.js +46 -0
- package/dist/prompts/whats_new.js.map +1 -0
- package/dist/server.d.ts +34 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +43 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/get_activity_item.d.ts +6 -0
- package/dist/tools/get_activity_item.d.ts.map +1 -0
- package/dist/tools/get_activity_item.js +33 -0
- package/dist/tools/get_activity_item.js.map +1 -0
- package/dist/tools/get_competitor.d.ts +6 -0
- package/dist/tools/get_competitor.d.ts.map +1 -0
- package/dist/tools/get_competitor.js +37 -0
- package/dist/tools/get_competitor.js.map +1 -0
- package/dist/tools/get_digest.d.ts +6 -0
- package/dist/tools/get_digest.d.ts.map +1 -0
- package/dist/tools/get_digest.js +33 -0
- package/dist/tools/get_digest.js.map +1 -0
- package/dist/tools/index.d.ts +20 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +36 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/list_activities.d.ts +6 -0
- package/dist/tools/list_activities.d.ts.map +1 -0
- package/dist/tools/list_activities.js +87 -0
- package/dist/tools/list_activities.js.map +1 -0
- package/dist/tools/list_competitors.d.ts +6 -0
- package/dist/tools/list_competitors.d.ts.map +1 -0
- package/dist/tools/list_competitors.js +58 -0
- package/dist/tools/list_competitors.js.map +1 -0
- package/dist/tools/list_digests.d.ts +6 -0
- package/dist/tools/list_digests.d.ts.map +1 -0
- package/dist/tools/list_digests.js +63 -0
- package/dist/tools/list_digests.js.map +1 -0
- package/dist/tools/list_latest_digests.d.ts +6 -0
- package/dist/tools/list_latest_digests.d.ts.map +1 -0
- package/dist/tools/list_latest_digests.js +30 -0
- package/dist/tools/list_latest_digests.js.map +1 -0
- package/dist/tools/whoami.d.ts +6 -0
- package/dist/tools/whoami.d.ts.map +1 -0
- package/dist/tools/whoami.js +30 -0
- package/dist/tools/whoami.js.map +1 -0
- package/dist/transports/http.d.ts +58 -0
- package/dist/transports/http.d.ts.map +1 -0
- package/dist/transports/http.js +179 -0
- package/dist/transports/http.js.map +1 -0
- package/dist/transports/stdio.d.ts +12 -0
- package/dist/transports/stdio.d.ts.map +1 -0
- package/dist/transports/stdio.js +35 -0
- package/dist/transports/stdio.js.map +1 -0
- package/dist/types.d.ts +6204 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +359 -0
- package/dist/types.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +5 -0
- package/dist/version.js.map +1 -0
- package/package.json +68 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Meertrack
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
# `@meertrack/mcp`
|
|
2
|
+
|
|
3
|
+
[](https://modelcontextprotocol.io/specification/2025-11-25)
|
|
4
|
+
[](#the-8-tools)
|
|
5
|
+
[](https://www.npmjs.com/package/@meertrack/mcp)
|
|
6
|
+
[](https://github.com/meertrack/meertrack-mcp/actions/workflows/ci.yml)
|
|
7
|
+
|
|
8
|
+
Model Context Protocol server for [Meertrack](https://meertrack.com). Ask your
|
|
9
|
+
agent "what did my competitors ship this week?" from Claude, Cursor, Claude
|
|
10
|
+
Code, VS Code, Windsurf, Cline, ChatGPT, or anywhere that speaks MCP.
|
|
11
|
+
|
|
12
|
+
Wraps the [Meertrack v1 REST API](https://api.meertrack.com/v1) as **8
|
|
13
|
+
read-only tools** and **3 prompt workflows**. No backend changes, same
|
|
14
|
+
`mt_live_` keys, same rate limits.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Pick your transport
|
|
19
|
+
|
|
20
|
+
| | Local (stdio) | Remote (Streamable HTTP) |
|
|
21
|
+
| --- | --- | --- |
|
|
22
|
+
| **Setup time** | 30 seconds (paste a JSON block) | 10 seconds (paste a URL) |
|
|
23
|
+
| **Best for** | Individual Pro customers; all Claude Desktop plans; any IDE on your laptop | Team/Enterprise custom connectors; Claude.ai web; remote-capable IDEs |
|
|
24
|
+
| **Runs where** | Your machine (`npx -y @meertrack/mcp`) | Meertrack's Fly.io fleet (`https://mcp.meertrack.com/mcp`) |
|
|
25
|
+
| **Auth** | `MEERTRACK_API_KEY` env var | `Authorization: Bearer mt_live_…` header |
|
|
26
|
+
| **Plan gating** | Works on Claude Pro, Team, Enterprise | Claude Desktop "Add custom connector" is **Team/Enterprise only** |
|
|
27
|
+
|
|
28
|
+
**If you're on Claude Pro, use the local (stdio) path.** The "Add custom
|
|
29
|
+
connector" button in the Claude Desktop settings is gated to Team/Enterprise,
|
|
30
|
+
and pasting `https://mcp.meertrack.com/mcp` there won't do anything on a Pro
|
|
31
|
+
plan.
|
|
32
|
+
|
|
33
|
+
## Get an API key
|
|
34
|
+
|
|
35
|
+
Mint a production key at **Settings → API Keys** in the Meertrack app. Keys
|
|
36
|
+
start with `mt_live_`. Only production keys work; there is no `mt_test_`
|
|
37
|
+
flavour.
|
|
38
|
+
|
|
39
|
+
> **Rate limits.** Each API key shares a **60 requests/minute** budget enforced
|
|
40
|
+
> upstream. If you run the MCP from multiple clients at once (Claude Desktop +
|
|
41
|
+
> Cursor + a background agent) they all draw from the same bucket. Mint a
|
|
42
|
+
> separate key per workstation or per agent to isolate budgets. The tool-error
|
|
43
|
+
> message on 429 includes both a human-readable reset time and the raw
|
|
44
|
+
> `X-RateLimit-Reset` epoch so the agent can back off automatically.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Local install: recommended default
|
|
49
|
+
|
|
50
|
+
All local-mode clients use the same shape: `npx -y @meertrack/mcp` with
|
|
51
|
+
`MEERTRACK_API_KEY` in the environment. What differs is the config file and
|
|
52
|
+
the surrounding JSON key.
|
|
53
|
+
|
|
54
|
+
Drop-in copies of every config file below live in [`examples/`](examples/).
|
|
55
|
+
|
|
56
|
+
### Claude Desktop (all plans)
|
|
57
|
+
|
|
58
|
+
Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
|
|
59
|
+
or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"mcpServers": {
|
|
64
|
+
"meertrack": {
|
|
65
|
+
"command": "npx",
|
|
66
|
+
"args": ["-y", "@meertrack/mcp"],
|
|
67
|
+
"env": {
|
|
68
|
+
"MEERTRACK_API_KEY": "mt_live_..."
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
> **Gotcha**: Claude Desktop only re-reads this file on launch. Fully quit
|
|
76
|
+
> (⌘Q on macOS) and reopen. Reloading the window is not enough.
|
|
77
|
+
|
|
78
|
+
### Cursor
|
|
79
|
+
|
|
80
|
+
Edit `~/.cursor/mcp.json` (or `.cursor/mcp.json` in a project):
|
|
81
|
+
|
|
82
|
+
```json
|
|
83
|
+
{
|
|
84
|
+
"mcpServers": {
|
|
85
|
+
"meertrack": {
|
|
86
|
+
"command": "npx",
|
|
87
|
+
"args": ["-y", "@meertrack/mcp"],
|
|
88
|
+
"env": {
|
|
89
|
+
"MEERTRACK_API_KEY": "mt_live_..."
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Claude Code (CLI)
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
claude mcp add meertrack npx -y @meertrack/mcp \
|
|
100
|
+
--env MEERTRACK_API_KEY=mt_live_...
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### VS Code (GitHub Copilot MCP)
|
|
104
|
+
|
|
105
|
+
Edit `.vscode/mcp.json` (per-workspace) or the user settings equivalent:
|
|
106
|
+
|
|
107
|
+
```json
|
|
108
|
+
{
|
|
109
|
+
"servers": {
|
|
110
|
+
"meertrack": {
|
|
111
|
+
"command": "npx",
|
|
112
|
+
"args": ["-y", "@meertrack/mcp"],
|
|
113
|
+
"env": {
|
|
114
|
+
"MEERTRACK_API_KEY": "mt_live_..."
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
> **Gotcha**: VS Code uses `servers`, not `mcpServers`. The Copilot MCP picker
|
|
122
|
+
> won't find your server if you use the Claude Desktop key.
|
|
123
|
+
|
|
124
|
+
### Windsurf
|
|
125
|
+
|
|
126
|
+
Edit `~/.codeium/windsurf/mcp_config.json`:
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"mcpServers": {
|
|
131
|
+
"meertrack": {
|
|
132
|
+
"command": "npx",
|
|
133
|
+
"args": ["-y", "@meertrack/mcp"],
|
|
134
|
+
"env": {
|
|
135
|
+
"MEERTRACK_API_KEY": "mt_live_..."
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
> **Gotcha**: Windsurf's remote-connector shape uses `serverUrl`, not `url`.
|
|
143
|
+
> For the stdio config above, the shape is identical to Claude Desktop.
|
|
144
|
+
|
|
145
|
+
### Cline (VS Code extension)
|
|
146
|
+
|
|
147
|
+
Cline's settings panel → "MCP Servers" → paste:
|
|
148
|
+
|
|
149
|
+
```json
|
|
150
|
+
{
|
|
151
|
+
"mcpServers": {
|
|
152
|
+
"meertrack": {
|
|
153
|
+
"command": "npx",
|
|
154
|
+
"args": ["-y", "@meertrack/mcp"],
|
|
155
|
+
"env": {
|
|
156
|
+
"MEERTRACK_API_KEY": "mt_live_..."
|
|
157
|
+
},
|
|
158
|
+
"disabled": false,
|
|
159
|
+
"autoApprove": []
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Remote install: Team/Enterprise + claude.ai web
|
|
168
|
+
|
|
169
|
+
All remote clients point at the same URL:
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
https://mcp.meertrack.com/mcp
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
...with `Authorization: Bearer mt_live_…`. One shared hosted server. Nothing
|
|
176
|
+
to install locally.
|
|
177
|
+
|
|
178
|
+
### Claude Desktop (Team / Enterprise only: "Add custom connector")
|
|
179
|
+
|
|
180
|
+
Settings → Connectors → **Add custom connector** → paste the URL above and
|
|
181
|
+
your bearer token when prompted. The "Add custom connector" button is not
|
|
182
|
+
visible on Pro; use the stdio path above instead.
|
|
183
|
+
|
|
184
|
+
### Claude.ai web (Connectors)
|
|
185
|
+
|
|
186
|
+
Same as above in the web app's Connectors panel.
|
|
187
|
+
|
|
188
|
+
### Cursor (remote MCP)
|
|
189
|
+
|
|
190
|
+
```json
|
|
191
|
+
{
|
|
192
|
+
"mcpServers": {
|
|
193
|
+
"meertrack": {
|
|
194
|
+
"url": "https://mcp.meertrack.com/mcp",
|
|
195
|
+
"headers": {
|
|
196
|
+
"Authorization": "Bearer mt_live_..."
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### ChatGPT MCP connectors
|
|
204
|
+
|
|
205
|
+
Paste the URL and bearer in the ChatGPT "Add MCP" dialog. Note: ChatGPT's
|
|
206
|
+
bearer support is minimal today; full OAuth parity is tracked as Phase 11.
|
|
207
|
+
|
|
208
|
+
### n8n / Zapier / …any Streamable HTTP client
|
|
209
|
+
|
|
210
|
+
- Endpoint: `https://mcp.meertrack.com/mcp`
|
|
211
|
+
- Method: `POST`
|
|
212
|
+
- Headers: `Authorization: Bearer mt_live_…`, `Accept: application/json, text/event-stream`, `MCP-Protocol-Version: 2025-11-25`
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## The 8 tools
|
|
217
|
+
|
|
218
|
+
All read-only, all snake_case. Collection returns use the `list_` prefix;
|
|
219
|
+
single-item returns use `get_`. Every list response includes
|
|
220
|
+
`pagination.next_cursor` and `pagination.has_more`, and agents must pass
|
|
221
|
+
`next_cursor` back as `cursor` to fetch the next page.
|
|
222
|
+
|
|
223
|
+
| Domain | Tool | Wraps | Notes |
|
|
224
|
+
| --- | --- | --- | --- |
|
|
225
|
+
| Identity | [`whoami`](src/tools/whoami.ts) | `GET /me` | Confirms workspace + subscription + rate-limit snapshot. Call first. |
|
|
226
|
+
| Competitors | [`list_competitors`](src/tools/list_competitors.ts) | `GET /competitors` | Defaults to `expand=full` so agents don't round-trip for socials/pages. |
|
|
227
|
+
| Competitors | [`get_competitor`](src/tools/get_competitor.ts) | `GET /competitors/{id}` | 11 tracked sections (blog, pricing, jobs, …) with per-section caps. |
|
|
228
|
+
| Activity | [`list_activities`](src/tools/list_activities.ts) | `GET /activity` | Core "what shipped" feed. Default `limit=50` to stay under tool-result size limits. |
|
|
229
|
+
| Activity | [`get_activity_item`](src/tools/get_activity_item.ts) | `GET /activity/{row_uuid}` | Drill-in for a specific row's full payload. |
|
|
230
|
+
| Digests | [`list_digests`](src/tools/list_digests.ts) | `GET /digests` | Cursor-paginated weekly digests. No `total` field (unlike activity). |
|
|
231
|
+
| Digests | [`list_latest_digests`](src/tools/list_latest_digests.ts) | `GET /digests/latest` | No params; one-shot "what happened this week". |
|
|
232
|
+
| Digests | [`get_digest`](src/tools/get_digest.ts) | `GET /digests/{id}` | Full summary + themes for one competitor × period. |
|
|
233
|
+
|
|
234
|
+
Full input / output / error-code documentation is on the tool descriptions
|
|
235
|
+
themselves, and the MCP client displays them inline.
|
|
236
|
+
|
|
237
|
+
## The 3 prompts
|
|
238
|
+
|
|
239
|
+
Slash commands in Claude Desktop / Cursor / Claude Code / any prompt-capable
|
|
240
|
+
MCP client. Each one chains tool calls into a complete workflow.
|
|
241
|
+
|
|
242
|
+
| Prompt | Args | Chains |
|
|
243
|
+
| --- | --- | --- |
|
|
244
|
+
| [`/weekly_recap`](src/prompts/weekly_recap.ts) | none | `list_latest_digests` → per-competitor summary + highlights |
|
|
245
|
+
| [`/competitor_deep_dive`](src/prompts/competitor_deep_dive.ts) | `competitor_name` | `list_competitors` → `get_competitor` → `list_activities` (last 30d) |
|
|
246
|
+
| [`/whats_new`](src/prompts/whats_new.ts) | `days?` (default 7) | `list_activities` from `now - N days`, grouped by competitor |
|
|
247
|
+
|
|
248
|
+
### Example invocations
|
|
249
|
+
|
|
250
|
+
- `/weekly_recap`
|
|
251
|
+
- `/competitor_deep_dive competitor_name="Acme"`
|
|
252
|
+
- `/whats_new days="14"`
|
|
253
|
+
|
|
254
|
+
See [`examples/prompts.md`](examples/prompts.md) for a dozen copy-paste user
|
|
255
|
+
prompts grouped by use case (weekly check-in, feature spec research, pricing
|
|
256
|
+
comparison, board-deck prep).
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## Troubleshooting
|
|
261
|
+
|
|
262
|
+
When the upstream API returns an error, the MCP tool response surfaces the
|
|
263
|
+
upstream `code` in the error text. Map them:
|
|
264
|
+
|
|
265
|
+
| Upstream `code` | What it means | Fix |
|
|
266
|
+
| --- | --- | --- |
|
|
267
|
+
| `unauthorized` | Key is invalid, revoked, or expired | Mint a new key at Settings → API Keys and update the config |
|
|
268
|
+
| `competitor_inactive` | Competitor is archived in this workspace | Reactivate the competitor in the dashboard |
|
|
269
|
+
| `forbidden_competitor` | The `id` you passed isn't in this workspace | Call `list_competitors` first to discover valid ids |
|
|
270
|
+
| `rate_limited` | 60 req/min cap hit | Wait until the reset timestamp in the error message, or mint a second key for the other client |
|
|
271
|
+
| `not_found` | No such row in this workspace | The id is either wrong or belongs to a different workspace |
|
|
272
|
+
| `invalid_parameter` / `invalid_cursor` | Bad input | Check the error message; cursors expire, so re-list from the start |
|
|
273
|
+
|
|
274
|
+
**Other common snags**
|
|
275
|
+
|
|
276
|
+
- Claude Desktop didn't pick up your config → **quit and relaunch the app**,
|
|
277
|
+
not just close the window. Config is read at launch.
|
|
278
|
+
- `command not found: npx` → install Node ≥ 20. The MCP pins `engines.node`.
|
|
279
|
+
- Remote URL returns 401 with `WWW-Authenticate: Bearer` → your bearer is
|
|
280
|
+
missing, malformed, or doesn't start with `mt_live_`.
|
|
281
|
+
- You see 401s that clear up when you refresh the key → the bearer is fine;
|
|
282
|
+
this is a spec-conformant "please authenticate" from the MCP. Send the
|
|
283
|
+
`Authorization` header.
|
|
284
|
+
- Running both stdio and remote with the **same key** → you're sharing a
|
|
285
|
+
60/min budget across both. Mint separate keys per client.
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## Semantic versioning
|
|
290
|
+
|
|
291
|
+
MCP tool schemas are part of the public API contract; agents cache them. So:
|
|
292
|
+
|
|
293
|
+
- **MAJOR**: a tool is removed, or an existing tool's input/output schema
|
|
294
|
+
breaks (required arg added, field renamed, enum value removed).
|
|
295
|
+
- **MINOR**: a new tool, a new optional argument, or a new prompt.
|
|
296
|
+
- **PATCH**: bug fixes, description improvements, internal refactors with no
|
|
297
|
+
schema impact.
|
|
298
|
+
|
|
299
|
+
See [CHANGELOG.md](CHANGELOG.md) for the release history.
|
|
300
|
+
|
|
301
|
+
## Security & privacy
|
|
302
|
+
|
|
303
|
+
- [SECURITY.md](SECURITY.md): disclosure policy (`security@meertrack.com`),
|
|
304
|
+
in-scope surface.
|
|
305
|
+
- [docs/PRIVACY.md](docs/PRIVACY.md): the MCP layer is stateless; bearers are
|
|
306
|
+
forwarded per-request and nothing is persisted.
|
|
307
|
+
- [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md): request flow diagram.
|
|
308
|
+
- [docs/OBSERVABILITY.md](docs/OBSERVABILITY.md): what gets logged, and how
|
|
309
|
+
bearer tokens are redacted.
|
|
310
|
+
|
|
311
|
+
## License
|
|
312
|
+
|
|
313
|
+
MIT.
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bearer resolution for both transports.
|
|
3
|
+
*
|
|
4
|
+
* - `stdio`: key comes from `MEERTRACK_API_KEY` once at process start.
|
|
5
|
+
* - `http` : key comes from the `Authorization` header per request, with a
|
|
6
|
+
* `?api_key=` query-string fallback for clients that can't set
|
|
7
|
+
* custom headers (some Claude Desktop builds, claude.ai web).
|
|
8
|
+
*
|
|
9
|
+
* In both modes we validate the `mt_live_` prefix locally before the first
|
|
10
|
+
* upstream call — fail fast with a useful message instead of round-tripping
|
|
11
|
+
* an upstream 401 for an obviously malformed key.
|
|
12
|
+
*/
|
|
13
|
+
export declare const API_KEY_PREFIX = "mt_live_";
|
|
14
|
+
/** True iff `value` begins with `mt_live_`. Does not assert length/charset. */
|
|
15
|
+
export declare function hasApiKeyPrefix(value: string): boolean;
|
|
16
|
+
/** Strict format check: prefix + non-empty base64url body. */
|
|
17
|
+
export declare function isWellFormedApiKey(value: string): boolean;
|
|
18
|
+
export declare class MissingApiKeyError extends Error {
|
|
19
|
+
constructor(message: string);
|
|
20
|
+
}
|
|
21
|
+
export declare class InvalidApiKeyError extends Error {
|
|
22
|
+
constructor(message: string);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* stdio: resolve the bearer from the environment exactly once at startup.
|
|
26
|
+
* Throws a descriptive error that the entrypoint can surface on stderr and
|
|
27
|
+
* exit with. Never logs the key itself.
|
|
28
|
+
*/
|
|
29
|
+
export declare function resolveEnvApiKey(env?: NodeJS.ProcessEnv): string;
|
|
30
|
+
/**
|
|
31
|
+
* HTTP mode: resolution outcome per request. Successful cases carry the
|
|
32
|
+
* forwardable bearer; failures carry everything the transport needs to emit
|
|
33
|
+
* a spec-conformant 401 (WWW-Authenticate header value included).
|
|
34
|
+
*/
|
|
35
|
+
export type HttpAuthResolution = {
|
|
36
|
+
ok: true;
|
|
37
|
+
apiKey: string;
|
|
38
|
+
source: "header" | "query";
|
|
39
|
+
} | {
|
|
40
|
+
ok: false;
|
|
41
|
+
status: 401;
|
|
42
|
+
code: "unauthorized";
|
|
43
|
+
message: string;
|
|
44
|
+
wwwAuthenticate: string;
|
|
45
|
+
};
|
|
46
|
+
export interface HttpAuthContext {
|
|
47
|
+
/** Case-insensitive header lookup — works for `Headers`, plain objects, and Hono's helpers. */
|
|
48
|
+
header: (name: string) => string | null | undefined;
|
|
49
|
+
/** Parsed search params for the inbound URL. */
|
|
50
|
+
searchParams: URLSearchParams;
|
|
51
|
+
/** Public URL of the `/.well-known/oauth-protected-resource` document. */
|
|
52
|
+
protectedResourceMetadataUrl: string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Extract a bearer from an incoming HTTP request. Header wins over query when
|
|
56
|
+
* both are set. If absent or malformed, return an `ok: false` resolution
|
|
57
|
+
* carrying a fully-formed `WWW-Authenticate` header value — the transport
|
|
58
|
+
* emits the 401 without touching the upstream API.
|
|
59
|
+
*/
|
|
60
|
+
export declare function extractHttpBearer(ctx: HttpAuthContext): HttpAuthResolution;
|
|
61
|
+
/** Extract a bearer token from an `Authorization` header value, or `null` if absent/malformed. */
|
|
62
|
+
export declare function parseBearerHeader(value: string): string | null;
|
|
63
|
+
/**
|
|
64
|
+
* MCP 2025-11-25 §Authorization / RFC 9728: 401 responses on the HTTP transport
|
|
65
|
+
* MUST advertise where the client can find Protected Resource Metadata. Clients
|
|
66
|
+
* use this to discover how to authenticate (static bearer today; OAuth in a
|
|
67
|
+
* future version).
|
|
68
|
+
*/
|
|
69
|
+
export declare function buildWwwAuthenticateHeader(protectedResourceMetadataUrl: string): string;
|
|
70
|
+
/**
|
|
71
|
+
* Redact every `mt_live_…` token in `value`. Apply to any string before
|
|
72
|
+
* writing it to logs or error messages. Also redacts `Bearer mt_live_…`.
|
|
73
|
+
*/
|
|
74
|
+
export declare function redactApiKeys(value: string): string;
|
|
75
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,eAAO,MAAM,cAAc,aAAa,CAAC;AAKzC,+EAA+E;AAC/E,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED,8DAA8D;AAC9D,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAcR;AAED;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAA;CAAE,GACxD;IACE,EAAE,EAAE,KAAK,CAAC;IACV,MAAM,EAAE,GAAG,CAAC;IACZ,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEN,MAAM,WAAW,eAAe;IAC9B,+FAA+F;IAC/F,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACpD,gDAAgD;IAChD,YAAY,EAAE,eAAe,CAAC;IAC9B,0EAA0E;IAC1E,4BAA4B,EAAE,MAAM,CAAC;CACtC;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,eAAe,GAAG,kBAAkB,CAgC1E;AAED,kGAAkG;AAClG,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAK9D;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,4BAA4B,EAAE,MAAM,GAAG,MAAM,CAEvF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnD"}
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bearer resolution for both transports.
|
|
3
|
+
*
|
|
4
|
+
* - `stdio`: key comes from `MEERTRACK_API_KEY` once at process start.
|
|
5
|
+
* - `http` : key comes from the `Authorization` header per request, with a
|
|
6
|
+
* `?api_key=` query-string fallback for clients that can't set
|
|
7
|
+
* custom headers (some Claude Desktop builds, claude.ai web).
|
|
8
|
+
*
|
|
9
|
+
* In both modes we validate the `mt_live_` prefix locally before the first
|
|
10
|
+
* upstream call — fail fast with a useful message instead of round-tripping
|
|
11
|
+
* an upstream 401 for an obviously malformed key.
|
|
12
|
+
*/
|
|
13
|
+
export const API_KEY_PREFIX = "mt_live_";
|
|
14
|
+
/** Full pattern: `mt_live_` followed by base64url characters. */
|
|
15
|
+
const API_KEY_PATTERN = /^mt_live_[A-Za-z0-9_-]+$/;
|
|
16
|
+
/** True iff `value` begins with `mt_live_`. Does not assert length/charset. */
|
|
17
|
+
export function hasApiKeyPrefix(value) {
|
|
18
|
+
return value.startsWith(API_KEY_PREFIX);
|
|
19
|
+
}
|
|
20
|
+
/** Strict format check: prefix + non-empty base64url body. */
|
|
21
|
+
export function isWellFormedApiKey(value) {
|
|
22
|
+
return API_KEY_PATTERN.test(value);
|
|
23
|
+
}
|
|
24
|
+
export class MissingApiKeyError extends Error {
|
|
25
|
+
constructor(message) {
|
|
26
|
+
super(message);
|
|
27
|
+
this.name = "MissingApiKeyError";
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export class InvalidApiKeyError extends Error {
|
|
31
|
+
constructor(message) {
|
|
32
|
+
super(message);
|
|
33
|
+
this.name = "InvalidApiKeyError";
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* stdio: resolve the bearer from the environment exactly once at startup.
|
|
38
|
+
* Throws a descriptive error that the entrypoint can surface on stderr and
|
|
39
|
+
* exit with. Never logs the key itself.
|
|
40
|
+
*/
|
|
41
|
+
export function resolveEnvApiKey(env = process.env) {
|
|
42
|
+
const raw = env["MEERTRACK_API_KEY"];
|
|
43
|
+
if (!raw || raw.trim().length === 0) {
|
|
44
|
+
throw new MissingApiKeyError("MEERTRACK_API_KEY is not set. Mint a key at Settings → API Keys in the Meertrack app and export it before running the MCP server.");
|
|
45
|
+
}
|
|
46
|
+
const trimmed = raw.trim();
|
|
47
|
+
if (!hasApiKeyPrefix(trimmed)) {
|
|
48
|
+
throw new InvalidApiKeyError("MEERTRACK_API_KEY does not start with `mt_live_`. Only production keys (`mt_live_…`) are supported.");
|
|
49
|
+
}
|
|
50
|
+
return trimmed;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Extract a bearer from an incoming HTTP request. Header wins over query when
|
|
54
|
+
* both are set. If absent or malformed, return an `ok: false` resolution
|
|
55
|
+
* carrying a fully-formed `WWW-Authenticate` header value — the transport
|
|
56
|
+
* emits the 401 without touching the upstream API.
|
|
57
|
+
*/
|
|
58
|
+
export function extractHttpBearer(ctx) {
|
|
59
|
+
const headerValue = ctx.header("authorization") ?? ctx.header("Authorization");
|
|
60
|
+
const fromHeader = headerValue ? parseBearerHeader(headerValue) : null;
|
|
61
|
+
const fromQuery = ctx.searchParams.get("api_key");
|
|
62
|
+
const candidate = fromHeader ?? (fromQuery ? fromQuery.trim() : null);
|
|
63
|
+
const source = fromHeader ? "header" : "query";
|
|
64
|
+
const wwwAuthenticate = buildWwwAuthenticateHeader(ctx.protectedResourceMetadataUrl);
|
|
65
|
+
if (!candidate) {
|
|
66
|
+
return {
|
|
67
|
+
ok: false,
|
|
68
|
+
status: 401,
|
|
69
|
+
code: "unauthorized",
|
|
70
|
+
message: "Missing API key. Send `Authorization: Bearer mt_live_…` (preferred) or `?api_key=mt_live_…` as a query-string fallback.",
|
|
71
|
+
wwwAuthenticate,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
if (!hasApiKeyPrefix(candidate)) {
|
|
75
|
+
return {
|
|
76
|
+
ok: false,
|
|
77
|
+
status: 401,
|
|
78
|
+
code: "unauthorized",
|
|
79
|
+
message: "API key does not start with `mt_live_`. Only production keys are supported — mint one at Settings → API Keys.",
|
|
80
|
+
wwwAuthenticate,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
return { ok: true, apiKey: candidate, source };
|
|
84
|
+
}
|
|
85
|
+
/** Extract a bearer token from an `Authorization` header value, or `null` if absent/malformed. */
|
|
86
|
+
export function parseBearerHeader(value) {
|
|
87
|
+
const match = /^Bearer\s+(.+)$/i.exec(value.trim());
|
|
88
|
+
if (!match)
|
|
89
|
+
return null;
|
|
90
|
+
const token = match[1]?.trim() ?? "";
|
|
91
|
+
return token.length > 0 ? token : null;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* MCP 2025-11-25 §Authorization / RFC 9728: 401 responses on the HTTP transport
|
|
95
|
+
* MUST advertise where the client can find Protected Resource Metadata. Clients
|
|
96
|
+
* use this to discover how to authenticate (static bearer today; OAuth in a
|
|
97
|
+
* future version).
|
|
98
|
+
*/
|
|
99
|
+
export function buildWwwAuthenticateHeader(protectedResourceMetadataUrl) {
|
|
100
|
+
return `Bearer realm="meertrack", resource_metadata="${protectedResourceMetadataUrl}"`;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Redact every `mt_live_…` token in `value`. Apply to any string before
|
|
104
|
+
* writing it to logs or error messages. Also redacts `Bearer mt_live_…`.
|
|
105
|
+
*/
|
|
106
|
+
export function redactApiKeys(value) {
|
|
107
|
+
return value.replace(/mt_live_[A-Za-z0-9_-]+/g, "mt_live_***");
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { ActivityDetailResponse, ActivityListResponse, ChangeType, CompetitorDetailListResponse, CompetitorListResponse, CompetitorOverviewResponse, DigestLatestResponse, DigestListResponse, DigestResponse, MeResponse, SectionSlug } from "./types.js";
|
|
2
|
+
export declare const DEFAULT_BASE_URL = "https://api.meertrack.com/v1";
|
|
3
|
+
/** Resolve the upstream base URL, honoring `MEERTRACK_API_BASE_URL` for staging/local. */
|
|
4
|
+
export declare function resolveBaseUrl(override?: string): string;
|
|
5
|
+
export interface MeertrackClientOptions {
|
|
6
|
+
baseUrl?: string;
|
|
7
|
+
apiKey: string;
|
|
8
|
+
/** Test/DI seam — defaults to global fetch. */
|
|
9
|
+
fetchImpl?: typeof fetch;
|
|
10
|
+
/** Optional override for the User-Agent suffix (tests). */
|
|
11
|
+
userAgent?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Fired after every upstream response (success or failure) with the parsed
|
|
14
|
+
* `X-Request-Id` header. Used by the HTTP transport to fold the upstream
|
|
15
|
+
* trace ID into the per-request structured log line so a Fly log entry can
|
|
16
|
+
* be cross-referenced against Meertrack backend logs.
|
|
17
|
+
*/
|
|
18
|
+
onUpstreamResponse?: (info: {
|
|
19
|
+
status: number;
|
|
20
|
+
requestId: string | null;
|
|
21
|
+
}) => void;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Typed error thrown for every non-2xx upstream response. `code` reflects the
|
|
25
|
+
* upstream error envelope's `error.code` when present, else a generic fallback
|
|
26
|
+
* (`http_<status>`, `transport_error`, `invalid_response`).
|
|
27
|
+
*/
|
|
28
|
+
export declare class MeertrackApiError extends Error {
|
|
29
|
+
readonly status: number;
|
|
30
|
+
readonly code: string;
|
|
31
|
+
readonly rateLimitReset?: number;
|
|
32
|
+
constructor(params: {
|
|
33
|
+
status: number;
|
|
34
|
+
code: string;
|
|
35
|
+
message: string;
|
|
36
|
+
rateLimitReset?: number;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
export interface ListActivityParams {
|
|
40
|
+
competitor_ids?: string[];
|
|
41
|
+
sections?: SectionSlug[];
|
|
42
|
+
change_types?: ChangeType[];
|
|
43
|
+
from?: string;
|
|
44
|
+
to?: string;
|
|
45
|
+
limit?: number;
|
|
46
|
+
cursor?: string;
|
|
47
|
+
}
|
|
48
|
+
export interface ListCompetitorsParams {
|
|
49
|
+
active?: boolean;
|
|
50
|
+
ids?: string[];
|
|
51
|
+
expand?: "full";
|
|
52
|
+
}
|
|
53
|
+
export interface ListDigestsParams {
|
|
54
|
+
competitor_id?: string[];
|
|
55
|
+
from?: string;
|
|
56
|
+
to?: string;
|
|
57
|
+
limit?: number;
|
|
58
|
+
cursor?: string;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Thin typed wrapper over `api.meertrack.com/v1`. Each method is a 1:1 shadow
|
|
62
|
+
* of its endpoint. No retry/backoff in v1 — a 429 throws with the reset
|
|
63
|
+
* epoch and the caller (the MCP tool layer) decides what to tell the agent.
|
|
64
|
+
*/
|
|
65
|
+
export declare class MeertrackClient {
|
|
66
|
+
readonly baseUrl: string;
|
|
67
|
+
readonly apiKey: string;
|
|
68
|
+
private readonly fetchImpl;
|
|
69
|
+
private readonly userAgent;
|
|
70
|
+
private readonly onUpstreamResponse?;
|
|
71
|
+
constructor(opts: MeertrackClientOptions);
|
|
72
|
+
me(): Promise<MeResponse>;
|
|
73
|
+
listCompetitors(params?: ListCompetitorsParams): Promise<CompetitorListResponse | CompetitorDetailListResponse>;
|
|
74
|
+
getCompetitor(id: string): Promise<CompetitorOverviewResponse>;
|
|
75
|
+
listActivity(params?: ListActivityParams): Promise<ActivityListResponse>;
|
|
76
|
+
getActivityItem(rowUuid: string): Promise<ActivityDetailResponse>;
|
|
77
|
+
listDigests(params?: ListDigestsParams): Promise<DigestListResponse>;
|
|
78
|
+
listLatestDigests(): Promise<DigestLatestResponse>;
|
|
79
|
+
getDigest(id: string): Promise<DigestResponse>;
|
|
80
|
+
private request;
|
|
81
|
+
}
|
|
82
|
+
/** Parse an upstream non-2xx into a `MeertrackApiError`. Exported for tests. */
|
|
83
|
+
export declare function toApiError(response: Response): Promise<MeertrackApiError>;
|
|
84
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|