Skip to content

Commit ffada62

Browse files
committed
feat(mcp-web,examples): add HTTP request support and DuckDB example
- Introduce 'http-request' capability to mcp-web.yaml, enabling RESTful operations with read/write mode control and input validation - Add DuckDB database example to oafp-examples.yaml, demonstrating local DB usage These changes expand web automation features and provide new database usage guidance.
1 parent 264b5b6 commit ffada62

2 files changed

Lines changed: 98 additions & 5 deletions

File tree

ai/mcps/mcp-web.yaml

Lines changed: 91 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,13 @@ help:
66
desc : If defined starts a MCP server on the provided port
77
example : "8888"
88
mandatory: false
9+
- name : readwrite
10+
desc : If true, allows mutating HTTP methods in http-request (POST, PUT, PATCH, DELETE)
11+
example : "true"
12+
mandatory: false
913

1014
todo:
15+
- Init web context
1116
- (if ): "isDef(args.onport)"
1217
((then)):
1318
- (httpdStart ): "${onport:-8080}"
@@ -65,9 +70,40 @@ todo:
6570
readOnlyHint : true
6671
idempotentHint: true
6772

73+
http-request:
74+
name : http-request
75+
description: Executes HTTP REST requests against a URL and returns the raw $rest response map (GET and HEAD are allowed in read-only mode; POST/PUT/PATCH/DELETE require readwrite=true).
76+
inputSchema:
77+
type : object
78+
properties:
79+
url:
80+
type : string
81+
description: The URL to request.
82+
method:
83+
type : string
84+
description: HTTP method to use. HEAD is supported and does not require readwrite=true.
85+
enum : [ GET, HEAD, POST, PUT, PATCH, DELETE ]
86+
default : GET
87+
data:
88+
type : object
89+
description: Optional request payload map for POST, PUT and PATCH methods.
90+
headers:
91+
type : object
92+
description: Optional request headers map used for non-GET methods.
93+
throwExceptions:
94+
type : boolean
95+
description: If true, non-2xx responses throw exceptions when using non-GET methods.
96+
default : false
97+
required: [ url ]
98+
annotations:
99+
title : http-request
100+
readOnlyHint : false
101+
idempotentHint: false
102+
68103
((fns )): &MCPFNS
69-
web-search: Web search
70-
get-url : Get URL
104+
web-search : Web search
105+
get-url : Get URL
106+
http-request: HTTP Request
71107

72108
((else)):
73109
- (stdioMCP ): *MCPSERVER
@@ -97,6 +133,14 @@ init:
97133
defaultUserAgent: mini-a-mcp-web
98134

99135
jobs:
136+
# -----------------------
137+
- name : Init web context
138+
check:
139+
in:
140+
readwrite: toBoolean.isBoolean.default(false)
141+
exec : | #js
142+
global.__webReadWrite__ = args.readwrite === true
143+
100144
# -----------------
101145
- name : Web search
102146
check:
@@ -113,7 +157,49 @@ jobs:
113157
check:
114158
in:
115159
url : isString
116-
style : isString.oneOf([ "html", "basic", "text", "map" ]).default("basic")
160+
style : isString.oneOf([ "html", "basic", "text", "map" ]).default(__)
117161
exec : | #js
118-
var ws = new WebSearch()
119-
return ws.getURL(args.url, args.style)
162+
var _s = $rest().get(args.url)
163+
if (isDef(args.style)) {
164+
var ws = new WebSearch()
165+
return ws.getURL(_s, args.style)
166+
} else {
167+
return _s
168+
}
169+
170+
# -------------------
171+
- name : HTTP Request
172+
check:
173+
in:
174+
url : isString
175+
method : isString.oneOf([ "GET", "HEAD", "POST", "PUT", "PATCH", "DELETE" ]).default("GET")
176+
data : isMap.default(__)
177+
headers : isMap.default(__)
178+
throwExceptions: toBoolean.isBoolean.default(false)
179+
exec : | #js
180+
var method = String(args.method).toLowerCase()
181+
if ([ "post", "put", "patch", "delete" ].indexOf(method) >= 0 && !global.__webReadWrite__) {
182+
return "[ERROR] Read-only mode. Set readwrite=true to allow write operations"
183+
}
184+
185+
var r = $rest({
186+
requestHeaders : args.headers,
187+
throwExceptions: args.throwExceptions
188+
})
189+
190+
switch(method) {
191+
case "get":
192+
return r.get(args.url)
193+
case "head":
194+
return r.head(args.url)
195+
case "post":
196+
return r.post(args.url, _$(args.data, "data").isMap().default({}))
197+
case "put":
198+
return r.put(args.url, _$(args.data, "data").isMap().default({}))
199+
case "patch":
200+
return r.patch(args.url, _$(args.data, "data").isMap().default({}))
201+
case "delete":
202+
return r.delete(args.url)
203+
default:
204+
throw "Unsupported HTTP method '" + args.method + "'."
205+
}

oafp-examples.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,3 +1327,10 @@ data:
13271327
e: |
13281328
# opack install plugin-xls
13291329
oafp cmd="kubectl get all -A -o json" path="items[].setp(@,'','m').spec.containers.map(&{ ns: get('m').metadata.namespace, kind: get('m').kind, name: get('m').metadata.name, container: name, image: image }, nvl(@, from_json('[]'))) | []" out=xls outxlsfile=list.xlsx
1330+
- c: DB
1331+
s: DuckDB
1332+
d: Creates and queries a local DuckDB file database.
1333+
e: |
1334+
# opack install jdbc-duckdb
1335+
oafp libs="@jdbc-duckdb/jdbc-duckdb.js" in=ls data="." lsrecursive=true out=db dbjdbc="jdbc:duckdb:test.db"
1336+
oafp libs="@jdbc-duckdb/jdbc-duckdb.js" in=db indbjdbc="jdbc:duckdb:test.db" data="select isFile, count(*) as number_of_files, sum(size) sum_size from data group by isFile" out=ctable

0 commit comments

Comments
 (0)