@lynq/lynq 0.3.0 → 0.5.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 (54) hide show
  1. package/README.md +88 -12
  2. package/dist/adapters/express.d.ts +7 -2
  3. package/dist/adapters/express.mjs +2 -2
  4. package/dist/adapters/hono.d.ts +7 -2
  5. package/dist/adapters/hono.mjs +1 -1
  6. package/dist/chunk-BVDKAIOU.mjs +1 -0
  7. package/dist/chunk-INAAPNKG.mjs +1 -0
  8. package/dist/chunk-L7SD7KKW.mjs +1 -0
  9. package/dist/chunk-OJJZGR4B.mjs +170 -0
  10. package/dist/chunk-OYHVJKUP.mjs +1 -0
  11. package/dist/chunk-SPZY5GJA.mjs +1 -0
  12. package/dist/index.d.ts +5 -7
  13. package/dist/index.mjs +1 -1
  14. package/dist/middleware/auth.d.ts +6 -8
  15. package/dist/middleware/auth.mjs +1 -1
  16. package/dist/middleware/bearer.d.ts +19 -0
  17. package/dist/middleware/bearer.mjs +1 -0
  18. package/dist/middleware/combine.d.ts +12 -0
  19. package/dist/middleware/combine.mjs +1 -0
  20. package/dist/middleware/credentials.d.ts +19 -0
  21. package/dist/middleware/credentials.mjs +1 -0
  22. package/dist/middleware/crypto.d.ts +64 -0
  23. package/dist/middleware/crypto.mjs +2 -0
  24. package/dist/middleware/github.d.ts +54 -0
  25. package/dist/middleware/github.mjs +2 -0
  26. package/dist/middleware/google.d.ts +55 -0
  27. package/dist/middleware/google.mjs +2 -0
  28. package/dist/middleware/guard.d.ts +15 -0
  29. package/dist/middleware/guard.mjs +1 -0
  30. package/dist/middleware/jwt.d.ts +27 -0
  31. package/dist/middleware/jwt.mjs +1 -0
  32. package/dist/middleware/logger.d.ts +11 -0
  33. package/dist/middleware/logger.mjs +1 -0
  34. package/dist/middleware/oauth.d.ts +28 -0
  35. package/dist/middleware/oauth.mjs +1 -0
  36. package/dist/middleware/payment.d.ts +28 -0
  37. package/dist/middleware/payment.mjs +1 -0
  38. package/dist/middleware/rate-limit.d.ts +15 -0
  39. package/dist/middleware/rate-limit.mjs +1 -0
  40. package/dist/middleware/stripe.d.ts +60 -0
  41. package/dist/middleware/stripe.mjs +1 -0
  42. package/dist/middleware/tip.d.ts +15 -0
  43. package/dist/middleware/tip.mjs +4 -0
  44. package/dist/middleware/truncate.d.ts +13 -0
  45. package/dist/middleware/truncate.mjs +1 -0
  46. package/dist/middleware/url-action.d.ts +30 -0
  47. package/dist/middleware/url-action.mjs +1 -0
  48. package/dist/pages-IPpN74gp.d.ts +26 -0
  49. package/dist/pages-VK55ZBAP.mjs +1 -0
  50. package/dist/store.d.ts +9 -0
  51. package/dist/store.mjs +1 -0
  52. package/dist/test.d.ts +1 -1
  53. package/dist/{types-D504PjnN.d.ts → types-BdFjg9Tn.d.ts} +40 -7
  54. package/package.json +94 -3
