@recall_v3/mcp-server 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/dist/api/client.d.ts +111 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/client.js +244 -0
- package/dist/config/index.d.ts +89 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +256 -0
- package/dist/crypto/index.d.ts +56 -0
- package/dist/crypto/index.d.ts.map +1 -0
- package/dist/crypto/index.js +224 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +189 -0
- package/dist/tools/getContext.d.ts +18 -0
- package/dist/tools/getContext.d.ts.map +1 -0
- package/dist/tools/getContext.js +87 -0
- package/dist/tools/getHistory.d.ts +18 -0
- package/dist/tools/getHistory.d.ts.map +1 -0
- package/dist/tools/getHistory.js +97 -0
- package/dist/tools/getTranscripts.d.ts +19 -0
- package/dist/tools/getTranscripts.d.ts.map +1 -0
- package/dist/tools/getTranscripts.js +129 -0
- package/dist/tools/index.d.ts +13 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +37 -0
- package/dist/tools/logDecision.d.ts +19 -0
- package/dist/tools/logDecision.d.ts.map +1 -0
- package/dist/tools/logDecision.js +92 -0
- package/dist/tools/saveSession.d.ts +26 -0
- package/dist/tools/saveSession.d.ts.map +1 -0
- package/dist/tools/saveSession.js +115 -0
- package/dist/tools/types.d.ts +32 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +33 -0
- package/dist/tools/utils.d.ts +52 -0
- package/dist/tools/utils.d.ts.map +1 -0
- package/dist/tools/utils.js +238 -0
- package/package.json +46 -0
- package/src/api/client.ts +295 -0
- package/src/config/index.ts +247 -0
- package/src/crypto/index.ts +207 -0
- package/src/index.ts +232 -0
- package/src/tools/getContext.ts +106 -0
- package/src/tools/getHistory.ts +118 -0
- package/src/tools/getTranscripts.ts +150 -0
- package/src/tools/index.ts +13 -0
- package/src/tools/logDecision.ts +118 -0
- package/src/tools/saveSession.ts +159 -0
- package/src/tools/types.ts +47 -0
- package/src/tools/utils.ts +226 -0
- package/tsconfig.json +14 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* Recall MCP Server v3
|
|
5
|
+
* Local MCP server for AI coding assistants
|
|
6
|
+
*
|
|
7
|
+
* This package provides the local MCP server that connects
|
|
8
|
+
* to the Recall API for team memory synchronization.
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
|
|
12
|
+
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
13
|
+
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
14
|
+
// Tool implementations
|
|
15
|
+
const index_js_2 = require("./tools/index.js");
|
|
16
|
+
// Tool definitions
|
|
17
|
+
const TOOLS = [
|
|
18
|
+
{
|
|
19
|
+
name: 'recall_get_context',
|
|
20
|
+
description: "Get team brain (context.md) for the current repository. This is the distilled current state - loads automatically at every session start. Use recall_get_history for the full encyclopedia.",
|
|
21
|
+
inputSchema: {
|
|
22
|
+
type: 'object',
|
|
23
|
+
properties: {
|
|
24
|
+
projectPath: {
|
|
25
|
+
type: 'string',
|
|
26
|
+
description: 'Optional: explicit path to the project root. If not provided, uses current working directory.',
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: 'recall_get_history',
|
|
33
|
+
description: "Get detailed session history (context.md + recent sessions). This includes more context than recall_get_context but uses more tokens.",
|
|
34
|
+
inputSchema: {
|
|
35
|
+
type: 'object',
|
|
36
|
+
properties: {
|
|
37
|
+
projectPath: {
|
|
38
|
+
type: 'string',
|
|
39
|
+
description: 'Path to the project root. REQUIRED to ensure correct repo context. Use the absolute path to the project you are working in.',
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
required: ['projectPath'],
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: 'recall_get_transcripts',
|
|
47
|
+
description: "Get full session transcripts (context.md + history.md). WARNING: This can be very large and use many tokens. Only use when you need complete historical details.",
|
|
48
|
+
inputSchema: {
|
|
49
|
+
type: 'object',
|
|
50
|
+
properties: {
|
|
51
|
+
projectPath: {
|
|
52
|
+
type: 'string',
|
|
53
|
+
description: 'Path to the project root. REQUIRED to ensure correct repo context. Use the absolute path to the project you are working in.',
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
required: ['projectPath'],
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: 'recall_save_session',
|
|
61
|
+
description: "Save a summary of what was accomplished in this coding session. This updates the team memory files.",
|
|
62
|
+
inputSchema: {
|
|
63
|
+
type: 'object',
|
|
64
|
+
properties: {
|
|
65
|
+
summary: {
|
|
66
|
+
type: 'string',
|
|
67
|
+
description: 'What was accomplished in this session - list all items worked on, kept short',
|
|
68
|
+
},
|
|
69
|
+
decisions: {
|
|
70
|
+
type: 'array',
|
|
71
|
+
description: 'Key decisions made',
|
|
72
|
+
items: {
|
|
73
|
+
type: 'object',
|
|
74
|
+
properties: {
|
|
75
|
+
what: { type: 'string', description: 'What was decided' },
|
|
76
|
+
why: { type: 'string', description: 'Why this decision was made' },
|
|
77
|
+
},
|
|
78
|
+
required: ['what', 'why'],
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
mistakes: {
|
|
82
|
+
type: 'array',
|
|
83
|
+
description: 'Mistakes or gotchas discovered - things the team should not repeat',
|
|
84
|
+
items: { type: 'string' },
|
|
85
|
+
},
|
|
86
|
+
filesChanged: {
|
|
87
|
+
type: 'array',
|
|
88
|
+
description: 'Files that were modified',
|
|
89
|
+
items: { type: 'string' },
|
|
90
|
+
},
|
|
91
|
+
nextSteps: {
|
|
92
|
+
type: 'string',
|
|
93
|
+
description: 'What should be done next',
|
|
94
|
+
},
|
|
95
|
+
blockers: {
|
|
96
|
+
type: 'string',
|
|
97
|
+
description: 'Any blockers encountered',
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
required: ['summary'],
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
name: 'recall_log_decision',
|
|
105
|
+
description: "Log an important decision made during coding. Quick way to capture why something was done.",
|
|
106
|
+
inputSchema: {
|
|
107
|
+
type: 'object',
|
|
108
|
+
properties: {
|
|
109
|
+
decision: {
|
|
110
|
+
type: 'string',
|
|
111
|
+
description: 'What was decided',
|
|
112
|
+
},
|
|
113
|
+
reasoning: {
|
|
114
|
+
type: 'string',
|
|
115
|
+
description: 'Why this decision was made',
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
required: ['decision', 'reasoning'],
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
];
|
|
122
|
+
class RecallMCPServer {
|
|
123
|
+
server;
|
|
124
|
+
constructor() {
|
|
125
|
+
this.server = new index_js_1.Server({
|
|
126
|
+
name: 'recall-mcp-v3',
|
|
127
|
+
version: '0.1.0',
|
|
128
|
+
}, {
|
|
129
|
+
capabilities: {
|
|
130
|
+
tools: {},
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
this.setupHandlers();
|
|
134
|
+
}
|
|
135
|
+
setupHandlers() {
|
|
136
|
+
// List available tools
|
|
137
|
+
this.server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
|
|
138
|
+
return { tools: TOOLS };
|
|
139
|
+
});
|
|
140
|
+
// Handle tool calls
|
|
141
|
+
this.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
142
|
+
const { name, arguments: args = {} } = request.params;
|
|
143
|
+
try {
|
|
144
|
+
let result;
|
|
145
|
+
switch (name) {
|
|
146
|
+
case 'recall_get_context':
|
|
147
|
+
result = await (0, index_js_2.getContext)(args);
|
|
148
|
+
break;
|
|
149
|
+
case 'recall_get_history':
|
|
150
|
+
result = await (0, index_js_2.getHistory)(args);
|
|
151
|
+
break;
|
|
152
|
+
case 'recall_get_transcripts':
|
|
153
|
+
result = await (0, index_js_2.getTranscripts)(args);
|
|
154
|
+
break;
|
|
155
|
+
case 'recall_save_session':
|
|
156
|
+
result = await (0, index_js_2.saveSession)(args);
|
|
157
|
+
break;
|
|
158
|
+
case 'recall_log_decision':
|
|
159
|
+
result = await (0, index_js_2.logDecision)(args);
|
|
160
|
+
break;
|
|
161
|
+
default:
|
|
162
|
+
return {
|
|
163
|
+
content: [{ type: 'text', text: `Unknown tool: ${name}` }],
|
|
164
|
+
isError: true,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
content: result.content.map(c => ({ type: 'text', text: c.text })),
|
|
169
|
+
isError: result.isError,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
174
|
+
return {
|
|
175
|
+
content: [{ type: 'text', text: `Error: ${message}` }],
|
|
176
|
+
isError: true,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
async run() {
|
|
182
|
+
const transport = new stdio_js_1.StdioServerTransport();
|
|
183
|
+
await this.server.connect(transport);
|
|
184
|
+
console.error('Recall MCP v3 server running on stdio');
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
// Start server
|
|
188
|
+
const server = new RecallMCPServer();
|
|
189
|
+
server.run().catch(console.error);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* getContext Tool Implementation
|
|
3
|
+
*
|
|
4
|
+
* Fetches the team brain (context.md) for the current repository.
|
|
5
|
+
* This is the distilled current state - loaded at every session start.
|
|
6
|
+
*/
|
|
7
|
+
import { type ToolResponse } from './types.js';
|
|
8
|
+
export interface GetContextArgs {
|
|
9
|
+
projectPath?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Execute the getContext tool
|
|
13
|
+
*
|
|
14
|
+
* @param args - Tool arguments (projectPath is optional)
|
|
15
|
+
* @returns MCP tool response with context.md content
|
|
16
|
+
*/
|
|
17
|
+
export declare function getContext(args: GetContextArgs): Promise<ToolResponse>;
|
|
18
|
+
//# sourceMappingURL=getContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getContext.d.ts","sourceRoot":"","sources":["../../src/tools/getContext.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAqD,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAGlG,MAAM,WAAW,cAAc;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CAkF5E"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* getContext Tool Implementation
|
|
4
|
+
*
|
|
5
|
+
* Fetches the team brain (context.md) for the current repository.
|
|
6
|
+
* This is the distilled current state - loaded at every session start.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.getContext = getContext;
|
|
10
|
+
const client_js_1 = require("../api/client.js");
|
|
11
|
+
const index_js_1 = require("../config/index.js");
|
|
12
|
+
const index_js_2 = require("../crypto/index.js");
|
|
13
|
+
const types_js_1 = require("./types.js");
|
|
14
|
+
const utils_js_1 = require("./utils.js");
|
|
15
|
+
/**
|
|
16
|
+
* Execute the getContext tool
|
|
17
|
+
*
|
|
18
|
+
* @param args - Tool arguments (projectPath is optional)
|
|
19
|
+
* @returns MCP tool response with context.md content
|
|
20
|
+
*/
|
|
21
|
+
async function getContext(args) {
|
|
22
|
+
try {
|
|
23
|
+
// Get API token
|
|
24
|
+
const token = (0, index_js_1.getApiToken)();
|
|
25
|
+
if (!token) {
|
|
26
|
+
return (0, types_js_1.errorResponse)('Not authenticated. Run `recall auth` to connect your account, or set RECALL_API_TOKEN environment variable.');
|
|
27
|
+
}
|
|
28
|
+
// Resolve project path
|
|
29
|
+
const projectPath = (0, utils_js_1.resolveProjectPath)(args.projectPath);
|
|
30
|
+
// Get repo info from git
|
|
31
|
+
const repoInfo = await (0, utils_js_1.getRepoInfo)(projectPath);
|
|
32
|
+
if (!repoInfo) {
|
|
33
|
+
return (0, types_js_1.errorResponse)(`Could not determine repository info for: ${projectPath}\n` +
|
|
34
|
+
'Make sure this is a git repository with a remote origin.');
|
|
35
|
+
}
|
|
36
|
+
// Create API client
|
|
37
|
+
const client = new client_js_1.RecallApiClient({
|
|
38
|
+
baseUrl: (0, index_js_1.getApiBaseUrl)(),
|
|
39
|
+
token,
|
|
40
|
+
});
|
|
41
|
+
// Resolve repo to get repoId and teamId
|
|
42
|
+
const { repoId, teamId } = await client.resolveRepo(repoInfo.fullName, repoInfo.defaultBranch);
|
|
43
|
+
// Get team key (fetch from API if not cached)
|
|
44
|
+
let teamKey = (0, index_js_1.getTeamKey)(teamId);
|
|
45
|
+
if (!teamKey) {
|
|
46
|
+
const keyResponse = await client.getTeamKey(teamId);
|
|
47
|
+
teamKey = keyResponse.encryptionKey;
|
|
48
|
+
(0, index_js_1.setTeamKey)(teamId, teamKey);
|
|
49
|
+
}
|
|
50
|
+
// Fetch context from API
|
|
51
|
+
const response = await client.getContext(repoId);
|
|
52
|
+
// The contextMd comes encrypted from the API, decrypt it
|
|
53
|
+
let contextMd;
|
|
54
|
+
try {
|
|
55
|
+
// Check if content is encrypted
|
|
56
|
+
if (response.contextMd.startsWith('{') || response.contextMd.includes(':')) {
|
|
57
|
+
contextMd = (0, index_js_2.decryptContent)(response.contextMd, teamKey);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
// Already plaintext (shouldn't happen, but handle gracefully)
|
|
61
|
+
contextMd = response.contextMd;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch (decryptError) {
|
|
65
|
+
// If decryption fails, it might already be plaintext
|
|
66
|
+
contextMd = response.contextMd;
|
|
67
|
+
}
|
|
68
|
+
// Format output with metadata
|
|
69
|
+
const header = `Reading from: ${projectPath}/.recall`;
|
|
70
|
+
return (0, types_js_1.formattedResponse)(header, contextMd);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
if (error instanceof client_js_1.AuthenticationError) {
|
|
74
|
+
return (0, types_js_1.errorResponse)('Authentication failed. Your token may have expired.\n' +
|
|
75
|
+
'Run `recall auth` to reconnect your account.');
|
|
76
|
+
}
|
|
77
|
+
if (error instanceof client_js_1.RecallApiError) {
|
|
78
|
+
if (error.code === 'REPO_NOT_FOUND') {
|
|
79
|
+
return (0, types_js_1.errorResponse)('This repository is not connected to Recall.\n' +
|
|
80
|
+
'Run `recall init` to set up team memory for this repo.');
|
|
81
|
+
}
|
|
82
|
+
return (0, types_js_1.errorResponse)(`API Error: ${error.message}`);
|
|
83
|
+
}
|
|
84
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
85
|
+
return (0, types_js_1.errorResponse)(message);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* getHistory Tool Implementation
|
|
3
|
+
*
|
|
4
|
+
* Fetches context.md + recent session history for the repository.
|
|
5
|
+
* This provides more detail than getContext but uses more tokens.
|
|
6
|
+
*/
|
|
7
|
+
import { type ToolResponse } from './types.js';
|
|
8
|
+
export interface GetHistoryArgs {
|
|
9
|
+
projectPath: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Execute the getHistory tool
|
|
13
|
+
*
|
|
14
|
+
* @param args - Tool arguments (projectPath is required)
|
|
15
|
+
* @returns MCP tool response with context.md + history.md content
|
|
16
|
+
*/
|
|
17
|
+
export declare function getHistory(args: GetHistoryArgs): Promise<ToolResponse>;
|
|
18
|
+
//# sourceMappingURL=getHistory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getHistory.d.ts","sourceRoot":"","sources":["../../src/tools/getHistory.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAqD,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAGlG,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CA8F5E"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* getHistory Tool Implementation
|
|
4
|
+
*
|
|
5
|
+
* Fetches context.md + recent session history for the repository.
|
|
6
|
+
* This provides more detail than getContext but uses more tokens.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.getHistory = getHistory;
|
|
10
|
+
const client_js_1 = require("../api/client.js");
|
|
11
|
+
const index_js_1 = require("../config/index.js");
|
|
12
|
+
const index_js_2 = require("../crypto/index.js");
|
|
13
|
+
const types_js_1 = require("./types.js");
|
|
14
|
+
const utils_js_1 = require("./utils.js");
|
|
15
|
+
/**
|
|
16
|
+
* Execute the getHistory tool
|
|
17
|
+
*
|
|
18
|
+
* @param args - Tool arguments (projectPath is required)
|
|
19
|
+
* @returns MCP tool response with context.md + history.md content
|
|
20
|
+
*/
|
|
21
|
+
async function getHistory(args) {
|
|
22
|
+
try {
|
|
23
|
+
// Get API token
|
|
24
|
+
const token = (0, index_js_1.getApiToken)();
|
|
25
|
+
if (!token) {
|
|
26
|
+
return (0, types_js_1.errorResponse)('Not authenticated. Run `recall auth` to connect your account, or set RECALL_API_TOKEN environment variable.');
|
|
27
|
+
}
|
|
28
|
+
// Resolve project path
|
|
29
|
+
const projectPath = (0, utils_js_1.resolveProjectPath)(args.projectPath);
|
|
30
|
+
// Get repo info from git
|
|
31
|
+
const repoInfo = await (0, utils_js_1.getRepoInfo)(projectPath);
|
|
32
|
+
if (!repoInfo) {
|
|
33
|
+
return (0, types_js_1.errorResponse)(`Could not determine repository info for: ${projectPath}\n` +
|
|
34
|
+
'Make sure this is a git repository with a remote origin.');
|
|
35
|
+
}
|
|
36
|
+
// Create API client
|
|
37
|
+
const client = new client_js_1.RecallApiClient({
|
|
38
|
+
baseUrl: (0, index_js_1.getApiBaseUrl)(),
|
|
39
|
+
token,
|
|
40
|
+
});
|
|
41
|
+
// Resolve repo to get repoId and teamId
|
|
42
|
+
const { repoId, teamId } = await client.resolveRepo(repoInfo.fullName, repoInfo.defaultBranch);
|
|
43
|
+
// Get team key (fetch from API if not cached)
|
|
44
|
+
let teamKey = (0, index_js_1.getTeamKey)(teamId);
|
|
45
|
+
if (!teamKey) {
|
|
46
|
+
const keyResponse = await client.getTeamKey(teamId);
|
|
47
|
+
teamKey = keyResponse.encryptionKey;
|
|
48
|
+
(0, index_js_1.setTeamKey)(teamId, teamKey);
|
|
49
|
+
}
|
|
50
|
+
// Fetch history from API
|
|
51
|
+
const response = await client.getHistory(repoId);
|
|
52
|
+
// Decrypt content
|
|
53
|
+
let contextMd;
|
|
54
|
+
let historyMd;
|
|
55
|
+
try {
|
|
56
|
+
// Decrypt context
|
|
57
|
+
if (response.contextMd.startsWith('{') || response.contextMd.includes(':')) {
|
|
58
|
+
contextMd = (0, index_js_2.decryptContent)(response.contextMd, teamKey);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
contextMd = response.contextMd;
|
|
62
|
+
}
|
|
63
|
+
// Decrypt history
|
|
64
|
+
if (response.historyMd.startsWith('{') || response.historyMd.includes(':')) {
|
|
65
|
+
historyMd = (0, index_js_2.decryptContent)(response.historyMd, teamKey);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
historyMd = response.historyMd;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch (decryptError) {
|
|
72
|
+
// If decryption fails, use as-is
|
|
73
|
+
contextMd = response.contextMd;
|
|
74
|
+
historyMd = response.historyMd;
|
|
75
|
+
}
|
|
76
|
+
// Combine context and history
|
|
77
|
+
const combinedContent = `# Recall Context\n\n${contextMd}\n\n---\n\n# Session History\n\n${historyMd}`;
|
|
78
|
+
// Format output with metadata
|
|
79
|
+
const header = `Reading history from: ${projectPath}/.recall (${response.sessionCount} sessions)`;
|
|
80
|
+
return (0, types_js_1.formattedResponse)(header, combinedContent);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
if (error instanceof client_js_1.AuthenticationError) {
|
|
84
|
+
return (0, types_js_1.errorResponse)('Authentication failed. Your token may have expired.\n' +
|
|
85
|
+
'Run `recall auth` to reconnect your account.');
|
|
86
|
+
}
|
|
87
|
+
if (error instanceof client_js_1.RecallApiError) {
|
|
88
|
+
if (error.code === 'REPO_NOT_FOUND') {
|
|
89
|
+
return (0, types_js_1.errorResponse)('This repository is not connected to Recall.\n' +
|
|
90
|
+
'Run `recall init` to set up team memory for this repo.');
|
|
91
|
+
}
|
|
92
|
+
return (0, types_js_1.errorResponse)(`API Error: ${error.message}`);
|
|
93
|
+
}
|
|
94
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
95
|
+
return (0, types_js_1.errorResponse)(message);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* getTranscripts Tool Implementation
|
|
3
|
+
*
|
|
4
|
+
* Fetches full session transcripts (context.md + history.md + transcripts.md).
|
|
5
|
+
* WARNING: This can be very large and use many tokens.
|
|
6
|
+
* Only use when you need complete historical details.
|
|
7
|
+
*/
|
|
8
|
+
import { type ToolResponse } from './types.js';
|
|
9
|
+
export interface GetTranscriptsArgs {
|
|
10
|
+
projectPath: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Execute the getTranscripts tool
|
|
14
|
+
*
|
|
15
|
+
* @param args - Tool arguments (projectPath is required)
|
|
16
|
+
* @returns MCP tool response with full transcripts content
|
|
17
|
+
*/
|
|
18
|
+
export declare function getTranscripts(args: GetTranscriptsArgs): Promise<ToolResponse>;
|
|
19
|
+
//# sourceMappingURL=getTranscripts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getTranscripts.d.ts","sourceRoot":"","sources":["../../src/tools/getTranscripts.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,EAAqD,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAGlG,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,YAAY,CAAC,CA6HpF"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* getTranscripts Tool Implementation
|
|
4
|
+
*
|
|
5
|
+
* Fetches full session transcripts (context.md + history.md + transcripts.md).
|
|
6
|
+
* WARNING: This can be very large and use many tokens.
|
|
7
|
+
* Only use when you need complete historical details.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.getTranscripts = getTranscripts;
|
|
11
|
+
const client_js_1 = require("../api/client.js");
|
|
12
|
+
const index_js_1 = require("../config/index.js");
|
|
13
|
+
const index_js_2 = require("../crypto/index.js");
|
|
14
|
+
const types_js_1 = require("./types.js");
|
|
15
|
+
const utils_js_1 = require("./utils.js");
|
|
16
|
+
/**
|
|
17
|
+
* Execute the getTranscripts tool
|
|
18
|
+
*
|
|
19
|
+
* @param args - Tool arguments (projectPath is required)
|
|
20
|
+
* @returns MCP tool response with full transcripts content
|
|
21
|
+
*/
|
|
22
|
+
async function getTranscripts(args) {
|
|
23
|
+
try {
|
|
24
|
+
// Get API token
|
|
25
|
+
const token = (0, index_js_1.getApiToken)();
|
|
26
|
+
if (!token) {
|
|
27
|
+
return (0, types_js_1.errorResponse)('Not authenticated. Run `recall auth` to connect your account, or set RECALL_API_TOKEN environment variable.');
|
|
28
|
+
}
|
|
29
|
+
// Resolve project path
|
|
30
|
+
const projectPath = (0, utils_js_1.resolveProjectPath)(args.projectPath);
|
|
31
|
+
// Get repo info from git
|
|
32
|
+
const repoInfo = await (0, utils_js_1.getRepoInfo)(projectPath);
|
|
33
|
+
if (!repoInfo) {
|
|
34
|
+
return (0, types_js_1.errorResponse)(`Could not determine repository info for: ${projectPath}\n` +
|
|
35
|
+
'Make sure this is a git repository with a remote origin.');
|
|
36
|
+
}
|
|
37
|
+
// Create API client
|
|
38
|
+
const client = new client_js_1.RecallApiClient({
|
|
39
|
+
baseUrl: (0, index_js_1.getApiBaseUrl)(),
|
|
40
|
+
token,
|
|
41
|
+
});
|
|
42
|
+
// Resolve repo to get repoId and teamId
|
|
43
|
+
const { repoId, teamId } = await client.resolveRepo(repoInfo.fullName, repoInfo.defaultBranch);
|
|
44
|
+
// Get team key (fetch from API if not cached)
|
|
45
|
+
let teamKey = (0, index_js_1.getTeamKey)(teamId);
|
|
46
|
+
if (!teamKey) {
|
|
47
|
+
const keyResponse = await client.getTeamKey(teamId);
|
|
48
|
+
teamKey = keyResponse.encryptionKey;
|
|
49
|
+
(0, index_js_1.setTeamKey)(teamId, teamKey);
|
|
50
|
+
}
|
|
51
|
+
// Fetch transcripts from API
|
|
52
|
+
const response = await client.getTranscripts(repoId);
|
|
53
|
+
// Decrypt all content
|
|
54
|
+
let contextMd;
|
|
55
|
+
let historyMd;
|
|
56
|
+
let transcriptsMd;
|
|
57
|
+
try {
|
|
58
|
+
// Decrypt context
|
|
59
|
+
if (response.contextMd.startsWith('{') || response.contextMd.includes(':')) {
|
|
60
|
+
contextMd = (0, index_js_2.decryptContent)(response.contextMd, teamKey);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
contextMd = response.contextMd;
|
|
64
|
+
}
|
|
65
|
+
// Decrypt history
|
|
66
|
+
if (response.historyMd.startsWith('{') || response.historyMd.includes(':')) {
|
|
67
|
+
historyMd = (0, index_js_2.decryptContent)(response.historyMd, teamKey);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
historyMd = response.historyMd;
|
|
71
|
+
}
|
|
72
|
+
// Decrypt transcripts
|
|
73
|
+
if (response.transcriptsMd.startsWith('{') || response.transcriptsMd.includes(':')) {
|
|
74
|
+
transcriptsMd = (0, index_js_2.decryptContent)(response.transcriptsMd, teamKey);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
transcriptsMd = response.transcriptsMd;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch (decryptError) {
|
|
81
|
+
// If decryption fails, use as-is
|
|
82
|
+
contextMd = response.contextMd;
|
|
83
|
+
historyMd = response.historyMd;
|
|
84
|
+
transcriptsMd = response.transcriptsMd;
|
|
85
|
+
}
|
|
86
|
+
// Combine all content with warning
|
|
87
|
+
const combinedContent = [
|
|
88
|
+
`# TOKEN WARNING`,
|
|
89
|
+
``,
|
|
90
|
+
response.tokenWarning,
|
|
91
|
+
``,
|
|
92
|
+
`---`,
|
|
93
|
+
``,
|
|
94
|
+
`# Recall Context`,
|
|
95
|
+
``,
|
|
96
|
+
contextMd,
|
|
97
|
+
``,
|
|
98
|
+
`---`,
|
|
99
|
+
``,
|
|
100
|
+
`# Session History`,
|
|
101
|
+
``,
|
|
102
|
+
historyMd,
|
|
103
|
+
``,
|
|
104
|
+
`---`,
|
|
105
|
+
``,
|
|
106
|
+
`# Full Transcripts`,
|
|
107
|
+
``,
|
|
108
|
+
transcriptsMd,
|
|
109
|
+
].join('\n');
|
|
110
|
+
// Format output
|
|
111
|
+
const header = `Reading full transcripts from: ${projectPath}/.recall`;
|
|
112
|
+
return (0, types_js_1.formattedResponse)(header, combinedContent);
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
if (error instanceof client_js_1.AuthenticationError) {
|
|
116
|
+
return (0, types_js_1.errorResponse)('Authentication failed. Your token may have expired.\n' +
|
|
117
|
+
'Run `recall auth` to reconnect your account.');
|
|
118
|
+
}
|
|
119
|
+
if (error instanceof client_js_1.RecallApiError) {
|
|
120
|
+
if (error.code === 'REPO_NOT_FOUND') {
|
|
121
|
+
return (0, types_js_1.errorResponse)('This repository is not connected to Recall.\n' +
|
|
122
|
+
'Run `recall init` to set up team memory for this repo.');
|
|
123
|
+
}
|
|
124
|
+
return (0, types_js_1.errorResponse)(`API Error: ${error.message}`);
|
|
125
|
+
}
|
|
126
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
127
|
+
return (0, types_js_1.errorResponse)(message);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Implementations
|
|
3
|
+
*
|
|
4
|
+
* Exports all MCP tool implementations.
|
|
5
|
+
*/
|
|
6
|
+
export { getContext, type GetContextArgs } from './getContext.js';
|
|
7
|
+
export { getHistory, type GetHistoryArgs } from './getHistory.js';
|
|
8
|
+
export { getTranscripts, type GetTranscriptsArgs } from './getTranscripts.js';
|
|
9
|
+
export { saveSession, type SaveSessionArgs } from './saveSession.js';
|
|
10
|
+
export { logDecision, type LogDecisionArgs } from './logDecision.js';
|
|
11
|
+
export { type ToolResponse, successResponse, errorResponse, formattedResponse } from './types.js';
|
|
12
|
+
export * from './utils.js';
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EAAE,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,KAAK,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAClG,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Tool Implementations
|
|
4
|
+
*
|
|
5
|
+
* Exports all MCP tool implementations.
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
19
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
20
|
+
};
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.formattedResponse = exports.errorResponse = exports.successResponse = exports.logDecision = exports.saveSession = exports.getTranscripts = exports.getHistory = exports.getContext = void 0;
|
|
23
|
+
var getContext_js_1 = require("./getContext.js");
|
|
24
|
+
Object.defineProperty(exports, "getContext", { enumerable: true, get: function () { return getContext_js_1.getContext; } });
|
|
25
|
+
var getHistory_js_1 = require("./getHistory.js");
|
|
26
|
+
Object.defineProperty(exports, "getHistory", { enumerable: true, get: function () { return getHistory_js_1.getHistory; } });
|
|
27
|
+
var getTranscripts_js_1 = require("./getTranscripts.js");
|
|
28
|
+
Object.defineProperty(exports, "getTranscripts", { enumerable: true, get: function () { return getTranscripts_js_1.getTranscripts; } });
|
|
29
|
+
var saveSession_js_1 = require("./saveSession.js");
|
|
30
|
+
Object.defineProperty(exports, "saveSession", { enumerable: true, get: function () { return saveSession_js_1.saveSession; } });
|
|
31
|
+
var logDecision_js_1 = require("./logDecision.js");
|
|
32
|
+
Object.defineProperty(exports, "logDecision", { enumerable: true, get: function () { return logDecision_js_1.logDecision; } });
|
|
33
|
+
var types_js_1 = require("./types.js");
|
|
34
|
+
Object.defineProperty(exports, "successResponse", { enumerable: true, get: function () { return types_js_1.successResponse; } });
|
|
35
|
+
Object.defineProperty(exports, "errorResponse", { enumerable: true, get: function () { return types_js_1.errorResponse; } });
|
|
36
|
+
Object.defineProperty(exports, "formattedResponse", { enumerable: true, get: function () { return types_js_1.formattedResponse; } });
|
|
37
|
+
__exportStar(require("./utils.js"), exports);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* logDecision Tool Implementation
|
|
3
|
+
*
|
|
4
|
+
* Logs an important decision made during coding.
|
|
5
|
+
* Quick way to capture why something was done.
|
|
6
|
+
*/
|
|
7
|
+
import { type ToolResponse } from './types.js';
|
|
8
|
+
export interface LogDecisionArgs {
|
|
9
|
+
decision: string;
|
|
10
|
+
reasoning: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Execute the logDecision tool
|
|
14
|
+
*
|
|
15
|
+
* @param args - Tool arguments with decision and reasoning
|
|
16
|
+
* @returns MCP tool response with confirmation
|
|
17
|
+
*/
|
|
18
|
+
export declare function logDecision(args: LogDecisionArgs): Promise<ToolResponse>;
|
|
19
|
+
//# sourceMappingURL=logDecision.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logDecision.d.ts","sourceRoot":"","sources":["../../src/tools/logDecision.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAkC,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAI/E,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC,CA6F9E"}
|