@lynq/lynq 0.8.3 → 0.8.4
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 +116 -0
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# @lynq/lynq
|
|
2
|
+
|
|
3
|
+
[](https://github.com/hogekai/lynq/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/@lynq/lynq)
|
|
5
|
+
|
|
6
|
+
Lightweight MCP server framework. Tool visibility control through middleware.
|
|
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
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { createMCPServer } from "@lynq/lynq";
|
|
50
|
+
import { guard } from "@lynq/lynq/guard";
|
|
51
|
+
import { z } from "zod";
|
|
52
|
+
|
|
53
|
+
const server = createMCPServer({ name: "my-server", version: "1.0.0" });
|
|
54
|
+
|
|
55
|
+
server.tool("login", {
|
|
56
|
+
input: z.object({ username: z.string(), password: z.string() }),
|
|
57
|
+
}, async (args, c) => {
|
|
58
|
+
const user = await authenticate(args.username, args.password);
|
|
59
|
+
c.session.set("user", user);
|
|
60
|
+
c.session.authorize("guard");
|
|
61
|
+
return c.text(`Welcome, ${user.name}`);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
server.tool("weather", guard(), {
|
|
65
|
+
description: "Get weather for a city",
|
|
66
|
+
input: z.object({ city: z.string() }),
|
|
67
|
+
}, async (args, c) => {
|
|
68
|
+
return c.text(JSON.stringify(await fetchWeather(args.city)));
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
await server.stdio();
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Features
|
|
75
|
+
|
|
76
|
+
- **Session-Scoped Visibility** — `authorize()` shows tools, `revoke()` hides them. Client notification is automatic.
|
|
77
|
+
- **Hono-Style Middleware** — Global via `server.use()`, per-tool inline. Three hooks: `onRegister`, `onCall`, `onResult`.
|
|
78
|
+
- **Built-in Middleware** — `guard()` `rateLimit()` `logger()` `truncate()` `credentials()` `some()` `every()` `except()`
|
|
79
|
+
- **Response Helpers** — `c.text()` `c.json()` `c.error()` `c.image()` — chainable: `c.text("done").json({ id: 1 })`
|
|
80
|
+
- **Elicitation** — `c.elicit.form(message, zodSchema)` for structured user input. `c.elicit.url()` for external flows.
|
|
81
|
+
- **Framework Adapters** — `server.http()` returns `(Request) => Response`. Mount in Hono, Express, Deno, Workers.
|
|
82
|
+
- **Test Helpers** — `createTestClient()` for in-memory testing. No transport setup.
|
|
83
|
+
- **Tiny Core** — One dependency. ESM only. No config files, no magic.
|
|
84
|
+
|
|
85
|
+
## Middleware Composition
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
import { guard } from "@lynq/lynq/guard";
|
|
89
|
+
import { rateLimit } from "@lynq/lynq/rate-limit";
|
|
90
|
+
import { logger } from "@lynq/lynq/logger";
|
|
91
|
+
|
|
92
|
+
server.use(logger()); // global
|
|
93
|
+
server.tool("search", guard(), rateLimit({ max: 10 }), config, handler); // per-tool stack
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Ecosystem
|
|
97
|
+
|
|
98
|
+
| Package | Description |
|
|
99
|
+
|---|---|
|
|
100
|
+
| [@lynq/github](https://www.npmjs.com/package/@lynq/github) | GitHub OAuth provider |
|
|
101
|
+
| [@lynq/google](https://www.npmjs.com/package/@lynq/google) | Google OAuth provider |
|
|
102
|
+
| [@lynq/stripe](https://www.npmjs.com/package/@lynq/stripe) | Stripe Checkout payment provider |
|
|
103
|
+
| [@lynq/crypto](https://www.npmjs.com/package/@lynq/crypto) | Crypto payment provider |
|
|
104
|
+
| [@lynq/hono](https://www.npmjs.com/package/@lynq/hono) | Hono framework adapter |
|
|
105
|
+
| [@lynq/express](https://www.npmjs.com/package/@lynq/express) | Express framework adapter |
|
|
106
|
+
| [@lynq/store-redis](https://www.npmjs.com/package/@lynq/store-redis) | Redis Store implementation |
|
|
107
|
+
| [@lynq/store-sqlite](https://www.npmjs.com/package/@lynq/store-sqlite) | SQLite Store implementation |
|
|
108
|
+
| [create-lynq](https://www.npmjs.com/package/create-lynq) | CLI scaffold tool |
|
|
109
|
+
|
|
110
|
+
## Documentation
|
|
111
|
+
|
|
112
|
+
[https://hogekai.github.io/lynq/](https://hogekai.github.io/lynq/)
|
|
113
|
+
|
|
114
|
+
## License
|
|
115
|
+
|
|
116
|
+
MIT
|