@tacitai/mcp-server 0.1.1 → 0.2.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.
Files changed (68) hide show
  1. package/dist/auth.d.ts +32 -0
  2. package/dist/auth.js +64 -0
  3. package/dist/client.d.ts +60 -5
  4. package/dist/client.js +234 -53
  5. package/dist/index.js +128 -106
  6. package/dist/oauth.d.ts +115 -0
  7. package/dist/oauth.js +619 -0
  8. package/dist/prompts.d.ts +2 -0
  9. package/dist/prompts.js +12 -0
  10. package/dist/setup.d.ts +28 -5
  11. package/dist/setup.js +266 -59
  12. package/dist/tools/agents.d.ts +277 -0
  13. package/dist/tools/agents.js +335 -0
  14. package/dist/tools/annotations.d.ts +117 -0
  15. package/dist/tools/annotations.js +130 -0
  16. package/dist/tools/artifacts.d.ts +178 -8
  17. package/dist/tools/artifacts.js +372 -81
  18. package/dist/tools/chronicle.d.ts +3 -0
  19. package/dist/tools/chronicle.js +165 -0
  20. package/dist/tools/connector_write_back.d.ts +3 -0
  21. package/dist/tools/connector_write_back.js +27 -0
  22. package/dist/tools/converse.d.ts +10 -0
  23. package/dist/tools/converse.js +88 -0
  24. package/dist/tools/crews.d.ts +3 -0
  25. package/dist/tools/crews.js +115 -0
  26. package/dist/tools/drafts.d.ts +83 -0
  27. package/dist/tools/drafts.js +86 -0
  28. package/dist/tools/errors.d.ts +15 -0
  29. package/dist/tools/errors.js +21 -0
  30. package/dist/tools/export.d.ts +54 -0
  31. package/dist/tools/export.js +55 -0
  32. package/dist/tools/gm.d.ts +214 -0
  33. package/dist/tools/gm.js +198 -0
  34. package/dist/tools/ingest.d.ts +58 -4
  35. package/dist/tools/ingest.js +109 -76
  36. package/dist/tools/kb.d.ts +544 -0
  37. package/dist/tools/kb.js +687 -0
  38. package/dist/tools/lake-structure.d.ts +3 -0
  39. package/dist/tools/lake-structure.js +126 -0
  40. package/dist/tools/lake.d.ts +932 -0
  41. package/dist/tools/lake.js +1017 -0
  42. package/dist/tools/move.d.ts +200 -0
  43. package/dist/tools/move.js +96 -0
  44. package/dist/tools/outbox.d.ts +274 -0
  45. package/dist/tools/outbox.js +223 -0
  46. package/dist/tools/people.d.ts +3 -0
  47. package/dist/tools/people.js +59 -0
  48. package/dist/tools/pyramid.d.ts +554 -0
  49. package/dist/tools/pyramid.js +758 -0
  50. package/dist/tools/recall.d.ts +2 -0
  51. package/dist/tools/recall.js +28 -17
  52. package/dist/tools/registry.d.ts +17 -0
  53. package/dist/tools/registry.js +197 -0
  54. package/dist/tools/research.d.ts +47 -0
  55. package/dist/tools/research.js +575 -0
  56. package/dist/tools/search.d.ts +9 -0
  57. package/dist/tools/search.js +86 -25
  58. package/dist/tools/sharing.d.ts +63 -0
  59. package/dist/tools/sharing.js +157 -0
  60. package/dist/tools/synthesize.d.ts +54 -2
  61. package/dist/tools/synthesize.js +80 -23
  62. package/dist/tools/web-url.d.ts +57 -0
  63. package/dist/tools/web-url.js +74 -0
  64. package/dist/tools/workspaces.d.ts +3 -0
  65. package/dist/tools/workspaces.js +47 -0
  66. package/dist/transport.d.ts +9 -0
  67. package/dist/transport.js +209 -0
  68. package/package.json +5 -4
package/dist/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env node
2
- "use strict";
3
2
  // SPDX-License-Identifier: MIT
4
3
  /**
5
4
  * @tacit/mcp-server — stdio MCP server
@@ -22,54 +21,48 @@
22
21
  * `tacit-mcp-server setup` is reserved for MV-1057h setup wizard.
23
22
  * Currently prints a placeholder message and exits 0.
24
23
  */
