@kawoou/kadoc-mcp 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/README.md ADDED
@@ -0,0 +1,200 @@
1
+ # kadoc-mcp
2
+
3
+ [![npm version](https://badge.fury.io/js/%40kawoou%2Fkadoc-mcp.svg)](https://www.npmjs.com/package/@kawoou/kadoc-mcp)
4
+
5
+ kadoc-server를 위한 MCP (Model Context Protocol) 클라이언트
6
+
7
+ ## 기능
8
+
9
+ - kadoc-server 문서 CRUD 연동
10
+ - BM25 전문 검색
11
+ - 폴더 관리
12
+ - 봉투 암호화 세션 지원 (X25519 + XSalsa20-Poly1305)
13
+ - 자동 세션 관리
14
+
15
+ ## 설치
16
+
17
+ ```bash
18
+ # 설치 없이 바로 실행
19
+ npx @kawoou/kadoc-mcp
20
+
21
+ # 또는 글로벌 설치
22
+ npm install -g @kawoou/kadoc-mcp
23
+ kadoc-mcp
24
+ ```
25
+
26
+ ## 설정
27
+
28
+ ### 자동 설정 (권장)
29
+
30
+ MCP가 처음 실행될 때 설정 파일이 없으면 자동으로 사용자를 등록하고 `~/.kadoc.json` 파일을 생성합니다.
31
+
32
+ 1. `KADOC_SERVER_URL` 환경 변수 설정 (또는 기본값 `http://localhost:3000` 사용)
33
+ 2. Claude Desktop에서 MCP 실행
34
+ 3. 자동으로 사용자 등록 및 설정 파일 생성 완료
35
+
36
+ ### 수동 설정
37
+
38
+ `~/.kadoc.json` 파일을 직접 생성할 수도 있습니다:
39
+
40
+ ```json
41
+ {
42
+ "servers": {
43
+ "default": {
44
+ "url": "http://localhost:3000",
45
+ "auth": {
46
+ "authKey": "your-auth-key-from-register"
47
+ }
48
+ },
49
+ "production": {
50
+ "url": "https://kadoc.example.com",
51
+ "auth": {
52
+ "authKey": "production-auth-key"
53
+ }
54
+ }
55
+ },
56
+ "defaultServer": "default"
57
+ }
58
+ ```
59
+
60
+ 수동 등록 시:
61
+ ```bash
62
+ curl -X POST http://localhost:3000/auth/register
63
+ ```
64
+ 응답의 `authKey`를 설정 파일에 저장
65
+
66
+ ## Claude Desktop 설정
67
+
68
+ `claude_desktop_config.json`에 추가:
69
+
70
+ ```json
71
+ {
72
+ "mcpServers": {
73
+ "kadoc": {
74
+ "command": "npx",
75
+ "args": ["@kawoou/kadoc-mcp"],
76
+ "env": {
77
+ "KADOC_SERVER_URL": "http://localhost:3000"
78
+ }
79
+ }
80
+ }
81
+ }
82
+ ```
83
+
84
+ 또는 기존 설정 파일 사용 시:
85
+ ```json
86
+ {
87
+ "mcpServers": {
88
+ "kadoc": {
89
+ "command": "npx",
90
+ "args": ["@kawoou/kadoc-mcp"],
91
+ "env": {
92
+ "KADOC_CONFIG": "~/.kadoc.json"
93
+ }
94
+ }
95
+ }
96
+ }
97
+ ```
98
+
99
+ ## MCP Tools
100
+
101
+ ### 문서 관리
102
+ | 도구 | 설명 |
103
+ |------|------|
104
+ | `write_document` | 문서 작성 (path, title, content, metadata?) |
105
+ | `update_document` | 문서 수정 (path, title?, content?, metadata?) |
106
+ | `read_document` | 문서 읽기 (path) |
107
+ | `delete_document` | 문서 삭제 (path) |
108
+ | `list_documents` | 문서 목록 조회 (folder?, limit?) |
109
+
110
+ `metadata`는 임의의 키-값 쌍을 저장하는 JSON 객체입니다:
111
+ ```json
112
+ { "author": "홍길동", "tags": ["회의", "2024"], "priority": "high" }
113
+ ```
114
+
115
+ ### 검색
116
+ | 도구 | 설명 |
117
+ |------|------|
118
+ | `search` | BM25 기반 전문 검색 (query, folder?, limit?) |
119
+
120
+ ### 폴더 관리
121
+ | 도구 | 설명 |
122
+ |------|------|
123
+ | `create_folder` | 폴더 생성 (path) |
124
+ | `list_folders` | 폴더 목록 조회 (limit?) |
125
+ | `delete_folder` | 폴더 및 하위 문서 삭제 (path) |
126
+ | `get_index_settings` | 인덱스 설정 조회 (path) |
127
+ | `set_index_settings` | 인덱스 설정 변경 (path, indexFields?) |
128
+
129
+ `indexFields`에 지정된 메타데이터 필드가 검색 인덱스에 포함됩니다.
130
+ `title`과 `content`는 항상 인덱싱되며, 설정 변경 시 폴더 내 문서가 자동 재인덱싱됩니다.
131
+
132
+ ## 암호화 세션
133
+
134
+ kadoc-mcp는 자동으로 암호화 세션을 관리합니다:
135
+
136
+ 1. 첫 요청 시 `handshake()` 호출
137
+ 2. X25519 ECDH로 shared secret 생성
138
+ 3. 이후 모든 요청/응답 XSalsa20-Poly1305로 암호화
139
+ 4. 세션 만료 시 자동 재연결
140
+
141
+ 수동으로 세션 제어:
142
+ ```typescript
143
+ import { KadocClient } from '@kawoou/kadoc-mcp';
144
+
145
+ const client = new KadocClient(config);
146
+
147
+ // 세션 시작
148
+ await client.handshake();
149
+
150
+ // 세션 상태 확인
151
+ if (client.hasSession()) {
152
+ // 암호화 통신 중
153
+ }
154
+
155
+ // 세션 종료
156
+ await client.endSession();
157
+ ```
158
+
159
+ ## 개발
160
+
161
+ ```bash
162
+ # 의존성 설치
163
+ npm install
164
+
165
+ # 개발 모드 실행
166
+ npm run dev
167
+
168
+ # 빌드
169
+ npm run build
170
+
171
+ # 테스트
172
+ npm test
173
+ ```
174
+
175
+ ## 환경 변수
176
+
177
+ | 변수 | 설명 |
178
+ |------|------|
179
+ | `KADOC_SERVER_URL` | kadoc-server URL (기본: `http://localhost:3000`) |
180
+ | `KADOC_CONFIG` | 설정 파일 경로 (기본: `~/.kadoc.json`) |
181
+
182
+ ## 프로젝트 구조
183
+
184
+ ```
185
+ src/
186
+ ├── index.ts # MCP 서버 엔트리포인트
187
+ ├── config.ts # 설정 파일 로더
188
+ ├── client/
189
+ │ └── kadoc-client.ts # HTTP 클라이언트 (암호화 지원)
190
+ ├── crypto/
191
+ │ └── envelope.ts # 암호화 유틸리티
192
+ └── tools/
193
+ ├── documents.ts # 문서 MCP 도구
194
+ ├── folders.ts # 폴더 MCP 도구
195
+ └── search.ts # 검색 MCP 도구
196
+ ```
197
+
198
+ ## 라이선스
199
+
200
+ MIT
@@ -0,0 +1,74 @@
1
+ import { Config } from '../config.js';
2
+ export interface ApiError {
3
+ error: {
4
+ code: string;
5
+ message: string;
6
+ details?: unknown;
7
+ };
8
+ requestId: string;
9
+ }
10
+ export interface PaginatedResponse<T> {
11
+ items: T[];
12
+ nextCursor?: string;
13
+ hasMore: boolean;
14
+ }
15
+ export declare class KadocClient {
16
+ private config;
17
+ private sessions;
18
+ constructor(config: Config);
19
+ /**
20
+ * Make a request to the kadoc-server
21
+ * Automatically uses encryption if session is established
22
+ */
23
+ request<T>(method: 'GET' | 'POST' | 'PUT' | 'DELETE', path: string, body?: unknown, serverName?: string): Promise<T>;
24
+ /**
25
+ * Perform handshake with server to establish encrypted session
26
+ */
27
+ handshake(serverName?: string): Promise<void>;
28
+ /**
29
+ * End encrypted session
30
+ */
31
+ endSession(serverName?: string): Promise<void>;
32
+ /**
33
+ * Check if session is established and valid
34
+ */
35
+ hasSession(serverName?: string): boolean;
36
+ createDocument(params: {
37
+ path: string;
38
+ title: string;
39
+ content: string;
40
+ metadata?: Record<string, unknown>;
41
+ }): Promise<unknown>;
42
+ readDocument(path: string): Promise<unknown>;
43
+ updateDocument(params: {
44
+ path: string;
45
+ title?: string;
46
+ content?: string;
47
+ metadata?: Record<string, unknown>;
48
+ }): Promise<unknown>;
49
+ deleteDocument(path: string): Promise<unknown>;
50
+ listDocuments(params: {
51
+ folder?: string;
52
+ cursor?: string;
53
+ limit?: number;
54
+ }): Promise<unknown>;
55
+ search(params: {
56
+ query: string;
57
+ folder?: string;
58
+ limit?: number;
59
+ }): Promise<unknown>;
60
+ createFolder(params: {
61
+ path: string;
62
+ }): Promise<unknown>;
63
+ listFolders(params: {
64
+ cursor?: string;
65
+ limit?: number;
66
+ }): Promise<unknown>;
67
+ deleteFolder(path: string): Promise<unknown>;
68
+ getIndexSettings(path: string): Promise<unknown>;
69
+ setIndexSettings(params: {
70
+ path: string;
71
+ indexFields?: string[];
72
+ }): Promise<unknown>;
73
+ }
74
+ //# sourceMappingURL=kadoc-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kadoc-client.d.ts","sourceRoot":"","sources":["../../src/client/kadoc-client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAmB,MAAM,cAAc,CAAC;AAYvD,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC;IACF,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;CAClB;AAoBD,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAuC;gBAE3C,MAAM,EAAE,MAAM;IAI1B;;;OAGG;IACG,OAAO,CAAC,CAAC,EACb,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,EACzC,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,OAAO,EACd,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,CAAC,CAAC;IAwEb;;OAEG;IACG,SAAS,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwCnD;;OAEG;IACG,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBpD;;OAEG;IACH,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO;IAOlC,cAAc,CAAC,MAAM,EAAE;QAC3B,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACpC;IASK,YAAY,CAAC,IAAI,EAAE,MAAM;IAIzB,cAAc,CAAC,MAAM,EAAE;QAC3B,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACpC;IAQK,cAAc,CAAC,IAAI,EAAE,MAAM;IAI3B,aAAa,CAAC,MAAM,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;IAW1E,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;IASjE,YAAY,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE;IAIrC,WAAW,CAAC,MAAM,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;IASvD,YAAY,CAAC,IAAI,EAAE,MAAM;IAIzB,gBAAgB,CAAC,IAAI,EAAE,MAAM;IAI7B,gBAAgB,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE;CAKxE"}
@@ -0,0 +1,202 @@
1
+ import { request } from 'undici';
2
+ import { getServerConfig } from '../config.js';
3
+ import { generateKeyPair, computeSharedSecret, encodePublicKey, decodePublicKey, encrypt, decryptJson, generateNonce, } from '../crypto/envelope.js';
4
+ export class KadocClient {
5
+ config;
6
+ sessions = new Map(); // serverName -> session
7
+ constructor(config) {
8
+ this.config = config;
9
+ }
10
+ /**
11
+ * Make a request to the kadoc-server
12
+ * Automatically uses encryption if session is established
13
+ */
14
+ async request(method, path, body, serverName) {
15
+ const serverConfig = getServerConfig(this.config, serverName);
16
+ const serverKey = serverName ?? this.config.defaultServer;
17
+ const url = `${serverConfig.url}${path}`;
18
+ const headers = {
19
+ 'X-Auth-Key': serverConfig.auth.authKey,
20
+ };
21
+ // Only set Content-Type for requests with body
22
+ if (body || (method !== 'GET' && method !== 'DELETE')) {
23
+ headers['Content-Type'] = 'application/json';
24
+ }
25
+ // Get session if available
26
+ const session = this.sessions.get(serverKey);
27
+ let requestBody = body;
28
+ if (session && Date.now() < session.expiresAt) {
29
+ headers['X-Session-Id'] = session.sessionId;
30
+ // Encrypt request body if present
31
+ if (body) {
32
+ const encrypted = encrypt(body, session.sharedSecret);
33
+ const nonce = generateNonce();
34
+ requestBody = { encrypted, nonce };
35
+ }
36
+ }
37
+ const response = await request(url, {
38
+ method,
39
+ headers,
40
+ body: requestBody ? JSON.stringify(requestBody) : undefined,
41
+ });
42
+ // Handle 204 No Content responses
43
+ if (response.statusCode === 204) {
44
+ return {};
45
+ }
46
+ // Read response text first to handle empty body
47
+ const responseText = await response.body.text();
48
+ let responseBody;
49
+ try {
50
+ responseBody = responseText ? JSON.parse(responseText) : {};
51
+ }
52
+ catch {
53
+ // If response is not JSON, return empty object for success, throw for error
54
+ if (response.statusCode >= 400) {
55
+ throw new Error(`HTTP ${response.statusCode}: ${responseText}`);
56
+ }
57
+ return {};
58
+ }
59
+ if (response.statusCode >= 400) {
60
+ const error = responseBody;
61
+ throw new Error(`[${error.error?.code || 'ERROR'}] ${error.error?.message || 'Unknown error'}`);
62
+ }
63
+ // Decrypt response if encrypted
64
+ if (session && responseBody.encrypted) {
65
+ const encryptedResponse = responseBody;
66
+ const decrypted = decryptJson(encryptedResponse.encrypted, session.sharedSecret);
67
+ if (!decrypted) {
68
+ throw new Error('Failed to decrypt response');
69
+ }
70
+ return decrypted;
71
+ }
72
+ return responseBody;
73
+ }
74
+ /**
75
+ * Perform handshake with server to establish encrypted session
76
+ */
77
+ async handshake(serverName) {
78
+ const serverConfig = getServerConfig(this.config, serverName);
79
+ const serverKey = serverName ?? this.config.defaultServer;
80
+ // Generate ephemeral key pair
81
+ const clientKeyPair = generateKeyPair();
82
+ const url = `${serverConfig.url}/auth/handshake`;
83
+ const response = await request(url, {
84
+ method: 'POST',
85
+ headers: {
86
+ 'Content-Type': 'application/json',
87
+ 'X-Auth-Key': serverConfig.auth.authKey,
88
+ },
89
+ body: JSON.stringify({
90
+ clientPublicKey: encodePublicKey(clientKeyPair.publicKey),
91
+ }),
92
+ });
93
+ const responseBody = await response.body.json();
94
+ if (response.statusCode >= 400) {
95
+ const error = responseBody;
96
+ throw new Error(`[${error.error.code}] ${error.error.message}`);
97
+ }
98
+ const handshakeResponse = responseBody;
99
+ // Compute shared secret
100
+ const serverPublicKey = decodePublicKey(handshakeResponse.data.serverPublicKey);
101
+ const sharedSecret = computeSharedSecret(clientKeyPair.secretKey, serverPublicKey);
102
+ // Store session
103
+ this.sessions.set(serverKey, {
104
+ sessionId: handshakeResponse.data.sessionId,
105
+ sharedSecret,
106
+ expiresAt: handshakeResponse.data.expiresAt,
107
+ });
108
+ }
109
+ /**
110
+ * End encrypted session
111
+ */
112
+ async endSession(serverName) {
113
+ const serverConfig = getServerConfig(this.config, serverName);
114
+ const serverKey = serverName ?? this.config.defaultServer;
115
+ const session = this.sessions.get(serverKey);
116
+ if (!session) {
117
+ return;
118
+ }
119
+ const url = `${serverConfig.url}/auth/session`;
120
+ await request(url, {
121
+ method: 'DELETE',
122
+ headers: {
123
+ 'X-Session-Id': session.sessionId,
124
+ },
125
+ });
126
+ this.sessions.delete(serverKey);
127
+ }
128
+ /**
129
+ * Check if session is established and valid
130
+ */
131
+ hasSession(serverName) {
132
+ const serverKey = serverName ?? this.config.defaultServer;
133
+ const session = this.sessions.get(serverKey);
134
+ return !!session && Date.now() < session.expiresAt;
135
+ }
136
+ // Document operations
137
+ async createDocument(params) {
138
+ return this.request('POST', '/documents', {
139
+ path: params.path,
140
+ title: params.title,
141
+ content: params.content,
142
+ metadata: params.metadata,
143
+ });
144
+ }
145
+ async readDocument(path) {
146
+ return this.request('GET', `/documents/${encodeURIComponent(path)}`);
147
+ }
148
+ async updateDocument(params) {
149
+ return this.request('PUT', `/documents/${encodeURIComponent(params.path)}`, {
150
+ title: params.title,
151
+ content: params.content,
152
+ metadata: params.metadata,
153
+ });
154
+ }
155
+ async deleteDocument(path) {
156
+ return this.request('DELETE', `/documents/${encodeURIComponent(path)}`);
157
+ }
158
+ async listDocuments(params) {
159
+ const searchParams = new URLSearchParams();
160
+ if (params.folder)
161
+ searchParams.set('folder', params.folder);
162
+ if (params.cursor)
163
+ searchParams.set('cursor', params.cursor);
164
+ if (params.limit)
165
+ searchParams.set('limit', String(params.limit));
166
+ const query = searchParams.toString();
167
+ return this.request('GET', `/documents${query ? `?${query}` : ''}`);
168
+ }
169
+ // Search
170
+ async search(params) {
171
+ return this.request('POST', '/search', {
172
+ query: params.query,
173
+ folder: params.folder,
174
+ limit: params.limit,
175
+ });
176
+ }
177
+ // Folder operations
178
+ async createFolder(params) {
179
+ return this.request('POST', '/folders', { path: params.path });
180
+ }
181
+ async listFolders(params) {
182
+ const searchParams = new URLSearchParams();
183
+ if (params.cursor)
184
+ searchParams.set('cursor', params.cursor);
185
+ if (params.limit)
186
+ searchParams.set('limit', String(params.limit));
187
+ const query = searchParams.toString();
188
+ return this.request('GET', `/folders${query ? `?${query}` : ''}`);
189
+ }
190
+ async deleteFolder(path) {
191
+ return this.request('DELETE', `/folders/${encodeURIComponent(path)}`);
192
+ }
193
+ async getIndexSettings(path) {
194
+ return this.request('GET', `/folders/${encodeURIComponent(path)}/index-settings`);
195
+ }
196
+ async setIndexSettings(params) {
197
+ return this.request('PUT', `/folders/${encodeURIComponent(params.path)}/index-settings`, {
198
+ indexFields: params.indexFields,
199
+ });
200
+ }
201
+ }
202
+ //# sourceMappingURL=kadoc-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kadoc-client.js","sourceRoot":"","sources":["../../src/client/kadoc-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ import { z } from 'zod';
2
+ declare const serverAuthSchema: z.ZodObject<{
3
+ authKey: z.ZodString;
4
+ }, "strip", z.ZodTypeAny, {
5
+ authKey: string;
6
+ }, {
7
+ authKey: string;
8
+ }>;
9
+ declare const serverConfigSchema: z.ZodObject<{
10
+ url: z.ZodString;
11
+ auth: z.ZodObject<{
12
+ authKey: z.ZodString;
13
+ }, "strip", z.ZodTypeAny, {
14
+ authKey: string;
15
+ }, {
16
+ authKey: string;
17
+ }>;
18
+ }, "strip", z.ZodTypeAny, {
19
+ url: string;
20
+ auth: {
21
+ authKey: string;
22
+ };
23
+ }, {
24
+ url: string;
25
+ auth: {
26
+ authKey: string;
27
+ };
28
+ }>;
29
+ declare const configSchema: z.ZodObject<{
30
+ servers: z.ZodRecord<z.ZodString, z.ZodObject<{
31
+ url: z.ZodString;
32
+ auth: z.ZodObject<{
33
+ authKey: z.ZodString;
34
+ }, "strip", z.ZodTypeAny, {
35
+ authKey: string;
36
+ }, {
37
+ authKey: string;
38
+ }>;
39
+ }, "strip", z.ZodTypeAny, {
40
+ url: string;
41
+ auth: {
42
+ authKey: string;
43
+ };
44
+ }, {
45
+ url: string;
46
+ auth: {
47
+ authKey: string;
48
+ };
49
+ }>>;
50
+ defaultServer: z.ZodString;
51
+ }, "strip", z.ZodTypeAny, {
52
+ servers: Record<string, {
53
+ url: string;
54
+ auth: {
55
+ authKey: string;
56
+ };
57
+ }>;
58
+ defaultServer: string;
59
+ }, {
60
+ servers: Record<string, {
61
+ url: string;
62
+ auth: {
63
+ authKey: string;
64
+ };
65
+ }>;
66
+ defaultServer: string;
67
+ }>;
68
+ export type ServerAuth = z.infer<typeof serverAuthSchema>;
69
+ export type ServerConfig = z.infer<typeof serverConfigSchema>;
70
+ export type Config = z.infer<typeof configSchema>;
71
+ /**
72
+ * Load configuration, auto-registering if auth is missing
73
+ */
74
+ export declare function loadConfigAsync(configPath?: string): Promise<Config>;
75
+ /**
76
+ * Synchronous config load (for backward compatibility, throws if auth missing)
77
+ */
78
+ export declare function loadConfig(configPath?: string): Config;
79
+ export declare function getServerConfig(config: Config, serverName?: string): ServerConfig;
80
+ export declare function getConfigPath(): string;
81
+ export {};
82
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,QAAA,MAAM,gBAAgB;;;;;;EAEpB,CAAC;AAEH,QAAA,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;EAGtB,CAAC;AAEH,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAGhB,CAAC;AAaH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC1D,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC9D,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAiDlD;;GAEG;AACH,wBAAsB,eAAe,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA+E1E;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CA6BtD;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,YAAY,CASjF;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC"}