fastr-mcp-suite 1.0.0 → 1.2.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.
Files changed (55) hide show
  1. package/LICENSE.md +19 -103
  2. package/README.md +61 -45
  3. package/dist/auth.d.ts +16 -27
  4. package/dist/auth.d.ts.map +1 -1
  5. package/dist/auth.js +15 -138
  6. package/dist/auth.js.map +1 -1
  7. package/dist/cards/fluentcart/tools.d.ts +1 -2
  8. package/dist/cards/fluentcart/tools.d.ts.map +1 -1
  9. package/dist/cards/fluentcart/tools.js +109 -53
  10. package/dist/cards/fluentcart/tools.js.map +1 -1
  11. package/dist/cards/lemonsqueezy/tools.d.ts +1 -2
  12. package/dist/cards/lemonsqueezy/tools.d.ts.map +1 -1
  13. package/dist/cards/lemonsqueezy/tools.js +110 -13
  14. package/dist/cards/lemonsqueezy/tools.js.map +1 -1
  15. package/dist/http.js +9 -6
  16. package/dist/http.js.map +1 -1
  17. package/dist/index.js +2 -2
  18. package/dist/index.js.map +1 -1
  19. package/dist/reference-reader.d.ts +38 -0
  20. package/dist/reference-reader.d.ts.map +1 -0
  21. package/dist/reference-reader.js +140 -0
  22. package/dist/reference-reader.js.map +1 -0
  23. package/dist/server.d.ts.map +1 -1
  24. package/dist/server.js +65 -38
  25. package/dist/server.js.map +1 -1
  26. package/dist/skills/fastr-mcp-suite/SKILL.md +273 -0
  27. package/dist/skills/fluentcart-developer/SKILL.md +28 -5
  28. package/dist/skills/fluentcart-developer/examples/sample-custom-addon/fluentcart-custom-addon.php +0 -1
  29. package/dist/skills/fluentcart-developer/examples/sample-custom-payment-gateway/fluentcart-custom-gateway-example.php +0 -1
  30. package/dist/skills/fluentcart-developer/examples/sample-shipping-carrier/fluentcart-custom-shipping-carrier.php +0 -1
  31. package/dist/skills/fluentcart-developer/references/action-hooks-admin-templates.md +2 -2
  32. package/dist/skills/fluentcart-developer/references/filter-hooks-customers-subscriptions.md +3 -3
  33. package/dist/skills/fluentcart-developer/references/filter-hooks-orders-payments.md +1 -1
  34. package/dist/skills/fluentcart-developer/references/hooks-complete-index.md +834 -0
  35. package/dist/skills/fluentcart-developer/references/models-complete-index.md +912 -0
  36. package/dist/skills/fluentcart-developer/references/paddle-gateway-case-study.md +27 -21
  37. package/dist/skills/fluentcart-developer/references/rest-api-checkout.md +15 -13
  38. package/dist/skills/fluentcart-developer/references/rest-api-coupons.md +69 -62
  39. package/dist/skills/fluentcart-developer/references/rest-api-orders.md +221 -0
  40. package/dist/skills/fluentcart-developer/references/rest-api-products.md +163 -29
  41. package/dist/skills/fluentcart-developer/references/rest-api-subscriptions.md +332 -0
  42. package/dist/skills/lemonsqueezy-developer/SKILL.md +70 -57
  43. package/dist/skills/lemonsqueezy-developer/references/api-reference.md +591 -585
  44. package/dist/skills/lemonsqueezy-developer/references/checkouts-and-orders.md +135 -129
  45. package/dist/skills/lemonsqueezy-developer/references/developer-guide.md +60 -53
  46. package/dist/skills/lemonsqueezy-developer/references/go-live-guide.md +94 -87
  47. package/dist/skills/lemonsqueezy-developer/references/license-keys-and-activation.md +97 -91
  48. package/dist/skills/lemonsqueezy-developer/references/subscriptions-lifecycle.md +85 -79
  49. package/dist/skills/lemonsqueezy-developer/references/webhooks-and-security.md +152 -143
  50. package/dist/version.d.ts +13 -0
  51. package/dist/version.d.ts.map +1 -0
  52. package/dist/version.js +13 -0
  53. package/dist/version.js.map +1 -0
  54. package/package.json +2 -2
  55. package/smithery.config.json +2 -9
