lynkr 3.3.1 → 4.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.
@@ -0,0 +1,697 @@
1
+ # Tool Calling & Execution Modes
2
+
3
+ Complete guide to Lynkr's tool calling system, execution modes, and custom tool development.
4
+
5
+ ---
6
+
7
+ ## Overview
8
+
9
+ Lynkr supports two tool execution modes:
10
+
11
+ - **Server Mode (default)**: Tools execute on Lynkr server
12
+ - **Client Mode (passthrough)**: Tools execute on client (Claude Code CLI/Cursor)
13
+
14
+ This enables flexible deployment scenarios: centralized tooling, security policies, or client-side file access.
15
+
16
+ ---
17
+
18
+ ## Tool Execution Modes
19
+
20
+ ### Server Mode (Default)
21
+
22
+ **How it works:**
23
+ - Client sends request without tools
24
+ - Lynkr injects standard tools
25
+ - Model requests tool execution
26
+ - Tools run on Lynkr server
27
+ - Results sent back to model
28
+
29
+ **Benefits:**
30
+ - ✅ Centralized control
31
+ - ✅ Policy enforcement
32
+ - ✅ Consistent environment
33
+ - ✅ Works with any client
34
+
35
+ **Use cases:**
36
+ - Production deployments
37
+ - Team environments
38
+ - Policy-enforced workflows
39
+ - Air-gapped deployments
40
+
41
+ **Configuration:**
42
+ ```bash
43
+ # Default - no configuration needed
44
+ # Server mode activates when client doesn't send tools
45
+ ```
46
+
47
+ ### Client Mode (Passthrough)
48
+
49
+ **How it works:**
50
+ - Client sends request with tools
51
+ - Lynkr passes tools to model
52
+ - Model requests tool execution
53
+ - Client executes tools locally
54
+ - Results sent back through Lynkr
55
+
56
+ **Benefits:**
57
+ - ✅ Local file system access
58
+ - ✅ User-specific permissions
59
+ - ✅ No server-side execution
60
+ - ✅ Familiar CLI behavior
61
+
62
+ **Use cases:**
63
+ - Claude Code CLI (default behavior)
64
+ - Local development
65
+ - Personal use
66
+ - Custom tooling
67
+
68
+ **Configuration:**
69
+ ```bash
70
+ # Client sends tools in request
71
+ # Lynkr automatically uses passthrough mode
72
+ ```
73
+
74
+ ---
75
+
76
+ ## Built-in Tools
77
+
78
+ ### File Operations
79
+
80
+ #### Read Tool
81
+ **Purpose:** Read file contents
82
+
83
+ **Parameters:**
84
+ - `file_path` (string, required): Absolute path to file
85
+ - `offset` (number, optional): Line number to start reading from
86
+ - `limit` (number, optional): Number of lines to read
87
+
88
+ **Example:**
89
+ ```json
90
+ {
91
+ "name": "Read",
92
+ "input": {
93
+ "file_path": "/path/to/file.js",
94
+ "offset": 0,
95
+ "limit": 100
96
+ }
97
+ }
98
+ ```
99
+
100
+ **Features:**
101
+ - Automatic truncation (2,000 lines max)
102
+ - Line numbering
103
+ - UTF-8 support
104
+
105
+ #### Write Tool
106
+ **Purpose:** Write content to file
107
+
108
+ **Parameters:**
109
+ - `file_path` (string, required): Absolute path to file
110
+ - `content` (string, required): File content
111
+
112
+ **Example:**
113
+ ```json
114
+ {
115
+ "name": "Write",
116
+ "input": {
117
+ "file_path": "/path/to/file.js",
118
+ "content": "console.log('Hello');"
119
+ }
120
+ }
121
+ ```
122
+
123
+ **Features:**
124
+ - Creates directories if needed
125
+ - Overwrites existing files
126
+ - UTF-8 encoding
127
+
128
+ #### Edit Tool
129
+ **Purpose:** Find and replace in file
130
+
131
+ **Parameters:**
132
+ - `file_path` (string, required): Absolute path to file
133
+ - `old_string` (string, required): Text to find
134
+ - `new_string` (string, required): Replacement text
135
+ - `replace_all` (boolean, optional): Replace all occurrences
136
+
137
+ **Example:**
138
+ ```json
139
+ {
140
+ "name": "Edit",
141
+ "input": {
142
+ "file_path": "/path/to/file.js",
143
+ "old_string": "var x = 1;",
144
+ "new_string": "const x = 1;",
145
+ "replace_all": true
146
+ }
147
+ }
148
+ ```
149
+
150
+ ### Git Operations
151
+
152
+ #### git_status Tool
153
+ **Purpose:** Check git repository status
154
+
155
+ **Example:**
156
+ ```json
157
+ {
158
+ "name": "git_status",
159
+ "input": {}
160
+ }
161
+ ```
162
+
163
+ **Returns:**
164
+ - Untracked files
165
+ - Modified files
166
+ - Staged changes
167
+ - Current branch
168
+
169
+ #### git_diff Tool
170
+ **Purpose:** Show git diff
171
+
172
+ **Parameters:**
173
+ - `staged` (boolean, optional): Show staged changes only
174
+
175
+ **Example:**
176
+ ```json
177
+ {
178
+ "name": "git_diff",
179
+ "input": {
180
+ "staged": false
181
+ }
182
+ }
183
+ ```
184
+
185
+ #### git_commit Tool
186
+ **Purpose:** Create git commit
187
+
188
+ **Parameters:**
189
+ - `message` (string, required): Commit message
190
+ - `files` (array, optional): Files to stage and commit
191
+
192
+ **Example:**
193
+ ```json
194
+ {
195
+ "name": "git_commit",
196
+ "input": {
197
+ "message": "Fix authentication bug",
198
+ "files": ["src/auth.js", "test/auth.test.js"]
199
+ }
200
+ }
201
+ ```
202
+
203
+ **Policy enforcement:**
204
+ ```bash
205
+ # Prevent git push
206
+ POLICY_GIT_ALLOW_PUSH=false
207
+
208
+ # Require tests before commit
209
+ POLICY_GIT_REQUIRE_TESTS=true
210
+ POLICY_GIT_TEST_COMMAND="npm test"
211
+ ```
212
+
213
+ ### Bash Execution
214
+
215
+ #### Bash Tool
216
+ **Purpose:** Execute shell commands
217
+
218
+ **Parameters:**
219
+ - `command` (string, required): Shell command to execute
220
+ - `timeout` (number, optional): Timeout in milliseconds (default: 120000)
221
+
222
+ **Example:**
223
+ ```json
224
+ {
225
+ "name": "Bash",
226
+ "input": {
227
+ "command": "npm test",
228
+ "timeout": 60000
229
+ }
230
+ }
231
+ ```
232
+
233
+ **Features:**
234
+ - Automatic truncation (1,000 lines max)
235
+ - Working directory preservation
236
+ - Environment variable access
237
+ - Timeout protection
238
+
239
+ **Security:**
240
+ ```bash
241
+ # Commands are NOT sandboxed by default
242
+ # Use with caution in server mode
243
+ ```
244
+
245
+ ### Search Operations
246
+
247
+ #### Grep Tool
248
+ **Purpose:** Search file contents (ripgrep-powered)
249
+
250
+ **Parameters:**
251
+ - `pattern` (string, required): Regex pattern to search
252
+ - `path` (string, optional): Directory to search (default: workspace)
253
+ - `glob` (string, optional): File pattern filter (e.g., "*.js")
254
+ - `type` (string, optional): File type (e.g., "js", "py")
255
+ - `output_mode` (string, optional): "content", "files_with_matches", "count"
256
+
257
+ **Example:**
258
+ ```json
259
+ {
260
+ "name": "Grep",
261
+ "input": {
262
+ "pattern": "function.*Auth",
263
+ "glob": "*.js",
264
+ "output_mode": "content"
265
+ }
266
+ }
267
+ ```
268
+
269
+ #### Glob Tool
270
+ **Purpose:** Find files by pattern
271
+
272
+ **Parameters:**
273
+ - `pattern` (string, required): Glob pattern (e.g., "**/*.js")
274
+ - `path` (string, optional): Directory to search
275
+
276
+ **Example:**
277
+ ```json
278
+ {
279
+ "name": "Glob",
280
+ "input": {
281
+ "pattern": "src/**/*.test.js"
282
+ }
283
+ }
284
+ ```
285
+
286
+ ### Memory Operations
287
+
288
+ #### memory_search Tool
289
+ **Purpose:** Search long-term memories
290
+
291
+ **Parameters:**
292
+ - `query` (string, required): Search query
293
+
294
+ **Example:**
295
+ ```json
296
+ {
297
+ "name": "memory_search",
298
+ "input": {
299
+ "query": "authentication preferences"
300
+ }
301
+ }
302
+ ```
303
+
304
+ **Returns:**
305
+ - Top N relevant memories (default: 5)
306
+ - Memory type, content, importance
307
+ - Creation and access timestamps
308
+
309
+ #### memory_add Tool
310
+ **Purpose:** Manually add memory
311
+
312
+ **Parameters:**
313
+ - `content` (string, required): Memory content
314
+ - `memory_type` (string, required): "preference", "decision", "fact", "entity", "relationship"
315
+ - `importance` (number, optional): 0.0-1.0 (default: 1.0)
316
+
317
+ **Example:**
318
+ ```json
319
+ {
320
+ "name": "memory_add",
321
+ "input": {
322
+ "content": "User prefers TypeScript over JavaScript",
323
+ "memory_type": "preference",
324
+ "importance": 0.9
325
+ }
326
+ }
327
+ ```
328
+
329
+ #### memory_forget Tool
330
+ **Purpose:** Delete specific memory
331
+
332
+ **Parameters:**
333
+ - `query` (string, required): Search query to find memory to delete
334
+
335
+ **Example:**
336
+ ```json
337
+ {
338
+ "name": "memory_forget",
339
+ "input": {
340
+ "query": "old preference about MongoDB"
341
+ }
342
+ }
343
+ ```
344
+
345
+ ---
346
+
347
+ ## MCP Integration
348
+
349
+ ### Model Context Protocol (MCP)
350
+
351
+ Lynkr supports MCP for dynamic tool registration.
352
+
353
+ **Features:**
354
+ - Automatic MCP server discovery
355
+ - JSON-RPC 2.0 communication
356
+ - Dynamic tool registration
357
+ - Optional sandbox isolation
358
+
359
+ ### MCP Configuration
360
+
361
+ **Enable MCP:**
362
+ ```bash
363
+ MCP_ENABLED=true # default: true
364
+ ```
365
+
366
+ **Sandbox mode:**
367
+ ```bash
368
+ # Enable Docker sandbox for MCP tools
369
+ MCP_SANDBOX_ENABLED=true # default: true
370
+
371
+ # Docker image for sandbox
372
+ MCP_SANDBOX_IMAGE=ubuntu:22.04
373
+ ```
374
+
375
+ ### MCP Server Discovery
376
+
377
+ **Locations searched:**
378
+ 1. `./mcp-servers/` (workspace directory)
379
+ 2. `~/.mcp/servers/` (user directory)
380
+ 3. Environment variable: `MCP_SERVER_PATH`
381
+
382
+ **Example MCP server:**
383
+ ```json
384
+ {
385
+ "name": "my-custom-tool",
386
+ "description": "Does something useful",
387
+ "inputSchema": {
388
+ "type": "object",
389
+ "properties": {
390
+ "input": {
391
+ "type": "string",
392
+ "description": "Input parameter"
393
+ }
394
+ },
395
+ "required": ["input"]
396
+ }
397
+ }
398
+ ```
399
+
400
+ ### Using MCP Tools
401
+
402
+ MCP tools are automatically registered and available to models:
403
+
404
+ ```json
405
+ {
406
+ "name": "my-custom-tool",
407
+ "input": {
408
+ "input": "test value"
409
+ }
410
+ }
411
+ ```
412
+
413
+ ---
414
+
415
+ ## Custom Tool Development
416
+
417
+ ### Creating Custom Tools
418
+
419
+ **File structure:**
420
+ ```
421
+ src/tools/
422
+ ├── workspace.js (Read, Write, Edit)
423
+ ├── git.js (git_status, git_diff, git_commit)
424
+ ├── bash.js (Bash)
425
+ ├── search.js (Grep, Glob)
426
+ ├── memory.js (memory_search, memory_add, memory_forget)
427
+ └── custom.js (Your custom tools)
428
+ ```
429
+
430
+ **Custom tool template:**
431
+ ```javascript
432
+ // src/tools/custom.js
433
+
434
+ const logger = require("pino")();
435
+
436
+ /**
437
+ * Custom tool definition
438
+ */
439
+ const myCustomTool = {
440
+ name: "my_custom_tool",
441
+ description: "Does something useful",
442
+ input_schema: {
443
+ type: "object",
444
+ properties: {
445
+ input: {
446
+ type: "string",
447
+ description: "Input parameter"
448
+ }
449
+ },
450
+ required: ["input"]
451
+ }
452
+ };
453
+
454
+ /**
455
+ * Custom tool implementation
456
+ */
457
+ async function executeMyCustomTool(input) {
458
+ try {
459
+ logger.info({ input }, "Executing my_custom_tool");
460
+
461
+ // Your tool logic here
462
+ const result = doSomething(input);
463
+
464
+ return {
465
+ success: true,
466
+ result: result
467
+ };
468
+ } catch (error) {
469
+ logger.error({ error }, "my_custom_tool failed");
470
+ throw error;
471
+ }
472
+ }
473
+
474
+ module.exports = {
475
+ myCustomTool,
476
+ executeMyCustomTool
477
+ };
478
+ ```
479
+
480
+ ### Registering Custom Tools
481
+
482
+ **File:** `src/tools/index.js`
483
+
484
+ ```javascript
485
+ const { myCustomTool, executeMyCustomTool } = require("./custom");
486
+
487
+ // Add to STANDARD_TOOLS
488
+ const STANDARD_TOOLS = [
489
+ // ... existing tools
490
+ myCustomTool
491
+ ];
492
+
493
+ // Add to tool executor
494
+ async function executeTool(toolName, toolInput) {
495
+ switch (toolName) {
496
+ // ... existing cases
497
+ case "my_custom_tool":
498
+ return await executeMyCustomTool(toolInput);
499
+ default:
500
+ throw new Error(`Unknown tool: ${toolName}`);
501
+ }
502
+ }
503
+ ```
504
+
505
+ ### Tool Best Practices
506
+
507
+ 1. **Error handling:**
508
+ ```javascript
509
+ try {
510
+ // Tool logic
511
+ } catch (error) {
512
+ logger.error({ error, input }, "Tool execution failed");
513
+ throw new Error(`Tool failed: ${error.message}`);
514
+ }
515
+ ```
516
+
517
+ 2. **Input validation:**
518
+ ```javascript
519
+ function validateInput(input) {
520
+ if (!input || typeof input !== "string") {
521
+ throw new Error("Invalid input: expected string");
522
+ }
523
+ }
524
+ ```
525
+
526
+ 3. **Logging:**
527
+ ```javascript
528
+ logger.info({
529
+ toolName: "my_custom_tool",
530
+ input: input,
531
+ duration: Date.now() - startTime
532
+ }, "Tool executed successfully");
533
+ ```
534
+
535
+ 4. **Timeout protection:**
536
+ ```javascript
537
+ const timeout = 30000; // 30 seconds
538
+ const result = await Promise.race([
539
+ executeTool(input),
540
+ new Promise((_, reject) =>
541
+ setTimeout(() => reject(new Error("Tool timeout")), timeout)
542
+ )
543
+ ]);
544
+ ```
545
+
546
+ ---
547
+
548
+ ## Tool Policies
549
+
550
+ ### Git Policies
551
+
552
+ **Prevent git push:**
553
+ ```bash
554
+ POLICY_GIT_ALLOW_PUSH=false
555
+ ```
556
+
557
+ **Require tests before commit:**
558
+ ```bash
559
+ POLICY_GIT_REQUIRE_TESTS=true
560
+ POLICY_GIT_TEST_COMMAND="npm test"
561
+ ```
562
+
563
+ **Example:**
564
+ ```
565
+ User: "Commit these changes"
566
+ Assistant: *Runs git commit*
567
+ Lynkr: [Blocks] Running tests first (POLICY_GIT_REQUIRE_TESTS=true)
568
+ Lynkr: *Executes npm test*
569
+ Lynkr: Tests passed, proceeding with commit
570
+ ```
571
+
572
+ ### Web Fetch Policies
573
+
574
+ **Restrict allowed hosts:**
575
+ ```bash
576
+ WEB_SEARCH_ALLOWED_HOSTS=github.com,stackoverflow.com
577
+ ```
578
+
579
+ **Custom search endpoint:**
580
+ ```bash
581
+ WEB_SEARCH_ENDPOINT=http://localhost:8888/search
582
+ ```
583
+
584
+ ### Workspace Policies
585
+
586
+ **Restrict workspace access:**
587
+ ```bash
588
+ WORKSPACE_ROOT=/path/to/projects
589
+ ```
590
+
591
+ **Max agent loop iterations:**
592
+ ```bash
593
+ POLICY_MAX_STEPS=8
594
+ ```
595
+
596
+ ---
597
+
598
+ ## Tool Security
599
+
600
+ ### Server Mode Security
601
+
602
+ **Risks:**
603
+ - Tools run with Lynkr server permissions
604
+ - Can access server filesystem
605
+ - Can execute arbitrary commands
606
+
607
+ **Mitigations:**
608
+ 1. **Run as unprivileged user:**
609
+ ```bash
610
+ # Create dedicated user
611
+ useradd -r -s /bin/false lynkr
612
+
613
+ # Run as lynkr user
614
+ sudo -u lynkr npm start
615
+ ```
616
+
617
+ 2. **Use Docker isolation:**
618
+ ```yaml
619
+ # docker-compose.yml
620
+ services:
621
+ lynkr:
622
+ user: "1000:1000" # Non-root user
623
+ read_only: true # Read-only root filesystem
624
+ volumes:
625
+ - ./workspace:/workspace # Limited access
626
+ ```
627
+
628
+ 3. **Enable policies:**
629
+ ```bash
630
+ POLICY_GIT_ALLOW_PUSH=false
631
+ POLICY_GIT_REQUIRE_TESTS=true
632
+ WEB_SEARCH_ALLOWED_HOSTS=github.com
633
+ WORKSPACE_ROOT=/workspace
634
+ ```
635
+
636
+ ### Client Mode Security
637
+
638
+ **Risks:**
639
+ - Tools run with client user permissions
640
+ - Can access client filesystem
641
+ - Can execute commands on client machine
642
+
643
+ **Mitigations:**
644
+ - Review tool calls before execution
645
+ - Use Claude Code CLI safety features
646
+ - Run client in restricted environment
647
+
648
+ ---
649
+
650
+ ## Debugging Tools
651
+
652
+ ### Enable tool logging
653
+
654
+ ```bash
655
+ LOG_LEVEL=debug npm start
656
+ ```
657
+
658
+ **Output:**
659
+ ```json
660
+ {
661
+ "level": "debug",
662
+ "msg": "Tool executed",
663
+ "toolName": "Read",
664
+ "input": {"file_path": "/path/to/file.js"},
665
+ "duration": 12,
666
+ "success": true
667
+ }
668
+ ```
669
+
670
+ ### Test tool execution
671
+
672
+ ```bash
673
+ # Test Read tool
674
+ curl -X POST http://localhost:8081/v1/messages \
675
+ -H "Content-Type: application/json" \
676
+ -d '{
677
+ "model": "claude-3.5-sonnet",
678
+ "messages": [{"role": "user", "content": "Read package.json"}],
679
+ "max_tokens": 1024
680
+ }'
681
+ ```
682
+
683
+ ---
684
+
685
+ ## Next Steps
686
+
687
+ - **[MCP Integration Guide](mcp.md)** - Model Context Protocol setup
688
+ - **[Production Guide](production.md)** - Production deployment
689
+ - **[API Reference](api.md)** - API endpoints
690
+ - **[FAQ](faq.md)** - Common questions
691
+
692
+ ---
693
+
694
+ ## Getting Help
695
+
696
+ - **[GitHub Discussions](https://github.com/vishalveerareddy123/Lynkr/discussions)** - Ask questions
697
+ - **[GitHub Issues](https://github.com/vishalveerareddy123/Lynkr/issues)** - Report issues