@lobstack-ai/mcp 0.1.0 → 0.1.2
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 +23 -13
- package/dist/server.d.ts +1 -1
- package/dist/server.js +9 -9
- package/dist/tools/spend.d.ts +11 -8
- package/dist/tools/spend.js +11 -8
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# @lobstack-ai/mcp
|
|
2
2
|
|
|
3
|
-
An MCP server for the [Lobstack](https://www.lobstack.ai)
|
|
4
|
-
|
|
5
|
-
served it, how many tokens,
|
|
3
|
+
An MCP server for the [Lobstack API](https://www.lobstack.ai/api-platform). One
|
|
4
|
+
API key reaches [26 models across 9 providers](https://www.lobstack.ai/models), and
|
|
5
|
+
every call comes back with a receipt: which model served it, how many tokens,
|
|
6
|
+
what it cost.
|
|
6
7
|
|
|
7
8
|
Works in Claude Desktop, Claude Code, Cursor, Zed, or anything else that speaks
|
|
8
9
|
the Model Context Protocol over stdio.
|
|
@@ -118,8 +119,17 @@ against.
|
|
|
118
119
|
The catalogue: model key, label, tier, provider, context window, and USD per
|
|
119
120
|
million input and output tokens. Optional `tier` and `provider` filters.
|
|
120
121
|
|
|
121
|
-
|
|
122
|
-
|
|
122
|
+
**The first entry is `auto` — Nex 1, the router.** It carries `tier: "router"`
|
|
123
|
+
and a null price on purpose: its cost is whichever model it picks, which is not
|
|
124
|
+
knowable until the request is scored. That is the one null in this list that is
|
|
125
|
+
not a gap.
|
|
126
|
+
|
|
127
|
+
Every other null price is. A model the registry cannot price comes back with
|
|
128
|
+
`null` and renders as `—`, and it is not free — a zero there would be a claim
|
|
129
|
+
that a real charge did not happen.
|
|
130
|
+
|
|
131
|
+
The full catalogue with rates is also public, no key required, at
|
|
132
|
+
<https://www.lobstack.ai/models>.
|
|
123
133
|
|
|
124
134
|
### `lobstack_chat`
|
|
125
135
|
|
|
@@ -129,7 +139,7 @@ Sends a prompt or a conversation and returns the reply plus the receipt.
|
|
|
129
139
|
| --- | --- | --- |
|
|
130
140
|
| `prompt` | string | A single user message. Use this **or** `messages`. |
|
|
131
141
|
| `messages` | array | `{ role, content }`, OpenAI-shaped. Use this **or** `prompt`. |
|
|
132
|
-
| `model` | string | Defaults to `auto` — the router picks the cheapest capable model. |
|
|
142
|
+
| `model` | string | Defaults to `auto` — **Nex 1**, the router, picks the cheapest capable model. |
|
|
133
143
|
| `system` | string | Prepended to the conversation. |
|
|
134
144
|
| `max_tokens` | integer | Cap on the reply. |
|
|
135
145
|
| `temperature` | number | Some models do not accept it; the receipt says when it was dropped. |
|
|
@@ -171,14 +181,14 @@ It also reports `unpriced_requests` and sets `is_floor`. The endpoint sums an
|
|
|
171
181
|
unpriced row as zero — the only arithmetic available — so a total that includes
|
|
172
182
|
one is a lower bound, not a total, and this tool says which.
|
|
173
183
|
|
|
174
|
-
It does **not** report a savings total.
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
184
|
+
It does **not** report a savings total. Savings are reported per call, by
|
|
185
|
+
`lobstack_chat`, where the API sends them with the reason attached. Adding them
|
|
186
|
+
up client-side would mean pricing the org's tokens against a copy of the rate
|
|
187
|
+
card, and a copy drifts.
|
|
178
188
|
|
|
179
189
|
## Two rules about the numbers
|
|
180
190
|
|
|
181
|
-
**A null cost is not zero.** `cost_usd: null` means the
|
|
191
|
+
**A null cost is not zero.** `cost_usd: null` means the API could not price
|
|
182
192
|
the call. It renders as `unpriced`, never as `$0.00`. Rendering it as `$0.00`
|
|
183
193
|
writes off a real charge, and that exact substitution ran for three months in
|
|
184
194
|
production.
|
|
@@ -198,11 +208,11 @@ production.
|
|
|
198
208
|
| variable | default | notes |
|
|
199
209
|
| --- | --- | --- |
|
|
200
210
|
| `LOBSTACK_API_KEY` | none | Read once at startup. Never logged, never in a tool result. |
|
|
201
|
-
| `LOBSTACK_BASE_URL` | `https://www.lobstack.ai/api/gateway/v1` |
|
|
211
|
+
| `LOBSTACK_BASE_URL` | `https://www.lobstack.ai/api/gateway/v1` | The Lobstack API base URL. Change it only to point at a staging deployment. |
|
|
202
212
|
|
|
203
213
|
**Use `www`, not the bare apex.** `lobstack.ai` redirects to `www.lobstack.ai`,
|
|
204
214
|
and [RFC 9110 §15.4](https://www.rfc-editor.org/rfc/rfc9110#section-15.4)
|
|
205
|
-
requires a client to drop `Authorization` across a host change — so the
|
|
215
|
+
requires a client to drop `Authorization` across a host change — so the API
|
|
206
216
|
answers a perfectly good key with "missing credentials". This server rewrites
|
|
207
217
|
the apex and tells you it did, and refuses to follow any other 3xx rather than
|
|
208
218
|
send a request whose credential has been stripped.
|
package/dist/server.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The MCP server: four tools over the Lobstack
|
|
2
|
+
* The MCP server: four tools over the Lobstack API.
|
|
3
3
|
*
|
|
4
4
|
* Exported as a factory rather than wired straight to stdio so the tests can
|
|
5
5
|
* drive it over an in-memory transport with a real MCP client on the other end,
|
package/dist/server.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The MCP server: four tools over the Lobstack
|
|
2
|
+
* The MCP server: four tools over the Lobstack API.
|
|
3
3
|
*
|
|
4
4
|
* Exported as a factory rather than wired straight to stdio so the tests can
|
|
5
5
|
* drive it over an in-memory transport with a real MCP client on the other end,
|
|
@@ -48,7 +48,7 @@ export const SERVER_VERSION = (() => {
|
|
|
48
48
|
return "0.0.0";
|
|
49
49
|
}
|
|
50
50
|
})();
|
|
51
|
-
const INSTRUCTIONS = `Lobstack is a metered LLM gateway: one key reaches every major model, and every call
|
|
51
|
+
const INSTRUCTIONS = `The Lobstack API is a metered LLM gateway: one key reaches every major model, and every call
|
|
52
52
|
comes back with a receipt saying which model served it and what it cost.
|
|
53
53
|
|
|
54
54
|
- lobstack_route_preview needs NO API key. It scores a prompt against the same
|
|
@@ -56,7 +56,7 @@ comes back with a receipt saying which model served it and what it cost.
|
|
|
56
56
|
estimated cost. Use it to choose a model, or to show what routing does.
|
|
57
57
|
- lobstack_chat runs the completion. Send model "auto" to let the router pick
|
|
58
58
|
the cheapest model that can handle the prompt.
|
|
59
|
-
- Costs are reported as the
|
|
59
|
+
- Costs are reported as the API priced them. A null cost means the API
|
|
60
60
|
could not price the call — it does not mean the call was free.
|
|
61
61
|
- A saving labelled "saved" is like-for-like: the caller named a model and got
|
|
62
62
|
something cheaper. A saving labelled "vs ceiling" is measured against the most
|
|
@@ -69,23 +69,23 @@ export function createServer(options = {}) {
|
|
|
69
69
|
title: "Preview routing and cost",
|
|
70
70
|
description: "Score a prompt and report which model the Lobstack router would serve it with, and what that would cost. " +
|
|
71
71
|
"Runs no inference, spends nothing, and NEEDS NO API KEY — use it to pick a model before calling lobstack_chat, " +
|
|
72
|
-
"or to show what the
|
|
72
|
+
"or to show what the Lobstack API does on a machine with no key configured. Token counts are estimates; the billed " +
|
|
73
73
|
"figure comes from the provider's usage block on the real call.",
|
|
74
74
|
inputSchema: routePreviewInput,
|
|
75
75
|
outputSchema: routePreviewOutput,
|
|
76
76
|
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
77
77
|
}, async (args) => runRoutePreview(cfg, args));
|
|
78
78
|
server.registerTool("lobstack_models", {
|
|
79
|
-
title: "List
|
|
80
|
-
description: "The models the Lobstack
|
|
79
|
+
title: "List Lobstack API models",
|
|
80
|
+
description: "The models the Lobstack API serves, with capability tier, provider, context window and USD price per " +
|
|
81
81
|
"million input and output tokens. A model the registry cannot price shows a null price, not zero.",
|
|
82
82
|
inputSchema: modelsInput,
|
|
83
83
|
outputSchema: modelsOutput,
|
|
84
84
|
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
85
85
|
}, async (args) => runModels(cfg, args));
|
|
86
86
|
server.registerTool("lobstack_chat", {
|
|
87
|
-
title: "Chat through the
|
|
88
|
-
description: "Send a prompt or conversation through the Lobstack
|
|
87
|
+
title: "Chat through the Lobstack API",
|
|
88
|
+
description: "Send a prompt or conversation through the Lobstack API and get the reply plus a receipt: the model that " +
|
|
89
89
|
'actually served it, token counts, USD cost, and any saving with the reason it may be claimed. Model "auto" ' +
|
|
90
90
|
"(the default) lets the router pick the cheapest model that can handle the prompt. This call spends money " +
|
|
91
91
|
"against the configured key's allowance.",
|
|
@@ -95,7 +95,7 @@ export function createServer(options = {}) {
|
|
|
95
95
|
}, async (args) => runChat(cfg, args));
|
|
96
96
|
server.registerTool("lobstack_spend", {
|
|
97
97
|
title: "Read spend and usage",
|
|
98
|
-
description: "What this organization has spent through the
|
|
98
|
+
description: "What this organization has spent through the Lobstack API over a range, broken down by day, model, key or agent, " +
|
|
99
99
|
"with request counts, tokens, error counts and latency percentiles. Requires an API key with the usage:read " +
|
|
100
100
|
"scope. Reports how many requests could not be priced, because a total that includes them is a floor.",
|
|
101
101
|
inputSchema: spendInput,
|
package/dist/tools/spend.d.ts
CHANGED
|
@@ -17,15 +17,18 @@
|
|
|
17
17
|
* `truncated` — the endpoint pages to a cap. When it binds, the sums are a
|
|
18
18
|
* floor for a second, independent reason.
|
|
19
19
|
*
|
|
20
|
-
* WHAT THIS TOOL DOES NOT REPORT
|
|
20
|
+
* WHAT THIS TOOL DOES NOT REPORT (YET)
|
|
21
21
|
*
|
|
22
|
-
* A savings total. `/api/v1/usage`
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
22
|
+
* A savings total. `/api/v1/usage` now computes one, server-side from the
|
|
23
|
+
* priced ledger, as a top-level `savings` object split in two and never
|
|
24
|
+
* summed: `named` (a measured saving against a model the caller asked for) and
|
|
25
|
+
* `plan_ceiling` (a counterfactual against the priciest model the plan allows,
|
|
26
|
+
* when the caller sent `auto`). `savings` is null when the ledger could not be
|
|
27
|
+
* read. This tool does not read it yet; if it ever does, the two blocks must
|
|
28
|
+
* stay separate and `plan_ceiling` must be labelled as a counterfactual. What
|
|
29
|
+
* it must never do is add up per-call savings client-side from a rate card we
|
|
30
|
+
* hold a copy of. Per-call savings are reported by lobstack_chat, where the
|
|
31
|
+
* API sends them with the reason attached.
|
|
29
32
|
*/
|
|
30
33
|
import { z } from "zod";
|
|
31
34
|
import type { Config } from "../config.js";
|
package/dist/tools/spend.js
CHANGED
|
@@ -17,15 +17,18 @@
|
|
|
17
17
|
* `truncated` — the endpoint pages to a cap. When it binds, the sums are a
|
|
18
18
|
* floor for a second, independent reason.
|
|
19
19
|
*
|
|
20
|
-
* WHAT THIS TOOL DOES NOT REPORT
|
|
20
|
+
* WHAT THIS TOOL DOES NOT REPORT (YET)
|
|
21
21
|
*
|
|
22
|
-
* A savings total. `/api/v1/usage`
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
22
|
+
* A savings total. `/api/v1/usage` now computes one, server-side from the
|
|
23
|
+
* priced ledger, as a top-level `savings` object split in two and never
|
|
24
|
+
* summed: `named` (a measured saving against a model the caller asked for) and
|
|
25
|
+
* `plan_ceiling` (a counterfactual against the priciest model the plan allows,
|
|
26
|
+
* when the caller sent `auto`). `savings` is null when the ledger could not be
|
|
27
|
+
* read. This tool does not read it yet; if it ever does, the two blocks must
|
|
28
|
+
* stay separate and `plan_ceiling` must be labelled as a counterfactual. What
|
|
29
|
+
* it must never do is add up per-call savings client-side from a rate card we
|
|
30
|
+
* hold a copy of. Per-call savings are reported by lobstack_chat, where the
|
|
31
|
+
* API sends them with the reason attached.
|
|
29
32
|
*/
|
|
30
33
|
import { z } from "zod";
|
|
31
34
|
import { apiUrl } from "../config.js";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobstack-ai/mcp",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "The Lobstack
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "The Lobstack API as an MCP server: one key across many model providers, and what each call cost.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"lobstack-mcp": "./dist/index.js"
|
|
@@ -38,7 +38,8 @@
|
|
|
38
38
|
"anthropic",
|
|
39
39
|
"claude",
|
|
40
40
|
"cursor",
|
|
41
|
-
"lobstack"
|
|
41
|
+
"lobstack",
|
|
42
|
+
"lobstack-api"
|
|
42
43
|
],
|
|
43
44
|
"license": "MIT",
|
|
44
45
|
"author": "Lobstack",
|
|
@@ -49,7 +50,7 @@
|
|
|
49
50
|
"bugs": {
|
|
50
51
|
"url": "https://github.com/Lobstack-ai/lobstack-mcp/issues"
|
|
51
52
|
},
|
|
52
|
-
"homepage": "https://
|
|
53
|
+
"homepage": "https://www.lobstack.ai/docs/mcp",
|
|
53
54
|
"dependencies": {
|
|
54
55
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
55
56
|
"zod": "^3.25.76"
|