@aigne/example-mcp-blocklet 1.9.1 → 1.10.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 +38 -3
- package/index.ts +35 -39
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# MCP Blocklet Demo
|
|
2
2
|
|
|
3
|
-
This demo demonstrates how to use [AIGNE Framework](https://github.com/AIGNE-io/aigne-framework) and MCP to interact with apps hosted on the [Blocklet platform](https://github.com/blocklet).
|
|
3
|
+
This demo demonstrates how to use [AIGNE Framework](https://github.com/AIGNE-io/aigne-framework) and MCP to interact with apps hosted on the [Blocklet platform](https://github.com/blocklet). The example now supports both one-shot and interactive chat modes, along with customizable model settings and pipeline input/output.
|
|
4
4
|
|
|
5
5
|
## Prerequisites
|
|
6
6
|
|
|
@@ -15,7 +15,14 @@ This demo demonstrates how to use [AIGNE Framework](https://github.com/AIGNE-io/
|
|
|
15
15
|
```bash
|
|
16
16
|
export OPENAI_API_KEY=YOUR_OPENAI_API_KEY # Set your OpenAI API key
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
# Run in one-shot mode (default)
|
|
19
|
+
npx -y @aigne/example-mcp-blocklet
|
|
20
|
+
|
|
21
|
+
# Run in interactive chat mode
|
|
22
|
+
npx -y @aigne/example-mcp-blocklet --chat
|
|
23
|
+
|
|
24
|
+
# Use pipeline input
|
|
25
|
+
echo "What are the features of this blocklet app?" | npx -y @aigne/example-mcp-blocklet
|
|
19
26
|
```
|
|
20
27
|
|
|
21
28
|
## Installation
|
|
@@ -46,7 +53,7 @@ BLOCKLET_APP_URL="" # Set your Blocklet app URL here
|
|
|
46
53
|
### Run the Example
|
|
47
54
|
|
|
48
55
|
```bash
|
|
49
|
-
pnpm start
|
|
56
|
+
pnpm start # Run in one-shot mode (default)
|
|
50
57
|
```
|
|
51
58
|
|
|
52
59
|
or
|
|
@@ -55,6 +62,34 @@ or
|
|
|
55
62
|
pnpm start https://your-blocklet-app-url
|
|
56
63
|
```
|
|
57
64
|
|
|
65
|
+
### Run Options
|
|
66
|
+
|
|
67
|
+
The example supports the following command-line parameters:
|
|
68
|
+
|
|
69
|
+
| Parameter | Description | Default |
|
|
70
|
+
|-----------|-------------|---------|
|
|
71
|
+
| `--chat` | Run in interactive chat mode | Disabled (one-shot mode) |
|
|
72
|
+
| `--model <provider[:model]>` | AI model to use in format 'provider[:model]' where model is optional. Examples: 'openai' or 'openai:gpt-4o-mini' | openai |
|
|
73
|
+
| `--temperature <value>` | Temperature for model generation | Provider default |
|
|
74
|
+
| `--top-p <value>` | Top-p sampling value | Provider default |
|
|
75
|
+
| `--presence-penalty <value>` | Presence penalty value | Provider default |
|
|
76
|
+
| `--frequency-penalty <value>` | Frequency penalty value | Provider default |
|
|
77
|
+
| `--log-level <level>` | Set logging level (ERROR, WARN, INFO, DEBUG, TRACE) | INFO |
|
|
78
|
+
| `--input`, `-i <input>` | Specify input directly | None |
|
|
79
|
+
|
|
80
|
+
#### Examples
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# Run in chat mode (interactive)
|
|
84
|
+
pnpm start -- --chat
|
|
85
|
+
|
|
86
|
+
# Set logging level
|
|
87
|
+
pnpm start -- --log-level DEBUG
|
|
88
|
+
|
|
89
|
+
# Use pipeline input
|
|
90
|
+
echo "What are the features of this blocklet app?" | pnpm start
|
|
91
|
+
```
|
|
92
|
+
|
|
58
93
|
## License
|
|
59
94
|
|
|
60
95
|
This project is licensed under the MIT License.
|
package/index.ts
CHANGED
|
@@ -1,19 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env bunwrapper
|
|
2
2
|
|
|
3
3
|
import assert from "node:assert";
|
|
4
|
-
import {
|
|
5
|
-
import { AIAgent,
|
|
6
|
-
import { loadModel } from "@aigne/core/loader/index.js";
|
|
7
|
-
import { logger } from "@aigne/core/utils/logger.js";
|
|
4
|
+
import { runWithAIGNE } from "@aigne/cli/utils/run-with-aigne.js";
|
|
5
|
+
import { AIAgent, MCPAgent, PromptBuilder } from "@aigne/core";
|
|
8
6
|
import { UnauthorizedError, refreshAuthorization } from "@modelcontextprotocol/sdk/client/auth.js";
|
|
9
7
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
10
|
-
// @ts-ignore
|
|
11
8
|
import JWT from "jsonwebtoken";
|
|
12
|
-
|
|
13
9
|
import { TerminalOAuthProvider } from "./oauth.js";
|
|
14
10
|
|
|
15
|
-
logger.enable(`aigne:mcp,${process.env.DEBUG}`);
|
|
16
|
-
|
|
17
11
|
const rawUrl = process.argv[2] || process.env.BLOCKLET_APP_URL;
|
|
18
12
|
assert(
|
|
19
13
|
rawUrl,
|
|
@@ -56,9 +50,12 @@ try {
|
|
|
56
50
|
let tokens = await provider.tokens();
|
|
57
51
|
if (tokens) {
|
|
58
52
|
let decoded = JWT.decode(tokens.access_token);
|
|
59
|
-
if (decoded) {
|
|
53
|
+
if (decoded && typeof decoded === "object") {
|
|
54
|
+
const exp = decoded.exp;
|
|
55
|
+
assert(typeof exp === "number", "Invalid access token");
|
|
56
|
+
|
|
60
57
|
const now = Date.now();
|
|
61
|
-
const expiresAt =
|
|
58
|
+
const expiresAt = exp * 1000;
|
|
62
59
|
if (now < expiresAt) {
|
|
63
60
|
console.info("Tokens already exist and not expired, skipping authorization");
|
|
64
61
|
} else if (tokens.refresh_token) {
|
|
@@ -66,7 +63,7 @@ try {
|
|
|
66
63
|
decoded = JWT.decode(tokens.refresh_token);
|
|
67
64
|
if (decoded) {
|
|
68
65
|
const now = Date.now();
|
|
69
|
-
const expiresAt =
|
|
66
|
+
const expiresAt = exp * 1000;
|
|
70
67
|
if (now < expiresAt) {
|
|
71
68
|
console.info("Refresh token already exists and not expired, refreshing authorization");
|
|
72
69
|
try {
|
|
@@ -111,34 +108,33 @@ try {
|
|
|
111
108
|
}
|
|
112
109
|
}
|
|
113
110
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
const blocklet = await MCPAgent.from({
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
111
|
+
await runWithAIGNE(
|
|
112
|
+
async () => {
|
|
113
|
+
const blocklet = await MCPAgent.from({
|
|
114
|
+
url: appUrl.href,
|
|
115
|
+
transport: "streamableHttp",
|
|
116
|
+
opts: {
|
|
117
|
+
authProvider: provider,
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const agent = AIAgent.from({
|
|
122
|
+
instructions: PromptBuilder.from(
|
|
123
|
+
"You are a helpful assistant that can help users query and analyze data from the blocklet. You can perform various database queries on the blocklet database, before performing any queries, please try to understand the user's request and generate a query base on the database schema.",
|
|
124
|
+
),
|
|
125
|
+
skills: [blocklet],
|
|
126
|
+
memory: true,
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
return agent;
|
|
121
130
|
},
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
instructions: PromptBuilder.from(
|
|
131
|
-
"You are a helpful assistant that can help users query and analyze data from the blocklet. You can perform various database queries on the blocklet database, before performing any queries, please try to understand the user's request and generate a query base on the database schema.",
|
|
132
|
-
),
|
|
133
|
-
memory: true,
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
const userAgent = aigne.invoke(agent);
|
|
137
|
-
|
|
138
|
-
await runChatLoopInTerminal(userAgent, {
|
|
139
|
-
welcome:
|
|
140
|
-
"Hello! I'm a chatbot that can help you interact with the blocklet. Try asking me a question about the blocklet!",
|
|
141
|
-
defaultQuestion: "How many users are there in the database?",
|
|
142
|
-
});
|
|
131
|
+
{
|
|
132
|
+
chatLoopOptions: {
|
|
133
|
+
welcome:
|
|
134
|
+
"Hello! I'm a chatbot that can help you interact with the blocklet. Try asking me a question about the blocklet!",
|
|
135
|
+
defaultQuestion: "How many users are there in the database?",
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
);
|
|
143
139
|
|
|
144
140
|
process.exit(0);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aigne/example-mcp-blocklet",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"description": "A demonstration of using AIGNE Framework and MCP Server hosted by the Blocklet platform",
|
|
5
5
|
"author": "Arcblock <blocklet@arcblock.io> https://github.com/blocklet",
|
|
6
6
|
"homepage": "https://github.com/AIGNE-io/aigne-framework/tree/main/examples/mcp-blocklet",
|
|
@@ -20,11 +20,12 @@
|
|
|
20
20
|
"jsonwebtoken": "^9.0.2",
|
|
21
21
|
"open": "^10.1.2",
|
|
22
22
|
"zod": "^3.24.4",
|
|
23
|
-
"@aigne/
|
|
24
|
-
"@aigne/
|
|
23
|
+
"@aigne/cli": "^1.10.0",
|
|
24
|
+
"@aigne/core": "^1.16.0"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
|
-
"@
|
|
27
|
+
"@types/jsonwebtoken": "^9.0.9",
|
|
28
|
+
"@aigne/test-utils": "^0.3.0"
|
|
28
29
|
},
|
|
29
30
|
"scripts": {
|
|
30
31
|
"start": "bun run index.ts",
|