@dashclaw/mcp-server 1.0.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/lib/server.js ADDED
@@ -0,0 +1,132 @@
1
+ // mcp-server/lib/server.js
2
+
3
+ /**
4
+ * Factory function that creates a configured McpServer with all tools and resources registered.
5
+ *
6
+ * Uses @modelcontextprotocol/server v2 alpha API:
7
+ * - registerTool(name, config, handler) — config.inputSchema accepts Standard Schema (via fromJsonSchema)
8
+ * - registerResource(name, uri, config, readCallback) — static resources
9
+ * - registerResource(name, ResourceTemplate, config, readCallback) — URI template resources
10
+ */
11
+
12
+ import { McpServer, ResourceTemplate, fromJsonSchema } from '@modelcontextprotocol/server';
13
+ import { DashClawClient } from './client.js';
14
+ import { TOOL_DEFINITIONS, createToolHandlers } from './tools.js';
15
+ import { RESOURCE_DEFINITIONS, createResourceHandlers } from './resources.js';
16
+
17
+ /**
18
+ * Convert a JSON Schema object to a Standard Schema wrapper accepted by registerTool.
19
+ * Uses fromJsonSchema from the MCP SDK which wraps the schema with a validator.
20
+ *
21
+ * @param {object} jsonSchema - JSON Schema object
22
+ * @returns {object} Standard Schema wrapper
23
+ */
24
+ function jsonSchemaToInputSchema(jsonSchema) {
25
+ return fromJsonSchema(jsonSchema);
26
+ }
27
+
28
+ /**
29
+ * Create and configure an McpServer instance with all tools and resources from
30
+ * TOOL_DEFINITIONS and RESOURCE_DEFINITIONS.
31
+ *
32
+ * @param {object} config - Configuration options
33
+ * @param {string} [config.url] - DashClaw instance URL (default: http://localhost:3000)
34
+ * @param {string} [config.apiKey] - API key (oc_live_ prefix)
35
+ * @param {string} [config.agentId] - Default agent ID for tool calls
36
+ * @returns {McpServer} Configured MCP server ready to connect
37
+ */
38
+ export function createServer(config = {}) {
39
+ // 1. Create DashClawClient
40
+ const client = new DashClawClient({
41
+ url: config.url,
42
+ apiKey: config.apiKey,
43
+ agentId: config.agentId,
44
+ });
45
+
46
+ // 2. Create tool and resource handlers bound to the client
47
+ const toolHandlers = createToolHandlers(client);
48
+ const resourceHandlers = createResourceHandlers(client);
49
+
50
+ // 3. Create McpServer instance
51
+ const server = new McpServer(
52
+ {
53
+ name: '@dashclaw/mcp-server',
54
+ version: '1.0.0',
55
+ },
56
+ {
57
+ capabilities: {
58
+ tools: {},
59
+ resources: {},
60
+ },
61
+ }
62
+ );
63
+
64
+ // 4. Register all tools
65
+ for (const toolDef of TOOL_DEFINITIONS) {
66
+ const handler = toolHandlers[toolDef.name];
67
+ if (!handler) {
68
+ throw new Error(`Missing handler for tool: ${toolDef.name}`);
69
+ }
70
+
71
+ server.registerTool(
72
+ toolDef.name,
73
+ {
74
+ description: toolDef.description,
75
+ inputSchema: jsonSchemaToInputSchema(toolDef.inputSchema),
76
+ },
77
+ async (args) => {
78
+ const text = await handler(args);
79
+ return {
80
+ content: [{ type: 'text', text }],
81
+ };
82
+ }
83
+ );
84
+ }
85
+
86
+ // 5. Register static resources and the agent history template
87
+ for (const resDef of RESOURCE_DEFINITIONS) {
88
+ const resourceHandler = resourceHandlers[resDef.uri];
89
+ if (!resourceHandler) {
90
+ throw new Error(`Missing handler for resource: ${resDef.uri}`);
91
+ }
92
+
93
+ if (resDef.isTemplate) {
94
+ // URI template resource: dashclaw://agent/{agent_id}/history
95
+ // readCallback is called with (uri, variables, ctx)
96
+ const template = new ResourceTemplate(resDef.uri, { list: undefined });
97
+ server.registerResource(
98
+ resDef.name,
99
+ template,
100
+ {
101
+ description: resDef.description,
102
+ mimeType: resDef.mimeType,
103
+ },
104
+ async (uri, variables) => {
105
+ const text = await resourceHandler(variables);
106
+ return {
107
+ contents: [{ uri: uri.href, mimeType: resDef.mimeType, text }],
108
+ };
109
+ }
110
+ );
111
+ } else {
112
+ // Static resource
113
+ // readCallback is called with (uri, ctx)
114
+ server.registerResource(
115
+ resDef.name,
116
+ resDef.uri,
117
+ {
118
+ description: resDef.description,
119
+ mimeType: resDef.mimeType,
120
+ },
121
+ async (uri) => {
122
+ const text = await resourceHandler();
123
+ return {
124
+ contents: [{ uri: uri.href, mimeType: resDef.mimeType, text }],
125
+ };
126
+ }
127
+ );
128
+ }
129
+ }
130
+
131
+ return server;
132
+ }