25
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
26
- if (k2 === undefined) k2 = k;
27
- var desc = Object.getOwnPropertyDescriptor(m, k);
28
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
29
- desc = { enumerable: true, get: function() { return m[k]; } };
30
- }
31
- Object.defineProperty(o, k2, desc);
32
- }) : (function(o, m, k, k2) {
33
- if (k2 === undefined) k2 = k;
34
- o[k2] = m[k];
35
- }));
36
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
37
- Object.defineProperty(o, "default", { enumerable: true, value: v });
38
- }) : function(o, v) {
39
- o["default"] = v;
40
- });
41
- var __importStar = (this && this.__importStar) || (function () {
42
- var ownKeys = function(o) {
43
- ownKeys = Object.getOwnPropertyNames || function (o) {
44
- var ar = [];
45
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
46
- return ar;
47
- };
48
- return ownKeys(o);
49
- };
50
- return function (mod) {
51
- if (mod && mod.__esModule) return mod;
52
- var result = {};
53
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
54
- __setModuleDefault(result, mod);
55
- return result;
56
- };
57
- })();
58
- Object.defineProperty(exports, "__esModule", { value: true });
59
- const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
60
- const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
61
- const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
62
- const semver = __importStar(require("semver"));
63
- const path = __importStar(require("path"));
64
- const fs = __importStar(require("fs"));
65
- // Tool handlers
66
- const search_js_1 = require("./tools/search.js");
67
- const synthesize_js_1 = require("./tools/synthesize.js");
68
- const recall_js_1 = require("./tools/recall.js");
69
- const artifacts_js_1 = require("./tools/artifacts.js");
70
- const ingest_js_1 = require("./tools/ingest.js");
71
- // Setup wizard (MV-1057h)
72
- const setup_js_1 = require("./setup.js");
24
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
25
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
26
+ import * as semver from 'semver';
27
+ import * as path from 'path';
28
+ import * as fs from 'fs';
29
+ import * as os from 'os';
30
+ import { fileURLToPath } from 'url';
31
+ import { TacitClient, getClient as getModuleClient } from './client.js';
32
+ import { startHttpTransport } from './transport.js';
33
+ // Tool registration modules
34
+ import { registerSearchTools } from './tools/search.js';
35
+ import { registerSynthesizeTools } from './tools/synthesize.js';
36
+ import { registerConverseTools } from './tools/converse.js';
37
+ import { registerConnectorWriteBackTools } from './tools/connector_write_back.js';
38
+ import { registerRecallTools } from './tools/recall.js';
39
+ import { registerArtifactTools } from './tools/artifacts.js';
40
+ import { registerDraftTools } from './tools/drafts.js';
41
+ import { registerIngestTools } from './tools/ingest.js';
42
+ import { registerOutboxTools } from './tools/outbox.js';
43
+ import { registerAnnotationTools } from './tools/annotations.js';
44
+ import { registerExportTools } from './tools/export.js';
45
+ import { registerMoveTools } from './tools/move.js';
46
+ import { registerAgentTools } from './tools/agents.js';
47
+ import { registerPyramidTools } from './tools/pyramid.js';
48
+ import { registerSharingTools } from './tools/sharing.js';
49
+ import { registerKbTools } from './tools/kb.js';
50
+ import { registerLakeTools } from './tools/lake.js';
51
+ import { registerWebUrlTools } from './tools/web-url.js';
52
+ import { registerWorkspaceTools } from './tools/workspaces.js';
53
+ import { registerChronicleTools } from './tools/chronicle.js';
54
+ import { registerCrewTools } from './tools/crews.js';
55
+ import { registerPeopleTools } from './tools/people.js';
56
+ import { registerLakeStructureTools } from './tools/lake-structure.js';
57
+ import { registerResearchTools } from './tools/research.js';
58
+ import { registerGmTools } from './tools/gm.js';
59
+ import { registerPrompts } from './prompts.js';
60
+ import { getRequestPrincipal } from './client.js';
61
+ // Setup wizard (MV-1057h / W5)
62
+ import { setup, profileToEnvVar } from './setup.js';
63
+ // ─── ESM __dirname replacement ───────────────────────────────────────────────
64
+ const __filename = fileURLToPath(import.meta.url);
65
+ const __dirname = path.dirname(__filename);
73
66
  // ─── Compatibility guard ──────────────────────────────────────────────────────
