@qilin-agent/mcp-resources 0.0.0-stage → 3.1.4
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 +21 -0
- package/README.i18n.yaml +64 -0
- package/README.md +133 -2
- package/README.zh.md +134 -0
- package/lib/index.js +181 -0
- package/lib/types/index.d.ts +53 -0
- package/lib/types/render.d.ts +15 -0
- package/lib/types/tools.d.ts +19 -0
- package/package.json +53 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 kkutysllb
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.i18n.yaml
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Bilingual-pair consistency record for README.md (docs/i18n/README.md): per heading
|
|
2
|
+
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
|
|
3
|
+
# After editing either side, bring the other along and re-record with:
|
|
4
|
+
# pnpm run verify-translation-pairing --write packages/mcp/mcp-resources/README.md
|
|
5
|
+
/:
|
|
6
|
+
en: 34b851d97ea0313e
|
|
7
|
+
zh: 2fa00063647b6eee
|
|
8
|
+
/qilin-agent-mcp-resources:
|
|
9
|
+
en: 6fd173493f20a57e
|
|
10
|
+
zh: 4d9677fa6aa459da
|
|
11
|
+
/qilin-agent-mcp-resources/summary:
|
|
12
|
+
en: bce3ffe5fdd801a6
|
|
13
|
+
zh: 7378d3a526c0043a
|
|
14
|
+
/qilin-agent-mcp-resources/table-of-contents:
|
|
15
|
+
en: d152484eb41ac6b4
|
|
16
|
+
zh: 725b47765ee8f30b
|
|
17
|
+
/qilin-agent-mcp-resources/use-this-package:
|
|
18
|
+
en: 1f8d430124c6b30b
|
|
19
|
+
zh: f8beadb2461b3d91
|
|
20
|
+
/qilin-agent-mcp-resources/use-this-package/server-configuration:
|
|
21
|
+
en: 40166de24ff78e77
|
|
22
|
+
zh: 29f269bfea41164a
|
|
23
|
+
/qilin-agent-mcp-resources/use-this-package/discover-and-read:
|
|
24
|
+
en: f7fb6597acd3c5dc
|
|
25
|
+
zh: 9c59219fb4ab00d9
|
|
26
|
+
/qilin-agent-mcp-resources/understand-the-implementation:
|
|
27
|
+
en: fb5ca02328f07491
|
|
28
|
+
zh: b4392bce3371203e
|
|
29
|
+
/qilin-agent-mcp-resources/further-exploration:
|
|
30
|
+
en: d1ab183ea9b282a5
|
|
31
|
+
zh: ed27a99bd03e0c8c
|
|
32
|
+
/qilin-agent-mcp-resources/model-experience:
|
|
33
|
+
en: 215e7ba838619b7b
|
|
34
|
+
zh: a311da3843709f90
|
|
35
|
+
/qilin-agent-mcp-resources/model-experience/shared-resource-tools:
|
|
36
|
+
en: 520e0b6cb35e4285
|
|
37
|
+
zh: 20a323f87e6d12fc
|
|
38
|
+
/qilin-agent-mcp-resources/model-experience/shared-resource-tools/what-the-model-sees:
|
|
39
|
+
en: a660f500f0ae911d
|
|
40
|
+
zh: abffab84afb60121
|
|
41
|
+
/qilin-agent-mcp-resources/model-experience/shared-resource-tools/token-effect:
|
|
42
|
+
en: 92682e15ca9e90a5
|
|
43
|
+
zh: 3487ef2adb89c9e4
|
|
44
|
+
/qilin-agent-mcp-resources/model-experience/shared-resource-tools/kv-cache-effect:
|
|
45
|
+
en: fdb450babcdf877b
|
|
46
|
+
zh: f013ae46ce9e1125
|
|
47
|
+
/qilin-agent-mcp-resources/model-experience/resource-results:
|
|
48
|
+
en: f46ae3151a215b4d
|
|
49
|
+
zh: 8d15019792d3fe61
|
|
50
|
+
/qilin-agent-mcp-resources/model-experience/resource-results/what-the-model-sees:
|
|
51
|
+
en: 62d0a18c52283474
|
|
52
|
+
zh: 70b2fbea70c98818
|
|
53
|
+
/qilin-agent-mcp-resources/model-experience/resource-results/token-effect:
|
|
54
|
+
en: e6fb5043a1ccc6ff
|
|
55
|
+
zh: d15d2e7b5986d614
|
|
56
|
+
/qilin-agent-mcp-resources/model-experience/resource-results/kv-cache-effect:
|
|
57
|
+
en: ea0dfc069bf175c0
|
|
58
|
+
zh: 3e1465e56ff79764
|
|
59
|
+
/qilin-agent-mcp-resources/known-limitations-and-deferred-work:
|
|
60
|
+
en: 58d13dc99946c11d
|
|
61
|
+
zh: 4099c46a1ca60512
|
|
62
|
+
/qilin-agent-mcp-resources/known-limitations-and-deferred-work/dev-note:
|
|
63
|
+
en: e67f633dc6fe7773
|
|
64
|
+
zh: 3bb0c20c93f16f98
|
package/README.md
CHANGED
|
@@ -1,3 +1,134 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
description: "Discover and read MCP resources on demand with shared tools, explicit server selection, and agent-scoped access."
|
|
3
|
+
kind: "package-reference"
|
|
4
|
+
---
|
|
2
5
|
|
|
3
|
-
|
|
6
|
+
# @qilin-agent/mcp-resources
|
|
7
|
+
|
|
8
|
+
English | [中文](README.zh.md)
|
|
9
|
+
|
|
10
|
+
## Summary
|
|
11
|
+
|
|
12
|
+
`qilin-mcp-resources` lets the model discover and read documents from configured MCP servers. Shipped profiles make its three shared tools available automatically when a server is configured in the caller's scope. Each tool requires an explicit server name and reads content only when called. Resource text enters conversation history; binary payloads remain available to programmatic callers and appear as descriptions to the model.
|
|
13
|
+
|
|
14
|
+
## Table of Contents
|
|
15
|
+
|
|
16
|
+
- [Use this package](#use-this-package)
|
|
17
|
+
- [Understand the implementation](#understand-the-implementation)
|
|
18
|
+
- [Further Exploration](#further-exploration)
|
|
19
|
+
- [Model Experience](#model-experience)
|
|
20
|
+
- [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
|
|
21
|
+
- [Dev Note](#dev-note)
|
|
22
|
+
|
|
23
|
+
-----
|
|
24
|
+
|
|
25
|
+
<a id="use-this-package"></a>
|
|
26
|
+
## Use this package
|
|
27
|
+
|
|
28
|
+
Shipped profiles already mount this package once. Configure only the [MCP client](../mcp-client/README.md) entries for the servers you need.
|
|
29
|
+
|
|
30
|
+
### Server configuration
|
|
31
|
+
|
|
32
|
+
Use the [client configuration](../mcp-client/README.md#use-this-package) to add a server in the intended scope. This package has no configuration fields.
|
|
33
|
+
|
|
34
|
+
A caller with no configured MCP server sees no MCP prompt text or resource tools in native or PTC mode. A configured server enables the three shared resource tools, including when another provider mounts its client or the server has no tools or instructions. Connection failures do not remove the shared tools while the client entry remains active; resource calls report the connection error.
|
|
35
|
+
|
|
36
|
+
### Discover and read
|
|
37
|
+
|
|
38
|
+
When system-prompt assembly is mounted, the prompt lists server names visible to the calling agent. Call `list_mcp_resources` or `list_mcp_resource_templates` with one of those names as `server`. Without a cursor, the MCP SDK collects the server’s pages. An explicit `cursor` requests that page; pass a returned `nextCursor` unchanged. Read a listed URI or an expanded template with `read_mcp_resource`, using the same `server` name and an explicit `uri`.
|
|
39
|
+
|
|
40
|
+
Every operation resolves the server in the calling agent's scope. A missing server argument or unavailable server fails before dispatch. The connection owner handles request cancellation, timeouts, and recovery; a failed request remains a failed tool call.
|
|
41
|
+
|
|
42
|
+
-----
|
|
43
|
+
|
|
44
|
+
<a id="understand-the-implementation"></a>
|
|
45
|
+
## Understand the implementation
|
|
46
|
+
|
|
47
|
+
<details>
|
|
48
|
+
<summary>Implementation internals — click to expand</summary>
|
|
49
|
+
|
|
50
|
+
The [base](../../bundle/base/README.md) and standalone [sdk-minimal](../../bundle/sdk-minimal/README.md) bundles each own this row:
|
|
51
|
+
|
|
52
|
+
```yaml
|
|
53
|
+
- id: mcp-resources
|
|
54
|
+
name: '@qilin-agent/mcp-resources'
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The first provider in a scope registers its shared tools; removing the last removes those local registrations, while inherited providers and tools remain visible. The resource service owns the shared tool effects independently of the first provider's plugin, so unloading that provider cannot remove tools needed by another server. Provider selection and the server-name prompt use the same scoped registry. Each call resolves its server before dispatch.
|
|
58
|
+
|
|
59
|
+
Canonical results retain the complete JSON for programmatic callers. The pure text renderer adds server attribution and replaces string-valued `blob` fields with a description of their base64 length; URI, MIME type, and text fields remain in the rendered JSON. The tool pipeline owns recorded results. Server instructions belong to the MCP client and its logged system-prompt section.
|
|
60
|
+
|
|
61
|
+
| Source | Responsibility |
|
|
62
|
+
|---|---|
|
|
63
|
+
| [`src/index.ts`](src/index.ts) | Scoped provider selection and server-name prompt context |
|
|
64
|
+
| [`src/tools.ts`](src/tools.ts) | Shared resource operations and argument schemas |
|
|
65
|
+
| [`src/render.ts`](src/render.ts) | Attributed text projection without inline binary payloads |
|
|
66
|
+
|
|
67
|
+
</details>
|
|
68
|
+
|
|
69
|
+
-----
|
|
70
|
+
|
|
71
|
+
<a id="further-exploration"></a>
|
|
72
|
+
## Further Exploration
|
|
73
|
+
|
|
74
|
+
These pages cover server configuration, execution, and the decisions behind resource access.
|
|
75
|
+
|
|
76
|
+
- [MCP client](../mcp-client/README.md) — server transports, instructions, and connection lifecycle.
|
|
77
|
+
- [Tools subsystem](../../../docs/subsystems/tools.md) — canonical values and model-visible results.
|
|
78
|
+
- [Resource visibility decision](../../../.agents/notes/implemented/feature/2026-09-13-mcp-resources-in-profiles.md) — shared profile mounting and visibility from configured servers.
|
|
79
|
+
- [Resources and instructions decision](../../../.agents/notes/implemented/feature/2026-09-12-mcp-resources-and-instructions.md) — scope, on-demand access, and excluded mechanisms.
|
|
80
|
+
|
|
81
|
+
-----
|
|
82
|
+
|
|
83
|
+
<a id="model-experience"></a>
|
|
84
|
+
## Model Experience
|
|
85
|
+
|
|
86
|
+
### Shared resource tools
|
|
87
|
+
|
|
88
|
+
#### What the model sees
|
|
89
|
+
|
|
90
|
+
The [generated tool schemas](../../../docs/tool-catalog.md#qilin-agentmcp-resources) define three tools shared by all caller-visible configured servers. With none, native schemas, PTC declarations and bindings, and the server-name prompt are absent. Connecting, disconnecting, or retrying an active client leaves these shared tool definitions unchanged. When system-prompt assembly is mounted and providers are visible, the `MCP resource servers` section says `Use list_mcp_resources, list_mcp_resource_templates, or read_mcp_resource with one of these names as the server argument: <JSON array>.` The names come from the same scoped registry, including servers with neither tools nor instructions. An empty registry contributes no section.
|
|
91
|
+
|
|
92
|
+
#### Token effect
|
|
93
|
+
|
|
94
|
+
With no caller-visible configured servers, this package adds no tool or prompt tokens. Otherwise, three shared definitions contribute a fixed schema cost and the server-name section adds a sorted JSON list of visible names. Resource listings and documents add content only when an operation returns them.
|
|
95
|
+
|
|
96
|
+
#### KV Cache effect
|
|
97
|
+
|
|
98
|
+
Adding the first caller-visible server or removing the last changes the next tool schema or PTC declaration prefix. Changes to visible names update the server-name section; replacing a provider under the same name leaves that text unchanged. Connection failures alone do not change the shared definitions or names.
|
|
99
|
+
|
|
100
|
+
### Resource results
|
|
101
|
+
|
|
102
|
+
#### What the model sees
|
|
103
|
+
|
|
104
|
+
A successful result starts with `MCP server: <server>`, followed by a newline and the returned JSON. Each string-valued `blob` becomes `[binary resource: <length> base64 characters; available to programmatic callers]`. Server-provided text, metadata, and continuation cursors remain visible.
|
|
105
|
+
|
|
106
|
+
#### Token effect
|
|
107
|
+
|
|
108
|
+
Rendered results add text to tool history. Binary descriptions replace the payload's base64 token cost; this package imposes no separate text-size limit.
|
|
109
|
+
|
|
110
|
+
#### KV Cache effect
|
|
111
|
+
|
|
112
|
+
Each result appends to history without rewriting earlier results. Later reads can return changed server content and append a different result; the package does not refresh previously recorded content.
|
|
113
|
+
|
|
114
|
+
## Known Limitations and Deferred Work
|
|
115
|
+
|
|
116
|
+
<a id="known-limitations-and-deferred-work"></a>
|
|
117
|
+
|
|
118
|
+
Resource access is explicit and on demand.
|
|
119
|
+
|
|
120
|
+
- A configured server without the MCP `resources` capability still appears in the server-name prompt and keeps shared resource tools available. The SDK returns empty resource and template lists; unsupported reads fail.
|
|
121
|
+
- `tools.restrict()` checks names supplied by global or ancestor scopes when the filter is registered. Naming a resource tool absent from those scopes fails as an unknown tool. Resource tools registered in the caller's own scope are outside allow/deny masks.
|
|
122
|
+
- Resource subscriptions and update notifications are unsupported; call the list or read tools again to obtain current content.
|
|
123
|
+
- Binary resources are not projected as native images or audio. Programmatic callers retain their canonical base64 values.
|
|
124
|
+
- The caller must supply a server name. The shared tools do not aggregate different servers; pagination follows the MCP SDK.
|
|
125
|
+
|
|
126
|
+
<a id="dev-note"></a>
|
|
127
|
+
### Dev Note
|
|
128
|
+
|
|
129
|
+
<details>
|
|
130
|
+
<summary>Working context for maintainers — click to expand</summary>
|
|
131
|
+
|
|
132
|
+
None.
|
|
133
|
+
|
|
134
|
+
</details>
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "通过共享工具、显式服务器选择和 agent 作用域访问,按需发现与读取 MCP 资源。"
|
|
3
|
+
kind: "package-reference"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @qilin-agent/mcp-resources
|
|
7
|
+
|
|
8
|
+
[English](README.md) | 中文
|
|
9
|
+
|
|
10
|
+
## 概述
|
|
11
|
+
|
|
12
|
+
`qilin-mcp-resources` 让模型发现和读取已配置 MCP 服务器提供的文档。随附 profile 在调用方作用域中配置了服务器时,自动提供三个共享工具。每个工具都要求显式指定服务器名称,并且仅在调用时读取内容。资源文本进入对话历史;二进制载荷仍可供程序化调用方访问,并以说明文字呈现给模型。
|
|
13
|
+
|
|
14
|
+
## 目录
|
|
15
|
+
|
|
16
|
+
- [使用本包](#use-this-package)
|
|
17
|
+
- [理解实现](#understand-the-implementation)
|
|
18
|
+
- [进一步探索](#further-exploration)
|
|
19
|
+
- [模型体验](#model-experience)
|
|
20
|
+
- [已知限制与延后工作](#known-limitations-and-deferred-work)
|
|
21
|
+
- [开发备注](#dev-note)
|
|
22
|
+
|
|
23
|
+
-----
|
|
24
|
+
|
|
25
|
+
<a id="use-this-package"></a>
|
|
26
|
+
## 使用本包
|
|
27
|
+
|
|
28
|
+
随附 profile 已经统一挂载本包一次。你只需为所需服务器配置 [MCP 客户端](../mcp-client/README.zh.md)条目。
|
|
29
|
+
|
|
30
|
+
### 服务器配置
|
|
31
|
+
|
|
32
|
+
通过[客户端配置](../mcp-client/README.zh.md#use-this-package)在目标作用域中添加服务器。本包没有配置字段。
|
|
33
|
+
|
|
34
|
+
调用方没有已配置 MCP 服务器时,在 native 或 PTC 模式下都看不到 MCP 提示词文本或资源工具。配置服务器后会启用三个共享资源工具,包括由其他提供方挂载客户端的服务器,以及没有工具或指令的服务器。只要客户端条目保持激活,连接失败就不会移除共享工具;资源调用会报告连接错误。
|
|
35
|
+
|
|
36
|
+
### 发现与读取
|
|
37
|
+
|
|
38
|
+
挂载系统提示词组装服务时,提示词列出调用 agent 可见的服务器名称。将其中一个名称作为 `server` 调用 `list_mcp_resources` 或 `list_mcp_resource_templates`。未提供游标时,MCP SDK 收集服务器的全部分页;显式提供游标时返回一页;将其中的 `nextCursor` 原样作为 `cursor` 传入,以请求下一页。使用相同的 `server` 名称和显式 `uri`,通过 `read_mcp_resource` 读取已列出的 URI 或展开后的模板。
|
|
39
|
+
|
|
40
|
+
每个操作都在调用 agent 的作用域中解析服务器。缺少服务器参数或服务器不可用时,会在派发前失败。连接所有者负责请求取消、超时与恢复;失败的请求仍表现为失败的工具调用。
|
|
41
|
+
|
|
42
|
+
-----
|
|
43
|
+
|
|
44
|
+
<a id="understand-the-implementation"></a>
|
|
45
|
+
## 理解实现
|
|
46
|
+
|
|
47
|
+
<details>
|
|
48
|
+
<summary>实现内部细节——点击展开</summary>
|
|
49
|
+
|
|
50
|
+
[base](../../bundle/base/README.zh.md) 与独立的 [sdk-minimal](../../bundle/sdk-minimal/README.zh.md) bundle 分别拥有以下配置行:
|
|
51
|
+
|
|
52
|
+
```yaml
|
|
53
|
+
- id: mcp-resources
|
|
54
|
+
name: '@qilin-agent/mcp-resources'
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
作用域中的首个提供方注册该作用域的共享工具;移除最后一个提供方会移除本地工具注册,继承的提供方与工具仍然可见。资源服务独立于首个提供方插件拥有共享工具 effect,因此卸载该提供方不会移除其他服务器仍需要的工具。提供方选择与服务器名称提示词使用同一作用域注册表。每次调用都在派发前解析服务器。
|
|
58
|
+
|
|
59
|
+
规范结果为程序化调用方保留完整 JSON。纯文本渲染器添加服务器归属信息,并将字符串值的 `blob` 字段替换为说明其 base64 长度的文字;URI、MIME 类型与文本字段仍保留在渲染后的 JSON 中。工具流水线负责记录结果。服务器指令归 MCP 客户端及其已记录的系统提示词段落所有。
|
|
60
|
+
|
|
61
|
+
| 源码 | 职责 |
|
|
62
|
+
|---|---|
|
|
63
|
+
| [`src/index.ts`](src/index.ts) | 作用域提供方选择与服务器名称提示词上下文 |
|
|
64
|
+
| [`src/tools.ts`](src/tools.ts) | 共享资源操作与参数 schema |
|
|
65
|
+
| [`src/render.ts`](src/render.ts) | 带归属信息且不内联二进制载荷的文本投影 |
|
|
66
|
+
|
|
67
|
+
</details>
|
|
68
|
+
|
|
69
|
+
-----
|
|
70
|
+
|
|
71
|
+
<a id="further-exploration"></a>
|
|
72
|
+
## 进一步探索
|
|
73
|
+
|
|
74
|
+
以下页面介绍服务器配置、执行机制与资源访问决策。
|
|
75
|
+
|
|
76
|
+
- [MCP 客户端](../mcp-client/README.zh.md)——服务器传输、指令与连接生命周期。
|
|
77
|
+
- [工具子系统](../../../docs/subsystems/tools.zh.md)——规范值与模型可见结果。
|
|
78
|
+
- [资源可见性决策](../../../.agents/notes/implemented/feature/2026-09-13-mcp-resources-in-profiles.zh.md)——profile 统一挂载及由已配置服务器决定的可见性。
|
|
79
|
+
- [资源与指令决策](../../../.agents/notes/implemented/feature/2026-09-12-mcp-resources-and-instructions.zh.md)——作用域、按需访问及未纳入的机制。
|
|
80
|
+
|
|
81
|
+
-----
|
|
82
|
+
|
|
83
|
+
<a id="model-experience"></a>
|
|
84
|
+
## 模型体验
|
|
85
|
+
|
|
86
|
+
### 共享资源工具
|
|
87
|
+
|
|
88
|
+
#### 模型看到什么
|
|
89
|
+
|
|
90
|
+
[生成的工具 schema](../../../docs/tool-catalog.zh.md#qilin-agentmcp-resources)定义了调用方可见的所有已配置服务器共享的三个工具。没有这类服务器时,native schema、PTC 声明与绑定以及服务器名称提示词均不存在。激活的客户端连接、断开或重试时,这些共享工具定义保持不变。挂载系统提示词装配且存在可见提供方时,`MCP resource servers` 段落显示 `Use list_mcp_resources, list_mcp_resource_templates, or read_mcp_resource with one of these names as the server argument: <JSON array>.` 名称来自同一作用域注册表,包括既没有工具也没有指令的服务器。注册表为空时不贡献该段落。
|
|
91
|
+
|
|
92
|
+
#### Token 影响
|
|
93
|
+
|
|
94
|
+
没有调用方可见的已配置服务器时,本包不增加工具或提示词 token。否则,三个共享定义带来固定的 schema 开销,服务器名称段落增加按序排列的可见名称 JSON 列表。资源列表和文档仅在操作返回后增加内容。
|
|
95
|
+
|
|
96
|
+
#### KV Cache 影响
|
|
97
|
+
|
|
98
|
+
添加调用方可见的首个服务器或移除最后一个服务器,会改变后续工具 schema 或 PTC 声明前缀。可见名称变化时更新服务器名称段落;替换同名提供方不会改变该文本。单纯的连接失败不会改变共享定义或名称。
|
|
99
|
+
|
|
100
|
+
### 资源结果
|
|
101
|
+
|
|
102
|
+
#### 模型看到什么
|
|
103
|
+
|
|
104
|
+
成功结果以 `MCP server: <server>` 开头,随后是换行和返回的 JSON。每个字符串值的 `blob` 都变为 `[binary resource: <length> base64 characters; available to programmatic callers]`。服务器提供的文本、元数据与续传游标仍然可见。
|
|
105
|
+
|
|
106
|
+
#### Token 影响
|
|
107
|
+
|
|
108
|
+
渲染后的结果向工具历史添加文本。二进制说明文字替代载荷的 base64 token 开销;本包不设置额外的文本大小限制。
|
|
109
|
+
|
|
110
|
+
#### KV Cache 影响
|
|
111
|
+
|
|
112
|
+
每个结果追加到历史中,不改写此前的结果。后续读取可以返回已变化的服务器内容并追加不同结果;本包不会刷新此前已记录的内容。
|
|
113
|
+
|
|
114
|
+
## 已知限制与延后工作
|
|
115
|
+
|
|
116
|
+
<a id="known-limitations-and-deferred-work"></a>
|
|
117
|
+
|
|
118
|
+
资源访问由显式调用按需发起。
|
|
119
|
+
|
|
120
|
+
- 不具备 MCP `resources` 能力的已配置服务器仍会出现在服务器名称提示词中,并保持共享资源工具可用。SDK 返回空的资源列表与模板列表;不受支持的读取会失败。
|
|
121
|
+
- `tools.restrict()` 在注册过滤条件时检查全局或祖先作用域提供的名称。引用这些作用域中不存在的资源工具名称会报未知工具错误。注册在调用方自身作用域中的资源工具不受 allow/deny 掩码过滤。
|
|
122
|
+
- 不支持资源订阅与更新通知;再次调用列表或读取工具以获取当前内容。
|
|
123
|
+
- 二进制资源不会投影为原生图片或音频。程序化调用方保留其规范 base64 值。
|
|
124
|
+
- 调用方必须提供服务器名称。共享工具不会聚合不同服务器;分页遵循 MCP SDK。
|
|
125
|
+
|
|
126
|
+
<a id="dev-note"></a>
|
|
127
|
+
### 开发备注
|
|
128
|
+
|
|
129
|
+
<details>
|
|
130
|
+
<summary>维护者的工作上下文——点击展开</summary>
|
|
131
|
+
|
|
132
|
+
无。
|
|
133
|
+
|
|
134
|
+
</details>
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { Service } from "@qilin-agent/kylin";
|
|
2
|
+
import { NamedEntries, ScopedLayers, createScope, scopeOf } from "@qilin-agent/scope";
|
|
3
|
+
import { defineTool } from "@qilin-agent/tools";
|
|
4
|
+
//#region lib/types/render.js
|
|
5
|
+
/**
|
|
6
|
+
* Resource-result projection keeps binary payloads out of model history.
|
|
7
|
+
*
|
|
8
|
+
* @module @qilin-agent/mcp-resources
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Render resource JSON while retaining raw binary data only for programmatic callers.
|
|
12
|
+
* @param server - configured server attribution.
|
|
13
|
+
* @param value - canonical resource result.
|
|
14
|
+
* @returns attributed text with binary payload descriptions.
|
|
15
|
+
*/
|
|
16
|
+
function renderResourceResult(server, value) {
|
|
17
|
+
return [{
|
|
18
|
+
type: "text",
|
|
19
|
+
text: `MCP server: ${server}\n${JSON.stringify(value, (key, item) => {
|
|
20
|
+
if (key === "blob" && typeof item === "string") return `[binary resource: ${item.length} base64 characters; available to programmatic callers]`;
|
|
21
|
+
return item;
|
|
22
|
+
})}`
|
|
23
|
+
}];
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region lib/types/tools.js
|
|
27
|
+
/**
|
|
28
|
+
* Three shared tools adapt model arguments to scoped resource operations.
|
|
29
|
+
*
|
|
30
|
+
* @module @qilin-agent/mcp-resources
|
|
31
|
+
*/
|
|
32
|
+
const listParameters = {
|
|
33
|
+
server: {
|
|
34
|
+
type: "string",
|
|
35
|
+
required: true,
|
|
36
|
+
description: "Configured MCP server name."
|
|
37
|
+
},
|
|
38
|
+
cursor: {
|
|
39
|
+
type: "string",
|
|
40
|
+
description: "Continuation cursor returned by this server."
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
const output = {
|
|
44
|
+
schema: { type: "json" },
|
|
45
|
+
render: (args, value) => renderResourceResult(args.server, value)
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Register resource operations in the consumer's tool scope.
|
|
49
|
+
* @param ctx - context owning the tool registrations.
|
|
50
|
+
* @param request - caller-aware resource operation.
|
|
51
|
+
* @returns the effect disposer that removes all three tools synchronously.
|
|
52
|
+
*/
|
|
53
|
+
function registerResourceTools(ctx, request) {
|
|
54
|
+
return ctx.effect(function* () {
|
|
55
|
+
yield ctx.tools.register(defineTool({
|
|
56
|
+
name: "list_mcp_resources",
|
|
57
|
+
description: "List resources available from an MCP server.",
|
|
58
|
+
parameters: listParameters,
|
|
59
|
+
output,
|
|
60
|
+
execute: (args, exec) => request(args.server, {
|
|
61
|
+
method: "resources/list",
|
|
62
|
+
...args.cursor === void 0 ? {} : { cursor: args.cursor }
|
|
63
|
+
}, exec)
|
|
64
|
+
}));
|
|
65
|
+
yield ctx.tools.register(defineTool({
|
|
66
|
+
name: "list_mcp_resource_templates",
|
|
67
|
+
description: "List parameterized resource URI templates from an MCP server.",
|
|
68
|
+
parameters: listParameters,
|
|
69
|
+
output,
|
|
70
|
+
execute: (args, exec) => request(args.server, {
|
|
71
|
+
method: "resources/templates/list",
|
|
72
|
+
...args.cursor === void 0 ? {} : { cursor: args.cursor }
|
|
73
|
+
}, exec)
|
|
74
|
+
}));
|
|
75
|
+
yield ctx.tools.register(defineTool({
|
|
76
|
+
name: "read_mcp_resource",
|
|
77
|
+
description: "Read an MCP resource by URI from the named server. Use a listed URI or an expanded resource template.",
|
|
78
|
+
parameters: {
|
|
79
|
+
server: listParameters.server,
|
|
80
|
+
uri: {
|
|
81
|
+
type: "string",
|
|
82
|
+
required: true,
|
|
83
|
+
description: "Resource URI to read."
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
output,
|
|
87
|
+
execute: (args, exec) => request(args.server, {
|
|
88
|
+
method: "resources/read",
|
|
89
|
+
uri: args.uri
|
|
90
|
+
}, exec)
|
|
91
|
+
}));
|
|
92
|
+
}, "mcpResources.resourceTools");
|
|
93
|
+
}
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region lib/types/index.js
|
|
96
|
+
/**
|
|
97
|
+
* Scoped MCP resource providers and the shared model-facing resource tools.
|
|
98
|
+
*
|
|
99
|
+
* @module @qilin-agent/mcp-resources
|
|
100
|
+
*/
|
|
101
|
+
var ResourceLayer = class {
|
|
102
|
+
servers = new NamedEntries((name) => /* @__PURE__ */ new Error(`MCP resource server "${name}" is already registered in this scope`));
|
|
103
|
+
disposeTools;
|
|
104
|
+
isEmpty() {
|
|
105
|
+
return this.servers.isEmpty();
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
/** Scoped resource access plus three tools shared by configured MCP servers. */
|
|
109
|
+
var McpResourceRuntime = class extends Service {
|
|
110
|
+
/** Tool registry required by the resource consumer. */
|
|
111
|
+
static inject = ["tools"];
|
|
112
|
+
layers = new ScopedLayers(() => new ResourceLayer(), () => void 0);
|
|
113
|
+
/** Shared tool registrations outlive any one server's registering context. */
|
|
114
|
+
selfCtx;
|
|
115
|
+
constructor(ctx) {
|
|
116
|
+
super(ctx, "mcpResources");
|
|
117
|
+
this.selfCtx = ctx;
|
|
118
|
+
ctx.inject(["systemPrompt"], (inner) => {
|
|
119
|
+
inner.systemPrompt.section({
|
|
120
|
+
name: "mcp-resource-servers",
|
|
121
|
+
order: inner.systemPrompt.getSectionOrder("MCP_SERVERS"),
|
|
122
|
+
interpolate: false,
|
|
123
|
+
text: ({ scope }) => {
|
|
124
|
+
const names = [...this.layers.merge(scope, (layer) => layer.servers).keys()].sort();
|
|
125
|
+
return names.length === 0 ? "" : `## MCP resource servers
|
|
126
|
+
|
|
127
|
+
Use list_mcp_resources, list_mcp_resource_templates, or read_mcp_resource with one of these names as the server argument: ${JSON.stringify(names)}.`;
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Register one server and expose resource tools while that scope has providers.
|
|
134
|
+
* @param server - configured server name, unique in this scope.
|
|
135
|
+
* @param provider - connection-owned resource operations.
|
|
136
|
+
* @returns the effect disposer for this exact registration.
|
|
137
|
+
*/
|
|
138
|
+
register(server, provider) {
|
|
139
|
+
const ctx = this.ctx;
|
|
140
|
+
const scope = scopeOf(ctx);
|
|
141
|
+
return ctx.effect(function* () {
|
|
142
|
+
let disposal;
|
|
143
|
+
yield () => disposal;
|
|
144
|
+
yield this.layers.effect(ctx, (layer) => {
|
|
145
|
+
const first = layer.servers.isEmpty();
|
|
146
|
+
const remove = layer.servers.insert(server, provider);
|
|
147
|
+
try {
|
|
148
|
+
if (first) layer.disposeTools = this.registerTools(scope);
|
|
149
|
+
} catch (error) {
|
|
150
|
+
remove();
|
|
151
|
+
throw error;
|
|
152
|
+
}
|
|
153
|
+
return () => {
|
|
154
|
+
remove();
|
|
155
|
+
if (layer.servers.isEmpty()) disposal = layer.disposeTools();
|
|
156
|
+
};
|
|
157
|
+
}, { label: `mcpResources.provider(${server})` });
|
|
158
|
+
}.bind(this), `mcpResources.register(${server})`);
|
|
159
|
+
}
|
|
160
|
+
/** Own one scope's tools independently of its configured server plugins. */
|
|
161
|
+
registerTools(scope) {
|
|
162
|
+
const ctx = this.selfCtx;
|
|
163
|
+
return ctx.effect(function* () {
|
|
164
|
+
let toolCtx = ctx;
|
|
165
|
+
if (scope !== void 0) {
|
|
166
|
+
const owned = createScope(ctx, scope);
|
|
167
|
+
yield owned.rawDispose;
|
|
168
|
+
toolCtx = owned.ctx;
|
|
169
|
+
}
|
|
170
|
+
yield registerResourceTools(toolCtx, (server, request, exec) => this.request(server, request, exec));
|
|
171
|
+
}.bind(this), "mcpResources.tools");
|
|
172
|
+
}
|
|
173
|
+
/** Resolve the caller-visible server before starting any network operation. */
|
|
174
|
+
request(server, request, exec) {
|
|
175
|
+
const provider = this.layers.merge(exec.agent, (layer) => layer.servers).get(server);
|
|
176
|
+
if (!provider) throw new Error(`MCP resource server "${server}" is unavailable in this agent's scope`);
|
|
177
|
+
return provider.request(request, exec);
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
//#endregion
|
|
181
|
+
export { McpResourceRuntime, McpResourceRuntime as default };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scoped MCP resource providers and the shared model-facing resource tools.
|
|
3
|
+
*
|
|
4
|
+
* @module @qilin-agent/mcp-resources
|
|
5
|
+
*/
|
|
6
|
+
import { Service, type Context } from '@qilin-agent/kylin';
|
|
7
|
+
import type { JsonValue } from '@qilin-agent/util-values';
|
|
8
|
+
import type { ToolExecution } from '@qilin-agent/tools';
|
|
9
|
+
declare module '@qilin-agent/kylin' {
|
|
10
|
+
interface Context {
|
|
11
|
+
mcpResources: McpResourceRuntime;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/** One supported resource operation, with server-owned cursors and URIs. */
|
|
15
|
+
export type McpResourceRequest = {
|
|
16
|
+
method: 'resources/list' | 'resources/templates/list';
|
|
17
|
+
cursor?: string;
|
|
18
|
+
} | {
|
|
19
|
+
method: 'resources/read';
|
|
20
|
+
uri: string;
|
|
21
|
+
};
|
|
22
|
+
/** One configured server's resource access, owned by its MCP connection plugin. */
|
|
23
|
+
export interface McpResourceProvider {
|
|
24
|
+
/**
|
|
25
|
+
* Run an operation against one live connection generation.
|
|
26
|
+
* @param request - MCP resource method and parameters.
|
|
27
|
+
* @param exec - caller identity and cancellation for this invocation.
|
|
28
|
+
* @returns the protocol result as lossless JSON.
|
|
29
|
+
*/
|
|
30
|
+
request(request: McpResourceRequest, exec: ToolExecution): Promise<JsonValue>;
|
|
31
|
+
}
|
|
32
|
+
/** Scoped resource access plus three tools shared by configured MCP servers. */
|
|
33
|
+
export declare class McpResourceRuntime extends Service {
|
|
34
|
+
/** Tool registry required by the resource consumer. */
|
|
35
|
+
static inject: string[];
|
|
36
|
+
private readonly layers;
|
|
37
|
+
/** Shared tool registrations outlive any one server's registering context. */
|
|
38
|
+
private readonly selfCtx;
|
|
39
|
+
constructor(ctx: Context);
|
|
40
|
+
/**
|
|
41
|
+
* Register one server and expose resource tools while that scope has providers.
|
|
42
|
+
* @param server - configured server name, unique in this scope.
|
|
43
|
+
* @param provider - connection-owned resource operations.
|
|
44
|
+
* @returns the effect disposer for this exact registration.
|
|
45
|
+
*/
|
|
46
|
+
register(server: string, provider: McpResourceProvider): () => void;
|
|
47
|
+
/** Own one scope's tools independently of its configured server plugins. */
|
|
48
|
+
private registerTools;
|
|
49
|
+
/** Resolve the caller-visible server before starting any network operation. */
|
|
50
|
+
private request;
|
|
51
|
+
}
|
|
52
|
+
export default McpResourceRuntime;
|
|
53
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource-result projection keeps binary payloads out of model history.
|
|
3
|
+
*
|
|
4
|
+
* @module @qilin-agent/mcp-resources
|
|
5
|
+
*/
|
|
6
|
+
import type { ContentBlock } from '@qilin-agent/llm';
|
|
7
|
+
import type { JsonValue } from '@qilin-agent/util-values';
|
|
8
|
+
/**
|
|
9
|
+
* Render resource JSON while retaining raw binary data only for programmatic callers.
|
|
10
|
+
* @param server - configured server attribution.
|
|
11
|
+
* @param value - canonical resource result.
|
|
12
|
+
* @returns attributed text with binary payload descriptions.
|
|
13
|
+
*/
|
|
14
|
+
export declare function renderResourceResult(server: string, value: JsonValue): ContentBlock[];
|
|
15
|
+
//# sourceMappingURL=render.d.ts.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Three shared tools adapt model arguments to scoped resource operations.
|
|
3
|
+
*
|
|
4
|
+
* @module @qilin-agent/mcp-resources
|
|
5
|
+
*/
|
|
6
|
+
import type { Context } from '@qilin-agent/kylin';
|
|
7
|
+
import { type ToolExecution } from '@qilin-agent/tools';
|
|
8
|
+
import type { JsonValue } from '@qilin-agent/util-values';
|
|
9
|
+
import type { McpResourceRequest } from './index.ts';
|
|
10
|
+
type RequestResource = (server: string, request: McpResourceRequest, exec: ToolExecution) => Promise<JsonValue>;
|
|
11
|
+
/**
|
|
12
|
+
* Register resource operations in the consumer's tool scope.
|
|
13
|
+
* @param ctx - context owning the tool registrations.
|
|
14
|
+
* @param request - caller-aware resource operation.
|
|
15
|
+
* @returns the effect disposer that removes all three tools synchronously.
|
|
16
|
+
*/
|
|
17
|
+
export declare function registerResourceTools(ctx: Context, request: RequestResource): () => void;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=tools.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,56 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qilin-agent/mcp-resources",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"description": "Scoped MCP resource discovery and reading through shared model tools",
|
|
4
|
+
"version": "3.1.4",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/kkutysllb/QiLin.git",
|
|
11
|
+
"directory": "packages/mcp/mcp-resources"
|
|
12
|
+
},
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": "^22.19.0 || >=24.0.0"
|
|
15
|
+
},
|
|
16
|
+
"type": "module",
|
|
17
|
+
"main": "lib/index.js",
|
|
18
|
+
"types": "lib/types/index.d.ts",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./lib/types/index.d.ts",
|
|
22
|
+
"default": "./lib/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./src/*": "./src/*",
|
|
25
|
+
"./package.json": "./package.json"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"lib/index.js",
|
|
29
|
+
"lib/types/**/*.d.ts"
|
|
30
|
+
],
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"@qilin-agent/kylin": "~4.0.3",
|
|
34
|
+
"@qilin-agent/llm": "3.1.4",
|
|
35
|
+
"@qilin-agent/scope": "3.1.4",
|
|
36
|
+
"@qilin-agent/tools": "3.1.4",
|
|
37
|
+
"@qilin-agent/system-prompt": "3.1.4"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@qilin-agent/kylin": "~4.0.3",
|
|
41
|
+
"@qilin-agent/llm": "3.1.4",
|
|
42
|
+
"@qilin-agent/ptc-runtime": "3.1.4",
|
|
43
|
+
"@qilin-agent/scope": "3.1.4",
|
|
44
|
+
"@qilin-agent/tools": "3.1.4",
|
|
45
|
+
"@qilin-agent/system-prompt": "3.1.4",
|
|
46
|
+
"@qilin-agent/agent": "3.1.4"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"@qilin-agent/util-values": "3.1.4"
|
|
50
|
+
},
|
|
51
|
+
"peerDependenciesMeta": {
|
|
52
|
+
"@qilin-agent/system-prompt": {
|
|
53
|
+
"optional": true
|
|
54
|
+
}
|
|
55
|
+
}
|
|
6
56
|
}
|