@mappies/miniwat-agent 0.5.0 → 0.8.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.
- package/README.md +914 -1
- package/dist/index.cjs +481 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +83 -4
- package/dist/index.d.ts +83 -4
- package/dist/index.js +479 -5
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1 +1,914 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Miniwat Agent
|
|
2
|
+
|
|
3
|
+
> Build conversational AI applications with OpenAI or AWS Bedrock in
|
|
4
|
+
> just a few lines of code.
|
|
5
|
+
|
|
6
|
+
The `Agent` class is the main entry point to miniwat. It combines a
|
|
7
|
+
language model, optional system instructions, an optional planner, conversation history, and
|
|
8
|
+
streaming into a simple API.
|
|
9
|
+
|
|
10
|
+
``` ts
|
|
11
|
+
const model = new OpenAiModel({
|
|
12
|
+
modelId: "gpt-4.1-mini",
|
|
13
|
+
apiKey: process.env.OPENAI_API_KEY
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const agent = new Agent({ model });
|
|
17
|
+
const session = new Session();
|
|
18
|
+
|
|
19
|
+
const response = await agent.invoke("Hello!", session);
|
|
20
|
+
|
|
21
|
+
console.log(response.message.content);
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
------------------------------------------------------------------------
|
|
25
|
+
|
|
26
|
+
# Why miniwat?
|
|
27
|
+
|
|
28
|
+
Most LLM libraries require you to manually:
|
|
29
|
+
|
|
30
|
+
- Track conversation history
|
|
31
|
+
- Send the entire message list every request
|
|
32
|
+
- Configure streaming
|
|
33
|
+
- Manage model-specific APIs
|
|
34
|
+
|
|
35
|
+
With miniwat you work with only three objects:
|
|
36
|
+
|
|
37
|
+
``` text
|
|
38
|
+
Model
|
|
39
|
+
↓
|
|
40
|
+
Agent
|
|
41
|
+
↓
|
|
42
|
+
Session
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Everything else happens automatically.
|
|
46
|
+
|
|
47
|
+
------------------------------------------------------------------------
|
|
48
|
+
|
|
49
|
+
# Installation
|
|
50
|
+
|
|
51
|
+
``` bash
|
|
52
|
+
npm install @mappies/miniwat-agent
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Choose one model implementation.
|
|
56
|
+
|
|
57
|
+
``` bash
|
|
58
|
+
npm install @mappies/miniwat-provider-openai
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
or
|
|
62
|
+
|
|
63
|
+
``` bash
|
|
64
|
+
npm install @mappies/miniwat-provider-bedrock
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
------------------------------------------------------------------------
|
|
68
|
+
|
|
69
|
+
# Quick Start
|
|
70
|
+
|
|
71
|
+
The following example creates an AI assistant using OpenAI. It can be copied directly into a project and run as-is.
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
import { Agent, Session } from "@mappies/miniwat-agent";
|
|
75
|
+
import { OpenAiModel } from "@mappies/miniwat-provider-openai";
|
|
76
|
+
|
|
77
|
+
async function main() {
|
|
78
|
+
const model = new OpenAiModel({
|
|
79
|
+
modelId: "gpt-4.1-mini",
|
|
80
|
+
apiKey: process.env.OPENAI_API_KEY
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const agent = new Agent({
|
|
84
|
+
model,
|
|
85
|
+
instruction: {
|
|
86
|
+
system: {
|
|
87
|
+
value: "You are a helpful assistant."
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const session = new Session();
|
|
93
|
+
|
|
94
|
+
const response = await agent.invoke(
|
|
95
|
+
"Explain what TypeScript is in one paragraph.",
|
|
96
|
+
session
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
console.log(response.message.content);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
main().catch(console.error);
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Run the example after setting your OpenAI API key.
|
|
106
|
+
|
|
107
|
+
**Linux / macOS**
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
export OPENAI_API_KEY=your_api_key
|
|
111
|
+
node app.js
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**Windows PowerShell**
|
|
115
|
+
|
|
116
|
+
```powershell
|
|
117
|
+
$env:OPENAI_API_KEY="your_api_key"
|
|
118
|
+
node app.js
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Congratulations! You've built your first miniwat application.
|
|
122
|
+
|
|
123
|
+
The rest of this guide explains each part of the example in more detail.
|
|
124
|
+
|
|
125
|
+
------------------------------------------------------------------------
|
|
126
|
+
|
|
127
|
+
# Your First Agent
|
|
128
|
+
|
|
129
|
+
## Step 1 --- Create a model
|
|
130
|
+
|
|
131
|
+
### OpenAI
|
|
132
|
+
|
|
133
|
+
``` ts
|
|
134
|
+
import { OpenAiModel } from "@mappies/miniwat-provider-openai";
|
|
135
|
+
|
|
136
|
+
const model = new OpenAiModel({
|
|
137
|
+
modelId: "gpt-4.1-mini",
|
|
138
|
+
apiKey: process.env.OPENAI_API_KEY
|
|
139
|
+
});
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### AWS Bedrock
|
|
143
|
+
|
|
144
|
+
``` ts
|
|
145
|
+
import { BedrockModel } from "@mappies/miniwat-provider-bedrock";
|
|
146
|
+
|
|
147
|
+
const model = new BedrockModel({
|
|
148
|
+
region: "us-east-1",
|
|
149
|
+
modelId: "anthropic.claude-3-5-sonnet-20240620-v1:0"
|
|
150
|
+
});
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
------------------------------------------------------------------------
|
|
154
|
+
|
|
155
|
+
## Step 2 --- Create an Agent
|
|
156
|
+
|
|
157
|
+
``` ts
|
|
158
|
+
const agent = new Agent({
|
|
159
|
+
model
|
|
160
|
+
});
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
At this point the agent is ready to answer prompts.
|
|
164
|
+
|
|
165
|
+
Planning is optional. When no planner is configured, the agent sends prompts directly to the model. To enable multi-step planning, provide a planner when creating the agent.
|
|
166
|
+
|
|
167
|
+
``` ts
|
|
168
|
+
import { DefaultPlanner } from "@mappies/miniwat-agent";
|
|
169
|
+
|
|
170
|
+
const planner = new DefaultPlanner(model);
|
|
171
|
+
|
|
172
|
+
const agent = new Agent({
|
|
173
|
+
model,
|
|
174
|
+
planner
|
|
175
|
+
});
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
------------------------------------------------------------------------
|
|
179
|
+
|
|
180
|
+
## Step 3 --- Create a Session
|
|
181
|
+
|
|
182
|
+
``` ts
|
|
183
|
+
const session = new Session();
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
A `Session` stores the conversation history.
|
|
187
|
+
|
|
188
|
+
Think of it as a chat thread.
|
|
189
|
+
|
|
190
|
+
Reuse the same session if you want the model to remember previous
|
|
191
|
+
messages.
|
|
192
|
+
|
|
193
|
+
------------------------------------------------------------------------
|
|
194
|
+
|
|
195
|
+
## Step 4 --- Ask a question
|
|
196
|
+
|
|
197
|
+
``` ts
|
|
198
|
+
const response = await agent.invoke(
|
|
199
|
+
"Explain TypeScript generics.",
|
|
200
|
+
session
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
console.log(response.message.content);
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
That's all you need to build a basic chatbot.
|
|
207
|
+
|
|
208
|
+
------------------------------------------------------------------------
|
|
209
|
+
|
|
210
|
+
# Conversation Memory
|
|
211
|
+
|
|
212
|
+
Every call automatically appends:
|
|
213
|
+
|
|
214
|
+
1. your prompt
|
|
215
|
+
2. the assistant response
|
|
216
|
+
|
|
217
|
+
to the session.
|
|
218
|
+
|
|
219
|
+
``` ts
|
|
220
|
+
await agent.invoke("My name is Alice.", session);
|
|
221
|
+
|
|
222
|
+
await agent.invoke(
|
|
223
|
+
"What's my name?",
|
|
224
|
+
session
|
|
225
|
+
);
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Because both requests share the same session, the model remembers the
|
|
229
|
+
earlier conversation.
|
|
230
|
+
|
|
231
|
+
To start over:
|
|
232
|
+
|
|
233
|
+
``` ts
|
|
234
|
+
const newSession = new Session();
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
------------------------------------------------------------------------
|
|
238
|
+
|
|
239
|
+
# Customizing the Assistant
|
|
240
|
+
|
|
241
|
+
Add a system instruction.
|
|
242
|
+
|
|
243
|
+
``` ts
|
|
244
|
+
const agent = new Agent({
|
|
245
|
+
model,
|
|
246
|
+
instruction: {
|
|
247
|
+
system: {
|
|
248
|
+
value: "You are a friendly programming tutor."
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
This instruction is applied automatically to every request.
|
|
255
|
+
|
|
256
|
+
------------------------------------------------------------------------
|
|
257
|
+
|
|
258
|
+
# Streaming Responses
|
|
259
|
+
|
|
260
|
+
For chat applications, streaming provides a better user experience.
|
|
261
|
+
|
|
262
|
+
``` ts
|
|
263
|
+
const stream = await agent.stream(
|
|
264
|
+
"Write a short story.",
|
|
265
|
+
session
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
stream.on("data", chunk => {
|
|
269
|
+
process.stdout.write(chunk);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
await (stream as any).promise;
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
The stream promise ensures the completed response is written back into
|
|
276
|
+
the session.
|
|
277
|
+
|
|
278
|
+
------------------------------------------------------------------------
|
|
279
|
+
|
|
280
|
+
# Model Options
|
|
281
|
+
|
|
282
|
+
Pass inference settings per request.
|
|
283
|
+
|
|
284
|
+
``` ts
|
|
285
|
+
await agent.invoke(prompt, session, {
|
|
286
|
+
inference: {
|
|
287
|
+
temperature: 0.2,
|
|
288
|
+
maxTokens: 800,
|
|
289
|
+
topP: 0.9
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
A temperature of **0.2** is recommended for most assistants.
|
|
295
|
+
|
|
296
|
+
------------------------------------------------------------------------
|
|
297
|
+
|
|
298
|
+
# Events
|
|
299
|
+
|
|
300
|
+
Applications often need progress updates.
|
|
301
|
+
|
|
302
|
+
``` ts
|
|
303
|
+
await agent.invoke(prompt, session, {
|
|
304
|
+
event: {
|
|
305
|
+
onThinking: async text => {
|
|
306
|
+
console.log(text);
|
|
307
|
+
},
|
|
308
|
+
|
|
309
|
+
onTooling: async message => {
|
|
310
|
+
console.log(message);
|
|
311
|
+
},
|
|
312
|
+
|
|
313
|
+
onResponse: async message => {
|
|
314
|
+
console.log(message.content);
|
|
315
|
+
},
|
|
316
|
+
|
|
317
|
+
onPlanUpdated: async plan => {
|
|
318
|
+
console.log(plan);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
`onPlanUpdated` is called when a configured planner's plan changes during execution.
|
|
325
|
+
|
|
326
|
+
Typical uses include:
|
|
327
|
+
|
|
328
|
+
- updating a status indicator
|
|
329
|
+
- logging tool execution
|
|
330
|
+
- displaying plan execution progress
|
|
331
|
+
- saving completed responses
|
|
332
|
+
|
|
333
|
+
------------------------------------------------------------------------
|
|
334
|
+
|
|
335
|
+
# Building a Chat Loop
|
|
336
|
+
|
|
337
|
+
``` ts
|
|
338
|
+
while (true) {
|
|
339
|
+
const response = await agent.invoke(userInput, session);
|
|
340
|
+
|
|
341
|
+
console.log(response.message.content);
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
Notice there is no manual message management.
|
|
346
|
+
|
|
347
|
+
The session grows automatically.
|
|
348
|
+
|
|
349
|
+
------------------------------------------------------------------------
|
|
350
|
+
|
|
351
|
+
# Using MCP Tools
|
|
352
|
+
|
|
353
|
+
One of miniwat's primary design goals is to make AI agents **safe to use in production**.
|
|
354
|
+
|
|
355
|
+
Unlike many agent frameworks that allow language models to connect to arbitrary MCP servers, **miniwat takes a security-first approach**. Only **miniwat-approved MCP packages** can be used by an application. MCP packages are **not** downloaded or installed automatically—they must be explicitly installed with `npm` before they can be configured and used.
|
|
356
|
+
|
|
357
|
+
This explicit opt-in model helps reduce risks such as:
|
|
358
|
+
|
|
359
|
+
- Executing untrusted code
|
|
360
|
+
- Loading unexpected third-party MCP servers
|
|
361
|
+
- Accessing unauthorized local or network resources
|
|
362
|
+
- Accidentally exposing secrets
|
|
363
|
+
- Server-Side Request Forgery (SSRF)
|
|
364
|
+
- Prompt injection through unsafe tools
|
|
365
|
+
- Data exfiltration
|
|
366
|
+
|
|
367
|
+
The philosophy is simple:
|
|
368
|
+
|
|
369
|
+
> **Powerful AI agents require trustworthy tools.**
|
|
370
|
+
|
|
371
|
+
By requiring applications to explicitly install and configure approved MCP packages, miniwat gives developers complete control over the capabilities exposed to their agents while maintaining a strong security posture.
|
|
372
|
+
|
|
373
|
+
## Serverless MCP Architecture
|
|
374
|
+
|
|
375
|
+
miniwat is also designed around a **serverless MCP architecture**.
|
|
376
|
+
|
|
377
|
+
Rather than communicating with long-running MCP servers over stdio, HTTP, or WebSockets, miniwat executes **functions exported by locally installed npm packages**. This eliminates the need to deploy, monitor, and secure separate MCP server processes, making miniwat a natural fit for modern serverless platforms.
|
|
378
|
+
|
|
379
|
+
This design provides several advantages:
|
|
380
|
+
|
|
381
|
+
- **Lower latency** – Tool functions execute directly within your application process.
|
|
382
|
+
- **Simpler deployment** – No MCP servers need to be started or managed.
|
|
383
|
+
- **Reduced operational overhead** – Deploy a single application instead of multiple services.
|
|
384
|
+
- **Improved security** – Only explicitly installed and approved MCP packages can be executed.
|
|
385
|
+
- **Serverless friendly** – Works naturally in environments such as AWS Lambda, Azure Functions, and Google Cloud Functions, where long-running MCP servers are impractical.
|
|
386
|
+
|
|
387
|
+
Because miniwat executes functions instead of connecting to external MCP servers, it uses its own `mcp.json` format. Rather than describing how to connect to remote servers, the configuration describes:
|
|
388
|
+
|
|
389
|
+
- which npm package provides the MCP implementation
|
|
390
|
+
- which tool definitions from that package are exposed to the language model
|
|
391
|
+
- which environment variables are required as secrets
|
|
392
|
+
|
|
393
|
+
This approach keeps MCP configuration simple while making deployments portable, secure, and well suited for serverless applications.
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
397
|
+
## Available MCP Servers
|
|
398
|
+
|
|
399
|
+
The following MCP servers are currently approved for use with miniwat.
|
|
400
|
+
|
|
401
|
+
| MCP | npm Package | Description | Repository |
|
|
402
|
+
|-----|-------------|-------------|------------|
|
|
403
|
+
| **Weather** | `@mappies/miniwat-mcp-weather` | Provides weather tools, including current weather and daily forecast lookup. | `https://gitlab.com/mappies/miniwat/mcp/weather` |
|
|
404
|
+
| **Web** | `@mappies/miniwat-mcp-web` | Provides web tools, including web search and safe URL fetching. | `https://gitlab.com/mappies/miniwat/mcp/web` |
|
|
405
|
+
| **Trello** | `@mappies/miniwat-mcp-trello` | Provides Trello tools for boards, lists, cards, labels, members, and workspaces. | `https://gitlab.com/mappies/miniwat/mcp/trello` |
|
|
406
|
+
|
|
407
|
+
> **Important**
|
|
408
|
+
>
|
|
409
|
+
> miniwat does not download MCP packages automatically. You must install the MCP packages yourself.
|
|
410
|
+
|
|
411
|
+
```bash
|
|
412
|
+
npm install @mappies/miniwat-mcp-weather
|
|
413
|
+
npm install @mappies/miniwat-mcp-web
|
|
414
|
+
npm install @mappies/miniwat-mcp-trello
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
419
|
+
## miniwat MCP Config Format
|
|
420
|
+
|
|
421
|
+
miniwat uses its own MCP configuration format.
|
|
422
|
+
|
|
423
|
+
It does **not** use the standard MCP `mcp.json` format.
|
|
424
|
+
|
|
425
|
+
A miniwat MCP config uses a top-level `mcpServers` object. Each MCP server entry defines:
|
|
426
|
+
|
|
427
|
+
- the npm package that provides the MCP implementation
|
|
428
|
+
- the tool definitions to expose to the language model
|
|
429
|
+
- optional `secrets` required by that MCP
|
|
430
|
+
|
|
431
|
+
Each MCP package may provide many tool definitions. The `tools` array allows you to explicitly choose which tool definitions are exposed to your agent. This follows the principle of least privilege—only the capabilities your application requires are made available to the language model.
|
|
432
|
+
|
|
433
|
+
For example, the Weather MCP provides both current weather and weather forecast tools. If your application only needs current weather, simply omit the forecast tool from the configuration.
|
|
434
|
+
|
|
435
|
+
Example `mcp.json`:
|
|
436
|
+
|
|
437
|
+
```json
|
|
438
|
+
{
|
|
439
|
+
"mcpServers": {
|
|
440
|
+
"Weather": {
|
|
441
|
+
"package": "@mappies/miniwat-mcp-weather",
|
|
442
|
+
"tools": [
|
|
443
|
+
{
|
|
444
|
+
"import": "GET_CURRENT_WEATHER_DEFINITION"
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
"import": "GET_WEATHER_FORECAST_DEFINITION"
|
|
448
|
+
}
|
|
449
|
+
]
|
|
450
|
+
},
|
|
451
|
+
"Web": {
|
|
452
|
+
"package": "@mappies/miniwat-mcp-web",
|
|
453
|
+
"tools": [
|
|
454
|
+
{
|
|
455
|
+
"import": "SEARCH_WEB_DEFINITION"
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
"import": "FETCH_URL_DEFINITION"
|
|
459
|
+
}
|
|
460
|
+
]
|
|
461
|
+
},
|
|
462
|
+
"Trello": {
|
|
463
|
+
"package": "@mappies/miniwat-mcp-trello",
|
|
464
|
+
"secrets": [
|
|
465
|
+
"TRELLO_API_KEY",
|
|
466
|
+
"TRELLO_TOKEN"
|
|
467
|
+
],
|
|
468
|
+
"tools": [
|
|
469
|
+
{
|
|
470
|
+
"import": "LIST_TRELLO_BOARDS_DEFINITION"
|
|
471
|
+
},
|
|
472
|
+
{
|
|
473
|
+
"import": "CREATE_TRELLO_BOARD_DEFINITION"
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
"import": "GET_TRELLO_BOARD_DEFINITION"
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
"import": "LIST_TRELLO_LISTS_DEFINITION"
|
|
480
|
+
},
|
|
481
|
+
{
|
|
482
|
+
"import": "MOVE_TRELLO_LIST_DEFINITION"
|
|
483
|
+
},
|
|
484
|
+
{
|
|
485
|
+
"import": "GET_TRELLO_CARD_DEFINITION"
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
"import": "LIST_TRELLO_LABELS_DEFINITION"
|
|
489
|
+
},
|
|
490
|
+
{
|
|
491
|
+
"import": "UPDATE_CARD_TITLE_DEFINITION"
|
|
492
|
+
},
|
|
493
|
+
{
|
|
494
|
+
"import": "REMOVE_CARD_LABEL_DEFINITION"
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
"import": "ADD_CARD_LABEL_DEFINITION"
|
|
498
|
+
},
|
|
499
|
+
{
|
|
500
|
+
"import": "ADD_MEMBER_TO_BOARD_DEFINITION"
|
|
501
|
+
},
|
|
502
|
+
{
|
|
503
|
+
"import": "LIST_TRELLO_CARDS_DEFINITION"
|
|
504
|
+
},
|
|
505
|
+
{
|
|
506
|
+
"import": "LIST_TRELLO_WORKSPACES_DEFINITION"
|
|
507
|
+
}
|
|
508
|
+
]
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
---
|
|
515
|
+
|
|
516
|
+
## Configuring a Model with MCP Tools
|
|
517
|
+
|
|
518
|
+
In miniwat, MCP tools are passed to the model through the `mcpConfig` option.
|
|
519
|
+
|
|
520
|
+
For example, import your `mcp.json` file:
|
|
521
|
+
|
|
522
|
+
```ts
|
|
523
|
+
import mcpConfig from "./mcp.json";
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
Then pass it to the model provider.
|
|
527
|
+
|
|
528
|
+
### OpenAI
|
|
529
|
+
|
|
530
|
+
```ts
|
|
531
|
+
import { OpenAiModel } from "@mappies/miniwat-provider-openai";
|
|
532
|
+
import mcpConfig from "./mcp.json";
|
|
533
|
+
|
|
534
|
+
const model = new OpenAiModel({
|
|
535
|
+
modelId: "gpt-4.1-mini",
|
|
536
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
537
|
+
mcpConfig
|
|
538
|
+
});
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
### AWS Bedrock
|
|
542
|
+
|
|
543
|
+
```ts
|
|
544
|
+
import { BedrockModel } from "@mappies/miniwat-provider-bedrock";
|
|
545
|
+
import mcpConfig from "./mcp.json";
|
|
546
|
+
|
|
547
|
+
const model = new BedrockModel({
|
|
548
|
+
region: "us-east-1",
|
|
549
|
+
modelId: "your-bedrock-model-id-or-arn",
|
|
550
|
+
mcpConfig
|
|
551
|
+
});
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
The provider creates a `ToolDispatcher` internally from the given `mcpConfig`.
|
|
555
|
+
|
|
556
|
+
---
|
|
557
|
+
|
|
558
|
+
## Using MCP Tools with Agent
|
|
559
|
+
|
|
560
|
+
After the model is configured with `mcpConfig`, create an `Agent` normally.
|
|
561
|
+
|
|
562
|
+
```ts
|
|
563
|
+
import { Agent, Session } from "@mappies/miniwat-agent";
|
|
564
|
+
|
|
565
|
+
const agent = new Agent({
|
|
566
|
+
model,
|
|
567
|
+
instruction: {
|
|
568
|
+
system: {
|
|
569
|
+
value: "You are a helpful assistant."
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
const session = new Session();
|
|
575
|
+
|
|
576
|
+
const response = await agent.invoke(
|
|
577
|
+
"What's the weather in Blacksburg tomorrow?",
|
|
578
|
+
session
|
|
579
|
+
);
|
|
580
|
+
|
|
581
|
+
console.log(response.message.content);
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
The model can now discover the configured miniwat-approved tools and call them when needed.
|
|
585
|
+
|
|
586
|
+
---
|
|
587
|
+
|
|
588
|
+
## Passing Secrets to MCP Servers
|
|
589
|
+
|
|
590
|
+
Some MCP servers require credentials.
|
|
591
|
+
|
|
592
|
+
For example, the Trello MCP requires:
|
|
593
|
+
|
|
594
|
+
```json
|
|
595
|
+
"secrets": [
|
|
596
|
+
"TRELLO_API_KEY",
|
|
597
|
+
"TRELLO_TOKEN"
|
|
598
|
+
]
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
The `secrets` array tells miniwat which environment variables are required by that MCP server.
|
|
602
|
+
|
|
603
|
+
Do **not** put secret values directly inside `mcp.json`.
|
|
604
|
+
|
|
605
|
+
Instead, define them as environment variables before starting your application.
|
|
606
|
+
|
|
607
|
+
### Linux / macOS
|
|
608
|
+
|
|
609
|
+
```bash
|
|
610
|
+
export TRELLO_API_KEY=your_trello_api_key
|
|
611
|
+
export TRELLO_TOKEN=your_trello_token
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
### Windows PowerShell
|
|
615
|
+
|
|
616
|
+
```powershell
|
|
617
|
+
$env:TRELLO_API_KEY="your_trello_api_key"
|
|
618
|
+
$env:TRELLO_TOKEN="your_trello_token"
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
Your `mcp.json` should only contain the names of the required secrets:
|
|
622
|
+
|
|
623
|
+
```json
|
|
624
|
+
{
|
|
625
|
+
"mcpServers": {
|
|
626
|
+
"Trello": {
|
|
627
|
+
"package": "@mappies/miniwat-mcp-trello",
|
|
628
|
+
"secrets": [
|
|
629
|
+
"TRELLO_API_KEY",
|
|
630
|
+
"TRELLO_TOKEN"
|
|
631
|
+
],
|
|
632
|
+
"tools": [
|
|
633
|
+
{
|
|
634
|
+
"import": "LIST_TRELLO_BOARDS_DEFINITION"
|
|
635
|
+
}
|
|
636
|
+
]
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
This keeps sensitive values out of source control.
|
|
643
|
+
|
|
644
|
+
---
|
|
645
|
+
|
|
646
|
+
## Building a Custom MCP Package
|
|
647
|
+
|
|
648
|
+
A miniwat MCP is simply an **npm package** that exports tool definitions and their corresponding implementation functions.
|
|
649
|
+
|
|
650
|
+
Unlike traditional MCP implementations, there is no server to run. miniwat loads your package directly and executes the exported functions.
|
|
651
|
+
|
|
652
|
+
### Package Structure
|
|
653
|
+
|
|
654
|
+
A simple MCP package might look like this:
|
|
655
|
+
|
|
656
|
+
```text
|
|
657
|
+
my-mcp/
|
|
658
|
+
├── package.json
|
|
659
|
+
└── src/
|
|
660
|
+
├── index.ts
|
|
661
|
+
└── getRandomNumber.ts
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
### Export a Tool Definition
|
|
665
|
+
|
|
666
|
+
Every tool begins with a definition that describes the tool to the language model.
|
|
667
|
+
|
|
668
|
+
```ts
|
|
669
|
+
export const GET_RANDOM_NUMBER_DEFINITION = {
|
|
670
|
+
name: "getRandomNumber",
|
|
671
|
+
description: "Generate a random number between two values.",
|
|
672
|
+
inputSchema: {
|
|
673
|
+
type: "object",
|
|
674
|
+
properties: {
|
|
675
|
+
min: { type: "number" },
|
|
676
|
+
max: { type: "number" }
|
|
677
|
+
},
|
|
678
|
+
required: ["min", "max"]
|
|
679
|
+
}
|
|
680
|
+
} as const;
|
|
681
|
+
```
|
|
682
|
+
|
|
683
|
+
### Export the Tool Function
|
|
684
|
+
|
|
685
|
+
Each tool definition must have a corresponding exported function whose name exactly matches the definition's `name` property.
|
|
686
|
+
|
|
687
|
+
The function accepts a **single object parameter**, with properties that match the tool's `inputSchema`. When the language model invokes the tool, miniwat automatically maps the generated JSON arguments to this object and calls your function.
|
|
688
|
+
|
|
689
|
+
|
|
690
|
+
```ts
|
|
691
|
+
export async function getRandomNumber({ min, max }: { min: number; max: number; }) {
|
|
692
|
+
return {
|
|
693
|
+
value: Math.floor(Math.random() * (max - min + 1)) + min
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
### Optional: Input Text Helper
|
|
699
|
+
|
|
700
|
+
If you want the UI to display status updates while the tool is running, export an input text helper.
|
|
701
|
+
|
|
702
|
+
```ts
|
|
703
|
+
export function getRandomNumberInputText({ min, max }: { min: number; max: number; }) {
|
|
704
|
+
return `Generating a random number between ${min} and ${max}.`;
|
|
705
|
+
}
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
### Export Everything
|
|
709
|
+
|
|
710
|
+
Export the definitions and functions from your package.
|
|
711
|
+
|
|
712
|
+
```ts
|
|
713
|
+
export * from "./getRandomNumber";
|
|
714
|
+
```
|
|
715
|
+
|
|
716
|
+
### Use the Package
|
|
717
|
+
|
|
718
|
+
Install the package into your application.
|
|
719
|
+
|
|
720
|
+
```bash
|
|
721
|
+
npm install @your-org/my-mcp
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
Then expose the desired tool definitions in `mcp.json`.
|
|
725
|
+
|
|
726
|
+
```json
|
|
727
|
+
{
|
|
728
|
+
"mcpServers": {
|
|
729
|
+
"Example": {
|
|
730
|
+
"package": "@your-org/my-mcp",
|
|
731
|
+
"tools": [
|
|
732
|
+
{
|
|
733
|
+
"import": "GET_RANDOM_NUMBER_DEFINITION"
|
|
734
|
+
}
|
|
735
|
+
]
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
Only the tool definitions listed in `mcp.json` are exposed to the language model, allowing you to choose exactly which actions your agent can perform.
|
|
742
|
+
|
|
743
|
+
---
|
|
744
|
+
|
|
745
|
+
## Example: Model Provider Factory
|
|
746
|
+
|
|
747
|
+
A common pattern is to create a model factory that always loads the MCP config.
|
|
748
|
+
|
|
749
|
+
```ts
|
|
750
|
+
import { Model } from "@mappies/miniwat-agent-core";
|
|
751
|
+
import { BedrockModel } from "@mappies/miniwat-provider-bedrock";
|
|
752
|
+
import { OpenAiModel } from "@mappies/miniwat-provider-openai";
|
|
753
|
+
import mcpConfig from "../mcp.json";
|
|
754
|
+
|
|
755
|
+
export class ModelProviderFactory {
|
|
756
|
+
static create(): Model {
|
|
757
|
+
const options = {
|
|
758
|
+
mcpConfig
|
|
759
|
+
};
|
|
760
|
+
|
|
761
|
+
if (process.env.OPENAI_API_KEY) {
|
|
762
|
+
return new OpenAiModel({
|
|
763
|
+
...options,
|
|
764
|
+
modelId: process.env.DEFAULT_OPENAI_MODEL || "gpt-4.1-mini",
|
|
765
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
766
|
+
baseURL: process.env.OPENAI_BASE_URL
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
return new BedrockModel({
|
|
771
|
+
...options,
|
|
772
|
+
region: process.env.AWS_REGION,
|
|
773
|
+
modelId: process.env.DEFAULT_BEDROCK_MODEL_ARN || ""
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
```
|
|
778
|
+
|
|
779
|
+
Then use the factory when creating your agent.
|
|
780
|
+
|
|
781
|
+
```ts
|
|
782
|
+
const model = ModelProviderFactory.create();
|
|
783
|
+
|
|
784
|
+
const agent = new Agent({
|
|
785
|
+
model,
|
|
786
|
+
instruction: {
|
|
787
|
+
system: {
|
|
788
|
+
value: "You are a helpful assistant."
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
});
|
|
792
|
+
```
|
|
793
|
+
|
|
794
|
+
---
|
|
795
|
+
|
|
796
|
+
## Automatic Tool Execution
|
|
797
|
+
|
|
798
|
+
Once the model is configured with `mcpConfig`, tool execution is automatic.
|
|
799
|
+
|
|
800
|
+
For example, if the user asks:
|
|
801
|
+
|
|
802
|
+
> What's the weather in Blacksburg tomorrow?
|
|
803
|
+
|
|
804
|
+
The model may invoke the **Weather** MCP.
|
|
805
|
+
|
|
806
|
+
If the user asks:
|
|
807
|
+
|
|
808
|
+
> Search the web for the latest TypeScript release notes.
|
|
809
|
+
|
|
810
|
+
The model may invoke the **Web** MCP.
|
|
811
|
+
|
|
812
|
+
If the user asks:
|
|
813
|
+
|
|
814
|
+
> Summarize https://example.com/report.pdf
|
|
815
|
+
|
|
816
|
+
The model may invoke the **Web** MCP's `fetchUrl` tool.
|
|
817
|
+
|
|
818
|
+
If the user asks:
|
|
819
|
+
|
|
820
|
+
> Create a Trello board named Sprint Planning.
|
|
821
|
+
|
|
822
|
+
The model may invoke the **Trello** MCP.
|
|
823
|
+
|
|
824
|
+
From your application's perspective, there is nothing special to do.
|
|
825
|
+
|
|
826
|
+
```ts
|
|
827
|
+
const response = await agent.invoke(prompt, session);
|
|
828
|
+
```
|
|
829
|
+
|
|
830
|
+
The model provider and `ToolDispatcher` handle the tool workflow:
|
|
831
|
+
|
|
832
|
+
1. List configured tools from `mcpConfig`.
|
|
833
|
+
2. Send tool definitions to the model.
|
|
834
|
+
3. Let the model choose a tool when needed.
|
|
835
|
+
4. Execute the selected tool.
|
|
836
|
+
5. Send the tool result back to the model.
|
|
837
|
+
6. Continue the conversation.
|
|
838
|
+
7. Return the final response.
|
|
839
|
+
|
|
840
|
+
---
|
|
841
|
+
|
|
842
|
+
## Observing Tool Activity
|
|
843
|
+
|
|
844
|
+
You can observe tool activity with `onTooling`.
|
|
845
|
+
|
|
846
|
+
```ts
|
|
847
|
+
const response = await agent.invoke(prompt, session, {
|
|
848
|
+
event: {
|
|
849
|
+
onThinking: async text => {
|
|
850
|
+
console.log("Thinking:", text);
|
|
851
|
+
},
|
|
852
|
+
onTooling: async message => {
|
|
853
|
+
console.log("Tool activity:", message);
|
|
854
|
+
},
|
|
855
|
+
onResponse: async message => {
|
|
856
|
+
console.log("Response:", message.content);
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
});
|
|
860
|
+
```
|
|
861
|
+
|
|
862
|
+
This is useful for:
|
|
863
|
+
|
|
864
|
+
- logging tool calls
|
|
865
|
+
- displaying status updates in a UI
|
|
866
|
+
- saving tool call history
|
|
867
|
+
- debugging MCP behavior
|
|
868
|
+
|
|
869
|
+
------------------------------------------------------------------------
|
|
870
|
+
|
|
871
|
+
# Which API should I use?
|
|
872
|
+
|
|
873
|
+
## invoke()
|
|
874
|
+
|
|
875
|
+
Use when you want the complete response.
|
|
876
|
+
|
|
877
|
+
``` ts
|
|
878
|
+
await agent.invoke(prompt, session);
|
|
879
|
+
```
|
|
880
|
+
|
|
881
|
+
## stream()
|
|
882
|
+
|
|
883
|
+
Use when building chat interfaces.
|
|
884
|
+
|
|
885
|
+
``` ts
|
|
886
|
+
await agent.stream(prompt, session);
|
|
887
|
+
```
|
|
888
|
+
|
|
889
|
+
------------------------------------------------------------------------
|
|
890
|
+
|
|
891
|
+
# Best Practices
|
|
892
|
+
|
|
893
|
+
- Create one `Session` per conversation.
|
|
894
|
+
- Reuse that session until the conversation ends.
|
|
895
|
+
- Use `stream()` for interactive UIs.
|
|
896
|
+
- Keep system instructions short and focused.
|
|
897
|
+
- Use low temperatures for factual assistants.
|
|
898
|
+
|
|
899
|
+
------------------------------------------------------------------------
|
|
900
|
+
|
|
901
|
+
# Next Steps
|
|
902
|
+
|
|
903
|
+
You now know how to:
|
|
904
|
+
|
|
905
|
+
- create a model
|
|
906
|
+
- create an agent
|
|
907
|
+
- maintain conversations with sessions
|
|
908
|
+
- customize behavior with instructions
|
|
909
|
+
- stream responses
|
|
910
|
+
- receive events
|
|
911
|
+
- build a chatbot
|
|
912
|
+
|
|
913
|
+
From here you can integrate miniwat into a CLI, web server, desktop
|
|
914
|
+
application, or WebSocket chat service.
|