create-bk-agent 0.23.4 → 0.23.6

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 (45) hide show
  1. package/README.md +0 -2
  2. package/dist/src/add/modules/knowledge.js +18 -18
  3. package/dist/src/add/modules/server.js +1 -1
  4. package/dist/src/add/patcher.js +106 -68
  5. package/dist/src/scaffold.js +29 -16
  6. package/package.json +2 -2
  7. package/templates/README.md +26 -0
  8. package/templates/base/autonomous/package.json +1 -1
  9. package/templates/base/autonomous/src/index.ts +83 -83
  10. package/templates/base/coding/package.json +1 -1
  11. package/templates/base/enterprise/package.json +1 -1
  12. package/templates/base/minimal/package.json +1 -1
  13. package/templates/base/minimal/src/index.ts +43 -43
  14. package/templates/base/multi-agent/package.json +2 -2
  15. package/templates/base/multi-agent/src/engine.ts +78 -78
  16. package/templates/base/single/package.json +2 -2
  17. package/templates/base/single/src/engine.ts +67 -67
  18. package/templates/autonomous/.env.example +0 -8
  19. package/templates/autonomous/package.json +0 -25
  20. package/templates/autonomous/src/index.ts +0 -64
  21. package/templates/autonomous/tsconfig.json +0 -16
  22. package/templates/base/multi-agent/src/providers/openai-compatible.ts +0 -104
  23. package/templates/base/single/src/providers/openai-compatible.ts +0 -104
  24. package/templates/coding/.env.example +0 -8
  25. package/templates/coding/package.json +0 -26
  26. package/templates/coding/src/index.ts +0 -42
  27. package/templates/coding/tsconfig.json +0 -17
  28. package/templates/domain-agent/.env.example +0 -7
  29. package/templates/domain-agent/package.json +0 -27
  30. package/templates/domain-agent/src/agents/orchestrator.ts +0 -22
  31. package/templates/domain-agent/src/agents/specialist-a.ts +0 -17
  32. package/templates/domain-agent/src/agents/specialist-b.ts +0 -16
  33. package/templates/domain-agent/src/config.ts +0 -19
  34. package/templates/domain-agent/src/engine.ts +0 -49
  35. package/templates/domain-agent/src/index.ts +0 -27
  36. package/templates/domain-agent/src/providers/openai-compatible.ts +0 -104
  37. package/templates/domain-agent/src/tools/example-tools.ts +0 -28
  38. package/templates/domain-agent/tsconfig.json +0 -17
  39. package/templates/mcp-server/package.json +0 -30
  40. package/templates/mcp-server/src/server.ts +0 -40
  41. package/templates/mcp-server/src/tools/example.ts +0 -10
  42. package/templates/mcp-server/tsconfig.json +0 -16
  43. package/templates/minimal/package.json +0 -25
  44. package/templates/minimal/src/index.ts +0 -40
  45. package/templates/minimal/tsconfig.json +0 -16
