harper-kb 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.
- package/LICENSE +21 -0
- package/README.md +288 -0
- package/config.yaml +13 -0
- package/dist/core/embeddings.d.ts +31 -0
- package/dist/core/embeddings.d.ts.map +1 -0
- package/dist/core/embeddings.js +199 -0
- package/dist/core/embeddings.js.map +1 -0
- package/dist/core/entries.d.ts +101 -0
- package/dist/core/entries.d.ts.map +1 -0
- package/dist/core/entries.js +304 -0
- package/dist/core/entries.js.map +1 -0
- package/dist/core/history.d.ts +31 -0
- package/dist/core/history.d.ts.map +1 -0
- package/dist/core/history.js +119 -0
- package/dist/core/history.js.map +1 -0
- package/dist/core/knowledge-base.d.ts +49 -0
- package/dist/core/knowledge-base.d.ts.map +1 -0
- package/dist/core/knowledge-base.js +117 -0
- package/dist/core/knowledge-base.js.map +1 -0
- package/dist/core/search.d.ts +34 -0
- package/dist/core/search.d.ts.map +1 -0
- package/dist/core/search.js +327 -0
- package/dist/core/search.js.map +1 -0
- package/dist/core/tags.d.ts +39 -0
- package/dist/core/tags.d.ts.map +1 -0
- package/dist/core/tags.js +97 -0
- package/dist/core/tags.js.map +1 -0
- package/dist/core/triage.d.ts +61 -0
- package/dist/core/triage.d.ts.map +1 -0
- package/dist/core/triage.js +136 -0
- package/dist/core/triage.js.map +1 -0
- package/dist/core/webhook-endpoints.d.ts +46 -0
- package/dist/core/webhook-endpoints.d.ts.map +1 -0
- package/dist/core/webhook-endpoints.js +85 -0
- package/dist/core/webhook-endpoints.js.map +1 -0
- package/dist/hooks.d.ts +67 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +53 -0
- package/dist/hooks.js.map +1 -0
- package/dist/http-utils.d.ts +38 -0
- package/dist/http-utils.d.ts.map +1 -0
- package/dist/http-utils.js +133 -0
- package/dist/http-utils.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +78 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/protocol.d.ts +25 -0
- package/dist/mcp/protocol.d.ts.map +1 -0
- package/dist/mcp/protocol.js +105 -0
- package/dist/mcp/protocol.js.map +1 -0
- package/dist/mcp/server.d.ts +28 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +144 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools.d.ts +26 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +706 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/oauth/authorize.d.ts +28 -0
- package/dist/oauth/authorize.d.ts.map +1 -0
- package/dist/oauth/authorize.js +421 -0
- package/dist/oauth/authorize.js.map +1 -0
- package/dist/oauth/init.d.ts +18 -0
- package/dist/oauth/init.d.ts.map +1 -0
- package/dist/oauth/init.js +30 -0
- package/dist/oauth/init.js.map +1 -0
- package/dist/oauth/keys.d.ts +34 -0
- package/dist/oauth/keys.d.ts.map +1 -0
- package/dist/oauth/keys.js +101 -0
- package/dist/oauth/keys.js.map +1 -0
- package/dist/oauth/metadata.d.ts +23 -0
- package/dist/oauth/metadata.d.ts.map +1 -0
- package/dist/oauth/metadata.js +57 -0
- package/dist/oauth/metadata.js.map +1 -0
- package/dist/oauth/middleware.d.ts +23 -0
- package/dist/oauth/middleware.d.ts.map +1 -0
- package/dist/oauth/middleware.js +65 -0
- package/dist/oauth/middleware.js.map +1 -0
- package/dist/oauth/register.d.ts +15 -0
- package/dist/oauth/register.d.ts.map +1 -0
- package/dist/oauth/register.js +78 -0
- package/dist/oauth/register.js.map +1 -0
- package/dist/oauth/token.d.ts +16 -0
- package/dist/oauth/token.d.ts.map +1 -0
- package/dist/oauth/token.js +184 -0
- package/dist/oauth/token.js.map +1 -0
- package/dist/oauth/validate.d.ts +40 -0
- package/dist/oauth/validate.d.ts.map +1 -0
- package/dist/oauth/validate.js +61 -0
- package/dist/oauth/validate.js.map +1 -0
- package/dist/resources/HistoryResource.d.ts +41 -0
- package/dist/resources/HistoryResource.d.ts.map +1 -0
- package/dist/resources/HistoryResource.js +61 -0
- package/dist/resources/HistoryResource.js.map +1 -0
- package/dist/resources/KnowledgeBaseResource.d.ts +60 -0
- package/dist/resources/KnowledgeBaseResource.d.ts.map +1 -0
- package/dist/resources/KnowledgeBaseResource.js +118 -0
- package/dist/resources/KnowledgeBaseResource.js.map +1 -0
- package/dist/resources/KnowledgeEntryResource.d.ts +61 -0
- package/dist/resources/KnowledgeEntryResource.d.ts.map +1 -0
- package/dist/resources/KnowledgeEntryResource.js +191 -0
- package/dist/resources/KnowledgeEntryResource.js.map +1 -0
- package/dist/resources/MeResource.d.ts +31 -0
- package/dist/resources/MeResource.d.ts.map +1 -0
- package/dist/resources/MeResource.js +40 -0
- package/dist/resources/MeResource.js.map +1 -0
- package/dist/resources/QueryLogResource.d.ts +22 -0
- package/dist/resources/QueryLogResource.d.ts.map +1 -0
- package/dist/resources/QueryLogResource.js +66 -0
- package/dist/resources/QueryLogResource.js.map +1 -0
- package/dist/resources/ServiceKeyResource.d.ts +52 -0
- package/dist/resources/ServiceKeyResource.d.ts.map +1 -0
- package/dist/resources/ServiceKeyResource.js +151 -0
- package/dist/resources/ServiceKeyResource.js.map +1 -0
- package/dist/resources/TagResource.d.ts +27 -0
- package/dist/resources/TagResource.d.ts.map +1 -0
- package/dist/resources/TagResource.js +41 -0
- package/dist/resources/TagResource.js.map +1 -0
- package/dist/resources/TriageResource.d.ts +53 -0
- package/dist/resources/TriageResource.d.ts.map +1 -0
- package/dist/resources/TriageResource.js +120 -0
- package/dist/resources/TriageResource.js.map +1 -0
- package/dist/resources/WebhookEndpointResource.d.ts +63 -0
- package/dist/resources/WebhookEndpointResource.d.ts.map +1 -0
- package/dist/resources/WebhookEndpointResource.js +115 -0
- package/dist/resources/WebhookEndpointResource.js.map +1 -0
- package/dist/types.d.ts +378 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/webhooks/github.d.ts +25 -0
- package/dist/webhooks/github.d.ts.map +1 -0
- package/dist/webhooks/github.js +165 -0
- package/dist/webhooks/github.js.map +1 -0
- package/dist/webhooks/middleware.d.ts +19 -0
- package/dist/webhooks/middleware.d.ts.map +1 -0
- package/dist/webhooks/middleware.js +144 -0
- package/dist/webhooks/middleware.js.map +1 -0
- package/dist/webhooks/types.d.ts +18 -0
- package/dist/webhooks/types.d.ts.map +1 -0
- package/dist/webhooks/types.js +5 -0
- package/dist/webhooks/types.js.map +1 -0
- package/package.json +69 -0
- package/schema/knowledge.graphql +136 -0
- package/schema/oauth.graphql +45 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* harper-kb — Harper Knowledge Base Plugin
|
|
3
|
+
*
|
|
4
|
+
* Sub-component plugin that provides a knowledge base with vector search,
|
|
5
|
+
* triage queue, and MCP server integration. Loaded by a parent application
|
|
6
|
+
* via `package:` in the parent's config.yaml.
|
|
7
|
+
*
|
|
8
|
+
* Harper calls handleApplication(scope) on each worker thread.
|
|
9
|
+
*/
|
|
10
|
+
import { initEmbeddingModel, dispose as disposeEmbeddings } from "./core/embeddings.js";
|
|
11
|
+
import { KnowledgeBaseResource } from "./resources/KnowledgeBaseResource.js";
|
|
12
|
+
import { KnowledgeEntryResource } from "./resources/KnowledgeEntryResource.js";
|
|
13
|
+
import { TriageResource } from "./resources/TriageResource.js";
|
|
14
|
+
import { TagResource } from "./resources/TagResource.js";
|
|
15
|
+
import { QueryLogResource } from "./resources/QueryLogResource.js";
|
|
16
|
+
import { ServiceKeyResource } from "./resources/ServiceKeyResource.js";
|
|
17
|
+
import { WebhookEndpointResource } from "./resources/WebhookEndpointResource.js";
|
|
18
|
+
import { HistoryResource } from "./resources/HistoryResource.js";
|
|
19
|
+
import { MeResource } from "./resources/MeResource.js";
|
|
20
|
+
import { createMcpMiddleware } from "./mcp/server.js";
|
|
21
|
+
import { createWebhookMiddleware } from "./webhooks/middleware.js";
|
|
22
|
+
import { initOAuth } from "./oauth/init.js";
|
|
23
|
+
// Re-export core modules for external use
|
|
24
|
+
export { createKnowledgeBase, getKnowledgeBase, updateKnowledgeBase, deleteKnowledgeBase, listKnowledgeBases, } from "./core/knowledge-base.js";
|
|
25
|
+
export { createEntry, getEntry, updateEntry, deprecateEntry, linkSupersedes, linkSiblings, linkRelated, } from "./core/entries.js";
|
|
26
|
+
export { search, filterByApplicability } from "./core/search.js";
|
|
27
|
+
export { logEdit, getHistory } from "./core/history.js";
|
|
28
|
+
export { listTags, syncTags } from "./core/tags.js";
|
|
29
|
+
export { submitTriage, processTriage, listPending, dismissTriage, findBySourceId } from "./core/triage.js";
|
|
30
|
+
export { generateEmbedding, initEmbeddingModel, dispose as disposeEmbeddings } from "./core/embeddings.js";
|
|
31
|
+
export { createWebhookEndpoint, listWebhookEndpoints, deleteWebhookEndpoint } from "./core/webhook-endpoints.js";
|
|
32
|
+
export { registerHooks } from "./hooks.js";
|
|
33
|
+
/**
|
|
34
|
+
* Plugin entry point — called by Harper on each worker thread.
|
|
35
|
+
*/
|
|
36
|
+
export async function handleApplication(scope) {
|
|
37
|
+
const scopeLogger = scope.logger;
|
|
38
|
+
scopeLogger?.info?.('Knowledge base plugin initializing...');
|
|
39
|
+
// Read plugin configuration
|
|
40
|
+
const rawOptions = (scope.options.getAll() || {});
|
|
41
|
+
const embeddingModel = rawOptions.embeddingModel || 'nomic-embed-text';
|
|
42
|
+
// Initialize the embedding model in the background (downloads on first run).
|
|
43
|
+
// Don't await — the download can take minutes and would exceed Harper's
|
|
44
|
+
// 30-second handleApplication timeout. Semantic search degrades gracefully
|
|
45
|
+
// to keyword-only mode until the model is ready.
|
|
46
|
+
initEmbeddingModel({ embeddingModel, componentDir: scope.directory }).then(() => scopeLogger?.info?.(`Embedding model "${embeddingModel}" loaded`), (error) => scopeLogger?.error?.('Failed to initialize embedding model — semantic search will be unavailable:', error.message));
|
|
47
|
+
// Initialize OAuth (signing keys, middleware)
|
|
48
|
+
await initOAuth(scope);
|
|
49
|
+
// Register REST Resource classes
|
|
50
|
+
scope.resources.set('KnowledgeBase', KnowledgeBaseResource);
|
|
51
|
+
scope.resources.set('Knowledge', KnowledgeEntryResource);
|
|
52
|
+
scope.resources.set('Triage', TriageResource);
|
|
53
|
+
scope.resources.set('KnowledgeTag', TagResource);
|
|
54
|
+
scope.resources.set('QueryLog', QueryLogResource);
|
|
55
|
+
scope.resources.set('ServiceKey', ServiceKeyResource);
|
|
56
|
+
scope.resources.set('WebhookEndpoint', WebhookEndpointResource);
|
|
57
|
+
scope.resources.set('History', HistoryResource);
|
|
58
|
+
scope.resources.set('me', MeResource);
|
|
59
|
+
// Register webhook intake middleware (before MCP so /webhooks/* is handled first)
|
|
60
|
+
scope.server.http?.(createWebhookMiddleware(scope));
|
|
61
|
+
// Register MCP endpoint middleware (runFirst so it executes before Harper's auth layer)
|
|
62
|
+
scope.server.http?.(createMcpMiddleware(), { runFirst: true });
|
|
63
|
+
scopeLogger?.info?.('Knowledge base resources, OAuth, and MCP endpoint registered');
|
|
64
|
+
// Watch for configuration changes
|
|
65
|
+
scope.options.on('change', (_key, _value, _config) => {
|
|
66
|
+
scopeLogger?.debug?.('Knowledge base configuration changed');
|
|
67
|
+
// Future: re-configure embedding model or other settings as needed
|
|
68
|
+
});
|
|
69
|
+
// Clean up on scope close
|
|
70
|
+
scope.on('close', () => {
|
|
71
|
+
scopeLogger?.info?.('Knowledge base plugin shutting down');
|
|
72
|
+
disposeEmbeddings().catch((error) => {
|
|
73
|
+
scopeLogger?.error?.('Error disposing embedding model:', error.message);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
scopeLogger?.info?.('Knowledge base plugin initialized');
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal MCP JSON-RPC 2.0 Protocol Handler
|
|
3
|
+
*
|
|
4
|
+
* Routes initialize, tools/list, and tools/call methods.
|
|
5
|
+
* No SDK, no transport layer — just a function from parsed body to response body.
|
|
6
|
+
*/
|
|
7
|
+
import type { ValidatedCaller } from '../oauth/validate.ts';
|
|
8
|
+
interface JsonRpcResponse {
|
|
9
|
+
jsonrpc: '2.0';
|
|
10
|
+
id: string | number | null;
|
|
11
|
+
result?: unknown;
|
|
12
|
+
error?: {
|
|
13
|
+
code: number;
|
|
14
|
+
message: string;
|
|
15
|
+
data?: unknown;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Handle a single JSON-RPC request.
|
|
20
|
+
*
|
|
21
|
+
* Returns a JSON-RPC response object, or null for notifications (no id).
|
|
22
|
+
*/
|
|
23
|
+
export declare function handleJsonRpc(body: unknown, caller: ValidatedCaller): Promise<JsonRpcResponse | null>;
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=protocol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/mcp/protocol.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAc5D,UAAU,eAAe;IACxB,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAC1D;AAcD;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAsF3G"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal MCP JSON-RPC 2.0 Protocol Handler
|
|
3
|
+
*
|
|
4
|
+
* Routes initialize, tools/list, and tools/call methods.
|
|
5
|
+
* No SDK, no transport layer — just a function from parsed body to response body.
|
|
6
|
+
*/
|
|
7
|
+
import { tools } from "./tools.js";
|
|
8
|
+
const SERVER_INFO = {
|
|
9
|
+
name: 'knowledge-base',
|
|
10
|
+
version: '0.1.0',
|
|
11
|
+
};
|
|
12
|
+
const PROTOCOL_VERSION = '2025-03-26';
|
|
13
|
+
const INVALID_REQUEST = -32600;
|
|
14
|
+
const METHOD_NOT_FOUND = -32601;
|
|
15
|
+
const INTERNAL_ERROR = -32603;
|
|
16
|
+
/** Pre-built name→tool index (built once at module load). */
|
|
17
|
+
const toolsByName = new Map(tools.map((t) => [t.name, t]));
|
|
18
|
+
/** Format a tool definition for the tools/list response. */
|
|
19
|
+
function toToolListEntry(tool) {
|
|
20
|
+
return {
|
|
21
|
+
name: tool.name,
|
|
22
|
+
description: tool.description,
|
|
23
|
+
inputSchema: tool.inputSchema,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Handle a single JSON-RPC request.
|
|
28
|
+
*
|
|
29
|
+
* Returns a JSON-RPC response object, or null for notifications (no id).
|
|
30
|
+
*/
|
|
31
|
+
export async function handleJsonRpc(body, caller) {
|
|
32
|
+
if (!body || typeof body !== 'object' || body.jsonrpc !== '2.0') {
|
|
33
|
+
return {
|
|
34
|
+
jsonrpc: '2.0',
|
|
35
|
+
id: body?.id ?? null,
|
|
36
|
+
error: { code: INVALID_REQUEST, message: 'Invalid JSON-RPC request' },
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
const req = body;
|
|
40
|
+
// Notifications have no id — acknowledge silently
|
|
41
|
+
if (req.id === undefined || req.id === null) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
const { id } = req;
|
|
45
|
+
try {
|
|
46
|
+
switch (req.method) {
|
|
47
|
+
case 'initialize':
|
|
48
|
+
return {
|
|
49
|
+
jsonrpc: '2.0',
|
|
50
|
+
id,
|
|
51
|
+
result: {
|
|
52
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
53
|
+
capabilities: { tools: {} },
|
|
54
|
+
serverInfo: SERVER_INFO,
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
case 'tools/list':
|
|
58
|
+
return {
|
|
59
|
+
jsonrpc: '2.0',
|
|
60
|
+
id,
|
|
61
|
+
result: {
|
|
62
|
+
tools: tools.map(toToolListEntry),
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
case 'tools/call': {
|
|
66
|
+
const toolName = req.params?.name;
|
|
67
|
+
const toolArgs = req.params?.arguments ?? {};
|
|
68
|
+
const tool = toolsByName.get(toolName);
|
|
69
|
+
if (!tool) {
|
|
70
|
+
return {
|
|
71
|
+
jsonrpc: '2.0',
|
|
72
|
+
id,
|
|
73
|
+
error: {
|
|
74
|
+
code: METHOD_NOT_FOUND,
|
|
75
|
+
message: `Unknown tool: ${toolName}`,
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const result = await tool.handler(toolArgs, caller);
|
|
80
|
+
return { jsonrpc: '2.0', id, result };
|
|
81
|
+
}
|
|
82
|
+
default:
|
|
83
|
+
return {
|
|
84
|
+
jsonrpc: '2.0',
|
|
85
|
+
id,
|
|
86
|
+
error: {
|
|
87
|
+
code: METHOD_NOT_FOUND,
|
|
88
|
+
message: `Unknown method: ${req.method}`,
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
logger?.error?.('MCP JSON-RPC handler failed:', error.message);
|
|
95
|
+
return {
|
|
96
|
+
jsonrpc: '2.0',
|
|
97
|
+
id,
|
|
98
|
+
error: {
|
|
99
|
+
code: INTERNAL_ERROR,
|
|
100
|
+
message: 'Internal server error',
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=protocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/mcp/protocol.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Server Middleware
|
|
3
|
+
*
|
|
4
|
+
* Creates an HTTP middleware for Harper's scope.server.http() that handles
|
|
5
|
+
* MCP (Model Context Protocol) requests as direct JSON-RPC.
|
|
6
|
+
*
|
|
7
|
+
* Each knowledge base gets its own MCP endpoint at /mcp/<kbId>.
|
|
8
|
+
* The kbId is extracted from the URL path, validated against the
|
|
9
|
+
* KnowledgeBase table, and passed to all tools implicitly via the caller.
|
|
10
|
+
*
|
|
11
|
+
* Auth: Validates JWT Bearer tokens issued by the co-located OAuth 2.1
|
|
12
|
+
* authorization server. Tokens are scoped to a specific KB via the
|
|
13
|
+
* audience claim (aud = "{baseUrl}/mcp/{kbId}"). Unauthenticated
|
|
14
|
+
* requests get read-only access.
|
|
15
|
+
*/
|
|
16
|
+
import type { HarperRequest } from '../types.ts';
|
|
17
|
+
/**
|
|
18
|
+
* Create an MCP middleware function for Harper's scope.server.http().
|
|
19
|
+
*
|
|
20
|
+
* The middleware:
|
|
21
|
+
* 1. Checks if the request pathname starts with /mcp/
|
|
22
|
+
* 2. Extracts kbId from the path
|
|
23
|
+
* 3. Validates the KB exists
|
|
24
|
+
* 4. Validates Bearer token (scoped to this KB)
|
|
25
|
+
* 5. Handles the MCP request via JSON-RPC dispatch
|
|
26
|
+
*/
|
|
27
|
+
export declare function createMcpMiddleware(): (request: HarperRequest, next: (req: HarperRequest) => Promise<unknown>) => Promise<unknown>;
|
|
28
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAOH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAajD;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,IAAI,CACtC,OAAO,EAAE,aAAa,EACtB,IAAI,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,OAAO,CAAC,KAC1C,OAAO,CAAC,OAAO,CAAC,CAgIpB"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Server Middleware
|
|
3
|
+
*
|
|
4
|
+
* Creates an HTTP middleware for Harper's scope.server.http() that handles
|
|
5
|
+
* MCP (Model Context Protocol) requests as direct JSON-RPC.
|
|
6
|
+
*
|
|
7
|
+
* Each knowledge base gets its own MCP endpoint at /mcp/<kbId>.
|
|
8
|
+
* The kbId is extracted from the URL path, validated against the
|
|
9
|
+
* KnowledgeBase table, and passed to all tools implicitly via the caller.
|
|
10
|
+
*
|
|
11
|
+
* Auth: Validates JWT Bearer tokens issued by the co-located OAuth 2.1
|
|
12
|
+
* authorization server. Tokens are scoped to a specific KB via the
|
|
13
|
+
* audience claim (aud = "{baseUrl}/mcp/{kbId}"). Unauthenticated
|
|
14
|
+
* requests get read-only access.
|
|
15
|
+
*/
|
|
16
|
+
import { handleJsonRpc } from "./protocol.js";
|
|
17
|
+
import { validateMcpAuth } from "../oauth/validate.js";
|
|
18
|
+
import { getKnowledgeBase } from "../core/knowledge-base.js";
|
|
19
|
+
import { checkAccess } from "../hooks.js";
|
|
20
|
+
import { readBody, getBaseUrl } from "../http-utils.js";
|
|
21
|
+
/**
|
|
22
|
+
* Extract the kbId from the URL path.
|
|
23
|
+
*
|
|
24
|
+
* Matches: /mcp/<kbId> or /mcp/<kbId>/...
|
|
25
|
+
* Returns null if the path doesn't match.
|
|
26
|
+
*/
|
|
27
|
+
function extractKbIdFromPath(pathname) {
|
|
28
|
+
const match = pathname.match(/^\/mcp\/([^/]+)/);
|
|
29
|
+
return match ? match[1] : null;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Create an MCP middleware function for Harper's scope.server.http().
|
|
33
|
+
*
|
|
34
|
+
* The middleware:
|
|
35
|
+
* 1. Checks if the request pathname starts with /mcp/
|
|
36
|
+
* 2. Extracts kbId from the path
|
|
37
|
+
* 3. Validates the KB exists
|
|
38
|
+
* 4. Validates Bearer token (scoped to this KB)
|
|
39
|
+
* 5. Handles the MCP request via JSON-RPC dispatch
|
|
40
|
+
*/
|
|
41
|
+
export function createMcpMiddleware() {
|
|
42
|
+
return async (request, next) => {
|
|
43
|
+
const pathname = request.pathname || '';
|
|
44
|
+
// Only handle /mcp/<kbId> routes (bare /mcp passes through)
|
|
45
|
+
if (!pathname.startsWith('/mcp/')) {
|
|
46
|
+
return next(request);
|
|
47
|
+
}
|
|
48
|
+
// Extract kbId from the path
|
|
49
|
+
const kbId = extractKbIdFromPath(pathname);
|
|
50
|
+
if (!kbId) {
|
|
51
|
+
return next(request);
|
|
52
|
+
}
|
|
53
|
+
// Validate the KB exists
|
|
54
|
+
const kb = await getKnowledgeBase(kbId);
|
|
55
|
+
if (!kb) {
|
|
56
|
+
return new Response(JSON.stringify({
|
|
57
|
+
jsonrpc: '2.0',
|
|
58
|
+
error: {
|
|
59
|
+
code: -32001,
|
|
60
|
+
message: `Knowledge base not found: ${kbId}`,
|
|
61
|
+
},
|
|
62
|
+
id: null,
|
|
63
|
+
}), {
|
|
64
|
+
status: 404,
|
|
65
|
+
headers: { 'Content-Type': 'application/json' },
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
// Validate JWT Bearer token (if present), scoped to this KB
|
|
69
|
+
const { caller, hasToken } = await validateMcpAuth(request, kbId);
|
|
70
|
+
// Invalid token → 401 so the client re-authenticates
|
|
71
|
+
if (hasToken && !caller) {
|
|
72
|
+
const baseUrl = getBaseUrl(request);
|
|
73
|
+
return new Response(JSON.stringify({
|
|
74
|
+
jsonrpc: '2.0',
|
|
75
|
+
error: {
|
|
76
|
+
code: -32001,
|
|
77
|
+
message: 'Unauthorized',
|
|
78
|
+
},
|
|
79
|
+
id: null,
|
|
80
|
+
}), {
|
|
81
|
+
status: 401,
|
|
82
|
+
headers: {
|
|
83
|
+
'Content-Type': 'application/json',
|
|
84
|
+
'WWW-Authenticate': `Bearer resource_metadata="${baseUrl}/.well-known/oauth-protected-resource/${kbId}"`,
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
// No token → anonymous read-only; valid token → authenticated caller
|
|
89
|
+
const effectiveCaller = caller ?? {
|
|
90
|
+
userId: 'anonymous',
|
|
91
|
+
clientId: 'anonymous',
|
|
92
|
+
scopes: ['mcp:read'],
|
|
93
|
+
kbId,
|
|
94
|
+
};
|
|
95
|
+
// Run the onAccessCheck hook (if registered by the parent app)
|
|
96
|
+
const accessResult = await checkAccess(effectiveCaller, kbId);
|
|
97
|
+
if (accessResult && !accessResult.allow) {
|
|
98
|
+
logger?.warn?.(`Access denied for ${effectiveCaller.userId} on KB ${kbId}: ${accessResult.reason || 'denied by hook'}`);
|
|
99
|
+
return new Response(JSON.stringify({
|
|
100
|
+
jsonrpc: '2.0',
|
|
101
|
+
error: {
|
|
102
|
+
code: -32001,
|
|
103
|
+
message: 'Forbidden',
|
|
104
|
+
},
|
|
105
|
+
id: null,
|
|
106
|
+
}), {
|
|
107
|
+
status: 403,
|
|
108
|
+
headers: { 'Content-Type': 'application/json' },
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
// Hook may override scopes (e.g., downgrade to read-only)
|
|
112
|
+
const finalCaller = accessResult?.scopes
|
|
113
|
+
? { ...effectiveCaller, scopes: accessResult.scopes }
|
|
114
|
+
: effectiveCaller;
|
|
115
|
+
try {
|
|
116
|
+
const bodyText = await readBody(request);
|
|
117
|
+
const body = bodyText ? JSON.parse(bodyText) : undefined;
|
|
118
|
+
const response = await handleJsonRpc(body, finalCaller);
|
|
119
|
+
// Notification (no id) → 202 Accepted
|
|
120
|
+
if (response === null) {
|
|
121
|
+
return new Response(null, { status: 202 });
|
|
122
|
+
}
|
|
123
|
+
return new Response(JSON.stringify(response), {
|
|
124
|
+
status: 200,
|
|
125
|
+
headers: { 'Content-Type': 'application/json' },
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
logger?.error?.('MCP request handling failed:', error.message, error.stack);
|
|
130
|
+
return new Response(JSON.stringify({
|
|
131
|
+
jsonrpc: '2.0',
|
|
132
|
+
error: {
|
|
133
|
+
code: -32603,
|
|
134
|
+
message: 'Internal server error',
|
|
135
|
+
},
|
|
136
|
+
id: null,
|
|
137
|
+
}), {
|
|
138
|
+
status: 500,
|
|
139
|
+
headers: { 'Content-Type': 'application/json' },
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool Definitions
|
|
3
|
+
*
|
|
4
|
+
* Static array of tool definitions with JSON Schema input schemas
|
|
5
|
+
* and handler functions. Each handler receives (args, caller) and
|
|
6
|
+
* returns MCP tool content.
|
|
7
|
+
*
|
|
8
|
+
* The kbId is implicit — it comes from the caller (extracted from the URL
|
|
9
|
+
* path /mcp/<kbId>), so tools don't need it as an input parameter.
|
|
10
|
+
*/
|
|
11
|
+
import type { ValidatedCaller } from '../oauth/validate.ts';
|
|
12
|
+
export interface ToolContent {
|
|
13
|
+
content: Array<{
|
|
14
|
+
type: 'text';
|
|
15
|
+
text: string;
|
|
16
|
+
}>;
|
|
17
|
+
isError?: true;
|
|
18
|
+
}
|
|
19
|
+
export interface ToolDefinition {
|
|
20
|
+
name: string;
|
|
21
|
+
description: string;
|
|
22
|
+
inputSchema: Record<string, unknown>;
|
|
23
|
+
handler: (args: Record<string, unknown>, caller: ValidatedCaller) => Promise<ToolContent>;
|
|
24
|
+
}
|
|
25
|
+
export declare const tools: ToolDefinition[];
|
|
26
|
+
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/mcp/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAiBH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAM5D,MAAM,WAAW,WAAW;IAC3B,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,IAAI,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,eAAe,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;CAC1F;AA8BD,eAAO,MAAM,KAAK,EAAE,cAAc,EAgsBjC,CAAC"}
|