@airmcp-dev/cli 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.
Files changed (122) hide show
  1. package/LICENSE +17 -0
  2. package/dist/commands/add.d.ts +3 -0
  3. package/dist/commands/add.d.ts.map +1 -0
  4. package/dist/commands/add.js +192 -0
  5. package/dist/commands/add.js.map +1 -0
  6. package/dist/commands/check.d.ts +3 -0
  7. package/dist/commands/check.d.ts.map +1 -0
  8. package/dist/commands/check.js +218 -0
  9. package/dist/commands/check.js.map +1 -0
  10. package/dist/commands/connect.d.ts +3 -0
  11. package/dist/commands/connect.d.ts.map +1 -0
  12. package/dist/commands/connect.js +135 -0
  13. package/dist/commands/connect.js.map +1 -0
  14. package/dist/commands/create.d.ts +3 -0
  15. package/dist/commands/create.d.ts.map +1 -0
  16. package/dist/commands/create.js +150 -0
  17. package/dist/commands/create.js.map +1 -0
  18. package/dist/commands/dev.d.ts +3 -0
  19. package/dist/commands/dev.d.ts.map +1 -0
  20. package/dist/commands/dev.js +184 -0
  21. package/dist/commands/dev.js.map +1 -0
  22. package/dist/commands/disconnect.d.ts +3 -0
  23. package/dist/commands/disconnect.d.ts.map +1 -0
  24. package/dist/commands/disconnect.js +69 -0
  25. package/dist/commands/disconnect.js.map +1 -0
  26. package/dist/commands/index.d.ts +13 -0
  27. package/dist/commands/index.d.ts.map +1 -0
  28. package/dist/commands/index.js +16 -0
  29. package/dist/commands/index.js.map +1 -0
  30. package/dist/commands/inspect.d.ts +3 -0
  31. package/dist/commands/inspect.d.ts.map +1 -0
  32. package/dist/commands/inspect.js +159 -0
  33. package/dist/commands/inspect.js.map +1 -0
  34. package/dist/commands/license.d.ts +3 -0
  35. package/dist/commands/license.d.ts.map +1 -0
  36. package/dist/commands/license.js +113 -0
  37. package/dist/commands/license.js.map +1 -0
  38. package/dist/commands/list.d.ts +3 -0
  39. package/dist/commands/list.d.ts.map +1 -0
  40. package/dist/commands/list.js +101 -0
  41. package/dist/commands/list.js.map +1 -0
  42. package/dist/commands/start.d.ts +3 -0
  43. package/dist/commands/start.d.ts.map +1 -0
  44. package/dist/commands/start.js +130 -0
  45. package/dist/commands/start.js.map +1 -0
  46. package/dist/commands/status.d.ts +3 -0
  47. package/dist/commands/status.d.ts.map +1 -0
  48. package/dist/commands/status.js +83 -0
  49. package/dist/commands/status.js.map +1 -0
  50. package/dist/commands/stop.d.ts +3 -0
  51. package/dist/commands/stop.d.ts.map +1 -0
  52. package/dist/commands/stop.js +56 -0
  53. package/dist/commands/stop.js.map +1 -0
  54. package/dist/index.d.ts +3 -0
  55. package/dist/index.d.ts.map +1 -0
  56. package/dist/index.js +46 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/templates/agent/.ai/context.md +36 -0
  59. package/dist/templates/agent/.vscode/air.code-snippets +178 -0
  60. package/dist/templates/agent/package.json +17 -0
  61. package/dist/templates/agent/src/index.ts +98 -0
  62. package/dist/templates/agent/tsconfig.json +14 -0
  63. package/dist/templates/agent-ko/.ai/context.md +36 -0
  64. package/dist/templates/agent-ko/.vscode/air.code-snippets +178 -0
  65. package/dist/templates/agent-ko/package.json +17 -0
  66. package/dist/templates/agent-ko/src/index.ts +92 -0
  67. package/dist/templates/agent-ko/tsconfig.json +14 -0
  68. package/dist/templates/api/.ai/context.md +36 -0
  69. package/dist/templates/api/.vscode/air.code-snippets +178 -0
  70. package/dist/templates/api/package.json +17 -0
  71. package/dist/templates/api/src/index.ts +76 -0
  72. package/dist/templates/api/tsconfig.json +14 -0
  73. package/dist/templates/api-ko/.ai/context.md +36 -0
  74. package/dist/templates/api-ko/.vscode/air.code-snippets +178 -0
  75. package/dist/templates/api-ko/package.json +17 -0
  76. package/dist/templates/api-ko/src/index.ts +70 -0
  77. package/dist/templates/api-ko/tsconfig.json +14 -0
  78. package/dist/templates/basic/.ai/context.md +36 -0
  79. package/dist/templates/basic/.vscode/air.code-snippets +178 -0
  80. package/dist/templates/basic/package.json +17 -0
  81. package/dist/templates/basic/src/index.ts +39 -0
  82. package/dist/templates/basic/tsconfig.json +15 -0
  83. package/dist/templates/basic-ko/.ai/context.md +36 -0
  84. package/dist/templates/basic-ko/.vscode/air.code-snippets +178 -0
  85. package/dist/templates/basic-ko/package.json +17 -0
  86. package/dist/templates/basic-ko/src/index.ts +39 -0
  87. package/dist/templates/basic-ko/tsconfig.json +14 -0
  88. package/dist/templates/crud/.ai/context.md +36 -0
  89. package/dist/templates/crud/.vscode/air.code-snippets +178 -0
  90. package/dist/templates/crud/package.json +17 -0
  91. package/dist/templates/crud/src/index.ts +82 -0
  92. package/dist/templates/crud/tsconfig.json +14 -0
  93. package/dist/templates/crud-ko/.ai/context.md +36 -0
  94. package/dist/templates/crud-ko/.vscode/air.code-snippets +178 -0
  95. package/dist/templates/crud-ko/package.json +17 -0
  96. package/dist/templates/crud-ko/src/index.ts +81 -0
  97. package/dist/templates/crud-ko/tsconfig.json +14 -0
  98. package/dist/utils/index.d.ts +7 -0
  99. package/dist/utils/index.d.ts.map +1 -0
  100. package/dist/utils/index.js +8 -0
  101. package/dist/utils/index.js.map +1 -0
  102. package/dist/utils/json-editor.d.ts +45 -0
  103. package/dist/utils/json-editor.d.ts.map +1 -0
  104. package/dist/utils/json-editor.js +122 -0
  105. package/dist/utils/json-editor.js.map +1 -0
  106. package/dist/utils/path-resolver.d.ts +30 -0
  107. package/dist/utils/path-resolver.d.ts.map +1 -0
  108. package/dist/utils/path-resolver.js +121 -0
  109. package/dist/utils/path-resolver.js.map +1 -0
  110. package/dist/utils/printer.d.ts +26 -0
  111. package/dist/utils/printer.d.ts.map +1 -0
  112. package/dist/utils/printer.js +65 -0
  113. package/dist/utils/printer.js.map +1 -0
  114. package/dist/utils/process-manager.d.ts +36 -0
  115. package/dist/utils/process-manager.d.ts.map +1 -0
  116. package/dist/utils/process-manager.js +143 -0
  117. package/dist/utils/process-manager.js.map +1 -0
  118. package/dist/utils/test-console.d.ts +8 -0
  119. package/dist/utils/test-console.d.ts.map +1 -0
  120. package/dist/utils/test-console.js +198 -0
  121. package/dist/utils/test-console.js.map +1 -0
  122. package/package.json +52 -0
