@spaceflow/core 0.14.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +195 -46
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/cli-runtime/di/container.ts +12 -1
- package/src/cli-runtime/di/services.ts +3 -2
- package/src/cli-runtime/extension-loader.ts +38 -8
- package/src/commands/mcp/mcp.service.ts +154 -15
- package/src/extension-system/define-extension.ts +2 -16
- package/src/extension-system/extension.interface.ts +0 -6
- package/src/extension-system/types.ts +29 -16
- package/src/index.ts +1 -1
- package/src/locales/en/mcp.json +1 -0
- package/src/locales/zh-cn/mcp.json +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spaceflow/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "Spaceflow 核心能力库",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Lydanne",
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
"zod-to-json-schema": "^3.25.1",
|
|
100
100
|
"commander": "^12.1.0",
|
|
101
101
|
"i18next": "^25.8.4",
|
|
102
|
-
"@spaceflow/shared": "0.
|
|
102
|
+
"@spaceflow/shared": "0.6.0"
|
|
103
103
|
},
|
|
104
104
|
"devDependencies": {
|
|
105
105
|
"@swc/core": "1.15.3",
|
|
@@ -25,6 +25,7 @@ interface ServiceRegistration<T = unknown> {
|
|
|
25
25
|
*/
|
|
26
26
|
export class ServiceContainer implements SpaceflowContext {
|
|
27
27
|
private registrations = new Map<string, ServiceRegistration>();
|
|
28
|
+
private _cwd!: string;
|
|
28
29
|
private _config!: IConfigReader;
|
|
29
30
|
private _output!: IOutputService;
|
|
30
31
|
private _storage!: IStorageService;
|
|
@@ -32,7 +33,13 @@ export class ServiceContainer implements SpaceflowContext {
|
|
|
32
33
|
/**
|
|
33
34
|
* 设置核心服务(config, output, storage)
|
|
34
35
|
*/
|
|
35
|
-
setCoreServices(
|
|
36
|
+
setCoreServices(
|
|
37
|
+
config: IConfigReader,
|
|
38
|
+
output: IOutputService,
|
|
39
|
+
storage: IStorageService,
|
|
40
|
+
cwd: string,
|
|
41
|
+
): void {
|
|
42
|
+
this._cwd = cwd;
|
|
36
43
|
this._config = config;
|
|
37
44
|
this._output = output;
|
|
38
45
|
this._storage = storage;
|
|
@@ -95,6 +102,10 @@ export class ServiceContainer implements SpaceflowContext {
|
|
|
95
102
|
}
|
|
96
103
|
}
|
|
97
104
|
|
|
105
|
+
get cwd(): string {
|
|
106
|
+
return this._cwd;
|
|
107
|
+
}
|
|
108
|
+
|
|
98
109
|
get config(): IConfigReader {
|
|
99
110
|
return this._config;
|
|
100
111
|
}
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
LlmProxyService,
|
|
7
7
|
FileAdapter,
|
|
8
8
|
} from "@spaceflow/core";
|
|
9
|
+
import { findProjectRoot } from "@spaceflow/shared";
|
|
9
10
|
import { join } from "path";
|
|
10
11
|
import type { ServiceContainer } from "./container";
|
|
11
12
|
import { UnifiedConfigReader } from "./config";
|
|
@@ -14,13 +15,13 @@ import { UnifiedConfigReader } from "./config";
|
|
|
14
15
|
* 初始化服务容器
|
|
15
16
|
*/
|
|
16
17
|
export function initializeContainer(container: ServiceContainer, cwd?: string): void {
|
|
17
|
-
const workDir = cwd || process.
|
|
18
|
+
const workDir = cwd || process.env.SPACEFLOW_CWD || findProjectRoot();
|
|
18
19
|
// 初始化核心服务(.env 已在 CLI 壳子阶段加载)
|
|
19
20
|
const config = new UnifiedConfigReader(workDir);
|
|
20
21
|
const output = new OutputService();
|
|
21
22
|
const storageDir = join(workDir, ".spaceflow", "cache");
|
|
22
23
|
const storage = new StorageService(new FileAdapter(storageDir));
|
|
23
|
-
container.setCoreServices(config, output, storage);
|
|
24
|
+
container.setCoreServices(config, output, storage, workDir);
|
|
24
25
|
// 注册服务工厂
|
|
25
26
|
registerServiceFactories(container);
|
|
26
27
|
}
|
|
@@ -11,6 +11,16 @@ export class ExtensionLoader {
|
|
|
11
11
|
|
|
12
12
|
constructor(private readonly ctx: SpaceflowContext) {}
|
|
13
13
|
|
|
14
|
+
/** 当前工作目录(项目根) */
|
|
15
|
+
get cwd(): string {
|
|
16
|
+
return this.ctx.cwd;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** 获取上下文(供内部命令使用) */
|
|
20
|
+
getContext(): SpaceflowContext {
|
|
21
|
+
return this.ctx;
|
|
22
|
+
}
|
|
23
|
+
|
|
14
24
|
/**
|
|
15
25
|
* 注册扩展
|
|
16
26
|
*/
|
|
@@ -56,19 +66,39 @@ export class ExtensionLoader {
|
|
|
56
66
|
}
|
|
57
67
|
|
|
58
68
|
/**
|
|
59
|
-
* 获取所有 MCP
|
|
60
|
-
* 返回扩展中定义的
|
|
69
|
+
* 获取所有 MCP 工具
|
|
70
|
+
* 返回扩展中定义的 tools 字段
|
|
71
|
+
*/
|
|
72
|
+
getTools(): Array<{ extensionName: string; tools: NonNullable<ExtensionDefinition["tools"]> }> {
|
|
73
|
+
const result: Array<{
|
|
74
|
+
extensionName: string;
|
|
75
|
+
tools: NonNullable<ExtensionDefinition["tools"]>;
|
|
76
|
+
}> = [];
|
|
77
|
+
for (const ext of this.extensions.values()) {
|
|
78
|
+
if (ext.tools && ext.tools.length > 0) {
|
|
79
|
+
result.push({ extensionName: ext.name, tools: ext.tools });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return result;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* 获取所有 MCP 资源
|
|
87
|
+
* 返回扩展中定义的 resources 字段
|
|
61
88
|
*/
|
|
62
|
-
|
|
63
|
-
|
|
89
|
+
getResources(): Array<{
|
|
90
|
+
extensionName: string;
|
|
91
|
+
resources: NonNullable<ExtensionDefinition["resources"]>;
|
|
92
|
+
}> {
|
|
93
|
+
const result: Array<{
|
|
64
94
|
extensionName: string;
|
|
65
|
-
|
|
95
|
+
resources: NonNullable<ExtensionDefinition["resources"]>;
|
|
66
96
|
}> = [];
|
|
67
97
|
for (const ext of this.extensions.values()) {
|
|
68
|
-
if (ext.
|
|
69
|
-
|
|
98
|
+
if (ext.resources && ext.resources.length > 0) {
|
|
99
|
+
result.push({ extensionName: ext.name, resources: ext.resources });
|
|
70
100
|
}
|
|
71
101
|
}
|
|
72
|
-
return
|
|
102
|
+
return result;
|
|
73
103
|
}
|
|
74
104
|
}
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import { t } from "@spaceflow/core";
|
|
2
|
-
import type { VerboseLevel } from "@spaceflow/core";
|
|
2
|
+
import type { VerboseLevel, McpResourceDefinition, SpaceflowContext } from "@spaceflow/core";
|
|
3
3
|
import { shouldLog, type McpToolMetadata } from "@spaceflow/core";
|
|
4
|
+
import { readConfigSync } from "@spaceflow/shared";
|
|
4
5
|
import type { ExtensionLoader } from "../../cli-runtime/extension-loader";
|
|
5
6
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
6
7
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
7
8
|
import { z } from "zod";
|
|
8
9
|
import { spawn } from "child_process";
|
|
9
10
|
|
|
11
|
+
/** 内部 resource 收集结构 */
|
|
12
|
+
interface CollectedResource {
|
|
13
|
+
resource: McpResourceDefinition;
|
|
14
|
+
ctx: SpaceflowContext;
|
|
15
|
+
}
|
|
16
|
+
|
|
10
17
|
export class McpService {
|
|
11
18
|
constructor(private readonly extensionLoader: ExtensionLoader) {}
|
|
12
19
|
|
|
@@ -21,27 +28,24 @@ export class McpService {
|
|
|
21
28
|
return;
|
|
22
29
|
}
|
|
23
30
|
if (shouldLog(verbose, 1)) {
|
|
24
|
-
const cwd =
|
|
31
|
+
const cwd = this.extensionLoader.cwd;
|
|
25
32
|
console.error(t("mcp:cwdInfo", { cwd }));
|
|
26
|
-
if (!process.env.SPACEFLOW_CWD) {
|
|
27
|
-
console.error(t("mcp:cwdEnvHint"));
|
|
28
|
-
}
|
|
29
33
|
console.error(t("mcp:scanning"));
|
|
30
34
|
}
|
|
31
35
|
|
|
32
36
|
const extensions = this.extensionLoader.getExtensions();
|
|
33
|
-
const
|
|
37
|
+
const extensionTools = this.extensionLoader.getTools();
|
|
34
38
|
|
|
35
39
|
if (shouldLog(verbose, 2)) {
|
|
36
40
|
console.error(t("mcp:foundExtensions", { count: extensions.length }));
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
const allTools: Array<{ tool: McpToolMetadata; handler: any; ctx: any }> = [];
|
|
40
|
-
for (const { extensionName,
|
|
44
|
+
for (const { extensionName, tools } of extensionTools) {
|
|
41
45
|
if (shouldLog(verbose, 2)) {
|
|
42
|
-
console.error(` 扩展 ${extensionName} 提供 ${
|
|
46
|
+
console.error(` 扩展 ${extensionName} 提供 ${tools.length} 个 MCP 工具`);
|
|
43
47
|
}
|
|
44
|
-
for (const tool of
|
|
48
|
+
for (const tool of tools) {
|
|
45
49
|
if (shouldLog(verbose, 3)) {
|
|
46
50
|
console.error(` - ${tool.name}: ${tool.description}`);
|
|
47
51
|
}
|
|
@@ -55,21 +59,32 @@ export class McpService {
|
|
|
55
59
|
methodName: "handler",
|
|
56
60
|
},
|
|
57
61
|
handler: tool.handler,
|
|
58
|
-
ctx: this.extensionLoader
|
|
62
|
+
ctx: this.extensionLoader.getContext(),
|
|
59
63
|
});
|
|
60
64
|
}
|
|
61
65
|
}
|
|
62
66
|
|
|
63
|
-
|
|
67
|
+
// 收集扩展 resources + 内置 resources
|
|
68
|
+
const allResources = this.collectResources(verbose);
|
|
69
|
+
|
|
70
|
+
if (allTools.length === 0 && allResources.length === 0) {
|
|
64
71
|
console.error(t("mcp:noToolsFound"));
|
|
65
72
|
console.error(t("mcp:noToolsHint"));
|
|
66
73
|
process.exit(1);
|
|
67
74
|
}
|
|
68
75
|
|
|
69
76
|
if (shouldLog(verbose, 1)) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
77
|
+
if (allTools.length > 0) {
|
|
78
|
+
console.error(t("mcp:toolsFound", { count: allTools.length }));
|
|
79
|
+
for (const { tool } of allTools) {
|
|
80
|
+
console.error(` - ${tool.name}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (allResources.length > 0) {
|
|
84
|
+
console.error(t("mcp:resourcesFound", { count: allResources.length }));
|
|
85
|
+
for (const { resource } of allResources) {
|
|
86
|
+
console.error(` - ${resource.name} (${resource.uri})`);
|
|
87
|
+
}
|
|
73
88
|
}
|
|
74
89
|
}
|
|
75
90
|
|
|
@@ -81,7 +96,93 @@ export class McpService {
|
|
|
81
96
|
}
|
|
82
97
|
|
|
83
98
|
// 被 MCP 客户端通过管道调用,正常启动 stdio server
|
|
84
|
-
await this.runServer(allTools, verbose);
|
|
99
|
+
await this.runServer(allTools, allResources, verbose);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* 收集所有 MCP 资源(扩展 + 内置)
|
|
104
|
+
*/
|
|
105
|
+
private collectResources(verbose?: VerboseLevel): CollectedResource[] {
|
|
106
|
+
const ctx = this.extensionLoader.getContext();
|
|
107
|
+
const allResources: CollectedResource[] = [];
|
|
108
|
+
|
|
109
|
+
// 1. 收集扩展声明的 resources
|
|
110
|
+
const extensionResources = this.extensionLoader.getResources();
|
|
111
|
+
for (const { extensionName, resources } of extensionResources) {
|
|
112
|
+
if (shouldLog(verbose, 2)) {
|
|
113
|
+
console.error(` 扩展 ${extensionName} 提供 ${resources.length} 个 MCP 资源`);
|
|
114
|
+
}
|
|
115
|
+
for (const resource of resources) {
|
|
116
|
+
allResources.push({ resource, ctx });
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// 2. 内置资源:项目配置(过滤敏感字段)
|
|
121
|
+
allResources.push({
|
|
122
|
+
resource: {
|
|
123
|
+
name: "spaceflow-config",
|
|
124
|
+
uri: "spaceflow://config",
|
|
125
|
+
title: "Spaceflow Configuration",
|
|
126
|
+
description: "当前项目的 Spaceflow 配置(已过滤敏感字段)",
|
|
127
|
+
mimeType: "application/json",
|
|
128
|
+
handler: async (_uri, ctx) => {
|
|
129
|
+
const config = readConfigSync(ctx.cwd);
|
|
130
|
+
return JSON.stringify(this.sanitizeConfig(config), null, 2);
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
ctx,
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// 3. 内置资源:扩展列表
|
|
137
|
+
allResources.push({
|
|
138
|
+
resource: {
|
|
139
|
+
name: "spaceflow-extensions",
|
|
140
|
+
uri: "spaceflow://extensions",
|
|
141
|
+
title: "Installed Extensions",
|
|
142
|
+
description: "当前项目已安装的 Spaceflow 扩展及其工具/资源",
|
|
143
|
+
mimeType: "application/json",
|
|
144
|
+
handler: async () => {
|
|
145
|
+
const extensions = this.extensionLoader.getExtensions();
|
|
146
|
+
const summary = extensions.map((ext) => ({
|
|
147
|
+
name: ext.name,
|
|
148
|
+
version: ext.version,
|
|
149
|
+
description: ext.description,
|
|
150
|
+
commands: ext.commands.map((c) => c.name),
|
|
151
|
+
tools: (ext.tools || []).map((t) => ({ name: t.name, description: t.description })),
|
|
152
|
+
resources: (ext.resources || []).map((r) => ({
|
|
153
|
+
name: r.name,
|
|
154
|
+
uri: r.uri,
|
|
155
|
+
description: r.description,
|
|
156
|
+
})),
|
|
157
|
+
}));
|
|
158
|
+
return JSON.stringify(summary, null, 2);
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
ctx,
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
return allResources;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* 过滤配置中的敏感字段
|
|
169
|
+
*/
|
|
170
|
+
private sanitizeConfig(config: Record<string, any>): Record<string, any> {
|
|
171
|
+
const sensitiveKeys = ["token", "apiKey", "appSecret", "authToken", "apikey", "secret"];
|
|
172
|
+
const sanitize = (obj: any): any => {
|
|
173
|
+
if (obj === null || obj === undefined || typeof obj !== "object") return obj;
|
|
174
|
+
if (Array.isArray(obj)) return obj.map(sanitize);
|
|
175
|
+
const result: Record<string, any> = {};
|
|
176
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
177
|
+
if (sensitiveKeys.some((sk) => key.toLowerCase().includes(sk.toLowerCase()))) {
|
|
178
|
+
result[key] = value ? "***" : "";
|
|
179
|
+
} else {
|
|
180
|
+
result[key] = sanitize(value);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return result;
|
|
184
|
+
};
|
|
185
|
+
return sanitize(config);
|
|
85
186
|
}
|
|
86
187
|
|
|
87
188
|
/**
|
|
@@ -89,6 +190,7 @@ export class McpService {
|
|
|
89
190
|
*/
|
|
90
191
|
private async runServer(
|
|
91
192
|
allTools: Array<{ tool: McpToolMetadata; handler: any; ctx: any }>,
|
|
193
|
+
allResources: CollectedResource[],
|
|
92
194
|
verbose?: VerboseLevel,
|
|
93
195
|
): Promise<void> {
|
|
94
196
|
const server = new McpServer({ name: "spaceflow", version: "1.0.0" });
|
|
@@ -129,6 +231,43 @@ export class McpService {
|
|
|
129
231
|
);
|
|
130
232
|
}
|
|
131
233
|
|
|
234
|
+
// 注册所有资源(使用 v2 API: server.registerResource)
|
|
235
|
+
for (const { resource, ctx } of allResources) {
|
|
236
|
+
server.registerResource(
|
|
237
|
+
resource.name,
|
|
238
|
+
resource.uri,
|
|
239
|
+
{
|
|
240
|
+
title: resource.title,
|
|
241
|
+
description: resource.description,
|
|
242
|
+
mimeType: resource.mimeType || "application/json",
|
|
243
|
+
},
|
|
244
|
+
async (uri) => {
|
|
245
|
+
try {
|
|
246
|
+
const text = await resource.handler(uri.href, ctx);
|
|
247
|
+
return {
|
|
248
|
+
contents: [
|
|
249
|
+
{
|
|
250
|
+
uri: uri.href,
|
|
251
|
+
mimeType: resource.mimeType || "application/json",
|
|
252
|
+
text,
|
|
253
|
+
},
|
|
254
|
+
],
|
|
255
|
+
};
|
|
256
|
+
} catch (error) {
|
|
257
|
+
return {
|
|
258
|
+
contents: [
|
|
259
|
+
{
|
|
260
|
+
uri: uri.href,
|
|
261
|
+
mimeType: "text/plain",
|
|
262
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
263
|
+
},
|
|
264
|
+
],
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
},
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
|
|
132
271
|
// 启动 stdio 传输
|
|
133
272
|
const transport = new StdioServerTransport();
|
|
134
273
|
await server.connect(transport);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExtensionDefinition
|
|
1
|
+
import type { ExtensionDefinition } from "./types";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* 定义扩展
|
|
@@ -6,20 +6,6 @@ import type { ExtensionDefinition, McpServerDefinition } from "./types";
|
|
|
6
6
|
* @param definition 扩展定义
|
|
7
7
|
* @returns 扩展定义(原样返回,仅用于类型推断)
|
|
8
8
|
*/
|
|
9
|
-
export function defineExtension(
|
|
10
|
-
definition: ExtensionDefinition,
|
|
11
|
-
): ExtensionDefinition {
|
|
12
|
-
return definition;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* 定义 MCP 服务器
|
|
17
|
-
* 这是一个类型安全的工厂函数,用于创建 MCP 服务器定义
|
|
18
|
-
* @param definition MCP 服务器定义
|
|
19
|
-
* @returns MCP 服务器定义(原样返回,仅用于类型推断)
|
|
20
|
-
*/
|
|
21
|
-
export function defineMcpServer(
|
|
22
|
-
definition: McpServerDefinition,
|
|
23
|
-
): McpServerDefinition {
|
|
9
|
+
export function defineExtension(definition: ExtensionDefinition): ExtensionDefinition {
|
|
24
10
|
return definition;
|
|
25
11
|
}
|
|
@@ -19,6 +19,8 @@ export interface OptionDefinition {
|
|
|
19
19
|
* 命令和 MCP 工具共用此上下文
|
|
20
20
|
*/
|
|
21
21
|
export interface SpaceflowContext {
|
|
22
|
+
/** 当前工作目录(优先 SPACEFLOW_CWD 环境变量) */
|
|
23
|
+
readonly cwd: string;
|
|
22
24
|
/** 配置读取器 */
|
|
23
25
|
readonly config: IConfigReader;
|
|
24
26
|
/** 输出服务 */
|
|
@@ -134,6 +136,29 @@ export interface ServiceDefinition {
|
|
|
134
136
|
factory: (ctx: SpaceflowContext) => unknown;
|
|
135
137
|
}
|
|
136
138
|
|
|
139
|
+
/**
|
|
140
|
+
* MCP 资源定义
|
|
141
|
+
*/
|
|
142
|
+
export interface McpResourceDefinition {
|
|
143
|
+
/** 资源名称(唯一标识符) */
|
|
144
|
+
name: string;
|
|
145
|
+
/** 资源 URI(固定 URI,如 "config://spaceflow") */
|
|
146
|
+
uri: string;
|
|
147
|
+
/** 资源标题(人类可读) */
|
|
148
|
+
title?: string;
|
|
149
|
+
/** 资源描述 */
|
|
150
|
+
description?: string;
|
|
151
|
+
/** MIME 类型(默认 application/json) */
|
|
152
|
+
mimeType?: string;
|
|
153
|
+
/**
|
|
154
|
+
* 资源读取处理函数
|
|
155
|
+
* @param uri 请求的 URI
|
|
156
|
+
* @param ctx Spaceflow 上下文
|
|
157
|
+
* @returns 资源内容(字符串)
|
|
158
|
+
*/
|
|
159
|
+
handler: (uri: string, ctx: SpaceflowContext) => Promise<string>;
|
|
160
|
+
}
|
|
161
|
+
|
|
137
162
|
/**
|
|
138
163
|
* MCP 工具定义
|
|
139
164
|
*/
|
|
@@ -152,20 +177,6 @@ export interface McpToolDefinition {
|
|
|
152
177
|
handler: (input: unknown, ctx: SpaceflowContext) => Promise<unknown>;
|
|
153
178
|
}
|
|
154
179
|
|
|
155
|
-
/**
|
|
156
|
-
* MCP 服务器定义
|
|
157
|
-
*/
|
|
158
|
-
export interface McpServerDefinition {
|
|
159
|
-
/** 服务器名称 */
|
|
160
|
-
name: string;
|
|
161
|
-
/** 服务器版本 */
|
|
162
|
-
version?: string;
|
|
163
|
-
/** 服务器描述 */
|
|
164
|
-
description?: string;
|
|
165
|
-
/** 工具列表 */
|
|
166
|
-
tools: McpToolDefinition[];
|
|
167
|
-
}
|
|
168
|
-
|
|
169
180
|
/**
|
|
170
181
|
* 扩展定义
|
|
171
182
|
*/
|
|
@@ -184,8 +195,10 @@ export interface ExtensionDefinition {
|
|
|
184
195
|
configDependencies?: string[];
|
|
185
196
|
/** 命令列表 */
|
|
186
197
|
commands: CommandDefinition[];
|
|
187
|
-
/** MCP
|
|
188
|
-
|
|
198
|
+
/** MCP 工具列表 */
|
|
199
|
+
tools?: McpToolDefinition[];
|
|
200
|
+
/** MCP 资源列表 */
|
|
201
|
+
resources?: McpResourceDefinition[];
|
|
189
202
|
/** 服务定义列表 */
|
|
190
203
|
services?: ServiceDefinition[];
|
|
191
204
|
/**
|
package/src/index.ts
CHANGED
|
@@ -48,7 +48,7 @@ export * from "./shared/spaceflow-dir";
|
|
|
48
48
|
export * from "./shared/rspack-config";
|
|
49
49
|
|
|
50
50
|
// MCP - Model Context Protocol 支持
|
|
51
|
-
// 注意:
|
|
51
|
+
// 注意:McpToolDefinition 已在 extension-system/types.ts 中定义(用于 defineExtension 的 tools 字段)
|
|
52
52
|
// 这里只导出装饰器和工具函数,避免重复导出
|
|
53
53
|
export {
|
|
54
54
|
MCP_SERVER_METADATA,
|
package/src/locales/en/mcp.json
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"noToolsFound": "❌ No MCP tools found",
|
|
17
17
|
"noToolsHint": " Hint: Make sure you have installed MCP-enabled extensions that export mcpService or getMcpTools\n If the working directory is incorrect, set the environment variable in your MCP config:\n \"env\": { \"SPACEFLOW_CWD\": \"/path/to/your/project\" }",
|
|
18
18
|
"toolsFound": "✅ Found {{count}} MCP tools",
|
|
19
|
+
"resourcesFound": "📦 Found {{count}} MCP resources",
|
|
19
20
|
"ttyHint": "💡 MCP Server must be started by an MCP client (e.g. Cursor, Claude Desktop) via pipe.\n Add the following config to your MCP client:\n\n \"spaceflow\": {\n \"command\": \"npx\",\n \"args\": [\"@spaceflow/cli\", \"mcp\"],\n \"env\": { \"SPACEFLOW_CWD\": \"/path/to/your/project\" }\n }",
|
|
20
21
|
"serverStarted": "🚀 MCP Server started with {{count}} tools"
|
|
21
22
|
}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"noToolsFound": "❌ 没有找到任何 MCP 工具",
|
|
17
17
|
"noToolsHint": " 提示: 确保已安装支持 MCP 的扩展,并导出 mcpService 或 getMcpTools\n 如果工作目录不正确,请在 MCP 配置中设置环境变量:\n \"env\": { \"SPACEFLOW_CWD\": \"/path/to/your/project\" }",
|
|
18
18
|
"toolsFound": "✅ 共发现 {{count}} 个 MCP 工具",
|
|
19
|
+
"resourcesFound": "📦 共发现 {{count}} 个 MCP 资源",
|
|
19
20
|
"ttyHint": "💡 MCP Server 需要由 MCP 客户端(如 Cursor、Claude Desktop)通过管道启动。\n 请将以下配置添加到你的 MCP 客户端中:\n\n \"spaceflow\": {\n \"command\": \"npx\",\n \"args\": [\"@spaceflow/cli\", \"mcp\"],\n \"env\": { \"SPACEFLOW_CWD\": \"/path/to/your/project\" }\n }",
|
|
20
21
|
"serverStarted": "🚀 MCP Server 已启动,共 {{count}} 个工具"
|
|
21
22
|
}
|