package/LICENSE.md CHANGED
@@ -1,110 +1,26 @@
1
- # License — Fastr MCP Suite (server implementation)
1
+ # MIT License
2
2
 
3
- The `server/` directory is licensed under the **Business Source License 1.1**
4
- on the terms below. The skill content under the repository's `skills/` directory
5
- is a separate work, licensed MIT, and is not part of the Licensed Work.
3
+ Copyright (c) 2026 Atif Jubaer (Fastrsoft)
6
4
 
7
- ---
8
-
9
- Business Source License 1.1
10
-
11
- License text copyright (c) 2024 MariaDB plc, All Rights Reserved.
12
- "Business Source License" is a trademark of MariaDB plc.
13
-
14
- Parameters
15
-
16
- Licensor: Atif Jubaer (Fastrsoft)
17
- Licensed Work: The Fastr MCP Suite server implementation — the contents of
18
- the `server/` directory of this repository, including its
19
- source code, build scripts, configuration and any bundled
20
- copies of the skill documents. The Licensed Work is
21
- (c) 2026 Atif Jubaer (Fastrsoft).
22
- Additional Use Grant: You may make production use of the Licensed Work, provided
23
- Your use does not include offering the Licensed Work to third
24
- parties on a hosted or embedded basis in order to compete with
25
- the Licensor's paid version(s) of the Licensed Work, and does
26
- not include reselling, sublicensing or private-labelling the
27
- Licensed Work as a paid MCP server, paid distribution or
28
- commercial hosted service.
29
- Change Date: Four years from the date each version of the Licensed Work is
30
- first publicly distributed.
31
- Change License: MIT License
32
-
33
- Terms
34
-
35
- The Licensor hereby grants you the right to copy, modify, create derivative
36
- works, redistribute, and make non-production use of the Licensed Work. The
37
- Licensor may make an Additional Use Grant, above, permitting limited production use.
38
-
39
- Effective on the Change Date, or the fourth anniversary of the first publicly
40
- available distribution of a specific version of the Licensed Work under this
41
- License, whichever comes first, the Licensor hereby grants you rights under
42
- the terms of the Change License, and the rights granted in the paragraph
43
- above terminate.
44
-
45
- If your use of the Licensed Work does not comply with the requirements
46
- currently in effect as described in this License, you must purchase a
47
- commercial license from the Licensor, its affiliated entities, or authorized
48
- resellers, or you must refrain from using the Licensed Work.
49
-
50
- All copies of the original and modified Licensed Work, and derivative works
51
- of the Licensed Work, are subject to this License. This License applies
52
- separately for each version of the Licensed Work and the Change Date may vary
53
- for each version of the Licensed Work released by Licensor.
54
-
55
- You must conspicuously display this License on each original or modified copy
56
- of the Licensed Work. If you receive the Licensed Work in original or
57
- modified form from a third party, the terms and conditions set forth in this
58
- License apply to your use of that work.
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:
59
11
 
60
- Any use of the Licensed Work in violation of this License will automatically
61
- terminate your rights under this License for the current and all other
62
- versions of the Licensed Work.
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
63
14
 
