kiku-agent 1.0.0 → 1.0.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/README.md +293 -122
- package/package.json +60 -61
- package/server/agent/agentCore.js +892 -782
- package/server/agent/appPaths.js +21 -0
- package/server/agent/audioPlayer.js +739 -673
- package/server/agent/cli.js +1414 -1111
- package/server/agent/commandRegistry.js +74 -58
- package/server/agent/commands.js +1694 -788
- package/server/agent/config.js +264 -90
- package/server/agent/contextCompactor.js +79 -0
- package/server/agent/doctor.js +69 -0
- package/server/agent/eventBus.js +107 -103
- package/server/agent/gpuMetrics.js +189 -0
- package/server/agent/llmClient.js +369 -200
- package/server/agent/mcpClient.js +364 -0
- package/server/agent/memory.js +670 -566
- package/server/agent/modelManager.js +77 -0
- package/server/agent/research.js +202 -0
- package/server/agent/session.js +244 -239
- package/server/agent/subagent.js +116 -0
- package/server/agent/theme.js +125 -124
- package/server/agent/toolRouter.js +201 -0
- package/server/agent/tools.js +1679 -1528
- package/server/agent/ui.js +760 -469
- package/server/agent/youtubeAuth.js +144 -65
- package/server/mcp/claude-desktop-config.example.json +1 -1
- package/server/mcp/data/discography.js +36 -36
- package/server/mcp/dataAdapter.js +102 -0
- package/server/mcp/examples/claude-code.mcp.example.json +19 -0
- package/server/mcp/examples/claude-desktop.example.json +11 -0
- package/server/mcp/examples/cline.example.json +13 -0
- package/server/mcp/examples/cursor.example.json +14 -0
- package/server/mcp/examples/gemini-cli.example.json +17 -0
- package/server/mcp/examples/opencode.example.json +21 -0
- package/server/mcp/examples/vscode.example.json +19 -0
- package/server/mcp/examples/windsurf.example.json +14 -0
- package/server/mcp/handler.js +85 -159
- package/server/mcp/security.js +140 -138
- package/server/mcp/server.js +129 -100
- package/server/mcp/stdio.js +4 -2
package/server/mcp/server.js
CHANGED
|
@@ -1,100 +1,129 @@
|
|
|
1
|
-
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
import { toolDefinitions, handleToolCall } from './tools.js';
|
|
4
|
-
import { resourceDefinitions, readResource } from './resources.js';
|
|
5
|
-
import { getPrompt } from './prompts.js';
|
|
6
|
-
|
|
7
|
-
export function createMcpServer() {
|
|
8
|
-
const server = new McpServer({
|
|
9
|
-
name: 'kiku
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
},
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
'
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
},
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
server.registerPrompt(
|
|
94
|
-
'
|
|
95
|
-
{
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { toolDefinitions, handleToolCall } from './tools.js';
|
|
4
|
+
import { resourceDefinitions, readResource } from './resources.js';
|
|
5
|
+
import { getPrompt } from './prompts.js';
|
|
6
|
+
|
|
7
|
+
export function createMcpServer() {
|
|
8
|
+
const server = new McpServer({
|
|
9
|
+
name: 'kiku',
|
|
10
|
+
title: 'kiku',
|
|
11
|
+
version: '1.1.0',
|
|
12
|
+
description: 'MCP server exposing the Ju Jingyi catalog as tools, resources, and prompts.',
|
|
13
|
+
websiteUrl: 'https://jujingyi-kikuuu.vercel.app/',
|
|
14
|
+
icons: [
|
|
15
|
+
{
|
|
16
|
+
src: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+DQogIDxkZWZzPg0KICAgIDxsaW5lYXJHcmFkaWVudCBpZD0icGV0YWwiIHgxPSIwIiB5MT0iMCIgeDI9IjEiIHkyPSIxIj4NCiAgICAgIDxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iI2Y5YThkNCIvPg0KICAgICAgPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjZWM0ODk5Ii8+DQogICAgPC9saW5lYXJHcmFkaWVudD4NCiAgPC9kZWZzPg0KICA8cmVjdCB3aWR0aD0iNjQiIGhlaWdodD0iNjQiIHJ4PSIxNCIgZmlsbD0iIzIwMTIyYiIvPg0KICA8ZyBmaWxsPSJ1cmwoI3BldGFsKSI+DQogICAgPGVsbGlwc2UgY3g9IjMyIiBjeT0iMTkiIHJ4PSI3LjUiIHJ5PSIxMSIvPg0KICAgIDxlbGxpcHNlIGN4PSIzMiIgY3k9IjQ1IiByeD0iNy41IiByeT0iMTEiLz4NCiAgICA8ZWxsaXBzZSBjeD0iMTkiIGN5PSIzMiIgcng9IjExIiByeT0iNy41Ii8+DQogICAgPGVsbGlwc2UgY3g9IjQ1IiBjeT0iMzIiIHJ4PSIxMSIgcnk9IjcuNSIvPg0KICA8L2c+DQogIDxjaXJjbGUgY3g9IjMyIiBjeT0iMzIiIHI9IjUuNSIgZmlsbD0iI2ZkZTY4YSIvPg0KPC9zdmc+DQo=',
|
|
17
|
+
mimeType: 'image/svg+xml',
|
|
18
|
+
sizes: ['any', '64x64', '128x128'],
|
|
19
|
+
theme: 'dark',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
src: 'https://jujingyi-kikuuu.vercel.app/mcp-logo-128.png',
|
|
23
|
+
mimeType: 'image/png',
|
|
24
|
+
sizes: ['128x128'],
|
|
25
|
+
theme: 'dark',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
src: 'https://jujingyi-kikuuu.vercel.app/mcp-logo-64.png',
|
|
29
|
+
mimeType: 'image/png',
|
|
30
|
+
sizes: ['64x64'],
|
|
31
|
+
theme: 'dark',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
src: 'https://jujingyi-kikuuu.vercel.app/mcp-logo.svg',
|
|
35
|
+
mimeType: 'image/svg+xml',
|
|
36
|
+
sizes: ['any'],
|
|
37
|
+
theme: 'dark',
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
}, {
|
|
41
|
+
capabilities: {
|
|
42
|
+
tools: {},
|
|
43
|
+
resources: {},
|
|
44
|
+
prompts: {},
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
for (const tool of toolDefinitions) {
|
|
49
|
+
server.registerTool(
|
|
50
|
+
tool.name,
|
|
51
|
+
{
|
|
52
|
+
description: tool.description,
|
|
53
|
+
inputSchema: tool.inputSchema,
|
|
54
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
|
|
55
|
+
},
|
|
56
|
+
async (args) => {
|
|
57
|
+
try {
|
|
58
|
+
const result = await handleToolCall(tool.name, args);
|
|
59
|
+
return {
|
|
60
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
61
|
+
structuredContent: result,
|
|
62
|
+
isError: result?.status === 'error',
|
|
63
|
+
};
|
|
64
|
+
} catch (err) {
|
|
65
|
+
return {
|
|
66
|
+
content: [{ type: 'text', text: JSON.stringify({ status: 'error', message: err.message }) }],
|
|
67
|
+
isError: true,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const resourceMap = {
|
|
75
|
+
'kiku://bio': 'kiku-bio',
|
|
76
|
+
'kiku://awards': 'kiku-awards',
|
|
77
|
+
'kiku://catalog': 'kiku-catalog',
|
|
78
|
+
'kiku://timeline': 'kiku-timeline',
|
|
79
|
+
'kiku://discography': 'kiku-discography',
|
|
80
|
+
'kiku://brands': 'kiku-brands',
|
|
81
|
+
'kiku://social': 'kiku-social',
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
for (const def of resourceDefinitions) {
|
|
85
|
+
server.registerResource(
|
|
86
|
+
resourceMap[def.uri],
|
|
87
|
+
def.uri,
|
|
88
|
+
{ description: def.description, mimeType: def.mimeType },
|
|
89
|
+
async (uri) => readResource(uri.href)
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
server.registerPrompt(
|
|
94
|
+
'recommend_series',
|
|
95
|
+
{
|
|
96
|
+
description: 'Recommend Ju Jingyi dramas based on mood or genre preference.',
|
|
97
|
+
argsSchema: {
|
|
98
|
+
mood: z.string().optional().describe('Current mood: romantic, action-packed, mysterious, emotional, or lighthearted'),
|
|
99
|
+
genre: z.string().optional().describe('Preferred genre: historical, fantasy, xianxia, romance, or suspense'),
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
async (args) => getPrompt('recommend_series', args)
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
server.registerPrompt(
|
|
106
|
+
'brand_portfolio',
|
|
107
|
+
{ description: 'Summarize Ju Jingyi brand endorsements and commercial influence.' },
|
|
108
|
+
async (args) => getPrompt('brand_portfolio', args)
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
server.registerPrompt(
|
|
112
|
+
'character_summary',
|
|
113
|
+
{
|
|
114
|
+
description: 'Get a detailed summary of a specific character role by Ju Jingyi.',
|
|
115
|
+
argsSchema: {
|
|
116
|
+
character_name: z.string().min(1).describe('Character name, such as Yang Caiwei, Bai Suzhen, Lu Wuyi, or Han Yunxi'),
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
async (args) => getPrompt('character_summary', args)
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
server.registerPrompt(
|
|
123
|
+
'career_overview',
|
|
124
|
+
{ description: 'Get a comprehensive career overview organized by era.' },
|
|
125
|
+
async (args) => getPrompt('career_overview', args)
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
return server;
|
|
129
|
+
}
|
package/server/mcp/stdio.js
CHANGED
|
@@ -10,10 +10,12 @@ let closing = false;
|
|
|
10
10
|
async function shutdown(exitCode = 0) {
|
|
11
11
|
if (closing) return;
|
|
12
12
|
closing = true;
|
|
13
|
-
await Promise.allSettled([transport.close(), server.close()]);
|
|
14
|
-
process.exitCode
|
|
13
|
+
await Promise.allSettled([transport.close().catch(() => {}), server.close().catch(() => {})]);
|
|
14
|
+
process.exit(exitCode);
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
process.stdin.once('end', () => { void shutdown(0); });
|
|
18
|
+
process.stdin.once('close', () => { void shutdown(0); });
|
|
17
19
|
process.once('SIGINT', () => { void shutdown(130); });
|
|
18
20
|
process.once('SIGTERM', () => { void shutdown(143); });
|
|
19
21
|
process.once('uncaughtException', error => {
|