caplets 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +327 -2
- package/dist/index.js +3271 -106
- package/package.json +7 -3
- package/schemas/caplets-config.schema.json +218 -0
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,14 +1,334 @@
|
|
|
1
1
|
# Caplets
|
|
2
2
|
|
|
3
|
-
Caplets is a
|
|
3
|
+
Caplets is a progressive-disclosure gateway for Model Context Protocol (MCP) servers.
|
|
4
|
+
|
|
5
|
+
Instead of connecting an MCP client to many downstream servers and exposing every tool up
|
|
6
|
+
front, Caplets exposes one top-level tool per configured server. An agent first chooses a
|
|
7
|
+
capability domain, then asks Caplets to list, search, inspect, or call that server's
|
|
8
|
+
underlying tools.
|
|
9
|
+
|
|
10
|
+
This keeps the initial MCP tool list small, makes tool selection easier, and avoids
|
|
11
|
+
flattened tool-name collisions across servers.
|
|
12
|
+
|
|
13
|
+
## Inspiration
|
|
14
|
+
|
|
15
|
+
Caplets is a mashup of two ideas that work well separately but leave a gap together:
|
|
16
|
+
agent skills and MCP servers.
|
|
17
|
+
|
|
18
|
+
Agent skills are great at progressive disclosure. They show an agent a compact capability
|
|
19
|
+
card first, then let it read deeper instructions only when that skill is relevant. MCP
|
|
20
|
+
servers are great at live tool execution, but most clients expose their tools as one flat
|
|
21
|
+
list up front. That means a powerful MCP setup can flood the agent with every tool from
|
|
22
|
+
every server before it knows which capability area matters.
|
|
23
|
+
|
|
24
|
+
Caplets borrows the skill-shaped discovery model and applies it to MCP. Each downstream
|
|
25
|
+
server becomes a skill-like capability card first; its actual MCP tools stay hidden until
|
|
26
|
+
the agent chooses that server and asks to search, list, inspect, or call them.
|
|
27
|
+
|
|
28
|
+
## What It Does
|
|
29
|
+
|
|
30
|
+
- Reads downstream MCP server definitions from `~/.caplets/config.json`.
|
|
31
|
+
- Registers one generated MCP tool for each enabled server.
|
|
32
|
+
- Uses the configured server ID as the generated tool name.
|
|
33
|
+
- Uses the configured `name` and `description` as the capability card shown to agents.
|
|
34
|
+
- Starts downstream servers lazily when an operation needs them.
|
|
35
|
+
- Supports stdio, Streamable HTTP, and legacy HTTP+SSE downstream servers.
|
|
36
|
+
- Lets agents `list_tools`, `search_tools`, `get_tool`, and `call_tool` within one selected server namespace.
|
|
37
|
+
- Preserves downstream tool results instead of rewriting them into a custom format.
|
|
38
|
+
- Redacts secrets from structured errors.
|
|
39
|
+
- Supports static remote auth and OAuth token storage for remote servers.
|
|
40
|
+
|
|
41
|
+
## Install
|
|
42
|
+
|
|
43
|
+
Caplets requires Node.js 22 or newer.
|
|
44
|
+
|
|
45
|
+
```sh
|
|
46
|
+
pnpm add -g caplets
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
For local development from this repository:
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
pnpm install
|
|
53
|
+
pnpm build
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Configure
|
|
57
|
+
|
|
58
|
+
Create a starter `~/.caplets/config.json`:
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
caplets init
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The generated config includes a disabled example server. Replace it with the MCP servers
|
|
65
|
+
you want Caplets to expose:
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"$schema": "https://raw.githubusercontent.com/spiritledsoftware/caplets/main/schemas/caplets-config.schema.json",
|
|
70
|
+
"version": 1,
|
|
71
|
+
"defaultSearchLimit": 20,
|
|
72
|
+
"maxSearchLimit": 50,
|
|
73
|
+
"mcpServers": {
|
|
74
|
+
"filesystem": {
|
|
75
|
+
"name": "Project Files",
|
|
76
|
+
"description": "Read, search, and edit local project files.",
|
|
77
|
+
"command": "npx",
|
|
78
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/you/code"],
|
|
79
|
+
"cwd": "/home/you/code",
|
|
80
|
+
"startupTimeoutMs": 10000,
|
|
81
|
+
"callTimeoutMs": 60000,
|
|
82
|
+
"toolCacheTtlMs": 30000
|
|
83
|
+
},
|
|
84
|
+
"docs": {
|
|
85
|
+
"name": "Hosted Docs",
|
|
86
|
+
"description": "Search hosted product and API documentation.",
|
|
87
|
+
"transport": "http",
|
|
88
|
+
"url": "https://mcp.example.com/mcp",
|
|
89
|
+
"auth": {
|
|
90
|
+
"type": "bearer",
|
|
91
|
+
"token": "$env:DOCS_MCP_TOKEN"
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The default config path can be overridden with `CAPLETS_CONFIG`:
|
|
99
|
+
|
|
100
|
+
```sh
|
|
101
|
+
CAPLETS_CONFIG=/path/to/config.json caplets init
|
|
102
|
+
CAPLETS_CONFIG=/path/to/config.json caplets serve
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Caplets validates this file at startup. Config changes take effect after restarting the
|
|
106
|
+
Caplets MCP server.
|
|
107
|
+
|
|
108
|
+
The optional `$schema` field points editors at the generated JSON Schema in
|
|
109
|
+
[`schemas/caplets-config.schema.json`](schemas/caplets-config.schema.json). CI verifies that
|
|
110
|
+
the committed schema stays in sync with the Zod config validator.
|
|
111
|
+
|
|
112
|
+
`caplets init` refuses to overwrite an existing config. To intentionally replace the file:
|
|
113
|
+
|
|
114
|
+
```sh
|
|
115
|
+
caplets init --force
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Server IDs
|
|
119
|
+
|
|
120
|
+
Each key under `mcpServers` is the stable server ID. It becomes the generated MCP tool
|
|
121
|
+
name exactly, so keep it short and specific:
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"mcpServers": {
|
|
126
|
+
"linear": {
|
|
127
|
+
"name": "Linear",
|
|
128
|
+
"description": "Read and update Linear issues and projects.",
|
|
129
|
+
"command": "npx",
|
|
130
|
+
"args": ["-y", "linear-mcp-server"]
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Server IDs must match `^[a-zA-Z0-9_-]{1,64}$`. Spaces, dots, slashes, colons, and
|
|
137
|
+
Unicode IDs are rejected.
|
|
138
|
+
|
|
139
|
+
### Stdio Servers
|
|
140
|
+
|
|
141
|
+
Use `command` for a local stdio MCP server. `args`, `env`, and `cwd` are optional.
|
|
142
|
+
|
|
143
|
+
```json
|
|
144
|
+
{
|
|
145
|
+
"name": "Local Tools",
|
|
146
|
+
"description": "Run local development tools through stdio.",
|
|
147
|
+
"command": "node",
|
|
148
|
+
"args": ["./server.mjs"],
|
|
149
|
+
"env": {
|
|
150
|
+
"API_TOKEN": "${API_TOKEN}"
|
|
151
|
+
},
|
|
152
|
+
"cwd": "/home/you/project"
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Remote Servers
|
|
157
|
+
|
|
158
|
+
Use `transport` and `url` for remote MCP servers.
|
|
159
|
+
|
|
160
|
+
```json
|
|
161
|
+
{
|
|
162
|
+
"name": "Remote Docs",
|
|
163
|
+
"description": "Search documentation from a remote MCP server.",
|
|
164
|
+
"transport": "http",
|
|
165
|
+
"url": "https://mcp.example.com/mcp",
|
|
166
|
+
"auth": {
|
|
167
|
+
"type": "headers",
|
|
168
|
+
"headers": {
|
|
169
|
+
"x-api-key": "$env:REMOTE_DOCS_API_KEY"
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
`transport` can be `http` for MCP Streamable HTTP or `sse` for legacy HTTP+SSE. Remote
|
|
176
|
+
URLs must use `https://`, except loopback development URLs such as `http://localhost`.
|
|
177
|
+
|
|
178
|
+
### Authentication
|
|
179
|
+
|
|
180
|
+
Remote servers can use:
|
|
181
|
+
|
|
182
|
+
- `{"type": "none"}`
|
|
183
|
+
- `{"type": "bearer", "token": "$env:TOKEN"}`
|
|
184
|
+
- `{"type": "headers", "headers": {"x-api-key": "$env:API_KEY"}}`
|
|
185
|
+
- `{"type": "oauth2", ...}`
|
|
186
|
+
|
|
187
|
+
For OAuth-backed remote servers, authenticate once with:
|
|
188
|
+
|
|
189
|
+
```sh
|
|
190
|
+
caplets auth login <server>
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
For headless terminals:
|
|
194
|
+
|
|
195
|
+
```sh
|
|
196
|
+
caplets auth login <server> --no-open
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
OAuth tokens are stored under `~/.caplets/auth/<server>.json` with owner-only file
|
|
200
|
+
permissions where the platform supports them. When an OAuth token expires, run
|
|
201
|
+
`caplets auth login <server>` again.
|
|
202
|
+
|
|
203
|
+
To inspect or remove stored OAuth credentials:
|
|
204
|
+
|
|
205
|
+
```sh
|
|
206
|
+
caplets auth list
|
|
207
|
+
caplets auth logout <server>
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Optional Server Settings
|
|
211
|
+
|
|
212
|
+
Every server can set:
|
|
213
|
+
|
|
214
|
+
- `startupTimeoutMs`: timeout for starting or checking the downstream server. Defaults to `10000`.
|
|
215
|
+
- `callTimeoutMs`: timeout for downstream tool calls. Defaults to `60000`.
|
|
216
|
+
- `toolCacheTtlMs`: how long downstream tool metadata stays fresh. Defaults to `30000`; `0` refreshes every time.
|
|
217
|
+
- `disabled`: omit the server from Caplets discovery. Defaults to `false`.
|
|
218
|
+
|
|
219
|
+
## Add Caplets To An MCP Client
|
|
220
|
+
|
|
221
|
+
Configure your MCP client to run Caplets as a stdio server:
|
|
222
|
+
|
|
223
|
+
```json
|
|
224
|
+
{
|
|
225
|
+
"mcpServers": {
|
|
226
|
+
"caplets": {
|
|
227
|
+
"command": "caplets",
|
|
228
|
+
"args": ["serve"]
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
If your client starts the configured command directly, `caplets` without arguments also
|
|
235
|
+
starts the MCP server. `serve` is explicit and recommended for clarity.
|
|
236
|
+
|
|
237
|
+
## How Agents Use It
|
|
238
|
+
|
|
239
|
+
Caplets initially exposes one MCP tool per enabled server. If the config has `filesystem`
|
|
240
|
+
and `docs`, the client sees two top-level tools: `filesystem` and `docs`.
|
|
241
|
+
|
|
242
|
+
Each generated server tool accepts an `operation`:
|
|
243
|
+
|
|
244
|
+
```json
|
|
245
|
+
{
|
|
246
|
+
"operation": "list_tools"
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Search within a selected server:
|
|
251
|
+
|
|
252
|
+
```json
|
|
253
|
+
{
|
|
254
|
+
"operation": "search_tools",
|
|
255
|
+
"query": "read file",
|
|
256
|
+
"limit": 10
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Inspect one exact downstream tool:
|
|
261
|
+
|
|
262
|
+
```json
|
|
263
|
+
{
|
|
264
|
+
"operation": "get_tool",
|
|
265
|
+
"tool": "read_file"
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Call one exact downstream tool:
|
|
270
|
+
|
|
271
|
+
```json
|
|
272
|
+
{
|
|
273
|
+
"operation": "call_tool",
|
|
274
|
+
"tool": "read_file",
|
|
275
|
+
"arguments": {
|
|
276
|
+
"path": "/home/you/code/project/README.md"
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
Available operations:
|
|
282
|
+
|
|
283
|
+
- `get_server`: return the configured capability card without starting the downstream server.
|
|
284
|
+
- `check_server`: start or connect to the downstream server and verify its tool list.
|
|
285
|
+
- `list_tools`: return compact downstream tool metadata.
|
|
286
|
+
- `search_tools`: search downstream tool names and descriptions within this server.
|
|
287
|
+
- `get_tool`: return full metadata for one exact downstream tool.
|
|
288
|
+
- `call_tool`: invoke one exact downstream tool with JSON object arguments.
|
|
289
|
+
|
|
290
|
+
Requests are strict: operation-specific extra fields are rejected, and `call_tool` requires
|
|
291
|
+
`arguments` to be a JSON object.
|
|
4
292
|
|
|
5
293
|
## Development
|
|
6
294
|
|
|
7
295
|
```sh
|
|
8
296
|
pnpm install
|
|
297
|
+
pnpm dev
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Useful commands:
|
|
301
|
+
|
|
302
|
+
```sh
|
|
303
|
+
pnpm build
|
|
304
|
+
pnpm test
|
|
305
|
+
pnpm typecheck
|
|
306
|
+
pnpm lint
|
|
307
|
+
pnpm format:check
|
|
308
|
+
pnpm schema:generate
|
|
309
|
+
pnpm schema:check
|
|
9
310
|
pnpm verify
|
|
10
311
|
```
|
|
11
312
|
|
|
313
|
+
`pnpm dev` rebuilds on source changes and restarts the local stdio MCP server from
|
|
314
|
+
`dist/index.js`. Use it for local development, not as the command configured in an MCP
|
|
315
|
+
client, because build logs are written to stdout.
|
|
316
|
+
|
|
317
|
+
## Product Notes
|
|
318
|
+
|
|
319
|
+
The product requirements document lives at
|
|
320
|
+
[`docs/product/caplets-progressive-mcp-disclosure-prd.md`](docs/product/caplets-progressive-mcp-disclosure-prd.md).
|
|
321
|
+
It describes the progressive MCP disclosure model, configuration rules, MVP tool surface,
|
|
322
|
+
security expectations, and non-goals.
|
|
323
|
+
|
|
324
|
+
Caplets intentionally does not provide a hosted service, GUI, cross-server flattened tool
|
|
325
|
+
search, automatic MCP client config import, or namespaced flattened tool IDs such as
|
|
326
|
+
`server.tool`.
|
|
327
|
+
|
|
328
|
+
Progressive disclosure is context management, not a security boundary. Caplets reduces the
|
|
329
|
+
tool surface shown to the agent up front, but downstream MCP servers remain responsible for
|
|
330
|
+
their own tool behavior and any client-side confirmations.
|
|
331
|
+
|
|
12
332
|
## Release Flow
|
|
13
333
|
|
|
14
334
|
User-facing changes should include a changeset:
|
|
@@ -17,4 +337,9 @@ User-facing changes should include a changeset:
|
|
|
17
337
|
pnpm changeset
|
|
18
338
|
```
|
|
19
339
|
|
|
20
|
-
Merging changesets to `main` lets the release workflow open a version PR. Merging that
|
|
340
|
+
Merging changesets to `main` lets the release workflow open a version PR. Merging that
|
|
341
|
+
version PR publishes the package to npm through trusted publishing.
|
|
342
|
+
|
|
343
|
+
## License
|
|
344
|
+
|
|
345
|
+
MIT
|