@toa.io/extensions.exposition 1.0.0-alpha.284 → 1.0.0-alpha.285
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/CHANGELOG.md +11 -0
- package/documentation/mcp.md +7 -1
- package/documentation/rpc.md +21 -17
- package/features/mcp.feature +32 -28
- package/features/oauth.grants.feature +1 -1
- package/features/rpc.feature +21 -21
- package/features/steps/Gateway.ts +4 -3
- package/package.json +2 -2
- package/source/Introspection.ts +4 -1
- package/source/MCP/tools.ts +1 -0
- package/source/MCP/types.ts +4 -1
- package/source/RPC/names.test.ts +22 -22
- package/source/RPC/names.ts +4 -3
- package/source/RTD/walk.test.ts +5 -5
- package/source/directives/mcp/MCP.ts +8 -1
- package/source/directives/mcp/Tool.test.ts +26 -2
- package/source/directives/mcp/Tool.ts +23 -4
- package/transpiled/Introspection.d.ts +2 -0
- package/transpiled/Introspection.js +1 -1
- package/transpiled/Introspection.js.map +1 -1
- package/transpiled/MCP/tools.js +1 -0
- package/transpiled/MCP/tools.js.map +1 -1
- package/transpiled/MCP/types.d.ts +3 -1
- package/transpiled/RPC/names.d.ts +3 -2
- package/transpiled/RPC/names.js +1 -1
- package/transpiled/RPC/names.js.map +1 -1
- package/transpiled/directives/mcp/MCP.js +7 -1
- package/transpiled/directives/mcp/MCP.js.map +1 -1
- package/transpiled/directives/mcp/Tool.d.ts +6 -1
- package/transpiled/directives/mcp/Tool.js +14 -3
- package/transpiled/directives/mcp/Tool.js.map +1 -1
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [1.0.0-alpha.285](https://github.com/toa-io/toa/compare/v1.0.0-alpha.284...v1.0.0-alpha.285) (2026-09-05)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **exposition:** a procedure is named in characters a tool's name may hold ([857ff75](https://github.com/toa-io/toa/commit/857ff75858e633682d5c245eccde3dc00797ec00))
|
|
11
|
+
|
|
12
|
+
### Features
|
|
13
|
+
|
|
14
|
+
* **exposition:** a tool says what to call it, beside what it is ([c94dcd1](https://github.com/toa-io/toa/commit/c94dcd10ab5a2875975fdba94b37dae128f454c4))
|
|
15
|
+
|
|
16
|
+
|
|
6
17
|
# [1.0.0-alpha.284](https://github.com/toa-io/toa/compare/v1.0.0-alpha.283...v1.0.0-alpha.284) (2026-09-05)
|
|
7
18
|
|
|
8
19
|
### Bug Fixes
|
package/documentation/mcp.md
CHANGED
|
@@ -37,7 +37,9 @@ A tool is an RTD method that says it is one, named as the [procedure](rpc.md#the
|
|
|
37
37
|
/hot:
|
|
38
38
|
GET:
|
|
39
39
|
query: { criteria: temperature=gt=80 }
|
|
40
|
-
mcp:tool:
|
|
40
|
+
mcp:tool:
|
|
41
|
+
title: Hot pots
|
|
42
|
+
description: The pots that are too hot to pour.
|
|
41
43
|
endpoint: enumerate
|
|
42
44
|
```
|
|
43
45
|
|
|
@@ -48,6 +50,10 @@ it would spend a model's context on what it has no business calling.
|
|
|
48
50
|
The value is what the tool is, and stating it is what publishes it — there is no way to publish one
|
|
49
51
|
that says nothing, because a tool a model cannot read the purpose of is one it cannot choose.
|
|
50
52
|
|
|
53
|
+
A `title` is what a person is shown where a client lists what it may call. Without one a client has
|
|
54
|
+
only the name, which is an address — `apps._identity._id.repos.POST` — and reads as one. A
|
|
55
|
+
description alone is written as the value; a title beside it is written as a mapping.
|
|
56
|
+
|
|
51
57
|
An operation [states what it is](/documentation/component/declaration.md) as well, and that is not
|
|
52
58
|
this: it is written without knowledge of any route, and a tool is an operation and a route together.
|
|
53
59
|
The two routes above are one operation and two tools, and one sentence is not true of both. The
|
package/documentation/rpc.md
CHANGED
|
@@ -13,27 +13,31 @@ one an application could choose is one it could collide with a route of its own.
|
|
|
13
13
|
|
|
14
14
|
## The name
|
|
15
15
|
|
|
16
|
-
A procedure is an RTD method — a node and a verb — and its name is
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
A procedure is an RTD method — a node and a verb — and its name is the route template with a
|
|
17
|
+
variable marked by a leading `_` and the verb as the last segment, joined by `.`.
|
|
18
|
+
|
|
19
|
+
The separator is `.` and not `/` because a name is a tool's name too, and
|
|
20
|
+
[MCP](mcp.md) names the characters one may hold: letters, digits, `_`, `-` and `.`. A client that
|
|
21
|
+
receives one outside that set may refuse the tool, and one that accepts it rewrites what it shows
|
|
22
|
+
a model — so what is published has to be spellable as it stands.
|
|
19
23
|
|
|
20
24
|
| route | verb | method |
|
|
21
25
|
| --- | --- | --- |
|
|
22
|
-
| `/pots` | `GET` | `pots
|
|
23
|
-
| `/pots` | `POST` | `pots
|
|
24
|
-
| `/pots/:id` | `GET` | `pots
|
|
25
|
-
| `/identity/tokens/:identity` | `POST` | `identity
|
|
26
|
-
| `/files/**` | `GET` | `files
|
|
26
|
+
| `/pots` | `GET` | `pots.GET` |
|
|
27
|
+
| `/pots` | `POST` | `pots.POST` |
|
|
28
|
+
| `/pots/:id` | `GET` | `pots._id.GET` |
|
|
29
|
+
| `/identity/tokens/:identity` | `POST` | `identity.tokens._identity.POST` |
|
|
30
|
+
| `/files/**` | `GET` | `files.__.GET` |
|
|
27
31
|
| `/` | `GET` | `GET` |
|
|
28
32
|
|
|
29
|
-
The verb is always the last segment, so `/pots/GET` answering `POST` is `pots
|
|
30
|
-
`/pots` answering `GET` is `pots
|
|
33
|
+
The verb is always the last segment, so `/pots/GET` answering `POST` is `pots.GET.POST` and
|
|
34
|
+
`/pots` answering `GET` is `pots.GET`. Nothing is declared to make a name: a re-mounted route is
|
|
31
35
|
a renamed procedure, because the name is the address.
|
|
32
36
|
|
|
33
37
|
## What has a name
|
|
34
38
|
|
|
35
39
|
A segment is addressed where it holds only `A-Z`, `a-z`, `0-9` and `-`. `_` is the name's own,
|
|
36
|
-
marking a variable, and `__` the rest of a path.
|
|
40
|
+
marking a variable, and `__` the rest of a path; `.` is what divides one segment from the next.
|
|
37
41
|
|
|
38
42
|
A route with a segment holding anything else — a `.`, a `_`, a `*`, a variable that is not one
|
|
39
43
|
word — has no name. It is served over HTTP as it always was; what it loses is the address, so
|
|
@@ -51,16 +55,16 @@ A key the template names is a route variable, and is taken by the path. `query`
|
|
|
51
55
|
querystring. Whatever is left is the body.
|
|
52
56
|
|
|
53
57
|
```json
|
|
54
|
-
{"jsonrpc": "2.0", "id": 1, "method": "pots
|
|
58
|
+
{"jsonrpc": "2.0", "id": 1, "method": "pots._id.GET", "params": {"id": "a1b2"}}
|
|
55
59
|
```
|
|
56
60
|
|
|
57
61
|
```json
|
|
58
|
-
{"jsonrpc": "2.0", "id": 2, "method": "pots
|
|
62
|
+
{"jsonrpc": "2.0", "id": 2, "method": "pots.POST",
|
|
59
63
|
"params": {"title": "Kettle", "volume": 1.7}}
|
|
60
64
|
```
|
|
61
65
|
|
|
62
66
|
```json
|
|
63
|
-
{"jsonrpc": "2.0", "id": 3, "method": "pots
|
|
67
|
+
{"jsonrpc": "2.0", "id": 3, "method": "pots.GET",
|
|
64
68
|
"params": {"query": {"criteria": "volume=gt=1", "limit": 10}}}
|
|
65
69
|
```
|
|
66
70
|
|
|
@@ -87,8 +91,8 @@ A request may carry an array of calls instead of one, and answers an array of wh
|
|
|
87
91
|
answered — shorter than what it was given, where some were notifications.
|
|
88
92
|
|
|
89
93
|
```json
|
|
90
|
-
[{"jsonrpc": "2.0", "id": 1, "method": "pots
|
|
91
|
-
{"jsonrpc": "2.0", "method": "pots
|
|
94
|
+
[{"jsonrpc": "2.0", "id": 1, "method": "pots._id.GET", "params": {"id": "a1b2"}},
|
|
95
|
+
{"jsonrpc": "2.0", "method": "pots._id.DELETE", "params": {"id": "c3d4"}}]
|
|
92
96
|
```
|
|
93
97
|
|
|
94
98
|
They run one after another, in the order given. `batch` is how many one request may carry, 32
|
|
@@ -127,7 +131,7 @@ in its manifest, and is what a caller reads.
|
|
|
127
131
|
## Authorization
|
|
128
132
|
|
|
129
133
|
A procedure is authorized as the resource is, against the path and the verb its name states.
|
|
130
|
-
A token restricted to `/pots/:id/` for `GET` authorizes `pots
|
|
134
|
+
A token restricted to `/pots/:id/` for `GET` authorizes `pots._id.GET` and nothing else,
|
|
131
135
|
whichever way the call arrives.
|
|
132
136
|
|
|
133
137
|
[`anonymous`](access.md#anonymous) is the one directive that reads a call differently from a
|
package/features/mcp.feature
CHANGED
|
@@ -8,7 +8,8 @@ Feature: Model Context Protocol
|
|
|
8
8
|
says.
|
|
9
9
|
|
|
10
10
|
What a tool is, is stated on the route and nowhere else. The operation states what it is
|
|
11
|
-
too, and that is not this: one operation mounted on two routes is two tools.
|
|
11
|
+
too, and that is not this: one operation mounted on two routes is two tools. A `title`
|
|
12
|
+
beside the description is what a person is shown where a client lists what it may call.
|
|
12
13
|
|
|
13
14
|
Two revisions are answered from one endpoint that remembers nothing between requests: the
|
|
14
15
|
modern one, where every request carries its own version and capabilities, and the one
|
|
@@ -42,7 +43,9 @@ Feature: Model Context Protocol
|
|
|
42
43
|
GET:
|
|
43
44
|
query:
|
|
44
45
|
criteria: volume>=100
|
|
45
|
-
mcp:tool:
|
|
46
|
+
mcp:tool:
|
|
47
|
+
title: Large pots
|
|
48
|
+
description: The pots that hold a hundred or more, newest first.
|
|
46
49
|
endpoint: enumerate
|
|
47
50
|
/unpublished:
|
|
48
51
|
GET: enumerate
|
|
@@ -160,7 +163,7 @@ Feature: Model Context Protocol
|
|
|
160
163
|
id: 2
|
|
161
164
|
result:
|
|
162
165
|
tools:
|
|
163
|
-
- name: pots
|
|
166
|
+
- name: pots.GET
|
|
164
167
|
description: All the pots, newest first.
|
|
165
168
|
inputSchema:
|
|
166
169
|
type: object
|
|
@@ -178,7 +181,7 @@ Feature: Model Context Protocol
|
|
|
178
181
|
additionalProperties: false
|
|
179
182
|
annotations:
|
|
180
183
|
readOnlyHint: true
|
|
181
|
-
- name: pots
|
|
184
|
+
- name: pots.POST
|
|
182
185
|
description: Start a new pot brewing.
|
|
183
186
|
inputSchema:
|
|
184
187
|
type: object
|
|
@@ -192,7 +195,7 @@ Feature: Model Context Protocol
|
|
|
192
195
|
- title
|
|
193
196
|
- volume
|
|
194
197
|
additionalProperties: false
|
|
195
|
-
- name: pots
|
|
198
|
+
- name: pots._id.GET
|
|
196
199
|
description: One pot, by its id.
|
|
197
200
|
inputSchema:
|
|
198
201
|
type: object
|
|
@@ -202,7 +205,8 @@ Feature: Model Context Protocol
|
|
|
202
205
|
required:
|
|
203
206
|
- id
|
|
204
207
|
additionalProperties: false
|
|
205
|
-
- name: pots
|
|
208
|
+
- name: pots.large.GET
|
|
209
|
+
title: Large pots
|
|
206
210
|
description: The pots that hold a hundred or more, newest first.
|
|
207
211
|
annotations:
|
|
208
212
|
readOnlyHint: true
|
|
@@ -212,11 +216,11 @@ Feature: Model Context Protocol
|
|
|
212
216
|
"""
|
|
213
217
|
And the reply does not contain:
|
|
214
218
|
"""
|
|
215
|
-
pots
|
|
219
|
+
pots.guarded.GET
|
|
216
220
|
"""
|
|
217
221
|
And the reply does not contain:
|
|
218
222
|
"""
|
|
219
|
-
pots
|
|
223
|
+
pots.unpublished.GET
|
|
220
224
|
"""
|
|
221
225
|
And the reply does not contain:
|
|
222
226
|
"""
|
|
@@ -235,10 +239,10 @@ Feature: Model Context Protocol
|
|
|
235
239
|
content-type: application/json
|
|
236
240
|
mcp-protocol-version: 2026-07-28
|
|
237
241
|
mcp-method: tools/call
|
|
238
|
-
mcp-name: pots
|
|
242
|
+
mcp-name: pots.unpublished.GET
|
|
239
243
|
|
|
240
244
|
{"jsonrpc": "2.0", "id": 30, "method": "tools/call",
|
|
241
|
-
"params": {"name": "pots
|
|
245
|
+
"params": {"name": "pots.unpublished.GET", "arguments": {},
|
|
242
246
|
"_meta": {"io.modelcontextprotocol/protocolVersion": "2026-07-28",
|
|
243
247
|
"io.modelcontextprotocol/clientCapabilities": {}}}}
|
|
244
248
|
"""
|
|
@@ -283,7 +287,7 @@ Feature: Model Context Protocol
|
|
|
283
287
|
id: 20
|
|
284
288
|
result:
|
|
285
289
|
tools:
|
|
286
|
-
- name: pots
|
|
290
|
+
- name: pots.GET
|
|
287
291
|
"""
|
|
288
292
|
|
|
289
293
|
Scenario: A tool takes what the procedure takes
|
|
@@ -295,10 +299,10 @@ Feature: Model Context Protocol
|
|
|
295
299
|
content-type: application/json
|
|
296
300
|
mcp-protocol-version: 2026-07-28
|
|
297
301
|
mcp-method: tools/call
|
|
298
|
-
mcp-name: pots
|
|
302
|
+
mcp-name: pots._id.GET
|
|
299
303
|
|
|
300
304
|
{"jsonrpc": "2.0", "id": 3, "method": "tools/call",
|
|
301
|
-
"params": {"name": "pots
|
|
305
|
+
"params": {"name": "pots._id.GET",
|
|
302
306
|
"arguments": {"id": "4c4759e6f9c74da989d64511df42d6f4"},
|
|
303
307
|
"_meta": {"io.modelcontextprotocol/protocolVersion": "2026-07-28",
|
|
304
308
|
"io.modelcontextprotocol/clientCapabilities": {}}}}
|
|
@@ -326,10 +330,10 @@ Feature: Model Context Protocol
|
|
|
326
330
|
content-type: application/json
|
|
327
331
|
mcp-protocol-version: 2026-07-28
|
|
328
332
|
mcp-method: tools/call
|
|
329
|
-
mcp-name: pots
|
|
333
|
+
mcp-name: pots.POST
|
|
330
334
|
|
|
331
335
|
{"jsonrpc": "2.0", "id": 4, "method": "tools/call",
|
|
332
|
-
"params": {"name": "pots
|
|
336
|
+
"params": {"name": "pots.POST", "arguments": {"title": "Kettle", "volume": 1.7},
|
|
333
337
|
"_meta": {"io.modelcontextprotocol/protocolVersion": "2026-07-28",
|
|
334
338
|
"io.modelcontextprotocol/clientCapabilities": {}}}}
|
|
335
339
|
"""
|
|
@@ -354,10 +358,10 @@ Feature: Model Context Protocol
|
|
|
354
358
|
content-type: application/json
|
|
355
359
|
mcp-protocol-version: 2026-07-28
|
|
356
360
|
mcp-method: tools/call
|
|
357
|
-
mcp-name: kettles
|
|
361
|
+
mcp-name: kettles.GET
|
|
358
362
|
|
|
359
363
|
{"jsonrpc": "2.0", "id": 5, "method": "tools/call",
|
|
360
|
-
"params": {"name": "kettles
|
|
364
|
+
"params": {"name": "kettles.GET", "arguments": {},
|
|
361
365
|
"_meta": {"io.modelcontextprotocol/protocolVersion": "2026-07-28",
|
|
362
366
|
"io.modelcontextprotocol/clientCapabilities": {}}}}
|
|
363
367
|
"""
|
|
@@ -403,10 +407,10 @@ Feature: Model Context Protocol
|
|
|
403
407
|
content-type: application/json
|
|
404
408
|
mcp-protocol-version: 2026-07-28
|
|
405
409
|
mcp-method: tools/call
|
|
406
|
-
mcp-name: pots
|
|
410
|
+
mcp-name: pots.GET
|
|
407
411
|
|
|
408
412
|
{"jsonrpc": "2.0", "id": 7, "method": "tools/call",
|
|
409
|
-
"params": {"name": "pots
|
|
413
|
+
"params": {"name": "pots.POST", "arguments": {},
|
|
410
414
|
"_meta": {"io.modelcontextprotocol/protocolVersion": "2026-07-28",
|
|
411
415
|
"io.modelcontextprotocol/clientCapabilities": {}}}}
|
|
412
416
|
"""
|
|
@@ -484,7 +488,7 @@ Feature: Model Context Protocol
|
|
|
484
488
|
named a record that is not the caller's, which it may correct itself by naming another.
|
|
485
489
|
A challenge here would send the client to ask for a scope that would not help.
|
|
486
490
|
|
|
487
|
-
# developer:secret, who is not an `admin` and so may not reach `pots
|
|
491
|
+
# developer:secret, who is not an `admin` and so may not reach `pots.guarded.GET`
|
|
488
492
|
Given the `identity.basic` database contains:
|
|
489
493
|
| _id | authority | username | password |
|
|
490
494
|
| efe3a65ebbee47ed95a73edd911ea328 | nex | developer | $2b$10$ZRSKkgZoGnrcTNA5w5eCcu3pxDzdTduhteVYXcp56AaNcilNkwJ.O |
|
|
@@ -498,10 +502,10 @@ Feature: Model Context Protocol
|
|
|
498
502
|
content-type: application/json
|
|
499
503
|
mcp-protocol-version: 2026-07-28
|
|
500
504
|
mcp-method: tools/call
|
|
501
|
-
mcp-name: pots
|
|
505
|
+
mcp-name: pots.guarded.GET
|
|
502
506
|
|
|
503
507
|
{"jsonrpc": "2.0", "id": 31, "method": "tools/call",
|
|
504
|
-
"params": {"name": "pots
|
|
508
|
+
"params": {"name": "pots.guarded.GET", "arguments": {},
|
|
505
509
|
"_meta": {"io.modelcontextprotocol/protocolVersion": "2026-07-28",
|
|
506
510
|
"io.modelcontextprotocol/clientCapabilities": {}}}}
|
|
507
511
|
"""
|
|
@@ -531,10 +535,10 @@ Feature: Model Context Protocol
|
|
|
531
535
|
content-type: application/json
|
|
532
536
|
mcp-protocol-version: 2026-07-28
|
|
533
537
|
mcp-method: tools/call
|
|
534
|
-
mcp-name: pots
|
|
538
|
+
mcp-name: pots._id.GET
|
|
535
539
|
|
|
536
540
|
{"jsonrpc": "2.0", "id": 32, "method": "tools/call",
|
|
537
|
-
"params": {"name": "pots
|
|
541
|
+
"params": {"name": "pots._id.GET",
|
|
538
542
|
"arguments": {"id": "not-an-id"},
|
|
539
543
|
"_meta": {"io.modelcontextprotocol/protocolVersion": "2026-07-28",
|
|
540
544
|
"io.modelcontextprotocol/clientCapabilities": {}}}}
|
|
@@ -570,10 +574,10 @@ Feature: Model Context Protocol
|
|
|
570
574
|
content-type: application/json
|
|
571
575
|
mcp-protocol-version: 2026-07-28
|
|
572
576
|
mcp-method: tools/call
|
|
573
|
-
mcp-name: echo
|
|
577
|
+
mcp-name: echo.GET
|
|
574
578
|
|
|
575
579
|
{"jsonrpc": "2.0", "id": 10, "method": "tools/call",
|
|
576
|
-
"params": {"name": "echo
|
|
580
|
+
"params": {"name": "echo.GET", "arguments": {},
|
|
577
581
|
"_meta": {"io.modelcontextprotocol/protocolVersion": "2026-07-28",
|
|
578
582
|
"io.modelcontextprotocol/clientCapabilities": {}}}}
|
|
579
583
|
"""
|
|
@@ -612,10 +616,10 @@ Feature: Model Context Protocol
|
|
|
612
616
|
content-type: application/json
|
|
613
617
|
mcp-protocol-version: 2026-07-28
|
|
614
618
|
mcp-method: tools/call
|
|
615
|
-
mcp-name: echo
|
|
619
|
+
mcp-name: echo.GET
|
|
616
620
|
|
|
617
621
|
{"jsonrpc": "2.0", "id": 11, "method": "tools/call",
|
|
618
|
-
"params": {"name": "echo
|
|
622
|
+
"params": {"name": "echo.GET", "arguments": {"greeting": "hello"},
|
|
619
623
|
"_meta": {"io.modelcontextprotocol/protocolVersion": "2026-07-28",
|
|
620
624
|
"io.modelcontextprotocol/clientCapabilities": {}}}}
|
|
621
625
|
"""
|
package/features/rpc.feature
CHANGED
|
@@ -43,7 +43,7 @@ Feature: JSON-RPC
|
|
|
43
43
|
accept: application/yaml
|
|
44
44
|
content-type: application/json
|
|
45
45
|
|
|
46
|
-
{"jsonrpc": "2.0", "id": 1, "method": "pots
|
|
46
|
+
{"jsonrpc": "2.0", "id": 1, "method": "pots._id.GET",
|
|
47
47
|
"params": {"id": "4c4759e6f9c74da989d64511df42d6f4"}}
|
|
48
48
|
"""
|
|
49
49
|
Then the following reply is sent:
|
|
@@ -67,7 +67,7 @@ Feature: JSON-RPC
|
|
|
67
67
|
accept: application/yaml
|
|
68
68
|
content-type: application/json
|
|
69
69
|
|
|
70
|
-
{"jsonrpc": "2.0", "id": 2, "method": "pots
|
|
70
|
+
{"jsonrpc": "2.0", "id": 2, "method": "pots.POST",
|
|
71
71
|
"params": {"title": "Kettle", "volume": 1.7}}
|
|
72
72
|
"""
|
|
73
73
|
Then the following reply is sent:
|
|
@@ -88,7 +88,7 @@ Feature: JSON-RPC
|
|
|
88
88
|
accept: application/yaml
|
|
89
89
|
content-type: application/json
|
|
90
90
|
|
|
91
|
-
{"jsonrpc": "2.0", "id": 3, "method": "pots
|
|
91
|
+
{"jsonrpc": "2.0", "id": 3, "method": "pots.GET",
|
|
92
92
|
"params": {"query": {"limit": 1}}}
|
|
93
93
|
"""
|
|
94
94
|
Then the following reply is sent:
|
|
@@ -108,7 +108,7 @@ Feature: JSON-RPC
|
|
|
108
108
|
host: nex.toa.io
|
|
109
109
|
content-type: application/json
|
|
110
110
|
|
|
111
|
-
{"jsonrpc": "2.0", "method": "pots
|
|
111
|
+
{"jsonrpc": "2.0", "method": "pots.POST", "params": {"title": "Pot", "volume": 1}}
|
|
112
112
|
"""
|
|
113
113
|
Then the following reply is sent:
|
|
114
114
|
"""
|
|
@@ -123,7 +123,7 @@ Feature: JSON-RPC
|
|
|
123
123
|
accept: application/yaml
|
|
124
124
|
content-type: application/json
|
|
125
125
|
|
|
126
|
-
{"jsonrpc": "2.0", "id": 4, "method": "kettles
|
|
126
|
+
{"jsonrpc": "2.0", "id": 4, "method": "kettles.GET", "params": {}}
|
|
127
127
|
"""
|
|
128
128
|
Then the following reply is sent:
|
|
129
129
|
"""
|
|
@@ -163,7 +163,7 @@ Feature: JSON-RPC
|
|
|
163
163
|
accept: application/yaml
|
|
164
164
|
content-type: application/json
|
|
165
165
|
|
|
166
|
-
{"jsonrpc": "2.0", "id": 17, "method": "pots
|
|
166
|
+
{"jsonrpc": "2.0", "id": 17, "method": "pots.GET", "params": {}}
|
|
167
167
|
"""
|
|
168
168
|
Then the following reply is sent:
|
|
169
169
|
"""
|
|
@@ -216,7 +216,7 @@ Feature: JSON-RPC
|
|
|
216
216
|
accept: application/yaml
|
|
217
217
|
content-type: application/json
|
|
218
218
|
|
|
219
|
-
{"jsonrpc": "2.0", "id": 5, "method": "pots
|
|
219
|
+
{"jsonrpc": "2.0", "id": 5, "method": "pots._id.GET", "params": {}}
|
|
220
220
|
"""
|
|
221
221
|
Then the following reply is sent:
|
|
222
222
|
"""
|
|
@@ -236,7 +236,7 @@ Feature: JSON-RPC
|
|
|
236
236
|
accept: application/yaml
|
|
237
237
|
content-type: application/json
|
|
238
238
|
|
|
239
|
-
{"jsonrpc": "2.0", "id": 6, "method": "pots
|
|
239
|
+
{"jsonrpc": "2.0", "id": 6, "method": "pots.faulty.GET", "params": {}}
|
|
240
240
|
"""
|
|
241
241
|
Then the following reply is sent:
|
|
242
242
|
"""
|
|
@@ -256,7 +256,7 @@ Feature: JSON-RPC
|
|
|
256
256
|
accept: application/yaml
|
|
257
257
|
content-type: application/json
|
|
258
258
|
|
|
259
|
-
{"jsonrpc": "2.0", "id": 7, "method": "pots
|
|
259
|
+
{"jsonrpc": "2.0", "id": 7, "method": "pots.guarded.GET", "params": {}}
|
|
260
260
|
"""
|
|
261
261
|
Then the following reply is sent:
|
|
262
262
|
"""
|
|
@@ -271,10 +271,10 @@ Feature: JSON-RPC
|
|
|
271
271
|
accept: application/yaml
|
|
272
272
|
content-type: application/json
|
|
273
273
|
|
|
274
|
-
[{"jsonrpc": "2.0", "id": 8, "method": "pots
|
|
274
|
+
[{"jsonrpc": "2.0", "id": 8, "method": "pots._id.GET",
|
|
275
275
|
"params": {"id": "4c4759e6f9c74da989d64511df42d6f4"}},
|
|
276
|
-
{"jsonrpc": "2.0", "id": 9, "method": "kettles
|
|
277
|
-
{"jsonrpc": "2.0", "method": "pots
|
|
276
|
+
{"jsonrpc": "2.0", "id": 9, "method": "kettles.GET", "params": {}},
|
|
277
|
+
{"jsonrpc": "2.0", "method": "pots.POST", "params": {"title": "Pot", "volume": 1}}]
|
|
278
278
|
"""
|
|
279
279
|
Then the following reply is sent:
|
|
280
280
|
"""
|
|
@@ -299,9 +299,9 @@ Feature: JSON-RPC
|
|
|
299
299
|
accept: application/yaml
|
|
300
300
|
content-type: application/json
|
|
301
301
|
|
|
302
|
-
[{"jsonrpc": "2.0", "id": 13, "method": "pots
|
|
303
|
-
{"jsonrpc": "2.0", "id": 14, "method": "pots
|
|
304
|
-
{"jsonrpc": "2.0", "id": 15, "method": "pots
|
|
302
|
+
[{"jsonrpc": "2.0", "id": 13, "method": "pots.GET", "params": {}},
|
|
303
|
+
{"jsonrpc": "2.0", "id": 14, "method": "pots.GET", "params": {}},
|
|
304
|
+
{"jsonrpc": "2.0", "id": 15, "method": "pots.GET", "params": {}}]
|
|
305
305
|
"""
|
|
306
306
|
Then the following reply is sent:
|
|
307
307
|
"""
|
|
@@ -320,8 +320,8 @@ Feature: JSON-RPC
|
|
|
320
320
|
host: nex.toa.io
|
|
321
321
|
content-type: application/json
|
|
322
322
|
|
|
323
|
-
[{"jsonrpc": "2.0", "method": "pots
|
|
324
|
-
{"jsonrpc": "2.0", "method": "pots
|
|
323
|
+
[{"jsonrpc": "2.0", "method": "pots.POST", "params": {"title": "One", "volume": 1}},
|
|
324
|
+
{"jsonrpc": "2.0", "method": "pots.POST", "params": {"title": "Two", "volume": 2}}]
|
|
325
325
|
"""
|
|
326
326
|
Then the following reply is sent:
|
|
327
327
|
"""
|
|
@@ -356,7 +356,7 @@ Feature: JSON-RPC
|
|
|
356
356
|
accept: application/yaml
|
|
357
357
|
content-type: application/json
|
|
358
358
|
|
|
359
|
-
{"jsonrpc": "1.0", "id": 10, "method": "pots
|
|
359
|
+
{"jsonrpc": "1.0", "id": 10, "method": "pots.GET"}
|
|
360
360
|
"""
|
|
361
361
|
Then the following reply is sent:
|
|
362
362
|
"""
|
|
@@ -394,8 +394,8 @@ Feature: JSON-RPC
|
|
|
394
394
|
accept: application/yaml
|
|
395
395
|
content-type: application/json
|
|
396
396
|
|
|
397
|
-
[{"jsonrpc": "2.0", "id": 11, "method": "pots
|
|
398
|
-
{"jsonrpc": "2.0", "id": 12, "method": "pots
|
|
397
|
+
[{"jsonrpc": "2.0", "id": 11, "method": "pots.GET", "params": {}},
|
|
398
|
+
{"jsonrpc": "2.0", "id": 12, "method": "pots.GET", "params": {}}]
|
|
399
399
|
"""
|
|
400
400
|
Then the following reply is sent:
|
|
401
401
|
"""
|
|
@@ -421,7 +421,7 @@ Feature: JSON-RPC
|
|
|
421
421
|
accept: application/yaml
|
|
422
422
|
content-type: application/json
|
|
423
423
|
|
|
424
|
-
{"jsonrpc": "2.0", "id": 9, "method": "pots
|
|
424
|
+
{"jsonrpc": "2.0", "id": 9, "method": "pots.GET", "params": {}}
|
|
425
425
|
"""
|
|
426
426
|
Then the following reply is sent:
|
|
427
427
|
"""
|
|
@@ -158,8 +158,9 @@ export class Gateway {
|
|
|
158
158
|
/*
|
|
159
159
|
* The gateway waits for the branches it discovers, but a component's own resources —
|
|
160
160
|
* a storage, a queue — are still connecting when it answers. Fifty milliseconds was
|
|
161
|
-
* enough until the composition grew; a scenario that asks too early
|
|
162
|
-
* precedes the route
|
|
161
|
+
* enough until the composition grew, then a hundred; a scenario that asks too early
|
|
162
|
+
* reads the 404 that precedes the route, which `realtime` was failing on in two runs
|
|
163
|
+
* of three. It is a sleep and not a poll, so it is raised rather than fixed.
|
|
163
164
|
*/
|
|
164
165
|
await timeout(DISCOVERY)
|
|
165
166
|
}
|
|
@@ -217,7 +218,7 @@ const DEFAULT_TREE = JSON.stringify({
|
|
|
217
218
|
} satisfies syntax.Node)
|
|
218
219
|
|
|
219
220
|
/** Milliseconds a composition is given to finish connecting what it needs. */
|
|
220
|
-
const DISCOVERY =
|
|
221
|
+
const DISCOVERY = 500
|
|
221
222
|
|
|
222
223
|
const DEFAULT_PROPERTIES: Partial<http.Options> = {
|
|
223
224
|
authorities: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toa.io/extensions.exposition",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.285",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Toa Exposition",
|
|
6
6
|
"author": "temich <tema.gurtovoy@gmail.com>",
|
|
@@ -58,5 +58,5 @@
|
|
|
58
58
|
"@types/cors": "2.8.19",
|
|
59
59
|
"@types/negotiator": "0.6.5"
|
|
60
60
|
},
|
|
61
|
-
"gitHead": "
|
|
61
|
+
"gitHead": "44ed1be7e322a5ea8f1a8ed85ba96b9dfaf28224"
|
|
62
62
|
}
|
package/source/Introspection.ts
CHANGED
|
@@ -8,6 +8,9 @@ export interface Introspection {
|
|
|
8
8
|
* one sentence cannot be true of both. The operation's own is for the Introspection.
|
|
9
9
|
*/
|
|
10
10
|
description?: string
|
|
11
|
+
|
|
12
|
+
/** what a person is shown where a client lists this method, which a name is not */
|
|
13
|
+
title?: string
|
|
11
14
|
route?: Record<string, Schema>
|
|
12
15
|
query?: Record<string, Schema>
|
|
13
16
|
|
|
@@ -40,7 +43,7 @@ export function order (introspection: Introspection): Introspection {
|
|
|
40
43
|
return ordered
|
|
41
44
|
}
|
|
42
45
|
|
|
43
|
-
const KEYS = ['description', 'route', 'query', 'headers', 'input', 'output', 'errors'] as const
|
|
46
|
+
const KEYS = ['title', 'description', 'route', 'query', 'headers', 'input', 'output', 'errors'] as const
|
|
44
47
|
|
|
45
48
|
/**
|
|
46
49
|
* The schema of one input property, taken out of it: a property another family fills is
|
package/source/MCP/tools.ts
CHANGED
|
@@ -54,6 +54,7 @@ export async function list (tree: Tree, context: http.Context): Promise<Tool[]>
|
|
|
54
54
|
// in the order the revision documents one, which is the order it is read in
|
|
55
55
|
const tool: Tool = {
|
|
56
56
|
name: named,
|
|
57
|
+
...introspection.title === undefined ? {} : { title: introspection.title },
|
|
57
58
|
...described === undefined ? {} : { description: described },
|
|
58
59
|
inputSchema: input(introspection, variables.map((variable) => variable.name)),
|
|
59
60
|
...schema === undefined ? {} : { outputSchema: schema },
|
package/source/MCP/types.ts
CHANGED
|
@@ -66,7 +66,10 @@ export interface Content {
|
|
|
66
66
|
export interface Tool {
|
|
67
67
|
name: string
|
|
68
68
|
|
|
69
|
-
/** what
|
|
69
|
+
/** what a person is shown where a client lists this tool; a name is an address */
|
|
70
|
+
title?: string
|
|
71
|
+
|
|
72
|
+
/** what the route states this method is */
|
|
70
73
|
description?: string
|
|
71
74
|
inputSchema: object
|
|
72
75
|
outputSchema?: object
|