64
- This License does not grant you any right in any trademark or logo of
65
- Licensor or its affiliates (provided that you may use a trademark or logo of
66
- Licensor as expressly required by this License).
67
-
68
- TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
69
- AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
70
- EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
71
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
72
- TITLE.
73
- Covenants of Licensor
74
-
75
- In consideration of the right to use this License's text and the "Business Source
76
- License" name and trademark, Licensor covenants to MariaDB, and to all other
77
- recipients of the licensed work to be provided by Licensor:
78
-
79
- To specify as the Change License the GPL Version 2.0 or any later version, or a
80
- license that is compatible with GPL Version 2.0 or a later version, where
81
- "compatible" means that software provided under the Change License can be
82
- included in a program with software provided under GPL Version 2.0 or a later
83
- version. Licensor may specify additional Change Licenses without limitation.
84
-
85
- To either: (a) specify an additional grant of rights to use that does not impose
86
- any additional restriction on the right granted in this License, as the
87
- Additional Use Grant; or (b) insert the text "None".
88
-
89
- To specify a Change Date.
90
-
91
- Not to modify this License in any other way.
92
-
93
- Notice
94
-
95
- The Business Source License (this document, or the "License") is not an Open
96
- Source license. However, the Licensed Work will eventually be made available
97
- under an Open Source License, as stated in this License.
98
-
99
- For more information on the use of the Business Source License for MariaDB
100
- products, please visit the MariaDB Business Source License FAQ
101
- <https://mariadb.com/bsl-faq-mariadb/>. For more information on the use of the
102
- Business Source License generally, please visit the Adopting and Developing
103
- Business Source License FAQ <https://mariadb.com/bsl-faq-adopting/>.
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.
104
22
 
105
23
  ---
106
24
 
107
- ## Commercial licensing
108
-
109
- For paid distribution, resale, private-label or hosted use outside the Additional
110
- Use Grant, contact the Licensor for a commercial license.
25
+ The server and the skill content under `skills/` are both MIT. There is no
26
+ commercial tier, no licence key, and no restriction on hosting a modified copy.
package/README.md CHANGED
@@ -1,11 +1,42 @@
1
1
  # Fastr MCP Suite
2
2
 
3
- One MCP server that ships the Playing Cards — **FluentCart Pro Agent** and **Lemon Squeezy Developer Agent** — as executable tools plus a skills catalog, so an agent pulls only the slice of documentation it needs instead of loading 239 KB of markdown into the context window.
3
+ One MCP server that ships the Playing Cards — **FluentCart Developer Agent** and **Lemon Squeezy Developer Agent** — as executable tools plus a skills catalog, so an agent pulls only the slice of documentation it needs instead of loading 239 KB of markdown into the context window.
4
+
5
+ **Free and MIT-licensed.** All ten tools are registered for every caller on every transport: no licence key, no account, no subscription, no request quota. Nothing in this server validates a purchase, because there is nothing to purchase.
4
6
 
5
7
  Protocol: MCP `2026-07-28` (stateless, per-request `_meta` envelope) with a `2025-11-25` legacy fallback. Transports: `stdio` for local clients, Streamable HTTP for marketplaces and hosted deploys.
6
8
 
7
9
  ## Run it
8
10
 
