@awareness-sdk/local 0.1.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/bin/awareness-local.mjs +489 -0
- package/package.json +31 -0
- package/src/api.mjs +122 -0
- package/src/core/cloud-sync.mjs +970 -0
- package/src/core/config.mjs +303 -0
- package/src/core/embedder.mjs +239 -0
- package/src/core/index.mjs +34 -0
- package/src/core/indexer.mjs +726 -0
- package/src/core/knowledge-extractor.mjs +629 -0
- package/src/core/memory-store.mjs +665 -0
- package/src/core/search.mjs +633 -0
- package/src/daemon.mjs +1720 -0
- package/src/mcp-server.mjs +335 -0
- package/src/spec/awareness-spec.json +393 -0
- package/src/web/index.html +1015 -0
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LocalMcpServer — MCP protocol layer for Awareness Local.
|
|
3
|
+
*
|
|
4
|
+
* Registers 5 MCP tools that are 100% compatible with the cloud API:
|
|
5
|
+
* - awareness_init — session creation + context loading
|
|
6
|
+
* - awareness_recall — progressive disclosure search (summary/full)
|
|
7
|
+
* - awareness_record — remember / remember_batch / update_task / submit_insights
|
|
8
|
+
* - awareness_lookup — type-based structured data queries
|
|
9
|
+
* - awareness_get_agent_prompt — spec-based agent prompt
|
|
10
|
+
*
|
|
11
|
+
* Uses @modelcontextprotocol/sdk McpServer with Zod schemas.
|
|
12
|
+
* All tools return: { content: [{ type: 'text', text: JSON.stringify(result) }] }
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
16
|
+
import { z } from 'zod';
|
|
17
|
+
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// Helpers
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Wrap a result object in the MCP-standard content envelope.
|
|
24
|
+
* @param {object} result
|
|
25
|
+
* @returns {{ content: Array<{ type: string, text: string }> }}
|
|
26
|
+
*/
|
|
27
|
+
function mcpResult(result) {
|
|
28
|
+
return {
|
|
29
|
+
content: [{ type: 'text', text: JSON.stringify(result) }],
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Wrap an error message in the MCP-standard content envelope with isError flag.
|
|
35
|
+
* @param {string} message
|
|
36
|
+
* @returns {{ content: Array<{ type: string, text: string }>, isError: boolean }}
|
|
37
|
+
*/
|
|
38
|
+
function mcpError(message) {
|
|
39
|
+
return {
|
|
40
|
+
content: [{ type: 'text', text: JSON.stringify({ error: message }) }],
|
|
41
|
+
isError: true,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
// LocalMcpServer
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
|
|
49
|
+
export class LocalMcpServer {
|
|
50
|
+
/**
|
|
51
|
+
* @param {object} engine — injected from the daemon, provides:
|
|
52
|
+
* - memoryStore {MemoryStore} — markdown file CRUD
|
|
53
|
+
* - indexer {Indexer} — SQLite FTS5 index
|
|
54
|
+
* - search {SearchEngine} — hybrid recall
|
|
55
|
+
* - extractor {KnowledgeExtractor} — rule + pre-extracted knowledge
|
|
56
|
+
* - config {object} — loaded config.json
|
|
57
|
+
* - loadSpec {() => object} — returns awareness-spec.json contents
|
|
58
|
+
* - createSession {(source) => object}
|
|
59
|
+
* - remember {(params) => Promise<object>}
|
|
60
|
+
* - rememberBatch {(params) => Promise<object>}
|
|
61
|
+
* - updateTask {(params) => Promise<object>}
|
|
62
|
+
* - submitInsights {(params) => Promise<object>}
|
|
63
|
+
* - lookup {(params) => Promise<object>}
|
|
64
|
+
*/
|
|
65
|
+
constructor(engine) {
|
|
66
|
+
this.engine = engine;
|
|
67
|
+
this.server = new McpServer({
|
|
68
|
+
name: 'awareness-local',
|
|
69
|
+
version: '1.0.0',
|
|
70
|
+
});
|
|
71
|
+
this._registerTools();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// -----------------------------------------------------------------------
|
|
75
|
+
// Tool registration
|
|
76
|
+
// -----------------------------------------------------------------------
|
|
77
|
+
|
|
78
|
+
/** @private */
|
|
79
|
+
_registerTools() {
|
|
80
|
+
this._registerInit();
|
|
81
|
+
this._registerRecall();
|
|
82
|
+
this._registerRecord();
|
|
83
|
+
this._registerLookup();
|
|
84
|
+
this._registerGetAgentPrompt();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// ======================== awareness_init ================================
|
|
88
|
+
|
|
89
|
+
/** @private */
|
|
90
|
+
_registerInit() {
|
|
91
|
+
this.server.tool(
|
|
92
|
+
'awareness_init',
|
|
93
|
+
{
|
|
94
|
+
memory_id: z.string().optional().describe(
|
|
95
|
+
'Memory identifier (ignored in local mode, uses project dir)'
|
|
96
|
+
),
|
|
97
|
+
source: z.string().optional().describe('Client source identifier'),
|
|
98
|
+
days: z.number().optional().default(7).describe(
|
|
99
|
+
'Days of history to load'
|
|
100
|
+
),
|
|
101
|
+
max_cards: z.number().optional().default(5),
|
|
102
|
+
max_tasks: z.number().optional().default(5),
|
|
103
|
+
},
|
|
104
|
+
async (params) => {
|
|
105
|
+
try {
|
|
106
|
+
const session = this.engine.createSession(params.source);
|
|
107
|
+
const stats = this.engine.indexer.getStats();
|
|
108
|
+
const recentCards = this.engine.indexer.getRecentKnowledge(
|
|
109
|
+
params.max_cards ?? 5
|
|
110
|
+
);
|
|
111
|
+
const openTasks = this.engine.indexer.getOpenTasks(
|
|
112
|
+
params.max_tasks ?? 5
|
|
113
|
+
);
|
|
114
|
+
const recentSessions = this.engine.indexer.getRecentSessions(
|
|
115
|
+
params.days ?? 7
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
// Load workflow rules from awareness-spec.json
|
|
119
|
+
const spec = this.engine.loadSpec();
|
|
120
|
+
|
|
121
|
+
return mcpResult({
|
|
122
|
+
session_id: session.id,
|
|
123
|
+
mode: 'local',
|
|
124
|
+
knowledge_cards: recentCards,
|
|
125
|
+
open_tasks: openTasks,
|
|
126
|
+
recent_sessions: recentSessions,
|
|
127
|
+
stats,
|
|
128
|
+
synthesized_rules: spec.core_lines?.join('\n') || '',
|
|
129
|
+
init_guides: spec.init_guides || {},
|
|
130
|
+
// Local mode does not have agent_profiles, active_skills, setup_hints.
|
|
131
|
+
// Keep fields present (empty) for client compatibility.
|
|
132
|
+
agent_profiles: [],
|
|
133
|
+
active_skills: [],
|
|
134
|
+
setup_hints: [],
|
|
135
|
+
});
|
|
136
|
+
} catch (err) {
|
|
137
|
+
return mcpError(`awareness_init failed: ${err.message}`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// ======================== awareness_recall ==============================
|
|
144
|
+
|
|
145
|
+
/** @private */
|
|
146
|
+
_registerRecall() {
|
|
147
|
+
this.server.tool(
|
|
148
|
+
'awareness_recall',
|
|
149
|
+
{
|
|
150
|
+
semantic_query: z.string().optional().default('').describe(
|
|
151
|
+
'Natural language search query (required for search)'
|
|
152
|
+
),
|
|
153
|
+
keyword_query: z.string().optional().default('').describe(
|
|
154
|
+
'Exact keyword match for BM25 full-text search'
|
|
155
|
+
),
|
|
156
|
+
scope: z.enum(['all', 'timeline', 'knowledge', 'insights'])
|
|
157
|
+
.optional().default('all')
|
|
158
|
+
.describe('Search scope'),
|
|
159
|
+
recall_mode: z.enum(['precise', 'session', 'structured', 'hybrid', 'auto'])
|
|
160
|
+
.optional().default('hybrid')
|
|
161
|
+
.describe('Search mode (hybrid recommended)'),
|
|
162
|
+
limit: z.number().min(1).max(30).optional().default(10)
|
|
163
|
+
.describe('Max results'),
|
|
164
|
+
detail: z.enum(['summary', 'full']).optional().default('summary')
|
|
165
|
+
.describe(
|
|
166
|
+
'summary = lightweight index (~50-100 tokens each); ' +
|
|
167
|
+
'full = complete content for specified ids'
|
|
168
|
+
),
|
|
169
|
+
ids: z.array(z.string()).optional().describe(
|
|
170
|
+
'Item IDs to expand when detail=full (from a prior detail=summary call)'
|
|
171
|
+
),
|
|
172
|
+
agent_role: z.string().optional().default('').describe('Agent role filter'),
|
|
173
|
+
},
|
|
174
|
+
async (params) => {
|
|
175
|
+
try {
|
|
176
|
+
// Phase 2: full content for specific IDs
|
|
177
|
+
if (params.detail === 'full' && params.ids?.length) {
|
|
178
|
+
const items = await this.engine.search.getFullContent(params.ids);
|
|
179
|
+
return mcpResult({
|
|
180
|
+
results: items,
|
|
181
|
+
total: items.length,
|
|
182
|
+
mode: 'local',
|
|
183
|
+
detail: 'full',
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Phase 1: search and return summary index
|
|
188
|
+
if (!params.semantic_query && !params.keyword_query) {
|
|
189
|
+
return mcpResult({
|
|
190
|
+
results: [],
|
|
191
|
+
total: 0,
|
|
192
|
+
mode: 'local',
|
|
193
|
+
detail: 'summary',
|
|
194
|
+
search_method: 'hybrid',
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const summaries = await this.engine.search.recall({
|
|
199
|
+
semantic_query: params.semantic_query,
|
|
200
|
+
keyword_query: params.keyword_query,
|
|
201
|
+
scope: params.scope,
|
|
202
|
+
recall_mode: params.recall_mode,
|
|
203
|
+
limit: params.limit,
|
|
204
|
+
agent_role: params.agent_role,
|
|
205
|
+
detail: params.detail || 'summary',
|
|
206
|
+
ids: params.ids,
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
return mcpResult({
|
|
210
|
+
results: summaries,
|
|
211
|
+
total: summaries.length,
|
|
212
|
+
mode: 'local',
|
|
213
|
+
detail: params.detail || 'summary',
|
|
214
|
+
search_method: 'hybrid',
|
|
215
|
+
});
|
|
216
|
+
} catch (err) {
|
|
217
|
+
return mcpError(`awareness_recall failed: ${err.message}`);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// ======================== awareness_record ==============================
|
|
224
|
+
|
|
225
|
+
/** @private */
|
|
226
|
+
_registerRecord() {
|
|
227
|
+
this.server.tool(
|
|
228
|
+
'awareness_record',
|
|
229
|
+
{
|
|
230
|
+
action: z.enum([
|
|
231
|
+
'remember', 'remember_batch', 'update_task', 'submit_insights',
|
|
232
|
+
]).describe('Record action type'),
|
|
233
|
+
content: z.string().optional().describe('Memory content (markdown)'),
|
|
234
|
+
title: z.string().optional().describe('Memory title'),
|
|
235
|
+
items: z.array(z.object({
|
|
236
|
+
content: z.string(),
|
|
237
|
+
title: z.string().optional(),
|
|
238
|
+
event_type: z.string().optional(),
|
|
239
|
+
tags: z.array(z.string()).optional(),
|
|
240
|
+
insights: z.any().optional(),
|
|
241
|
+
})).optional().describe('Batch items for remember_batch'),
|
|
242
|
+
insights: z.object({
|
|
243
|
+
knowledge_cards: z.array(z.any()).optional(),
|
|
244
|
+
action_items: z.array(z.any()).optional(),
|
|
245
|
+
risks: z.array(z.any()).optional(),
|
|
246
|
+
}).optional().describe('Pre-extracted knowledge cards, tasks, risks'),
|
|
247
|
+
session_id: z.string().optional(),
|
|
248
|
+
agent_role: z.string().optional(),
|
|
249
|
+
event_type: z.string().optional(),
|
|
250
|
+
tags: z.array(z.string()).optional(),
|
|
251
|
+
// Task update fields
|
|
252
|
+
task_id: z.string().optional(),
|
|
253
|
+
status: z.string().optional(),
|
|
254
|
+
},
|
|
255
|
+
async (params) => {
|
|
256
|
+
try {
|
|
257
|
+
switch (params.action) {
|
|
258
|
+
case 'remember':
|
|
259
|
+
return mcpResult(await this.engine.remember(params));
|
|
260
|
+
case 'remember_batch':
|
|
261
|
+
return mcpResult(await this.engine.rememberBatch(params));
|
|
262
|
+
case 'update_task':
|
|
263
|
+
return mcpResult(await this.engine.updateTask(params));
|
|
264
|
+
case 'submit_insights':
|
|
265
|
+
return mcpResult(await this.engine.submitInsights(params));
|
|
266
|
+
default:
|
|
267
|
+
return mcpError(`Unknown action: ${params.action}`);
|
|
268
|
+
}
|
|
269
|
+
} catch (err) {
|
|
270
|
+
return mcpError(`awareness_record failed: ${err.message}`);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// ======================== awareness_lookup ==============================
|
|
277
|
+
|
|
278
|
+
/** @private */
|
|
279
|
+
_registerLookup() {
|
|
280
|
+
this.server.tool(
|
|
281
|
+
'awareness_lookup',
|
|
282
|
+
{
|
|
283
|
+
type: z.enum([
|
|
284
|
+
'context', 'tasks', 'knowledge', 'risks',
|
|
285
|
+
'session_history', 'timeline',
|
|
286
|
+
]).describe(
|
|
287
|
+
'Data type to look up. ' +
|
|
288
|
+
'context = full dump, tasks = open tasks, knowledge = cards, ' +
|
|
289
|
+
'risks = risk items, session_history = past sessions, timeline = events'
|
|
290
|
+
),
|
|
291
|
+
limit: z.number().optional().default(10).describe('Max items'),
|
|
292
|
+
status: z.string().optional().describe('Status filter'),
|
|
293
|
+
category: z.string().optional().describe('Category filter (knowledge cards)'),
|
|
294
|
+
priority: z.string().optional().describe('Priority filter (tasks/risks)'),
|
|
295
|
+
session_id: z.string().optional().describe('Session ID (for session_history)'),
|
|
296
|
+
agent_role: z.string().optional().describe('Agent role filter'),
|
|
297
|
+
query: z.string().optional().describe('Keyword filter'),
|
|
298
|
+
},
|
|
299
|
+
async (params) => {
|
|
300
|
+
try {
|
|
301
|
+
const result = await this.engine.lookup(params);
|
|
302
|
+
return mcpResult(result);
|
|
303
|
+
} catch (err) {
|
|
304
|
+
return mcpError(`awareness_lookup failed: ${err.message}`);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// ======================== awareness_get_agent_prompt ====================
|
|
311
|
+
|
|
312
|
+
/** @private */
|
|
313
|
+
_registerGetAgentPrompt() {
|
|
314
|
+
this.server.tool(
|
|
315
|
+
'awareness_get_agent_prompt',
|
|
316
|
+
{
|
|
317
|
+
role: z.string().optional().describe('Agent role to get prompt for'),
|
|
318
|
+
},
|
|
319
|
+
async (params) => {
|
|
320
|
+
try {
|
|
321
|
+
const spec = this.engine.loadSpec();
|
|
322
|
+
return mcpResult({
|
|
323
|
+
prompt: spec.init_guides?.sub_agent_guide || '',
|
|
324
|
+
role: params.role || '',
|
|
325
|
+
mode: 'local',
|
|
326
|
+
});
|
|
327
|
+
} catch (err) {
|
|
328
|
+
return mcpError(`awareness_get_agent_prompt failed: ${err.message}`);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
export default LocalMcpServer;
|