@@ -1,104 +0,0 @@
1
- import OpenAI from 'openai';
2
- import type { LLMProvider, LLMMessage, LLMStreamCallbacks, ToolDefinition } from '@backendkit-labs/agent-core';
3
-
4
- export interface OpenAICompatibleProviderOptions {
5
- apiKey: string;
6
- baseUrl: string;
7
- model: string;
8
- maxRetries?: number;
9
- }
10
-
11
- function isRetryable(err: unknown): boolean {
12
- if (err && typeof err === 'object' && 'status' in err) {
13
- const s = (err as { status: number }).status;
14
- return s === 429 || s >= 500;
15
- }
16
- return false;
17
- }
18
-
19
- const sleep = (ms: number) => new Promise<void>(r => setTimeout(r, ms));
20
-
21
- export class OpenAICompatibleProvider implements LLMProvider {
22
- private readonly client: OpenAI;
23
- private readonly model: string;
24
- private readonly maxRetries: number;
25
-
26
- constructor(opts: OpenAICompatibleProviderOptions) {
27
- this.client = new OpenAI({ apiKey: opts.apiKey, baseURL: opts.baseUrl, maxRetries: 0 });
28
- this.model = opts.model;
29
- this.maxRetries = opts.maxRetries ?? 3;
30
- }
31
-
32
- async chat(messages: LLMMessage[], tools: ToolDefinition[], callbacks: LLMStreamCallbacks): Promise<void> {
33
- const oaiTools = tools.map(t => ({
34
- type: 'function' as const,
35
- function: { name: t.name, description: t.description, parameters: t.parameters },
36
- })) as OpenAI.Chat.ChatCompletionTool[];
37
-
38
- let attempt = 0;
39
- let emitted = false;
40
-
41
- while (attempt < this.maxRetries) {
42
- attempt++;
43
- try {
44
- await this.stream(messages, oaiTools, {
45
- ...callbacks,
46
- onChunk: (d) => { emitted = true; callbacks.onChunk?.(d); },
47
- });
48
- return;
49
- } catch (err) {
50
- if (emitted || !isRetryable(err) || attempt >= this.maxRetries) {
51
- callbacks.onError(err instanceof Error ? err : new Error(String(err)));
52
- return;
53
- }
54
- await sleep(Math.min(1000 * 2 ** attempt, 16_000));
55
- }
56
- }
57
- }
58
-
59
- private async stream(
60
- messages: LLMMessage[],
61
- oaiTools: OpenAI.Chat.ChatCompletionTool[],
62
- callbacks: LLMStreamCallbacks,
63
- ): Promise<void> {
64
- const stream = await this.client.chat.completions.create({
65
- model: this.model,
66
- messages: messages as OpenAI.Chat.ChatCompletionMessageParam[],
67
- tools: oaiTools.length ? oaiTools : undefined,
68
- tool_choice: oaiTools.length ? 'auto' : undefined,
69
- stream: true,
70
- stream_options: { include_usage: true },
71
- });
72
-
73
- let content = '';
74
- const toolBuffers = new Map<number, { id: string; name: string; args: string }>();
75
-
76
- for await (const chunk of stream) {
77
- if (chunk.usage) callbacks.onMetrics?.(chunk.usage.prompt_tokens, chunk.usage.completion_tokens);
78
- const delta = chunk.choices[0]?.delta;
79
- if (!delta) continue;
80
- if (delta.content) { content += delta.content; callbacks.onChunk?.(delta.content); }
81
- if (delta.tool_calls) {
82
- for (const tc of delta.tool_calls) {
83
- if (!toolBuffers.has(tc.index)) toolBuffers.set(tc.index, { id: '', name: '', args: '' });
84
- const buf = toolBuffers.get(tc.index)!;
85
- if (tc.id) buf.id = tc.id;
86
- if (tc.function?.name) buf.name += tc.function.name;
87
- if (tc.function?.arguments) buf.args += tc.function.arguments;
88
- }
89
- }
90
- }
91
-
92
- const toolCalls = [...toolBuffers.entries()]
93
- .sort(([a], [b]) => a - b)
94
- .map(([, b]) => ({ id: b.id, type: 'function' as const, function: { name: b.name, arguments: b.args } }));
95
-
96
- for (const tc of toolCalls) callbacks.onToolCall?.(tc.function.name, tc.function.arguments, tc.id);
97
-
98
- callbacks.onDone({
99
- role: 'assistant',
100
- content: content || null,
101
- tool_calls: toolCalls.length ? toolCalls : undefined,
102
- });
103
- }
104
- }
@@ -1,8 +0,0 @@
1
- # LLM provider — pick one
2
- ANTHROPIC_API_KEY=sk-ant-...
3
- # OPENAI_API_KEY=sk-...
4
- # DEEPSEEK_API_KEY=...
5
-
6
- # Provider to use: anthropic | openai | deepseek
7
- LLM_PROVIDER=anthropic
8
- LLM_MODEL=claude-sonnet-4-6
@@ -1,26 +0,0 @@
1
- {
2
- "name": "my-coding-agent",
3
- "version": "0.1.0",
4
- "private": true,
5
- "description": "Coding assistant agent — edit files, run commands, search code",
6
- "main": "dist/index.js",
7
- "scripts": {
8
- "dev": "ts-node src/index.ts",
9
- "build": "tsc",
10
- "start": "node dist/index.js",
11
- "typecheck": "tsc --noEmit"
12
- },
13
- "dependencies": {
14
- "@backendkit-labs/agent-coding": "^0.28.0",
15
- "@backendkit-labs/agent-core": "^0.36.0",
16
- "dotenv": "^16.0.0"
17
- },
18
- "devDependencies": {
19
- "@types/node": "^20.0.0",
20
- "ts-node": "^10.9.0",
21
- "typescript": "^5.4.0"
22
- },
23
- "engines": {
24
- "node": ">=20.0.0"
25
- }
26
- }
@@ -1,42 +0,0 @@
1
- import 'dotenv/config';
2
- import * as readline from 'readline';
3
- import { createCodingEngine, TerminalTransport } from '@backendkit-labs/agent-coding';
4
-
5
- // ── Provider setup ────────────────────────────────────────────────────────────
6
-
7
- const provider = process.env.LLM_PROVIDER ?? 'anthropic';
8
- const apiKey = process.env.ANTHROPIC_API_KEY ?? process.env.OPENAI_API_KEY ?? process.env.LLM_API_KEY ?? '';
9
- const model = process.env.LLM_MODEL;
10
-
11
- if (!apiKey) {
12
- console.error('Missing API key. Set ANTHROPIC_API_KEY or OPENAI_API_KEY in .env');
13
- process.exit(1);
14
- }
15
-
16
- // ── Engine ────────────────────────────────────────────────────────────────────
17
-
18
- const transport = new TerminalTransport();
19
-
20
- const engine = createCodingEngine({
21
- providers: { [provider]: { apiKey, ...(model ? { model } : {}) } },
22
- defaultProvider: provider,
23
- workingDir: process.cwd(),
24
- appName: 'my-coding-agent',
25
- transport,
26
- });
27
-
28
- // ── REPL ──────────────────────────────────────────────────────────────────────
29
-
30
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
31
-
32
- function prompt() {
33
- rl.question('\n❯ ', async (input) => {
34
- const trimmed = input.trim();
35
- if (!trimmed || trimmed === '/exit') { rl.close(); return; }
36
- await engine.run(trimmed);
37
- prompt();
38
- });
39
- }
40
-
41
- console.log('Coding agent ready. Type your request or /exit to quit.\n');
42
- prompt();
@@ -1,17 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "commonjs",
5
- "moduleResolution": "node16",
6
- "lib": ["ES2022"],
7
- "types": ["node"],
8
- "outDir": "dist",
9
- "rootDir": "src",
10
- "strict": true,
11
- "skipLibCheck": true,
12
- "esModuleInterop": true,
13
- "resolveJsonModule": true
14
- },
15
- "include": ["src/**/*"],
16
- "exclude": ["node_modules", "dist"]
17
- }
@@ -1,7 +0,0 @@
1
- # LLM — any OpenAI-compatible endpoint
2
- LLM_API_KEY=sk-...
3
- LLM_BASE_URL=https://api.openai.com/v1
4
- LLM_MODEL=gpt-4o
5
-
6
- # TODO: Add your domain-specific env vars here
7
- # MY_SERVICE_URL=http://localhost:8080
@@ -1,27 +0,0 @@
1
- {
2
- "name": "my-domain-agent",
3
- "version": "0.1.0",
4
- "private": true,
5
- "description": "Multi-agent system: orchestrator + domain specialists",
6
- "main": "dist/index.js",
7
- "scripts": {
8
- "dev": "ts-node src/index.ts",
9
- "build": "tsc",
10
- "start": "node dist/index.js",
11
- "typecheck": "tsc --noEmit"
12
- },
13
- "dependencies": {
14
- "@backendkit-labs/agent-core": "^0.36.0",
15
- "dotenv": "^16.0.0",
16
- "openai": "^4.0.0",
17
- "zod": "^4.6.6"
18
- },
19
- "devDependencies": {
20
- "@types/node": "^20.0.0",
21
- "ts-node": "^10.9.0",
22
- "typescript": "^5.4.0"
23
- },
24
- "engines": {
25
- "node": ">=20.0.0"
26
- }
27
- }
@@ -1,22 +0,0 @@
1
- import type { AgentProfile } from '@backendkit-labs/agent-core';
2
-
3
- // The orchestrator receives every user request and delegates to the right specialist.
4
- // It does NOT call tools directly — it uses ask_agent to route work.
5
- export const ORCHESTRATOR_PROFILE: AgentProfile = {
6
- id: 'orchestrator',
7
- name: 'Orchestrator',
8
- icon: '🎯',
9
- description: 'Routes requests to the right specialist agent',
10
- delegatesTo: ['specialist-a', 'specialist-b'], // TODO: list your specialists
11
- allowedTools: [],
12
- systemPrompt: `You are the orchestrator for a TODO: <describe your domain> system.
13
-
14
- Your ONLY job is to analyze the user request and delegate to the right specialist via ask_agent.
15
- Do not attempt to handle requests directly.
16
-
17
- Available specialists:
18
- - specialist-a: TODO describe what this specialist handles
19
- - specialist-b: TODO describe what this specialist handles
20
-
21
- Always delegate. Never answer directly.`,
22
- };
@@ -1,17 +0,0 @@
1
- import type { AgentProfile } from '@backendkit-labs/agent-core';
2
-
3
- // TODO: Rename this file and agent to match your domain (e.g. docker-agent.ts, k8s-agent.ts)
4
- export const SPECIALIST_A_PROFILE: AgentProfile = {
5
- id: 'specialist-a',
6
- name: 'Specialist A',
7
- icon: '🔧',
8
- description: 'TODO: describe what this specialist does',
9
- delegatesTo: [],
10
- allowedTools: [
11
- 'example_action', // TODO: list the tool names this agent can use
12
- ],
13
- systemPrompt: `You are a specialist in TODO: <your domain area>.
14
-
15
- Use the available tools to complete the task delegated to you.
16
- Be precise and report results clearly.`,
17
- };
@@ -1,16 +0,0 @@
1
- import type { AgentProfile } from '@backendkit-labs/agent-core';
2
-
3
- // TODO: Rename and customize for your second specialist
4
- export const SPECIALIST_B_PROFILE: AgentProfile = {
5
- id: 'specialist-b',
6
- name: 'Specialist B',
7
- icon: '📊',
8
- description: 'TODO: describe what this specialist does',
9
- delegatesTo: [],
10
- allowedTools: [
11
- 'example_query', // TODO: list the tool names this agent can use
12
- ],
13
- systemPrompt: `You are a specialist in TODO: <your domain area>.
14
-
15
- Use the available tools to complete the task delegated to you.`,
16
- };
@@ -1,19 +0,0 @@
1
- import 'dotenv/config';
2
-
3
- export interface Config {
4
- llmApiKey: string;
5
- llmBaseUrl: string;
6
- llmModel: string;
7
- // TODO: add your domain-specific config fields
8
- }
9
-
10
- export function loadConfig(): Config {
11
- const llmApiKey = process.env.LLM_API_KEY ?? '';
12
- if (!llmApiKey) throw new Error('Missing LLM_API_KEY in environment');
13
-
14
- return {
15
- llmApiKey,
16
- llmBaseUrl: process.env.LLM_BASE_URL ?? 'https://api.openai.com/v1',
17
- llmModel: process.env.LLM_MODEL ?? 'gpt-4o',
18
- };
19
- }
@@ -1,49 +0,0 @@
1
- import {
2
- AgentEngine,
3
- AgentRegistry,
4
- ToolRegistry,
5
- ProviderRegistry,
6
- CallbackTransport,
7
- } from '@backendkit-labs/agent-core';
8
- import { OpenAICompatibleProvider } from './providers/openai-compatible';
9
- import { loadConfig } from './config';
10
- import { ORCHESTRATOR_PROFILE } from './agents/orchestrator';
11
- import { SPECIALIST_A_PROFILE } from './agents/specialist-a';
12
- import { SPECIALIST_B_PROFILE } from './agents/specialist-b';
13
- import { exampleAction, exampleQuery } from './tools/example-tools';
14
-
15
- export function createDomainEngine(transport: CallbackTransport): AgentEngine {
16
- const config = loadConfig();
17
-
18
- const tools = new ToolRegistry();
19
- tools
20
- .register(exampleAction)
21
- .register(exampleQuery);
22
- // TODO: register more tools
23
-
24
- const agents = new AgentRegistry();
25
- agents
26
- .register(ORCHESTRATOR_PROFILE)
27
- .register(SPECIALIST_A_PROFILE)
28
- .register(SPECIALIST_B_PROFILE);
29
- // TODO: register more specialists
30
-
31
- const providers = new ProviderRegistry();
32
- providers.register('default', new OpenAICompatibleProvider({
33
- apiKey: config.llmApiKey,
34
- baseUrl: config.llmBaseUrl,
35
- model: config.llmModel,
36
- }));
37
-
38
- return new AgentEngine({
39
- model: { provider: 'default', id: config.llmModel },
40
- agents,
41
- tools,
42
- providers,
43
- defaultProvider: 'default',
44
- defaultAgentId: 'orchestrator',
45
- transport,
46
- maxIterations: 30,
47
- iterationMode: 'auto',
48
- });
49
- }
@@ -1,27 +0,0 @@
1
- import * as readline from 'readline';
2
- import { CallbackTransport } from '@backendkit-labs/agent-core';
3
- import { createDomainEngine } from './engine';
4
-
5
- const transport = new CallbackTransport((event) => {
6
- if (event.type === 'token') process.stdout.write(event.content);
7
- if (event.type === 'tool_call') console.log(`\n⚙ ${event.name}`);
8
- if (event.type === 'agent_switch') console.log(`\n→ ${event.to_name ?? event.to}`);
9
- if (event.type === 'block_end') console.log();
10
- if (event.type === 'error') console.error(`\nError: ${event.message}`);
11
- });
12
-
13
- const engine = createDomainEngine(transport);
14
-
15
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
16
-
17
- function prompt() {
18
- rl.question('\n> ', async (input) => {
19
- const trimmed = input.trim();
20
- if (!trimmed || trimmed === '/exit') { rl.close(); return; }
21
- await engine.run(trimmed);
22
- prompt();
23
- });
24
- }
25
-
26
- console.log('Domain agent ready. Type your request or /exit to quit.\n');
27
- prompt();
@@ -1,104 +0,0 @@
1
- import OpenAI from 'openai';
2
- import type { LLMProvider, LLMMessage, LLMStreamCallbacks, ToolDefinition } from '@backendkit-labs/agent-core';
3
-
4
- export interface OpenAICompatibleProviderOptions {
5
- apiKey: string;
6
- baseUrl: string;
7
- model: string;
8
- maxRetries?: number;
9
- }
10
-
11
- function isRetryable(err: unknown): boolean {
12
- if (err && typeof err === 'object' && 'status' in err) {
13
- const s = (err as { status: number }).status;
14
- return s === 429 || s >= 500;
15
- }
16
- return false;
17
- }
18
-
19
- const sleep = (ms: number) => new Promise<void>(r => setTimeout(r, ms));
20
-
21
- export class OpenAICompatibleProvider implements LLMProvider {
22
- private readonly client: OpenAI;
23
- private readonly model: string;
24
- private readonly maxRetries: number;
25
-
26
- constructor(opts: OpenAICompatibleProviderOptions) {
27
- this.client = new OpenAI({ apiKey: opts.apiKey, baseURL: opts.baseUrl, maxRetries: 0 });
28
- this.model = opts.model;
29
- this.maxRetries = opts.maxRetries ?? 3;
30
- }
31
-
32
- async chat(messages: LLMMessage[], tools: ToolDefinition[], callbacks: LLMStreamCallbacks): Promise<void> {
33
- const oaiTools = tools.map(t => ({
34
- type: 'function' as const,
35
- function: { name: t.name, description: t.description, parameters: t.parameters },
36
- })) as OpenAI.Chat.ChatCompletionTool[];
37
-
38
- let attempt = 0;
39
- let emitted = false;
40
-
41
- while (attempt < this.maxRetries) {
42
- attempt++;
43
- try {
44
- await this.stream(messages, oaiTools, {
45
- ...callbacks,
46
- onChunk: (d) => { emitted = true; callbacks.onChunk?.(d); },
47
- });
48
- return;
49
- } catch (err) {
50
- if (emitted || !isRetryable(err) || attempt >= this.maxRetries) {
51
- callbacks.onError(err instanceof Error ? err : new Error(String(err)));
52
- return;
53
- }
54
- await sleep(Math.min(1000 * 2 ** attempt, 16_000));
55
- }
56
- }
57
- }
58
-
59
- private async stream(
60
- messages: LLMMessage[],
61
- oaiTools: OpenAI.Chat.ChatCompletionTool[],
62
- callbacks: LLMStreamCallbacks,
63
- ): Promise<void> {
64
- const stream = await this.client.chat.completions.create({
65
- model: this.model,
66
- messages: messages as OpenAI.Chat.ChatCompletionMessageParam[],
67
- tools: oaiTools.length ? oaiTools : undefined,
68
- tool_choice: oaiTools.length ? 'auto' : undefined,
69
- stream: true,
70
- stream_options: { include_usage: true },
71
- });
72
-
73
- let content = '';
74
- const toolBuffers = new Map<number, { id: string; name: string; args: string }>();
75
-
76
- for await (const chunk of stream) {
77
- if (chunk.usage) callbacks.onMetrics?.(chunk.usage.prompt_tokens, chunk.usage.completion_tokens);
78
- const delta = chunk.choices[0]?.delta;
79
- if (!delta) continue;
80
- if (delta.content) { content += delta.content; callbacks.onChunk?.(delta.content); }
81
- if (delta.tool_calls) {
82
- for (const tc of delta.tool_calls) {
83
- if (!toolBuffers.has(tc.index)) toolBuffers.set(tc.index, { id: '', name: '', args: '' });
84
- const buf = toolBuffers.get(tc.index)!;
85
- if (tc.id) buf.id = tc.id;
86
- if (tc.function?.name) buf.name += tc.function.name;
87
- if (tc.function?.arguments) buf.args += tc.function.arguments;
88
- }
89
- }
90
- }
91
-
92
- const toolCalls = [...toolBuffers.entries()]
93
- .sort(([a], [b]) => a - b)
94
- .map(([, b]) => ({ id: b.id, type: 'function' as const, function: { name: b.name, arguments: b.args } }));
95
-
96
- for (const tc of toolCalls) callbacks.onToolCall?.(tc.function.name, tc.function.arguments, tc.id);
97
-
98
- callbacks.onDone({
99
- role: 'assistant',
100
- content: content || null,
101
- tool_calls: toolCalls.length ? toolCalls : undefined,
102
- });
103
- }
104
- }
@@ -1,28 +0,0 @@
1
- import { defineTool, z } from '@backendkit-labs/agent-core';
2
-
3
- // TODO: Replace these with tools that call your actual domain SDK/API
4
-
5
- export const exampleAction = defineTool({
6
- name: 'example_action',
7
- description: 'TODO: describe what this tool does',
8
- input: z.object({
9
- target: z.string().describe('Target to act on'),
10
- // TODO: add more parameters
11
- }),
12
- execute: async ({ target }) => {
13
- // TODO: implement the actual action
14
- return `Action executed on: ${target}`;
15
- },
16
- });
17
-
18
- export const exampleQuery = defineTool({
19
- name: 'example_query',
20
- description: 'TODO: describe what this query returns',
21
- input: z.object({
22
- filter: z.string().optional().describe('Optional filter'),
23
- }),
24
- execute: async ({ filter }) => {
25
- // TODO: implement the actual query
26
- return JSON.stringify({ results: [], filter });
27
- },
28
- });
@@ -1,17 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "commonjs",
5
- "moduleResolution": "node16",
6
- "lib": ["ES2022"],
7
- "types": ["node"],
8
- "outDir": "dist",
9
- "rootDir": "src",
10
- "strict": true,
11
- "skipLibCheck": true,
12
- "esModuleInterop": true,
13
- "resolveJsonModule": true
14
- },
15
- "include": ["src/**/*"],
16
- "exclude": ["node_modules", "dist"]
17
- }
@@ -1,30 +0,0 @@
1
- {
2
- "name": "my-mcp-server",
3
- "version": "0.1.0",
4
- "private": true,
5
- "description": "MCP server — expose agent tools via Model Context Protocol",
6
- "main": "dist/server.js",
7
- "bin": {
8
- "my-mcp-server": "./dist/server.js"
9
- },
10
- "scripts": {
11
- "dev": "ts-node src/server.ts",
12
- "build": "tsc",
13
- "start": "node dist/server.js",
14
- "typecheck": "tsc --noEmit"
15
- },
16
- "dependencies": {
17
- "@backendkit-labs/agent-core": "^0.36.0",
18
- "@modelcontextprotocol/sdk": "^1.12.0",
19
- "dotenv": "^16.0.0",
20
- "zod": "^4.6.6"
21
- },
22
- "devDependencies": {
23
- "@types/node": "^20.0.0",
24
- "ts-node": "^10.9.0",
25
- "typescript": "^5.4.0"
26
- },
27
- "engines": {
28
- "node": ">=20.0.0"
29
- }
30
- }
@@ -1,40 +0,0 @@
1
- #!/usr/bin/env node
2
- import 'dotenv/config';
3
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
4
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
5
- import { z } from 'zod';
6
- import { exampleHandler, exampleInputSchema } from './tools/example';
7
-
8
- // ── MCP Server ────────────────────────────────────────────────────────────────
9
-
10
- const server = new McpServer({
11
- name: 'my-mcp-server',
12
- version: '0.1.0',
13
- });
14
-
15
- // ── Register tools ────────────────────────────────────────────────────────────
16
-
17
- // @ts-expect-error: MCP SDK + zod generic depth limit, safe at runtime
18
- server.tool(
19
- 'example_query',
20
- 'TODO: describe what this tool does',
21
- exampleInputSchema.shape,
22
- async (args: z.infer<typeof exampleInputSchema>) => ({
23
- content: [{ type: 'text' as const, text: await exampleHandler(args) }],
24
- }),
25
- );
26
-
27
- // TODO: register more tools following the same pattern:
28
- // server.tool('tool_name', 'description', schema.shape, handler)
29
-
30
- // ── Transport: stdio (for Claude Desktop / Cursor / VS Code) ─────────────────
31
-
32
- const transport = new StdioServerTransport();
33
- await server.connect(transport);
34
-
35
- // To use this server, add it to your MCP client config:
36
- // {
37
- // "mcpServers": {
38
- // "my-server": { "command": "npx", "args": ["my-mcp-server"] }
39
- // }
40
- // }
@@ -1,10 +0,0 @@
1
- import { z } from 'zod';
2
-
3
- export const exampleInputSchema = z.object({
4
- query: z.string().describe('The query to process'),
5
- });
6
-
7
- export async function exampleHandler({ query }: z.infer<typeof exampleInputSchema>): Promise<string> {
8
- // TODO: implement your tool logic
9
- return `Result for: ${query}`;
10
- }
@@ -1,16 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "commonjs",
5
- "moduleResolution": "node16",
6
- "lib": ["ES2022"],
7
- "types": ["node"],
8
- "outDir": "dist",
9
- "rootDir": "src",
10
- "strict": true,
11
- "skipLibCheck": true,
12
- "esModuleInterop": true
13
- },
14
- "include": ["src/**/*"],
15
- "exclude": ["node_modules", "dist"]
16
- }