kloudy-mcp 0.1.10 → 0.1.11
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 +15 -3
- package/dist/kloudy-mcp/src/cli.js +7 -4
- package/dist/kloudy-mcp/src/cli.js.map +1 -1
- package/dist/kloudy-mcp/src/clients.js +6 -2
- package/dist/kloudy-mcp/src/clients.js.map +1 -1
- package/dist/kloudy-mcp/src/http-auth.d.ts +0 -2
- package/dist/kloudy-mcp/src/http-auth.js +0 -24
- package/dist/kloudy-mcp/src/http-auth.js.map +1 -1
- package/dist/kloudy-mcp/src/http-config.d.ts +0 -1
- package/dist/kloudy-mcp/src/http-config.js +0 -4
- package/dist/kloudy-mcp/src/http-config.js.map +1 -1
- package/dist/kloudy-mcp/src/http-server.js +18 -23
- package/dist/kloudy-mcp/src/http-server.js.map +1 -1
- package/dist/kloudy-mcp/src/mcp-server.d.ts +1 -1
- package/dist/kloudy-mcp/src/mcp-server.js +2 -2
- package/dist/kloudy-mcp/src/mcp-server.js.map +1 -1
- package/dist/kloudy-mcp/src/version.d.ts +1 -1
- package/dist/kloudy-mcp/src/version.js +1 -1
- package/dist/shared/src/anonymous-device-store.d.ts +6 -0
- package/dist/shared/src/anonymous-device-store.js +66 -0
- package/dist/shared/src/anonymous-device-store.js.map +1 -0
- package/dist/shared/src/api-x/client.d.ts +35 -6
- package/dist/shared/src/api-x/client.js +223 -21
- package/dist/shared/src/api-x/client.js.map +1 -1
- package/dist/shared/src/api-x/music-projections.d.ts +137 -0
- package/dist/shared/src/api-x/music-projections.js +27 -0
- package/dist/shared/src/api-x/music-projections.js.map +1 -0
- package/dist/shared/src/api-x/projections.d.ts +1 -5
- package/dist/shared/src/api-x/projections.js +25 -82
- package/dist/shared/src/api-x/projections.js.map +1 -1
- package/dist/shared/src/api-x/types.d.ts +75 -36
- package/dist/shared/src/capabilities/archive-documents.d.ts +3 -0
- package/dist/shared/src/capabilities/archive-documents.js +99 -0
- package/dist/shared/src/capabilities/archive-documents.js.map +1 -0
- package/dist/shared/src/capabilities/archive.js +69 -29
- package/dist/shared/src/capabilities/archive.js.map +1 -1
- package/dist/shared/src/capabilities/catalog.d.ts +89 -4
- package/dist/shared/src/capabilities/catalog.js +55 -9
- package/dist/shared/src/capabilities/catalog.js.map +1 -1
- package/dist/shared/src/capabilities/character-contributions.d.ts +3 -0
- package/dist/shared/src/capabilities/character-contributions.js +41 -0
- package/dist/shared/src/capabilities/character-contributions.js.map +1 -0
- package/dist/shared/src/capabilities/content-metadata.d.ts +349 -0
- package/dist/shared/src/capabilities/content-metadata.js +45 -0
- package/dist/shared/src/capabilities/content-metadata.js.map +1 -0
- package/dist/shared/src/capabilities/instructions.js +1 -1
- package/dist/shared/src/capabilities/instructions.js.map +1 -1
- package/dist/shared/src/capabilities/registry.d.ts +3 -1
- package/dist/shared/src/capabilities/registry.js +16 -5
- package/dist/shared/src/capabilities/registry.js.map +1 -1
- package/dist/shared/src/capabilities/resource-facts.d.ts +166 -0
- package/dist/shared/src/capabilities/resource-facts.js +72 -0
- package/dist/shared/src/capabilities/resource-facts.js.map +1 -0
- package/dist/shared/src/capabilities/shared.d.ts +0 -1
- package/dist/shared/src/capabilities/shared.js +0 -6
- package/dist/shared/src/capabilities/shared.js.map +1 -1
- package/dist/shared/src/knowledge/client.d.ts +2 -1
- package/dist/shared/src/knowledge/client.js +5 -1
- package/dist/shared/src/knowledge/client.js.map +1 -1
- package/dist/shared/src/local-access.d.ts +6 -0
- package/dist/shared/src/local-access.js +9 -0
- package/dist/shared/src/local-access.js.map +1 -0
- package/dist/shared/src/state-store.d.ts +8 -2
- package/dist/shared/src/state-store.js +10 -1
- package/dist/shared/src/state-store.js.map +1 -1
- package/docs/http-deployment.md +20 -21
- package/docs/http-mcp.md +23 -11
- package/docs/local-mcp.md +56 -23
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ npx -y kloudy-mcp --version
|
|
|
18
18
|
npx -y kloudy-mcp serve
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
当前工作区支持可选登录(尚未发布):公开只读工具无需登录;个人资产、草稿、写操作和语义检索需要通过浏览器 OAuth 登录并选择固定的 Agent Character,随后重新连接本地 MCP:
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
24
|
npx -y kloudy-mcp login
|
|
@@ -36,7 +36,7 @@ npx -y kloudy-mcp logout
|
|
|
36
36
|
codex mcp add kloudy -- npx -y kloudy-mcp serve
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
`serve`、`login` 和 `logout` 面向本地单用户客户端。Kloudy 自有 Agent 的生产主路径是常驻 `serve-http`
|
|
39
|
+
`serve`、`login` 和 `logout` 面向本地单用户客户端。Kloudy 自有 Agent 的生产主路径是常驻 `serve-http` 的公开 `/mcp`:已授权请求携带绑定单个 Agent Character 的标准 OAuth Bearer,匿名请求省略 Authorization。`serve-request` 保留为每 Run 独立进程的诊断和显式回滚路径。三种入口调用同一个工具注册和 Schema,因此新增能力只需在 MCP 契约中实现一次,是否向模型开放仍由各 Agent 的工具政策决定。
|
|
40
40
|
|
|
41
41
|
远程服务使用:
|
|
42
42
|
|
|
@@ -44,8 +44,20 @@ codex mcp add kloudy -- npx -y kloudy-mcp serve
|
|
|
44
44
|
kloudy-mcp serve-http
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
`serve-http`
|
|
47
|
+
`serve-http` 提供统一的 `/mcp`、路径型 OAuth Protected Resource Metadata 和本机健康接口。它不读取本地登录文件;无 Authorization 仅开放匿名公开只读工具,有 Authorization 必须通过 OAuth 校验,Token 限制在当前请求内存中。协议、身份和全部配置项见 [Streamable HTTP 说明](docs/http-mcp.md);使用仅依赖正式 npm 包的最小项目部署到 Linux,见 [HTTP MCP 独立项目部署](docs/http-deployment.md)。
|
|
48
48
|
|
|
49
49
|
默认连接线上 API-X `https://shape.kloudy.cn/api-x`、网页 `https://shape.kloudy.cn` 和 Resource `https://shape.kloudy.cn/mcp`。可通过 `KLOUDY_API_X_BASE_URL`、`KLOUDY_WEB_BASE_URL` 和 `KLOUDY_MCP_OAUTH_RESOURCE_URL` 显式配置本地客户端的服务、网页和 OAuth Resource 地址;HTTP MCP 服务另用 `KLOUDY_MCP_PUBLIC_URL` 配置自身 Resource。
|
|
50
50
|
|
|
51
51
|
`wiki_semantic_search` 需要登录,通过 API-X `/agent/knowledge/wiki/semantic-search` 返回索引版本、Wiki 证据片段和来源 URL;最终知识回答由 MCP 客户端根据证据生成,证据不足时应明确拒答。账号私有读取和写入工具也需要登录。Community 评论会立即公开发布,但只能删除当前 Agent Character 自己发布的评论;Blog 工具只能操作草稿;Archive 和 Wiki 投稿需要管理员审核后才会发布。
|
|
52
|
+
|
|
53
|
+
### 公共角色投稿
|
|
54
|
+
|
|
55
|
+
当前源码新增 9 个 `character_contribution_*` 工具,支持四类公共资料角色的新建、修改及草稿审核流程;与 CLI 共用能力定义。需授权 Agent,不能投稿身份角色,也不能直接发布。详见 [角色投稿参数与流程](docs/local-mcp.md#公共资料角色投稿本地源码尚未发布)。尚未发布,需配套新版 API-X。
|
|
56
|
+
|
|
57
|
+
## 新增图鉴类型投稿
|
|
58
|
+
|
|
59
|
+
共享 `archive_search`、`archive_get` 和 `archive_contribution_*` 已支持产品、图书、美术、地点的新建与编辑投稿。提交进入审核,不直接发布。参数和示例见[图鉴投稿说明](../../docs/archive-contributions.md)。
|
|
60
|
+
|
|
61
|
+
歌曲/音频查询、播放来源属性和创作者关系投稿:见[共享能力说明](../../docs/music-resource-facts.md)。新增能力位于当前源码,正式安装版本以 npm 发布为准。
|
|
62
|
+
|
|
63
|
+
图鉴详情与公开 Character 主页的介绍文档、子文档可通过 `archive_document_*` 工具读取和投稿;提交只进入管理员审核。参数、文档树约束和删除语义见[图鉴与角色介绍文档投稿](../../docs/archive-document-contributions.md)。
|
|
@@ -8,6 +8,7 @@ import { FileStateStore, takeRequestIdentity } from '../../shared/src/state-stor
|
|
|
8
8
|
import { loginWithBrowser } from '../../shared/src/browser-login.js';
|
|
9
9
|
import { getVersionCommandOutput, KLOUDY_MCP_VERSION } from './version.js';
|
|
10
10
|
import { createClients } from './clients.js';
|
|
11
|
+
import { selectLocalAccess } from '../../shared/src/local-access.js';
|
|
11
12
|
import { loadHttpServerConfig } from './http-config.js';
|
|
12
13
|
import { installHttpServerShutdown, startHttpServer } from './http-server.js';
|
|
13
14
|
async function main() {
|
|
@@ -22,16 +23,18 @@ async function main() {
|
|
|
22
23
|
if (args.length > 0)
|
|
23
24
|
throw new Error('serve does not accept arguments');
|
|
24
25
|
const config = loadConfig();
|
|
25
|
-
const
|
|
26
|
-
const
|
|
26
|
+
const access = await selectLocalAccess(new FileStateStore(config.stateDirectory));
|
|
27
|
+
const { api, knowledge } = createClients(access.store, 'local-mcp');
|
|
28
|
+
const server = createMcpServer(api, knowledge, access.anonymous);
|
|
27
29
|
await server.connect(new StdioServerTransport());
|
|
28
30
|
return;
|
|
29
31
|
}
|
|
30
32
|
case 'serve-request': {
|
|
31
33
|
if (args.length > 0)
|
|
32
34
|
throw new Error('serve-request does not accept arguments');
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
+
const state = takeRequestIdentity();
|
|
36
|
+
const { api, knowledge } = createClients(state, 'agent-request-mcp');
|
|
37
|
+
const server = createMcpServer(api, knowledge, (await state.read()).anonymous === true);
|
|
35
38
|
await server.connect(new StdioServerTransport());
|
|
36
39
|
return;
|
|
37
40
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtF,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAE9E,KAAK,UAAU,IAAI;IACjB,MAAM,CAAC,OAAO,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC1D,MAAM,aAAa,GAAG,uBAAuB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC7D,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;QAChC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAC5B,OAAO;IACT,CAAC;IAED,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;YACxE,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;YAC5B,MAAM,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,16 @@
|
|
|
1
|
+
import { AnonymousDeviceStore } from '../../shared/src/anonymous-device-store.js';
|
|
1
2
|
import { KnowledgeApiClient } from '../../shared/src/knowledge/client.js';
|
|
2
3
|
import { ApiXClient } from '../../shared/src/api-x/client.js';
|
|
3
4
|
import { loadConfig } from '../../shared/src/config.js';
|
|
4
5
|
import { KLOUDY_MCP_VERSION } from './version.js';
|
|
5
6
|
export function createClients(stateStore, clientKind, config = loadConfig()) {
|
|
6
7
|
const userAgent = `kloudy-mcp/${KLOUDY_MCP_VERSION}`;
|
|
8
|
+
const api = new ApiXClient(config, stateStore, fetch, userAgent, clientKind, clientKind === 'remote-http-mcp'
|
|
9
|
+
? { getOrCreate: async () => 'kloudy-mcp-server' }
|
|
10
|
+
: clientKind === 'local-mcp' ? new AnonymousDeviceStore(config.stateDirectory) : undefined);
|
|
7
11
|
return {
|
|
8
|
-
api
|
|
9
|
-
knowledge: new KnowledgeApiClient(config, stateStore, fetch, userAgent, clientKind),
|
|
12
|
+
api,
|
|
13
|
+
knowledge: new KnowledgeApiClient(config, stateStore, fetch, userAgent, clientKind, () => api.requestDeviceId()),
|
|
10
14
|
};
|
|
11
15
|
}
|
|
12
16
|
//# sourceMappingURL=clients.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clients.js","sourceRoot":"","sources":["../../../src/clients.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAkB,MAAM,4BAA4B,CAAC;AAExE,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,UAAU,aAAa,CAC3B,UAAsB,EACtB,UAAkB,EAClB,SAAoB,UAAU,EAAE;IAEhC,MAAM,SAAS,GAAG,cAAc,kBAAkB,EAAE,CAAC;IACrD,
|
|
1
|
+
{"version":3,"file":"clients.js","sourceRoot":"","sources":["../../../src/clients.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,4CAA4C,CAAC;AAClF,OAAO,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAkB,MAAM,4BAA4B,CAAC;AAExE,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,UAAU,aAAa,CAC3B,UAAsB,EACtB,UAAkB,EAClB,SAAoB,UAAU,EAAE;IAEhC,MAAM,SAAS,GAAG,cAAc,kBAAkB,EAAE,CAAC;IACrD,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EACzE,UAAU,KAAK,iBAAiB;QAC9B,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,IAAI,EAAE,CAAC,mBAAmB,EAAE;QAClD,CAAC,CAAC,UAAU,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,oBAAoB,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAChG,OAAO;QACL,GAAG;QACH,SAAS,EAAE,IAAI,kBAAkB,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC;KACjH,CAAC;AACJ,CAAC"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { IncomingHttpHeaders } from 'node:http';
|
|
2
1
|
import type { AuthInfo } from '@modelcontextprotocol/sdk/server/auth/types.js';
|
|
3
2
|
import type { OAuthTokenVerifier } from '@modelcontextprotocol/sdk/server/auth/provider.js';
|
|
4
3
|
import { RequestStateStore } from '../../shared/src/state-store.js';
|
|
@@ -10,4 +9,3 @@ export declare class HttpAuthContextVerifier implements OAuthTokenVerifier {
|
|
|
10
9
|
verifyAccessToken(token: string): Promise<AuthInfo>;
|
|
11
10
|
}
|
|
12
11
|
export declare function requestStateFromAuthInfo(authInfo: AuthInfo | undefined): RequestStateStore;
|
|
13
|
-
export declare function requestStateFromInternalHeaders(headers: IncomingHttpHeaders, expectedServiceToken: string | null): RequestStateStore;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { InvalidTokenError, ServerError } from '@modelcontextprotocol/sdk/server/auth/errors.js';
|
|
2
|
-
import { timingSafeEqual } from 'node:crypto';
|
|
3
2
|
import { z } from 'zod';
|
|
4
3
|
import { RequestStateStore } from '../../shared/src/state-store.js';
|
|
5
4
|
const bearerTokenSchema = z.string().min(1).max(8192).regex(/^[\x21-\x7e]+$/);
|
|
@@ -90,29 +89,6 @@ export function requestStateFromAuthInfo(authInfo) {
|
|
|
90
89
|
throw invalidToken();
|
|
91
90
|
}
|
|
92
91
|
}
|
|
93
|
-
export function requestStateFromInternalHeaders(headers, expectedServiceToken) {
|
|
94
|
-
const authorization = singleHeader(headers.authorization);
|
|
95
|
-
const prefix = 'Bearer ';
|
|
96
|
-
const presented = authorization?.startsWith(prefix) ? authorization.slice(prefix.length) : '';
|
|
97
|
-
if (!expectedServiceToken || !safeEqual(presented, expectedServiceToken))
|
|
98
|
-
throw invalidToken();
|
|
99
|
-
try {
|
|
100
|
-
return new RequestStateStore({
|
|
101
|
-
accessToken: singleHeader(headers['k-oauth-access-token']) ?? '',
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
catch {
|
|
105
|
-
throw invalidToken();
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
function singleHeader(value) {
|
|
109
|
-
return typeof value === 'string' ? value : undefined;
|
|
110
|
-
}
|
|
111
|
-
function safeEqual(left, right) {
|
|
112
|
-
const leftBuffer = Buffer.from(left);
|
|
113
|
-
const rightBuffer = Buffer.from(right);
|
|
114
|
-
return leftBuffer.length === rightBuffer.length && timingSafeEqual(leftBuffer, rightBuffer);
|
|
115
|
-
}
|
|
116
92
|
function invalidToken() {
|
|
117
93
|
return new InvalidTokenError('Access token is invalid or expired');
|
|
118
94
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-auth.js","sourceRoot":"","sources":["../../../src/http-auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,iDAAiD,CAAC;
|
|
1
|
+
{"version":3,"file":"http-auth.js","sourceRoot":"","sources":["../../../src/http-auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -25,9 +25,6 @@ export function loadHttpServerConfig(env = process.env) {
|
|
|
25
25
|
throw new Error('KLOUDY_MCP_AUTH_CONTEXT_URL must not contain query or hash');
|
|
26
26
|
}
|
|
27
27
|
const authContextServiceToken = parseSecret(env.KLOUDY_MCP_AUTH_CONTEXT_SERVICE_TOKEN, 'KLOUDY_MCP_AUTH_CONTEXT_SERVICE_TOKEN');
|
|
28
|
-
const internalServiceToken = env.KLOUDY_MCP_INTERNAL_SERVICE_TOKEN
|
|
29
|
-
? parseSecret(env.KLOUDY_MCP_INTERNAL_SERVICE_TOKEN, 'KLOUDY_MCP_INTERNAL_SERVICE_TOKEN')
|
|
30
|
-
: null;
|
|
31
28
|
const authTimeoutMs = parseTimeout(env.KLOUDY_MCP_AUTH_TIMEOUT_MS);
|
|
32
29
|
const requiredScopes = parseScopes(env.KLOUDY_MCP_REQUIRED_SCOPES);
|
|
33
30
|
const allowedHosts = unique([
|
|
@@ -43,7 +40,6 @@ export function loadHttpServerConfig(env = process.env) {
|
|
|
43
40
|
authorizationServerUrl,
|
|
44
41
|
authContextUrl,
|
|
45
42
|
authContextServiceToken,
|
|
46
|
-
internalServiceToken,
|
|
47
43
|
authTimeoutMs,
|
|
48
44
|
requiredScopes,
|
|
49
45
|
allowedHosts,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-config.js","sourceRoot":"","sources":["../../../src/http-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,iBAAiB,GAAG,WAAW,CAAC;AACtC,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAChC,MAAM,kBAAkB,GAAG,UAAU,iBAAiB,IAAI,iBAAiB,MAAM,CAAC;AAClF,MAAM,cAAc,GAAG,CAAC,WAAW,CAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"http-config.js","sourceRoot":"","sources":["../../../src/http-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,7 +3,8 @@ import { requireBearerAuth } from '@modelcontextprotocol/sdk/server/auth/middlew
|
|
|
3
3
|
import { getOAuthProtectedResourceMetadataUrl } from '@modelcontextprotocol/sdk/server/auth/router.js';
|
|
4
4
|
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
5
5
|
import { createClients } from './clients.js';
|
|
6
|
-
import {
|
|
6
|
+
import { RequestStateStore } from '../../shared/src/state-store.js';
|
|
7
|
+
import { HttpAuthContextVerifier, requestStateFromAuthInfo, } from './http-auth.js';
|
|
7
8
|
import { createMcpServer } from './mcp-server.js';
|
|
8
9
|
import { KLOUDY_MCP_VERSION } from './version.js';
|
|
9
10
|
export function createHttpApp(config, dependencies = {}) {
|
|
@@ -23,7 +24,7 @@ export function createHttpApp(config, dependencies = {}) {
|
|
|
23
24
|
status: 'ready',
|
|
24
25
|
resource: config.publicUrl.href,
|
|
25
26
|
version: KLOUDY_MCP_VERSION,
|
|
26
|
-
|
|
27
|
+
anonymousToolsEnabled: true,
|
|
27
28
|
});
|
|
28
29
|
});
|
|
29
30
|
app.get(new URL(resourceMetadataUrl).pathname, (_request, response) => {
|
|
@@ -33,11 +34,12 @@ export function createHttpApp(config, dependencies = {}) {
|
|
|
33
34
|
scopes_supported: config.requiredScopes,
|
|
34
35
|
bearer_methods_supported: ['header'],
|
|
35
36
|
resource_name: 'Kloudy MCP',
|
|
37
|
+
kloudy_version: KLOUDY_MCP_VERSION,
|
|
36
38
|
});
|
|
37
39
|
});
|
|
38
|
-
const handleMcp = async (request, response, stateStore
|
|
39
|
-
const { api, knowledge } = createClients(stateStore,
|
|
40
|
-
const server = createMcpServer(api, knowledge);
|
|
40
|
+
const handleMcp = async (request, response, stateStore) => {
|
|
41
|
+
const { api, knowledge } = createClients(stateStore, 'remote-http-mcp');
|
|
42
|
+
const server = createMcpServer(api, knowledge, (await stateStore.read()).anonymous === true);
|
|
41
43
|
const transport = new StreamableHTTPServerTransport();
|
|
42
44
|
let closed = false;
|
|
43
45
|
const close = async () => {
|
|
@@ -68,26 +70,19 @@ export function createHttpApp(config, dependencies = {}) {
|
|
|
68
70
|
await close();
|
|
69
71
|
}
|
|
70
72
|
};
|
|
71
|
-
app.post('/mcp',
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
jsonrpc: '2.0',
|
|
82
|
-
error: { code: -32001, message: 'Unauthorized' },
|
|
83
|
-
id: null,
|
|
84
|
-
});
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
await handleMcp(request, response, stateStore, 'agent-internal-http-mcp');
|
|
73
|
+
app.post('/mcp', (request, response, next) => {
|
|
74
|
+
// 只有完全没有 Authorization 才是匿名;提供的无效凭据必须失败关闭。
|
|
75
|
+
if (request.headers.authorization === undefined)
|
|
76
|
+
return next();
|
|
77
|
+
return requireAuth(request, response, next);
|
|
78
|
+
}, async (request, response) => {
|
|
79
|
+
const stateStore = request.headers.authorization === undefined
|
|
80
|
+
? new RequestStateStore({ anonymous: true })
|
|
81
|
+
: requestStateFromAuthInfo(request.auth);
|
|
82
|
+
await handleMcp(request, response, stateStore);
|
|
88
83
|
});
|
|
89
84
|
for (const method of ['get', 'delete']) {
|
|
90
|
-
for (const path of ['/mcp'
|
|
85
|
+
for (const path of ['/mcp']) {
|
|
91
86
|
app[method](path, (_request, response) => {
|
|
92
87
|
response.status(405).json({
|
|
93
88
|
jsonrpc: '2.0',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-server.js","sourceRoot":"","sources":["../../../src/http-server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,6CAA6C,CAAC;AAClF,OAAO,EAAE,iBAAiB,EAAE,MAAM,gEAAgE,CAAC;AACnG,OAAO,EAAE,oCAAoC,EAAE,MAAM,iDAAiD,CAAC;AAEvG,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AAGnG,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EACL,uBAAuB,EACvB,wBAAwB,
|
|
1
|
+
{"version":3,"file":"http-server.js","sourceRoot":"","sources":["../../../src/http-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
2
|
import type { WikiSemanticApi } from '../../shared/src/knowledge/types.js';
|
|
3
3
|
import type { KloudyApi } from '../../shared/src/api-x/types.js';
|
|
4
|
-
export declare function createMcpServer(api: KloudyApi, wikiSemantic: WikiSemanticApi): McpServer;
|
|
4
|
+
export declare function createMcpServer(api: KloudyApi, wikiSemantic: WikiSemanticApi, anonymous?: boolean): McpServer;
|
|
@@ -3,11 +3,11 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
3
3
|
import { createCapabilityRegistry } from '../../shared/src/capabilities/registry.js';
|
|
4
4
|
import { registerCapabilityTools } from './capability-adapter.js';
|
|
5
5
|
import { KLOUDY_MCP_VERSION } from './version.js';
|
|
6
|
-
export function createMcpServer(api, wikiSemantic) {
|
|
6
|
+
export function createMcpServer(api, wikiSemantic, anonymous = false) {
|
|
7
7
|
const server = new McpServer({ name: 'kloudy-mcp', version: KLOUDY_MCP_VERSION }, {
|
|
8
8
|
instructions: KLOUDY_CAPABILITY_INSTRUCTIONS,
|
|
9
9
|
});
|
|
10
|
-
registerCapabilityTools(server, createCapabilityRegistry(api, wikiSemantic));
|
|
10
|
+
registerCapabilityTools(server, createCapabilityRegistry(api, wikiSemantic, anonymous));
|
|
11
11
|
return server;
|
|
12
12
|
}
|
|
13
13
|
//# sourceMappingURL=mcp-server.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../../../src/mcp-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,8BAA8B,EAAE,MAAM,+CAA+C,CAAC;AAC/F,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGpE,OAAO,EAAE,wBAAwB,EAAE,MAAM,2CAA2C,CAAC;AACrF,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,UAAU,eAAe,CAAC,GAAc,EAAE,YAA6B;
|
|
1
|
+
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../../../src/mcp-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,8BAA8B,EAAE,MAAM,+CAA+C,CAAC;AAC/F,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGpE,OAAO,EAAE,wBAAwB,EAAE,MAAM,2CAA2C,CAAC;AACrF,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,UAAU,eAAe,CAAC,GAAc,EAAE,YAA6B,EAAE,SAAS,GAAG,KAAK;IAC9F,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,kBAAkB,EAAE,EACnD;QACE,YAAY,EAAE,8BAA8B;KAC7C,CACF,CAAC;IAEF,uBAAuB,CAAC,MAAM,EAAE,wBAAwB,CAAC,GAAG,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC,CAAC;IACxF,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const KLOUDY_MCP_VERSION = "0.1.
|
|
1
|
+
export declare const KLOUDY_MCP_VERSION = "0.1.11";
|
|
2
2
|
export declare function getVersionCommandOutput(command: string, args: string[]): string | undefined;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
2
|
+
import { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { setTimeout } from 'node:timers/promises';
|
|
5
|
+
/** 独立于 OAuth 状态的本地访客设备;按 API-X 地址隔离。 */
|
|
6
|
+
export class AnonymousDeviceStore {
|
|
7
|
+
directory;
|
|
8
|
+
constructor(directory) {
|
|
9
|
+
this.directory = directory;
|
|
10
|
+
}
|
|
11
|
+
async getOrCreate(apiUrl, register) {
|
|
12
|
+
const key = createHash('sha256').update(apiUrl).digest('hex');
|
|
13
|
+
const directory = join(this.directory, 'anonymous-devices');
|
|
14
|
+
const path = join(directory, `${key}.json`);
|
|
15
|
+
const read = async () => {
|
|
16
|
+
try {
|
|
17
|
+
const value = JSON.parse(await readFile(path, 'utf8'));
|
|
18
|
+
if (typeof value.deviceId !== 'string' || !value.deviceId.trim())
|
|
19
|
+
throw new Error('Invalid anonymous device cache');
|
|
20
|
+
return value.deviceId;
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
if (error.code === 'ENOENT')
|
|
24
|
+
return undefined;
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
const saved = await read();
|
|
29
|
+
if (saved)
|
|
30
|
+
return saved;
|
|
31
|
+
await mkdir(directory, { recursive: true, mode: 0o700 });
|
|
32
|
+
const lock = `${path}.lock`;
|
|
33
|
+
const deadline = Date.now() + 15_000;
|
|
34
|
+
for (;;) {
|
|
35
|
+
try {
|
|
36
|
+
await mkdir(lock, { mode: 0o700 });
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
if (error.code !== 'EEXIST')
|
|
41
|
+
throw error;
|
|
42
|
+
const saved = await read();
|
|
43
|
+
if (saved)
|
|
44
|
+
return saved;
|
|
45
|
+
if (Date.now() >= deadline)
|
|
46
|
+
throw new Error('Anonymous device cache is locked; remove the stale .lock directory after confirming no registration is running');
|
|
47
|
+
await setTimeout(50);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const temporary = `${path}.${randomUUID()}.tmp`;
|
|
51
|
+
try {
|
|
52
|
+
const saved = await read();
|
|
53
|
+
if (saved)
|
|
54
|
+
return saved;
|
|
55
|
+
const deviceId = await register();
|
|
56
|
+
await writeFile(temporary, JSON.stringify({ deviceId }) + '\n', { mode: 0o600, flag: 'wx' });
|
|
57
|
+
await rename(temporary, path);
|
|
58
|
+
return deviceId;
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
await rm(temporary, { force: true });
|
|
62
|
+
await rm(lock, { recursive: true, force: true });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=anonymous-device-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anonymous-device-store.js","sourceRoot":"","sources":["../../../../shared/src/anonymous-device-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import type { FactKind, FactAction, FactCreate, FactWrite, FactQuery } from '../capabilities/resource-facts.js';
|
|
2
|
+
import type { AnonymousDeviceStore } from '../anonymous-device-store.js';
|
|
1
3
|
import type { AppConfig } from '../config.js';
|
|
2
4
|
import type { StateStore } from '../state-store.js';
|
|
3
|
-
import type { ArchiveContributionCreateInput, ArchiveContributionListInput, ArchiveContributionResourceType, ArchiveContributionWriteInput, ArchiveResourceType, ArchiveSearchInput, AssetListInput, BlogListInput, BlogDraftCreateInput, CharacterSearchInput, CommunityCommentCreateInput, DocumentDirectoryInput, DocumentReadInput, KloudyApi, SearchInput, WikiContributionWriteInput } from './types.js';
|
|
5
|
+
import type { CharacterContributionCreateInput, CharacterContributionWriteInput, CharacterContributionListInput, ArchiveDocumentContributionCreateInput, ArchiveDocumentContributionListInput, ArchiveDocumentProposedInput, ArchiveDocumentTarget, ArchiveContributionCreateInput, ArchiveContributionListInput, ArchiveContributionResourceType, ArchiveContributionWriteInput, ArchiveResourceType, ArchiveSearchInput, AssetListInput, BlogListInput, BlogDraftCreateInput, CharacterSearchInput, CommunityCommentCreateInput, DocumentDirectoryInput, DocumentReadInput, KloudyApi, SearchInput, WikiContributionWriteInput } from './types.js';
|
|
4
6
|
export declare class ApiXError extends Error {
|
|
5
7
|
readonly code: string;
|
|
6
8
|
readonly retryable: boolean;
|
|
@@ -15,7 +17,8 @@ export declare class ApiXClient implements KloudyApi {
|
|
|
15
17
|
private readonly fetchImpl;
|
|
16
18
|
private readonly clientIdentity;
|
|
17
19
|
private readonly clientKind;
|
|
18
|
-
|
|
20
|
+
private readonly anonymousDeviceStore?;
|
|
21
|
+
constructor(config: AppConfig, stateStore: StateStore, fetchImpl?: typeof fetch, clientIdentity?: string, clientKind?: string, anonymousDeviceStore?: Pick<AnonymousDeviceStore, "getOrCreate"> | undefined);
|
|
19
22
|
hasSession(): Promise<boolean>;
|
|
20
23
|
registerOAuthClient(redirectUri: string): Promise<string>;
|
|
21
24
|
exchangeAgentAuthorization(clientId: string, code: string, codeVerifier: string, redirectUri: string): Promise<LoginResult>;
|
|
@@ -62,14 +65,26 @@ export declare class ApiXClient implements KloudyApi {
|
|
|
62
65
|
listCommunityMessages(input: SearchInput, runId: string): Promise<import("./types.js").SearchResult<import("./types.js").CommunityMessage>>;
|
|
63
66
|
createCommunityComment(input: CommunityCommentCreateInput, runId: string): Promise<import("./types.js").CommunityCommentCreateResult>;
|
|
64
67
|
deleteCommunityComment(commentSn: string, runId: string): Promise<boolean>;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
68
|
+
listFactDefinitions(kind: FactKind, input: SearchInput, runId: string): Promise<unknown>;
|
|
69
|
+
listResourceFacts(kind: FactKind, input: FactQuery, runId: string): Promise<unknown>;
|
|
70
|
+
createFactContribution(kind: FactKind, input: FactCreate, runId: string): Promise<unknown>;
|
|
71
|
+
updateFactContribution(kind: FactKind, draftSn: string, input: FactWrite, runId: string): Promise<unknown>;
|
|
72
|
+
factContributionAction(kind: FactKind, action: FactAction, draftSn: string, runId: string): Promise<unknown>;
|
|
69
73
|
searchArchive(input: ArchiveSearchInput, runId: string): Promise<import("./types.js").SearchResult<import("./types.js").ArchiveItem>>;
|
|
74
|
+
listSongAudios(songId: string, input: SearchInput, runId: string): Promise<import("./types.js").SearchResult<import("./types.js").ArchiveItem>>;
|
|
75
|
+
getAudioBySn(audioSn: string, runId: string): Promise<import("./types.js").ArchiveItem>;
|
|
70
76
|
getArchiveItem(resourceType: ArchiveResourceType, itemId: string, runId: string): Promise<import("./types.js").ArchiveItem>;
|
|
71
77
|
searchWiki(input: SearchInput, runId: string): Promise<unknown>;
|
|
72
78
|
getWiki(entryId: string, runId: string): Promise<unknown>;
|
|
79
|
+
createCharacterContribution(input: CharacterContributionCreateInput, runId: string): Promise<unknown>;
|
|
80
|
+
updateCharacterContribution(characterId: string, input: CharacterContributionWriteInput, runId: string): Promise<unknown>;
|
|
81
|
+
deleteCharacterContribution(characterId: string, runId: string): Promise<unknown>;
|
|
82
|
+
submitCharacterContribution(characterId: string, runId: string): Promise<unknown>;
|
|
83
|
+
withdrawCharacterContribution(characterId: string, runId: string): Promise<unknown>;
|
|
84
|
+
reopenCharacterContribution(characterId: string, runId: string): Promise<unknown>;
|
|
85
|
+
getCharacterContribution(characterId: string, runId: string): Promise<unknown>;
|
|
86
|
+
listCharacterContributions(input: CharacterContributionListInput, runId: string): Promise<unknown>;
|
|
87
|
+
getCharacterContributionHistory(draftSn: string, runId: string): Promise<unknown>;
|
|
73
88
|
createArchiveContribution(input: ArchiveContributionCreateInput, runId: string): Promise<unknown>;
|
|
74
89
|
updateArchiveContribution(resourceType: ArchiveContributionResourceType, resourceId: string, input: ArchiveContributionWriteInput, runId: string): Promise<unknown>;
|
|
75
90
|
deleteArchiveContribution(resourceType: ArchiveContributionResourceType, resourceId: string, runId: string): Promise<unknown>;
|
|
@@ -79,6 +94,17 @@ export declare class ApiXClient implements KloudyApi {
|
|
|
79
94
|
getArchiveContribution(resourceType: ArchiveContributionResourceType, resourceId: string, runId: string): Promise<unknown>;
|
|
80
95
|
listArchiveContributions(input: ArchiveContributionListInput, runId: string): Promise<unknown>;
|
|
81
96
|
getArchiveContributionHistory(draftSn: string, runId: string): Promise<unknown>;
|
|
97
|
+
listArchiveDocuments(target: Omit<ArchiveDocumentTarget, 'nodeId'>, runId: string): Promise<unknown>;
|
|
98
|
+
getArchiveDocument(target: ArchiveDocumentTarget, runId: string): Promise<unknown>;
|
|
99
|
+
createArchiveDocumentContribution(input: ArchiveDocumentContributionCreateInput, runId: string): Promise<unknown>;
|
|
100
|
+
updateArchiveDocumentContribution(target: ArchiveDocumentTarget, proposed: ArchiveDocumentProposedInput, runId: string): Promise<unknown>;
|
|
101
|
+
deleteArchiveDocumentContribution(target: ArchiveDocumentTarget, runId: string): Promise<unknown>;
|
|
102
|
+
submitArchiveDocumentContribution(target: ArchiveDocumentTarget, runId: string): Promise<unknown>;
|
|
103
|
+
withdrawArchiveDocumentContribution(target: ArchiveDocumentTarget, runId: string): Promise<unknown>;
|
|
104
|
+
reopenArchiveDocumentContribution(target: ArchiveDocumentTarget, runId: string): Promise<unknown>;
|
|
105
|
+
getArchiveDocumentContribution(target: ArchiveDocumentTarget, runId: string): Promise<unknown>;
|
|
106
|
+
listArchiveDocumentContributions(input: ArchiveDocumentContributionListInput, runId: string): Promise<unknown>;
|
|
107
|
+
getArchiveDocumentContributionHistory(draftSn: string, runId: string): Promise<unknown>;
|
|
82
108
|
createWikiContribution(input: WikiContributionWriteInput & {
|
|
83
109
|
resourceId: string;
|
|
84
110
|
operation: 'create' | 'update' | 'delete';
|
|
@@ -99,8 +125,11 @@ export declare class ApiXClient implements KloudyApi {
|
|
|
99
125
|
openBlogDraft(articleId: string, runId: string): Promise<import("./types.js").BlogDraft>;
|
|
100
126
|
updateBlogDraftContent(articleId: string, content: string, runId: string): Promise<import("./types.js").BlogDraftContent>;
|
|
101
127
|
private contributionAction;
|
|
128
|
+
private archiveDocumentContributionAction;
|
|
102
129
|
private request;
|
|
103
130
|
private requestWithHeaders;
|
|
131
|
+
requestDeviceId(): Promise<string>;
|
|
132
|
+
private registerAnonymousDevice;
|
|
104
133
|
private ensureAccessToken;
|
|
105
134
|
private oauthRequest;
|
|
106
135
|
}
|