74
67
  function checkCompatibility() {
75
68
  const pkgPath = path.join(__dirname, '..', 'package.json');
@@ -78,13 +71,11 @@ function checkCompatibility() {
78
71
  pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
79
72
  }
80
73
  catch {
81
- // Non-fatal if package.json cannot be read at runtime.
82
74
  return;
83
75
  }
84
76
  const compat = pkg['compatibility'];
85
77
  const coreArtifactRange = compat?.['coreArtifact'];
86
78
  if (typeof coreArtifactRange === 'string') {
87
- // Print range for oracle D4 grep.
88
79
  process.stderr.write(`COMPAT_RANGE: ${coreArtifactRange}\n`);
89
80
  const coreVersion = process.env['TACIT_CORE_VERSION'];
90
81
  if (coreVersion) {
@@ -97,69 +88,100 @@ function checkCompatibility() {
97
88
  }
98
89
  }
99
90
  }
100
- // ─── Tool registry ────────────────────────────────────────────────────────────
101
- const TOOLS = [
102
- search_js_1.SEARCH_TOOL_DEF,
103
- synthesize_js_1.SYNTHESIZE_TOOL_DEF,
104
- recall_js_1.RECALL_TOOL_DEF,
105
- artifacts_js_1.ARTIFACT_LIST_TOOL_DEF,
106
- artifacts_js_1.ARTIFACT_CREATE_TOOL_DEF,
107
- artifacts_js_1.ARTIFACT_UPDATE_TOOL_DEF,
108
- artifacts_js_1.ARTIFACT_PUBLISH_TOOL_DEF,
109
- ingest_js_1.INGEST_FILE_TOOL_DEF,
110
- ingest_js_1.INGEST_URL_TOOL_DEF,
111
- ];
112
- async function dispatchTool(name, args) {
113
- switch (name) {
114
- case 'tacit_search':
115
- return (0, search_js_1.handleSearch)(args);
116
- case 'tacit_synthesize':
117
- case 'tacit_ask':
118
- case 'tacit_compose':
119
- return (0, synthesize_js_1.handleSynthesize)(args);
120
- case 'tacit_recall':
121
- return (0, recall_js_1.handleRecall)(args);
122
- case 'tacit_artifact_list':
123
- return (0, artifacts_js_1.handleArtifactList)(args);
124
- case 'tacit_artifact_create':
125
- return (0, artifacts_js_1.handleArtifactCreate)(args);
126
- case 'tacit_artifact_update':
127
- return (0, artifacts_js_1.handleArtifactUpdate)(args);
128
- case 'tacit_artifact_publish':
129
- return (0, artifacts_js_1.handleArtifactPublish)(args);
130
- case 'tacit_ingest_file':
131
- return (0, ingest_js_1.handleIngestFile)(args);
132
- case 'tacit_ingest_url':
133
- return (0, ingest_js_1.handleIngestUrl)(args);
134
- default:
135
- return {
136
- content: [{ type: 'text', text: `Unknown tool: ${name}` }],
137
- isError: true,
138
- };
91
+ // ─── Profile helpers ──────────────────────────────────────────────────────────
92
+ function parseProfile(argv) {
93
+ for (let i = 0; i < argv.length; i++) {
94
+ if (argv[i] === '--profile' && argv[i + 1] && !argv[i + 1].startsWith('--')) {
95
+ return argv[i + 1];
96
+ }
97
+ }
98
+ return 'tacit';
99
+ }
100
+ function checkProfileExpiry(profile) {
101
+ const metaPath = path.join(os.homedir(), '.tacit', 'profiles', `${profile}.json`);
102
+ if (!fs.existsSync(metaPath)) {
103
+ return;
104
+ }
105
+ let meta;
106
+ try {
107
+ meta = JSON.parse(fs.readFileSync(metaPath, 'utf-8'));
108
+ }
109
+ catch {
110
+ return;
111
+ }
112
+ const expiresAt = typeof meta['expires_at'] === 'string' ? meta['expires_at'] : null;
113
+ if (!expiresAt)
114
+ return;
115
+ const expiresMs = Date.parse(expiresAt);
116
+ if (Number.isNaN(expiresMs))
117
+ return;
118
+ const nowMs = Date.now();
119
+ const diffDays = Math.floor((expiresMs - nowMs) / (1000 * 60 * 60 * 24));
120
+ if (diffDays < 14) {
121
+ const apiUrl = typeof meta['api_url'] === 'string' ? meta['api_url'] : 'https://beta.tacitai.app';
122
+ process.stderr.write(`[TACIT] Developer token expires in ${diffDays} day${diffDays === 1 ? '' : 's'}. ` +
123
+ `Run: npx @tacitai/mcp-server setup --api-url ${apiUrl}\n`);
139
124
  }
140
125
  }
141
126
  // ─── Main ─────────────────────────────────────────────────────────────────────
142
127
  async function run() {
143
- // Handle setup subcommand before starting stdio transport (MV-1057h).
144
128
  if (process.argv[2] === 'setup') {
145
- await (0, setup_js_1.setup)(process.argv.slice(3));
129
+ await setup(process.argv.slice(3));
146
130
  return;
147
131
  }
148
- // Compatibility guard — exits non-zero on version mismatch.
132
+ const profile = parseProfile(process.argv.slice(2));
133
+ const envVarName = profileToEnvVar(profile);
134
+ if (envVarName !== 'TACIT_TOKEN' && process.env[envVarName] && !process.env['TACIT_TOKEN']) {
135
+ process.env['TACIT_TOKEN'] = process.env[envVarName];
136
+ }
137
+ checkProfileExpiry(profile);
149
138
  checkCompatibility();
150
- const server = new index_js_1.Server({ name: '@tacitai/mcp-server', version: '0.1.0' }, { capabilities: { tools: {} } });
151
- // tools/list
152
- server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
153
- tools: TOOLS,
154
- }));
155
- // tools/call
156
- server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
157
- const { name, arguments: args } = request.params;
158
- const result = await dispatchTool(name, args ?? {});
159
- return result;
160
- });
161
- // Wire stdio transport — NOT an HTTP server (D-4/D-10).
162
- const transport = new stdio_js_1.StdioServerTransport();
139
+ const server = new McpServer({ name: '@tacitai/mcp-server', version: '0.2.0' }, { capabilities: { tools: {}, prompts: {} } });
140
+ const isHttpMode = process.env['MCP_TRANSPORT'] === 'http';
141
+ let clientInstance = null;
142
+ const getClient = async () => {
143
+ if (isHttpMode) {
144
+ // Per-request client via AsyncLocalStorage (caller's token)
145
+ return getModuleClient();
146
+ }
147
+ if (!clientInstance) {
148
+ clientInstance = new TacitClient();
149
+ await clientInstance.initialize();
150
+ }
151
+ return clientInstance;
152
+ };
153
+ // Register all tool modules
154
+ registerSearchTools(server, getClient);
155
+ registerSynthesizeTools(server, getClient);
156
+ registerConverseTools(server, getClient);
157
+ registerConnectorWriteBackTools(server, getClient);
158
+ registerRecallTools(server, getClient);
159
+ registerArtifactTools(server, getClient);
160
+ registerDraftTools(server, getClient);
161
+ registerIngestTools(server, getClient);
162
+ registerOutboxTools(server);
163
+ registerAnnotationTools(server, getClient);
164
+ registerExportTools(server, getClient);
165
+ registerMoveTools(server, getClient);
166
+ registerAgentTools(server, getClient);
167
+ registerPyramidTools(server, getClient);
168
+ registerSharingTools(server, getClient);
169
+ registerKbTools(server, getClient);
170
+ registerLakeTools(server, getClient);
171
+ registerWebUrlTools(server);
172
+ registerWorkspaceTools(server, getClient);
173
+ registerChronicleTools(server, getClient);
174
+ registerCrewTools(server, getClient);
175
+ registerPeopleTools(server, getClient);
176
+ registerLakeStructureTools(server, getClient);
177
+ registerGmTools(server, getClient);
178
+ registerResearchTools(server, getClient, getRequestPrincipal);
179
+ registerPrompts(server);
180
+ if (process.env['MCP_TRANSPORT'] === 'http') {
181
+ await startHttpTransport(server);
182
+ return;
183
+ }
184
+ const transport = new StdioServerTransport();
163
185
  await server.connect(transport);