package/README.md CHANGED
@@ -3,44 +3,120 @@
3
3
  [![CI](https://github.com/hogekai/lynq/actions/workflows/ci.yml/badge.svg)](https://github.com/hogekai/lynq/actions/workflows/ci.yml)
4
4
  [![npm](https://img.shields.io/npm/v/@lynq/lynq)](https://www.npmjs.com/package/@lynq/lynq)
5
5
 
6
- Lightweight MCP server framework. Tool visibility control through middleware.
6
+ MCP servers are stateless by default. lynq makes them session-aware.
7
+
8
+ ## The Problem
9
+
10
+ With the official SDK, adding session-aware tool visibility requires manual plumbing:
11
+
12
+ ```ts
13
+ // Without lynq — manual session tracking, manual notifications
14
+ const sessions = new Map();
15
+
16
+ server.setRequestHandler(ListToolsRequestSchema, (req, extra) => {
17
+ const session = sessions.get(extra.sessionId);
18
+ const tools = [loginTool];
19
+ if (session?.authorized) tools.push(weatherTool); // manual filtering
20
+ return { tools };
21
+ });
22
+
23
+ server.setRequestHandler(CallToolRequestSchema, async (req, extra) => {
24
+ if (req.params.name === "login") {
25
+ sessions.set(extra.sessionId, { authorized: true });
26
+ server.sendToolListChanged(); // manual notification
27
+ }
28
+ // ...
29
+ });
30
+ ```
31
+
32
+ ## The Solution
33
+
34
+ ```ts
35
+ // With lynq — one line
36
+ server.tool("weather", guard(), config, handler);
37
+ // Client gets notified automatically. No manual wiring.
38
+ ```
39
+
40
+ ## Install
41
+
42
+ ```sh
43
+ npm install @lynq/lynq
44
+ ```
45
+
46
+ ## Quick Start
7
47
 
8
48
  ```ts
9
49
  import { createMCPServer } from "@lynq/lynq";
10
- import { auth } from "@lynq/lynq/auth";
50
+ import { guard } from "@lynq/lynq/guard";
11
51
  import { z } from "zod";
12
52
 
13
53
  const server = createMCPServer({ name: "my-server", version: "1.0.0" });
14
54
 
15
55
  server.tool("login", {
16
56
  input: z.object({ username: z.string(), password: z.string() }),
17
- }, async (args, ctx) => {
57
+ }, async (args, c) => {
18
58
  const user = await authenticate(args.username, args.password);
19
- ctx.session.set("user", user);
20
- ctx.session.authorize("auth");
21
- return ctx.text(`Welcome, ${user.name}`);
59
+ c.session.set("user", user);
60
+ c.session.authorize("guard");
61
+ return c.text(`Welcome, ${user.name}`);
22
62
  });
23
63
 
24
- server.tool("weather", auth(), {
64
+ server.tool("weather", guard(), {
25
65
  description: "Get weather for a city",
26
66
  input: z.object({ city: z.string() }),
27
- }, async (args, ctx) => {
28
- return ctx.text(JSON.stringify(await fetchWeather(args.city)));
67
+ }, async (args, c) => {
68
+ return c.text(JSON.stringify(await fetchWeather(args.city)));
29
69
  });
30
70
 
31
71
  await server.stdio();
32
72
  ```
33
73
 
34
- ## Install
35
-
36
74
  ```sh
37
- npm install @lynq/lynq @modelcontextprotocol/sdk zod
75
+ npx tsx server.ts
38
76
  ```
39
77
 
78
+ ## Features
79
+
80
+ - **Session-Scoped Visibility** — `authorize()` shows tools, `revoke()` hides them. Client notification is automatic.
81
+ - **Hono-Style Middleware** — Global via `server.use()`, per-tool inline. Three hooks: `onRegister`, `onCall`, `onResult`.
82
+ - **Built-in Middleware** — `guard()` `rateLimit()` `logger()` `truncate()` `credentials()` `some()` `every()` `except()`
83
+ - **Response Helpers** — `c.text()` `c.json()` `c.error()` `c.image()` — chainable: `c.text("done").json({ id: 1 })`
84
+ - **Elicitation** — `c.elicit.form(message, zodSchema)` for structured user input. `c.elicit.url()` for external flows.
85
+ - **Framework Adapters** — `server.http()` returns `(Request) => Response`. Mount in Hono, Express, Deno, Workers.
86
+ - **Test Helpers** — `createTestClient()` for in-memory testing. No transport setup.
87
+ - **Tiny Core** — One dependency. ESM only. No config files, no magic.
88
+
89
+ ## Middleware Composition
90
+
91
+ ```ts
92
+ import { guard } from "@lynq/lynq/guard";
93
+ import { rateLimit } from "@lynq/lynq/rate-limit";
94
+ import { logger } from "@lynq/lynq/logger";
95
+
96
+ server.use(logger()); // global
97
+ server.tool("search", guard(), rateLimit({ max: 10 }), config, handler); // per-tool stack
98
+ ```
99
+
100
+ ## Comparison
101
+
102
+ | | lynq | FastMCP | Official SDK |
103
+ |---|---|---|---|
104
+ | Per-tool middleware | Yes | No | No |
105
+ | Session-scoped visibility | Auto-notify | Manual | Manual |
106
+ | onResult hook | Yes | No | No |
107
+ | Response helpers | Chainable | Basic | No |
108
+ | Test helpers | Yes | No | No |
109
+ | HTTP server built-in | No (you choose) | Yes (opinionated) | No |
110
+
40
111
  ## Documentation
41
112
 
42
113
  [https://hogekai.github.io/lynq/](https://hogekai.github.io/lynq/)
43
114
 
115
+ - [Quick Start](https://hogekai.github.io/lynq/getting-started/quick-start)
116
+ - [Middleware Concepts](https://hogekai.github.io/lynq/concepts/middleware)
117
+ - [Why lynq](https://hogekai.github.io/lynq/why-lynq)
118
+ - [API Reference](https://hogekai.github.io/lynq/api-reference/)
119
+
44
120
  ## License
45
121
 
46
122
  MIT
@@ -1,5 +1,6 @@
1
1
  import { Express } from 'express';
2
- import { M as MCPServer } from '../types-D504PjnN.js';
2
+ import { M as MCPServer } from '../types-BdFjg9Tn.js';
3
+ import { P as PagesConfig } from '../pages-IPpN74gp.js';
3
4
  import '@modelcontextprotocol/sdk/types.js';
4
5
  import 'zod';
5
6
 
@@ -8,7 +9,11 @@ interface MountOptions {
8
9
  path?: string;
9
10
  /** Allowed hostnames for DNS rebinding protection. Default: localhost variants. */
10
11
  allowedHosts?: string[];
12
+ /** Enable default pages for specified auth/payment providers. */
13
+ pages?: PagesConfig;
14
+ /** URL prefix for pages routes. Default: "/lynq" */
15
+ pagesPrefix?: string;
11
16
  }
12
17
  declare function mountLynq(app: Express, server: MCPServer, options?: MountOptions): void;
13
18
 
14
- export { type MountOptions, mountLynq };
19
+ export { type MountOptions, PagesConfig, mountLynq };
@@ -1,2 +1,2 @@
1
- import {b,a}from'../chunk-7C4A572Z.mjs';function u(e){let t=e.protocol||"http",s=e.headers.host||"localhost",o=`${t}://${s}${e.originalUrl}`,r=new Headers;for(let[a,n]of Object.entries(e.headers))n&&r.set(a,Array.isArray(n)?n.join(", "):n);let i={method:e.method,headers:r};return e.method!=="GET"&&e.method!=="HEAD"&&(i.body=JSON.stringify(e.body)),new Request(o,i)}async function h(e,t){if(e.status(t.status),t.headers.forEach((s,o)=>e.setHeader(o,s)),t.body){let s=t.body.getReader();try{for(;;){let{done:o,value:r}=await s.read();if(o)break;e.write(r);}}finally{e.end();}}else e.end();}function y(e,t,s){let o=s?.path??"/mcp",r=t.http(),i=s?.allowedHosts??[...b];e.use(o,(a$1,n,d)=>{if(!a(a$1.headers.host??null,i)){n.status(403).json({jsonrpc:"2.0",error:{code:-32e3,message:"Forbidden"},id:null});return}d();}),e.all(o,async(a,n)=>{let d=u(a),p=await r(d);await h(n,p);});}
2
- export{y as mountLynq};
1
+ import {b,a}from'../chunk-7C4A572Z.mjs';import {b as b$1}from'../chunk-OJJZGR4B.mjs';function p(e){let g=e.protocol||"http",u=e.headers.host||"localhost",r=`${g}://${u}${e.originalUrl}`,n=new Headers;for(let[t,s]of Object.entries(e.headers))s&&n.set(t,Array.isArray(s)?s.join(", "):s);let a={method:e.method,headers:n};return e.method!=="GET"&&e.method!=="HEAD"&&(a.body=JSON.stringify(e.body)),new Request(r,a)}async function h(e,g){if(e.status(g.status),g.headers.forEach((u,r)=>e.setHeader(r,u)),g.body){let u=g.body.getReader();try{for(;;){let{done:r,value:n}=await u.read();if(r)break;e.write(n);}}finally{e.end();}}else e.end();}function P(e,g,u){let r=u?.path??"/mcp",n=g.http(),a$1=u?.allowedHosts??[...b];e.use(r,(t,s,i)=>{if(!a(t.headers.host??null,a$1)){s.status(403).json({jsonrpc:"2.0",error:{code:-32e3,message:"Forbidden"},id:null});return}i();}),e.all(r,async(t,s)=>{let i=p(t),o=await n(i);await h(s,o);}),u?.pages&&m(e,g,u);}function d(e){let g=e.protocol||"http",u=e.headers.host||"localhost";return `${g}://${u}`}function m(e,g,u){let r=u.pagesPrefix??"/lynq",n=u.pages;if(n.github&&typeof n.github!="string"){let a=n.github;e.get(`${r}/auth/github/callback`,async(t,s)=>{let{handleGitHubPage:i}=await import('../pages-VK55ZBAP.mjs'),o=await i(g,{code:t.query.code,state:t.query.state},a,r);if(o.redirect)return s.redirect(o.redirect);s.status(o.status).send(o.html);});}else if(typeof n.github=="string"){let a=n.github;e.get(`${r}/auth/github/callback`,(t,s)=>{let i=new URL(a,d(t));for(let[o,c]of Object.entries(t.query))typeof c=="string"&&i.searchParams.set(o,c);s.redirect(i.toString());});}if(n.google&&typeof n.google!="string"){let a=n.google;e.get(`${r}/auth/google/callback`,async(t,s)=>{let{handleGooglePage:i}=await import('../pages-VK55ZBAP.mjs'),o=`${d(t)}${r}/auth/google/callback`,c=await i(g,{code:t.query.code,state:t.query.state},a,r,o);if(c.redirect)return s.redirect(c.redirect);s.status(c.status).send(c.html);});}else if(typeof n.google=="string"){let a=n.google;e.get(`${r}/auth/google/callback`,(t,s)=>{let i=new URL(a,d(t));for(let[o,c]of Object.entries(t.query))typeof c=="string"&&i.searchParams.set(o,c);s.redirect(i.toString());});}if(n.stripe&&typeof n.stripe!="string"){let a=n.stripe;e.get(`${r}/payment/stripe/callback`,async(t,s)=>{let{handleStripePage:i}=await import('../pages-VK55ZBAP.mjs'),o=await i(g,{session_id:t.query.session_id,cancelled:t.query.cancelled,state:t.query.state},a,r);if(o.redirect)return s.redirect(o.redirect);s.status(o.status).send(o.html);});}else if(typeof n.stripe=="string"){let a=n.stripe;e.get(`${r}/payment/stripe/callback`,(t,s)=>{let i=new URL(a,d(t));for(let[o,c]of Object.entries(t.query))typeof c=="string"&&i.searchParams.set(o,c);s.redirect(i.toString());});}if(n.crypto&&typeof n.crypto!="string"){let a=n.crypto;e.get(`${r}/payment/crypto`,async(t,s)=>{let{handleCryptoGet:i}=await import('../pages-VK55ZBAP.mjs'),o=`${d(t)}${r}/payment/crypto/callback`,c=i({recipient:t.query.recipient,amount:t.query.amount,token:t.query.token,network:t.query.network,state:t.query.state},o);s.status(c.status).send(c.html);}),e.post(`${r}/payment/crypto/callback`,async(t,s)=>{let{handleCryptoPost:i}=await import('../pages-VK55ZBAP.mjs'),o=await i(g,t.body,a);s.status(o.status).json(o.json);});}else if(typeof n.crypto=="string"){let a=n.crypto;e.get(`${r}/payment/crypto`,(t,s)=>{let i=new URL(a,d(t));for(let[o,c]of Object.entries(t.query))typeof c=="string"&&i.searchParams.set(o,c);s.redirect(i.toString());});}e.get(`${r}/auth/success`,(a,t)=>{t.send(b$1("Authentication"));}),e.get(`${r}/payment/success`,(a,t)=>{t.send(b$1("Payment"));});}
2
+ export{P as mountLynq};
@@ -1,5 +1,6 @@
1
1
  import { Hono } from 'hono';
2
- import { M as MCPServer } from '../types-D504PjnN.js';
2
+ import { M as MCPServer } from '../types-BdFjg9Tn.js';
3
+ import { P as PagesConfig } from '../pages-IPpN74gp.js';
3
4
  import '@modelcontextprotocol/sdk/types.js';
4
5
  import 'zod';
5
6
 
@@ -8,7 +9,11 @@ interface MountOptions {
8
9
  path?: string;
9
10
  /** Allowed hostnames for DNS rebinding protection. Default: localhost variants. */
10
11
  allowedHosts?: string[];
12
+ /** Enable default pages for specified auth/payment providers. */
13
+ pages?: PagesConfig;
14
+ /** URL prefix for pages routes. Default: "/lynq" */
15
+ pagesPrefix?: string;
11
16
  }
12
17
  declare function mountLynq(app: Hono, server: MCPServer, options?: MountOptions): void;
13
18
 
14
- export { type MountOptions, mountLynq };
19
+ export { type MountOptions, PagesConfig, mountLynq };
@@ -1 +1 @@
1
- import {b,a}from'../chunk-7C4A572Z.mjs';function m(t,a$1,e){let r=e?.path??"/mcp",l=a$1.http(),i=e?.allowedHosts??[...b];t.use(r,async(o,p)=>a(o.req.header("host")??null,i)?p():o.json({jsonrpc:"2.0",error:{code:-32e3,message:"Forbidden"},id:null},403)),t.all(r,o=>l(o.req.raw));}export{m as mountLynq};
1
+ import {b,a}from'../chunk-7C4A572Z.mjs';import {b as b$1}from'../chunk-OJJZGR4B.mjs';function q(a$1,u,c){let s=c?.path??"/mcp",o=u.http(),t=c?.allowedHosts??[...b];a$1.use(s,async(e,r)=>a(e.req.header("host")??null,t)?r():e.json({jsonrpc:"2.0",error:{code:-32e3,message:"Forbidden"},id:null},403)),a$1.all(s,e=>o(e.req.raw)),c?.pages&&f(a$1,u,c);}function f(a,u,c){let s=c.pagesPrefix??"/lynq",o=c.pages;if(o.github&&typeof o.github!="string"?a.get(`${s}/auth/github/callback`,async t=>{let{handleGitHubPage:e}=await import('../pages-VK55ZBAP.mjs'),r=await e(u,{code:t.req.query("code"),state:t.req.query("state")},o.github,s);return r.redirect?t.redirect(r.redirect):t.html(r.html??"",r.status)}):typeof o.github=="string"&&a.get(`${s}/auth/github/callback`,t=>{let e=new URL(o.github,t.req.url),r=t.req.query();for(let[i,n]of Object.entries(r))e.searchParams.set(i,n);return t.redirect(e.toString())}),o.google&&typeof o.google!="string"?a.get(`${s}/auth/google/callback`,async t=>{let{handleGooglePage:e}=await import('../pages-VK55ZBAP.mjs'),i=`${new URL(t.req.url).origin}${s}/auth/google/callback`,n=await e(u,{code:t.req.query("code"),state:t.req.query("state")},o.google,s,i);return n.redirect?t.redirect(n.redirect):t.html(n.html??"",n.status)}):typeof o.google=="string"&&a.get(`${s}/auth/google/callback`,t=>{let e=new URL(o.google,t.req.url),r=t.req.query();for(let[i,n]of Object.entries(r))e.searchParams.set(i,n);return t.redirect(e.toString())}),o.stripe&&typeof o.stripe!="string"?a.get(`${s}/payment/stripe/callback`,async t=>{let{handleStripePage:e}=await import('../pages-VK55ZBAP.mjs'),r=await e(u,{session_id:t.req.query("session_id"),cancelled:t.req.query("cancelled"),state:t.req.query("state")},o.stripe,s);return r.redirect?t.redirect(r.redirect):t.html(r.html??"",r.status)}):typeof o.stripe=="string"&&a.get(`${s}/payment/stripe/callback`,t=>{let e=new URL(o.stripe,t.req.url),r=t.req.query();for(let[i,n]of Object.entries(r))e.searchParams.set(i,n);return t.redirect(e.toString())}),o.crypto&&typeof o.crypto!="string"){let t=o.crypto;a.get(`${s}/payment/crypto`,async e=>{let{handleCryptoGet:r}=await import('../pages-VK55ZBAP.mjs'),i=`${new URL(e.req.url).origin}${s}/payment/crypto/callback`,n=r({recipient:e.req.query("recipient"),amount:e.req.query("amount"),token:e.req.query("token"),network:e.req.query("network"),state:e.req.query("state")},i);return e.html(n.html??"",n.status)}),a.post(`${s}/payment/crypto/callback`,async e=>{let{handleCryptoPost:r}=await import('../pages-VK55ZBAP.mjs'),i=await e.req.json(),n=await r(u,i,t);return e.json(n.json,n.status)});}else typeof o.crypto=="string"&&a.get(`${s}/payment/crypto`,t=>{let e=new URL(o.crypto,t.req.url),r=t.req.query();for(let[i,n]of Object.entries(r))e.searchParams.set(i,n);return t.redirect(e.toString())});a.get(`${s}/auth/success`,t=>t.html(b$1("Authentication"))),a.get(`${s}/payment/success`,t=>t.html(b$1("Payment")));}export{q as mountLynq};
@@ -0,0 +1 @@
1
+ import {a}from'./chunk-OYHVJKUP.mjs';function s(e){let t={name:e.name??"payment",sessionKey:e.sessionKey??"payment",message:e.message??"Please complete payment to continue.",buildUrl:e.buildUrl,declineMessage:"Payment cancelled."};return e.timeout!==void 0&&(t.timeout=e.timeout),e.persistent!==void 0&&(t.persistent=e.persistent),e.skipIf&&(t.skipIf=e.skipIf),e.onComplete&&(t.onComplete=e.onComplete),a(t)}export{s as a};
@@ -0,0 +1 @@
1
+ import {a}from'./chunk-OYHVJKUP.mjs';function n(e){let t={name:e.name??"oauth",sessionKey:e.sessionKey??"user",message:e.message??"Please sign in to continue.",buildUrl:e.buildUrl,declineMessage:"Authentication cancelled."};return e.timeout!==void 0&&(t.timeout=e.timeout),e.persistent!==void 0&&(t.persistent=e.persistent),e.skipIf&&(t.skipIf=e.skipIf),e.onComplete&&(t.onComplete=e.onComplete),a(t)}export{n as a};
@@ -0,0 +1 @@
1
+ import {c}from'./chunk-VAAZWX4U.mjs';function g(e){let s=e?.name??"guard",n=e?.sessionKey??"user",t=e?.message??"Authorization required.";return {name:s,onRegister(){return false},async onCall(o,a){return o.session.get(n)?a():c(t)}}}export{g as a};
@@ -0,0 +1,170 @@
1
+ function c(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function u(e){let t=c(e);return `<!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>${t} Complete</title>
6
+ <style>
7
+ body { font-family: system-ui, sans-serif; display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0; color: #1a1a1a; }
8
+ .card { text-align: center; padding: 40px; }
9
+ .check { font-size: 3em; margin-bottom: 12px; }
10
+ h1 { font-size: 1.2em; margin-bottom: 8px; }
11
+ p { color: #666; font-size: 0.9em; }
12
+ </style>
13
+ </head>
14
+ <body>
15
+ <div class="card">
16
+ <div class="check">&#10003;</div>
17
+ <h1>${t} complete</h1>
18
+ <p>You can close this tab and return to your app.</p>
19
+ </div>
20
+ </body>
21
+ </html>`}function i(e){return `<!DOCTYPE html>
22
+ <html>
23
+ <head>
24
+ <meta charset="utf-8">
25
+ <title>Error</title>
26
+ <style>
27
+ body { font-family: system-ui, sans-serif; display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0; color: #1a1a1a; }
28
+ .card { text-align: center; padding: 40px; max-width: 420px; }
29
+ .icon { font-size: 3em; margin-bottom: 12px; }
30
+ h1 { font-size: 1.2em; margin-bottom: 8px; }
31
+ p { color: #dc2626; font-size: 0.9em; word-break: break-word; }
32
+ </style>
33
+ </head>
34
+ <body>
35
+ <div class="card">
36
+ <div class="icon">&#10007;</div>
37
+ <h1>Something went wrong</h1>
38
+ <p>${c(e)}</p>
39
+ </div>
40
+ </body>
41
+ </html>`}function l(e){let t=c(e.recipient),s=c(e.amount),a=c(e.token),n=c(e.network),r=c(e.state),o=c(e.callbackUrl);return `<!DOCTYPE html>
42
+ <html>
43
+ <head>
44
+ <meta charset="utf-8">
45
+ <meta name="viewport" content="width=device-width, initial-scale=1">
46
+ <title>Payment &mdash; ${s} ${a}</title>
47
+ <style>
48
+ * { margin: 0; padding: 0; box-sizing: border-box; }
49
+ body { font-family: system-ui, sans-serif; max-width: 420px; margin: 60px auto; padding: 20px; color: #1a1a1a; }
50
+ h1 { font-size: 1.4em; margin-bottom: 8px; }
51
+ .info { background: #f5f5f5; padding: 16px; border-radius: 8px; margin: 16px 0; font-size: 0.9em; }
52
+ .info dt { color: #666; font-size: 0.85em; margin-top: 8px; }
53
+ .info dd { font-family: monospace; word-break: break-all; }
54
+ button { width: 100%; padding: 14px; font-size: 1em; border: none; border-radius: 8px; cursor: pointer; margin-top: 12px; }
55
+ .btn-primary { background: #2563eb; color: white; }
56
+ .btn-primary:hover { background: #1d4ed8; }
57
+ .btn-primary:disabled { background: #93c5fd; cursor: not-allowed; }
58
+ .status { text-align: center; margin-top: 16px; font-size: 0.9em; color: #666; }
59
+ .success { color: #16a34a; }
60
+ .error { color: #dc2626; }
61
+ </style>
62
+ </head>
63
+ <body>
64
+ <h1>Send ${s} ${a}</h1>
65
+ <dl class="info">
66
+ <dt>To</dt>
67
+ <dd>${t}</dd>
68
+ <dt>Network</dt>
69
+ <dd>${n}</dd>
70
+ <dt>Amount</dt>
71
+ <dd>${s} ${a}</dd>
72
+ </dl>
73
+
74
+ <div id="data"
75
+ data-recipient="${t}"
76
+ data-amount="${s}"
77
+ data-token="${a}"
78
+ data-state="${r}"
79
+ data-callback="${o}"
80
+ ></div>
81
+
82
+ <button class="btn-primary" id="connectBtn">Connect Wallet</button>
83
+ <button class="btn-primary" id="payBtn" style="display:none">Send ${s} ${a}</button>
84
+ <p class="status" id="status"></p>
85
+
86
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/ethers/6.13.4/ethers.umd.min.js"></script>
87
+ <script>
88
+ (function() {
89
+ var d = document.getElementById("data").dataset;
90
+ var RECIPIENT = d.recipient;
91
+ var AMOUNT = d.amount;
92
+ var TOKEN = d.token;
93
+ var STATE = d.state;
94
+ var CALLBACK = d.callback;
95
+ var provider, signer;
96
+ var statusEl = document.getElementById("status");
97
+ var connectBtn = document.getElementById("connectBtn");
98
+ var payBtn = document.getElementById("payBtn");
99
+
100
+ connectBtn.addEventListener("click", async function() {
101
+ try {
102
+ if (!window.ethereum) {
103
+ statusEl.textContent = "No wallet detected. Install MetaMask.";
104
+ statusEl.className = "status error";
105
+ return;
106
+ }
107
+ provider = new ethers.BrowserProvider(window.ethereum);
108
+ signer = await provider.getSigner();
109
+ var addr = await signer.getAddress();
110
+ statusEl.textContent = "Connected: " + addr.slice(0, 6) + "..." + addr.slice(-4);
111
+ statusEl.className = "status";
112
+ connectBtn.style.display = "none";
113
+ payBtn.style.display = "block";
114
+ } catch (e) {
115
+ statusEl.textContent = "Connection failed: " + e.message;
116
+ statusEl.className = "status error";
117
+ }
118
+ });
119
+
120
+ payBtn.addEventListener("click", async function() {
121
+ payBtn.disabled = true;
122
+ statusEl.textContent = "Sending...";
123
+ statusEl.className = "status";
124
+
125
+ try {
126
+ if (TOKEN !== "ETH") {
127
+ statusEl.textContent = "ERC-20 transfers require a contract address. Use ETH for native transfers.";
128
+ statusEl.className = "status error";
129
+ payBtn.disabled = false;
130
+ return;
131
+ }
132
+
133
+ var tx = await signer.sendTransaction({
134
+ to: RECIPIENT,
135
+ value: ethers.parseEther(AMOUNT),
136
+ });
137
+
138
+ statusEl.textContent = "Waiting for confirmation...";
139
+ var receipt = await tx.wait();
140
+
141
+ var res = await fetch(CALLBACK, {
142
+ method: "POST",
143
+ headers: { "Content-Type": "application/json" },
144
+ body: JSON.stringify({
145
+ txHash: receipt.hash,
146
+ state: STATE,
147
+ recipient: RECIPIENT,
148
+ amount: AMOUNT,
149
+ }),
150
+ });
151
+ var data = await res.json();
152
+
153
+ if (data.success) {
154
+ statusEl.textContent = "Payment confirmed! You can close this tab.";
155
+ statusEl.className = "status success";
156
+ } else {
157
+ statusEl.textContent = "Verification failed: " + (data.error || "unknown");
158
+ statusEl.className = "status error";
159
+ payBtn.disabled = false;
160
+ }
161
+ } catch (e) {
162
+ statusEl.textContent = "Transaction failed: " + e.message;
163
+ statusEl.className = "status error";
164
+ payBtn.disabled = false;
165
+ }
166
+ });
167
+ })();
168
+ </script>
169
+ </body>
170
+ </html>`}async function g(e,t,s,a){if(s===true)return {status:500,html:i("GitHub pages require { clientId, clientSecret } configuration")};if(!t.code||!t.state)return {status:400,html:i("Missing code or state parameter")};try{let{handleCallback:n}=await import('./middleware/github.mjs'),r={clientId:s.clientId,clientSecret:s.clientSecret};s.sessionKey&&(r.sessionKey=s.sessionKey);let o=await n(e,{code:t.code,state:t.state},r);return o.success?{status:302,redirect:`${a}/auth/success`}:{status:500,html:i(o.error??"Authentication failed")}}catch(n){return {status:500,html:i(n instanceof Error?n.message:String(n))}}}async function m(e,t,s,a,n){if(s===true)return {status:500,html:i("Google pages require { clientId, clientSecret } configuration")};if(!t.code||!t.state)return {status:400,html:i("Missing code or state parameter")};try{let{handleCallback:r}=await import('./middleware/google.mjs'),o={clientId:s.clientId,clientSecret:s.clientSecret,redirectUri:n};s.sessionKey&&(o.sessionKey=s.sessionKey);let d=await r(e,{code:t.code,state:t.state},o);return d.success?{status:302,redirect:`${a}/auth/success`}:{status:500,html:i(d.error??"Authentication failed")}}catch(r){return {status:500,html:i(r instanceof Error?r.message:String(r))}}}async function p(e,t,s,a){if(s===true)return {status:500,html:i("Stripe pages require { secretKey } configuration")};if(t.cancelled==="true")return {status:200,html:i("Payment was cancelled")};if(!t.session_id||!t.state)return {status:400,html:i("Missing session_id or state parameter")};try{let{handleCallback:n}=await import('./middleware/stripe.mjs'),r={secretKey:s.secretKey};s.sessionKey&&(r.sessionKey=s.sessionKey);let o=await n(e,{checkoutSessionId:t.session_id,state:t.state},r);return o.success?{status:302,redirect:`${a}/payment/success`}:{status:500,html:i(o.error??"Payment verification failed")}}catch(n){return {status:500,html:i(n instanceof Error?n.message:String(n))}}}function f(e,t){return !e.recipient||!e.amount||!e.state?{status:400,html:i("Missing required payment parameters")}:{status:200,html:l({recipient:e.recipient,amount:e.amount,token:e.token??"USDC",network:e.network??"base",state:e.state,callbackUrl:t})}}async function h(e,t,s){if(!t.txHash||!t.state||!t.recipient||!t.amount)return {status:400,json:{success:false,error:"Missing txHash, state, recipient, or amount"}};try{let{handleCallback:a}=await import('./middleware/crypto.mjs'),n={recipient:t.recipient,amount:Number(t.amount)};s!==!0&&(s.rpcUrl&&(n.rpcUrl=s.rpcUrl),s.sessionKey&&(n.sessionKey=s.sessionKey));let r=await a(e,{txHash:t.txHash,state:t.state},n);return {status:r.success?200:500,json:r}}catch(a){return {status:500,json:{success:false,error:a instanceof Error?a.message:String(a)}}}}export{c as a,u as b,i as c,l as d,g as e,m as f,p as g,f as h,h as i};
@@ -0,0 +1 @@
1
+ import {c}from'./chunk-VAAZWX4U.mjs';function d(e){let o=e.name??"url-action",s=e.sessionKey??"user",l=e.timeout??3e5,a=e.declineMessage??"Action cancelled.";return {name:o,onRegister(){return false},async onCall(t,i){if(e.skipIf){if(await Promise.resolve(e.skipIf(t)))return i()}else if(e.persistent){if(await t.userStore.get(s))return i()}else if(t.session.get(s))return i();let n=crypto.randomUUID(),u=await e.buildUrl({sessionId:t.sessionId,elicitationId:n});if((await t.elicit.url(e.message,u,{elicitationId:n,waitForCompletion:true,timeout:l})).action!=="accept")return c(a);if(e.persistent){if(!await t.userStore.get(s))return c("Action was not completed.")}else if(!t.session.get(s))return c("Action was not completed.");return e.onComplete&&await Promise.resolve(e.onComplete(t)),t.session.authorize(o),i()}}}export{d as a};
@@ -0,0 +1 @@
1
+ function u(){let t=new Map;return {async get(e){let n=t.get(e);if(n){if(n.expiresAt!==void 0&&Date.now()>n.expiresAt){t.delete(e);return}return n.value}},async set(e,n,r){t.set(e,{value:n,expiresAt:r!==void 0?Date.now()+r*1e3:void 0});},async delete(e){t.delete(e);}}}function o(t){let e=t.get("user");if(e){if(typeof e=="string")return e;if(typeof e=="object"&&e!==null){let n=e;if(typeof n.id=="string")return n.id;if(typeof n.id=="number")return String(n.id);if(typeof n.sub=="string")return n.sub}}}function d(t,e){let n=()=>{let r=o(t);if(!r)throw new Error("userStore requires a user in session. Call session.set('user', ...) first.");return r};return {async get(r){return e.get(`user:${n()}:${r}`)},async set(r,s,i){await e.set(`user:${n()}:${r}`,s,i);},async delete(r){await e.delete(`user:${n()}:${r}`);}}}export{u as a,o as b,d as c};
package/dist/index.d.ts CHANGED
@@ -1,11 +1,9 @@
1
- import { M as MCPServer } from './types-D504PjnN.js';
2
- export { E as Elicit, a as ElicitFormResult, b as ElicitUrlResult, H as HttpAdapterOptions, R as ResourceConfig, c as ResourceContent, d as ResourceContext, e as ResourceHandler, f as RootInfo, S as Sample, g as SampleOptions, h as SampleRawParams, i as SampleRawResult, j as ServerInfo, k as Session, T as TaskConfig, l as TaskContext, m as TaskControl, n as TaskHandler, o as ToolConfig, p as ToolContext, q as ToolHandler, r as ToolInfo, s as ToolMiddleware, t as ToolResponse, u as error, v as image, w as json, x as text } from './types-D504PjnN.js';
1
+ import { S as ServerOptions, M as MCPServer } from './types-BdFjg9Tn.js';
2
+ export { E as Elicit, a as ElicitFormResult, b as ElicitUrlOptions, c as ElicitUrlResult, H as HttpAdapterOptions, R as ResourceConfig, d as ResourceContent, e as ResourceContext, f as ResourceHandler, g as RootInfo, h as Sample, i as SampleOptions, j as SampleRawParams, k as SampleRawResult, l as ServerInfo, m as Session, n as Store, T as TaskConfig, o as TaskContext, p as TaskControl, q as TaskHandler, r as ToolConfig, s as ToolContext, t as ToolHandler, u as ToolInfo, v as ToolMiddleware, w as ToolResponse, U as UserStore, x as error, y as image, z as json, A as text } from './types-BdFjg9Tn.js';
3
+ export { memoryStore } from './store.js';
3
4
  import '@modelcontextprotocol/sdk/types.js';
4
5
  import 'zod';
5
6
 
6
- declare function createMCPServer(info: {
7
- name: string;
8
- version: string;
9
- }): MCPServer;
7
+ declare function createMCPServer(info: ServerOptions): MCPServer;
10
8
 
11
- export { MCPServer, createMCPServer };
9
+ export { MCPServer, ServerOptions, createMCPServer };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import {c,d,b,a}from'./chunk-VAAZWX4U.mjs';export{c as error,d as image,b as json,a as text}from'./chunk-VAAZWX4U.mjs';import {InMemoryTaskStore}from'@modelcontextprotocol/sdk/experimental/tasks';import {Server}from'@modelcontextprotocol/sdk/server/index.js';import {ListToolsRequestSchema,CallToolRequestSchema,ListResourcesRequestSchema,ListResourceTemplatesRequestSchema,ReadResourceRequestSchema}from'@modelcontextprotocol/sdk/types.js';import {normalizeObjectSchema}from'@modelcontextprotocol/sdk/server/zod-compat.js';import {toJsonSchemaCompat}from'@modelcontextprotocol/sdk/server/zod-json-schema-compat.js';function k(i){if(i==null)return {type:"object"};let l=normalizeObjectSchema(i);return l?toJsonSchemaCompat(l):i}function H(i,l){let c=l[l.length-1];if(typeof c!="function")throw new TypeError(`${i}: last argument must be a handler function`);let a=l[l.length-2];if(a==null||typeof a!="object"||Array.isArray(a))throw new TypeError(`${i}: second-to-last argument must be a config object`);let u=l.slice(0,-2);for(let d of u)if(!d||typeof d!="object"||typeof d.name!="string")throw new TypeError(`${i}: each middleware must have a "name" property`);return {middlewares:u,config:a,handler:c}}function $(i,l){let c=[];for(let a of l)a.onRegister?.(i)===false&&c.push(a.name);return c}function G(i){let c=i.split(/\{[^}]+\}/).map(a=>a.replace(/[.*+?^$|()[\]\\]/g,"\\$&"));return new RegExp(`^${c.join("(.+)")}$`)}function O(i,l,c,a){let u=c.get(l);if(u==="disabled")return false;if(u==="enabled")return true;for(let d of i)if(!a.has(d))return false;return true}function D(i,l){let c=i.get(l);if(c)return c;for(let a of i.values())if(a.isTemplate&&a.uriPattern?.test(l))return a}function E(i,l,c){let a=i.filter(f=>f.onCall),u=i.filter(f=>f.onResult).reverse(),d=0,y=async()=>{if(d>=a.length){let v=await c();for(let M of u)v=await M.onResult(v,l);return v}return a[d++].onCall(l,y)};return y}function ie(i){return {async form(l,c){let a=k(c),u=await i.elicitInput({message:l,requestedSchema:a});return {action:u.action,content:u.content??{}}},async url(l,c){return {action:(await i.elicitInput({mode:"url",message:l,url:c,elicitationId:crypto.randomUUID()})).action}}}}function L(i){return async()=>{try{return (await i.listRoots()).roots.map(c=>{let a={uri:c.uri};return c.name!==void 0&&(a.name=c.name),a})}catch{return []}}}function le(i){async function l(a,u){let d={messages:[{role:"user",content:{type:"text",text:a}}],maxTokens:u?.maxTokens??1024};u?.model!==void 0&&(d.modelPreferences={hints:[{name:u.model}]}),u?.system!==void 0&&(d.systemPrompt=u.system),u?.temperature!==void 0&&(d.temperature=u.temperature),u?.stopSequences!==void 0&&(d.stopSequences=u.stopSequences);let f=(await i.createMessage(d)).content;return f.type==="text"?f.text:""}async function c(a){return i.createMessage(a)}return Object.assign(l,{raw:c})}function _(i,l,c$1,a$1,u){return {toolName:a$1,session:c$1,signal:u,sessionId:l,elicit:ie(i),roots:L(i),sample:le(i),text:a,json:b,error:c,image:d}}function ge(i){let l=[],c$1=new Map,a=new Map,u=new Map,d=new Map,y=new Map,f=new Set,v=new InMemoryTaskStore,M=new Proxy(v,{get(e,n,t){return n==="updateTaskStatus"?async(s,r,...o)=>(r==="cancelled"&&f.add(s),e.updateTaskStatus.call(e,s,r,...o)):Reflect.get(e,n,t)}}),b=new Server(i,{capabilities:{tools:{listChanged:true},resources:{listChanged:true},tasks:{list:{},cancel:{},requests:{tools:{call:{}}}}},taskStore:M});function C(e){let n=d.get(e);return n||(n={data:new Map,grants:new Set,toolOverrides:new Map,resourceOverrides:new Map},d.set(e,n)),n}function A(e,n){let t=C(n);return O(e.hiddenByMiddlewares,e.name,t.toolOverrides,t.grants)}function x(e,n){let t=C(n);return O(e.hiddenByMiddlewares,e.uri,t.resourceOverrides,t.grants)}function B(e,n){let t=C(n);return O(e.hiddenByMiddlewares,e.name,t.toolOverrides,t.grants)}function I(e){(e&&y.get(e)||b).sendToolListChanged().catch(()=>{});}function P(e){(e&&y.get(e)||b).sendResourceListChanged().catch(()=>{});}function q(e){let n=C(e);return {get(t){return n.data.get(t)},set(t,s){n.data.set(t,s);},authorize(t){n.grants.add(t),I(e),P(e);},revoke(t){n.grants.delete(t),I(e),P(e);},enableTools(...t){for(let s of t)n.toolOverrides.set(s,"enabled");I(e);},disableTools(...t){for(let s of t)n.toolOverrides.set(s,"disabled");I(e);},enableResources(...t){for(let s of t)n.resourceOverrides.set(s,"enabled");P(e);},disableResources(...t){for(let s of t)n.resourceOverrides.set(s,"disabled");P(e);}}}function z(e){e.setRequestHandler(ListToolsRequestSchema,(n,t)=>{let s=t.sessionId??"default",r=[];for(let o of c$1.values())A(o,s)&&r.push({name:o.name,description:o.description,inputSchema:k(o.input)});for(let o of u.values())B(o,s)&&r.push({name:o.name,description:o.description,inputSchema:k(o.input),execution:{taskSupport:"required"}});return {tools:r}}),e.setRequestHandler(CallToolRequestSchema,async(n,t)=>{let{name:s,arguments:r}=n.params,o=t.sessionId??"default",w=c$1.get(s);if(w){if(!A(w,o))return c(`Tool not available: ${s}`);let m=_(e,o,q(o),s,t.signal),p=()=>Promise.resolve(w.handler(r??{},m));return E(w.middlewares,m,p)()}let g=u.get(s);if(g){if(!B(g,o))return c(`Tool not available: ${s}`);let m=t.taskStore;if(!m)return c("Task store not available");let p=await m.createTask({pollInterval:1e3}),T=p.taskId,S={progress(h,j){if(f.has(T))return;let oe=j?`${h}% ${j}`:`${h}%`;m.updateTaskStatus(T,"working",oe).catch(()=>{});},get cancelled(){return f.has(T)}},F={..._(e,o,q(o),s,t.signal),task:S},se=async()=>((async()=>{try{let h=await g.handler(r??{},F);f.has(T)||await m.storeTaskResult(T,"completed",h);}catch(h){if(!f.has(T)){let j=h instanceof Error?h.message:String(h);await m.storeTaskResult(T,"failed",c(j)).catch(()=>{});}}})(),{task:p});return E(g.middlewares,F,se)()}return c(`Unknown tool: ${s}`)}),e.setRequestHandler(ListResourcesRequestSchema,(n,t)=>{let s=t.sessionId??"default",r=[];for(let o of a.values())!o.isTemplate&&x(o,s)&&r.push({uri:o.uri,name:o.name,description:o.description,mimeType:o.mimeType});return {resources:r}}),e.setRequestHandler(ListResourceTemplatesRequestSchema,(n,t)=>{let s=t.sessionId??"default",r=[];for(let o of a.values())o.isTemplate&&x(o,s)&&r.push({uriTemplate:o.uri,name:o.name,description:o.description,mimeType:o.mimeType});return {resourceTemplates:r}}),e.setRequestHandler(ReadResourceRequestSchema,async(n,t)=>{let{uri:s}=n.params,r=D(a,s);if(!r)throw new Error(`Unknown resource: ${s}`);let o=t.sessionId??"default";if(!x(r,o))throw new Error(`Resource not available: ${s}`);let w=q(o),g={uri:s,session:w,sessionId:o,roots:L(e)},m=_(e,o,w,r.uri,t.signal),p=async()=>{let S=await r.handler(s,g);return {contents:[{uri:s,mimeType:S.mimeType??r.mimeType,...S.text!=null?{text:S.text}:{},...S.blob!=null?{blob:S.blob}:{}}]}};return E(r.middlewares,m,p)()});}z(b);function Z(e){l.push(e);}function K(...e){let n=e[0],t=H(`tool("${n}")`,e.slice(1));if(typeof t.config.name=="string")throw new TypeError(`tool("${n}"): second-to-last argument must be a config object`);let s=t.config,r=[...l,...t.middlewares],o={name:n,description:s.description,middlewares:r};c$1.set(n,{name:n,description:s.description,input:s.input,handler:t.handler,middlewares:r,hiddenByMiddlewares:$(o,r)});}function Q(...e){let n=e[0],t=H(`resource("${n}")`,e.slice(1));if(typeof t.config.name!="string")throw new TypeError(`resource("${n}"): second-to-last argument must be a config object with a "name" property`);let s=t.config,r={name:s.name,description:s.description,middlewares:t.middlewares},o=n.includes("{");a.set(n,{uri:n,isTemplate:o,uriPattern:o?G(n):null,name:s.name,description:s.description,mimeType:s.mimeType,handler:t.handler,middlewares:t.middlewares,hiddenByMiddlewares:$(r,t.middlewares)});}function X(...e){let n=e[0],t=H(`task("${n}")`,e.slice(1));if(typeof t.config.name=="string")throw new TypeError(`task("${n}"): second-to-last argument must be a config object`);let s=t.config,r=[...l,...t.middlewares],o={name:n,description:s.description,middlewares:r};u.set(n,{name:n,description:s.description,input:s.input,handler:t.handler,middlewares:r,hiddenByMiddlewares:$(o,r)});}async function Y(){let{StdioServerTransport:e}=await import('@modelcontextprotocol/sdk/server/stdio.js'),n=new e;await b.connect(n);}async function ee(e){await b.connect(e);}let te={tools:{listChanged:true},resources:{listChanged:true},tasks:{list:{},cancel:{},requests:{tools:{call:{}}}}};function N(){let e=new Server(i,{capabilities:te,taskStore:M});return z(e),e}function ne(e){let n=null;async function t(){return n||(n=(await import('@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js')).WebStandardStreamableHTTPServerTransport),n}if(e?.sessionless)return async r=>{let o=await t(),w=N(),g=new o({sessionIdGenerator:void 0,enableJsonResponse:e?.enableJsonResponse});return await w.connect(g),g.handleRequest(r)};let s=new Map;return async r=>{let o=await t(),w=r.headers.get("mcp-session-id");if(w){let p=s.get(w);return p?p.transport.handleRequest(r):new Response(JSON.stringify({jsonrpc:"2.0",error:{code:-32e3,message:"Session not found"}}),{status:404,headers:{"Content-Type":"application/json"}})}let g=N(),m=new o({sessionIdGenerator:e?.sessionIdGenerator??(()=>crypto.randomUUID()),enableJsonResponse:e?.enableJsonResponse,onsessioninitialized:p=>{s.set(p,{server:g,transport:m}),y.set(p,g);},onsessionclosed:p=>{s.delete(p),y.delete(p);}});return await g.connect(m),m.handleRequest(r)}}return {use:Z,tool:K,resource:Q,task:X,stdio:Y,http:ne,connect:ee,_server:b,_getSession:C,_isToolVisible(e,n){let t=c$1.get(e);return t?A(t,n):false},_isResourceVisible(e,n){let t=a.get(e);return t?x(t,n):false},_isTaskVisible(e,n){let t=u.get(e);return t?B(t,n):false},_createSessionAPI:q}}export{ge as createMCPServer};
1
+ import {a,c as c$1}from'./chunk-SPZY5GJA.mjs';export{a as memoryStore}from'./chunk-SPZY5GJA.mjs';import {c,d,b,a as a$1}from'./chunk-VAAZWX4U.mjs';export{c as error,d as image,b as json,a as text}from'./chunk-VAAZWX4U.mjs';import {InMemoryTaskStore}from'@modelcontextprotocol/sdk/experimental/tasks';import {Server}from'@modelcontextprotocol/sdk/server/index.js';import {ListToolsRequestSchema,CallToolRequestSchema,ListResourcesRequestSchema,ListResourceTemplatesRequestSchema,ReadResourceRequestSchema}from'@modelcontextprotocol/sdk/types.js';import {normalizeObjectSchema}from'@modelcontextprotocol/sdk/server/zod-compat.js';import {toJsonSchemaCompat}from'@modelcontextprotocol/sdk/server/zod-json-schema-compat.js';function q(i){if(i==null)return {type:"object"};let l=normalizeObjectSchema(i);return l?toJsonSchemaCompat(l):i}function A(i,l){let c=l[l.length-1];if(typeof c!="function")throw new TypeError(`${i}: last argument must be a handler function`);let a=l[l.length-2];if(a==null||typeof a!="object"||Array.isArray(a))throw new TypeError(`${i}: second-to-last argument must be a config object`);let d=l.slice(0,-2);for(let u of d)if(!u||typeof u!="object"||typeof u.name!="string")throw new TypeError(`${i}: each middleware must have a "name" property`);return {middlewares:d,config:a,handler:c}}function U(i,l){let c=[];for(let a of l)a.onRegister?.(i)===false&&c.push(a.name);return c}function ee(i){let c=i.split(/\{[^}]+\}/).map(a=>a.replace(/[.*+?^$|()[\]\\]/g,"\\$&"));return new RegExp(`^${c.join("(.+)")}$`)}function B(i,l,c,a){let d=c.get(l);if(d==="disabled")return false;if(d==="enabled")return true;for(let u of i)if(!a.has(u))return false;return true}function te(i,l){let c=i.get(l);if(c)return c;for(let a of i.values())if(a.isTemplate&&a.uriPattern?.test(l))return a}function N(i,l,c){let a=i.filter(m=>m.onCall),d=i.filter(m=>m.onResult).reverse(),u=0,f=async()=>{if(u>=a.length){let w=await c();for(let P of d)w=await P.onResult(w,l);return w}return a[u++].onCall(l,f)};return f}function we(i,l,c){return {async form(a,d){let u=q(d),f=await i.elicitInput({message:a,requestedSchema:u});return {action:f.action,content:f.content??{}}},async url(a,d,u){let f=u?.elicitationId??crypto.randomUUID(),m;u?.waitForCompletion&&l&&(m=l(f,i));let w=await i.elicitInput({mode:"url",message:a,url:d,elicitationId:f});if(w.action==="accept"&&m){let P=u?.timeout??3e5,E=new Promise((j,J)=>{setTimeout(()=>J(new Error("Elicitation timed out")),P);});await Promise.race([m,E]);}else m&&c&&c(f);return {action:w.action}}}}function K(i){return async()=>{try{return (await i.listRoots()).roots.map(c=>{let a={uri:c.uri};return c.name!==void 0&&(a.name=c.name),a})}catch{return []}}}function Te(i){async function l(a,d){let u={messages:[{role:"user",content:{type:"text",text:a}}],maxTokens:d?.maxTokens??1024};d?.model!==void 0&&(u.modelPreferences={hints:[{name:d.model}]}),d?.system!==void 0&&(u.systemPrompt=d.system),d?.temperature!==void 0&&(u.temperature=d.temperature),d?.stopSequences!==void 0&&(u.stopSequences=d.stopSequences);let m=(await i.createMessage(u)).content;return m.type==="text"?m.text:""}async function c(a){return i.createMessage(a)}return Object.assign(l,{raw:c})}function V(i,l,c$2,a,d$1,u,f,m){return {toolName:a,session:c$2,signal:d$1,sessionId:l,elicit:we(i,f,m),roots:K(i),sample:Te(i),text:a$1,json:b,error:c,image:d,store:u,userStore:c$1(c$2,u)}}function Ce(i){let l=i.store??a(),c$2=[],a$1=new Map,d=new Map,u=new Map,f=new Map,m=new Map,w=new Map,P=36e5;function E(){let e=Date.now();for(let[t,n]of w)e-n.createdAt>P&&w.delete(t);}function j(e,t,n){return E(),new Promise(o=>{let r;try{r=n.createElicitationCompletionNotifier(e);}catch{}w.set(e,{resolver:o,completionNotifier:r,createdAt:Date.now()});})}function J(e){E();let t=w.get(e);t&&(w.delete(e),t.completionNotifier&&t.completionNotifier().catch(()=>{}),t.resolver());}function L(e){let t=w.get(e);t&&(w.delete(e),t.resolver());}let x=new Set,oe=new InMemoryTaskStore,Q=new Proxy(oe,{get(e,t,n){return t==="updateTaskStatus"?async(o,r,...s)=>(r==="cancelled"&&x.add(o),e.updateTaskStatus.call(e,o,r,...s)):Reflect.get(e,t,n)}}),C=new Server(i,{capabilities:{tools:{listChanged:true},resources:{listChanged:true},tasks:{list:{},cancel:{},requests:{tools:{call:{}}}}},taskStore:Q});function I(e){let t=f.get(e);return t||(t={data:new Map,grants:new Set,toolOverrides:new Map,resourceOverrides:new Map},f.set(e,t)),t}function z(e,t){let n=I(t);return B(e.hiddenByMiddlewares,e.name,n.toolOverrides,n.grants)}function H(e,t){let n=I(t);return B(e.hiddenByMiddlewares,e.uri,n.resourceOverrides,n.grants)}function D(e,t){let n=I(t);return B(e.hiddenByMiddlewares,e.name,n.toolOverrides,n.grants)}function O(e){(e&&m.get(e)||C).sendToolListChanged().catch(()=>{});}function _(e){(e&&m.get(e)||C).sendResourceListChanged().catch(()=>{});}function b(e){let t=I(e);return {get(n){return t.data.get(n)},set(n,o){t.data.set(n,o);},authorize(n){t.grants.add(n),O(e),_(e);},revoke(n){t.grants.delete(n),O(e),_(e);},enableTools(...n){for(let o of n)t.toolOverrides.set(o,"enabled");O(e);},disableTools(...n){for(let o of n)t.toolOverrides.set(o,"disabled");O(e);},enableResources(...n){for(let o of n)t.resourceOverrides.set(o,"enabled");_(e);},disableResources(...n){for(let o of n)t.resourceOverrides.set(o,"disabled");_(e);}}}function X(e){e.setRequestHandler(ListToolsRequestSchema,(t,n)=>{let o=n.sessionId??"default",r=[];for(let s of a$1.values())z(s,o)&&r.push({name:s.name,description:s.description,inputSchema:q(s.input)});for(let s of u.values())D(s,o)&&r.push({name:s.name,description:s.description,inputSchema:q(s.input),execution:{taskSupport:"required"}});return {tools:r}}),e.setRequestHandler(CallToolRequestSchema,async(t,n)=>{let{name:o,arguments:r}=t.params,s=n.sessionId??"default",g=a$1.get(o);if(g){if(!z(g,s))return c(`Tool not available: ${o}`);let T=V(e,s,b(s),o,n.signal,l,(y,k)=>j(y,s,k),L),p=()=>Promise.resolve(g.handler(r??{},T));return N(g.middlewares,T,p)()}let R=u.get(o);if(R){if(!D(R,s))return c(`Tool not available: ${o}`);let T=n.taskStore;if(!T)return c("Task store not available");let p=await T.createTask({pollInterval:1e3}),h=p.taskId,y={progress(S,M){if(x.has(h))return;let pe=M?`${S}% ${M}`:`${S}%`;T.updateTaskStatus(h,"working",pe).catch(()=>{});},get cancelled(){return x.has(h)}},k={...V(e,s,b(s),o,n.signal,l,(S,M)=>j(S,s,M),L),task:y},me=async()=>((async()=>{try{let S=await R.handler(r??{},k);x.has(h)||await T.storeTaskResult(h,"completed",S);}catch(S){if(!x.has(h)){let M=S instanceof Error?S.message:String(S);await T.storeTaskResult(h,"failed",c(M)).catch(()=>{});}}})(),{task:p});return N(R.middlewares,k,me)()}return c(`Unknown tool: ${o}`)}),e.setRequestHandler(ListResourcesRequestSchema,(t,n)=>{let o=n.sessionId??"default",r=[];for(let s of d.values())!s.isTemplate&&H(s,o)&&r.push({uri:s.uri,name:s.name,description:s.description,mimeType:s.mimeType});return {resources:r}}),e.setRequestHandler(ListResourceTemplatesRequestSchema,(t,n)=>{let o=n.sessionId??"default",r=[];for(let s of d.values())s.isTemplate&&H(s,o)&&r.push({uriTemplate:s.uri,name:s.name,description:s.description,mimeType:s.mimeType});return {resourceTemplates:r}}),e.setRequestHandler(ReadResourceRequestSchema,async(t,n)=>{let{uri:o}=t.params,r=te(d,o);if(!r)throw new Error(`Unknown resource: ${o}`);let s=n.sessionId??"default";if(!H(r,s))throw new Error(`Resource not available: ${o}`);let g=b(s),R={uri:o,session:g,sessionId:s,roots:K(e),store:l,userStore:c$1(g,l)},T=V(e,s,g,r.uri,n.signal,l,(y,k)=>j(y,s,k),L),p=async()=>{let y=await r.handler(o,R);return {contents:[{uri:o,mimeType:y.mimeType??r.mimeType,...y.text!=null?{text:y.text}:{},...y.blob!=null?{blob:y.blob}:{}}]}};return N(r.middlewares,T,p)()});}X(C);function se(e){c$2.push(e);}function re(...e){let t=e[0],n=A(`tool("${t}")`,e.slice(1));if(typeof n.config.name=="string")throw new TypeError(`tool("${t}"): second-to-last argument must be a config object`);let o=n.config,r=[...c$2,...n.middlewares],s={name:t,description:o.description,middlewares:r};a$1.set(t,{name:t,description:o.description,input:o.input,handler:n.handler,middlewares:r,hiddenByMiddlewares:U(s,r)});}function ie(...e){let t=e[0],n=A(`resource("${t}")`,e.slice(1));if(typeof n.config.name!="string")throw new TypeError(`resource("${t}"): second-to-last argument must be a config object with a "name" property`);let o=n.config,r={name:o.name,description:o.description,middlewares:n.middlewares},s=t.includes("{");d.set(t,{uri:t,isTemplate:s,uriPattern:s?ee(t):null,name:o.name,description:o.description,mimeType:o.mimeType,handler:n.handler,middlewares:n.middlewares,hiddenByMiddlewares:U(r,n.middlewares)});}function ae(...e){let t=e[0],n=A(`task("${t}")`,e.slice(1));if(typeof n.config.name=="string")throw new TypeError(`task("${t}"): second-to-last argument must be a config object`);let o=n.config,r=[...c$2,...n.middlewares],s={name:t,description:o.description,middlewares:r};u.set(t,{name:t,description:o.description,input:o.input,handler:n.handler,middlewares:r,hiddenByMiddlewares:U(s,r)});}async function le(){let{StdioServerTransport:e}=await import('@modelcontextprotocol/sdk/server/stdio.js'),t=new e;await C.connect(t);}async function ce(e){await C.connect(e);}let de={tools:{listChanged:true},resources:{listChanged:true},tasks:{list:{},cancel:{},requests:{tools:{call:{}}}}};function Y(){let e=new Server(i,{capabilities:de,taskStore:Q});return X(e),e}function ue(e){let t=null;async function n(){return t||(t=(await import('@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js')).WebStandardStreamableHTTPServerTransport),t}if(e?.sessionless)return async r=>{let s=await n(),g=Y(),R=new s({sessionIdGenerator:void 0,enableJsonResponse:e?.enableJsonResponse});return await g.connect(R),R.handleRequest(r)};let o=new Map;return async r=>{let s=await n(),g=r.headers.get("mcp-session-id");if(g){let p=o.get(g);return p?(e?.onRequest&&await e.onRequest(r,g,b(g)),p.transport.handleRequest(r)):new Response(JSON.stringify({jsonrpc:"2.0",error:{code:-32e3,message:"Session not found"}}),{status:404,headers:{"Content-Type":"application/json"}})}let R=Y(),T=new s({sessionIdGenerator:e?.sessionIdGenerator??(()=>crypto.randomUUID()),enableJsonResponse:e?.enableJsonResponse,onsessioninitialized:p=>{o.set(p,{server:R,transport:T}),m.set(p,R),e?.onRequest&&e.onRequest(r,p,b(p));},onsessionclosed:p=>{o.delete(p),m.delete(p);}});return await R.connect(T),T.handleRequest(r)}}return {use:se,tool:re,resource:ie,task:ae,stdio:le,http:ue,session:b,completeElicitation:J,store:l,connect:ce,_server:C,_getSession:I,_isToolVisible(e,t){let n=a$1.get(e);return n?z(n,t):false},_isResourceVisible(e,t){let n=d.get(e);return n?H(n,t):false},_isTaskVisible(e,t){let n=u.get(e);return n?D(n,t):false},_createSessionAPI:b}}export{Ce as createMCPServer};
@@ -1,13 +1,11 @@
1
- import { s as ToolMiddleware } from '../types-D504PjnN.js';
1
+ import { v as ToolMiddleware } from '../types-BdFjg9Tn.js';
2
+ import { GuardOptions } from './guard.js';
2
3
  import '@modelcontextprotocol/sdk/types.js';
3
4
  import 'zod';
4
5
 
5
- interface AuthOptions {
6
- /** Session key to check for authentication. Default: "user" */
7
- sessionKey?: string;
8
- /** Error message when not authenticated. */
9
- message?: string;
10
- }
11
- declare function auth(options?: AuthOptions): ToolMiddleware;
6
+ /** @deprecated Use `GuardOptions` from `@lynq/lynq/guard` instead. */
7
+ type AuthOptions = GuardOptions;
8
+ /** @deprecated Use `guard()` from `@lynq/lynq/guard` instead. */
9
+ declare function auth(options?: GuardOptions): ToolMiddleware;
12
10
 
13
11
  export { type AuthOptions, auth };
@@ -1 +1 @@
1
- import {c}from'../chunk-VAAZWX4U.mjs';function u(e){let t=e?.sessionKey??"user",r=e?.message??"Authentication required. Please login first.";return {name:"auth",onRegister(){return false},async onCall(n,o){return n.session.get(t)?o():c(r)}}}export{u as auth};
1
+ import {a}from'../chunk-L7SD7KKW.mjs';import'../chunk-VAAZWX4U.mjs';function e(o){return a({name:"auth",...o})}export{e as auth};
@@ -0,0 +1,19 @@
1
+ import { v as ToolMiddleware } from '../types-BdFjg9Tn.js';
2
+ import '@modelcontextprotocol/sdk/types.js';
3
+ import 'zod';
4
+
5
+ interface BearerOptions {
6
+ /** Middleware name. Default: "bearer" */
7
+ name?: string;
8
+ /** Session key where the raw token is stored. Default: "token" */
9
+ tokenKey?: string;
10
+ /** Session key to store verified user. Default: "user" */
11
+ sessionKey?: string;
12
+ /** Verify the token. Return user data or null/throw on failure. */
13
+ verify: (token: string) => Promise<unknown | null>;
14
+ /** Error message. Default: "Invalid or missing token." */
15
+ message?: string;
16
+ }
17
+ declare function bearer(options: BearerOptions): ToolMiddleware;
18
+
19
+ export { type BearerOptions, bearer };
@@ -0,0 +1 @@
1
+ import {c}from'../chunk-VAAZWX4U.mjs';function y(e){let n=e.name??"bearer",m=e.tokenKey??"token",t=e.sessionKey??"user",o=e.message??"Invalid or missing token.";return {name:n,onRegister(){return false},async onCall(s,i){if(s.session.get(t))return i();let a=s.session.get(m);if(!a)return c(o);let g=await e.verify(a);return g?(s.session.set(t,g),s.session.authorize(n),i()):c(o)}}}export{y as bearer};
@@ -0,0 +1,12 @@
1
+ import { v as ToolMiddleware, s as ToolContext } from '../types-BdFjg9Tn.js';
2
+ import '@modelcontextprotocol/sdk/types.js';
3
+ import 'zod';
4
+
5
+ /** Run the first middleware that doesn't short-circuit. */
6
+ declare function some(...middlewares: ToolMiddleware[]): ToolMiddleware;
7
+ /** Run all middlewares. Stop if any short-circuits. */
8
+ declare function every(...middlewares: ToolMiddleware[]): ToolMiddleware;
9
+ /** Run middleware only when the condition is false. */
10
+ declare function except(condition: (c: ToolContext) => boolean, middleware: ToolMiddleware): ToolMiddleware;
11
+
12
+ export { every, except, some };
@@ -0,0 +1 @@
1
+ function f(...n){return {name:`some(${n.map(e=>e.name).join(",")})`,onRegister(e){for(let o of n)if(o.onRegister?.(e)===false)return false},async onCall(e,o){let t,r;for(let s of n){if(!s.onCall){t=s;break}let u=false,a=async()=>(u=true,o()),i=await s.onCall(e,a);if(u)return t=s,i;r=i;}return t?o():r},onResult(e){return e}}}function c(...n){let l=n.map(o=>o.name),e=n.filter(o=>o.onResult).reverse();return {name:`every(${l.join(",")})`,onRegister(o){for(let t of n)if(t.onRegister?.(o)===false)return false},async onCall(o,t){let r=n.filter(a=>a.onCall),s=0,u=async()=>s>=r.length?t():r[s++].onCall(o,u);return u()},onResult(o,t){let r=o;for(let s of e){let u=s.onResult(r,t);u instanceof Promise||(r=u);}return r}}}function T(n,l){return {name:`except(${l.name})`,onRegister(e){return l.onRegister?.(e)},async onCall(e,o){return n(e)?o():l.onCall?l.onCall(e,o):o()},onResult(e,o){return l.onResult?l.onResult(e,o):e}}}export{c as every,T as except,f as some};
@@ -0,0 +1,19 @@
1
+ import { z } from 'zod';
2
+ import { v as ToolMiddleware } from '../types-BdFjg9Tn.js';
3
+ import '@modelcontextprotocol/sdk/types.js';
4
+
5
+ interface CredentialsOptions<T extends z.ZodObject<z.ZodRawShape>> {
6
+ /** Middleware name. Default: "credentials" */
7
+ name?: string;
8
+ /** Message shown to the user. */
9
+ message: string;
10
+ /** Zod schema for the form fields. */
11
+ schema: T;
12
+ /** Verify the submitted credentials. Return user data or null. */
13
+ verify: (fields: z.infer<T>) => Promise<unknown | null>;
14
+ /** Session key to store verified user. Default: "user" */
15
+ sessionKey?: string;
16
+ }
17
+ declare function credentials<T extends z.ZodObject<z.ZodRawShape>>(options: CredentialsOptions<T>): ToolMiddleware;
18
+
19
+ export { type CredentialsOptions, credentials };
@@ -0,0 +1 @@
1
+ import {c as c$1}from'../chunk-VAAZWX4U.mjs';function c(e){let r=e.name??"credentials",t=e.sessionKey??"user";return {name:r,onRegister(){return false},async onCall(s,i){if(s.session.get(t))return i();let a=await s.elicit.form(e.message,e.schema);if(a.action!=="accept")return c$1("Authentication cancelled.");let o=await e.verify(a.content);return o?(s.session.set(t,o),s.session.authorize(r),i()):c$1("Invalid credentials.")}}}export{c as credentials};
@@ -0,0 +1,64 @@
1
+ import { s as ToolContext, v as ToolMiddleware, M as MCPServer } from '../types-BdFjg9Tn.js';
2
+ import '@modelcontextprotocol/sdk/types.js';
3
+ import 'zod';
4
+
5
+ interface CryptoPaymentOptions {
6
+ /** Middleware name. Default: "crypto" */
7
+ name?: string;
8
+ /** Token symbol. Default: "USDC" */
9
+ token?: "USDC" | "USDT" | "DAI" | "ETH" | string;
10
+ /** Recipient wallet address. */
11
+ recipient: string;
12
+ /** Amount in token units. */
13
+ amount: number;
14
+ /** Network. Default: "base" */
15
+ network?: "base" | "base-sepolia" | "ethereum" | "polygon" | "solana" | string;
16
+ /** Base URL of your server. */
17
+ baseUrl: string;
18
+ /** Callback path. Default: "/payment/crypto/callback" */
19
+ callbackPath?: string;
20
+ /** Session key for payment data. Default: "payment" */
21
+ sessionKey?: string;
22
+ /** If true, only charge once per session per tool. Default: false */
23
+ once?: boolean;
24
+ /** Message shown to user. */
25
+ message?: string;
26
+ /** Timeout in ms. Default: 300000 */
27
+ timeout?: number;
28
+ /** Custom skip condition. Takes priority over sessionKey check. */
29
+ skipIf?: (c: ToolContext) => boolean | Promise<boolean>;
30
+ /** Called after payment completes successfully, before next(). */
31
+ onComplete?: (c: ToolContext) => void | Promise<void>;
32
+ }
33
+ /** @deprecated Use `CryptoPaymentOptions` instead. */
34
+ type UsdcPaymentOptions = CryptoPaymentOptions;
35
+ declare function crypto(options: CryptoPaymentOptions): ToolMiddleware;
36
+ /** @deprecated Use `crypto()` from `lynq/crypto` instead. */
37
+ declare const usdcPayment: typeof crypto;
38
+ interface HandleCallbackOptions {
39
+ /** RPC URL for the network. */
40
+ rpcUrl?: string;
41
+ /** Expected recipient address. */
42
+ recipient: string;
43
+ /** Expected amount. */
44
+ amount: number;
45
+ /** Session key. Default: "payment" */
46
+ sessionKey?: string;
47
+ }
48
+ /** @deprecated Use `HandleCallbackOptions` instead. */
49
+ type HandleUsdcCallbackOptions = HandleCallbackOptions;
50
+ /**
51
+ * Handle crypto payment callback. Call from your HTTP callback route.
52
+ * Verifies the on-chain transaction, stores in session, and completes elicitation.
53
+ */
54
+ declare function handleCallback(server: MCPServer, params: {
55
+ state: string;
56
+ txHash: string;
57
+ }, options: HandleCallbackOptions): Promise<{
58
+ success: boolean;
59
+ error?: string;
60
+ }>;
61
+ /** @deprecated Use `handleCallback()` from `lynq/crypto` instead. */
62
+ declare const handleUsdcCallback: typeof handleCallback;
63
+
64
+ export { type CryptoPaymentOptions, type HandleCallbackOptions, type HandleUsdcCallbackOptions, type UsdcPaymentOptions, crypto, handleCallback, handleUsdcCallback, usdcPayment };