@@ -0,0 +1,178 @@
1
+ {
2
+ // ═══════════════════════════════════════════
3
+ // air — MCP Server Development Snippets
4
+ // ═══════════════════════════════════════════
5
+
6
+ "air: defineServer": {
7
+ "prefix": "airserver",
8
+ "description": "Create a new MCP server with air",
9
+ "body": [
10
+ "import { defineServer, defineTool } from '@air/core';",
11
+ "",
12
+ "export default defineServer({",
13
+ " name: '${1:my-server}',",
14
+ " version: '${2:0.1.0}',",
15
+ " description: '${3:MCP server description}',",
16
+ "",
17
+ " shield: {",
18
+ " enabled: ${4|true,false|},",
19
+ " threatDetection: true,",
20
+ " },",
21
+ "",
22
+ " meter: {",
23
+ " enabled: true,",
24
+ " classify: true,",
25
+ " trackCalls: true,",
26
+ " },",
27
+ "",
28
+ " tools: [",
29
+ " $0",
30
+ " ],",
31
+ "});"
32
+ ]
33
+ },
34
+
35
+ "air: defineTool": {
36
+ "prefix": "airtool",
37
+ "description": "Define a new MCP tool",
38
+ "body": [
39
+ "defineTool('${1:tool_name}', {",
40
+ " description: '${2:Tool description}',",
41
+ " params: {",
42
+ " ${3:param}: { type: '${4|string,number,boolean,object|}', description: '${5:param description}' },",
43
+ " },",
44
+ " handler: async ({ ${3:param} }) => {",
45
+ " $0",
46
+ " return '${6:result}';",
47
+ " },",
48
+ "}),"
49
+ ]
50
+ },
51
+
52
+ "air: defineTool (no params)": {
53
+ "prefix": "airtool0",
54
+ "description": "Define a tool with no parameters",
55
+ "body": [
56
+ "defineTool('${1:tool_name}', {",
57
+ " description: '${2:Tool description}',",
58
+ " params: {},",
59
+ " handler: async () => {",
60
+ " $0",
61
+ " return '${3:result}';",
62
+ " },",
63
+ "}),"
64
+ ]
65
+ },
66
+
67
+ "air: defineTool (multi params)": {
68
+ "prefix": "airtoolm",
69
+ "description": "Define a tool with multiple parameters",
70
+ "body": [
71
+ "defineTool('${1:tool_name}', {",
72
+ " description: '${2:Tool description}',",
73
+ " params: {",
74
+ " ${3:param1}: { type: 'string', description: '${4:first param}' },",
75
+ " ${5:param2}: { type: 'string', description: '${6:second param}' },",
76
+ " },",
77
+ " handler: async ({ ${3:param1}, ${5:param2} }) => {",
78
+ " $0",
79
+ " return '${7:result}';",
80
+ " },",
81
+ "}),"
82
+ ]
83
+ },
84
+
85
+ "air: defineResource": {
86
+ "prefix": "airresource",
87
+ "description": "Define an MCP resource",
88
+ "body": [
89
+ "defineResource({",
90
+ " name: '${1:resource_name}',",
91
+ " uri: '${2:resource://path}',",
92
+ " description: '${3:Resource description}',",
93
+ " handler: async (uri, ctx) => {",
94
+ " $0",
95
+ " return '${4:content}';",
96
+ " },",
97
+ "}),"
98
+ ]
99
+ },
100
+
101
+ "air: definePrompt": {
102
+ "prefix": "airprompt",
103
+ "description": "Define an MCP prompt template",
104
+ "body": [
105
+ "definePrompt({",
106
+ " name: '${1:prompt_name}',",
107
+ " description: '${2:Prompt description}',",
108
+ " args: [",
109
+ " { name: '${3:arg}', description: '${4:arg description}' },",
110
+ " ],",
111
+ " handler: async ({ ${3:arg} }) => [",
112
+ " { role: 'user', content: `${5:prompt text \\${${3:arg}\\}}` },",
113
+ " ],",
114
+ "}),"
115
+ ]
116
+ },
117
+
118
+ "air: shield config": {
119
+ "prefix": "airshield",
120
+ "description": "Add shield (security) configuration",
121
+ "body": [
122
+ "shield: {",
123
+ " enabled: true,",
124
+ " policies: [",
125
+ " { name: '${1:policy_name}', target: '${2:*}', action: '${3|allow,deny|}', priority: ${4:10} },",
126
+ " ],",
127
+ " threatDetection: true,",
128
+ " rateLimit: {",
129
+ " maxCalls: ${5:100},",
130
+ " windowMs: ${6:60000},",
131
+ " },",
132
+ " audit: true,",
133
+ "},"
134
+ ]
135
+ },
136
+
137
+ "air: meter config": {
138
+ "prefix": "airmeter",
139
+ "description": "Add meter (metrics) configuration",
140
+ "body": [
141
+ "meter: {",
142
+ " enabled: true,",
143
+ " classify: true,",
144
+ " trackCalls: true,",
145
+ "},"
146
+ ]
147
+ },
148
+
149
+ "air: import core": {
150
+ "prefix": "airimport",
151
+ "description": "Import air/core essentials",
152
+ "body": [
153
+ "import { defineServer, defineTool${1:, getAuditLog, getMetricsSnapshot} } from '@air/core';"
154
+ ]
155
+ },
156
+
157
+ "air: import all": {
158
+ "prefix": "airimportall",
159
+ "description": "Import from all air packages",
160
+ "body": [
161
+ "import { defineServer, defineTool, getAuditLog, getMetricsSnapshot } from '@air/core';",
162
+ "import { AirLogger, PrettyFormatter, ConsoleTransport } from '@air/logger';",
163
+ "import { PolicyEngine, ThreatDetector, RateLimiter } from '@air/shield';",
164
+ "import { LayerClassifier, CallTracker } from '@air/meter';"
165
+ ]
166
+ },
167
+
168
+ "air: handler async": {
169
+ "prefix": "airhandler",
170
+ "description": "Async handler function for a tool",
171
+ "body": [
172
+ "handler: async ({ ${1:params} }) => {",
173
+ " $0",
174
+ " return '${2:result}';",
175
+ "},"
176
+ ]
177
+ }
178
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "my-crud-server",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "private": true,
6
+ "scripts": {
7
+ "dev": "air dev",
8
+ "start": "air start",
9
+ "build": "tsc"
10
+ },
11
+ "dependencies": {
12
+ "@airmcp-dev/core": "^0.1.0"
13
+ },
14
+ "devDependencies": {
15
+ "typescript": "^5.5.0"
16
+ }
17
+ }
@@ -0,0 +1,82 @@
1
+ // Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
2
+ // my-crud-server — src/index.ts
3
+ //
4
+ // DB CRUD 도구 서버 템플릿.
5
+ // 4개 도구(create, read, update, delete)를 제공한다.
6
+ // 실제 DB 연결은 사용자가 구현.
7
+
8
+ import { defineServer, defineTool, createStorage } from '@airmcp-dev/core';
9
+
10
+ // 인메모리 스토리지 (개발용, 실제로는 DB로 교체)
11
+ const store = createStorage({ adapter: 'memory' });
12
+
13
+ const server = defineServer({
14
+ name: 'my-crud-server',
15
+ version: '0.1.0',
16
+
17
+ // transport: { type: 'sse', port: 3510 },
18
+ description: 'CRUD operations for your data',
19
+
20
+ tools: [
21
+ defineTool('create', {
22
+ description: 'Create a new record',
23
+ params: {
24
+ collection: { type: 'string', description: 'Collection/table name' },
25
+ data: { type: 'string', description: 'JSON string of record data' },
26
+ },
27
+ handler: async ({ collection, data }) => {
28
+ const record = JSON.parse(data);
29
+ const id = `${collection}_${Date.now()}`;
30
+ await store.set(id, { ...record, _id: id, _collection: collection });
31
+ return { id, message: `Created in ${collection}` };
32
+ },
33
+ }),
34
+
35
+ defineTool('read', {
36
+ description: 'Read records from a collection',
37
+ params: {
38
+ collection: { type: 'string', description: 'Collection/table name' },
39
+ id: { type: 'string', description: 'Record ID (optional, omit for all)', optional: true },
40
+ },
41
+ handler: async ({ collection, id }) => {
42
+ if (id) {
43
+ const record = await store.get(id);
44
+ return record || { error: 'Not found' };
45
+ }
46
+ // 전체 조회 (인메모리 한정)
47
+ const all = await store.list({ prefix: `${collection}_` });
48
+ return { collection, count: all.length, records: all };
49
+ },
50
+ }),
51
+
52
+ defineTool('update', {
53
+ description: 'Update an existing record',
54
+ params: {
55
+ id: { type: 'string', description: 'Record ID' },
56
+ data: { type: 'string', description: 'JSON string of fields to update' },
57
+ },
58
+ handler: async ({ id, data }) => {
59
+ const existing = await store.get(id);
60
+ if (!existing) return { error: 'Not found' };
61
+ const updated = { ...existing, ...JSON.parse(data) };
62
+ await store.set(id, updated);
63
+ return { id, message: 'Updated', record: updated };
64
+ },
65
+ }),
66
+
67
+ defineTool('delete', {
68
+ description: 'Delete a record',
69
+ params: {
70
+ id: { type: 'string', description: 'Record ID' },
71
+ },
72
+ handler: async ({ id }) => {
73
+ const existing = await store.get(id);
74
+ if (!existing) return { error: 'Not found' };
75
+ await store.delete(id);
76
+ return { id, message: 'Deleted' };
77
+ },
78
+ }),
79
+ ],
80
+ });
81
+
82
+ server.start();
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "outDir": "dist",
7
+ "rootDir": "src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "resolveJsonModule": true
12
+ },
13
+ "include": ["src"]
14
+ }
@@ -0,0 +1,36 @@
1
+ # air MCP Server -- AI Context
2
+
3
+ This project is an MCP server built with the air framework.
4
+
5
+ ## Stack
6
+ - TypeScript + Node.js
7
+ - @airmcp-dev/core for server definition
8
+ - MCP protocol (JSON-RPC 2.0)
9
+
10
+ ## Key APIs
11
+ - defineServer({ name, tools, resources, prompts, use, shield, meter })
12
+ - defineTool(name, { params, handler })
13
+ - defineResource({ uri, name, handler })
14
+ - definePrompt(name, { args, handler })
15
+
16
+ ## Adding Features
17
+ - Add tool: `air add tool <name> --params "key:type"`
18
+ - Add resource: `air add resource <name>`
19
+ - Add prompt: `air add prompt <name>`
20
+
21
+ ## Plugins (import from @airmcp-dev/core)
22
+ timeoutPlugin, retryPlugin, circuitBreakerPlugin, fallbackPlugin,
23
+ cachePlugin, dedupPlugin, queuePlugin,
24
+ authPlugin, sanitizerPlugin, validatorPlugin,
25
+ corsPlugin, webhookPlugin, transformPlugin, i18nPlugin,
26
+ jsonLoggerPlugin, perUserRateLimitPlugin, dryrunPlugin
27
+
28
+ ## Transport
29
+ - stdio (default): for Claude Desktop direct execution
30
+ - sse: for remote connections (set transport.type and transport.port)
31
+ - http: for Streamable HTTP
32
+
33
+ ## Commands
34
+ - `air dev --console` -- dev mode with test console
35
+ - `air connect claude-desktop` -- register with client
36
+ - `air check` -- project diagnostics
@@ -0,0 +1,178 @@
1
+ {
2
+ // ═══════════════════════════════════════════
3
+ // air — MCP Server Development Snippets
4
+ // ═══════════════════════════════════════════
5
+
6
+ "air: defineServer": {
7
+ "prefix": "airserver",
8
+ "description": "Create a new MCP server with air",
9
+ "body": [
10
+ "import { defineServer, defineTool } from '@air/core';",
11
+ "",
12
+ "export default defineServer({",
13
+ " name: '${1:my-server}',",
14
+ " version: '${2:0.1.0}',",
15
+ " description: '${3:MCP server description}',",
16
+ "",
17
+ " shield: {",
18
+ " enabled: ${4|true,false|},",
19
+ " threatDetection: true,",
20
+ " },",
21
+ "",
22
+ " meter: {",
23
+ " enabled: true,",
24
+ " classify: true,",
25
+ " trackCalls: true,",
26
+ " },",
27
+ "",
28
+ " tools: [",
29
+ " $0",
30
+ " ],",
31
+ "});"
32
+ ]
33
+ },
34
+
35
+ "air: defineTool": {
36
+ "prefix": "airtool",
37
+ "description": "Define a new MCP tool",
38
+ "body": [
39
+ "defineTool('${1:tool_name}', {",
40
+ " description: '${2:Tool description}',",
41
+ " params: {",
42
+ " ${3:param}: { type: '${4|string,number,boolean,object|}', description: '${5:param description}' },",
43
+ " },",
44
+ " handler: async ({ ${3:param} }) => {",
45
+ " $0",
46
+ " return '${6:result}';",
47
+ " },",
48
+ "}),"
49
+ ]
50
+ },
51
+
52
+ "air: defineTool (no params)": {
53
+ "prefix": "airtool0",
54
+ "description": "Define a tool with no parameters",
55
+ "body": [
56
+ "defineTool('${1:tool_name}', {",
57
+ " description: '${2:Tool description}',",
58
+ " params: {},",
59
+ " handler: async () => {",
60
+ " $0",
61
+ " return '${3:result}';",
62
+ " },",
63
+ "}),"
64
+ ]
65
+ },
66
+
67
+ "air: defineTool (multi params)": {
68
+ "prefix": "airtoolm",
69
+ "description": "Define a tool with multiple parameters",
70
+ "body": [
71
+ "defineTool('${1:tool_name}', {",
72
+ " description: '${2:Tool description}',",
73
+ " params: {",
74
+ " ${3:param1}: { type: 'string', description: '${4:first param}' },",
75
+ " ${5:param2}: { type: 'string', description: '${6:second param}' },",
76
+ " },",
77
+ " handler: async ({ ${3:param1}, ${5:param2} }) => {",
78
+ " $0",
79
+ " return '${7:result}';",
80
+ " },",
81
+ "}),"
82
+ ]
83
+ },
84
+
85
+ "air: defineResource": {
86
+ "prefix": "airresource",
87
+ "description": "Define an MCP resource",
88
+ "body": [
89
+ "defineResource({",
90
+ " name: '${1:resource_name}',",
91
+ " uri: '${2:resource://path}',",
92
+ " description: '${3:Resource description}',",
93
+ " handler: async (uri, ctx) => {",
94
+ " $0",
95
+ " return '${4:content}';",
96
+ " },",
97
+ "}),"
98
+ ]
99
+ },
100
+
101
+ "air: definePrompt": {
102
+ "prefix": "airprompt",
103
+ "description": "Define an MCP prompt template",
104
+ "body": [
105
+ "definePrompt({",
106
+ " name: '${1:prompt_name}',",
107
+ " description: '${2:Prompt description}',",
108
+ " args: [",
109
+ " { name: '${3:arg}', description: '${4:arg description}' },",
110
+ " ],",
111
+ " handler: async ({ ${3:arg} }) => [",
112
+ " { role: 'user', content: `${5:prompt text \\${${3:arg}\\}}` },",
113
+ " ],",
114
+ "}),"
115
+ ]
116
+ },
117
+
118
+ "air: shield config": {
119
+ "prefix": "airshield",
120
+ "description": "Add shield (security) configuration",
121
+ "body": [
122
+ "shield: {",
123
+ " enabled: true,",
124
+ " policies: [",
125
+ " { name: '${1:policy_name}', target: '${2:*}', action: '${3|allow,deny|}', priority: ${4:10} },",
126
+ " ],",
127
+ " threatDetection: true,",
128
+ " rateLimit: {",
129
+ " maxCalls: ${5:100},",
130
+ " windowMs: ${6:60000},",
131
+ " },",
132
+ " audit: true,",
133
+ "},"
134
+ ]
135
+ },
136
+
137
+ "air: meter config": {
138
+ "prefix": "airmeter",
139
+ "description": "Add meter (metrics) configuration",
140
+ "body": [
141
+ "meter: {",
142
+ " enabled: true,",
143
+ " classify: true,",
144
+ " trackCalls: true,",
145
+ "},"
146
+ ]
147
+ },
148
+
149
+ "air: import core": {
150
+ "prefix": "airimport",
151
+ "description": "Import air/core essentials",
152
+ "body": [
153
+ "import { defineServer, defineTool${1:, getAuditLog, getMetricsSnapshot} } from '@air/core';"
154
+ ]
155
+ },
156
+
157
+ "air: import all": {
158
+ "prefix": "airimportall",
159
+ "description": "Import from all air packages",
160
+ "body": [
161
+ "import { defineServer, defineTool, getAuditLog, getMetricsSnapshot } from '@air/core';",
162
+ "import { AirLogger, PrettyFormatter, ConsoleTransport } from '@air/logger';",
163
+ "import { PolicyEngine, ThreatDetector, RateLimiter } from '@air/shield';",
164
+ "import { LayerClassifier, CallTracker } from '@air/meter';"
165
+ ]
166
+ },
167
+
168
+ "air: handler async": {
169
+ "prefix": "airhandler",
170
+ "description": "Async handler function for a tool",
171
+ "body": [
172
+ "handler: async ({ ${1:params} }) => {",
173
+ " $0",
174
+ " return '${2:result}';",
175
+ "},"
176
+ ]
177
+ }
178
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "my-crud-server",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "private": true,
6
+ "scripts": {
7
+ "dev": "air dev",
8
+ "start": "air start",
9
+ "build": "tsc"
10
+ },
11
+ "dependencies": {
12
+ "@airmcp-dev/core": "^0.1.0"
13
+ },
14
+ "devDependencies": {
15
+ "typescript": "^5.5.0"
16
+ }
17
+ }
@@ -0,0 +1,81 @@
1
+ // Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
2
+ // my-crud-server — src/index.ts
3
+ //
4
+ // DB CRUD 도구 서버 템플릿.
5
+ // 4개 도구(생성, 조회, 수정, 삭제)를 제공합니다.
6
+ // 실제 DB 연결은 직접 구현하세요.
7
+
8
+ import { defineServer, defineTool, createStorage } from '@airmcp-dev/core';
9
+
10
+ // 인메모리 스토리지 (개발용, 실제로는 DB로 교체하세요)
11
+ const store = createStorage({ adapter: 'memory' });
12
+
13
+ const server = defineServer({
14
+ name: 'my-crud-server',
15
+ version: '0.1.0',
16
+
17
+ // transport: { type: 'sse', port: 3510 },
18
+ description: '데이터 CRUD 도구 서버',
19
+
20
+ tools: [
21
+ defineTool('create', {
22
+ description: '새 레코드를 생성합니다',
23
+ params: {
24
+ collection: { type: 'string', description: '컬렉션/테이블 이름' },
25
+ data: { type: 'string', description: '레코드 데이터 (JSON 문자열)' },
26
+ },
27
+ handler: async ({ collection, data }) => {
28
+ const record = JSON.parse(data);
29
+ const id = `${collection}_${Date.now()}`;
30
+ await store.set(id, { ...record, _id: id, _collection: collection });
31
+ return { id, message: `${collection}에 생성 완료` };
32
+ },
33
+ }),
34
+
35
+ defineTool('read', {
36
+ description: '컬렉션에서 레코드를 조회합니다',
37
+ params: {
38
+ collection: { type: 'string', description: '컬렉션/테이블 이름' },
39
+ id: { type: 'string', description: '레코드 ID (생략하면 전체 조회)', optional: true },
40
+ },
41
+ handler: async ({ collection, id }) => {
42
+ if (id) {
43
+ const record = await store.get(id);
44
+ return record || { error: '찾을 수 없습니다' };
45
+ }
46
+ const all = await store.list({ prefix: `${collection}_` });
47
+ return { collection, count: all.length, records: all };
48
+ },
49
+ }),
50
+
51
+ defineTool('update', {
52
+ description: '기존 레코드를 수정합니다',
53
+ params: {
54
+ id: { type: 'string', description: '레코드 ID' },
55
+ data: { type: 'string', description: '수정할 필드 (JSON 문자열)' },
56
+ },
57
+ handler: async ({ id, data }) => {
58
+ const existing = await store.get(id);
59
+ if (!existing) return { error: '찾을 수 없습니다' };
60
+ const updated = { ...existing, ...JSON.parse(data) };
61
+ await store.set(id, updated);
62
+ return { id, message: '수정 완료', record: updated };
63
+ },
64
+ }),
65
+
66
+ defineTool('delete', {
67
+ description: '레코드를 삭제합니다',
68
+ params: {
69
+ id: { type: 'string', description: '레코드 ID' },
70
+ },
71
+ handler: async ({ id }) => {
72
+ const existing = await store.get(id);
73
+ if (!existing) return { error: '찾을 수 없습니다' };
74
+ await store.delete(id);
75
+ return { id, message: '삭제 완료' };
76
+ },
77
+ }),
78
+ ],
79
+ });
80
+
81
+ server.start();
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "outDir": "dist",
7
+ "rootDir": "src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "resolveJsonModule": true
12
+ },
13
+ "include": ["src"]
14
+ }
@@ -0,0 +1,7 @@
1
+ export { printer } from './printer.js';
2
+ export { resolveClientConfig, listClients, resolveAirConfig } from './path-resolver.js';
3
+ export type { SupportedClient, ClientPathInfo } from './path-resolver.js';
4
+ export { JsonEditor } from './json-editor.js';
5
+ export { ProcessManager } from './process-manager.js';
6
+ export type { ServerProcess } from './process-manager.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACxF,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,8 @@
1
+ // Copyright 2026 CodePedia Labs. Licensed under Apache-2.0.
2
+ // air CLI — utils/index.ts
3
+ // re-export only. 로직 없음.
4
+ export { printer } from './printer.js';
5
+ export { resolveClientConfig, listClients, resolveAirConfig } from './path-resolver.js';
6
+ export { JsonEditor } from './json-editor.js';
7
+ export { ProcessManager } from './process-manager.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,2BAA2B;AAC3B,yBAAyB;AAEzB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAExF,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}