164
186
  }
165
187
  run().catch((err) => {
@@ -0,0 +1,115 @@
1
+ /**
2
+ * OAuth 2.0 Authorization Server for MCP (FEAT-176).
3
+ *
4
+ * Authorization code flow with PKCE S256. In-memory stores for auth codes
5
+ * and access tokens — process restart voids all grants.
6
+ *
7
+ * Security invariants:
8
+ * - PINs, auth codes, and token values are NEVER logged.
9
+ * - OAuth path NEVER falls back to process.env.TACIT_TOKEN.
10
+ * - Unknown client_id → 400 (never redirect to unregistered URI).
11
+ * - code_challenge_method must be S256 (plain rejected).
12
+ */
13
+ import type { IncomingMessage, ServerResponse } from 'node:http';
14
+ export interface OAuthClient {
15
+ client_id: string;
16
+ client_secret?: string;
17
+ redirect_uris: string[];
18
+ client_name: string;
19
+ }
20
+ export interface OAuthTokenInfo {
21
+ user_email: string;
22
+ workspace_id: string;
23
+ tacit_token: string;
24
+ client_id: string;
25
+ }
26
+ interface AuthCodeEntry {
27
+ client_id: string;
28
+ redirect_uri: string;
29
+ code_challenge: string;
30
+ user_email: string;
31
+ workspace_id: string;
32
+ tacit_token: string;
33
+ state: string;
34
+ created_at: number;
35
+ }
36
+ interface CsrfEntry {
37
+ created_at: number;
38
+ client_id: string;
39
+ redirect_uri: string;
40
+ code_challenge: string;
41
+ code_challenge_method: string;
42
+ state: string;
43
+ scope: string;
44
+ }
45
+ export declare function getTokenTtlSeconds(): number;
46
+ export declare function isOAuthEnabled(): boolean;
47
+ export declare function getRegisteredClients(): OAuthClient[];
48
+ export declare function resetClientRegistry(): void;
49
+ export declare function findClient(client_id: string): OAuthClient | undefined;
50
+ export declare function validateRedirectUri(client: OAuthClient, redirect_uri: string): boolean;
51
+ export declare function registerDynamicClient(params: {
52
+ redirect_uris: string[];
53
+ client_name?: string;
54
+ token_endpoint_auth_method?: string;
55
+ }): {
56
+ client_id: string;
57
+ client_secret: string;
58
+ client_id_issued_at: number;
59
+ redirect_uris: string[];
60
+ client_name: string;
61
+ token_endpoint_auth_method: string;
62
+ };
63
+ export declare function issueAuthCode(params: {
64
+ client_id: string;
65
+ redirect_uri: string;
66
+ code_challenge: string;
67
+ user_email: string;
68
+ workspace_id: string;
69
+ tacit_token: string;
70
+ state: string;
71
+ }): string;
72
+ export declare function consumeAuthCode(code: string): AuthCodeEntry | null;
73
+ export declare function issueAccessToken(params: {
74
+ client_id: string;
75
+ user_email: string;
76
+ workspace_id: string;
77
+ tacit_token: string;
78
+ }): {
79
+ access_token: string;
80
+ expires_in: number;
81
+ };
82
+ export declare function validateOAuthToken(token: string): OAuthTokenInfo | null;
83
+ export declare function verifyPkce(code_verifier: string, code_challenge: string): boolean;
84
+ export declare function generateCsrfToken(params: {
85
+ client_id: string;
86
+ redirect_uri: string;
87
+ code_challenge: string;
88
+ code_challenge_method: string;
89
+ state: string;
90
+ scope: string;
91
+ }): string;
92
+ export declare function consumeCsrfToken(token: string): CsrfEntry | null;
93
+ export declare function checkLoginRateLimit(email: string): boolean;
94
+ export declare function getAuthorizationServerMetadata(issuer: string): Record<string, unknown>;
95
+ export declare function getProtectedResourceMetadata(resource: string, issuer: string): Record<string, unknown>;
96
+ export declare function renderLoginPage(params: {
97
+ client_name: string;
98
+ csrf_token: string;
99
+ error?: string;
100
+ }): string;
101
+ export declare function handleAuthorizeGet(req: IncomingMessage, res: ServerResponse): Promise<void>;
102
+ export declare function handleAuthorizePost(req: IncomingMessage, res: ServerResponse, apiUrl: string): Promise<void>;
103
+ export declare function handleTokenExchange(req: IncomingMessage, res: ServerResponse): Promise<void>;
104
+ export declare function handleClientRegistration(req: IncomingMessage, res: ServerResponse): Promise<void>;
105
+ export declare function handleDiscovery(res: ServerResponse, issuer: string): void;
106
+ export declare function handleProtectedResource(res: ServerResponse, resource: string, issuer: string): void;
107
+ export declare function startCleanupInterval(): void;
108
+ export declare function stopCleanupInterval(): void;
109
+ export declare function _testClearStores(): void;
110
+ export declare function _testGetStoreSize(): {
111
+ codes: number;
112
+ tokens: number;
113
+ csrf: number;
114
+ };
115
+ export {};