11
+ ### From npm
12
+
13
+ Published as [`fastr-mcp-suite`](https://www.npmjs.com/package/fastr-mcp-suite) — Node 22+, no clone and no build:
14
+
15
+ ```bash
16
+ npx -y fastr-mcp-suite
17
+ ```
18
+
19
+ Client config (Claude Code / Cursor / Windsurf):
20
+
21
+ ```json
22
+ {
23
+ "mcpServers": {
24
+ "fastr-suite": {
25
+ "command": "npx",
26
+ "args": ["-y", "fastr-mcp-suite"]
27
+ }
28
+ }
29
+ }
30
+ ```
31
+
32
+ ```bash
33
+ claude mcp add fastr-suite -- npx -y fastr-mcp-suite
34
+ ```
35
+
36
+ The npm package ships the stdio entry point only. The Streamable HTTP transport needs the source tree or the Docker image.
37
+
38
+ ### From source
39
+
9
40
  ```bash
10
41
  npm install
11
42
  npm run build # tsc + bundles both skill folders into dist/skills
@@ -14,76 +45,61 @@ node dist/index.js # stdio
14
45
  node dist/http.js # Streamable HTTP on :8080 (POST /mcp, GET /health)
15
46
  ```
16
47
 
17
- Claude Code / Cursor / Windsurf:
48
+ Point a client at the built file:
18
49
 
19
50
  ```json
20
51
  {
21
52
  "mcpServers": {
22
53
  "fastr-suite": {
23
54
  "command": "node",
24
- "args": ["/absolute/path/to/server/dist/index.js"],
25
- "env": { "PRO_LICENSE_KEY": "optional-license-key" }
55
+ "args": ["/absolute/path/to/server/dist/index.js"]
26
56
  }
27
57
  }
28
58
  }
29
59
  ```
30
60
 
31
- ## Tiers
32
-
33
- | Tier | What is registered |
34
- | --- | --- |
35
- | `core` (free) | `ls_search_docs`, `ls_get_schema`, `fc_search_hooks`, `fc_get_db_schema`, `suite_get_pro_info`, plus `skills/list` and `resources/read` for both skills |
36
- | `pro` (paid) | everything above **and** `ls_verify_webhook`, `ls_validate_license`, `fc_generate_payment_gateway_boilerplate` |
61
+ ## Tools
37
62
 
38
- Pro tools are **not registered** on a core session — the schema never reaches the client, so there is nothing to call. `suite_get_pro_info` is the upgrade surface: it always answers with the current tier and what Pro adds.
63
+ Ten tools, all free. `suite_get_info` reports the same list at runtime, scoped by card.
39
64
 
40
- How a tier is decided:
65
+ | Card | Tool | Answers |
66
+ | --- | --- | --- |
67
+ | FluentCart | `fc_search_hooks` | A hook name, when it fires, its arguments |
68
+ | FluentCart | `fc_get_db_schema` | A `wp_fct_*` table, its columns, the Eloquent model |
69
+ | FluentCart | `fc_get_reference` | Any of the 49 reference files, whole or by heading |
70
+ | FluentCart | `fc_generate_payment_gateway_boilerplate` | A complete PHP gateway class, settings schema and webhook entry point |
71
+ | Lemon Squeezy | `ls_search_docs` | Webhook signatures, checkout payloads, subscription states |
72
+ | Lemon Squeezy | `ls_get_schema` | The exact JSON:API body for an endpoint |
73
+ | Lemon Squeezy | `ls_get_reference` | Any of the 7 Lemon Squeezy reference files, whole or by heading |
74
+ | Lemon Squeezy | `ls_verify_webhook` | Timing-safe HMAC-SHA256 check against a raw payload |
75
+ | Lemon Squeezy | `ls_validate_license` | A live licence key, validated against Lemon Squeezy's API |
76
+ | Suite | `suite_get_info` | What this server is, which tools serve which card, and its licence |
41
77
 
42
- - **stdio** — `PRO_LICENSE_KEY` in the environment unlocks Pro. Convenience switch, not a security boundary.
43
- - **HTTP** — every request carries `Authorization: Bearer <token>`:
44
- 1. token in `VALID_LICENSE_KEYS` → Pro (ops/CI seats)
45
- 2. equals `MCPIZE_GATEWAY_SECRET` → Pro (constant-time compare)
46
- 3. equals `AGENSI_GATEWAY_SECRET` → Pro (constant-time compare)
47
- 4. otherwise validated live against `https://api.lemonsqueezy.com/v1/licenses/validate`, cached 10 minutes, active status and store id checked. Any failure fails closed to core.
78
+ The skills catalog is attached as an MCP extension, so clients that understand it also get `skills/list` and `resources/read` over the same 64 files.
48
79
 
49
- Copy [`.env.example`](./.env.example) to `.env` for the HTTP transport.
80
+ `ls_validate_license` is the only tool that reaches the network. It is cached for 60 s, bounded to 32 concurrent calls and times out at 5 s, so a public deploy does not become an unbounded relay into Lemon Squeezy's API.
50
81
 
51
82
  ## Deploy
52
83
 
53
- Docker (build from the **repository root** so the skill folders are in context):
84
+ ### Docker
54
85
 
55
86
  ```bash
56
- docker build -f server/Dockerfile -t fastr-mcp-suite .
57
- docker run -p 8080:8080 --env-file server/.env fastr-mcp-suite
87
+ docker build -t fastr-mcp-suite .
88
+ docker run -p 8080:8080 -e ALLOWED_HOSTS=your-host.example fastr-mcp-suite
58
89
  ```
59
90
 
60
- Works as-is on Railway / Render / Fly.io / MCPize: the image serves `POST /mcp` and answers `GET /health` for the platform healthcheck.
91
+ `ALLOWED_HOSTS` is the only environment variable worth setting: a comma-separated Host allowlist for DNS-rebinding protection. `PORT` overrides `8080`. Nothing else is read.
61
92
 
62
- ### Smithery
93
+ Any host that accepts a long-running HTTP process works — Railway, Render, Fly.io, a VPS. Mount `/health` as the liveness probe: it returns the protocol version, the card list and the licence.
63
94
 
64
- Smithery publishes a **URL**, not a repo manifest — the old `smithery.yaml`/`smithery.json` format is gone. Deploy the image, then register the endpoint:
95
+ ### MCPize
65
96
 
66
- ```bash
67
- npx -y smithery mcp publish "https://<your-host>/mcp" -n <namespace>/fastr-mcp-suite \
68
- --config-schema "$(cat server/smithery.config.json)"
69
- ```
97
+ [`mcpize.yaml`](../mcpize.yaml) at the repository root is the deployment manifest; `npx mcpize deploy` builds and publishes from there. MCPize authenticates callers at its own edge, but that credential no longer changes what the server registers — a caller with or without it sees the same ten tools.
70
98
 
71
- [`smithery.config.json`](./smithery.config.json) maps the user's licence key from the `ls-license-key` header onto upstream `Authorization`, which is exactly what the HTTP transport already reads. The field is optional, so a free user connects straight into the core tier.
99
+ ## Not affiliated
72
100
 
73
- ## Layout
101
+ This is an independent developer tool. It does not connect to a WordPress database, does not modify a FluentCart store, and is not published by either vendor. Documentation in `skills/` is compiled from their public references.
74
102
 
75
- ```
76
- src/
77
- auth.ts tier resolution (stdio env + HTTP license validation)
78
- paths.ts skills folder resolution (bundled dist/skills → repo skills/)
79
- server.ts server factory, catalog attach, Pro info tool
80
- index.ts stdio entry
81
- http.ts Streamable HTTP entry + /health
82
- cards/lemonsqueezy/tools.ts Card 2 tools
83
- cards/fluentcart/tools.ts Card 1 tools
84
- scripts/
85
- copy-skills.mjs bundles skills/* into dist/skills for npm
86
- verify-stdio.mjs end-to-end protocol, tier-gating and era probe
87
- ```
103
+ ## Licence
88
104
 
89
- Skill **content** is MIT and lives in the public repo under `skills/`. This server implementation is BSL-1.1 — see [LICENSE.md](./LICENSE.md).
105
+ MIT — see [`LICENSE.md`](./LICENSE.md). Fork it, host it, adapt it.
package/dist/auth.d.ts CHANGED
@@ -1,31 +1,20 @@
1
- export type Tier = 'core' | 'pro';
2
- export interface AuthContext {
3
- tier: Tier;
4
- userId?: string;
5
- source: 'stdio' | 'lemonsqueezy' | 'mcpize' | 'agensi' | 'none';
6
- /** Human-readable explanation, surfaced by `suite_get_pro_info` and logs. */
7
- reason: string;
8
- }
9
- /**
10
- * Local (stdio) tier resolution.
11
- *
12
- * Setting `PRO_LICENSE_KEY` in the environment unlocks Pro. This is a local
13
- * trust boundary, not a security boundary: anyone who controls the machine can
14
- * set the variable. The paid gate that matters is the HTTP transport, where
15
- * every request is validated server-side. Commercial terms are enforced by the
16
- * BSL-1.1 licence in `server/LICENSE`.
17
- */
18
- export declare function resolveLocalAuth(): AuthContext;
19
1
  /**
20
- * Resolve the tier for one HTTP request.
21
- *
22
- * 1. `VALID_LICENSE_KEYS` allowlist (ops escape hatch, e.g. internal seats).
23
- * 2. MCPize gateway token, checked against `MCPIZE_GATEWAY_SECRET`.
24
- * 3. Agensi gateway token, checked against `AGENSI_GATEWAY_SECRET`.
25
- * 4. Everything else is treated as a Lemon Squeezy licence key and validated live.
2
+ * The suite is free and MIT-licensed: every tool is registered for every caller
3
+ * on every transport. There is no tier to resolve, no licence key to validate,
4
+ * and no outbound call to make before a session can work — so this module no
5
+ * longer authenticates anything.
26
6
  *
27
- * There is deliberately no prefix-based trust: a client cannot mint itself Pro
28
- * by sending a string that starts with `ls_live_`.
7
+ * `AuthContext` survives as a small descriptor of the session. It is what
8
+ * `createServerInstance` receives and what `suite_get_info` reports, which is
9
+ * still useful when diagnosing which transport a client actually reached.
29
10
  */
30
- export declare function authenticateRequest(request?: Request): Promise<AuthContext>;
11
+ export type CardId = 'fluentcart' | 'lemonsqueezy';
12
+ export interface AuthContext {
13
+ /** Always `free`. Kept as a literal so a future gate has one obvious seam. */
14
+ tier: 'free';
15
+ cards: CardId[];
16
+ source: 'stdio' | 'http';
17
+ reason: string;
18
+ }
19
+ export declare function fullAccess(source: 'stdio' | 'http'): AuthContext;
31
20
  //# sourceMappingURL=auth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,KAAK,CAAC;AAElC,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,GAAG,cAAc,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;IAChE,6EAA6E;IAC7E,MAAM,EAAE,MAAM,CAAC;CAChB;AAqCD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,IAAI,WAAW,CAM9C;AAiED;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CAgCjF"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,MAAM,MAAM,GAAG,YAAY,GAAG,cAAc,CAAC;AAInD,MAAM,WAAW,WAAW;IAC1B,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,WAAW,CAOhE"}
package/dist/auth.js CHANGED
@@ -1,143 +1,20 @@
1
- import crypto from 'node:crypto';
2
- const LS_VALIDATE_URL = 'https://api.lemonsqueezy.com/v1/licenses/validate';
3
- const LICENSE_CACHE_TTL_MS = 10 * 60 * 1000;
4
- /** token -> resolution, so a busy client does not hit Lemon Squeezy on every request. */
5
- const licenseCache = new Map();
6
- /** Unauthenticated callers can send arbitrary tokens, so the cache is bounded. */
7
- const LICENSE_CACHE_MAX = 5000;
8
- /** A failed validation is cached briefly: it bounds upstream load during an outage. */
9
- const NEGATIVE_CACHE_TTL_MS = 30 * 1000;
10
- /** Beyond this many concurrent validations the answer is "core" without calling out. */
11
- const MAX_INFLIGHT_VALIDATIONS = 64;
12
- let inFlightValidations = 0;
13
- function cacheResolution(token, tier, ttlMs) {
14
- if (licenseCache.size >= LICENSE_CACHE_MAX) {
15
- // Map iteration is insertion-ordered, so the first key is the oldest entry.
16
- const oldest = licenseCache.keys().next().value;
17
- if (oldest !== undefined)
18
- licenseCache.delete(oldest);
19
- }
20
- licenseCache.set(token, { tier, expiresAt: Date.now() + ttlMs });
21
- }
22
- function timingSafeEqualStrings(a, b) {
23
- const left = Buffer.from(a, 'utf8');
24
- const right = Buffer.from(b, 'utf8');
25
- return left.length === right.length && crypto.timingSafeEqual(left, right);
26
- }
27
- function bearerToken(authorization) {
28
- if (!authorization)
29
- return '';
30
- return authorization.replace(/^Bearer\s+/i, '').trim();
31
- }
32
1
  /**
33
- * Local (stdio) tier resolution.
34
- *
35
- * Setting `PRO_LICENSE_KEY` in the environment unlocks Pro. This is a local
36
- * trust boundary, not a security boundary: anyone who controls the machine can
37
- * set the variable. The paid gate that matters is the HTTP transport, where
38
- * every request is validated server-side. Commercial terms are enforced by the
39
- * BSL-1.1 licence in `server/LICENSE`.
40
- */
41
- export function resolveLocalAuth() {
42
- const key = process.env.PRO_LICENSE_KEY?.trim();
43
- if (key && key.length >= 16) {
44
- return { tier: 'pro', source: 'stdio', reason: 'PRO_LICENSE_KEY present in environment' };
45
- }
46
- return { tier: 'core', source: 'stdio', reason: 'stdio session without PRO_LICENSE_KEY' };
47
- }
48
- /**
49
- * Validate a licence key against Lemon Squeezy. Results are cached for 10
50
- * minutes. Any network or parsing failure fails closed (core tier).
51
- */
52
- async function validateLicenseKey(licenseKey) {
53
- const cached = licenseCache.get(licenseKey);
54
- if (cached && cached.expiresAt > Date.now()) {
55
- return {
56
- tier: cached.tier,
57
- source: 'lemonsqueezy',
58
- reason: cached.tier === 'pro' ? 'license key valid (cached)' : 'license key invalid (cached)'
59
- };
60
- }
61
- // Any caller can present an unknown token. Without this cap, a burst of junk
62
- // tokens becomes a burst of 5-second outbound requests.
63
- if (inFlightValidations >= MAX_INFLIGHT_VALIDATIONS) {
64
- return {
65
- tier: 'core',
66
- source: 'lemonsqueezy',
67
- reason: 'license validation concurrency limit reached'
68
- };
69
- }
70
- inFlightValidations += 1;
71
- try {
72
- const res = await fetch(LS_VALIDATE_URL, {
73
- method: 'POST',
74
- headers: { 'Content-Type': 'application/x-www-form-urlencoded', Accept: 'application/json' },
75
- body: new URLSearchParams({ license_key: licenseKey }),
76
- signal: AbortSignal.timeout(5000)
77
- });
78
- const data = (await res.json());
79
- const expectedStore = process.env.LS_STORE_ID;
80
- const storeMatches = !expectedStore || String(data.license_key?.store_id ?? '') === String(expectedStore);
81
- const active = data.valid === true && data.license_key?.status === 'active' && storeMatches;
82
- const tier = active ? 'pro' : 'core';
83
- cacheResolution(licenseKey, tier, LICENSE_CACHE_TTL_MS);
84
- return {
85
- tier,
86
- source: 'lemonsqueezy',
87
- reason: active ? 'active Lemon Squeezy license' : 'license inactive, unknown, or wrong store'
88
- };
89
- }
90
- catch (err) {
91
- // Fail closed, but remember the failure for a moment: an outage must not
92
- // turn every request from every client into another outbound attempt.
93
- cacheResolution(licenseKey, 'core', NEGATIVE_CACHE_TTL_MS);
94
- return {
95
- tier: 'core',
96
- source: 'lemonsqueezy',
97
- reason: `license validation unavailable: ${err.message}`
98
- };
99
- }
100
- finally {
101
- inFlightValidations -= 1;
102
- }
103
- }
104
- /**
105
- * Resolve the tier for one HTTP request.
106
- *
107
- * 1. `VALID_LICENSE_KEYS` allowlist (ops escape hatch, e.g. internal seats).
108
- * 2. MCPize gateway token, checked against `MCPIZE_GATEWAY_SECRET`.
109
- * 3. Agensi gateway token, checked against `AGENSI_GATEWAY_SECRET`.
110
- * 4. Everything else is treated as a Lemon Squeezy licence key and validated live.
2
+ * The suite is free and MIT-licensed: every tool is registered for every caller
3
+ * on every transport. There is no tier to resolve, no licence key to validate,
4
+ * and no outbound call to make before a session can work — so this module no
5
+ * longer authenticates anything.
111
6
  *
112
- * There is deliberately no prefix-based trust: a client cannot mint itself Pro
113
- * by sending a string that starts with `ls_live_`.
7
+ * `AuthContext` survives as a small descriptor of the session. It is what
8
+ * `createServerInstance` receives and what `suite_get_info` reports, which is
9
+ * still useful when diagnosing which transport a client actually reached.
114
10
  */
115
- export async function authenticateRequest(request) {
116
- const token = bearerToken(request?.headers.get('authorization'));
117
- if (!token) {
118
- return { tier: 'core', source: 'none', reason: 'no Authorization header' };
119
- }
120
- const allowlist = (process.env.VALID_LICENSE_KEYS || '')
121
- .split(',')
122
- .map(k => k.trim())
123
- .filter(Boolean);
124
- // Compared in constant time like the gateway secrets, and without stopping at
125
- // the first match so the loop's duration does not reveal an entry's position.
126
- let allowlisted = false;
127
- for (const candidate of allowlist) {
128
- allowlisted = timingSafeEqualStrings(token, candidate) || allowlisted;
129
- }
130
- if (allowlisted) {
131
- return { tier: 'pro', source: 'lemonsqueezy', reason: 'token in VALID_LICENSE_KEYS allowlist' };
132
- }
133
- const mcpizeSecret = process.env.MCPIZE_GATEWAY_SECRET?.trim();
134
- if (mcpizeSecret && timingSafeEqualStrings(token, mcpizeSecret)) {
135
- return { tier: 'pro', source: 'mcpize', reason: 'MCPize gateway secret matched' };
136
- }
137
- const agensiSecret = process.env.AGENSI_GATEWAY_SECRET?.trim();
138
- if (agensiSecret && timingSafeEqualStrings(token, agensiSecret)) {
139
- return { tier: 'pro', source: 'agensi', reason: 'Agensi gateway secret matched' };
140
- }
141
- return validateLicenseKey(token);
11
+ const ALL_CARDS = ['fluentcart', 'lemonsqueezy'];
12
+ export function fullAccess(source) {
13
+ return {
14
+ tier: 'free',
15
+ cards: [...ALL_CARDS],
16
+ source,
17
+ reason: 'the whole suite is free — no licence key, account, or purchase required'
18
+ };
142
19
  }
143
20
  //# sourceMappingURL=auth.js.map
package/dist/auth.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,MAAM,SAAS,GAAsB,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;AAUpE,MAAM,UAAU,UAAU,CAAC,MAAwB;IACjD,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,CAAC,GAAG,SAAS,CAAC;QACrB,MAAM;QACN,MAAM,EAAE,yEAAyE;KAClF,CAAC;AACJ,CAAC"}
@@ -1,4 +1,3 @@
1
1
  import type { McpServer } from '@modelcontextprotocol/server';
2
- import type { AuthContext } from '../../auth.js';
3
- export declare function registerFluentCartTools(server: McpServer, auth: AuthContext): void;
2
+ export declare function registerFluentCartTools(server: McpServer): void;
4
3
  //# sourceMappingURL=tools.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/cards/fluentcart/tools.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAE9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAGjD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI,CAoKlF"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/cards/fluentcart/tools.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAK9D,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAuO/D"}