@tacitai/mcp-server 0.1.1 → 0.3.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/auth.d.ts +32 -0
- package/dist/auth.js +64 -0
- package/dist/client.d.ts +60 -5
- package/dist/client.js +234 -53
- package/dist/index.js +130 -106
- package/dist/oauth.d.ts +115 -0
- package/dist/oauth.js +619 -0
- package/dist/prompts.d.ts +2 -0
- package/dist/prompts.js +12 -0
- package/dist/setup.d.ts +28 -5
- package/dist/setup.js +266 -59
- package/dist/tools/agents.d.ts +277 -0
- package/dist/tools/agents.js +335 -0
- package/dist/tools/annotations.d.ts +117 -0
- package/dist/tools/annotations.js +130 -0
- package/dist/tools/artifacts.d.ts +178 -8
- package/dist/tools/artifacts.js +372 -81
- package/dist/tools/chronicle.d.ts +3 -0
- package/dist/tools/chronicle.js +165 -0
- package/dist/tools/connector_write_back.d.ts +3 -0
- package/dist/tools/connector_write_back.js +27 -0
- package/dist/tools/converse.d.ts +10 -0
- package/dist/tools/converse.js +88 -0
- package/dist/tools/crews.d.ts +3 -0
- package/dist/tools/crews.js +115 -0
- package/dist/tools/drafts.d.ts +83 -0
- package/dist/tools/drafts.js +86 -0
- package/dist/tools/errors.d.ts +15 -0
- package/dist/tools/errors.js +21 -0
- package/dist/tools/export.d.ts +54 -0
- package/dist/tools/export.js +55 -0
- package/dist/tools/gm.d.ts +214 -0
- package/dist/tools/gm.js +198 -0
- package/dist/tools/ingest.d.ts +58 -4
- package/dist/tools/ingest.js +109 -76
- package/dist/tools/kb.d.ts +544 -0
- package/dist/tools/kb.js +687 -0
- package/dist/tools/lake-structure.d.ts +3 -0
- package/dist/tools/lake-structure.js +126 -0
- package/dist/tools/lake.d.ts +932 -0
- package/dist/tools/lake.js +1017 -0
- package/dist/tools/move.d.ts +200 -0
- package/dist/tools/move.js +96 -0
- package/dist/tools/outbox.d.ts +274 -0
- package/dist/tools/outbox.js +223 -0
- package/dist/tools/people.d.ts +3 -0
- package/dist/tools/people.js +59 -0
- package/dist/tools/pyramid.d.ts +554 -0
- package/dist/tools/pyramid.js +758 -0
- package/dist/tools/recall.d.ts +2 -0
- package/dist/tools/recall.js +28 -17
- package/dist/tools/registry.d.ts +17 -0
- package/dist/tools/registry.js +199 -0
- package/dist/tools/research.d.ts +47 -0
- package/dist/tools/research.js +575 -0
- package/dist/tools/search.d.ts +9 -0
- package/dist/tools/search.js +86 -25
- package/dist/tools/sharing.d.ts +63 -0
- package/dist/tools/sharing.js +157 -0
- package/dist/tools/skills.d.ts +9 -0
- package/dist/tools/skills.js +98 -0
- package/dist/tools/synthesize.d.ts +54 -2
- package/dist/tools/synthesize.js +80 -23
- package/dist/tools/web-url.d.ts +57 -0
- package/dist/tools/web-url.js +74 -0
- package/dist/tools/workspaces.d.ts +3 -0
- package/dist/tools/workspaces.js +47 -0
- package/dist/transport.d.ts +9 -0
- package/dist/transport.js +209 -0
- package/package.json +5 -4
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
/**
|
|
3
|
+
* FEAT-111 Wave 2 — Outbox MCP tools:
|
|
4
|
+
* tacit_outbox_write — Write an envelope to the local outbox queue
|
|
5
|
+
* tacit_outbox_flush — Trigger an immediate drain of pending envelopes
|
|
6
|
+
* tacit_outbox_status — Check outbox queue status (pending/delivered/failed counts)
|
|
7
|
+
*/
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
import * as fs from 'fs';
|
|
10
|
+
import * as path from 'path';
|
|
11
|
+
import * as crypto from 'crypto';
|
|
12
|
+
import { execSync } from 'child_process';
|
|
13
|
+
// ─── tacit_outbox_write ──────────────────────────────────────────────────────
|
|
14
|
+
export const outboxWriteInputSchema = z.object({
|
|
15
|
+
title: z.string().min(1).describe('Title of the content'),
|
|
16
|
+
content: z.string().min(1).describe('Content body (markdown or plain text)'),
|
|
17
|
+
placement: z.object({
|
|
18
|
+
kb: z.object({
|
|
19
|
+
collections: z.array(z.union([
|
|
20
|
+
z.string().uuid(),
|
|
21
|
+
z.object({
|
|
22
|
+
name: z.string().min(1),
|
|
23
|
+
slug: z.string().optional(),
|
|
24
|
+
}),
|
|
25
|
+
])),
|
|
26
|
+
}).optional(),
|
|
27
|
+
pyramid: z.object({
|
|
28
|
+
portfolio_id: z.string().uuid().optional(),
|
|
29
|
+
program_id: z.string().uuid().optional(),
|
|
30
|
+
dossiers: z.array(z.union([
|
|
31
|
+
z.string().uuid(),
|
|
32
|
+
z.object({ name: z.string().min(1) }),
|
|
33
|
+
])).optional(),
|
|
34
|
+
}).optional(),
|
|
35
|
+
}).describe('Placement envelope — at least one of kb or pyramid required'),
|
|
36
|
+
content_origin: z.enum(['agent', 'human', 'git_sync']).default('agent'),
|
|
37
|
+
source_agent_id: z.string().optional().describe('Identifier for the source agent'),
|
|
38
|
+
autonomy_level: z.enum(['MENTAT', 'TWIN']).optional().describe('Agent autonomy level (SCRIBE excluded)'),
|
|
39
|
+
idempotency_key: z.string().optional().describe('Dedup key — same key = same content'),
|
|
40
|
+
replaces_object_id: z.string().uuid().optional().describe('UUID of object this replaces'),
|
|
41
|
+
content_format: z.enum(['MARKDOWN', 'HTML', 'PLAIN_TEXT']).default('MARKDOWN'),
|
|
42
|
+
});
|
|
43
|
+
export const OUTBOX_WRITE_TOOL_DEF = {
|
|
44
|
+
name: 'tacit_outbox_write',
|
|
45
|
+
description: 'Write content to the Tacit outbox queue (.tacit/outbox/pending/). ' +
|
|
46
|
+
'Content is drained to the API within 60s by the LaunchAgent, or immediately via tacit_outbox_flush. ' +
|
|
47
|
+
'Requires placement (at least one of kb or pyramid). SCRIBE autonomy level cannot write.',
|
|
48
|
+
inputSchema: {
|
|
49
|
+
type: 'object',
|
|
50
|
+
properties: {
|
|
51
|
+
title: { type: 'string', description: 'Content title' },
|
|
52
|
+
content: { type: 'string', description: 'Content body' },
|
|
53
|
+
placement: {
|
|
54
|
+
type: 'object',
|
|
55
|
+
description: 'Placement envelope (kb and/or pyramid)',
|
|
56
|
+
properties: {
|
|
57
|
+
kb: {
|
|
58
|
+
type: 'object',
|
|
59
|
+
properties: {
|
|
60
|
+
collections: {
|
|
61
|
+
type: 'array',
|
|
62
|
+
items: { oneOf: [{ type: 'string' }, { type: 'object', properties: { name: { type: 'string' } }, required: ['name'] }] },
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
pyramid: {
|
|
67
|
+
type: 'object',
|
|
68
|
+
properties: {
|
|
69
|
+
portfolio_id: { type: 'string' },
|
|
70
|
+
program_id: { type: 'string' },
|
|
71
|
+
dossiers: { type: 'array', items: { oneOf: [{ type: 'string' }, { type: 'object' }] } },
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
content_origin: { type: 'string', enum: ['agent', 'human', 'git_sync'], default: 'agent' },
|
|
77
|
+
source_agent_id: { type: 'string', description: 'Source agent identifier' },
|
|
78
|
+
autonomy_level: { type: 'string', enum: ['MENTAT', 'TWIN'] },
|
|
79
|
+
idempotency_key: { type: 'string', description: 'Deduplication key' },
|
|
80
|
+
replaces_object_id: { type: 'string', description: 'UUID of object this replaces' },
|
|
81
|
+
content_format: { type: 'string', enum: ['MARKDOWN', 'HTML', 'PLAIN_TEXT'], default: 'MARKDOWN' },
|
|
82
|
+
},
|
|
83
|
+
required: ['title', 'content', 'placement'],
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
function getOutboxDir() {
|
|
87
|
+
return path.resolve('.tacit', 'outbox');
|
|
88
|
+
}
|
|
89
|
+
export async function handleOutboxWrite(args) {
|
|
90
|
+
const parsed = outboxWriteInputSchema.safeParse(args);
|
|
91
|
+
if (!parsed.success) {
|
|
92
|
+
return { content: [{ type: 'text', text: `Invalid input: ${parsed.error.message}` }], isError: true };
|
|
93
|
+
}
|
|
94
|
+
const input = parsed.data;
|
|
95
|
+
if (!input.placement.kb && !input.placement.pyramid) {
|
|
96
|
+
return { content: [{ type: 'text', text: 'Placement must include at least one of kb or pyramid' }], isError: true };
|
|
97
|
+
}
|
|
98
|
+
const outboxDir = getOutboxDir();
|
|
99
|
+
const pendingDir = path.join(outboxDir, 'pending');
|
|
100
|
+
try {
|
|
101
|
+
fs.mkdirSync(pendingDir, { recursive: true });
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
return { content: [{ type: 'text', text: `Failed to create outbox directory: ${err}` }], isError: true };
|
|
105
|
+
}
|
|
106
|
+
const idempotencyKey = input.idempotency_key || crypto.randomUUID();
|
|
107
|
+
const envelope = {
|
|
108
|
+
title: input.title,
|
|
109
|
+
content: input.content,
|
|
110
|
+
content_format: input.content_format,
|
|
111
|
+
placement: input.placement,
|
|
112
|
+
content_origin: input.content_origin,
|
|
113
|
+
source_agent_id: input.source_agent_id,
|
|
114
|
+
autonomy_level: input.autonomy_level,
|
|
115
|
+
idempotency_key: idempotencyKey,
|
|
116
|
+
replaces_object_id: input.replaces_object_id,
|
|
117
|
+
queued_at: new Date().toISOString(),
|
|
118
|
+
};
|
|
119
|
+
const filename = `${Date.now()}_${idempotencyKey.slice(0, 8)}.json`;
|
|
120
|
+
const filepath = path.join(pendingDir, filename);
|
|
121
|
+
// Security: validate filename has no path traversal
|
|
122
|
+
if (filename.includes('..') || filename.includes('/')) {
|
|
123
|
+
return { content: [{ type: 'text', text: 'Invalid envelope filename' }], isError: true };
|
|
124
|
+
}
|
|
125
|
+
try {
|
|
126
|
+
fs.writeFileSync(filepath, JSON.stringify(envelope, null, 2), 'utf-8');
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
return { content: [{ type: 'text', text: `Failed to write envelope: ${err}` }], isError: true };
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
content: [{
|
|
133
|
+
type: 'text',
|
|
134
|
+
text: JSON.stringify({
|
|
135
|
+
status: 'queued',
|
|
136
|
+
envelope_path: filepath,
|
|
137
|
+
idempotency_key: idempotencyKey,
|
|
138
|
+
}),
|
|
139
|
+
}],
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
// ─── tacit_outbox_flush ──────────────────────────────────────────────────────
|
|
143
|
+
export const OUTBOX_FLUSH_TOOL_DEF = {
|
|
144
|
+
name: 'tacit_outbox_flush',
|
|
145
|
+
description: 'Immediately drain all pending outbox envelopes to the Tacit API. ' +
|
|
146
|
+
'Equivalent to running scripts/outbox-drain.sh.',
|
|
147
|
+
inputSchema: {
|
|
148
|
+
type: 'object',
|
|
149
|
+
properties: {},
|
|
150
|
+
required: [],
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
export async function handleOutboxFlush(_args) {
|
|
154
|
+
const drainScript = path.resolve('scripts', 'outbox-drain.sh');
|
|
155
|
+
if (!fs.existsSync(drainScript)) {
|
|
156
|
+
return { content: [{ type: 'text', text: 'Drain script not found at scripts/outbox-drain.sh' }], isError: true };
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
const output = execSync(`bash "${drainScript}"`, {
|
|
160
|
+
timeout: 60_000,
|
|
161
|
+
encoding: 'utf-8',
|
|
162
|
+
env: { ...process.env },
|
|
163
|
+
});
|
|
164
|
+
return { content: [{ type: 'text', text: output || 'Drain complete (no pending envelopes)' }] };
|
|
165
|
+
}
|
|
166
|
+
catch (err) {
|
|
167
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
168
|
+
return { content: [{ type: 'text', text: `Drain failed: ${msg}` }], isError: true };
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// ─── tacit_outbox_status ─────────────────────────────────────────────────────
|
|
172
|
+
export const OUTBOX_STATUS_TOOL_DEF = {
|
|
173
|
+
name: 'tacit_outbox_status',
|
|
174
|
+
description: 'Check the status of the outbox queue: counts of pending, delivered, and failed envelopes.',
|
|
175
|
+
inputSchema: {
|
|
176
|
+
type: 'object',
|
|
177
|
+
properties: {},
|
|
178
|
+
required: [],
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
export async function handleOutboxStatus(_args) {
|
|
182
|
+
const outboxDir = getOutboxDir();
|
|
183
|
+
const countFiles = (dir) => {
|
|
184
|
+
try {
|
|
185
|
+
return fs.readdirSync(dir).filter((f) => f.endsWith('.json')).length;
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
return 0;
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
const status = {
|
|
192
|
+
pending: countFiles(path.join(outboxDir, 'pending')),
|
|
193
|
+
delivered: countFiles(path.join(outboxDir, 'delivered')),
|
|
194
|
+
failed: countFiles(path.join(outboxDir, 'failed')),
|
|
195
|
+
};
|
|
196
|
+
return {
|
|
197
|
+
content: [{
|
|
198
|
+
type: 'text',
|
|
199
|
+
text: JSON.stringify(status),
|
|
200
|
+
}],
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
export function registerOutboxTools(server) {
|
|
204
|
+
server.tool('tacit_outbox_write', 'Write content to the Tacit outbox queue (.tacit/outbox/pending/).', {
|
|
205
|
+
title: z.string().min(1).describe('Title of the content'),
|
|
206
|
+
content: z.string().min(1).describe('Content body'),
|
|
207
|
+
placement: z.record(z.unknown()).describe('Placement envelope — at least one of kb or pyramid required'),
|
|
208
|
+
content_origin: z.enum(['agent', 'human', 'git_sync']).default('agent'),
|
|
209
|
+
source_agent_id: z.string().optional().describe('Source agent identifier'),
|
|
210
|
+
autonomy_level: z.enum(['MENTAT', 'TWIN']).optional().describe('Agent autonomy level'),
|
|
211
|
+
idempotency_key: z.string().optional().describe('Dedup key'),
|
|
212
|
+
replaces_object_id: z.string().optional().describe('UUID of object this replaces'),
|
|
213
|
+
content_format: z.enum(['MARKDOWN', 'HTML', 'PLAIN_TEXT']).default('MARKDOWN'),
|
|
214
|
+
}, async (args) => {
|
|
215
|
+
return handleOutboxWrite(args);
|
|
216
|
+
});
|
|
217
|
+
server.tool('tacit_outbox_flush', 'Immediately drain all pending outbox envelopes to the Tacit API.', {}, async () => {
|
|
218
|
+
return handleOutboxFlush({});
|
|
219
|
+
});
|
|
220
|
+
server.tool('tacit_outbox_status', 'Check outbox queue status (pending/delivered/failed counts).', {}, async () => {
|
|
221
|
+
return handleOutboxStatus({});
|
|
222
|
+
});
|
|
223
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { TacitApiError } from '../client.js';
|
|
3
|
+
import { success, error } from './errors.js';
|
|
4
|
+
export function registerPeopleTools(server, getClient) {
|
|
5
|
+
server.tool('tacit_list_people', 'List all people in the current workspace.', {}, async () => {
|
|
6
|
+
try {
|
|
7
|
+
const client = await getClient();
|
|
8
|
+
const data = await client.request('GET', '/api/v1/people');
|
|
9
|
+
return success(data);
|
|
10
|
+
}
|
|
11
|
+
catch (e) {
|
|
12
|
+
if (e instanceof TacitApiError)
|
|
13
|
+
return error(e.message);
|
|
14
|
+
return error(`Unexpected error: ${e instanceof Error ? e.message : String(e)}`);
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
server.tool('tacit_get_person', 'Get a person by ID.', {
|
|
18
|
+
person_id: z.string().uuid().describe('Person UUID'),
|
|
19
|
+
}, async (args) => {
|
|
20
|
+
try {
|
|
21
|
+
const client = await getClient();
|
|
22
|
+
const data = await client.request('GET', `/api/v1/people/${args.person_id}`);
|
|
23
|
+
return success(data);
|
|
24
|
+
}
|
|
25
|
+
catch (e) {
|
|
26
|
+
if (e instanceof TacitApiError)
|
|
27
|
+
return error(e.message);
|
|
28
|
+
return error(`Unexpected error: ${e instanceof Error ? e.message : String(e)}`);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
server.tool('tacit_create_person', 'Create a new person record.', {
|
|
32
|
+
name: z.string().describe("Person's name"),
|
|
33
|
+
url: z.string().url().optional().describe("Person's URL (LinkedIn, website, etc.)"),
|
|
34
|
+
email: z.string().email().optional().describe("Person's email address"),
|
|
35
|
+
}, async (args) => {
|
|
36
|
+
try {
|
|
37
|
+
const client = await getClient();
|
|
38
|
+
const data = await client.request('POST', '/api/v1/people', args);
|
|
39
|
+
return success(data);
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
if (e instanceof TacitApiError)
|
|
43
|
+
return error(e.message);
|
|
44
|
+
return error(`Unexpected error: ${e instanceof Error ? e.message : String(e)}`);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
server.tool('tacit_get_myself', "Get the authenticated user's own person record.", {}, async () => {
|
|
48
|
+
try {
|
|
49
|
+
const client = await getClient();
|
|
50
|
+
const data = await client.request('GET', '/api/v1/people/myself');
|
|
51
|
+
return success(data);
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
if (e instanceof TacitApiError)
|
|
55
|
+
return error(e.message);
|
|
56
|
+
return error(`Unexpected error: ${e instanceof Error ? e.message : String(e)}`);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|